0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-23 09:53:06 +00:00

Compare commits

...

44 Commits

Author SHA1 Message Date
Trevor Buckner
e497e42913 TEST 2025-11-17 16:15:44 +00:00
Víctor Losada Hernández
677e8eaf6c Merge pull request #4532 from G-Ambatte/fixUnearthedArcanaTheme
Fix UnearthedArcana theme
2025-11-15 17:52:59 +01:00
G.Ambatte
ad3d63a5b1 Merge branch 'master' into fixUnearthedArcanaTheme 2025-11-15 18:44:33 +13:00
G.Ambatte
93ef9bfd51 Set UnearthedArcana baseTheme to Blank 2025-11-15 18:33:22 +13:00
Trevor Buckner
972c675629 Merge pull request #4527 from MiniX16/master
Add unsaved-change warning to Home page editor
2025-11-14 23:04:19 -05:00
Trevor Buckner
fa9f180759 Modify slightly to follow the existing structure in editPage.jsx for easier merging of these pages later 2025-11-14 22:59:34 -05:00
Trevor Buckner
5625121b82 Merge branch 'master' into master 2025-11-14 22:25:47 -05:00
Trevor Buckner
b6065dbcf5 Fix page break in changelog 2025-11-15 03:12:29 +00:00
Trevor Buckner
24065b43e9 bump version to 3.20.0 2025-11-15 03:07:56 +00:00
G.Ambatte
d73b695127 Merge branch 'master' into master 2025-11-15 14:34:13 +13:00
Trevor Buckner
acd37bff4f Merge pull request #4409 from G-Ambatte/fixUserPageLinks-#807
Change all links to User Page to use encodeURIComponent
2025-11-14 17:20:12 -05:00
Trevor Buckner
76a4ff11b3 Merge branch 'master' into fixUserPageLinks-#807 2025-11-14 17:19:45 -05:00
MiniX16
b66625e59d Handle unsaved warning with onbeforeunload 2025-11-13 12:16:37 +01:00
Trevor Buckner
885a59a05f Merge pull request #4526 from G-Ambatte/fixEditPageGoogleTransfer
Fix transferring brews to/from Google storage
2025-11-12 14:46:57 -05:00
Trevor Buckner
2012f373c0 Merge branch 'master' into fixEditPageGoogleTransfer 2025-11-12 14:46:41 -05:00
MiniX16
590688f123 Add unsaved-change warning to Home page editor 2025-11-12 17:59:28 +01:00
G.Ambatte
6a4ea2c6c9 Move toggleGoogleStorage's trySave call to useEffect block 2025-11-11 22:06:44 +13:00
Víctor Losada Hernández
6ccefc2399 Merge pull request #4510 from Gazook89/Move-Nav.JSX
Move nav.jsx from shared to client directory
2025-11-10 23:41:39 +01:00
Víctor Losada Hernández
8d2744d106 Merge branch 'master' into Move-Nav.JSX 2025-11-10 23:38:21 +01:00
Víctor Losada Hernández
fe616a534a Merge pull request #4517 from G-Ambatte/fixSaveOnNewPage
Fix CTRL+S triggering save on New Page
2025-11-10 23:38:06 +01:00
Víctor Losada Hernández
71462ef782 Merge branch 'master' into fixSaveOnNewPage 2025-11-10 23:33:43 +01:00
Víctor Losada Hernández
64589bfda6 Merge pull request #4514 from Gazook89/move-codeEditor-to-components
Move codeEditor to components directory
2025-11-10 23:26:22 +01:00
Gazook89
f9f33955bc Merge branch 'master' into move-codeEditor-to-components 2025-11-09 23:30:53 -06:00
Gazook89
2ce13f61e1 update relative paths to absolute paths 2025-11-09 23:29:55 -06:00
Gazook89
6db4bf2274 Merge branch 'master' into Move-Nav.JSX 2025-11-09 23:24:21 -06:00
Trevor Buckner
750c237e02 Merge pull request #4513 from Gazook89/move-SVGs-to-components
Move SVG components to components folder
2025-11-09 18:39:44 -05:00
Trevor Buckner
1c8ef9ff3e Merge branch 'master' into move-SVGs-to-components 2025-11-09 18:37:20 -05:00
Trevor Buckner
5ca75ff0ef Merge pull request #4506 from dbolack-ab/dockerBuild
Add Docker Image build and Publish functions to package,json
2025-11-09 18:28:56 -05:00
Trevor Buckner
b5400b6959 Merge branch 'master' into dockerBuild 2025-11-09 18:24:07 -05:00
Trevor Buckner
e6e66ec1cc Merge branch 'master' into Move-Nav.JSX 2025-11-09 18:19:28 -05:00
Trevor Buckner
9da28f06e5 Merge pull request #4516 from Gazook89/move-markdown.js
Move markdown.js and markdownlegacy.js
2025-11-09 18:15:39 -05:00
Trevor Buckner
af348e7b2c Merge branch 'master' into move-markdown.js 2025-11-08 21:47:02 -05:00
Trevor Buckner
e02890c03e Merge pull request #4512 from Gazook89/Move-renderWarnings
Move renderWarnings from shared to client
2025-11-08 21:46:01 -05:00
G.Ambatte
20d38d03d6 Rename New Page save function to trySave for better Edit Page compatibility 2025-11-06 22:29:43 +13:00
Gazook89
c5aa774daa Move markdown.js and markdownlegacy.js
Moves the two files up a level, directly in `/shared/`.  Everything else is just updating paths for that.
2025-11-04 22:29:28 -06:00
Gazook89
29fe6430ce Move codeEditor to components directory
This simply moves the codeEditor folder to the components directory.  `codeEditor.jsx` simply builds a component which is then used elsewhere, and isn't shared between client and server, so it should be in the client directory.

