0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-06-22 04:58:40 +00:00

Merge branch 'master' into preloadVars

This commit is contained in:
David Bolack
2026-05-18 21:50:32 -05:00
21 changed files with 859 additions and 1341 deletions
+2 -2
View File
@@ -11,11 +11,11 @@ import MetadataEditor from './metadataEditor/metadataEditor.jsx';
const EDITOR_THEME_KEY = 'HB_editor_theme';
import * as themesImport from '@uiw/codemirror-themes-all';
import defaultCM5Theme from '@themes/codeMirror/default.js';
import darkbrewery from '@themes/codeMirror/darkbrewery.js';
import cm5Themes from 'codemirror-5-themes';
const themes = { default: defaultCM5Theme, darkbrewery, ...themesImport };
const themes = { default: defaultCM5Theme, ...cm5Themes, darkbrewery };
const EditorThemes = Object.entries(themes)
.filter(([name, value])=>Array.isArray(value) &&
-110
View File
@@ -6,116 +6,6 @@
height : 100%;
container : editor / inline-size;
background : white;
:where(.codeEditor) {
height : calc(100% - 25px);
.cm-editor { height : 100%;
outline:none !important;
}
&.brewSnippets .cm-snippetLine {
background : #33333328;
border-top : #333399 solid 1px;
}
:where(&.brewText) .cm-pageLine {
background : #33333328;
border-top : #333399 solid 1px;
}
&.brewSnippets {
.cm-pageLine {
background : #3e4e3e1b;
border-top : #3399423b solid 1px;
color:#777;
}
}
&:where(.brewText), &.brewSnippets {
.cm-tooltip-autocomplete {
li {
display : flex;
gap : 10px;
align-items : center;
justify-content : flex-start;
.cm-completionIcon { display : none; }
.cm-tooltip-autocomplete .cm-completionLabel { translate : 0 -2px; }
}
}
.cm-pageLine[data-page-number]::after {
content:attr(data-page-number);
float:right;
color : grey;
}
.cm-columnSplit {
font-style : italic;
color : grey;
background-color : fade(#229999, 15%);
border-bottom : #229999 solid 1px;
}
.cm-define {
&:not(.term):not(.definition) {
font-weight : bold;
color : #949494;
background : #E5E5E5;
border-radius : 3px;
}
&.term { color : rgb(96, 117, 143); }
&.definition { color : rgb(97, 57, 178); }
}
.cm-block:not(.cm-comment) {
font-weight : bold;
color : purple;
}
.cm-inline-block:not(.cm-comment) {
font-weight : bold;
color : red ;
span { color : inherit }
}
.cm-injection:not(.cm-comment) {
font-weight : bold;
color : green;
span { color : inherit }
}
.cm-emoji:not(.cm-comment) {
padding-bottom : 1px;
margin-left : 2px;
font-weight : bold;
color : #360034;
outline : solid 2px #FF96FC;
outline-offset : -2px;
background : #FFC8FF;
border-radius : 6px;
}
.cm-superscript:not(.cm-comment) {
font-size : 0.9em;
font-weight : bold;
vertical-align : super;
color : goldenrod;
}
.cm-subscript:not(.cm-comment) {
font-size : 0.9em;
font-weight : bold;
vertical-align : sub;
color : rgb(123, 123, 15);
}
.cm-definitionList {
.cm-definitionTerm { color : rgb(96, 117, 143); }
.cm-definitionColon {
font-weight : bold;
color : #949494;
background : #E5E5E5;
border-radius : 3px;
}
.cm-definitionDesc { color : rgb(97, 57, 178); }
}
}
}
.brewJump {
position : absolute;
@@ -23,19 +23,25 @@ const ThemeSnippets = {
V3_Blank : V3_Blank,
};
import * as themesImport from '@uiw/codemirror-themes-all';
import defaultCM5Theme from '@themes/codeMirror/default.js';
import darkbrewery from '@themes/codeMirror/darkbrewery.js';
import cm5Themes from 'codemirror-5-themes';
const themes = { default: defaultCM5Theme, darkbrewery, ...themesImport };
const themes = { default: defaultCM5Theme, ...cm5Themes, darkbrewery };
const EditorThemes = Object.entries(themes)
.filter(([name, value]) =>
Array.isArray(value) &&
const themeNames = Object.entries(themes)
.filter(([name, value])=>Array.isArray(value) &&
!name.endsWith('Init') &&
!name.endsWith('Style')
)
.map(([name]) => name);
.map(([name])=>name);
const EditorThemes = [
'default',
...themeNames
.filter((name)=>name !== 'default')
.sort((a, b)=>a.localeCompare(b))
];
const execute = function(val, props){
if(_.isFunction(val)) return val(props);
@@ -163,7 +169,7 @@ const Snippetbar = createReactClass({
this.props.updateEditorTheme(e.target.value);
this.setState({
showThemeSelector : false,
themeSelector : false,
});
},
+7 -1
View File
@@ -17,7 +17,7 @@ const getRedditLink = (brew)=>{
return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(brew.title.toWellFormed())}&text=${encodeURIComponent(text)}`;
};
export default ({ brew })=>(
export default ({ brew, currentPage })=>(
<Nav.dropdown>
<Nav.item color='teal' icon='fas fa-share-alt'>
share
@@ -28,6 +28,12 @@ export default ({ brew })=>(
<Nav.item color='blue' onClick={()=>{navigator.clipboard.writeText(`${global.config.baseUrl}/share/${getShareId(brew)}`);}}>
copy url
</Nav.item>
{currentPage > 1 &&
<Nav.item
color='blue'
onClick={()=>{navigator.clipboard.writeText(`${global.config.baseUrl}/share/${getShareId(brew)}#p${currentPage}`);}}>
copy url (page {currentPage})
</Nav.item>}
<Nav.item color='blue' href={getRedditLink(brew)} newTab rel='noopener noreferrer'>
post to reddit
</Nav.item>
+9 -11
View File
@@ -90,7 +90,7 @@ const EditPage = (props)=>{
const handleControlKeys = (e)=>{
if(!(e.ctrlKey || e.metaKey)) return;
if(e.keyCode === 83) trySaveRef.current(true);
if(e.keyCode === 83) trySaveRef.current(true, true, saveGoogle);
if(e.keyCode === 80) printCurrentBrew();
if([83, 80].includes(e.keyCode)) {
e.stopPropagation();
@@ -118,13 +118,9 @@ const EditPage = (props)=>{
const hasChange = !_.isEqual(currentBrew, lastSavedBrew.current);
setUnsavedChanges(hasChange);
if(autoSaveEnabled) trySave(false, hasChange);
if(autoSaveEnabled) trySave(false, hasChange, saveGoogle);
}, [currentBrew]);
useEffect(()=>{
trySave(true);
}, [saveGoogle]);
const handleSplitMove = ()=>{
editorRef.current?.update();
};
@@ -183,11 +179,13 @@ const EditPage = (props)=>{
};
const toggleGoogleStorage = ()=>{
const newSaveGoogle = !saveGoogle;
setSaveGoogle((prev)=>!prev);
setError(null);
trySave(true, true, newSaveGoogle);
};
const trySave = (immediate = false, hasChanges = true)=>{
const trySave = (immediate = false, hasChanges = true, saveToGoogle = false)=>{
clearTimeout(saveTimeout.current);
if(isSaving) return;
if(!hasChanges && !immediate) return;
@@ -196,7 +194,7 @@ const EditPage = (props)=>{
saveTimeout.current = setTimeout(async ()=>{
setIsSaving(true);
setError(null);
await save(currentBrew, saveGoogle)
await save(currentBrew, saveToGoogle)
.catch((err)=>{
setError(err);
});
@@ -216,7 +214,7 @@ const EditPage = (props)=>{
const brewToSave = {
...brew,
text : brew.text.normalize('NFC'),
pageCount : ((brew.renderer === 'legacy' ? brew.text.match(/\\page/g) : brew.text.match(/^\\page$/gm)) || []).length + 1,
pageCount : ((brew.renderer === 'legacy' ? brew.text.match(/\\page/g) : brew.text.match(/^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/gm)) || []).length + 1,
patches : stringifyPatches(makePatches(encodeURI(lastSavedBrew.current.text.normalize('NFC')), encodeURI(brew.text.normalize('NFC')))),
hash : await md5(lastSavedBrew.current.text.normalize('NFC')),
textBin : undefined,
@@ -314,7 +312,7 @@ const EditPage = (props)=>{
// #3 - Unsaved changes exist, click to save, show SAVE NOW
if(unsavedChanges)
return <Nav.item className='save' onClick={()=>trySave(true)} color='blue' icon='fas fa-save'>save now</Nav.item>;
return <Nav.item className='save' onClick={()=>trySave(true, true, saveGoogle)} color='blue' icon='fas fa-save'>save now</Nav.item>;
// #4 - No unsaved changes, autosave is ON, show AUTO-SAVED
if(autoSaveEnabled)
@@ -365,7 +363,7 @@ const EditPage = (props)=>{
<PrintNavItem />
<HelpNavItem />
<VaultNavItem />
<ShareNavItem brew={currentBrew} />
<ShareNavItem brew={currentBrew} currentPage={currentBrewRendererPageNum} />
<RecentNavItem brew={currentBrew} storageKey='edit' />
<AccountNavItem/>
</Nav.section>
+1 -1
View File
@@ -156,7 +156,7 @@ const NewPage = (props)=>{
const updatedBrew = { ...currentBrew };
splitTextStyleAndMetadata(updatedBrew);
const pageRegex = updatedBrew.renderer === 'legacy' ? /\\page/g : /^\\page$/gm;
const pageRegex = updatedBrew.renderer === 'legacy' ? /\\page/g : /^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/gm;
updatedBrew.pageCount = (updatedBrew.text.match(pageRegex) || []).length + 1;
const res = await request
@@ -92,6 +92,19 @@ const SharePage = (props)=>{
<Nav.item color='blue' icon='fas fa-clone' href={`/new/${processShareId()}`}>
clone to new
</Nav.item>
<Nav.item
color='blue'
icon='fas fa-link'
onClick={()=>{navigator.clipboard.writeText(`${global.config.baseUrl}/share/${processShareId()}`);}}>
copy url
</Nav.item>
{currentBrewRendererPageNum > 1 &&
<Nav.item
color='blue'
icon='fas fa-hashtag'
onClick={()=>{navigator.clipboard.writeText(`${global.config.baseUrl}/share/${processShareId()}#p${currentBrewRendererPageNum}`);}}>
copy url (page {currentBrewRendererPageNum})
</Nav.item>}
</Nav.dropdown>
</>
)}