mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-23 16:33:05 +00:00
Compare commits
1 Commits
ReworkHTML
...
upgrade-co
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e497e42913 |
@@ -8,36 +8,36 @@ const autoCompleteEmoji = require('./autocompleteEmoji');
|
||||
|
||||
let CodeMirror;
|
||||
if(typeof window !== 'undefined'){
|
||||
CodeMirror = require('codemirror');
|
||||
CodeMirror = require('codemirror5');
|
||||
|
||||
//Language Modes
|
||||
require('codemirror/mode/gfm/gfm.js'); //Github flavoured markdown
|
||||
require('codemirror/mode/css/css.js');
|
||||
require('codemirror/mode/javascript/javascript.js');
|
||||
require('codemirror5/mode/gfm/gfm.js'); //Github flavoured markdown
|
||||
require('codemirror5/mode/css/css.js');
|
||||
require('codemirror5/mode/javascript/javascript.js');
|
||||
|
||||
//Addons
|
||||
//Code folding
|
||||
require('codemirror/addon/fold/foldcode.js');
|
||||
require('codemirror/addon/fold/foldgutter.js');
|
||||
require('codemirror5/addon/fold/foldcode.js');
|
||||
require('codemirror5/addon/fold/foldgutter.js');
|
||||
//Search and replace
|
||||
require('codemirror/addon/search/search.js');
|
||||
require('codemirror/addon/search/searchcursor.js');
|
||||
require('codemirror/addon/search/jump-to-line.js');
|
||||
require('codemirror/addon/search/match-highlighter.js');
|
||||
require('codemirror/addon/search/matchesonscrollbar.js');
|
||||
require('codemirror/addon/dialog/dialog.js');
|
||||
require('codemirror5/addon/search/search.js');
|
||||
require('codemirror5/addon/search/searchcursor.js');
|
||||
require('codemirror5/addon/search/jump-to-line.js');
|
||||
require('codemirror5/addon/search/match-highlighter.js');
|
||||
require('codemirror5/addon/search/matchesonscrollbar.js');
|
||||
require('codemirror5/addon/dialog/dialog.js');
|
||||
//Trailing space highlighting
|
||||
// require('codemirror/addon/edit/trailingspace.js');
|
||||
//Active line highlighting
|
||||
// require('codemirror/addon/selection/active-line.js');
|
||||
//Scroll past last line
|
||||
require('codemirror/addon/scroll/scrollpastend.js');
|
||||
require('codemirror5/addon/scroll/scrollpastend.js');
|
||||
//Auto-closing
|
||||
//XML code folding is a requirement of the auto-closing tag feature and is not enabled
|
||||
require('codemirror/addon/fold/xml-fold.js');
|
||||
require('codemirror/addon/edit/closetag.js');
|
||||
require('codemirror5/addon/fold/xml-fold.js');
|
||||
require('codemirror5/addon/edit/closetag.js');
|
||||
//Autocompletion
|
||||
require('codemirror/addon/hint/show-hint.js');
|
||||
require('codemirror5/addon/hint/show-hint.js');
|
||||
|
||||
const foldPagesCode = require('./fold-pages');
|
||||
foldPagesCode.registerHomebreweryHelper(CodeMirror);
|
||||
@@ -462,4 +462,3 @@ const CodeEditor = createClass({
|
||||
});
|
||||
|
||||
module.exports = CodeEditor;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@import (less) 'codemirror/lib/codemirror.css';
|
||||
@import (less) 'codemirror/addon/fold/foldgutter.css';
|
||||
@import (less) 'codemirror/addon/search/matchesonscrollbar.css';
|
||||
@import (less) 'codemirror/addon/dialog/dialog.css';
|
||||
@import (less) 'codemirror/addon/hint/show-hint.css';
|
||||
@import (less) 'codemirror5/lib/codemirror.css';
|
||||
@import (less) 'codemirror5/addon/fold/foldgutter.css';
|
||||
@import (less) 'codemirror5/addon/search/matchesonscrollbar.css';
|
||||
@import (less) 'codemirror5/addon/dialog/dialog.css';
|
||||
@import (less) 'codemirror5/addon/hint/show-hint.css';
|
||||
|
||||
//Icon fonts included so they can appear in emoji autosuggest dropdown
|
||||
@import (less) './themes/fonts/iconFonts/diceFont.less';
|
||||
@@ -57,4 +57,4 @@
|
||||
.emojiPreview {
|
||||
font-size : 1.5em;
|
||||
line-height : 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
191
client/components/codeEditor/codeEditorV6.jsx
Normal file
191
client/components/codeEditor/codeEditorV6.jsx
Normal file
@@ -0,0 +1,191 @@
|
||||
import './codeEditor.less';
|
||||
import React, { useEffect, useImperativeHandle, useMemo, useRef } from 'react';
|
||||
import { Compartment, EditorSelection, EditorState } from '@codemirror/state';
|
||||
import { EditorView, keymap, highlightActiveLine, lineNumbers, highlightActiveLineGutter } from '@codemirror/view';
|
||||
import { history, historyKeymap, undo as historyUndo, redo as historyRedo, undoDepth, redoDepth } from '@codemirror/history';
|
||||
import { defaultKeymap, indentWithTab } from '@codemirror/commands';
|
||||
import { searchKeymap, highlightSelectionMatches } from '@codemirror/search';
|
||||
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
|
||||
import { defaultHighlightStyle } from '@codemirror/language';
|
||||
import { syntaxHighlighting } from '@codemirror/language';
|
||||
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
|
||||
import { languages } from '@codemirror/language-data';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { css } from '@codemirror/lang-css';
|
||||
|
||||
const baseExtensions = [
|
||||
lineNumbers(),
|
||||
highlightActiveLineGutter(),
|
||||
EditorView.lineWrapping,
|
||||
history(),
|
||||
keymap.of([
|
||||
indentWithTab,
|
||||
...closeBracketsKeymap,
|
||||
...searchKeymap,
|
||||
...historyKeymap,
|
||||
...defaultKeymap
|
||||
]),
|
||||
closeBrackets(),
|
||||
highlightSelectionMatches(),
|
||||
highlightActiveLine(),
|
||||
syntaxHighlighting(defaultHighlightStyle, { fallback: true })
|
||||
];
|
||||
|
||||
const languageExtension = (language)=>{
|
||||
switch(language){
|
||||
case 'css':
|
||||
return css();
|
||||
case 'javascript':
|
||||
return javascript({ jsx: true, typescript: true });
|
||||
case 'gfm':
|
||||
default:
|
||||
return markdown({ base: markdownLanguage, codeLanguages: languages });
|
||||
}
|
||||
};
|
||||
|
||||
const CodeEditorV6 = React.forwardRef(({
|
||||
value = '',
|
||||
onChange = ()=>{},
|
||||
language = 'gfm',
|
||||
readOnly = false,
|
||||
style = {},
|
||||
editorTheme,
|
||||
onSelectionChange = ()=>{},
|
||||
onScroll = ()=>{}
|
||||
}, ref)=>{
|
||||
const containerRef = useRef(null);
|
||||
const viewRef = useRef(null);
|
||||
const languageCompartment = useMemo(()=>new Compartment(), []);
|
||||
const readOnlyCompartment = useMemo(()=>new Compartment(), []);
|
||||
|
||||
useImperativeHandle(ref, ()=>({
|
||||
focus : ()=>viewRef.current?.focus(),
|
||||
getView : ()=>viewRef.current,
|
||||
getCM6View : ()=>viewRef.current,
|
||||
getCursorPosition : ()=>{
|
||||
const view = viewRef.current;
|
||||
if(!view) return { line: 0, ch: 0 };
|
||||
const { head } = view.state.selection.main;
|
||||
const lineInfo = view.state.doc.lineAt(head);
|
||||
return { line: lineInfo.number - 1, ch: head - lineInfo.from };
|
||||
},
|
||||
setCursorPosition : ({ line = 0, ch = 0 })=>{
|
||||
const view = viewRef.current;
|
||||
if(!view) return;
|
||||
const docLine = view.state.doc.line(Math.max(1, line + 1));
|
||||
const pos = Math.min(docLine.from + ch, docLine.to);
|
||||
view.dispatch({ selection: EditorSelection.cursor(pos), scrollIntoView: true });
|
||||
},
|
||||
getTopVisibleLine : ()=>{
|
||||
const view = viewRef.current;
|
||||
if(!view) return 0;
|
||||
const top = view.scrollDOM.scrollTop;
|
||||
const block = view.lineBlockAtHeight(top);
|
||||
const lineInfo = view.state.doc.lineAt(block.from);
|
||||
return lineInfo.number - 1;
|
||||
},
|
||||
updateSize : ()=>viewRef.current?.requestMeasure(),
|
||||
injectText : (text, overwrite=true)=>{
|
||||
const view = viewRef.current;
|
||||
if(!view) return;
|
||||
const { from, to } = view.state.selection.main;
|
||||
const insertFrom = overwrite ? from : from;
|
||||
const insertTo = overwrite ? to : from;
|
||||
view.dispatch({
|
||||
changes : { from: insertFrom, to: insertTo, insert: text },
|
||||
selection : EditorSelection.cursor(insertFrom + text.length),
|
||||
scrollIntoView : true
|
||||
});
|
||||
view.focus();
|
||||
},
|
||||
undo : ()=>{
|
||||
const view = viewRef.current;
|
||||
if(!view) return;
|
||||
historyUndo(view);
|
||||
},
|
||||
redo : ()=>{
|
||||
const view = viewRef.current;
|
||||
if(!view) return;
|
||||
historyRedo(view);
|
||||
},
|
||||
historySize : ()=>{
|
||||
const view = viewRef.current;
|
||||
if(!view) return { undo: 0, redo: 0 };
|
||||
return {
|
||||
undo : undoDepth(view.state),
|
||||
redo : redoDepth(view.state)
|
||||
};
|
||||
},
|
||||
foldAllCode : ()=>{},
|
||||
unfoldAllCode : ()=>{}
|
||||
}), []);
|
||||
|
||||
useEffect(()=>{
|
||||
if(!containerRef.current) return;
|
||||
|
||||
const initialExtensions = [
|
||||
...baseExtensions,
|
||||
languageCompartment.of(languageExtension(language)),
|
||||
readOnlyCompartment.of(EditorState.readOnly.of(readOnly)),
|
||||
EditorView.updateListener.of((update)=>{
|
||||
if(update.docChanged) onChange(update.state.doc.toString());
|
||||
if(update.selectionSet) onSelectionChange(update.view);
|
||||
})
|
||||
];
|
||||
|
||||
const state = EditorState.create({
|
||||
doc : value,
|
||||
extensions : initialExtensions
|
||||
});
|
||||
|
||||
const view = new EditorView({
|
||||
state,
|
||||
parent : containerRef.current
|
||||
});
|
||||
viewRef.current = view;
|
||||
|
||||
const handleScroll = ()=>onScroll(view);
|
||||
view.scrollDOM.addEventListener('scroll', handleScroll);
|
||||
|
||||
return ()=>{
|
||||
view.scrollDOM.removeEventListener('scroll', handleScroll);
|
||||
view.destroy();
|
||||
viewRef.current = null;
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(()=>{
|
||||
const view = viewRef.current;
|
||||
if(!view) return;
|
||||
view.dispatch({
|
||||
effects : languageCompartment.reconfigure(languageExtension(language))
|
||||
});
|
||||
}, [language, languageCompartment]);
|
||||
|
||||
useEffect(()=>{
|
||||
const view = viewRef.current;
|
||||
if(!view) return;
|
||||
view.dispatch({
|
||||
effects : readOnlyCompartment.reconfigure(EditorState.readOnly.of(readOnly))
|
||||
});
|
||||
}, [readOnly, readOnlyCompartment]);
|
||||
|
||||
useEffect(()=>{
|
||||
const view = viewRef.current;
|
||||
if(!view) return;
|
||||
const currentValue = view.state.doc.toString();
|
||||
if(value === currentValue) return;
|
||||
const transaction = view.state.update({
|
||||
changes : { from: 0, to: currentValue.length, insert: value }
|
||||
});
|
||||
view.dispatch(transaction);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div className='codeEditor' ref={containerRef} style={style} data-editor='cm6'></div>
|
||||
);
|
||||
});
|
||||
|
||||
CodeEditorV6.displayName = 'CodeEditorV6';
|
||||
|
||||
export default CodeEditorV6;
|
||||
@@ -7,6 +7,9 @@ const dedent = require('dedent-tabs').default;
|
||||
import Markdown from '../../../shared/markdown.js';
|
||||
|
||||
const CodeEditor = require('client/components/codeEditor/codeEditor.jsx');
|
||||
import CodeEditorV6 from 'client/components/codeEditor/codeEditorV6.jsx';
|
||||
|
||||
const USE_CM6 = global?.config?.enable_CM6 === true;
|
||||
const SnippetBar = require('./snippetbar/snippetbar.jsx');
|
||||
const MetadataEditor = require('./metadataEditor/metadataEditor.jsx');
|
||||
|
||||
@@ -58,12 +61,38 @@ const Editor = createClass({
|
||||
return {
|
||||
editorTheme : this.props.editorTheme,
|
||||
view : 'text', //'text', 'style', 'meta', 'snippet'
|
||||
snippetBarHeight : 26,
|
||||
snippetbarHeight : 25
|
||||
};
|
||||
},
|
||||
|
||||
editor : React.createRef(null),
|
||||
codeEditor : React.createRef(null),
|
||||
editor : React.createRef(null),
|
||||
codeEditor : React.createRef(null),
|
||||
codeEditorV6 : React.createRef(null),
|
||||
|
||||
getActiveEditor : function(){
|
||||
return USE_CM6 ? this.codeEditorV6.current : this.codeEditor.current;
|
||||
},
|
||||
|
||||
focusActiveEditor : function(){
|
||||
const editor = this.getActiveEditor();
|
||||
if(!editor) return;
|
||||
if(USE_CM6) editor.focus?.();
|
||||
else editor.codeMirror?.focus();
|
||||
},
|
||||
|
||||
handleCM6SelectionChange : function(view){
|
||||
if(!USE_CM6 || !view) return;
|
||||
const { head } = view.state.selection.main;
|
||||
const lineInfo = view.state.doc.lineAt(head);
|
||||
this.updateCurrentCursorPage({ line: lineInfo.number - 1 });
|
||||
},
|
||||
|
||||
handleCM6Scroll : function(){
|
||||
if(!USE_CM6) return;
|
||||
const topLine = this.codeEditorV6.current?.getTopVisibleLine?.();
|
||||
if(topLine == null) return;
|
||||
this.updateCurrentViewPage(topLine);
|
||||
},
|
||||
|
||||
isText : function() {return this.state.view == 'text';},
|
||||
isStyle : function() {return this.state.view == 'style';},
|
||||
@@ -76,8 +105,10 @@ const Editor = createClass({
|
||||
document.getElementById('BrewRenderer').addEventListener('keydown', this.handleControlKeys);
|
||||
document.addEventListener('keydown', this.handleControlKeys);
|
||||
|
||||
this.codeEditor.current.codeMirror.on('cursorActivity', (cm)=>{this.updateCurrentCursorPage(cm.getCursor());});
|
||||
this.codeEditor.current.codeMirror.on('scroll', _.throttle(()=>{this.updateCurrentViewPage(this.codeEditor.current.getTopVisibleLine());}, 200));
|
||||
if(!USE_CM6) {
|
||||
this.codeEditor.current?.codeMirror?.on('cursorActivity', (cm)=>{this.updateCurrentCursorPage(cm.getCursor());});
|
||||
this.codeEditor.current?.codeMirror?.on('scroll', _.throttle(()=>{this.updateCurrentViewPage(this.codeEditor.current.getTopVisibleLine());}, 200));
|
||||
}
|
||||
|
||||
const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY);
|
||||
if(editorTheme) {
|
||||
@@ -85,20 +116,12 @@ const Editor = createClass({
|
||||
editorTheme : editorTheme
|
||||
});
|
||||
}
|
||||
const snippetBar = document.querySelector('.editor > .snippetBar');
|
||||
if (!snippetBar) return;
|
||||
|
||||
this.resizeObserver = new ResizeObserver(entries => {
|
||||
const height = document.querySelector('.editor > .snippetBar').offsetHeight;
|
||||
this.setState({ snippetBarHeight: height });
|
||||
});
|
||||
|
||||
this.resizeObserver.observe(snippetBar);
|
||||
this.setState({ snippetbarHeight: document.querySelector('.editor > .snippetBar').offsetHeight });
|
||||
},
|
||||
|
||||
componentDidUpdate : function(prevProps, prevState, snapshot) {
|
||||
|
||||
this.highlightCustomMarkdown();
|
||||
if(!USE_CM6) this.highlightCustomMarkdown();
|
||||
if(prevProps.moveBrew !== this.props.moveBrew)
|
||||
this.brewJump();
|
||||
|
||||
@@ -116,10 +139,6 @@ const Editor = createClass({
|
||||
}
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.resizeObserver) this.resizeObserver.disconnect();
|
||||
},
|
||||
|
||||
handleControlKeys : function(e){
|
||||
if(!(e.ctrlKey && e.metaKey && e.shiftKey)) return;
|
||||
const LEFTARROW_KEY = 37;
|
||||
@@ -133,7 +152,8 @@ const Editor = createClass({
|
||||
},
|
||||
|
||||
updateCurrentCursorPage : function(cursor) {
|
||||
const lines = this.props.brew.text.split('\n').slice(1, cursor.line + 1);
|
||||
const cursorLine = cursor.line ?? cursor;
|
||||
const lines = this.props.brew.text.split('\n').slice(1, cursorLine + 1);
|
||||
const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
|
||||
const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1);
|
||||
this.props.onCursorPageChange(currentPage);
|
||||
@@ -420,7 +440,11 @@ const Editor = createClass({
|
||||
},
|
||||
|
||||
//Called when there are changes to the editor's dimensions
|
||||
update : function(){},
|
||||
update : function(){
|
||||
const snipHeight = document.querySelector('.editor > .snippetBar').offsetHeight;
|
||||
if(snipHeight !== this.state.snippetbarHeight)
|
||||
this.setState({ snippetbarHeight: snipHeight });
|
||||
},
|
||||
|
||||
updateEditorTheme : function(newTheme){
|
||||
window.localStorage.setItem(EDITOR_THEME_KEY, newTheme);
|
||||
@@ -445,7 +469,7 @@ const Editor = createClass({
|
||||
onChange={this.props.onBrewChange('text')}
|
||||
editorTheme={this.state.editorTheme}
|
||||
rerenderParent={this.rerenderParent}
|
||||
style={{ height: `calc(100% - ${this.state.snippetBarHeight}px)` }} />
|
||||
style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
|
||||
</>;
|
||||
}
|
||||
if(this.isStyle()){
|
||||
@@ -459,7 +483,7 @@ const Editor = createClass({
|
||||
enableFolding={true}
|
||||
editorTheme={this.state.editorTheme}
|
||||
rerenderParent={this.rerenderParent}
|
||||
style={{ height: `calc(100% - ${this.state.snippetBarHeight}px)` }} />
|
||||
style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
|
||||
</>;
|
||||
}
|
||||
if(this.isMeta()){
|
||||
@@ -476,6 +500,7 @@ const Editor = createClass({
|
||||
userThemes={this.props.userThemes}/>
|
||||
</>;
|
||||
}
|
||||
|
||||
if(this.isSnip()){
|
||||
if(!this.props.brew.snippets) { this.props.brew.snippets = DEFAULT_SNIPPET_TEXT; }
|
||||
return <>
|
||||
@@ -488,7 +513,7 @@ const Editor = createClass({
|
||||
enableFolding={true}
|
||||
editorTheme={this.state.editorTheme}
|
||||
rerenderParent={this.rerenderParent}
|
||||
style={{ height: `calc(100% -${this.state.snippetBarHeight}px)` }} />
|
||||
style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
|
||||
</>;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
.snippets {
|
||||
display : flex;
|
||||
justify-content : flex-start;
|
||||
min-width : 499.35px; //must be controlled every time an item is added, must be hardcoded for the wrapping as it is applied
|
||||
min-width : 432.18px; //must be controlled every time an item is added, must be hardcoded for the wrapping as it is applied
|
||||
}
|
||||
|
||||
.editors {
|
||||
@@ -237,7 +237,7 @@
|
||||
}
|
||||
|
||||
}
|
||||
@container editor (width < 750px) {
|
||||
@container editor (width < 683px) {
|
||||
.snippetBar {
|
||||
.editors {
|
||||
flex : 1;
|
||||
|
||||
@@ -3,16 +3,19 @@ const _ = require('lodash');
|
||||
const Nav = require('client/homebrew/navbar/nav.jsx');
|
||||
const { splitTextStyleAndMetadata } = require('../../../shared/helpers.js'); // Importing the function from helpers.js
|
||||
|
||||
const BREWKEY = 'HB_newPage_content';
|
||||
const STYLEKEY = 'HB_newPage_style';
|
||||
const METAKEY = 'HB_newPage_meta';
|
||||
const BREWKEY = 'homebrewery-new';
|
||||
const STYLEKEY = 'homebrewery-new-style';
|
||||
const METAKEY = 'homebrewery-new-meta';
|
||||
|
||||
const NewBrew = ()=>{
|
||||
const handleFileChange = (e)=>{
|
||||
const file = e.target.files[0];
|
||||
if(!file) return;
|
||||
|
||||
if(!confirmLocalStorageChange()) return;
|
||||
const currentNew = localStorage.getItem(BREWKEY);
|
||||
if(currentNew && !confirm(
|
||||
`You have some text in the new brew space, if you load a file that text will be lost, are you sure you want to load the file?`
|
||||
)) return;
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e)=>{
|
||||
@@ -34,35 +37,12 @@ const NewBrew = ()=>{
|
||||
|
||||
alert(`This file is invalid: ${!type ? 'Missing file extension' :`.${type} files are not supported`}. Only .txt files exported from the Homebrewery are allowed.`);
|
||||
|
||||
|
||||
console.log(file);
|
||||
};
|
||||
reader.readAsText(file);
|
||||
};
|
||||
|
||||
const confirmLocalStorageChange = ()=>{
|
||||
const currentText = localStorage.getItem(BREWKEY);
|
||||
const currentStyle = localStorage.getItem(STYLEKEY);
|
||||
const currentMeta = localStorage.getItem(METAKEY);
|
||||
|
||||
// TRUE if no data in any local storage key
|
||||
// TRUE if data in any local storage key AND approval given
|
||||
// FALSE if data in any local storage key AND approval declined
|
||||
return (!(currentText || currentStyle || currentMeta) || confirm(
|
||||
`You have made changes in the new brew space. If you continue, that information will be PERMANENTLY LOST.\nAre you sure you wish to continue?`
|
||||
));
|
||||
};
|
||||
|
||||
const clearLocalStorage = ()=>{
|
||||
if(!confirmLocalStorageChange()) return;
|
||||
|
||||
localStorage.removeItem(BREWKEY);
|
||||
localStorage.removeItem(STYLEKEY);
|
||||
localStorage.removeItem(METAKEY);
|
||||
|
||||
window.location.href = '/new';
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Nav.dropdown>
|
||||
@@ -70,31 +50,24 @@ const NewBrew = ()=>{
|
||||
className='new'
|
||||
color='purple'
|
||||
icon='fa-solid fa-plus-square'>
|
||||
new
|
||||
new
|
||||
</Nav.item>
|
||||
<Nav.item
|
||||
className='new'
|
||||
className='fromBlank'
|
||||
href='/new'
|
||||
newTab={true}
|
||||
color='purple'
|
||||
icon='fa-solid fa-file'>
|
||||
resume draft
|
||||
</Nav.item>
|
||||
<Nav.item
|
||||
className='fromBlank'
|
||||
newTab={true}
|
||||
color='yellow'
|
||||
icon='fa-solid fa-file-circle-plus'
|
||||
onClick={()=>{ clearLocalStorage(); }}>
|
||||
from blank
|
||||
from blank
|
||||
</Nav.item>
|
||||
|
||||
<Nav.item
|
||||
className='fromFile'
|
||||
color='green'
|
||||
color='purple'
|
||||
icon='fa-solid fa-upload'
|
||||
onClick={()=>{ document.getElementById('uploadTxt').click(); }}>
|
||||
<input id='uploadTxt' className='newFromLocal' type='file' onChange={handleFileChange} style={{ display: 'none' }} />
|
||||
from file
|
||||
from file
|
||||
</Nav.item>
|
||||
</Nav.dropdown>
|
||||
);
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
.newPage {
|
||||
.navItem.save {
|
||||
.fadeInRight();
|
||||
.transition(opacity);
|
||||
background-color : @orange;
|
||||
transition:all 0.2s;
|
||||
&:hover { background-color : @green; }
|
||||
|
||||
&.neverSaved {
|
||||
translate:-100%;
|
||||
.fadeOutRight();
|
||||
opacity: 0;
|
||||
background-color :#333;
|
||||
cursor:auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,5 +7,6 @@
|
||||
"local_environments" : ["docker", "local"],
|
||||
"publicUrl" : "https://homebrewery.naturalcrit.com",
|
||||
"hb_images" : null,
|
||||
"hb_fonts" : null
|
||||
"hb_fonts" : null,
|
||||
"enable_CM6" : true
|
||||
}
|
||||
|
||||
18
package.json
18
package.json
@@ -95,7 +95,23 @@
|
||||
"@sanity/diff-match-patch": "^3.2.0",
|
||||
"body-parser": "^2.2.0",
|
||||
"classnames": "^2.5.1",
|
||||
"codemirror": "^5.65.6",
|
||||
"@codemirror/autocomplete": "^6.18.2",
|
||||
"@codemirror/commands": "^6.7.2",
|
||||
"@codemirror/fold": "^6.7.1",
|
||||
"@codemirror/history": "^6.3.0",
|
||||
"@codemirror/lang-css": "^6.3.0",
|
||||
"@codemirror/lang-html": "^6.4.7",
|
||||
"@codemirror/lang-javascript": "^6.2.2",
|
||||
"@codemirror/lang-markdown": "^6.2.3",
|
||||
"@codemirror/language": "^6.10.2",
|
||||
"@codemirror/lint": "^6.8.0",
|
||||
"@codemirror/search": "^6.5.6",
|
||||
"@codemirror/state": "^6.4.1",
|
||||
"@codemirror/view": "^6.27.0",
|
||||
"@lezer/common": "^1.2.1",
|
||||
"@lezer/highlight": "^1.2.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"codemirror5": "npm:codemirror@^5.65.19",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"core-js": "^3.46.0",
|
||||
"cors": "^2.8.5",
|
||||
|
||||
@@ -8,24 +8,24 @@
|
||||
"create-react-class",
|
||||
"lodash",
|
||||
"classnames",
|
||||
"codemirror",
|
||||
"codemirror/mode/gfm/gfm.js",
|
||||
"codemirror/mode/css/css.js",
|
||||
"codemirror/mode/javascript/javascript.js",
|
||||
"codemirror/addon/fold/foldcode.js",
|
||||
"codemirror/addon/fold/foldgutter.js",
|
||||
"codemirror/addon/fold/xml-fold.js",
|
||||
"codemirror/addon/scroll/scrollpastend.js",
|
||||
"codemirror/addon/search/search.js",
|
||||
"codemirror/addon/search/searchcursor.js",
|
||||
"codemirror/addon/search/jump-to-line.js",
|
||||
"codemirror/addon/search/match-highlighter.js",
|
||||
"codemirror/addon/search/matchesonscrollbar.js",
|
||||
"codemirror/addon/dialog/dialog.js",
|
||||
"codemirror/addon/edit/closetag.js",
|
||||
"codemirror/addon/edit/trailingspace.js",
|
||||
"codemirror/addon/selection/active-line.js",
|
||||
"codemirror/addon/hint/show-hint.js",
|
||||
"codemirror5",
|
||||
"codemirror5/mode/gfm/gfm.js",
|
||||
"codemirror5/mode/css/css.js",
|
||||
"codemirror5/mode/javascript/javascript.js",
|
||||
"codemirror5/addon/fold/foldcode.js",
|
||||
"codemirror5/addon/fold/foldgutter.js",
|
||||
"codemirror5/addon/fold/xml-fold.js",
|
||||
"codemirror5/addon/scroll/scrollpastend.js",
|
||||
"codemirror5/addon/search/search.js",
|
||||
"codemirror5/addon/search/searchcursor.js",
|
||||
"codemirror5/addon/search/jump-to-line.js",
|
||||
"codemirror5/addon/search/match-highlighter.js",
|
||||
"codemirror5/addon/search/matchesonscrollbar.js",
|
||||
"codemirror5/addon/dialog/dialog.js",
|
||||
"codemirror5/addon/edit/closetag.js",
|
||||
"codemirror5/addon/edit/trailingspace.js",
|
||||
"codemirror5/addon/selection/active-line.js",
|
||||
"codemirror5/addon/hint/show-hint.js",
|
||||
"moment",
|
||||
"superagent",
|
||||
"@sanity/diff-match-patch",
|
||||
|
||||
@@ -554,7 +554,8 @@ const renderPage = async (req, res)=>{
|
||||
publicUrl : config.get('publicUrl') ?? '',
|
||||
baseUrl : `${req.protocol}://${req.get('host')}`,
|
||||
environment : nodeEnv,
|
||||
deployment : config.get('heroku_app_name') ?? ''
|
||||
deployment : config.get('heroku_app_name') ?? '',
|
||||
enable_CM6 : config.get('enable_CM6') ?? false
|
||||
};
|
||||
const props = {
|
||||
version : version,
|
||||
|
||||
@@ -31,12 +31,7 @@ renderer.html = function (token) {
|
||||
const openTag = html.substring(0, html.indexOf('>')+1);
|
||||
html = html.substring(html.indexOf('>')+1);
|
||||
html = html.substring(0, html.lastIndexOf('</div>'));
|
||||
|
||||
// Repeat the markdown processing for content inside the div, minus the preprocessing and postprocessing hooks which should only run once globally
|
||||
const opts = Marked.defaults;
|
||||
const tokens = Marked.lexer(html, opts);
|
||||
Marked.walkTokens(tokens, opts.walkTokens);
|
||||
return `${openTag} ${Marked.parser(tokens, opts)} </div>`;
|
||||
return `${openTag} ${Marked.parse(html)} </div>`;
|
||||
}
|
||||
return html;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user