Arguably it could go in `client/homebrew/editor` but I think the `/homebrew/` folder should be eliminated down the line and it's contents just re-sorted.

When working on the editor right now it's a pain to switch between `shared` and `client` hunting for the right file.
2025-11-04 13:12:56 -06:00
Gazook89
c38cc77fd0 Move SVG components to components folder
Move the SVGs out of the `shared` directory, closer to where they are actually used.  They are svg jsx files, setup as components, so i've moved them to the components directory.

Deleted `combat.svg.jsx` because we don't use it anywhere.

renamed the remaining two to be more descriptive of the image for additional clarity.
2025-11-04 12:52:12 -06:00
Gazook89
fc569e560b Move renderWarnings from shared to client
Moving this component to the component folder so it's closer to where it is actually used.  Not moving to the `homebrew` folder because ultimately i think pretty much everything in that folder should move to the components as well (`homebrew` isn't a helpful folder distinction).

Deletes a directory, moves 2 files.
2025-11-03 21:50:31 -06:00
Gazook89
081fd6f39d Move nav.jsx from shared to client directory
Moving the one file, changing a lot of imports (18 files), and deleting a directory.
2025-11-03 20:58:00 -06:00
David Bolack
bc41b9043d Remove circleci tests 2025-10-28 14:44:54 -05:00
David Bolack
a0d288057f Add Docker Image build and Publish to workflow
Adds docker:build and docker:publish npm scripts
expects DOCKERID to contain the user/organization id for formatting the tag ( DOCKERID/hombrewery:version )

Add CircleCI test to ensure image still builds
2025-10-28 14:10:04 -05:00
G.Ambatte
9f3944d038 Merge branch 'master' into fixUserPageLinks-#807 2025-09-29 23:14:59 +13:00
G.Ambatte
e1fb0a42c3 Merge branch 'master' into fixUserPageLinks-#807 2025-09-20 20:23:58 +12:00
G.Ambatte
90de9c0af1 Change all links to User Page to use encodeURIComponent 2025-09-01 21:51:27 +12:00
58 changed files with 2761 additions and 2444 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
import diceFont from '../../../themes/fonts/iconFonts/diceFont.js';
import elderberryInn from '../../../themes/fonts/iconFonts/elderberryInn.js';
import fontAwesome from '../../../themes/fonts/iconFonts/fontAwesome.js';
import gameIcons from '../../../themes/fonts/iconFonts/gameIcons.js';
import diceFont from 'themes/fonts/iconFonts/diceFont.js';
import elderberryInn from 'themes/fonts/iconFonts/elderberryInn.js';
import fontAwesome from 'themes/fonts/iconFonts/fontAwesome.js';
import gameIcons from 'themes/fonts/iconFonts/gameIcons.js';
const emojis = {
...diceFont,

View File

@@ -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;

View File

@@ -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;
}
}

View 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;

View File

