0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-09 09:22:38 +00:00

Merge branch 'master' of https://github.com/naturalcrit/homebrewery into add-remove-author-if-owner

This commit is contained in:
Víctor Losada Hernández
2025-11-15 20:06:32 +01:00
11 changed files with 2360 additions and 2291 deletions

View File

@@ -88,6 +88,63 @@ pre {
## changelog ## changelog
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery). For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
### Friday 11/14/2025 - v13.20.0
{{taskList
##### calculuschild
* [x] Cleanup and removal of redundant code (home/new/edit pages)
* [x] Compress brew payloads and when saving to speed up saving and reduce bandwidth usage
##### Gazook89
* [x] Cleanup (reorganizing files and folders)
##### G-Ambatte
* [x] Fix default save location failing on new documents
Fixes issue [#4437](https://github.com/naturalcrit/homebrewery/issues/3175)
* [x] Fix usernames with special symbols unable to open userpage
Fixes issue [#807](https://github.com/naturalcrit/homebrewery/issues/807)
* [x] Cleanup (tests, documentation, localstorage key names)
Fixes issues [#4119](https://github.com/naturalcrit/homebrewery/issues/4119), [#4443](https://github.com/naturalcrit/homebrewery/issues/4443), [#4454](https://github.com/naturalcrit/homebrewery/issues/4454)
* [x] Added indexes to Mongo schema for speed improvements on local installs
##### 5e-Cleric
* [x] Better handling for errors during brew deletion
* [x] Improve file import error messaging
* [x] Tweaked editor visuals (scrollbar, dev environment, cursor type)
Fixes issue [#2689](https://github.com/naturalcrit/homebrewery/issues/2689)
* [x] Add support for math symbols in curly blocks for CSS `calc()`
Fixes issue [#3175](https://github.com/naturalcrit/homebrewery/issues/3175)
##### abquintic
* [x] Added new {{openSans **:fas_copyright: LICENSE**}} snippets (DriveThruRPG, AELF, GNU, WotC, Mongoose, etc.) with logos
* [x] Added d100 dice icons via `:icon_name:` syntax
* [x] Fix Firefox crash from very long blockquotes
Fixes issue [#3426](https://github.com/naturalcrit/homebrewery/issues/3426)
* [x] Allow more symbol characters in CSS vars inside curly blocks
Fixes issue [#4201](https://github.com/naturalcrit/homebrewery/issues/4201)
* [x] Remove duplicate columnbreak at end of page
Fixes issue [#4401](https://github.com/naturalcrit/homebrewery/issues/4401)
* [x] Fix editor losing scroll position after page resize
Fixes issue [#2963](https://github.com/naturalcrit/homebrewery/issues/2963)
##### Emmanuel Ferdman (first contribution!)
* [x] Fixed edge case crash on admin page
}}
\page
### Wednesday 7/09/2025 - v3.19.3 ### Wednesday 7/09/2025 - v3.19.3
{{taskList {{taskList

View File

@@ -70,7 +70,7 @@ const Account = createClass({
{global.account.username} {global.account.username}
</Nav.item> </Nav.item>
<Nav.item <Nav.item
href={`/user/${encodeURI(global.account.username)}`} href={`/user/${encodeURIComponent(global.account.username)}`}
color='yellow' color='yellow'
icon='fas fa-beer' icon='fas fa-beer'
> >

View File

@@ -32,7 +32,7 @@ const MetadataNav = createClass({
return <> return <>
{this.props.brew.authors.map((author, idx, arr)=>{ {this.props.brew.authors.map((author, idx, arr)=>{
const spacer = arr.length - 1 == idx ? <></> : <span>, </span>; 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

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

View File

@@ -119,6 +119,10 @@ const EditPage = (props)=>{
if(autoSaveEnabled) trySave(false, hasChange); if(autoSaveEnabled) trySave(false, hasChange);
}, [currentBrew]); }, [currentBrew]);
useEffect(()=>{
trySave(true);
}, [saveGoogle]);
const handleSplitMove = ()=>{ const handleSplitMove = ()=>{
editorRef.current?.update(); editorRef.current?.update();
}; };
@@ -179,7 +183,6 @@ const EditPage = (props)=>{
const toggleGoogleStorage = ()=>{ const toggleGoogleStorage = ()=>{
setSaveGoogle((prev)=>!prev); setSaveGoogle((prev)=>!prev);
setError(null); setError(null);
trySave(true);
}; };
const trySave = (immediate = false, hasChanges = true)=>{ const trySave = (immediate = false, hasChanges = true)=>{

View File

@@ -96,7 +96,7 @@ const errorIndex = (props)=>{
**Brew Title:** ${escape(props.brew.brewTitle) || 'Unable to show title'} **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})`, [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'} **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})`, [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 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 ####### // ####### Admin page error #######
'52' : dedent` '52' : dedent`

View File

@@ -55,6 +55,7 @@ const HomePage =(props)=>{
const editorRef = useRef(null); const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew)); const lastSavedBrew = useRef(_.cloneDeep(props.brew));
const unsavedChangesRef = useRef(unsavedChanges);
useEffect(()=>{ useEffect(()=>{
fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme);
@@ -70,12 +71,20 @@ const HomePage =(props)=>{
}; };
document.addEventListener('keydown', handleControlKeys); document.addEventListener('keydown', handleControlKeys);
window.onbeforeunload = ()=>{
if(unsavedChangesRef.current)
return 'You have unsaved changes!';
};
return ()=>{ return ()=>{
document.removeEventListener('keydown', handleControlKeys); document.removeEventListener('keydown', handleControlKeys);
window.onbeforeunload = null;
}; };
}, []); }, []);
useEffect(()=>{
unsavedChangesRef.current = unsavedChanges;
}, [unsavedChanges]);
const save = ()=>{ const save = ()=>{
request.post('/api') request.post('/api')
.send(currentBrew) .send(currentBrew)

4
package-lock.json generated
View File

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

View File

@@ -1,7 +1,7 @@
{ {
"name": "homebrewery", "name": "homebrewery",
"description": "Create authentic looking D&D homebrews using only markdown", "description": "Create authentic looking D&D homebrews using only markdown",
"version": "3.19.3", "version": "3.20.0",
"type": "module", "type": "module",
"engines": { "engines": {
"npm": "^10.8.x", "npm": "^10.8.x",

View File

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

View File

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