diff --git a/changelog.md b/changelog.md
index 7cfbfde8a..1e1ac70e2 100644
--- a/changelog.md
+++ b/changelog.md
@@ -83,12 +83,40 @@ pre {
.page .exampleTable td,th {
border:1px dashed #00000030;
}
+
+.page .df {
+ font-size: 2em;
+ vertical-align: middle;
+}
```
## changelog
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
-### Friday 11/14/2025 - v13.20.0
+### Friday 1/11/2026 - v3.20.1
+
+{{taskList
+##### calculuschild
+* [x] Add D100 "ball" dice icons `:d100:` :df_d100_05:
+
+##### G-Ambatte
+* [x] Fix transparent edge on back cover image
+
+Fixes issue [#4551](https://github.com/naturalcrit/homebrewery/issues/4551)
+
+* [x] Fix "Out of sync" error when document contains extended unicode characters
+
+Fixes issue [#4583](https://github.com/naturalcrit/homebrewery/issues/4583)
+
+##### 5e-Cleric
+* [x] Fix page count error on Vault
+
+* [x] Fix cover page footnote set to all-caps
+
+Fixes issue [#4559](https://github.com/naturalcrit/homebrewery/issues/4559)
+}}
+
+### Friday 11/14/2025 - v3.20.0
{{taskList
##### calculuschild
diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx
index 787c2a3eb..cc6eb72ca 100644
--- a/client/admin/admin.jsx
+++ b/client/admin/admin.jsx
@@ -1,7 +1,7 @@
import './admin.less';
import React, { useEffect, useState } from 'react';
-const BrewUtils = require('./brewUtils/brewUtils.jsx');
-const NotificationUtils = require('./notificationUtils/notificationUtils.jsx');
+import BrewUtils from './brewUtils/brewUtils.jsx';
+import NotificationUtils from './notificationUtils/notificationUtils.jsx';
import AuthorUtils from './authorUtils/authorUtils.jsx';
import LockTools from './lockTools/lockTools.jsx';
diff --git a/client/admin/authorUtils/authorLookup/authorLookup.jsx b/client/admin/authorUtils/authorLookup/authorLookup.jsx
index abdece6f7..cdfe6274b 100644
--- a/client/admin/authorUtils/authorLookup/authorLookup.jsx
+++ b/client/admin/authorUtils/authorLookup/authorLookup.jsx
@@ -84,4 +84,4 @@ const authorLookup = ()=>{
);
};
-module.exports = authorLookup;
+export default authorLookup;
diff --git a/client/admin/authorUtils/authorUtils.jsx b/client/admin/authorUtils/authorUtils.jsx
index a96eea528..ef717a1ec 100644
--- a/client/admin/authorUtils/authorUtils.jsx
+++ b/client/admin/authorUtils/authorUtils.jsx
@@ -10,4 +10,4 @@ const authorUtils = ()=>{
);
};
-module.exports = authorUtils;
\ No newline at end of file
+export default authorUtils;
\ No newline at end of file
diff --git a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx
index d4b17c570..6cec01178 100644
--- a/client/admin/brewUtils/brewCleanup/brewCleanup.jsx
+++ b/client/admin/brewUtils/brewCleanup/brewCleanup.jsx
@@ -1,9 +1,8 @@
-const React = require('react');
-const createClass = require('create-react-class');
+import React from 'react';
+import createReactClass from 'create-react-class';
+import request from 'superagent';
-const request = require('superagent');
-
-const BrewCleanup = createClass({
+const BrewCleanup = createReactClass({
displayName : 'BrewCleanup',
getDefaultProps(){
return {};
@@ -69,4 +68,4 @@ const BrewCleanup = createClass({
}
});
-module.exports = BrewCleanup;
+export default BrewCleanup;
diff --git a/client/admin/brewUtils/brewCompress/brewCompress.jsx b/client/admin/brewUtils/brewCompress/brewCompress.jsx
index ccb59e027..181315fce 100644
--- a/client/admin/brewUtils/brewCompress/brewCompress.jsx
+++ b/client/admin/brewUtils/brewCompress/brewCompress.jsx
@@ -1,8 +1,8 @@
-const React = require('react');
-const createClass = require('create-react-class');
-const request = require('superagent');
+import React from 'react';
+import createReactClass from 'create-react-class';
+import request from 'superagent';
-const BrewCompress = createClass({
+const BrewCompress = createReactClass({
displayName : 'BrewCompress',
getDefaultProps(){
return {};
@@ -85,4 +85,4 @@ const BrewCompress = createClass({
}
});
-module.exports = BrewCompress;
+export default BrewCompress;
diff --git a/client/admin/brewUtils/brewLookup/brewLookup.jsx b/client/admin/brewUtils/brewLookup/brewLookup.jsx
index fb780f29e..6b725198c 100644
--- a/client/admin/brewUtils/brewLookup/brewLookup.jsx
+++ b/client/admin/brewUtils/brewLookup/brewLookup.jsx
@@ -1,12 +1,11 @@
-const React = require('react');
-const createClass = require('create-react-class');
-const cx = require('classnames');
+import React from 'react';
+import createReactClass from 'create-react-class';
+import request from 'superagent';
+import cx from 'classnames';
-const request = require('superagent');
-const Moment = require('moment');
+import Moment from 'moment';
-
-const BrewLookup = createClass({
+const BrewLookup = createReactClass({
getDefaultProps() {
return {};
},
@@ -110,4 +109,4 @@ const BrewLookup = createClass({
}
});
-module.exports = BrewLookup;
+export default BrewLookup;
diff --git a/client/admin/brewUtils/brewUtils.jsx b/client/admin/brewUtils/brewUtils.jsx
index bab2cb82f..dd663ddaa 100644
--- a/client/admin/brewUtils/brewUtils.jsx
+++ b/client/admin/brewUtils/brewUtils.jsx
@@ -1,15 +1,14 @@
-const React = require('react');
-const createClass = require('create-react-class');
-require('./brewUtils.less');
+import React from 'react';
+import './brewUtils.less';
-const BrewCleanup = require('./brewCleanup/brewCleanup.jsx');
-const BrewLookup = require('./brewLookup/brewLookup.jsx');
-const BrewCompress = require ('./brewCompress/brewCompress.jsx');
-const Stats = require('./stats/stats.jsx');
+import BrewCleanup from './brewCleanup/brewCleanup.jsx';
+import BrewLookup from './brewLookup/brewLookup.jsx';
+import BrewCompress from './brewCompress/brewCompress.jsx';
+import Stats from './stats/stats.jsx';
-const BrewUtils = createClass({
- render : function(){
- return <>
+const BrewUtils = ()=>{
+ return (
+ <>
@@ -17,8 +16,7 @@ const BrewUtils = createClass({
- >;
- }
-});
-
-module.exports = BrewUtils;
+ >
+ );
+};
+export default BrewUtils;
diff --git a/client/admin/brewUtils/stats/stats.jsx b/client/admin/brewUtils/stats/stats.jsx
index 7f96618f9..b05d3afd5 100644
--- a/client/admin/brewUtils/stats/stats.jsx
+++ b/client/admin/brewUtils/stats/stats.jsx
@@ -1,9 +1,8 @@
-const React = require('react');
-const createClass = require('create-react-class');
+import React from 'react';
+import createReactClass from 'create-react-class';
+import request from 'superagent';
-const request = require('superagent');
-
-const Stats = createClass({
+const Stats = createReactClass({
displayName : 'Stats',
getDefaultProps(){
return {};
@@ -43,4 +42,4 @@ const Stats = createClass({
}
});
-module.exports = Stats;
+export default Stats;
diff --git a/client/admin/lockTools/lockTools.jsx b/client/admin/lockTools/lockTools.jsx
index 9a28d330f..8144d5d11 100644
--- a/client/admin/lockTools/lockTools.jsx
+++ b/client/admin/lockTools/lockTools.jsx
@@ -1,11 +1,11 @@
/*eslint max-lines: ["warn", {"max": 500, "skipBlankLines": true, "skipComments": true}]*/
-require('./lockTools.less');
-const React = require('react');
-const createClass = require('create-react-class');
+import './lockTools.less';
+import React from 'react';
+import createReactClass from 'create-react-class';
import request from '../../homebrew/utils/request-middleware.js';
-const LockTools = createClass({
+const LockTools = createReactClass({
displayName : 'LockTools',
getInitialState : function() {
return {
@@ -55,7 +55,7 @@ const LockTools = createClass({
}
});
-const LockBrew = createClass({
+const LockBrew = createReactClass({
displayName : 'LockBrew',
getInitialState : function() {
// Default values
@@ -183,7 +183,7 @@ const LockBrew = createClass({
}
});
-const LockTable = createClass({
+const LockTable = createReactClass({
displayName : 'LockTable',
getDefaultProps : function() {
return {
@@ -273,7 +273,7 @@ const LockTable = createClass({
}
});
-const LockLookup = createClass({
+const LockLookup = createReactClass({
displayName : 'LockLookup',
getDefaultProps : function() {
return {
@@ -339,4 +339,4 @@ const LockLookup = createClass({
}
});
-module.exports = LockTools;
\ No newline at end of file
+export default LockTools;
\ No newline at end of file
diff --git a/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx b/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx
index 0cca1047e..3a64d4bf7 100644
--- a/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx
+++ b/client/admin/notificationUtils/notificationAdd/notificationAdd.jsx
@@ -1,7 +1,6 @@
-require('./notificationAdd.less');
-const React = require('react');
-const { useState, useRef } = require('react');
-const request = require('superagent');
+import './notificationAdd.less';
+import React, { useState, useRef } from 'react';
+import request from 'superagent';
const NotificationAdd = ()=>{
const [notificationResult, setNotificationResult] = useState(null);
@@ -106,4 +105,4 @@ const NotificationAdd = ()=>{
);
};
-module.exports = NotificationAdd;
+export default NotificationAdd;
diff --git a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx
index 05f81b776..063b3e908 100644
--- a/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx
+++ b/client/admin/notificationUtils/notificationLookup/notificationLookup.jsx
@@ -1,9 +1,7 @@
-require('./notificationLookup.less');
-
-const React = require('react');
-const { useState } = require('react');
-const request = require('superagent');
-const Moment = require('moment');
+import './notificationLookup.less';
+import React, { useState } from 'react';
+import request from 'superagent';
+import Moment from 'moment';
const NotificationDetail = ({ notification, onDelete })=>(
<>
@@ -102,4 +100,4 @@ const NotificationLookup = ()=>{
);
};
-module.exports = NotificationLookup;
+export default NotificationLookup;
diff --git a/client/admin/notificationUtils/notificationUtils.jsx b/client/admin/notificationUtils/notificationUtils.jsx
index 22ea21328..00db44a37 100644
--- a/client/admin/notificationUtils/notificationUtils.jsx
+++ b/client/admin/notificationUtils/notificationUtils.jsx
@@ -1,7 +1,6 @@
-const React = require('react');
-
-const NotificationLookup = require('./notificationLookup/notificationLookup.jsx');
-const NotificationAdd = require('./notificationAdd/notificationAdd.jsx');
+import React from 'react';
+import NotificationLookup from './notificationLookup/notificationLookup.jsx';
+import NotificationAdd from './notificationAdd/notificationAdd.jsx';
const NotificationUtils = ()=>{
return (
@@ -12,4 +11,4 @@ const NotificationUtils = ()=>{
);
};
-module.exports = NotificationUtils;
+export default NotificationUtils;
diff --git a/client/components/codeEditor/autocompleteEmoji.js b/client/components/codeEditor/autocompleteEmoji.js
index ae7f2628f..d5a3a71aa 100644
--- a/client/components/codeEditor/autocompleteEmoji.js
+++ b/client/components/codeEditor/autocompleteEmoji.js
@@ -79,6 +79,6 @@ const showAutocompleteEmoji = function(CodeMirror, editor) {
});
};
-module.exports = {
+export default {
showAutocompleteEmoji
};
\ No newline at end of file
diff --git a/client/components/codeEditor/close-tag.js b/client/components/codeEditor/close-tag.js
index 728b63a5c..84cf62169 100644
--- a/client/components/codeEditor/close-tag.js
+++ b/client/components/codeEditor/close-tag.js
@@ -38,11 +38,11 @@ const autoCloseCurlyBraces = function(CodeMirror, cm, typingClosingBrace) {
}
};
-module.exports = {
+export default {
autoCloseCurlyBraces : function(CodeMirror, codeMirror) {
const map = { name: 'autoCloseCurlyBraces' };
map[`'{'`] = function(cm) { return autoCloseCurlyBraces(CodeMirror, cm); };
map[`'}'`] = function(cm) { return autoCloseCurlyBraces(CodeMirror, cm, true); };
- codeMirror.addKeyMap(map);
+ codeMirror?.addKeyMap(map);
}
};
\ No newline at end of file
diff --git a/client/components/codeEditor/codeEditor.jsx b/client/components/codeEditor/codeEditor.jsx
index fb69b6dcf..3ec986689 100644
--- a/client/components/codeEditor/codeEditor.jsx
+++ b/client/components/codeEditor/codeEditor.jsx
@@ -1,51 +1,13 @@
/* eslint-disable max-lines */
-require('./codeEditor.less');
-const React = require('react');
-const createClass = require('create-react-class');
-const _ = require('lodash');
-const closeTag = require('./close-tag');
-const autoCompleteEmoji = require('./autocompleteEmoji');
-
+import './codeEditor.less';
+import React from 'react';
+import createReactClass from 'create-react-class';
+import _ from 'lodash';
+import closeTag from './close-tag';
+import autoCompleteEmoji from './autocompleteEmoji';
let CodeMirror;
-if(typeof window !== 'undefined'){
- CodeMirror = require('codemirror');
- //Language Modes
- require('codemirror/mode/gfm/gfm.js'); //Github flavoured markdown
- require('codemirror/mode/css/css.js');
- require('codemirror/mode/javascript/javascript.js');
-
- //Addons
- //Code folding
- require('codemirror/addon/fold/foldcode.js');
- require('codemirror/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');
- //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');
- //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');
- //Autocompletion
- require('codemirror/addon/hint/show-hint.js');
-
- const foldPagesCode = require('./fold-pages');
- foldPagesCode.registerHomebreweryHelper(CodeMirror);
- const foldCSSCode = require('./fold-css');
- foldCSSCode.registerHomebreweryHelper(CodeMirror);
-}
-
-const CodeEditor = createClass({
+const CodeEditor = createReactClass({
displayName : 'CodeEditor',
getDefaultProps : function() {
return {
@@ -66,23 +28,54 @@ const CodeEditor = createClass({
editor : React.createRef(null),
- componentDidMount : function() {
+ async componentDidMount() {
+ CodeMirror = (await import('codemirror')).default;
+ this.CodeMirror = CodeMirror;
+
+ await import('codemirror/mode/gfm/gfm.js');
+ await import('codemirror/mode/css/css.js');
+ await import('codemirror/mode/javascript/javascript.js');
+
+ // addons
+ await import('codemirror/addon/fold/foldcode.js');
+ await import('codemirror/addon/fold/foldgutter.js');
+ await import('codemirror/addon/fold/xml-fold.js');
+ await import('codemirror/addon/search/search.js');
+ await import('codemirror/addon/search/searchcursor.js');
+ await import('codemirror/addon/search/jump-to-line.js');
+ await import('codemirror/addon/search/match-highlighter.js');
+ await import('codemirror/addon/search/matchesonscrollbar.js');
+ await import('codemirror/addon/dialog/dialog.js');
+ await import('codemirror/addon/scroll/scrollpastend.js');
+ await import('codemirror/addon/edit/closetag.js');
+ await import('codemirror/addon/hint/show-hint.js');
+ // import 'codemirror/addon/selection/active-line.js';
+ // import 'codemirror/addon/edit/trailingspace.js';
+
+
+ // register helpers dynamically as well
+ const foldPagesCode = (await import('./fold-pages')).default;
+ const foldCSSCode = (await import('./fold-css')).default;
+ foldPagesCode.registerHomebreweryHelper(CodeMirror);
+ foldCSSCode.registerHomebreweryHelper(CodeMirror);
+
this.buildEditor();
- const newDoc = CodeMirror.Doc(this.props.value, this.props.language);
- this.codeMirror.swapDoc(newDoc);
+ const newDoc = CodeMirror?.Doc(this.props.value, this.props.language);
+ this.codeMirror?.swapDoc(newDoc);
},
+
componentDidUpdate : function(prevProps) {
if(prevProps.view !== this.props.view){ //view changed; swap documents
let newDoc;
if(!this.state.docs[this.props.view]) {
- newDoc = CodeMirror.Doc(this.props.value, this.props.language);
+ newDoc = CodeMirror?.Doc(this.props.value, this.props.language);
} else {
newDoc = this.state.docs[this.props.view];
}
- const oldDoc = { [prevProps.view]: this.codeMirror.swapDoc(newDoc) };
+ const oldDoc = { [prevProps.view]: this.codeMirror?.swapDoc(newDoc) };
this.setState((prevState)=>({
docs : _.merge({}, prevState.docs, oldDoc)
@@ -90,17 +83,17 @@ const CodeEditor = createClass({
this.props.rerenderParent();
} else if(this.codeMirror?.getValue() != this.props.value) { //update editor contents if brew.text is changed from outside
- this.codeMirror.setValue(this.props.value);
+ this.codeMirror?.setValue(this.props.value);
}
if(this.props.enableFolding) {
- this.codeMirror.setOption('foldOptions', this.foldOptions(this.codeMirror));
+ this.codeMirror?.setOption('foldOptions', this.foldOptions(this.codeMirror));
} else {
- this.codeMirror.setOption('foldOptions', false);
+ this.codeMirror?.setOption('foldOptions', false);
}
if(prevProps.editorTheme !== this.props.editorTheme){
- this.codeMirror.setOption('theme', this.props.editorTheme);
+ this.codeMirror?.setOption('theme', this.props.editorTheme);
}
},
@@ -188,8 +181,8 @@ const CodeEditor = createClass({
closeTag.autoCloseCurlyBraces(CodeMirror, this.codeMirror);
autoCompleteEmoji.showAutocompleteEmoji(CodeMirror, this.codeMirror);
- // Note: codeMirror passes a copy of itself in this callback. cm === this.codeMirror. Either one works.
- this.codeMirror.on('change', (cm)=>{this.props.onChange(cm.getValue());});
+ // Note: codeMirror passes a copy of itself in this callback. cm === this.codeMirror?. Either one works.
+ this.codeMirror?.on('change', (cm)=>{this.props.onChange(cm.getValue());});
this.updateSize();
},
@@ -203,84 +196,84 @@ const CodeEditor = createClass({
},
dedent : function () {
- this.codeMirror.execCommand('indentLess');
+ this.codeMirror?.execCommand('indentLess');
},
makeHeader : function (number) {
- const selection = this.codeMirror.getSelection();
+ const selection = this.codeMirror?.getSelection();
const header = Array(number).fill('#').join('');
- this.codeMirror.replaceSelection(`${header} ${selection}`, 'around');
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch + selection.length + number + 1 });
+ this.codeMirror?.replaceSelection(`${header} ${selection}`, 'around');
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch + selection.length + number + 1 });
},
makeBold : function() {
- const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '**' && selection.slice(-2) === '**';
- this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `**${selection}**`, 'around');
+ const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 2) === '**' && selection.slice(-2) === '**';
+ this.codeMirror?.replaceSelection(t ? selection.slice(2, -2) : `**${selection}**`, 'around');
if(selection.length === 0){
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
}
},
makeItalic : function() {
- const selection = this.codeMirror.getSelection(), t = selection.slice(0, 1) === '*' && selection.slice(-1) === '*';
- this.codeMirror.replaceSelection(t ? selection.slice(1, -1) : `*${selection}*`, 'around');
+ const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 1) === '*' && selection.slice(-1) === '*';
+ this.codeMirror?.replaceSelection(t ? selection.slice(1, -1) : `*${selection}*`, 'around');
if(selection.length === 0){
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 1 });
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 1 });
}
},
makeSuper : function() {
- const selection = this.codeMirror.getSelection(), t = selection.slice(0, 1) === '^' && selection.slice(-1) === '^';
- this.codeMirror.replaceSelection(t ? selection.slice(1, -1) : `^${selection}^`, 'around');
+ const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 1) === '^' && selection.slice(-1) === '^';
+ this.codeMirror?.replaceSelection(t ? selection.slice(1, -1) : `^${selection}^`, 'around');
if(selection.length === 0){
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 1 });
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 1 });
}
},
makeSub : function() {
- const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '^^' && selection.slice(-2) === '^^';
- this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `^^${selection}^^`, 'around');
+ const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 2) === '^^' && selection.slice(-2) === '^^';
+ this.codeMirror?.replaceSelection(t ? selection.slice(2, -2) : `^^${selection}^^`, 'around');
if(selection.length === 0){
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
}
},
makeNbsp : function() {
- this.codeMirror.replaceSelection(' ', 'end');
+ this.codeMirror?.replaceSelection(' ', 'end');
},
makeSpace : function() {
- const selection = this.codeMirror.getSelection();
+ const selection = this.codeMirror?.getSelection();
const t = selection.slice(0, 8) === '{{width:' && selection.slice(0 -4) === '% }}';
if(t){
const percent = parseInt(selection.slice(8, -4)) + 10;
- this.codeMirror.replaceSelection(percent < 90 ? `{{width:${percent}% }}` : '{{width:100% }}', 'around');
+ this.codeMirror?.replaceSelection(percent < 90 ? `{{width:${percent}% }}` : '{{width:100% }}', 'around');
} else {
- this.codeMirror.replaceSelection(`{{width:10% }}`, 'around');
+ this.codeMirror?.replaceSelection(`{{width:10% }}`, 'around');
}
},
removeSpace : function() {
- const selection = this.codeMirror.getSelection();
+ const selection = this.codeMirror?.getSelection();
const t = selection.slice(0, 8) === '{{width:' && selection.slice(0 -4) === '% }}';
if(t){
const percent = parseInt(selection.slice(8, -4)) - 10;
- this.codeMirror.replaceSelection(percent > 10 ? `{{width:${percent}% }}` : '', 'around');
+ this.codeMirror?.replaceSelection(percent > 10 ? `{{width:${percent}% }}` : '', 'around');
}
},
newColumn : function() {
- this.codeMirror.replaceSelection('\n\\column\n\n', 'end');
+ this.codeMirror?.replaceSelection('\n\\column\n\n', 'end');
},
newPage : function() {
- this.codeMirror.replaceSelection('\n\\page\n\n', 'end');
+ this.codeMirror?.replaceSelection('\n\\page\n\n', 'end');
},
injectText : function(injectText, overwrite=true) {
@@ -293,29 +286,29 @@ const CodeEditor = createClass({
},
makeUnderline : function() {
- const selection = this.codeMirror.getSelection(), t = selection.slice(0, 3) === '' && selection.slice(-4) === '';
- this.codeMirror.replaceSelection(t ? selection.slice(3, -4) : `${selection}`, 'around');
+ const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 3) === '' && selection.slice(-4) === '';
+ this.codeMirror?.replaceSelection(t ? selection.slice(3, -4) : `${selection}`, 'around');
if(selection.length === 0){
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 4 });
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 4 });
}
},
makeSpan : function() {
- const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '{{' && selection.slice(-2) === '}}';
- this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `{{ ${selection}}}`, 'around');
+ const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 2) === '{{' && selection.slice(-2) === '}}';
+ this.codeMirror?.replaceSelection(t ? selection.slice(2, -2) : `{{ ${selection}}}`, 'around');
if(selection.length === 0){
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - 2 });
}
},
makeDiv : function() {
- const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '{{' && selection.slice(-2) === '}}';
- this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `{{\n${selection}\n}}`, 'around');
+ const selection = this.codeMirror?.getSelection(), t = selection.slice(0, 2) === '{{' && selection.slice(-2) === '}}';
+ this.codeMirror?.replaceSelection(t ? selection.slice(2, -2) : `{{\n${selection}\n}}`, 'around');
if(selection.length === 0){
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setCursor({ line: cursor.line - 1, ch: cursor.ch }); // set to -2? if wanting to enter classes etc. if so, get rid of first \n when replacing selection
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setCursor({ line: cursor.line - 1, ch: cursor.ch }); // set to -2? if wanting to enter classes etc. if so, get rid of first \n when replacing selection
}
},
@@ -323,7 +316,7 @@ const CodeEditor = createClass({
let regex;
let cursorPos;
let newComment;
- const selection = this.codeMirror.getSelection();
+ const selection = this.codeMirror?.getSelection();
if(this.props.language === 'gfm'){
regex = /^\s*()\s*$/gs;
cursorPos = 4;
@@ -333,44 +326,44 @@ const CodeEditor = createClass({
cursorPos = 3;
newComment = `/* ${selection} */`;
}
- this.codeMirror.replaceSelection(regex.test(selection) == true ? selection.replace(regex, '$2') : newComment, 'around');
+ this.codeMirror?.replaceSelection(regex.test(selection) == true ? selection.replace(regex, '$2') : newComment, 'around');
if(selection.length === 0){
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - cursorPos });
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setCursor({ line: cursor.line, ch: cursor.ch - cursorPos });
};
},
makeLink : function() {
const isLink = /^\[(.*)\]\((.*)\)$/;
- const selection = this.codeMirror.getSelection().trim();
+ const selection = this.codeMirror?.getSelection().trim();
let match;
if(match = isLink.exec(selection)){
const altText = match[1];
const url = match[2];
- this.codeMirror.replaceSelection(`${altText} ${url}`);
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setSelection({ line: cursor.line, ch: cursor.ch - url.length }, { line: cursor.line, ch: cursor.ch });
+ this.codeMirror?.replaceSelection(`${altText} ${url}`);
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setSelection({ line: cursor.line, ch: cursor.ch - url.length }, { line: cursor.line, ch: cursor.ch });
} else {
- this.codeMirror.replaceSelection(`[${selection || 'alt text'}](url)`);
- const cursor = this.codeMirror.getCursor();
- this.codeMirror.setSelection({ line: cursor.line, ch: cursor.ch - 4 }, { line: cursor.line, ch: cursor.ch - 1 });
+ this.codeMirror?.replaceSelection(`[${selection || 'alt text'}](url)`);
+ const cursor = this.codeMirror?.getCursor();
+ this.codeMirror?.setSelection({ line: cursor.line, ch: cursor.ch - 4 }, { line: cursor.line, ch: cursor.ch - 1 });
}
},
makeList : function(listType) {
- const selectionStart = this.codeMirror.getCursor('from'), selectionEnd = this.codeMirror.getCursor('to');
- this.codeMirror.setSelection(
+ const selectionStart = this.codeMirror?.getCursor('from'), selectionEnd = this.codeMirror?.getCursor('to');
+ this.codeMirror?.setSelection(
{ line: selectionStart.line, ch: 0 },
- { line: selectionEnd.line, ch: this.codeMirror.getLine(selectionEnd.line).length }
+ { line: selectionEnd.line, ch: this.codeMirror?.getLine(selectionEnd.line).length }
);
- const newSelection = this.codeMirror.getSelection();
+ const newSelection = this.codeMirror?.getSelection();
const regex = /^\d+\.\s|^-\s/gm;
if(newSelection.match(regex) != null){ // if selection IS A LIST
- this.codeMirror.replaceSelection(newSelection.replace(regex, ''), 'around');
+ this.codeMirror?.replaceSelection(newSelection.replace(regex, ''), 'around');
} else { // if selection IS NOT A LIST
- listType == 'UL' ? this.codeMirror.replaceSelection(newSelection.replace(/^/gm, `- `), 'around') :
- this.codeMirror.replaceSelection(newSelection.replace(/^/gm, (()=>{
+ listType == 'UL' ? this.codeMirror?.replaceSelection(newSelection.replace(/^/gm, `- `), 'around') :
+ this.codeMirror?.replaceSelection(newSelection.replace(/^/gm, (()=>{
let n = 1;
return ()=>{
return `${n++}. `;
@@ -380,39 +373,39 @@ const CodeEditor = createClass({
},
foldAllCode : function() {
- this.codeMirror.execCommand('foldAll');
+ this.codeMirror?.execCommand('foldAll');
},
unfoldAllCode : function() {
- this.codeMirror.execCommand('unfoldAll');
+ this.codeMirror?.execCommand('unfoldAll');
},
//=-- Externally used -==//
setCursorPosition : function(line, char){
setTimeout(()=>{
- this.codeMirror.focus();
- this.codeMirror.doc.setCursor(line, char);
+ this.codeMirror?.focus();
+ this.codeMirror?.doc.setCursor(line, char);
}, 10);
},
getCursorPosition : function(){
- return this.codeMirror.getCursor();
+ return this.codeMirror?.getCursor();
},
getTopVisibleLine : function(){
- const rect = this.codeMirror.getWrapperElement().getBoundingClientRect();
- const topVisibleLine = this.codeMirror.lineAtHeight(rect.top, 'window');
+ const rect = this.codeMirror?.getWrapperElement().getBoundingClientRect();
+ const topVisibleLine = this.codeMirror?.lineAtHeight(rect.top, 'window');
return topVisibleLine;
},
updateSize : function(){
- this.codeMirror.refresh();
+ this.codeMirror?.refresh();
},
redo : function(){
- return this.codeMirror.redo();
+ return this.codeMirror?.redo();
},
undo : function(){
- return this.codeMirror.undo();
+ return this.codeMirror?.undo();
},
historySize : function(){
- return this.codeMirror.doc.historySize();
+ return this.codeMirror?.doc.historySize();
},
foldOptions : function(cm){
@@ -426,7 +419,7 @@ const CodeEditor = createClass({
let foldPreviewText = '';
while (currentLine <= to.line && text.length <= maxLength) {
- const currentText = this.codeMirror.getLine(currentLine);
+ const currentText = this.codeMirror?.getLine(currentLine);
currentLine++;
if(currentText[0] == '#'){
foldPreviewText = currentText;
@@ -461,5 +454,5 @@ const CodeEditor = createClass({
}
});
-module.exports = CodeEditor;
+export default CodeEditor;
diff --git a/client/components/codeEditor/fold-css.js b/client/components/codeEditor/fold-css.js
index 338cab176..06bfd96a4 100644
--- a/client/components/codeEditor/fold-css.js
+++ b/client/components/codeEditor/fold-css.js
@@ -1,4 +1,4 @@
-module.exports = {
+export default {
registerHomebreweryHelper : function(CodeMirror) {
CodeMirror.registerHelper('fold', 'homebrewerycss', function(cm, start) {
diff --git a/client/components/codeEditor/fold-pages.js b/client/components/codeEditor/fold-pages.js
index cff1c64e0..1d8d19f6b 100644
--- a/client/components/codeEditor/fold-pages.js
+++ b/client/components/codeEditor/fold-pages.js
@@ -1,4 +1,4 @@
-module.exports = {
+export default {
registerHomebreweryHelper : function(CodeMirror) {
CodeMirror.registerHelper('fold', 'homebrewery', function(cm, start) {
const matcher = /^\\page.*/;
diff --git a/client/components/combobox.jsx b/client/components/combobox.jsx
index ae9f1d7f8..651a31516 100644
--- a/client/components/combobox.jsx
+++ b/client/components/combobox.jsx
@@ -1,9 +1,9 @@
-const React = require('react');
-const createClass = require('create-react-class');
-const _ = require('lodash');
-require('./combobox.less');
+import React from 'react';
+import createReactClass from 'create-react-class';
+import _ from 'lodash';
+import './combobox.less';
-const Combobox = createClass({
+const Combobox = createReactClass({
displayName : 'Combobox',
getDefaultProps : function() {
return {
@@ -126,4 +126,4 @@ const Combobox = createClass({
}
});
-module.exports = Combobox;
+export default Combobox;
diff --git a/client/components/renderWarnings/renderWarnings.jsx b/client/components/renderWarnings/renderWarnings.jsx
index 6b8ea8184..75fdb8ff4 100644
--- a/client/components/renderWarnings/renderWarnings.jsx
+++ b/client/components/renderWarnings/renderWarnings.jsx
@@ -1,11 +1,11 @@
-require('./renderWarnings.less');
-const React = require('react');
-const createClass = require('create-react-class');
-const _ = require('lodash');
+import './renderWarnings.less';
+import React from 'react';
+import createReactClass from 'create-react-class';
+import _ from 'lodash';
import Dialog from '../dialog.jsx';
-const RenderWarnings = createClass({
+const RenderWarnings = createReactClass({
displayName : 'RenderWarnings',
getInitialState : function() {
return {
@@ -57,4 +57,4 @@ const RenderWarnings = createClass({
}
});
-module.exports = RenderWarnings;
+export default RenderWarnings;
diff --git a/client/components/splitPane/splitPane.jsx b/client/components/splitPane/splitPane.jsx
index 78ba59ed3..7cbfe2066 100644
--- a/client/components/splitPane/splitPane.jsx
+++ b/client/components/splitPane/splitPane.jsx
@@ -1,6 +1,5 @@
-require('./splitPane.less');
-const React = require('react');
-const { useState, useEffect } = React;
+import './splitPane.less';
+import React, { useEffect, useState } from 'react';
const PANE_WIDTH_KEY = 'HB_editor_splitWidth';
const LIVE_SCROLL_KEY = 'HB_editor_liveScroll';
@@ -108,4 +107,4 @@ const Pane = ({ width, children, isDragging, moveBrew, moveSource, liveScroll, s
);
};
-module.exports = SplitPane;
+export default SplitPane;
diff --git a/client/components/svg/cauldron.svg.jsx b/client/components/svg/cauldron.svg.jsx
index 49405783b..c396dd05e 100644
--- a/client/components/svg/cauldron.svg.jsx
+++ b/client/components/svg/cauldron.svg.jsx
@@ -1,7 +1,6 @@
-const React = require('react');
-const createClass = require('create-react-class');
+import React from 'react';
-module.exports = function(props){
+export default function(props){
return