@@ -3,7 +3,7 @@ const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
import Dialog from '../../../client/components/dialog.jsx';
import Dialog from '../dialog.jsx';
const RenderWarnings = createClass({
displayName : 'RenderWarnings',
@@ -25,7 +25,7 @@ const RenderWarnings = createClass({
if(!isChrome){
return <li key='chrome'>
<em>Built for Chrome </em> <br />
Other browsers have not been tested for compatiblilty. If you
Other browsers have not been tested for compatibility. If you
experience issues with your document not rendering or printing
properly, please try using the latest version of Chrome before
submitting a bug report.

View File

@@ -4,13 +4,13 @@ const React = require('react');
const { useState, useRef, useMemo, useEffect } = React;
const _ = require('lodash');
const MarkdownLegacy = require('naturalcrit/markdownLegacy.js');
import Markdown from 'naturalcrit/markdown.js';
const MarkdownLegacy = require('markdownLegacy.js');
import Markdown from 'markdown.js';
const ErrorBar = require('./errorBar/errorBar.jsx');
const ToolBar = require('./toolBar/toolBar.jsx');
//TODO: move to the brew renderer
const RenderWarnings = require('homebrewery/renderWarnings/renderWarnings.jsx');
const RenderWarnings = require('client/components/renderWarnings/renderWarnings.jsx');
const NotificationPopup = require('./notificationPopup/notificationPopup.jsx');
const Frame = require('react-frame-component').default;
const dedent = require('dedent-tabs').default;

View File

@@ -1,7 +1,7 @@
require('./notificationPopup.less');
import React, { useEffect, useState } from 'react';
import request from '../../utils/request-middleware.js';
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
import Dialog from '../../../components/dialog.jsx';

View File

@@ -4,9 +4,12 @@ const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const dedent = require('dedent-tabs').default;
import Markdown from '../../../shared/naturalcrit/markdown.js';
import Markdown from '../../../shared/markdown.js';
const CodeEditor = require('naturalcrit/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 MetadataEditor = require('./metadataEditor/metadataEditor.jsx');
@@ -62,8 +65,34 @@ const Editor = createClass({
};
},
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) {
@@ -90,7 +121,7 @@ const Editor = createClass({
componentDidUpdate : function(prevProps, prevState, snapshot) {
this.highlightCustomMarkdown();
if(!USE_CM6) this.highlightCustomMarkdown();
if(prevProps.moveBrew !== this.props.moveBrew)
this.brewJump();
@@ -121,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);

View File

@@ -1,6 +1,6 @@
const React = require('react');
const createClass = require('create-react-class');
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const request = require('superagent');
const Account = createClass({
@@ -70,7 +70,7 @@ const Account = createClass({
{global.account.username}
</Nav.item>
<Nav.item
href={`/user/${encodeURI(global.account.username)}`}
href={`/user/${encodeURIComponent(global.account.username)}`}
color='yellow'
icon='fas fa-beer'
>

View File

@@ -1,6 +1,6 @@
require('./error-navitem.less');
const React = require('react');
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const ErrorNavItem = ({ error = '', clearError })=>{
const response = error.response;

View File

@@ -1,7 +1,7 @@
const React = require('react');
const dedent = require('dedent-tabs').default;
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
module.exports = function(props){
return <Nav.dropdown>

View File

@@ -2,7 +2,7 @@ const React = require('react');
const createClass = require('create-react-class');
const Moment = require('moment');
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const MetadataNav = createClass({
@@ -32,7 +32,7 @@ const MetadataNav = createClass({
return <>
{this.props.brew.authors.map((author, idx, arr)=>{
const spacer = arr.length - 1 == idx ? <></> : <span>, </span>;
return <span key={idx}><a className='userPageLink' href={`/user/${author}`}>{author}</a>{spacer}</span>;
return <span key={idx}><a className='userPageLink' href={`/user/${encodeURIComponent(author)}`}>{author}</a>{spacer}</span>;
})}
</>;
},

View File

@@ -5,7 +5,7 @@ const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const NaturalCritIcon = require('naturalcrit/svg/naturalcrit.svg.jsx');
const NaturalCritIcon = require('client/components/svg/naturalcrit-d20.svg.jsx');
const Nav = {
base : createClass({

View File

@@ -2,7 +2,7 @@ require('./navbar.less');
const React = require('react');
const createClass = require('create-react-class');
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const PatreonNavItem = require('./patreon.navitem.jsx');
const Navbar = createClass({

View File

@@ -1,6 +1,6 @@
const React = require('react');
const _ = require('lodash');
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const { splitTextStyleAndMetadata } = require('../../../shared/helpers.js'); // Importing the function from helpers.js
const BREWKEY = 'homebrewery-new';

View File

@@ -1,5 +1,5 @@
const React = require('react');
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
module.exports = function(props){
return <Nav.item

View File

@@ -1,5 +1,5 @@
const React = require('react');
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const { printCurrentBrew } = require('../../../shared/helpers.js');
module.exports = function(){

View File

@@ -3,7 +3,7 @@ const createClass = require('create-react-class');
const _ = require('lodash');
const Moment = require('moment');
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const EDIT_KEY = 'HB_nav_recentlyEdited';
const VIEW_KEY = 'HB_nav_recentlyViewed';

View File

@@ -1,6 +1,6 @@
import React from 'react';
import dedent from 'dedent-tabs';
import Nav from 'naturalcrit/nav/nav.jsx';
import Nav from 'client/homebrew/navbar/nav.jsx';
const getShareId = (brew)=>(
brew.googleId && !brew.stubbed

View File

@@ -1,6 +1,6 @@
const React = require('react');
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
module.exports = function (props) {
return (

View File

@@ -1,7 +1,7 @@
const React = require('react');
const moment = require('moment');
const UIPage = require('../basePages/uiPage/uiPage.jsx');
const NaturalCritIcon = require('naturalcrit/svg/naturalcrit.svg.jsx');
const NaturalCritIcon = require('client/components/svg/naturalcrit-d20.svg.jsx');
let SAVEKEY = '';

View File

@@ -143,7 +143,7 @@ const BrewItem = ({
<span title="Username contained an email address; hidden to protect user's privacy">
{author}
</span>
) : (<a href={`/user/${author}`}>{author}</a>)}
) : (<a href={`/user/${encodeURIComponent(author)}`}>{author}</a>)}
{index < brew.authors.length - 1 && ', '}
</React.Fragment>
))}

View File

@@ -2,12 +2,12 @@ require('./uiPage.less');
const React = require('react');
const createClass = require('create-react-class');
const Nav = require('naturalcrit/nav/nav.jsx');
const Navbar = require('../../../navbar/navbar.jsx');
const NewBrewItem = require('../../../navbar/newbrew.navitem.jsx');
const HelpNavItem = require('../../../navbar/help.navitem.jsx');
const RecentNavItem = require('../../../navbar/recent.navitem.jsx').both;
const Account = require('../../../navbar/account.navitem.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const Navbar = require('client/homebrew/navbar/navbar.jsx');
const NewBrewItem = require('client/homebrew/navbar/newbrew.navitem.jsx');
const HelpNavItem = require('client/homebrew/navbar/help.navitem.jsx');
const RecentNavItem = require('client/homebrew/navbar/recent.navitem.jsx').both;
const Account = require('client/homebrew/navbar/account.navitem.jsx');
const UIPage = createClass({

View File

@@ -4,7 +4,7 @@ import './editPage.less';
// Common imports
import React, { useState, useEffect, useRef } from 'react';
import request from '../../utils/request-middleware.js';
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
import _ from 'lodash';
import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js';
@@ -14,15 +14,15 @@ import SplitPane from 'client/components/splitPane/splitPane.jsx';
import Editor from '../../editor/editor.jsx';
import BrewRenderer from '../../brewRenderer/brewRenderer.jsx';
import Nav from 'naturalcrit/nav/nav.jsx';
import Navbar from '../../navbar/navbar.jsx';
import NewBrewItem from '../../navbar/newbrew.navitem.jsx';
import AccountNavItem from '../../navbar/account.navitem.jsx';
import ErrorNavItem from '../../navbar/error-navitem.jsx';
import HelpNavItem from '../../navbar/help.navitem.jsx';
import VaultNavItem from '../../navbar/vault.navitem.jsx';
import PrintNavItem from '../../navbar/print.navitem.jsx';
import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx';
import Nav from 'client/homebrew/navbar/nav.jsx';
import Navbar from 'client/homebrew/navbar/navbar.jsx';
import NewBrewItem from 'client/homebrew/navbar/newbrew.navitem.jsx';
import AccountNavItem from 'client/homebrew/navbar/account.navitem.jsx';
import ErrorNavItem from 'client/homebrew/navbar/error-navitem.jsx';
import HelpNavItem from 'client/homebrew/navbar/help.navitem.jsx';
import VaultNavItem from 'client/homebrew/navbar/vault.navitem.jsx';
import PrintNavItem from 'client/homebrew/navbar/print.navitem.jsx';
import { both as RecentNavItem } from 'client/homebrew/navbar/recent.navitem.jsx';
// Page specific imports
import { Meta } from 'vitreum/headtags';
@@ -30,7 +30,7 @@ import { md5 } from 'hash-wasm';
import { gzipSync, strToU8 } from 'fflate';
import { makePatches, stringifyPatches } from '@sanity/diff-match-patch';
import ShareNavItem from '../../navbar/share.navitem.jsx';
import ShareNavItem from 'client/homebrew/navbar/share.navitem.jsx';
import LockNotification from './lockNotification/lockNotification.jsx';
import { updateHistory, versionHistoryGarbageCollection } from '../../utils/versionHistory.js';
import googleDriveIcon from '../../googleDrive.svg';
@@ -119,6 +119,10 @@ const EditPage = (props)=>{
if(autoSaveEnabled) trySave(false, hasChange);
}, [currentBrew]);
useEffect(()=>{
trySave(true);
}, [saveGoogle]);
const handleSplitMove = ()=>{
editorRef.current?.update();
};
@@ -179,7 +183,6 @@ const EditPage = (props)=>{
const toggleGoogleStorage = ()=>{
setSaveGoogle((prev)=>!prev);
setError(null);
trySave(true);
};
const trySave = (immediate = false, hasChanges = true)=>{

View File

@@ -1,7 +1,7 @@
require('./errorPage.less');
const React = require('react');
const UIPage = require('../basePages/uiPage/uiPage.jsx');
import Markdown from '../../../../shared/naturalcrit/markdown.js';
import Markdown from '../../../../shared/markdown.js';
const ErrorIndex = require('./errors/errorIndex.js');
const ErrorPage = ({ brew })=>{

View File

@@ -96,7 +96,7 @@ const errorIndex = (props)=>{
**Brew Title:** ${escape(props.brew.brewTitle) || 'Unable to show title'}
**Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'}
**Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${encodeURIComponent(author)})`;}).join(', ') || 'Unable to list authors'}
[Click here to be redirected to the brew's share page.](/share/${props.brew.shareId})`,
@@ -111,7 +111,7 @@ const errorIndex = (props)=>{
**Brew Title:** ${escape(props.brew.brewTitle) || 'Unable to show title'}
**Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'}
**Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${encodeURIComponent(author)})`;}).join(', ') || 'Unable to list authors'}
[Click here to be redirected to the brew's share page.](/share/${props.brew.shareId})`,
@@ -222,7 +222,7 @@ const errorIndex = (props)=>{
**Brew Title:** ${escape(props.brew.brewTitle)}
**Brew Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'}`,
**Brew Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${encodeURIComponent(author)})`;}).join(', ') || 'Unable to list authors'}`,
// ####### Admin page error #######
'52' : dedent`

View File

@@ -4,7 +4,7 @@ import './homePage.less';
// Common imports
import React, { useState, useEffect, useRef } from 'react';
import request from '../../utils/request-middleware.js';
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
import _ from 'lodash';
import { DEFAULT_BREW } from '../../../../server/brewDefaults.js';
@@ -14,15 +14,15 @@ import SplitPane from 'client/components/splitPane/splitPane.jsx';
import Editor from '../../editor/editor.jsx';
import BrewRenderer from '../../brewRenderer/brewRenderer.jsx';
import Nav from 'naturalcrit/nav/nav.jsx';
import Navbar from '../../navbar/navbar.jsx';
import NewBrewItem from '../../navbar/newbrew.navitem.jsx';
import AccountNavItem from '../../navbar/account.navitem.jsx';
import ErrorNavItem from '../../navbar/error-navitem.jsx';
import HelpNavItem from '../../navbar/help.navitem.jsx';
import VaultNavItem from '../../navbar/vault.navitem.jsx';
import PrintNavItem from '../../navbar/print.navitem.jsx';
import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx';
import Nav from 'client/homebrew/navbar/nav.jsx';
import Navbar from 'client/homebrew/navbar/navbar.jsx';
import NewBrewItem from 'client/homebrew/navbar/newbrew.navitem.jsx';
import AccountNavItem from 'client/homebrew/navbar/account.navitem.jsx';
import ErrorNavItem from 'client/homebrew/navbar/error-navitem.jsx';
import HelpNavItem from 'client/homebrew/navbar/help.navitem.jsx';
import VaultNavItem from 'client/homebrew/navbar/vault.navitem.jsx';
import PrintNavItem from 'client/homebrew/navbar/print.navitem.jsx';
import { both as RecentNavItem } from 'client/homebrew/navbar/recent.navitem.jsx';
// Page specific imports
import { Meta } from 'vitreum/headtags';
@@ -53,8 +53,9 @@ const HomePage =(props)=>{
const [isSaving , setIsSaving] = useState(false);
const [autoSaveEnabled , setAutoSaveEnable] = useState(false);
const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew));
const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew));
const unsavedChangesRef = useRef(unsavedChanges);
useEffect(()=>{
fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme);
@@ -70,12 +71,20 @@ const HomePage =(props)=>{
};
document.addEventListener('keydown', handleControlKeys);
window.onbeforeunload = ()=>{
if(unsavedChangesRef.current)
return 'You have unsaved changes!';
};
return ()=>{
document.removeEventListener('keydown', handleControlKeys);
window.onbeforeunload = null;
};
}, []);
useEffect(()=>{
unsavedChangesRef.current = unsavedChanges;
}, [unsavedChanges]);
const save = ()=>{
request.post('/api')
.send(currentBrew)

View File

@@ -4,7 +4,7 @@ import './newPage.less';
// Common imports
import React, { useState, useEffect, useRef } from 'react';
import request from '../../utils/request-middleware.js';
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
import _ from 'lodash';
import { DEFAULT_BREW } from '../../../../server/brewDefaults.js';
@@ -14,15 +14,15 @@ import SplitPane from 'client/components/splitPane/splitPane.jsx';
import Editor from '../../editor/editor.jsx';
import BrewRenderer from '../../brewRenderer/brewRenderer.jsx';
import Nav from 'naturalcrit/nav/nav.jsx';
import Navbar from '../../navbar/navbar.jsx';
import NewBrewItem from '../../navbar/newbrew.navitem.jsx';
import AccountNavItem from '../../navbar/account.navitem.jsx';
import ErrorNavItem from '../../navbar/error-navitem.jsx';
import HelpNavItem from '../../navbar/help.navitem.jsx';
import VaultNavItem from '../../navbar/vault.navitem.jsx';
import PrintNavItem from '../../navbar/print.navitem.jsx';
import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx';
import Nav from 'client/homebrew/navbar/nav.jsx';
import Navbar from 'client/homebrew/navbar/navbar.jsx';
import NewBrewItem from 'client/homebrew/navbar/newbrew.navitem.jsx';
import AccountNavItem from 'client/homebrew/navbar/account.navitem.jsx';
import ErrorNavItem from 'client/homebrew/navbar/error-navitem.jsx';
import HelpNavItem from 'client/homebrew/navbar/help.navitem.jsx';
import VaultNavItem from 'client/homebrew/navbar/vault.navitem.jsx';
import PrintNavItem from 'client/homebrew/navbar/print.navitem.jsx';
import { both as RecentNavItem } from 'client/homebrew/navbar/recent.navitem.jsx';
// Page specific imports
import { Meta } from 'vitreum/headtags';
@@ -56,6 +56,10 @@ const NewPage = (props)=>{
const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew));
// const saveTimeout = useRef(null);
// const warnUnsavedTimeout = useRef(null);
const trySaveRef = useRef(trySave); // CTRL+S listener lives outside React and needs ref to use trySave with latest copy of brew
const unsavedChangesRef = useRef(unsavedChanges); // Similarly, onBeforeUnload lives outside React and needs ref to unsavedChanges
useEffect(()=>{
loadBrew();
@@ -114,6 +118,11 @@ const NewPage = (props)=>{
if(autoSaveEnabled) trySave(false, hasChange);
}, [currentBrew]);
useEffect(()=>{
trySaveRef.current = trySave;
unsavedChangesRef.current = unsavedChanges;
});
const handleSplitMove = ()=>{
editorRef.current.update();
};
@@ -141,7 +150,7 @@ const NewPage = (props)=>{
}
};
const save = async ()=>{
const trySave = async ()=>{
setIsSaving(true);
const updatedBrew = { ...currentBrew };
@@ -190,7 +199,7 @@ const NewPage = (props)=>{
// #3 - Unsaved changes exist, click to save, show SAVE NOW
if(unsavedChanges)
return <Nav.item className='save' onClick={save} color='blue' icon='fas fa-save'>save now</Nav.item>;
return <Nav.item className='save' onClick={trySave} color='blue' icon='fas fa-save'>save now</Nav.item>;
// #4 - No unsaved changes, autosave is ON, show AUTO-SAVED
if(autoSaveEnabled)

View File

@@ -3,12 +3,12 @@ const React = require('react');
const { useState, useEffect, useCallback } = React;
const { Meta } = require('vitreum/headtags');
const Nav = require('naturalcrit/nav/nav.jsx');
const Navbar = require('../../navbar/navbar.jsx');
const MetadataNav = require('../../navbar/metadata.navitem.jsx');
const PrintNavItem = require('../../navbar/print.navitem.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const Account = require('../../navbar/account.navitem.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const Navbar = require('client/homebrew/navbar/navbar.jsx');
const MetadataNav = require('client/homebrew/navbar/metadata.navitem.jsx');
const PrintNavItem = require('client/homebrew/navbar/print.navitem.jsx');
const RecentNavItem = require('client/homebrew/navbar/recent.navitem.jsx').both;
const Account = require('client/homebrew/navbar/account.navitem.jsx');
const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
const { DEFAULT_BREW_LOAD } = require('../../../../server/brewDefaults.js');

View File

@@ -4,14 +4,14 @@ const _ = require('lodash');
const ListPage = require('../basePages/listPage/listPage.jsx');
const Nav = require('naturalcrit/nav/nav.jsx');
const Navbar = require('../../navbar/navbar.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const Account = require('../../navbar/account.navitem.jsx');
const NewBrew = require('../../navbar/newbrew.navitem.jsx');
const HelpNavItem = require('../../navbar/help.navitem.jsx');
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
const VaultNavitem = require('../../navbar/vault.navitem.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const Navbar = require('client/homebrew/navbar/navbar.jsx');
const RecentNavItem = require('client/homebrew/navbar/recent.navitem.jsx').both;
const Account = require('client/homebrew/navbar/account.navitem.jsx');
const NewBrew = require('client/homebrew/navbar/newbrew.navitem.jsx');
const HelpNavItem = require('client/homebrew/navbar/help.navitem.jsx');
const ErrorNavItem = require('client/homebrew/navbar/error-navitem.jsx');
const VaultNavitem = require('client/homebrew/navbar/vault.navitem.jsx');
const UserPage = (props)=>{
props = {

View File

@@ -5,12 +5,12 @@ require('./vaultPage.less');
const React = require('react');
const { useState, useEffect, useRef } = React;
const Nav = require('naturalcrit/nav/nav.jsx');
const Navbar = require('../../navbar/navbar.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const Account = require('../../navbar/account.navitem.jsx');
const NewBrew = require('../../navbar/newbrew.navitem.jsx');
const HelpNavItem = require('../../navbar/help.navitem.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const Navbar = require('client/homebrew/navbar/navbar.jsx');
const RecentNavItem = require('client/homebrew/navbar/recent.navitem.jsx').both;
const Account = require('client/homebrew/navbar/account.navitem.jsx');
const NewBrew = require('client/homebrew/navbar/newbrew.navitem.jsx');
const HelpNavItem = require('client/homebrew/navbar/help.navitem.jsx');
const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx');
const SplitPane = require('client/components/splitPane/splitPane.jsx');
const ErrorIndex = require('../errorPage/errors/errorIndex.js');

View File

@@ -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
}

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "homebrewery",
"version": "3.19.3",
"version": "3.20.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "homebrewery",
"version": "3.19.3",
"version": "3.20.0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {

View File

@@ -1,7 +1,7 @@
{
"name": "homebrewery",
"description": "Create authentic looking D&D homebrews using only markdown",
"version": "3.19.3",
"version": "3.20.0",
"type": "module",
"engines": {
"npm": "^10.8.x",
@@ -44,7 +44,9 @@
"phb": "node --experimental-require-module scripts/phb.js",
"prod": "set NODE_ENV=production && npm run build",
"postinstall": "npm run build",
"start": "node --experimental-require-module server.js"
"start": "node --experimental-require-module server.js",
"docker:build": "docker build -t ${DOCKERID}/homebrewery:$npm_package_version .",
"docker:publish": "docker login && docker push ${DOCKERID}/homebrewery:$npm_package_version"
},
"author": "stolksdorf",
"license": "MIT",
@@ -93,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",

View File

@@ -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",

View File

@@ -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,

View File

@@ -4,7 +4,7 @@ import { model as HomebrewModel } from './homebrew.model.js';
import express from 'express';
import zlib from 'zlib';
import GoogleActions from './googleActions.js';
import Markdown from '../shared/naturalcrit/markdown.js';
import Markdown from '../shared/markdown.js';
import yaml from 'js-yaml';
import asyncHandler from 'express-async-handler';
import { nanoid } from 'nanoid';

View File

@@ -16,10 +16,10 @@ import { gfmHeadingId as MarkedGFMHeadingId, resetHeadings as MarkedGFMResetHead
import { markedEmoji as MarkedEmojis } from 'marked-emoji';
//Icon fonts included so they can appear in emoji autosuggest dropdown
import diceFont from '../../themes/fonts/iconFonts/diceFont.js';
import elderberryInn from '../../themes/fonts/iconFonts/elderberryInn.js';
import gameIcons from '../../themes/fonts/iconFonts/gameIcons.js';
import fontAwesome from '../../themes/fonts/iconFonts/fontAwesome.js';
import diceFont from '../themes/fonts/iconFonts/diceFont.js';
import elderberryInn from '../themes/fonts/iconFonts/elderberryInn.js';
import gameIcons from '../themes/fonts/iconFonts/gameIcons.js';
import fontAwesome from '../themes/fonts/iconFonts/fontAwesome.js';
const renderer = new Marked.Renderer();
const tokenizer = new Marked.Tokenizer();

View File

@@ -1,3 +0,0 @@
module.exports = function(props){
return <svg version='1.1' x='0px' y='0px' viewBox='0 0 80 100' enableBackground='new 0 0 80 80'><g><g><polygon fill='#000000' points='12.9,71.4 7.6,66.1 19.3,54.4 20.7,55.8 10.4,66.1 12.9,68.6 23.2,58.3 24.6,59.7 '/></g><g><path fill='#000000' d='M29,61.6c-1.7,0-3.4-0.7-4.6-1.9l-5.1-5.1c-2.5-2.5-2.5-6.6,0-9.2l0.7-0.7L34.3,59l-0.7,0.7 C32.4,60.9,30.8,61.6,29,61.6z M20.1,47.6c-1.1,1.7-0.9,4.1,0.6,5.6l5.1,5.1c0.8,0.8,2,1.3,3.2,1.3c0.9,0,1.7-0.2,2.4-0.7 L20.1,47.6z'/></g><g><path fill='#000000' d='M12.3,74.8c-0.8,0-1.5-0.3-2-0.8l-5.2-5.2c-0.5-0.5-0.8-1.2-0.8-2c0-0.8,0.3-1.5,0.8-2 c1.1-1.1,2.9-1.1,4,0l5.2,5.2c1.1,1.1,1.1,2.9,0,4C13.8,74.5,13.1,74.8,12.3,74.8z M7.1,65.9c-0.2,0-0.4,0.1-0.6,0.2 c-0.2,0.2-0.2,0.4-0.2,0.6s0.1,0.4,0.2,0.6l5.2,5.2c0.3,0.3,0.9,0.3,1.2,0c0.3-0.3,0.3-0.8,0-1.2l-5.2-5.2 C7.5,66,7.3,65.9,7.1,65.9z'/></g><g><polygon fill='#000000' points='31.7,58.7 30.3,57.3 70,17.6 70,9 62.4,9 23.3,49.4 21.9,48 61.6,7 72,7 72,18.4 '/></g><g><rect x='46' y='6.7' transform='matrix(0.7168 0.6973 -0.6973 0.7168 35.9716 -23.568)' fill='#000000' width='2' height='51.6'/></g><g><rect x='13' y='61' fill='#000000' width='2' height='7'/></g><g><rect x='17' y='57' fill='#000000' width='2' height='7'/></g></g><g><g><polygon fill='#000000' points='68.4,71.4 56.7,59.7 58.1,58.3 68.4,68.6 70.8,66.1 60.5,55.8 61.9,54.4 73.6,66.1 '/></g><g><path fill='#000000' d='M52.2,61.6c-1.7,0-3.4-0.7-4.6-1.9L46.9,59l14.3-14.3l0.7,0.7c2.5,2.5,2.5,6.6,0,9.2l-5.1,5.1 C55.6,60.9,53.9,61.6,52.2,61.6z M49.8,58.9c0.7,0.4,1.5,0.7,2.4,0.7c1.2,0,2.3-0.5,3.2-1.3l5.1-5.1c1.5-1.5,1.7-3.8,0.6-5.6 L49.8,58.9z'/></g><g><path fill='#000000' d='M68.9,74.8c-0.8,0-1.5-0.3-2-0.8c-1.1-1.1-1.1-2.9,0-4l5.2-5.2c1.1-1.1,2.9-1.1,4,0c0.5,0.5,0.8,1.2,0.8,2 c0,0.8-0.3,1.5-0.8,2L70.9,74C70.4,74.5,69.7,74.8,68.9,74.8z M74.2,65.9c-0.2,0-0.4,0.1-0.6,0.2l-5.2,5.2c-0.3,0.3-0.3,0.8,0,1.2 c0.3,0.3,0.9,0.3,1.2,0l5.2-5.2c0.2-0.2,0.2-0.4,0.2-0.6s-0.1-0.4-0.2-0.6C74.6,66,74.4,65.9,74.2,65.9z'/></g><g><rect x='38.6' y='52.3' transform='matrix(0.7082 0.706 -0.706 0.7082 50.8397 -16.4875)' fill='#000000' width='13.4' height='2'/></g><g><polygon fill='#000000' points='30.6,39.9 9,18.4 9,7 19.7,7 41.1,29.1 39.7,30.5 18.8,9 11,9 11,17.6 32,38.5 '/></g><g><rect x='47.8' y='43.1' transform='matrix(0.6959 0.7181 -0.7181 0.6959 48.1381 -25.5246)' fill='#000000' width='12.8' height='2'/></g><g><rect x='12' y='23.1' transform='matrix(0.6974 0.7167 -0.7167 0.6974 25.1384 -11.3825)' fill='#000000' width='28.1' height='2'/></g><g><rect x='43.8' y='46.4' transform='matrix(0.6974 0.7167 -0.7167 0.6974 48.7492 -20.5985)' fill='#000000' width='10' height='2'/></g><g><rect x='66' y='61' fill='#000000' width='2' height='7'/></g><g><rect x='62' y='57' fill='#000000' width='2' height='7'/></g></g></svg>;
};

View File

@@ -1,6 +1,6 @@
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
test('Processes the markdown within an HTML block if its just a class wrapper', function() {
const source = '<div>*Bold text*</div>';

View File

@@ -1,6 +1,6 @@
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
describe('Inline Definition Lists', ()=>{
test('No Term 1 Definition', function() {

View File

@@ -1,4 +1,4 @@
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
const dedent = require('dedent-tabs').default;
// Marked.js adds line returns after closing tags on some default tokens.

View File

@@ -1,6 +1,6 @@
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
describe('Hard Breaks', ()=>{
test('Single Break', function() {

View File

@@ -1,7 +1,7 @@
/* eslint-disable max-lines */
const dedent = require('dedent-tabs').default;
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
// Marked.js adds line returns after closing tags on some default tokens.
// This removes those line returns for comparison sake.

View File

@@ -1,6 +1,6 @@
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
describe('Non-Breaking Spaces Interactions', ()=>{
test('I am actually a single-line definition list!', function() {

View File

@@ -1,6 +1,6 @@
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
describe('Justification', ()=>{
test('Left Justify', function() {

View File

@@ -1,7 +1,7 @@
/* eslint-disable max-lines */
const dedent = require('dedent-tabs').default;
import Markdown from 'naturalcrit/markdown.js';
import Markdown from 'markdown.js';
// Marked.js adds line returns after closing tags on some default tokens.
// This removes those line returns for comparison sake.

View File

@@ -1,4 +1,4 @@
import Markdown from '../../../../shared/naturalcrit/markdown.js';
import Markdown from '../../../../shared/markdown.js';
module.exports = {
createFooterFunc : function(headerSize=1){

View File

@@ -1,6 +1,6 @@
{
"name" : "UnearthedArcana",
"renderer" : "V3",
"baseTheme" : false,
"baseTheme" : "Blank",
"baseSnippets" : false
}

View File

@@ -39,7 +39,7 @@
"UnearthedArcana": {
"name": "UnearthedArcana",
"renderer": "V3",
"baseTheme": false,
"baseTheme": "Blank",
"baseSnippets": false,
"path": "UnearthedArcana"
}