From e842599b2229077ec9afebf47c54c0a4a3102194 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 24 May 2025 22:35:03 -0500 Subject: [PATCH 01/28] Add missing punction and sentence structure characters to mustache style assignment regex --- client/homebrew/editor/editor.jsx | 2 +- shared/naturalcrit/markdown.js | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index cf9a17303..7faa22f16 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -12,7 +12,7 @@ const MetadataEditor = require('./metadataEditor/metadataEditor.jsx'); const EDITOR_THEME_KEY = 'HOMEBREWERY-EDITOR-THEME'; -const PAGEBREAK_REGEX_V3 = /^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/m; +const PAGEBREAK_REGEX_V3 = /^(?=\\page(?:break)?(?: *{[^\n]*})?$)/m; const SNIPPETBREAK_REGEX_V3 = /^\\snippet\ .*$/; const SNIPPETBAR_HEIGHT = 25; const DEFAULT_STYLE_TEXT = dedent` diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index ac6988734..42bc5b054 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -185,7 +185,7 @@ const mustacheSpans = { start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token - const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%=?. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; + const inlineRegex = /{{(?=((?:[:=](?:"'['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\=]*'"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; const match = completeSpan.exec(src); if(match) { //Find closing delimiter @@ -242,7 +242,7 @@ const mustacheDivs = { start(src) { return src.match(/\n *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { const completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token - const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; + const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%. ]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; const match = completeBlock.exec(src); if(match) { //Find closing delimiter @@ -297,7 +297,7 @@ const mustacheInjectInline = { level : 'inline', start(src) { return src.match(/ *{[^{\n]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1]; @@ -343,7 +343,7 @@ const mustacheInjectBlock = { level : 'block', start(src) { return src.match(/\n *{[^{\n]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/ym; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.& ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/ym; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1]; @@ -735,6 +735,16 @@ const voidTags = new Set([ 'input', 'keygen', 'link', 'meta', 'param', 'source' ]); +const notInside = (string, stringMatch1, stringMatch2)=> { + const pos1 = string.indexOf(stringMatch1); + const pos2 = string.indexOf(stringMatch2); + + if((pos1 > 0) && (pos2 > 0) && (pos2 > pos1)) { + return true; + } + return false; +}; + const processStyleTags = (string)=>{ //split tags up. quotes can only occur right after : or =. //TODO: can we simplify to just split on commas? @@ -742,7 +752,7 @@ const processStyleTags = (string)=>{ const id = _.remove(tags, (tag)=>tag.startsWith('#')).map((tag)=>tag.slice(1))[0] || null; const classes = _.remove(tags, (tag)=>(!tag.includes(':')) && (!tag.includes('='))).join(' ') || null; - const attributes = _.remove(tags, (tag)=>(tag.includes('='))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"')) + const attributes = _.remove(tags, (tag)=>(notInside(tag, '=', ':'))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"')) ?.filter((attr)=>!attr.startsWith('class="') && !attr.startsWith('style="') && !attr.startsWith('id="')) .reduce((obj, attr)=>{ const index = attr.indexOf('='); From 50d2a0d3a2a842bede5f22feddad7cac1d113485 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 26 May 2025 23:13:21 -0500 Subject: [PATCH 02/28] FIx regression --- shared/naturalcrit/markdown.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index 42bc5b054..ff61e9793 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -185,9 +185,10 @@ const mustacheSpans = { start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token - const inlineRegex = /{{(?=((?:[:=](?:"'['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\=]*'"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; + const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\=]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; const match = completeSpan.exec(src); if(match) { + console.log('MustacheSpans'); //Find closing delimiter let blockCount = 0; let tags = {}; @@ -195,6 +196,7 @@ const mustacheSpans = { let endToken = 0; let delim; while (delim = inlineRegex.exec(match[0])) { + console.log(delim); if(_.isEmpty(tags)) { tags = processStyleTags(delim[0].substring(2)); endTags = delim[0].length; @@ -245,6 +247,7 @@ const mustacheDivs = { const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%. ]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; const match = completeBlock.exec(src); if(match) { + console.log('Mustache Divs'); //Find closing delimiter let blockCount = 0; let tags = {}; @@ -300,6 +303,7 @@ const mustacheInjectInline = { const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; const match = inlineRegex.exec(src); if(match) { + console.log('InlineInject'); const lastToken = tokens[tokens.length - 1]; if(!lastToken || lastToken.type == 'mustacheInjectInline') return false; @@ -739,7 +743,8 @@ const notInside = (string, stringMatch1, stringMatch2)=> { const pos1 = string.indexOf(stringMatch1); const pos2 = string.indexOf(stringMatch2); - if((pos1 > 0) && (pos2 > 0) && (pos2 > pos1)) { + if(((pos1 > 0) && (pos2 == -1)) || + ((pos1 > 0) && (pos2 > 0) && (pos2 > pos1))) { return true; } return false; From 16d7b11b8d03037fbc2db3c4f6ffcc7d62848242 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 26 Jul 2025 18:44:59 +1200 Subject: [PATCH 03/28] Add request-middleware test file --- .../homebrew/utils/request-middleware.spec.js | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 client/homebrew/utils/request-middleware.spec.js diff --git a/client/homebrew/utils/request-middleware.spec.js b/client/homebrew/utils/request-middleware.spec.js new file mode 100644 index 000000000..d7c198394 --- /dev/null +++ b/client/homebrew/utils/request-middleware.spec.js @@ -0,0 +1,74 @@ +import requestMiddleware from './request-middleware'; + +jest.mock('superagent'); +import request from 'superagent'; + +describe('request-middleware', ()=>{ + let version; + + let setFn; + let testFn; + + beforeEach(()=>{ + jest.resetAllMocks(); + version = global.version; + + global.version = '999'; + + setFn = jest.fn(); + testFn = jest.fn(()=>{ return { set: setFn }; }); + }); + + afterEach(()=>{ + global.version = version; + }); + + it('should add header to get', ()=>{ + // Ensure tests functions have been reset + expect(testFn).not.toHaveBeenCalled(); + expect(setFn).not.toHaveBeenCalled(); + + request.get = testFn; + + requestMiddleware.get('path'); + + expect(testFn).toHaveBeenCalledWith('path'); + expect(setFn).toHaveBeenCalledWith('Homebrewery-Version', '999'); + }); + + it('should add header to put', ()=>{ + expect(testFn).not.toHaveBeenCalled(); + expect(setFn).not.toHaveBeenCalled(); + + request.put = testFn; + + requestMiddleware.put('path'); + + expect(testFn).toHaveBeenCalledWith('path'); + expect(setFn).toHaveBeenCalledWith('Homebrewery-Version', '999'); + }); + + it('should add header to post', ()=>{ + expect(testFn).not.toHaveBeenCalled(); + expect(setFn).not.toHaveBeenCalled(); + + request.post = testFn; + + requestMiddleware.post('path'); + + expect(testFn).toHaveBeenCalledWith('path'); + expect(setFn).toHaveBeenCalledWith('Homebrewery-Version', '999'); + }); + + it('should add header to delete', ()=>{ + expect(testFn).not.toHaveBeenCalled(); + expect(setFn).not.toHaveBeenCalled(); + + request.delete = testFn; + + requestMiddleware.delete('path'); + + expect(testFn).toHaveBeenCalledWith('path'); + expect(setFn).toHaveBeenCalledWith('Homebrewery-Version', '999'); + }); +}); From 719edd82c5d2b3459f7097621e6fb79db481c15b Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Tue, 29 Jul 2025 16:35:25 -0400 Subject: [PATCH 04/28] Moving splitPane over to the components folder Just to reduce the number of changes needed to review on the UI overhaul #4122 PR --- .../naturalcrit => client/components}/splitPane/splitPane.jsx | 0 .../naturalcrit => client/components}/splitPane/splitPane.less | 0 client/homebrew/pages/editPage/editPage.jsx | 2 +- client/homebrew/pages/homePage/homePage.jsx | 2 +- client/homebrew/pages/newPage/newPage.jsx | 2 +- client/homebrew/pages/vaultPage/vaultPage.jsx | 2 +- 6 files changed, 4 insertions(+), 4 deletions(-) rename {shared/naturalcrit => client/components}/splitPane/splitPane.jsx (100%) rename {shared/naturalcrit => client/components}/splitPane/splitPane.less (100%) diff --git a/shared/naturalcrit/splitPane/splitPane.jsx b/client/components/splitPane/splitPane.jsx similarity index 100% rename from shared/naturalcrit/splitPane/splitPane.jsx rename to client/components/splitPane/splitPane.jsx diff --git a/shared/naturalcrit/splitPane/splitPane.less b/client/components/splitPane/splitPane.less similarity index 100% rename from shared/naturalcrit/splitPane/splitPane.less rename to client/components/splitPane/splitPane.less diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 29dad9de0..d1f0ed21c 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -21,7 +21,7 @@ const Account = require('../../navbar/account.navitem.jsx'); const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; const VaultNavItem = require('../../navbar/vault.navitem.jsx'); -const SplitPane = require('naturalcrit/splitPane/splitPane.jsx'); +const SplitPane = require('client/components/splitPane/splitPane.jsx'); const Editor = require('../../editor/editor.jsx'); const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx'); diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index d03e30c91..eac0216fd 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -15,7 +15,7 @@ const AccountNavItem = require('../../navbar/account.navitem.jsx'); const ErrorNavItem = require('../../navbar/error-navitem.jsx'); const { fetchThemeBundle } = require('../../../../shared/helpers.js'); -const SplitPane = require('naturalcrit/splitPane/splitPane.jsx'); +const SplitPane = require('client/components/splitPane/splitPane.jsx'); const Editor = require('../../editor/editor.jsx'); const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx'); diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 64fac86c0..ab7c22541 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -14,7 +14,7 @@ const ErrorNavItem = require('../../navbar/error-navitem.jsx'); const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; const HelpNavItem = require('../../navbar/help.navitem.jsx'); -const SplitPane = require('naturalcrit/splitPane/splitPane.jsx'); +const SplitPane = require('client/components/splitPane/splitPane.jsx'); const Editor = require('../../editor/editor.jsx'); const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx'); diff --git a/client/homebrew/pages/vaultPage/vaultPage.jsx b/client/homebrew/pages/vaultPage/vaultPage.jsx index f979aa4f7..e098bb1a2 100644 --- a/client/homebrew/pages/vaultPage/vaultPage.jsx +++ b/client/homebrew/pages/vaultPage/vaultPage.jsx @@ -12,7 +12,7 @@ const Account = require('../../navbar/account.navitem.jsx'); const NewBrew = require('../../navbar/newbrew.navitem.jsx'); const HelpNavItem = require('../../navbar/help.navitem.jsx'); const BrewItem = require('../basePages/listPage/brewItem/brewItem.jsx'); -const SplitPane = require('../../../../shared/naturalcrit/splitPane/splitPane.jsx'); +const SplitPane = require('client/components/splitPane/splitPane.jsx'); const ErrorIndex = require('../errorPage/errors/errorIndex.js'); import request from '../../utils/request-middleware.js'; From a8dab28fcf376b77ca0382e2c174e149e8aa6ed6 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 30 Jul 2025 12:00:50 +1200 Subject: [PATCH 05/28] Fix Account page FA icon font weights --- client/homebrew/pages/basePages/uiPage/uiPage.less | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/pages/basePages/uiPage/uiPage.less b/client/homebrew/pages/basePages/uiPage/uiPage.less index 39ccf1d74..f00b484c0 100644 --- a/client/homebrew/pages/basePages/uiPage/uiPage.less +++ b/client/homebrew/pages/basePages/uiPage/uiPage.less @@ -29,6 +29,7 @@ &::before { margin-right : 5px; font-family : 'Font Awesome 6 Free'; + font-weight : 900; content : '\f00c'; } } From 1eb226ea13fe31f80e1e11a5eed44f6fd4bb0727 Mon Sep 17 00:00:00 2001 From: Emmanuel Ferdman Date: Sun, 10 Aug 2025 23:26:41 -0700 Subject: [PATCH 06/28] Handle mongo count qurey error by returning default value Signed-off-by: Emmanuel Ferdman --- server/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/app.js b/server/app.js index 869fe6555..afba0997b 100644 --- a/server/app.js +++ b/server/app.js @@ -487,8 +487,8 @@ app.get('/account', asyncHandler(async (req, res, next)=>{ const query = { authors: req.account.username, googleId: { $exists: false } }; const mongoCount = await HomebrewModel.countDocuments(query) .catch((err)=>{ - mongoCount = 0; console.log(err); + return 0; }); data.accountDetails = { From aebc49c2d4c74fc761f966f73d4100fff91fa929 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:52:36 +0000 Subject: [PATCH 07/28] Bump the dev-dependencies group across 1 directory with 3 updates Bumps the dev-dependencies group with 3 updates in the / directory: [eslint](https://github.com/eslint/eslint), [stylelint](https://github.com/stylelint/stylelint) and [stylelint-config-recess-order](https://github.com/stormwarning/stylelint-config-recess-order). Updates `eslint` from 9.31.0 to 9.33.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v9.31.0...v9.33.0) Updates `stylelint` from 16.22.0 to 16.23.1 - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md) - [Commits](https://github.com/stylelint/stylelint/compare/16.22.0...16.23.1) Updates `stylelint-config-recess-order` from 7.1.0 to 7.2.0 - [Release notes](https://github.com/stormwarning/stylelint-config-recess-order/releases) - [Changelog](https://github.com/stormwarning/stylelint-config-recess-order/blob/main/CHANGELOG.md) - [Commits](https://github.com/stormwarning/stylelint-config-recess-order/compare/v7.1.0...v7.2.0) --- updated-dependencies: - dependency-name: eslint dependency-version: 9.33.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: stylelint dependency-version: 16.23.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: stylelint-config-recess-order dependency-version: 7.2.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] --- package-lock.json | 154 ++++++++++++++++++---------------------------- package.json | 6 +- 2 files changed, 64 insertions(+), 96 deletions(-) diff --git a/package-lock.json b/package-lock.json index eb82b0f40..20e573a6b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,7 +65,7 @@ "devDependencies": { "@stylistic/stylelint-plugin": "^3.1.3", "babel-plugin-transform-import-meta": "^2.3.3", - "eslint": "^9.31.0", + "eslint": "^9.33.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-react": "^7.37.5", "globals": "^16.3.0", @@ -73,8 +73,8 @@ "jest-expect-message": "^1.1.3", "jsdom-global": "^3.0.2", "postcss-less": "^6.0.0", - "stylelint": "^16.22.0", - "stylelint-config-recess-order": "^7.1.0", + "stylelint": "^16.23.1", + "stylelint-config-recess-order": "^7.2.0", "stylelint-config-recommended": "^16.0.0", "supertest": "^7.1.4" }, @@ -2021,18 +2021,19 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", - "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", - "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2080,9 +2081,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.31.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.31.0.tgz", - "integrity": "sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==", + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", + "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", "dev": true, "license": "MIT", "engines": { @@ -2102,13 +2103,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", - "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.14.0", + "@eslint/core": "^0.15.2", "levn": "^0.4.1" }, "engines": { @@ -2832,37 +2833,11 @@ } }, "node_modules/@keyv/serialize": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.3.tgz", - "integrity": "sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.0.tgz", + "integrity": "sha512-RlDgexML7Z63Q8BSaqhXdCYNBy/JQnqYIwxofUrNLGCblOMHp+xux2Q8nLMLlPpgHQPoU0Do8Z6btCpRBEqZ8g==", "dev": true, - "dependencies": { - "buffer": "^6.0.3" - } - }, - "node_modules/@keyv/serialize/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } + "license": "MIT" }, "node_modules/@mongodb-js/saslprep": { "version": "1.3.0", @@ -4675,22 +4650,24 @@ } }, "node_modules/cacheable": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.10.1.tgz", - "integrity": "sha512-Fa2BZY0CS9F0PFc/6aVA6tgpOdw+hmv9dkZOlHXII5v5Hw+meJBIWDcPrG9q/dXxGcNbym5t77fzmawrBQfTmQ==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.10.3.tgz", + "integrity": "sha512-M6p10iJ/VT0wT7TLIGUnm958oVrU2cUK8pQAVU21Zu7h8rbk/PeRtRWrvHJBql97Bhzk3g1N6+2VKC+Rjxna9Q==", "dev": true, + "license": "MIT", "dependencies": { "hookified": "^1.10.0", - "keyv": "^5.3.4" + "keyv": "^5.4.0" } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.4.tgz", - "integrity": "sha512-ypEvQvInNpUe+u+w8BIcPkQvEqXquyyibWE/1NB5T2BTzIpS5cGEV1LZskDzPSTvNAaT4+5FutvzlvnkxOSKlw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.0.tgz", + "integrity": "sha512-QG7qR2tijh1ftOvClut4YKKg1iW6cx3GZsKoGyJPxHkGWK9oJhG9P3j5deP0QQOGDowBMVQFaP+Vm4NpGYvmIQ==", "dev": true, + "license": "MIT", "dependencies": { - "@keyv/serialize": "^1.0.3" + "@keyv/serialize": "^1.1.0" } }, "node_modules/cached-path-relative": { @@ -6080,20 +6057,20 @@ } }, "node_modules/eslint": { - "version": "9.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.31.0.tgz", - "integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==", + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", + "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", - "@eslint/core": "^0.15.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.31.0", - "@eslint/plugin-kit": "^0.3.1", + "@eslint/js": "9.33.0", + "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -6258,19 +6235,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@eslint/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", - "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -7648,10 +7612,11 @@ } }, "node_modules/hookified": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.10.0.tgz", - "integrity": "sha512-dJw0492Iddsj56U1JsSTm9E/0B/29a1AuoSLRAte8vQg/kaTGF3IgjEWT8c8yG4cC10+HisE1x5QAwR0Xwc+DA==", - "dev": true + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.11.0.tgz", + "integrity": "sha512-aDdIN3GyU5I6wextPplYdfmWCo+aLmjjVbntmX6HLD5RCi/xKsivYEBhnRD+d9224zFf008ZpLMPlWF0ZodYZw==", + "dev": true, + "license": "MIT" }, "node_modules/html-encoding-sniffer": { "version": "4.0.0", @@ -13306,9 +13271,9 @@ "license": "ISC" }, "node_modules/stylelint": { - "version": "16.22.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.22.0.tgz", - "integrity": "sha512-SVEMTdjKNV4ollUrIY9ordZ36zHv2/PHzPjfPMau370MlL2VYXeLgSNMMiEbLGRO8RmD2R8/BVUeF2DfnfkC0w==", + "version": "16.23.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.23.1.tgz", + "integrity": "sha512-dNvDTsKV1U2YtiUDfe9d2gp902veFeo3ecCWdGlmLm2WFrAV0+L5LoOj/qHSBABQwMsZPJwfC4bf39mQm1S5zw==", "dev": true, "funding": [ { @@ -13335,7 +13300,7 @@ "debug": "^4.4.1", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^10.1.1", + "file-entry-cache": "^10.1.3", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -13369,10 +13334,11 @@ } }, "node_modules/stylelint-config-recess-order": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recess-order/-/stylelint-config-recess-order-7.1.0.tgz", - "integrity": "sha512-rFc4Z6SCGgEohr1khsmAZ83X56Tdi2dHY/GB7VT3qJkpKU1V2w+mYlK+b7Za5gpsxEng3jnb4FzWyIl/KTH0AQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recess-order/-/stylelint-config-recess-order-7.2.0.tgz", + "integrity": "sha512-3Y97dhsWkUHFKRLGNLF6LE5JuNB2EVAZKYJ41wBRK4gplYdk7eHhSIwE24hanu0AoNmv5534Djip70pE+y5qkA==", "dev": true, + "license": "ISC", "peerDependencies": { "stylelint": ">=16.18", "stylelint-order": ">=7" @@ -13472,21 +13438,23 @@ "license": "MIT" }, "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.1.tgz", - "integrity": "sha512-zcmsHjg2B2zjuBgjdnB+9q0+cWcgWfykIcsDkWDB4GTPtl1eXUA+gTI6sO0u01AqK3cliHryTU55/b2Ow1hfZg==", + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.1.3.tgz", + "integrity": "sha512-D+w75Ub8T55yor7fPgN06rkCAUbAYw2vpxJmmjv/GDAcvCnv9g7IvHhIZoxzRZThrXPFI2maeY24pPbtyYU7Lg==", "dev": true, + "license": "MIT", "dependencies": { - "flat-cache": "^6.1.10" + "flat-cache": "^6.1.12" } }, "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.11.tgz", - "integrity": "sha512-zfOAns94mp7bHG/vCn9Ru2eDCmIxVQ5dELUHKjHfDEOJmHNzE+uGa6208kfkgmtym4a0FFjEuFksCXFacbVhSg==", + "version": "6.1.12", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.12.tgz", + "integrity": "sha512-U+HqqpZPPXP5d24bWuRzjGqVqUcw64k4nZAbruniDwdRg0H10tvN7H6ku1tjhA4rg5B9GS3siEvwO2qjJJ6f8Q==", "dev": true, + "license": "MIT", "dependencies": { - "cacheable": "^1.10.1", + "cacheable": "^1.10.3", "flatted": "^3.3.3", "hookified": "^1.10.0" } diff --git a/package.json b/package.json index e32f5a05c..fd905d209 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "devDependencies": { "@stylistic/stylelint-plugin": "^3.1.3", "babel-plugin-transform-import-meta": "^2.3.3", - "eslint": "^9.31.0", + "eslint": "^9.33.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-react": "^7.37.5", "globals": "^16.3.0", @@ -146,8 +146,8 @@ "jest-expect-message": "^1.1.3", "jsdom-global": "^3.0.2", "postcss-less": "^6.0.0", - "stylelint": "^16.22.0", - "stylelint-config-recess-order": "^7.1.0", + "stylelint": "^16.23.1", + "stylelint-config-recess-order": "^7.2.0", "stylelint-config-recommended": "^16.0.0", "supertest": "^7.1.4" } From cca9ebefdb32d175b39e34e4cb2fa94b3df820d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 20 Aug 2025 23:23:13 +0200 Subject: [PATCH 08/28] better error handling for file import --- client/homebrew/navbar/newbrew.navitem.jsx | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/client/homebrew/navbar/newbrew.navitem.jsx b/client/homebrew/navbar/newbrew.navitem.jsx index 30d53c675..23b7c9e5e 100644 --- a/client/homebrew/navbar/newbrew.navitem.jsx +++ b/client/homebrew/navbar/newbrew.navitem.jsx @@ -5,7 +5,7 @@ const { splitTextStyleAndMetadata } = require('../../../shared/helpers.js'); // const BREWKEY = 'homebrewery-new'; const STYLEKEY = 'homebrewery-new-style'; -const METAKEY = 'homebrewery-new-meta'; +const METAKEY = 'homebrewery-new-meta'; const NewBrew = ()=>{ const handleFileChange = (e)=>{ @@ -22,10 +22,26 @@ const NewBrew = ()=>{ splitTextStyleAndMetadata(newBrew); // Modify newBrew directly localStorage.setItem(BREWKEY, newBrew.text); localStorage.setItem(STYLEKEY, newBrew.style); - localStorage.setItem(METAKEY, JSON.stringify(_.pick(newBrew, ['title', 'description', 'tags', 'systems', 'renderer', 'theme', 'lang']))); + localStorage.setItem( + METAKEY, + JSON.stringify( + _.pick(newBrew, ['title', 'description', 'tags', 'systems', 'renderer', 'theme', 'lang']) + ) + ); window.location.href = '/new'; } else { - alert('This file is invalid, please, enter a valid file'); + const type = file.name.split('.').pop().toLowercase(); + if(type === 'txt') { + alert( + `This file type is correct, but it is not from the homebrewery or has been tampered with, + please try with a correct file or report this as an issue if you think it is a mistake.` + ); + } else if(!type) { + alert('This file is invalid, please, enter a valid file'); + console.log(file); + } else { + alert(`This is a .${type} file, only '.txt' files are allowed`); + } } }; reader.readAsText(file); From 320f1e120f638e242b30adfb67b314a402c05244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 21 Aug 2025 12:23:41 +0200 Subject: [PATCH 09/28] reordering --- client/homebrew/navbar/newbrew.navitem.jsx | 73 +++++++++++----------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/client/homebrew/navbar/newbrew.navitem.jsx b/client/homebrew/navbar/newbrew.navitem.jsx index 23b7c9e5e..c20ae6b6c 100644 --- a/client/homebrew/navbar/newbrew.navitem.jsx +++ b/client/homebrew/navbar/newbrew.navitem.jsx @@ -10,44 +10,45 @@ const METAKEY = 'homebrewery-new-meta'; const NewBrew = ()=>{ const handleFileChange = (e)=>{ const file = e.target.files[0]; - if(file) { - const reader = new FileReader(); - reader.onload = (e)=>{ - const fileContent = e.target.result; - const newBrew = { - text : fileContent, - style : '' - }; - if(fileContent.startsWith('```metadata')) { - splitTextStyleAndMetadata(newBrew); // Modify newBrew directly - localStorage.setItem(BREWKEY, newBrew.text); - localStorage.setItem(STYLEKEY, newBrew.style); - localStorage.setItem( - METAKEY, - JSON.stringify( - _.pick(newBrew, ['title', 'description', 'tags', 'systems', 'renderer', 'theme', 'lang']) - ) - ); - window.location.href = '/new'; - } else { - const type = file.name.split('.').pop().toLowercase(); - if(type === 'txt') { - alert( - `This file type is correct, but it is not from the homebrewery or has been tampered with, - please try with a correct file or report this as an issue if you think it is a mistake.` - ); - } else if(!type) { - alert('This file is invalid, please, enter a valid file'); - console.log(file); - } else { - alert(`This is a .${type} file, only '.txt' files are allowed`); - } - } - }; - reader.readAsText(file); - } + if(!file) return; + + const currentNew = localStorage.getItem(BREWKEY); + if(currentNew && !confirm( + `You have some text in the new brew space, if you load a file that text will be lost, are you sure you want to load the file?` + )) return; + + const reader = new FileReader(); + reader.onload = (e)=>{ + const fileContent = e.target.result; + const newBrew = { text: fileContent, style: '' }; + + if(fileContent.startsWith('```metadata')) { + splitTextStyleAndMetadata(newBrew); + localStorage.setItem(BREWKEY, newBrew.text); + localStorage.setItem(STYLEKEY, newBrew.style); + localStorage.setItem(METAKEY, JSON.stringify( + _.pick(newBrew, ['title', 'description', 'tags', 'systems', 'renderer', 'theme', 'lang']) + )); + window.location.href = '/new'; + return; + } + + const type = file.name.split('.').pop().toLowerCase(); + if(type === 'txt') { + alert( + `This file type is correct, but it is not from the homebrewery or has been tampered with, please try with a correct file or report this as an issue if you think it is a mistake.` + ); + } else if(!type) { + alert('This file is invalid, please, enter a valid file'); + console.log(file); + } else { + alert(`This is a .${type} file, only .txt files are allowed`); + } + }; + reader.readAsText(file); }; + return ( Date: Thu, 21 Aug 2025 13:58:23 +0000 Subject: [PATCH 10/28] Bump @stylistic/stylelint-plugin from 3.1.3 to 4.0.0 Bumps [@stylistic/stylelint-plugin](https://github.com/stylelint-stylistic/stylelint-stylistic) from 3.1.3 to 4.0.0. - [Release notes](https://github.com/stylelint-stylistic/stylelint-stylistic/releases) - [Changelog](https://github.com/stylelint-stylistic/stylelint-stylistic/blob/main/CHANGELOG.md) - [Commits](https://github.com/stylelint-stylistic/stylelint-stylistic/compare/v3.1.3...v4.0.0) --- updated-dependencies: - dependency-name: "@stylistic/stylelint-plugin" dependency-version: 4.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 77 +++++++++++++---------------------------------- package.json | 2 +- 2 files changed, 22 insertions(+), 57 deletions(-) diff --git a/package-lock.json b/package-lock.json index 20e573a6b..705f327b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,7 @@ "written-number": "^0.11.1" }, "devDependencies": { - "@stylistic/stylelint-plugin": "^3.1.3", + "@stylistic/stylelint-plugin": "^4.0.0", "babel-plugin-transform-import-meta": "^2.3.3", "eslint": "^9.33.0", "eslint-plugin-jest": "^29.0.1", @@ -1884,9 +1884,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-3.0.1.tgz", - "integrity": "sha512-HNo8gGD02kHmcbX6PvCoUuOQvn4szyB9ca63vZHKX5A81QytgDG4oxG4IaEfHTlEZSZ6MjPEMWIVU+zF2PZcgw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", + "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", "dev": true, "funding": [ { @@ -1898,12 +1898,13 @@ "url": "https://opencollective.com/csstools" } ], + "license": "MIT", "engines": { "node": ">=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.1", - "@csstools/css-tokenizer": "^3.0.1" + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" } }, "node_modules/@dmsnell/diff-match-patch": { @@ -2980,17 +2981,17 @@ } }, "node_modules/@stylistic/stylelint-plugin": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-3.1.3.tgz", - "integrity": "sha512-85fsmzgsIVmyG3/GFrjuYj6Cz8rAM7IZiPiXCMiSMfoDOC1lOrzrXPDk24WqviAghnPqGpx8b0caK2PuewWGFg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@stylistic/stylelint-plugin/-/stylelint-plugin-4.0.0.tgz", + "integrity": "sha512-CFwt3K4Y/7bygNCLCQ8Sy4Hzgbhxq3BsNW0FIuYxl17HD3ywptm54ocyeiLVRrk5jtz1Zwks7Xr9eiZt8SWHAw==", "dev": true, + "license": "MIT", "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.1", - "@csstools/css-tokenizer": "^3.0.1", - "@csstools/media-query-list-parser": "^3.0.1", - "is-plain-object": "^5.0.0", - "postcss": "^8.4.41", - "postcss-selector-parser": "^6.1.2", + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3", + "postcss": "^8.5.6", + "postcss-selector-parser": "^7.1.0", "postcss-value-parser": "^4.2.0", "style-search": "^0.1.0" }, @@ -2998,7 +2999,7 @@ "node": "^18.12 || >=20.9" }, "peerDependencies": { - "stylelint": "^16.8.0" + "stylelint": "^16.22.0" } }, "node_modules/@tybys/wasm-util": { @@ -11538,10 +11539,11 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -13384,29 +13386,6 @@ "stylelint": "^16.18.0" } }, - "node_modules/stylelint/node_modules/@csstools/media-query-list-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-4.0.3.tgz", - "integrity": "sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" - } - }, "node_modules/stylelint/node_modules/@csstools/selector-specificity": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", @@ -13468,20 +13447,6 @@ "node": ">= 4" } }, - "node_modules/stylelint/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/stylelint/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", diff --git a/package.json b/package.json index fd905d209..5c7ea1032 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,7 @@ "written-number": "^0.11.1" }, "devDependencies": { - "@stylistic/stylelint-plugin": "^3.1.3", + "@stylistic/stylelint-plugin": "^4.0.0", "babel-plugin-transform-import-meta": "^2.3.3", "eslint": "^9.33.0", "eslint-plugin-jest": "^29.0.1", From dd46a059c539bdf9179a02d004ddd6cd478663bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 21 Aug 2025 16:53:36 +0200 Subject: [PATCH 11/28] aah, i forgot to add the latest commit --- client/homebrew/navbar/newbrew.navitem.jsx | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/client/homebrew/navbar/newbrew.navitem.jsx b/client/homebrew/navbar/newbrew.navitem.jsx index c20ae6b6c..ccade4e8b 100644 --- a/client/homebrew/navbar/newbrew.navitem.jsx +++ b/client/homebrew/navbar/newbrew.navitem.jsx @@ -34,16 +34,11 @@ const NewBrew = ()=>{ } const type = file.name.split('.').pop().toLowerCase(); - if(type === 'txt') { - alert( - `This file type is correct, but it is not from the homebrewery or has been tampered with, please try with a correct file or report this as an issue if you think it is a mistake.` - ); - } else if(!type) { - alert('This file is invalid, please, enter a valid file'); - console.log(file); - } else { - alert(`This is a .${type} file, only .txt files are allowed`); - } + + alert(`This file is invalid: ${!type ? "Missing file extension" :`.${type} files are not supported`}. Only .txt files exported from the Homebrewery are allowed.`); + + + console.log(file); }; reader.readAsText(file); }; From 029c105ff1f8c070874c5c04696009a5ca4fe029 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 23 Aug 2025 14:04:37 -0500 Subject: [PATCH 12/28] Fix \} in divblocks --- shared/naturalcrit/markdown.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index ff61e9793..c07d879ec 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -188,7 +188,6 @@ const mustacheSpans = { const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\=]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; const match = completeSpan.exec(src); if(match) { - console.log('MustacheSpans'); //Find closing delimiter let blockCount = 0; let tags = {}; @@ -196,7 +195,6 @@ const mustacheSpans = { let endToken = 0; let delim; while (delim = inlineRegex.exec(match[0])) { - console.log(delim); if(_.isEmpty(tags)) { tags = processStyleTags(delim[0].substring(2)); endTags = delim[0].length; @@ -243,11 +241,10 @@ const mustacheDivs = { level : 'block', start(src) { return src.match(/\n *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token + const completeBlock = /^ *{{[^\n]* *\n.*\n *}}/s; // Regex for the complete token const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%. ]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; const match = completeBlock.exec(src); if(match) { - console.log('Mustache Divs'); //Find closing delimiter let blockCount = 0; let tags = {}; @@ -303,7 +300,6 @@ const mustacheInjectInline = { const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; const match = inlineRegex.exec(src); if(match) { - console.log('InlineInject'); const lastToken = tokens[tokens.length - 1]; if(!lastToken || lastToken.type == 'mustacheInjectInline') return false; From cd378cad0ca0ce3d3cab047f53c60d2829c10a96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:25:55 +0000 Subject: [PATCH 13/28] Bump stylelint-config-recommended from 16.0.0 to 17.0.0 Bumps [stylelint-config-recommended](https://github.com/stylelint/stylelint-config-recommended) from 16.0.0 to 17.0.0. - [Release notes](https://github.com/stylelint/stylelint-config-recommended/releases) - [Changelog](https://github.com/stylelint/stylelint-config-recommended/blob/main/CHANGELOG.md) - [Commits](https://github.com/stylelint/stylelint-config-recommended/compare/16.0.0...17.0.0) --- updated-dependencies: - dependency-name: stylelint-config-recommended dependency-version: 17.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 705f327b2..b6b958b21 100644 --- a/package-lock.json +++ b/package-lock.json @@ -75,7 +75,7 @@ "postcss-less": "^6.0.0", "stylelint": "^16.23.1", "stylelint-config-recess-order": "^7.2.0", - "stylelint-config-recommended": "^16.0.0", + "stylelint-config-recommended": "^17.0.0", "supertest": "^7.1.4" }, "engines": { @@ -13347,9 +13347,9 @@ } }, "node_modules/stylelint-config-recommended": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-16.0.0.tgz", - "integrity": "sha512-4RSmPjQegF34wNcK1e1O3Uz91HN8P1aFdFzio90wNK9mjgAI19u5vsU868cVZboKzCaa5XbpvtTzAAGQAxpcXA==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-17.0.0.tgz", + "integrity": "sha512-WaMSdEiPfZTSFVoYmJbxorJfA610O0tlYuU2aEwY33UQhSPgFbClrVJYWvy3jGJx+XW37O+LyNLiZOEXhKhJmA==", "dev": true, "funding": [ { @@ -13366,7 +13366,7 @@ "node": ">=18.12.0" }, "peerDependencies": { - "stylelint": "^16.16.0" + "stylelint": "^16.23.0" } }, "node_modules/stylelint-order": { diff --git a/package.json b/package.json index 5c7ea1032..415ed8a54 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "postcss-less": "^6.0.0", "stylelint": "^16.23.1", "stylelint-config-recess-order": "^7.2.0", - "stylelint-config-recommended": "^16.0.0", + "stylelint-config-recommended": "^17.0.0", "supertest": "^7.1.4" } } From 8924685c26419628ba4088feac8c27d3da07e706 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:30:44 +0000 Subject: [PATCH 14/28] Bump cipher-base from 1.0.4 to 1.0.6 Bumps [cipher-base](https://github.com/crypto-browserify/cipher-base) from 1.0.4 to 1.0.6. - [Changelog](https://github.com/browserify/cipher-base/blob/master/CHANGELOG.md) - [Commits](https://github.com/crypto-browserify/cipher-base/compare/v1.0.4...v1.0.6) --- updated-dependencies: - dependency-name: cipher-base dependency-version: 1.0.6 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index b6b958b21..9869b7be9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4863,13 +4863,16 @@ } }, "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/cjs-module-lexer": { From e25c3daad6d8a6f16134a6029d82c1b6c1ebc044 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 20:15:31 +0000 Subject: [PATCH 15/28] Bump sha.js from 2.4.11 to 2.4.12 Bumps [sha.js](https://github.com/crypto-browserify/sha.js) from 2.4.11 to 2.4.12. - [Changelog](https://github.com/browserify/sha.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/crypto-browserify/sha.js/compare/v2.4.11...v2.4.12) --- updated-dependencies: - dependency-name: sha.js dependency-version: 2.4.12 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9869b7be9..623f4ecd3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12530,16 +12530,23 @@ "license": "ISC" }, "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "license": "(MIT AND BSD-3-Clause)", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/shasum": { From f1ad1b912414c00c03d16037abddb6ce09101fc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 04:44:12 +0000 Subject: [PATCH 16/28] Bump eslint from 9.33.0 to 9.34.0 in the dev-dependencies group Bumps the dev-dependencies group with 1 update: [eslint](https://github.com/eslint/eslint). Updates `eslint` from 9.33.0 to 9.34.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v9.33.0...v9.34.0) --- updated-dependencies: - dependency-name: eslint dependency-version: 9.34.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 623f4ecd3..430fb6778 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,7 +65,7 @@ "devDependencies": { "@stylistic/stylelint-plugin": "^4.0.0", "babel-plugin-transform-import-meta": "^2.3.3", - "eslint": "^9.33.0", + "eslint": "^9.34.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-react": "^7.37.5", "globals": "^16.3.0", @@ -2082,9 +2082,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.33.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", - "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz", + "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==", "dev": true, "license": "MIT", "engines": { @@ -6061,9 +6061,9 @@ } }, "node_modules/eslint": { - "version": "9.33.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", - "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.34.0.tgz", + "integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==", "dev": true, "license": "MIT", "dependencies": { @@ -6073,7 +6073,7 @@ "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.33.0", + "@eslint/js": "9.34.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", diff --git a/package.json b/package.json index 415ed8a54..5c6fb4efc 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,7 @@ "devDependencies": { "@stylistic/stylelint-plugin": "^4.0.0", "babel-plugin-transform-import-meta": "^2.3.3", - "eslint": "^9.33.0", + "eslint": "^9.34.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-react": "^7.37.5", "globals": "^16.3.0", From 83c3eacf831c866a70329468a50559f4a24fcd21 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 16:45:47 -0400 Subject: [PATCH 17/28] Change props and state to functional style --- client/homebrew/pages/homePage/homePage.jsx | 34 +++++++++------------ 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index eac0216fd..55d19d72b 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -21,25 +21,19 @@ const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx'); const { DEFAULT_BREW } = require('../../../../server/brewDefaults.js'); -const HomePage = createClass({ - displayName : 'HomePage', - getDefaultProps : function() { - return { - brew : DEFAULT_BREW, - ver : '0.0.0' - }; - }, - getInitialState : function() { - return { - brew : this.props.brew, - welcomeText : this.props.brew.text, - error : undefined, - currentEditorViewPageNum : 1, - currentEditorCursorPageNum : 1, - currentBrewRendererPageNum : 1, - themeBundle : {} - }; - }, +const HomePage =(props)=>{ + const { + brew = DEFAULT_BREW, + ver = '0.0.0' + } = props; + + const [brew , setBrew] = useState(brew); + const [welcomeText , setWelcomeText] = useState(brew.text); + const [error , setError] = useState(undefined); + const [currentEditorViewPageNum , setCurrentEditorViewPageNum] = useState(1); + const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); + const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); + const [themeBundle , setThemeBundle] = useState({}); editor : React.createRef(null), @@ -136,6 +130,6 @@ const HomePage = createClass({ ; } -}); +}; module.exports = HomePage; From 759dcb583360061c18a867004bf099eda85bacad Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 16:49:54 -0400 Subject: [PATCH 18/28] Change functions to const vars --- client/homebrew/pages/homePage/homePage.jsx | 40 +++++++++++---------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 55d19d72b..1b3ad0608 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -41,7 +41,7 @@ const HomePage =(props)=>{ fetchThemeBundle(this, this.props.brew.renderer, this.props.brew.theme); }, - handleSave : function(){ + const handleSave ()=>{ request.post('/api') .send(this.state.brew) .end((err, res)=>{ @@ -52,29 +52,31 @@ const HomePage =(props)=>{ const brew = res.body; window.location = `/edit/${brew.editId}`; }); - }, - handleSplitMove : function(){ + }; + + const handleSplitMove ()=>{ this.editor.current.update(); - }, + }; - handleEditorViewPageChange : function(pageNumber){ + const handleEditorViewPageChange (pageNumber)=>{ this.setState({ currentEditorViewPageNum: pageNumber }); - }, + }; - handleEditorCursorPageChange : function(pageNumber){ + const handleEditorCursorPageChange (pageNumber)=>{ this.setState({ currentEditorCursorPageNum: pageNumber }); - }, + }; - handleBrewRendererPageChange : function(pageNumber){ + const handleBrewRendererPageChange (pageNumber)=>{ this.setState({ currentBrewRendererPageNum: pageNumber }); - }, + }; - handleTextChange : function(text){ + const handleTextChange (text)=>{ this.setState((prevState)=>({ brew : { ...prevState.brew, text: text }, })); - }, - renderNavbar : function(){ + }; + + const renderNavbar = ()=>{ return {this.state.error ? @@ -88,12 +90,12 @@ const HomePage =(props)=>{ ; - }, + }; - render : function(){ - return
+ return ( +
- {this.renderNavbar()} + {renderNavbar()} ; - } +
+ ) }; module.exports = HomePage; From 8cf55932a9392799e5127e33e253d94ea6826c50 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 17:10:20 -0400 Subject: [PATCH 19/28] Fix useEffect and Refs; Update fetchThemeBundle to work with functional --- client/homebrew/pages/homePage/homePage.jsx | 75 +++++++++++---------- shared/helpers.js | 16 ++--- 2 files changed, 43 insertions(+), 48 deletions(-) diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 1b3ad0608..e09296388 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -22,26 +22,27 @@ const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx'); const { DEFAULT_BREW } = require('../../../../server/brewDefaults.js'); const HomePage =(props)=>{ - const { - brew = DEFAULT_BREW, - ver = '0.0.0' - } = props; + props = { + brew : DEFAULT_BREW, + ver : '0.0.0', + ...props + }; - const [brew , setBrew] = useState(brew); - const [welcomeText , setWelcomeText] = useState(brew.text); + const [brew , setBrew] = useState(props.brew); + const [welcomeText , setWelcomeText] = useState(props.brew.text); const [error , setError] = useState(undefined); const [currentEditorViewPageNum , setCurrentEditorViewPageNum] = useState(1); const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); const [themeBundle , setThemeBundle] = useState({}); - editor : React.createRef(null), + const editorRef = useRef(null); - componentDidMount : function() { - fetchThemeBundle(this, this.props.brew.renderer, this.props.brew.theme); - }, + useEffect(()=>{ + fetchThemeBundle(setError, setThemeBundle, brew.renderer, brew.theme); + }, []); - const handleSave ()=>{ + const handleSave = ()=>{ request.post('/api') .send(this.state.brew) .end((err, res)=>{ @@ -53,24 +54,24 @@ const HomePage =(props)=>{ window.location = `/edit/${brew.editId}`; }); }; - - const handleSplitMove ()=>{ + + const handleSplitMove = ()=>{ this.editor.current.update(); }; - const handleEditorViewPageChange (pageNumber)=>{ + const handleEditorViewPageChange = (pageNumber)=>{ this.setState({ currentEditorViewPageNum: pageNumber }); }; - const handleEditorCursorPageChange (pageNumber)=>{ + const handleEditorCursorPageChange = (pageNumber)=>{ this.setState({ currentEditorCursorPageNum: pageNumber }); }; - const handleBrewRendererPageChange (pageNumber)=>{ + const handleBrewRendererPageChange = (pageNumber)=>{ this.setState({ currentBrewRendererPageNum: pageNumber }); }; - const handleTextChange (text)=>{ + const handleTextChange = (text)=>{ this.setState((prevState)=>({ brew : { ...prevState.brew, text: text }, })); @@ -97,33 +98,33 @@ const HomePage =(props)=>{ {renderNavbar()}
- +
-
+
Save current
diff --git a/shared/helpers.js b/shared/helpers.js index e09b0bdc4..3f91583d6 100644 --- a/shared/helpers.js +++ b/shared/helpers.js @@ -116,27 +116,21 @@ const printCurrentBrew = ()=>{ } }; -const fetchThemeBundle = async (obj, renderer, theme)=>{ +const fetchThemeBundle = async (setError, setThemeBundle, renderer, theme)=>{ if(!renderer || !theme) return; const res = await request .get(`/api/theme/${renderer}/${theme}`) .catch((err)=>{ - obj.setState({ error: err }); + setError(err) }); if(!res) { - obj.setState((prevState)=>({ - ...prevState, - themeBundle : {} - })); + setThemeBundle({}); return; } const themeBundle = res.body; themeBundle.joinedStyles = themeBundle.styles.map((style)=>``).join('\n\n'); - obj.setState((prevState)=>({ - ...prevState, - themeBundle : themeBundle, - error : null - })); + setThemeBundle(themeBundle); + setError(null); }; const debugTextMismatch = (clientTextRaw, serverTextRaw, label) => { From 15c04ef37ed69b19136a19d4049f7710ec7e506d Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 17:14:37 -0400 Subject: [PATCH 20/28] Update homePage.jsx --- client/homebrew/pages/homePage/homePage.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index e09296388..c8a66e732 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -44,7 +44,7 @@ const HomePage =(props)=>{ const handleSave = ()=>{ request.post('/api') - .send(this.state.brew) + .send(brew) .end((err, res)=>{ if(err) { this.setState({ error: err }); @@ -81,7 +81,7 @@ const HomePage =(props)=>{ return {this.state.error ? - : + : null } From 986bfdd00a9843cf17de4ea1a15315a8b008f40d Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 30 Aug 2025 17:37:23 -0500 Subject: [PATCH 21/28] Prevent extra columns --- client/homebrew/brewRenderer/brewRenderer.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 6bcfc87ec..6f2e30c01 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -40,7 +40,7 @@ const BrewPage = (props)=>{ ...props }; const pageRef = useRef(null); - const cleanText = safeHTML(`${props.contents}\n
\n`); + const cleanText = safeHTML(`${props.contents}\n`); useEffect(()=>{ if(!pageRef.current) return; @@ -207,7 +207,8 @@ const BrewRenderer = (props)=>{ } // DO NOT REMOVE!!! REQUIRED FOR BACKWARDS COMPATIBILITY WITH NON-UPGRADABLE VERSIONS OF CHROME. - pageText += `\n\n \n\\column\n `; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear) + + pageText += pageText.indexOf(`\n\\column\n`) < 0 ? `\n\n \n\\column\n ` : 0; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear) const html = Markdown.render(pageText, index); From da578c53a809c3d9fc9869895883d7f199882753 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 18:50:49 -0400 Subject: [PATCH 22/28] Remove extraneous changes Overcorrecting in the other direction --- client/homebrew/brewRenderer/brewRenderer.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 6f2e30c01..84ce44bec 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -207,8 +207,7 @@ const BrewRenderer = (props)=>{ } // DO NOT REMOVE!!! REQUIRED FOR BACKWARDS COMPATIBILITY WITH NON-UPGRADABLE VERSIONS OF CHROME. - - pageText += pageText.indexOf(`\n\\column\n`) < 0 ? `\n\n \n\\column\n ` : 0; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear) + pageText += `\n\n \n\\column\n `; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear) const html = Markdown.render(pageText, index); From 53f6e48f8f73cc9fc872d03bffcf18153cd0e4fe Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 18:51:59 -0400 Subject: [PATCH 23/28] cleanup extra `\n` being added --- client/homebrew/brewRenderer/brewRenderer.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 84ce44bec..407a911c8 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -40,7 +40,7 @@ const BrewPage = (props)=>{ ...props }; const pageRef = useRef(null); - const cleanText = safeHTML(`${props.contents}\n`); + const cleanText = safeHTML(props.contents); useEffect(()=>{ if(!pageRef.current) return; From 6600d9344caa59436cf61664dca4ced2b5d06e53 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 18:53:55 -0400 Subject: [PATCH 24/28] Revert "Add missing punctuation and sentence structure characters to mustache style assignment regex" --- client/homebrew/editor/editor.jsx | 2 +- shared/naturalcrit/markdown.js | 23 ++++++----------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index fc20f2be4..8d331e46e 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -12,7 +12,7 @@ const MetadataEditor = require('./metadataEditor/metadataEditor.jsx'); const EDITOR_THEME_KEY = 'HOMEBREWERY-EDITOR-THEME'; -const PAGEBREAK_REGEX_V3 = /^(?=\\page(?:break)?(?: *{[^\n]*})?$)/m; +const PAGEBREAK_REGEX_V3 = /^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/m; const SNIPPETBREAK_REGEX_V3 = /^\\snippet\ .*$/; const DEFAULT_STYLE_TEXT = dedent` /*=======--- Example CSS styling ---=======*/ diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index c07d879ec..78107dcf4 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -185,7 +185,7 @@ const mustacheSpans = { start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token - const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\=]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; + const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-+*/()#%=?. ]*"|[\w\-+*/()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; const match = completeSpan.exec(src); if(match) { //Find closing delimiter @@ -241,8 +241,8 @@ const mustacheDivs = { level : 'block', start(src) { return src.match(/\n *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const completeBlock = /^ *{{[^\n]* *\n.*\n *}}/s; // Regex for the complete token - const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%. ]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; + const completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token + const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-+*/()#%=?. ]*"|[\w\-+*/()#%.]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; const match = completeBlock.exec(src); if(match) { //Find closing delimiter @@ -297,7 +297,7 @@ const mustacheInjectInline = { level : 'inline', start(src) { return src.match(/ *{[^{\n]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-+*/()#%=?. ]*"|[\w\-+*/()#%.]*)|[^"=':{}\s]*)*))\1}/g; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1]; @@ -343,7 +343,7 @@ const mustacheInjectBlock = { level : 'block', start(src) { return src.match(/\n *{[^{\n]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.& ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/ym; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-+*/()#%=?. ]*"|[\w\-+*/()#%.]*)|[^"=':{}\s]*)*))\1}/ym; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1]; @@ -735,17 +735,6 @@ const voidTags = new Set([ 'input', 'keygen', 'link', 'meta', 'param', 'source' ]); -const notInside = (string, stringMatch1, stringMatch2)=> { - const pos1 = string.indexOf(stringMatch1); - const pos2 = string.indexOf(stringMatch2); - - if(((pos1 > 0) && (pos2 == -1)) || - ((pos1 > 0) && (pos2 > 0) && (pos2 > pos1))) { - return true; - } - return false; -}; - const processStyleTags = (string)=>{ //split tags up. quotes can only occur right after : or =. //TODO: can we simplify to just split on commas? @@ -753,7 +742,7 @@ const processStyleTags = (string)=>{ const id = _.remove(tags, (tag)=>tag.startsWith('#')).map((tag)=>tag.slice(1))[0] || null; const classes = _.remove(tags, (tag)=>(!tag.includes(':')) && (!tag.includes('='))).join(' ') || null; - const attributes = _.remove(tags, (tag)=>(notInside(tag, '=', ':'))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"')) + const attributes = _.remove(tags, (tag)=>(tag.includes('='))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"')) ?.filter((attr)=>!attr.startsWith('class="') && !attr.startsWith('style="') && !attr.startsWith('id="')) .reduce((obj, attr)=>{ const index = attr.indexOf('='); From 518a3434bec39668998c01166aba2618d64b1033 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 19:02:39 -0400 Subject: [PATCH 25/28] Changes fetchThemeBundle helper to not need "this" parameter Looks a bit ugly but this is temporary toward converting edit/home/new into functional components --- client/homebrew/brewRenderer/brewRenderer.jsx | 4 ++-- client/homebrew/pages/editPage/editPage.jsx | 4 ++-- client/homebrew/pages/homePage/homePage.jsx | 2 +- client/homebrew/pages/newPage/newPage.jsx | 4 ++-- client/homebrew/pages/sharePage/sharePage.jsx | 20 ++++++------------- shared/helpers.js | 16 +++++---------- 6 files changed, 18 insertions(+), 32 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 6bcfc87ec..7a101e9f9 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -39,8 +39,8 @@ const BrewPage = (props)=>{ index : 0, ...props }; - const pageRef = useRef(null); - const cleanText = safeHTML(`${props.contents}\n
\n`); + const pageRef = useRef(null); + const cleanText = safeHTML(props.contents); useEffect(()=>{ if(!pageRef.current) return; diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index d1f0ed21c..ad99948a9 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -97,7 +97,7 @@ const EditPage = createClass({ htmlErrors : Markdown.validate(prevState.brew.text) })); - fetchThemeBundle(this, this.props.brew.renderer, this.props.brew.theme); + fetchThemeBundle((err)=>{this.setState({ error: err })}, (theme)=>{this.setState({ themeBundle: theme })}, this.props.brew.renderer, this.props.brew.theme); document.addEventListener('keydown', this.handleControlKeys); }, @@ -173,7 +173,7 @@ const EditPage = createClass({ handleMetaChange : function(metadata, field=undefined){ if(field == 'theme' || field == 'renderer') // Fetch theme bundle only if theme or renderer was changed - fetchThemeBundle(this, metadata.renderer, metadata.theme); + fetchThemeBundle((err)=>{this.setState({ error: err })}, (theme)=>{this.setState({ themeBundle: theme })}, metadata.renderer, metadata.theme); this.setState((prevState)=>({ brew : { diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index eac0216fd..3b8fdbf01 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -44,7 +44,7 @@ const HomePage = createClass({ editor : React.createRef(null), componentDidMount : function() { - fetchThemeBundle(this, this.props.brew.renderer, this.props.brew.theme); + fetchThemeBundle((err)=>{this.setState({ error: err })}, (theme)=>{this.setState({ themeBundle: theme })}, this.props.brew.renderer, this.props.brew.theme); }, handleSave : function(){ diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index ab7c22541..135794a81 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -80,7 +80,7 @@ const NewPage = createClass({ saveGoogle : (saveStorage == 'GOOGLE-DRIVE' && this.state.saveGoogle) }); - fetchThemeBundle(this, this.props.brew.renderer, this.props.brew.theme); + fetchThemeBundle((err)=>{this.setState({ error: err })}, (theme)=>{this.setState({ themeBundle: theme })}, this.props.brew.renderer, this.props.brew.theme); localStorage.setItem(BREWKEY, brew.text); if(brew.style) @@ -154,7 +154,7 @@ const NewPage = createClass({ handleMetaChange : function(metadata, field=undefined){ if(field == 'theme' || field == 'renderer') // Fetch theme bundle only if theme or renderer was changed - fetchThemeBundle(this, metadata.renderer, metadata.theme); + fetchThemeBundle((err)=>{this.setState({ error: err })}, (theme)=>{this.setState({ themeBundle: theme })}, metadata.renderer, metadata.theme); this.setState((prevState)=>({ brew : { ...prevState.brew, ...metadata }, diff --git a/client/homebrew/pages/sharePage/sharePage.jsx b/client/homebrew/pages/sharePage/sharePage.jsx index e9c5540a2..50104a665 100644 --- a/client/homebrew/pages/sharePage/sharePage.jsx +++ b/client/homebrew/pages/sharePage/sharePage.jsx @@ -17,15 +17,11 @@ const { printCurrentBrew, fetchThemeBundle } = require('../../../../shared/helpe const SharePage = (props)=>{ const { brew = DEFAULT_BREW_LOAD, disableMeta = false } = props; - const [state, setState] = useState({ - themeBundle : {}, - currentBrewRendererPageNum : 1, - }); + const [themeBundle, setThemeBundle] = useState({}); + const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); const handleBrewRendererPageChange = useCallback((pageNumber)=>{ - setState((prevState)=>({ - currentBrewRendererPageNum : pageNumber, - ...prevState })); + setCurrentBrewRendererPageNum(pageNumber); }, []); const handleControlKeys = (e)=>{ @@ -40,11 +36,7 @@ const SharePage = (props)=>{ useEffect(()=>{ document.addEventListener('keydown', handleControlKeys); - fetchThemeBundle( - { setState }, - brew.renderer, - brew.theme - ); + fetchThemeBundle(undefined, setThemeBundle, brew.renderer, brew.theme); return ()=>{ document.removeEventListener('keydown', handleControlKeys); @@ -114,9 +106,9 @@ const SharePage = (props)=>{ lang={brew.lang} renderer={brew.renderer} theme={brew.theme} - themeBundle={state.themeBundle} + themeBundle={themeBundle} onPageChange={handleBrewRendererPageChange} - currentBrewRendererPageNum={state.currentBrewRendererPageNum} + currentBrewRendererPageNum={currentBrewRendererPageNum} allowPrint={true} />
diff --git a/shared/helpers.js b/shared/helpers.js index e09b0bdc4..3f91583d6 100644 --- a/shared/helpers.js +++ b/shared/helpers.js @@ -116,27 +116,21 @@ const printCurrentBrew = ()=>{ } }; -const fetchThemeBundle = async (obj, renderer, theme)=>{ +const fetchThemeBundle = async (setError, setThemeBundle, renderer, theme)=>{ if(!renderer || !theme) return; const res = await request .get(`/api/theme/${renderer}/${theme}`) .catch((err)=>{ - obj.setState({ error: err }); + setError(err) }); if(!res) { - obj.setState((prevState)=>({ - ...prevState, - themeBundle : {} - })); + setThemeBundle({}); return; } const themeBundle = res.body; themeBundle.joinedStyles = themeBundle.styles.map((style)=>``).join('\n\n'); - obj.setState((prevState)=>({ - ...prevState, - themeBundle : themeBundle, - error : null - })); + setThemeBundle(themeBundle); + setError(null); }; const debugTextMismatch = (clientTextRaw, serverTextRaw, label) => { From 8671404bdc405b7efc2cf017b35d421326adc407 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 19:35:22 -0400 Subject: [PATCH 26/28] Refactor ErrorNavItem to not need "this" parameter Toward making edit/new/home pages functional, which do not have "this" --- client/homebrew/navbar/error-navitem.jsx | 269 +++++++++----------- client/homebrew/pages/editPage/editPage.jsx | 9 +- client/homebrew/pages/homePage/homePage.jsx | 10 +- client/homebrew/pages/newPage/newPage.jsx | 9 +- client/homebrew/pages/userPage/userPage.jsx | 6 +- 5 files changed, 155 insertions(+), 148 deletions(-) diff --git a/client/homebrew/navbar/error-navitem.jsx b/client/homebrew/navbar/error-navitem.jsx index ec72ace7d..6d9bec444 100644 --- a/client/homebrew/navbar/error-navitem.jsx +++ b/client/homebrew/navbar/error-navitem.jsx @@ -1,157 +1,138 @@ require('./error-navitem.less'); const React = require('react'); const Nav = require('naturalcrit/nav/nav.jsx'); -const createClass = require('create-react-class'); -const ErrorNavItem = createClass({ - getDefaultProps : function() { - return { - error : '', - parent : null - }; - }, - render : function() { - const clearError = ()=>{ - const state = { - error : null - }; - if(this.props.parent.state.isSaving) { - state.isSaving = false; - } - this.props.parent.setState(state); - }; +const ErrorNavItem = ({error = '', clearError})=>{ + const response = error.response; + const errorCode = error.code + const status = response?.status; + const HBErrorCode = response?.body?.HBErrorCode; + const message = response?.body?.message; - const error = this.props.error; - const response = error.response; - const status = response?.status; - const errorCode = error.code - const HBErrorCode = response?.body?.HBErrorCode; - const message = response?.body?.message; - let errMsg = ''; - try { - errMsg += `${error.toString()}\n\n`; - errMsg += `\`\`\`\n${error.stack}\n`; - errMsg += `${JSON.stringify(response?.error, null, ' ')}\n\`\`\``; - console.log(errMsg); - } catch (e){} - - if(status === 409) { - return - Oops! -
- {message ?? 'Conflict: please refresh to get latest changes'} -
-
; - } - - if(status === 412) { - return - Oops! -
- {message ?? 'Your client is out of date. Please save your changes elsewhere and refresh.'} -
-
; - } - - if(HBErrorCode === '04') { - return - Oops! -
- You are no longer signed in as an author of - this brew! Were you signed out from a different - window? Visit our log in page, then try again! -

- -
- Sign In -
-
-
- Not Now -
-
-
; - } - - if(response?.body?.errors?.[0].reason == 'storageQuotaExceeded') { - return - Oops! -
- Can't save because your Google Drive seems to be full! -
-
; - } - - if(response?.req.url.match(/^\/api.*Google.*$/m)){ - return - Oops! -
- Looks like your Google credentials have - expired! Visit our log in page to sign out - and sign back in with Google, - then try saving again! -

- -
- Sign In -
-
-
- Not Now -
-
-
; - } - - if(HBErrorCode === '09') { - return - Oops! -
- Looks like there was a problem retreiving - the theme, or a theme that it inherits, - for this brew. Verify that brew - {response.body.brewId} still exists! -
-
; - } - - if(HBErrorCode === '10') { - return - Oops! -
- Looks like the brew you have selected - as a theme is not tagged for use as a - theme. Verify that - brew - {response.body.brewId} has the meta:theme tag! -
-
; - } - - if(errorCode === 'ECONNABORTED') { - return - Oops! -
- The request to the server was interrupted or timed out. - This can happen due to a network issue, or if - trying to save a particularly large brew. - Please check your internet connection and try again. -
-
; - } + let errMsg = ''; + try { + errMsg += `${error.toString()}\n\n`; + errMsg += `\`\`\`\n${error.stack}\n`; + errMsg += `${JSON.stringify(response?.error, null, ' ')}\n\`\`\``; + console.log(errMsg); + } catch (e){} + if(status === 409) { return Oops! -
- Looks like there was a problem saving.
- Report the issue - here - . +
+ {message ?? 'Conflict: please refresh to get latest changes'}
; } -}); + + if(status === 412) { + return + Oops! +
+ {message ?? 'Your client is out of date. Please save your changes elsewhere and refresh.'} +
+
; + } + + if(HBErrorCode === '04') { + return + Oops! +
+ You are no longer signed in as an author of + this brew! Were you signed out from a different + window? Visit our log in page, then try again! +

+ +
+ Sign In +
+
+
+ Not Now +
+
+
; + } + + if(response?.body?.errors?.[0].reason == 'storageQuotaExceeded') { + return + Oops! +
+ Can't save because your Google Drive seems to be full! +
+
; + } + + if(response?.req.url.match(/^\/api.*Google.*$/m)){ + return + Oops! +
+ Looks like your Google credentials have + expired! Visit our log in page to sign out + and sign back in with Google, + then try saving again! +

+ +
+ Sign In +
+
+
+ Not Now +
+
+
; + } + + if(HBErrorCode === '09') { + return + Oops! +
+ Looks like there was a problem retreiving + the theme, or a theme that it inherits, + for this brew. Verify that brew + {response.body.brewId} still exists! +
+
; + } + + if(HBErrorCode === '10') { + return + Oops! +
+ Looks like the brew you have selected + as a theme is not tagged for use as a + theme. Verify that + brew + {response.body.brewId} has the meta:theme tag! +
+
; + } + + if(errorCode === 'ECONNABORTED') { + return + Oops! +
+ The request to the server was interrupted or timed out. + This can happen due to a network issue, or if + trying to save a particularly large brew. + Please check your internet connection and try again. +
+
; + } + + return + Oops! +
+ Looks like there was a problem saving.
+ Report the issue + here + . +
+
; +}; module.exports = ErrorNavItem; diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index d1f0ed21c..68b1f0777 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -438,6 +438,13 @@ const EditPage = createClass({ return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(title.toWellFormed())}&text=${encodeURIComponent(text)}`; }, + clearError : function(){ + setState({ + error : null, + isSaving : false + }) + }, + renderNavbar : function(){ const shareLink = this.processShareId(); @@ -449,7 +456,7 @@ const EditPage = createClass({ {this.renderGoogleDriveIcon()} {this.state.error ? - : + : {this.renderSaveButton()} {this.renderAutoSaveButton()} diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index eac0216fd..15150a5bd 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -80,11 +80,19 @@ const HomePage = createClass({ brew : { ...prevState.brew, text: text }, })); }, + + clearError : function(){ + setState({ + error : null, + isSaving : false + }) + }, + renderNavbar : function(){ return {this.state.error ? - : + : null } diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index ab7c22541..46d7c2612 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -211,6 +211,13 @@ const NewPage = createClass({ } }, + clearError : function(){ + setState({ + error : null, + isSaving : false + }) + }, + renderNavbar : function(){ return @@ -220,7 +227,7 @@ const NewPage = createClass({ {this.state.error ? - : + : this.renderSaveButton() } diff --git a/client/homebrew/pages/userPage/userPage.jsx b/client/homebrew/pages/userPage/userPage.jsx index f6fae639d..e4a8b0b4e 100644 --- a/client/homebrew/pages/userPage/userPage.jsx +++ b/client/homebrew/pages/userPage/userPage.jsx @@ -39,10 +39,14 @@ const UserPage = (props)=>{ }] : []) ]; + const clearError = ()=>{ + setError(null); + }; + const navItems = ( - {error && ()} + {error && ()} From 9c336062c61237b22b33fc183cab93e4804ec034 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 19:39:15 -0400 Subject: [PATCH 27/28] Fix typo --- client/homebrew/pages/editPage/editPage.jsx | 2 +- client/homebrew/pages/homePage/homePage.jsx | 2 +- client/homebrew/pages/newPage/newPage.jsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 9a85c5975..51196a444 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -456,7 +456,7 @@ const EditPage = createClass({ {this.renderGoogleDriveIcon()} {this.state.error ? - : + : {this.renderSaveButton()} {this.renderAutoSaveButton()} diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 9b7bad150..97c893cf5 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -92,7 +92,7 @@ const HomePage = createClass({ return {this.state.error ? - : + : null } diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index aab77c25c..c24128a93 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -227,7 +227,7 @@ const NewPage = createClass({ {this.state.error ? - : + : this.renderSaveButton() } From 93b86632fce8ecfc870a4a48c2b0633f2f6c6768 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 30 Aug 2025 20:14:29 -0400 Subject: [PATCH 28/28] Change from require to import --- client/homebrew/pages/homePage/homePage.jsx | 79 ++++++++++----------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index ab1eee122..84967b1ff 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -1,25 +1,25 @@ -require('./homePage.less'); -const React = require('react'); -const createClass = require('create-react-class'); -const cx = require('classnames'); -import request from '../../utils/request-middleware.js'; -const { Meta } = require('vitreum/headtags'); +import './homePage.less'; -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 VaultNavItem = require('../../navbar/vault.navitem.jsx'); -const RecentNavItem = require('../../navbar/recent.navitem.jsx').both; -const AccountNavItem = require('../../navbar/account.navitem.jsx'); -const ErrorNavItem = require('../../navbar/error-navitem.jsx'); -const { fetchThemeBundle } = require('../../../../shared/helpers.js'); +import React from 'react'; +import { useEffect, useState, useRef } from 'react'; +import request from '../../utils/request-middleware.js'; +import { Meta } from 'vitreum/headtags'; -const SplitPane = require('client/components/splitPane/splitPane.jsx'); -const Editor = require('../../editor/editor.jsx'); -const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx'); +import Nav from 'naturalcrit/nav/nav.jsx'; +import Navbar from '../../navbar/navbar.jsx'; +import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; +import HelpNavItem from '../../navbar/help.navitem.jsx'; +import VaultNavItem from '../../navbar/vault.navitem.jsx'; +import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; +import AccountNavItem from '../../navbar/account.navitem.jsx'; +import ErrorNavItem from '../../navbar/error-navitem.jsx'; +import { fetchThemeBundle } from '../../../../shared/helpers.js'; -const { DEFAULT_BREW } = require('../../../../server/brewDefaults.js'); +import SplitPane from 'client/components/splitPane/splitPane.jsx'; +import Editor from '../../editor/editor.jsx'; +import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; + +import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; const HomePage =(props)=>{ props = { @@ -35,6 +35,7 @@ const HomePage =(props)=>{ const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); const [themeBundle , setThemeBundle] = useState({}); + const [isSaving , setIsSaving] = useState(false); const editorRef = useRef(null); @@ -42,53 +43,49 @@ const HomePage =(props)=>{ fetchThemeBundle(setError, setThemeBundle, brew.renderer, brew.theme); }, []); - const handleSave = ()=>{ + const save = ()=>{ request.post('/api') .send(brew) .end((err, res)=>{ if(err) { - this.setState({ error: err }); + setError(err); return; } - const brew = res.body; - window.location = `/edit/${brew.editId}`; + const saved = res.body; + window.location = `/edit/${saved.editId}`; }); }; const handleSplitMove = ()=>{ - this.editor.current.update(); + editorRef.current.update(); }; const handleEditorViewPageChange = (pageNumber)=>{ - this.setState({ currentEditorViewPageNum: pageNumber }); + setCurrentEditorViewPageNum(pageNumber); }; - + const handleEditorCursorPageChange = (pageNumber)=>{ - this.setState({ currentEditorCursorPageNum: pageNumber }); + setCurrentEditorCursorPageNum(pageNumber); }; - + const handleBrewRendererPageChange = (pageNumber)=>{ - this.setState({ currentBrewRendererPageNum: pageNumber }); + setCurrentBrewRendererPageNum(pageNumber); }; const handleTextChange = (text)=>{ - this.setState((prevState)=>({ - brew : { ...prevState.brew, text: text }, - })); + setBrew((prevBrew) => ({ ...prevBrew, text })); }; const clearError = ()=>{ - setState({ - error : null, - isSaving : false - }) + setError(null); + setIsSaving(false); }; - renderNavbar : function(){ - return + const renderNavbar = ()=>{ + return - {this.state.error ? - : + {error ? + : null } @@ -131,7 +128,7 @@ const HomePage =(props)=>{ />
-
+
Save current