mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-27 13:53:09 +00:00
Compare commits
1 Commits
v3.20.0
...
upgrade-co
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e497e42913 |
@@ -8,36 +8,36 @@ const autoCompleteEmoji = require('./autocompleteEmoji');
|
|||||||
|
|
||||||
let CodeMirror;
|
let CodeMirror;
|
||||||
if(typeof window !== 'undefined'){
|
if(typeof window !== 'undefined'){
|
||||||
CodeMirror = require('codemirror');
|
CodeMirror = require('codemirror5');
|
||||||
|
|
||||||
//Language Modes
|
//Language Modes
|
||||||
require('codemirror/mode/gfm/gfm.js'); //Github flavoured markdown
|
require('codemirror5/mode/gfm/gfm.js'); //Github flavoured markdown
|
||||||
require('codemirror/mode/css/css.js');
|
require('codemirror5/mode/css/css.js');
|
||||||
require('codemirror/mode/javascript/javascript.js');
|
require('codemirror5/mode/javascript/javascript.js');
|
||||||
|
|
||||||
//Addons
|
//Addons
|
||||||
//Code folding
|
//Code folding
|
||||||
require('codemirror/addon/fold/foldcode.js');
|
require('codemirror5/addon/fold/foldcode.js');
|
||||||
require('codemirror/addon/fold/foldgutter.js');
|
require('codemirror5/addon/fold/foldgutter.js');
|
||||||
//Search and replace
|
//Search and replace
|
||||||
require('codemirror/addon/search/search.js');
|
require('codemirror5/addon/search/search.js');
|
||||||
require('codemirror/addon/search/searchcursor.js');
|
require('codemirror5/addon/search/searchcursor.js');
|
||||||
require('codemirror/addon/search/jump-to-line.js');
|
require('codemirror5/addon/search/jump-to-line.js');
|
||||||
require('codemirror/addon/search/match-highlighter.js');
|
require('codemirror5/addon/search/match-highlighter.js');
|
||||||
require('codemirror/addon/search/matchesonscrollbar.js');
|
require('codemirror5/addon/search/matchesonscrollbar.js');
|
||||||
require('codemirror/addon/dialog/dialog.js');
|
require('codemirror5/addon/dialog/dialog.js');
|
||||||
//Trailing space highlighting
|
//Trailing space highlighting
|
||||||
// require('codemirror/addon/edit/trailingspace.js');
|
// require('codemirror/addon/edit/trailingspace.js');
|
||||||
//Active line highlighting
|
//Active line highlighting
|
||||||
// require('codemirror/addon/selection/active-line.js');
|
// require('codemirror/addon/selection/active-line.js');
|
||||||
//Scroll past last line
|
//Scroll past last line
|
||||||
require('codemirror/addon/scroll/scrollpastend.js');
|
require('codemirror5/addon/scroll/scrollpastend.js');
|
||||||
//Auto-closing
|
//Auto-closing
|
||||||
//XML code folding is a requirement of the auto-closing tag feature and is not enabled
|
//XML code folding is a requirement of the auto-closing tag feature and is not enabled
|
||||||
require('codemirror/addon/fold/xml-fold.js');
|
require('codemirror5/addon/fold/xml-fold.js');
|
||||||
require('codemirror/addon/edit/closetag.js');
|
require('codemirror5/addon/edit/closetag.js');
|
||||||
//Autocompletion
|
//Autocompletion
|
||||||
require('codemirror/addon/hint/show-hint.js');
|
require('codemirror5/addon/hint/show-hint.js');
|
||||||
|
|
||||||
const foldPagesCode = require('./fold-pages');
|
const foldPagesCode = require('./fold-pages');
|
||||||
foldPagesCode.registerHomebreweryHelper(CodeMirror);
|
foldPagesCode.registerHomebreweryHelper(CodeMirror);
|
||||||
@@ -462,4 +462,3 @@ const CodeEditor = createClass({
|
|||||||
});
|
});
|
||||||
|
|
||||||
module.exports = CodeEditor;
|
module.exports = CodeEditor;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@import (less) 'codemirror/lib/codemirror.css';
|
@import (less) 'codemirror5/lib/codemirror.css';
|
||||||
@import (less) 'codemirror/addon/fold/foldgutter.css';
|
@import (less) 'codemirror5/addon/fold/foldgutter.css';
|
||||||
@import (less) 'codemirror/addon/search/matchesonscrollbar.css';
|
@import (less) 'codemirror5/addon/search/matchesonscrollbar.css';
|
||||||
@import (less) 'codemirror/addon/dialog/dialog.css';
|
@import (less) 'codemirror5/addon/dialog/dialog.css';
|
||||||
@import (less) 'codemirror/addon/hint/show-hint.css';
|
@import (less) 'codemirror5/addon/hint/show-hint.css';
|
||||||
|
|
||||||
//Icon fonts included so they can appear in emoji autosuggest dropdown
|
//Icon fonts included so they can appear in emoji autosuggest dropdown
|
||||||
@import (less) './themes/fonts/iconFonts/diceFont.less';
|
@import (less) './themes/fonts/iconFonts/diceFont.less';
|
||||||
|
|||||||
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';
|
import Markdown from '../../../shared/markdown.js';
|
||||||
|
|
||||||
const CodeEditor = require('client/components/codeEditor/codeEditor.jsx');
|
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 SnippetBar = require('./snippetbar/snippetbar.jsx');
|
||||||
const MetadataEditor = require('./metadataEditor/metadataEditor.jsx');
|
const MetadataEditor = require('./metadataEditor/metadataEditor.jsx');
|
||||||
|
|
||||||
@@ -58,12 +61,38 @@ const Editor = createClass({
|
|||||||
return {
|
return {
|
||||||
editorTheme : this.props.editorTheme,
|
editorTheme : this.props.editorTheme,
|
||||||
view : 'text', //'text', 'style', 'meta', 'snippet'
|
view : 'text', //'text', 'style', 'meta', 'snippet'
|
||||||
snippetBarHeight : 26,
|
snippetbarHeight : 25
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
editor : React.createRef(null),
|
editor : React.createRef(null),
|
||||||
codeEditor : 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';},
|
isText : function() {return this.state.view == 'text';},
|
||||||
isStyle : function() {return this.state.view == 'style';},
|
isStyle : function() {return this.state.view == 'style';},
|
||||||
@@ -76,8 +105,10 @@ const Editor = createClass({
|
|||||||
document.getElementById('BrewRenderer').addEventListener('keydown', this.handleControlKeys);
|
document.getElementById('BrewRenderer').addEventListener('keydown', this.handleControlKeys);
|
||||||
document.addEventListener('keydown', this.handleControlKeys);
|
document.addEventListener('keydown', this.handleControlKeys);
|
||||||
|
|
||||||
this.codeEditor.current.codeMirror.on('cursorActivity', (cm)=>{this.updateCurrentCursorPage(cm.getCursor());});
|
if(!USE_CM6) {
|
||||||
this.codeEditor.current.codeMirror.on('scroll', _.throttle(()=>{this.updateCurrentViewPage(this.codeEditor.current.getTopVisibleLine());}, 200));
|
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);
|
const editorTheme = window.localStorage.getItem(EDITOR_THEME_KEY);
|
||||||
if(editorTheme) {
|
if(editorTheme) {
|
||||||
@@ -85,20 +116,12 @@ const Editor = createClass({
|
|||||||
editorTheme : editorTheme
|
editorTheme : editorTheme
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const snippetBar = document.querySelector('.editor > .snippetBar');
|
this.setState({ snippetbarHeight: document.querySelector('.editor > .snippetBar').offsetHeight });
|
||||||
if (!snippetBar) return;
|
|
||||||
|
|
||||||
this.resizeObserver = new ResizeObserver(entries => {
|
|
||||||
const height = document.querySelector('.editor > .snippetBar').offsetHeight;
|
|
||||||
this.setState({ snippetBarHeight: height });
|
|
||||||
});
|
|
||||||
|
|
||||||
this.resizeObserver.observe(snippetBar);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidUpdate : function(prevProps, prevState, snapshot) {
|
componentDidUpdate : function(prevProps, prevState, snapshot) {
|
||||||
|
|
||||||
this.highlightCustomMarkdown();
|
if(!USE_CM6) this.highlightCustomMarkdown();
|
||||||
if(prevProps.moveBrew !== this.props.moveBrew)
|
if(prevProps.moveBrew !== this.props.moveBrew)
|
||||||
this.brewJump();
|
this.brewJump();
|
||||||
|
|
||||||
@@ -116,10 +139,6 @@ const Editor = createClass({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
if (this.resizeObserver) this.resizeObserver.disconnect();
|
|
||||||
},
|
|
||||||
|
|
||||||
handleControlKeys : function(e){
|
handleControlKeys : function(e){
|
||||||
if(!(e.ctrlKey && e.metaKey && e.shiftKey)) return;
|
if(!(e.ctrlKey && e.metaKey && e.shiftKey)) return;
|
||||||
const LEFTARROW_KEY = 37;
|
const LEFTARROW_KEY = 37;
|
||||||
@@ -133,7 +152,8 @@ const Editor = createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
updateCurrentCursorPage : function(cursor) {
|
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 pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
|
||||||
const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1);
|
const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1);
|
||||||
this.props.onCursorPageChange(currentPage);
|
this.props.onCursorPageChange(currentPage);
|
||||||
@@ -420,7 +440,11 @@ const Editor = createClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
//Called when there are changes to the editor's dimensions
|
//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){
|
updateEditorTheme : function(newTheme){
|
||||||
window.localStorage.setItem(EDITOR_THEME_KEY, newTheme);
|
window.localStorage.setItem(EDITOR_THEME_KEY, newTheme);
|
||||||
@@ -445,7 +469,7 @@ const Editor = createClass({
|
|||||||
onChange={this.props.onBrewChange('text')}
|
onChange={this.props.onBrewChange('text')}
|
||||||
editorTheme={this.state.editorTheme}
|
editorTheme={this.state.editorTheme}
|
||||||
rerenderParent={this.rerenderParent}
|
rerenderParent={this.rerenderParent}
|
||||||
style={{ height: `calc(100% - ${this.state.snippetBarHeight}px)` }} />
|
style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
if(this.isStyle()){
|
if(this.isStyle()){
|
||||||
@@ -459,7 +483,7 @@ const Editor = createClass({
|
|||||||
enableFolding={true}
|
enableFolding={true}
|
||||||
editorTheme={this.state.editorTheme}
|
editorTheme={this.state.editorTheme}
|
||||||
rerenderParent={this.rerenderParent}
|
rerenderParent={this.rerenderParent}
|
||||||
style={{ height: `calc(100% - ${this.state.snippetBarHeight}px)` }} />
|
style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
if(this.isMeta()){
|
if(this.isMeta()){
|
||||||
@@ -476,6 +500,7 @@ const Editor = createClass({
|
|||||||
userThemes={this.props.userThemes}/>
|
userThemes={this.props.userThemes}/>
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.isSnip()){
|
if(this.isSnip()){
|
||||||
if(!this.props.brew.snippets) { this.props.brew.snippets = DEFAULT_SNIPPET_TEXT; }
|
if(!this.props.brew.snippets) { this.props.brew.snippets = DEFAULT_SNIPPET_TEXT; }
|
||||||
return <>
|
return <>
|
||||||
@@ -488,7 +513,7 @@ const Editor = createClass({
|
|||||||
enableFolding={true}
|
enableFolding={true}
|
||||||
editorTheme={this.state.editorTheme}
|
editorTheme={this.state.editorTheme}
|
||||||
rerenderParent={this.rerenderParent}
|
rerenderParent={this.rerenderParent}
|
||||||
style={{ height: `calc(100% -${this.state.snippetBarHeight}px)` }} />
|
style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
.snippets {
|
.snippets {
|
||||||
display : flex;
|
display : flex;
|
||||||
justify-content : flex-start;
|
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 {
|
.editors {
|
||||||
@@ -237,7 +237,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@container editor (width < 750px) {
|
@container editor (width < 683px) {
|
||||||
.snippetBar {
|
.snippetBar {
|
||||||
.editors {
|
.editors {
|
||||||
flex : 1;
|
flex : 1;
|
||||||
|
|||||||
@@ -3,16 +3,19 @@ const _ = require('lodash');
|
|||||||
const Nav = require('client/homebrew/navbar/nav.jsx');
|
const Nav = require('client/homebrew/navbar/nav.jsx');
|
||||||
const { splitTextStyleAndMetadata } = require('../../../shared/helpers.js'); // Importing the function from helpers.js
|
const { splitTextStyleAndMetadata } = require('../../../shared/helpers.js'); // Importing the function from helpers.js
|
||||||
|
|
||||||
const BREWKEY = 'HB_newPage_content';
|
const BREWKEY = 'homebrewery-new';
|
||||||
const STYLEKEY = 'HB_newPage_style';
|
const STYLEKEY = 'homebrewery-new-style';
|
||||||
const METAKEY = 'HB_newPage_meta';
|
const METAKEY = 'homebrewery-new-meta';
|
||||||
|
|
||||||
const NewBrew = ()=>{
|
const NewBrew = ()=>{
|
||||||
const handleFileChange = (e)=>{
|
const handleFileChange = (e)=>{
|
||||||
const file = e.target.files[0];
|
const file = e.target.files[0];
|
||||||
if(!file) return;
|
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();
|
const reader = new FileReader();
|
||||||
reader.onload = (e)=>{
|
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.`);
|
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);
|
console.log(file);
|
||||||
};
|
};
|
||||||
reader.readAsText(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 (
|
return (
|
||||||
<Nav.dropdown>
|
<Nav.dropdown>
|
||||||
@@ -70,31 +50,24 @@ const NewBrew = ()=>{
|
|||||||
className='new'
|
className='new'
|
||||||
color='purple'
|
color='purple'
|
||||||
icon='fa-solid fa-plus-square'>
|
icon='fa-solid fa-plus-square'>
|
||||||
new
|
new
|
||||||
</Nav.item>
|
</Nav.item>
|
||||||
<Nav.item
|
<Nav.item
|
||||||
className='new'
|
className='fromBlank'
|
||||||
href='/new'
|
href='/new'
|
||||||
newTab={true}
|
newTab={true}
|
||||||
color='purple'
|
color='purple'
|
||||||
icon='fa-solid fa-file'>
|
icon='fa-solid fa-file'>
|
||||||
resume draft
|
from blank
|
||||||
</Nav.item>
|
|
||||||
<Nav.item
|
|
||||||
className='fromBlank'
|
|
||||||
newTab={true}
|
|
||||||
color='yellow'
|
|
||||||
icon='fa-solid fa-file-circle-plus'
|
|
||||||
onClick={()=>{ clearLocalStorage(); }}>
|
|
||||||
from blank
|
|
||||||
</Nav.item>
|
</Nav.item>
|
||||||
|
|
||||||
<Nav.item
|
<Nav.item
|
||||||
className='fromFile'
|
className='fromFile'
|
||||||
color='green'
|
color='purple'
|
||||||
icon='fa-solid fa-upload'
|
icon='fa-solid fa-upload'
|
||||||
onClick={()=>{ document.getElementById('uploadTxt').click(); }}>
|
onClick={()=>{ document.getElementById('uploadTxt').click(); }}>
|
||||||
<input id='uploadTxt' className='newFromLocal' type='file' onChange={handleFileChange} style={{ display: 'none' }} />
|
<input id='uploadTxt' className='newFromLocal' type='file' onChange={handleFileChange} style={{ display: 'none' }} />
|
||||||
from file
|
from file
|
||||||
</Nav.item>
|
</Nav.item>
|
||||||
</Nav.dropdown>
|
</Nav.dropdown>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
.newPage {
|
.newPage {
|
||||||
.navItem.save {
|
.navItem.save {
|
||||||
|
.fadeInRight();
|
||||||
|
.transition(opacity);
|
||||||
background-color : @orange;
|
background-color : @orange;
|
||||||
transition:all 0.2s;
|
|
||||||
&:hover { background-color : @green; }
|
&:hover { background-color : @green; }
|
||||||
|
|
||||||
&.neverSaved {
|
&.neverSaved {
|
||||||
translate:-100%;
|
.fadeOutRight();
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
background-color :#333;
|
|
||||||
cursor:auto;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,5 +7,6 @@
|
|||||||
"local_environments" : ["docker", "local"],
|
"local_environments" : ["docker", "local"],
|
||||||
"publicUrl" : "https://homebrewery.naturalcrit.com",
|
"publicUrl" : "https://homebrewery.naturalcrit.com",
|
||||||
"hb_images" : null,
|
"hb_images" : null,
|
||||||
"hb_fonts" : null
|
"hb_fonts" : null,
|
||||||
|
"enable_CM6" : true
|
||||||
}
|
}
|
||||||
|
|||||||
103
package-lock.json
generated
103
package-lock.json
generated
@@ -13,16 +13,16 @@
|
|||||||
"@babel/core": "^7.28.4",
|
"@babel/core": "^7.28.4",
|
||||||
"@babel/plugin-transform-runtime": "^7.28.3",
|
"@babel/plugin-transform-runtime": "^7.28.3",
|
||||||
"@babel/preset-env": "^7.28.3",
|
"@babel/preset-env": "^7.28.3",
|
||||||
"@babel/preset-react": "^7.28.5",
|
"@babel/preset-react": "^7.27.1",
|
||||||
"@babel/runtime": "^7.28.4",
|
"@babel/runtime": "^7.28.4",
|
||||||
"@dmsnell/diff-match-patch": "^1.1.0",
|
"@dmsnell/diff-match-patch": "^1.1.0",
|
||||||
"@googleapis/drive": "^19.2.0",
|
"@googleapis/drive": "^18.0.0",
|
||||||
"@sanity/diff-match-patch": "^3.2.0",
|
"@sanity/diff-match-patch": "^3.2.0",
|
||||||
"body-parser": "^2.2.0",
|
"body-parser": "^2.2.0",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"codemirror": "^5.65.6",
|
"codemirror": "^5.65.6",
|
||||||
"cookie-parser": "^1.4.7",
|
"cookie-parser": "^1.4.7",
|
||||||
"core-js": "^3.47.0",
|
"core-js": "^3.46.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"create-react-class": "^15.7.0",
|
"create-react-class": "^15.7.0",
|
||||||
"dedent-tabs": "^0.10.3",
|
"dedent-tabs": "^0.10.3",
|
||||||
@@ -34,29 +34,29 @@
|
|||||||
"fs-extra": "11.3.2",
|
"fs-extra": "11.3.2",
|
||||||
"hash-wasm": "^4.12.0",
|
"hash-wasm": "^4.12.0",
|
||||||
"idb-keyval": "^6.2.2",
|
"idb-keyval": "^6.2.2",
|
||||||
"js-yaml": "^4.1.1",
|
"js-yaml": "^4.1.0",
|
||||||
"jwt-simple": "^0.5.6",
|
"jwt-simple": "^0.5.6",
|
||||||
"less": "^3.13.1",
|
"less": "^3.13.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"marked": "15.0.12",
|
"marked": "15.0.12",
|
||||||
"marked-alignment-paragraphs": "^1.0.0",
|
"marked-alignment-paragraphs": "^1.0.0",
|
||||||
"marked-definition-lists": "^1.0.1",
|
"marked-definition-lists": "^1.0.1",
|
||||||
"marked-emoji": "^2.0.2",
|
"marked-emoji": "^2.0.1",
|
||||||
"marked-extended-tables": "^2.0.1",
|
"marked-extended-tables": "^2.0.1",
|
||||||
"marked-gfm-heading-id": "^4.1.3",
|
"marked-gfm-heading-id": "^4.1.2",
|
||||||
"marked-nonbreaking-spaces": "^1.0.1",
|
"marked-nonbreaking-spaces": "^1.0.1",
|
||||||
"marked-smartypants-lite": "^1.0.3",
|
"marked-smartypants-lite": "^1.0.3",
|
||||||
"marked-subsuper-text": "^1.0.4",
|
"marked-subsuper-text": "^1.0.4",
|
||||||
"marked-variables": "^1.0.4",
|
"marked-variables": "^1.0.4",
|
||||||
"markedLegacy": "npm:marked@^0.3.19",
|
"markedLegacy": "npm:marked@^0.3.19",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"mongoose": "^8.20.0",
|
"mongoose": "^8.19.1",
|
||||||
"nanoid": "5.1.6",
|
"nanoid": "5.1.6",
|
||||||
"nconf": "^0.13.0",
|
"nconf": "^0.13.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-frame-component": "^4.1.3",
|
"react-frame-component": "^4.1.3",
|
||||||
"react-router": "^7.9.6",
|
"react-router": "^7.9.4",
|
||||||
"romans": "^3.1.0",
|
"romans": "^3.1.0",
|
||||||
"sanitize-filename": "1.6.3",
|
"sanitize-filename": "1.6.3",
|
||||||
"superagent": "^10.2.1",
|
"superagent": "^10.2.1",
|
||||||
@@ -66,8 +66,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@stylistic/stylelint-plugin": "^4.0.0",
|
"@stylistic/stylelint-plugin": "^4.0.0",
|
||||||
"babel-plugin-transform-import-meta": "^2.3.3",
|
"babel-plugin-transform-import-meta": "^2.3.3",
|
||||||
"eslint": "^9.39.1",
|
"eslint": "^9.37.0",
|
||||||
"eslint-plugin-jest": "^29.1.0",
|
"eslint-plugin-jest": "^29.0.1",
|
||||||
"eslint-plugin-react": "^7.37.5",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"globals": "^16.4.0",
|
"globals": "^16.4.0",
|
||||||
"jest": "^30.2.0",
|
"jest": "^30.2.0",
|
||||||
@@ -1427,9 +1427,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-react-display-name": {
|
"node_modules/@babel/plugin-transform-react-display-name": {
|
||||||
"version": "7.28.0",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.27.1.tgz",
|
||||||
"integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==",
|
"integrity": "sha512-p9+Vl3yuHPmkirRrg021XiP+EETmPMQTLr6Ayjj85RLNEbb3Eya/4VI0vAdzQG9SEAl2Lnt7fy5lZyMzjYoZQQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.27.1"
|
"@babel/helper-plugin-utils": "^7.27.1"
|
||||||
@@ -1795,14 +1795,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/preset-react": {
|
"node_modules/@babel/preset-react": {
|
||||||
"version": "7.28.5",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.27.1.tgz",
|
||||||
"integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==",
|
"integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.27.1",
|
"@babel/helper-plugin-utils": "^7.27.1",
|
||||||
"@babel/helper-validator-option": "^7.27.1",
|
"@babel/helper-validator-option": "^7.27.1",
|
||||||
"@babel/plugin-transform-react-display-name": "^7.28.0",
|
"@babel/plugin-transform-react-display-name": "^7.27.1",
|
||||||
"@babel/plugin-transform-react-jsx": "^7.27.1",
|
"@babel/plugin-transform-react-jsx": "^7.27.1",
|
||||||
"@babel/plugin-transform-react-jsx-development": "^7.27.1",
|
"@babel/plugin-transform-react-jsx-development": "^7.27.1",
|
||||||
"@babel/plugin-transform-react-pure-annotations": "^7.27.1"
|
"@babel/plugin-transform-react-pure-annotations": "^7.27.1"
|
||||||
@@ -2258,9 +2258,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.39.1",
|
"version": "9.39.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.0.tgz",
|
||||||
"integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
|
"integrity": "sha512-BIhe0sW91JGPiaF1mOuPy5v8NflqfjIcDNpC+LbW9f609WVRX1rArrhi6Z2ymvrAry9jw+5POTj4t2t62o8Bmw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -2295,9 +2295,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@googleapis/drive": {
|
"node_modules/@googleapis/drive": {
|
||||||
"version": "19.2.0",
|
"version": "18.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-19.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-18.0.0.tgz",
|
||||||
"integrity": "sha512-XzhQ+CNwW54umLecZLzQ5Q2RborJD1+u2YzJIT/BOpne+VJfsCyxWVG0nxYQmcGdiFXJPeW5+V3sdP/A/nt3eA==",
|
"integrity": "sha512-nk4TirsHttwZSOjBEBjltCPDKUqwFso59G3WitNE+EGNVSVseSEq981f8Dmjq2ah0/fk3i206wuCU4PUCwcoTQ==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"googleapis-common": "^8.0.0"
|
"googleapis-common": "^8.0.0"
|
||||||
@@ -5343,9 +5343,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/core-js": {
|
"node_modules/core-js": {
|
||||||
"version": "3.47.0",
|
"version": "3.46.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.46.0.tgz",
|
||||||
"integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==",
|
"integrity": "sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
@@ -6259,9 +6259,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.39.1",
|
"version": "9.39.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.0.tgz",
|
||||||
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
|
"integrity": "sha512-iy2GE3MHrYTL5lrCtMZ0X1KLEKKUjmK0kzwcnefhR66txcEmXZD2YWgR5GNdcEwkNx3a0siYkSvl0vIC+Svjmg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -6271,7 +6271,7 @@
|
|||||||
"@eslint/config-helpers": "^0.4.2",
|
"@eslint/config-helpers": "^0.4.2",
|
||||||
"@eslint/core": "^0.17.0",
|
"@eslint/core": "^0.17.0",
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
"@eslint/js": "9.39.1",
|
"@eslint/js": "9.39.0",
|
||||||
"@eslint/plugin-kit": "^0.4.1",
|
"@eslint/plugin-kit": "^0.4.1",
|
||||||
"@humanfs/node": "^0.16.6",
|
"@humanfs/node": "^0.16.6",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
@@ -6319,9 +6319,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-jest": {
|
"node_modules/eslint-plugin-jest": {
|
||||||
"version": "29.1.0",
|
"version": "29.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.0.1.tgz",
|
||||||
"integrity": "sha512-LabxXbASXVjguqL+kBHTPMf3gUeSqwH4fsrEyHTY/MCs42I/p9+ctg09SJpYiD8eGaIsP6GwYr5xW6xWS9XgZg==",
|
"integrity": "sha512-EE44T0OSMCeXhDrrdsbKAhprobKkPtJTbQz5yEktysNpHeDZTAL1SfDTNKmcFfJkY6yrQLtTKZALrD3j/Gpmiw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -9466,9 +9466,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^2.0.1"
|
"argparse": "^2.0.1"
|
||||||
@@ -10026,12 +10026,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked-emoji": {
|
"node_modules/marked-emoji": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/marked-emoji/-/marked-emoji-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/marked-emoji/-/marked-emoji-2.0.1.tgz",
|
||||||
"integrity": "sha512-EFnLQn4wTyf+6pXfptkm83Z2mt3VbdEYedHBAsDpwUas5n5satsj42RGqAijBpmetgGerI1EzUuzf7NIccINUQ==",
|
"integrity": "sha512-P+nRr02dD+yPOFhtGdaVBzp0qzwlksI2f5GumIdHW/3UadzJ5sVi78CZikiSLr9PmdtUOZodZUBNIO6k38pDMQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"marked": ">=4 <18"
|
"marked": ">=4 <17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked-extended-tables": {
|
"node_modules/marked-extended-tables": {
|
||||||
@@ -10044,15 +10044,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked-gfm-heading-id": {
|
"node_modules/marked-gfm-heading-id": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-4.1.2.tgz",
|
||||||
"integrity": "sha512-aR0i63LmFbuxU/gAgrgz1Ir+8HK6zAIFXMlckeKHpV+qKbYaOP95L4Ux5Gi+sKmCZU5qnN2rdKpvpb7PnUBIWg==",
|
"integrity": "sha512-EQ1WiEGHJh0C8viU+hbXbhHyWTDgEia2i96fiSemm2wdYER6YBw/9QI5TB6YFTqFfmMOxBFXPcPJtlgD0fVV2w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"github-slugger": "^2.0.0"
|
"github-slugger": "^2.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"marked": ">=13 <18"
|
"marked": ">=13 <17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked-nonbreaking-spaces": {
|
"node_modules/marked-nonbreaking-spaces": {
|
||||||
@@ -10436,9 +10436,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mongoose": {
|
"node_modules/mongoose": {
|
||||||
"version": "8.20.0",
|
"version": "8.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.19.2.tgz",
|
||||||
"integrity": "sha512-SxqNb8yx+VOjIOx2l7HqkGvYuLC/T85d+jPvqGDdUbKJFz/5PVSsVxQzypQsX7chenYvq5bd8jIr4LtunedE7g==",
|
"integrity": "sha512-ww2T4dBV+suCbOfG5YPwj9pLCfUVyj8FEA1D3Ux1HHqutpLxGyOYEPU06iPRBW4cKr3PJfOSYsIpHWPTkz5zig==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bson": "^6.10.4",
|
"bson": "^6.10.4",
|
||||||
@@ -12065,9 +12065,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "7.9.6",
|
"version": "7.9.5",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.6.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.5.tgz",
|
||||||
"integrity": "sha512-Y1tUp8clYRXpfPITyuifmSoE2vncSME18uVLgaqyxh9H35JWpIfzHo+9y3Fzh5odk/jxPW29IgLgzcdwxGqyNA==",
|
"integrity": "sha512-JmxqrnBZ6E9hWmf02jzNn9Jm3UqyeimyiwzD69NjxGySG6lIz/1LVPsoTCwN7NBX2XjCEa1LIX5EMz1j2b6u6A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cookie": "^1.0.1",
|
"cookie": "^1.0.1",
|
||||||
@@ -14742,8 +14742,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/vitreum": {
|
"node_modules/vitreum": {
|
||||||
"version": "6.0.4",
|
"version": "6.0.4",
|
||||||
"resolved": "git+https://git@github.com/calculuschild/vitreum.git#929c351881c4229550374421c7e2890a94f4dca7",
|
"resolved": "git+https://git@github.com/calculuschild/vitreum.git#9d55fd6fb7e85e7070de798c4f9d5b983c1b7dba",
|
||||||
"integrity": "sha512-dclfZIgvZU4pOeju1U7CjfGcAMNY+HwhYxF5O1cB6j9EtBrUXQh5+8XlYvNrw2XIcjWIxWcWaCpAQgJxKssfbQ==",
|
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
38
package.json
38
package.json
@@ -88,16 +88,32 @@
|
|||||||
"@babel/core": "^7.28.4",
|
"@babel/core": "^7.28.4",
|
||||||
"@babel/plugin-transform-runtime": "^7.28.3",
|
"@babel/plugin-transform-runtime": "^7.28.3",
|
||||||
"@babel/preset-env": "^7.28.3",
|
"@babel/preset-env": "^7.28.3",
|
||||||
"@babel/preset-react": "^7.28.5",
|
"@babel/preset-react": "^7.27.1",
|
||||||
"@babel/runtime": "^7.28.4",
|
"@babel/runtime": "^7.28.4",
|
||||||
"@dmsnell/diff-match-patch": "^1.1.0",
|
"@dmsnell/diff-match-patch": "^1.1.0",
|
||||||
"@googleapis/drive": "^19.2.0",
|
"@googleapis/drive": "^18.0.0",
|
||||||
"@sanity/diff-match-patch": "^3.2.0",
|
"@sanity/diff-match-patch": "^3.2.0",
|
||||||
"body-parser": "^2.2.0",
|
"body-parser": "^2.2.0",
|
||||||
"classnames": "^2.5.1",
|
"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",
|
"cookie-parser": "^1.4.7",
|
||||||
"core-js": "^3.47.0",
|
"core-js": "^3.46.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"create-react-class": "^15.7.0",
|
"create-react-class": "^15.7.0",
|
||||||
"dedent-tabs": "^0.10.3",
|
"dedent-tabs": "^0.10.3",
|
||||||
@@ -109,29 +125,29 @@
|
|||||||
"fs-extra": "11.3.2",
|
"fs-extra": "11.3.2",
|
||||||
"hash-wasm": "^4.12.0",
|
"hash-wasm": "^4.12.0",
|
||||||
"idb-keyval": "^6.2.2",
|
"idb-keyval": "^6.2.2",
|
||||||
"js-yaml": "^4.1.1",
|
"js-yaml": "^4.1.0",
|
||||||
"jwt-simple": "^0.5.6",
|
"jwt-simple": "^0.5.6",
|
||||||
"less": "^3.13.1",
|
"less": "^3.13.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"marked": "15.0.12",
|
"marked": "15.0.12",
|
||||||
"marked-alignment-paragraphs": "^1.0.0",
|
"marked-alignment-paragraphs": "^1.0.0",
|
||||||
"marked-definition-lists": "^1.0.1",
|
"marked-definition-lists": "^1.0.1",
|
||||||
"marked-emoji": "^2.0.2",
|
"marked-emoji": "^2.0.1",
|
||||||
"marked-extended-tables": "^2.0.1",
|
"marked-extended-tables": "^2.0.1",
|
||||||
"marked-gfm-heading-id": "^4.1.3",
|
"marked-gfm-heading-id": "^4.1.2",
|
||||||
"marked-nonbreaking-spaces": "^1.0.1",
|
"marked-nonbreaking-spaces": "^1.0.1",
|
||||||
"marked-smartypants-lite": "^1.0.3",
|
"marked-smartypants-lite": "^1.0.3",
|
||||||
"marked-subsuper-text": "^1.0.4",
|
"marked-subsuper-text": "^1.0.4",
|
||||||
"marked-variables": "^1.0.4",
|
"marked-variables": "^1.0.4",
|
||||||
"markedLegacy": "npm:marked@^0.3.19",
|
"markedLegacy": "npm:marked@^0.3.19",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"mongoose": "^8.20.0",
|
"mongoose": "^8.19.1",
|
||||||
"nanoid": "5.1.6",
|
"nanoid": "5.1.6",
|
||||||
"nconf": "^0.13.0",
|
"nconf": "^0.13.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-frame-component": "^4.1.3",
|
"react-frame-component": "^4.1.3",
|
||||||
"react-router": "^7.9.6",
|
"react-router": "^7.9.4",
|
||||||
"romans": "^3.1.0",
|
"romans": "^3.1.0",
|
||||||
"sanitize-filename": "1.6.3",
|
"sanitize-filename": "1.6.3",
|
||||||
"superagent": "^10.2.1",
|
"superagent": "^10.2.1",
|
||||||
@@ -141,8 +157,8 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@stylistic/stylelint-plugin": "^4.0.0",
|
"@stylistic/stylelint-plugin": "^4.0.0",
|
||||||
"babel-plugin-transform-import-meta": "^2.3.3",
|
"babel-plugin-transform-import-meta": "^2.3.3",
|
||||||
"eslint": "^9.39.1",
|
"eslint": "^9.37.0",
|
||||||
"eslint-plugin-jest": "^29.1.0",
|
"eslint-plugin-jest": "^29.0.1",
|
||||||
"eslint-plugin-react": "^7.37.5",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"globals": "^16.4.0",
|
"globals": "^16.4.0",
|
||||||
"jest": "^30.2.0",
|
"jest": "^30.2.0",
|
||||||
|
|||||||
@@ -8,24 +8,24 @@
|
|||||||
"create-react-class",
|
"create-react-class",
|
||||||
"lodash",
|
"lodash",
|
||||||
"classnames",
|
"classnames",
|
||||||
"codemirror",
|
"codemirror5",
|
||||||
"codemirror/mode/gfm/gfm.js",
|
"codemirror5/mode/gfm/gfm.js",
|
||||||
"codemirror/mode/css/css.js",
|
"codemirror5/mode/css/css.js",
|
||||||
"codemirror/mode/javascript/javascript.js",
|
"codemirror5/mode/javascript/javascript.js",
|
||||||
"codemirror/addon/fold/foldcode.js",
|
"codemirror5/addon/fold/foldcode.js",
|
||||||
"codemirror/addon/fold/foldgutter.js",
|
"codemirror5/addon/fold/foldgutter.js",
|
||||||
"codemirror/addon/fold/xml-fold.js",
|
"codemirror5/addon/fold/xml-fold.js",
|
||||||
"codemirror/addon/scroll/scrollpastend.js",
|
"codemirror5/addon/scroll/scrollpastend.js",
|
||||||
"codemirror/addon/search/search.js",
|
"codemirror5/addon/search/search.js",
|
||||||
"codemirror/addon/search/searchcursor.js",
|
"codemirror5/addon/search/searchcursor.js",
|
||||||
"codemirror/addon/search/jump-to-line.js",
|
"codemirror5/addon/search/jump-to-line.js",
|
||||||
"codemirror/addon/search/match-highlighter.js",
|
"codemirror5/addon/search/match-highlighter.js",
|
||||||
"codemirror/addon/search/matchesonscrollbar.js",
|
"codemirror5/addon/search/matchesonscrollbar.js",
|
||||||
"codemirror/addon/dialog/dialog.js",
|
"codemirror5/addon/dialog/dialog.js",
|
||||||
"codemirror/addon/edit/closetag.js",
|
"codemirror5/addon/edit/closetag.js",
|
||||||
"codemirror/addon/edit/trailingspace.js",
|
"codemirror5/addon/edit/trailingspace.js",
|
||||||
"codemirror/addon/selection/active-line.js",
|
"codemirror5/addon/selection/active-line.js",
|
||||||
"codemirror/addon/hint/show-hint.js",
|
"codemirror5/addon/hint/show-hint.js",
|
||||||
"moment",
|
"moment",
|
||||||
"superagent",
|
"superagent",
|
||||||
"@sanity/diff-match-patch",
|
"@sanity/diff-match-patch",
|
||||||
|
|||||||
@@ -554,7 +554,8 @@ const renderPage = async (req, res)=>{
|
|||||||
publicUrl : config.get('publicUrl') ?? '',
|
publicUrl : config.get('publicUrl') ?? '',
|
||||||
baseUrl : `${req.protocol}://${req.get('host')}`,
|
baseUrl : `${req.protocol}://${req.get('host')}`,
|
||||||
environment : nodeEnv,
|
environment : nodeEnv,
|
||||||
deployment : config.get('heroku_app_name') ?? ''
|
deployment : config.get('heroku_app_name') ?? '',
|
||||||
|
enable_CM6 : config.get('enable_CM6') ?? false
|
||||||
};
|
};
|
||||||
const props = {
|
const props = {
|
||||||
version : version,
|
version : version,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import config from './config.js';
|
|||||||
|
|
||||||
|
|
||||||
let serviceAuth;
|
let serviceAuth;
|
||||||
let clientEmail;
|
|
||||||
if(!config.get('service_account')){
|
if(!config.get('service_account')){
|
||||||
const reset = '\x1b[0m'; // Reset to default style
|
const reset = '\x1b[0m'; // Reset to default style
|
||||||
const yellow = '\x1b[33m'; // yellow color
|
const yellow = '\x1b[33m'; // yellow color
|
||||||
@@ -16,10 +15,6 @@ if(!config.get('service_account')){
|
|||||||
JSON.parse(config.get('service_account')) :
|
JSON.parse(config.get('service_account')) :
|
||||||
config.get('service_account');
|
config.get('service_account');
|
||||||
|
|
||||||
if(keys?.client_email) {
|
|
||||||
clientEmail = keys.client_email;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
serviceAuth = googleDrive.auth.fromJSON(keys);
|
serviceAuth = googleDrive.auth.fromJSON(keys);
|
||||||
serviceAuth.scopes = ['https://www.googleapis.com/auth/drive'];
|
serviceAuth.scopes = ['https://www.googleapis.com/auth/drive'];
|
||||||
@@ -232,30 +227,14 @@ const GoogleActions = {
|
|||||||
|
|
||||||
if(!obj) return;
|
if(!obj) return;
|
||||||
|
|
||||||
if(clientEmail) {
|
|
||||||
await drive.permissions.create({
|
|
||||||
resource : {
|
|
||||||
type : 'user',
|
|
||||||
emailAddress : clientEmail,
|
|
||||||
role : 'writer'
|
|
||||||
},
|
|
||||||
fileId : obj.data.id,
|
|
||||||
fields : 'id',
|
|
||||||
})
|
|
||||||
.catch((err)=>{
|
|
||||||
console.log('Error adding Service Account permissions on Google Drive file');
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await drive.permissions.create({
|
await drive.permissions.create({
|
||||||
resource : { type : 'anyone',
|
resource : { type : 'anyone',
|
||||||
role : 'writer' },
|
role : 'writer' },
|
||||||
fileId : obj.data.id,
|
fileId : obj.data.id,
|
||||||
fields : 'id',
|
fields : 'id',
|
||||||
})
|
})
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
console.log('Error adding "Anyone" permissions on Google Drive file');
|
console.log('Error updating permissions');
|
||||||
console.error(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -31,12 +31,7 @@ renderer.html = function (token) {
|
|||||||
const openTag = html.substring(0, html.indexOf('>')+1);
|
const openTag = html.substring(0, html.indexOf('>')+1);
|
||||||
html = html.substring(html.indexOf('>')+1);
|
html = html.substring(html.indexOf('>')+1);
|
||||||
html = html.substring(0, html.lastIndexOf('</div>'));
|
html = html.substring(0, html.lastIndexOf('</div>'));
|
||||||
|
return `${openTag} ${Marked.parse(html)} </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 html;
|
return html;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ body { counter-reset : page-numbers 0; }
|
|||||||
.pageNumber { left : 30px; }
|
.pageNumber { left : 30px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
&:has(.resetCounting) { counter-set : page-numbers 1; }
|
.resetCounting { counter-set : page-numbers 1; }
|
||||||
|
|
||||||
&:not(:has(.skipCounting)) { counter-increment : page-numbers; }
|
&:not(:has(.skipCounting)) { counter-increment : page-numbers; }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user