0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-23 14:23:21 +00:00

Compare commits

...

79 Commits

Author SHA1 Message Date
dependabot[bot]
79f1d1a2a1 Bump express from 5.1.0 to 5.2.0
Bumps [express](https://github.com/expressjs/express) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/v5.1.0...v5.2.0)

---
updated-dependencies:
- dependency-name: express
  dependency-version: 5.2.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 22:03:46 +00:00
Víctor Losada Hernández
6c85484f78 Merge pull request #4352 from G-Ambatte/experimentalGoogleServiceAccountChange
Add Google service account to file permissions
2025-11-24 17:52:21 +01:00
Víctor Losada Hernández
50ebab21ce Merge branch 'master' into experimentalGoogleServiceAccountChange 2025-11-24 15:23:18 +01:00
Trevor Buckner
d79c4d9566 Merge pull request #4544 from naturalcrit/dependabot/npm_and_yarn/vitreum-929c351
Bump vitreum from `9d55fd6` to `929c351`
2025-11-21 15:21:48 -05:00
dependabot[bot]
d04434fdd8 Bump vitreum from 9d55fd6 to 929c351
Bumps [vitreum](https://github.com/calculuschild/vitreum) from `9d55fd6` to `929c351`.
- [Commits](9d55fd6fb7...929c351881)

---
updated-dependencies:
- dependency-name: vitreum
  dependency-version: 929c351881c4229550374421c7e2890a94f4dca7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-21 19:04:00 +00:00
Trevor Buckner
755d8bb77f Merge pull request #4543 from naturalcrit/dependabot/npm_and_yarn/googleapis/drive-19.2.0
Bump @googleapis/drive from 18.0.0 to 19.2.0
2025-11-21 14:02:34 -05:00
dependabot[bot]
fd8ffe8747 Bump @googleapis/drive from 18.0.0 to 19.2.0
Bumps [@googleapis/drive](https://github.com/googleapis/google-api-nodejs-client) from 18.0.0 to 19.2.0.
- [Release notes](https://github.com/googleapis/google-api-nodejs-client/releases)
- [Changelog](https://github.com/googleapis/google-api-nodejs-client/blob/main/.release-please-manifest.json)
- [Commits](https://github.com/googleapis/google-api-nodejs-client/compare/run-v18.0.0...drive-v19.2.0)

---
updated-dependencies:
- dependency-name: "@googleapis/drive"
  dependency-version: 19.2.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-21 03:02:38 +00:00
G.Ambatte
a504a2acfe Merge branch 'master' into experimentalGoogleServiceAccountChange 2025-11-21 10:26:49 +13:00
Trevor Buckner
4fcde805ce Merge pull request #4525 from naturalcrit/dependabot/npm_and_yarn/dev-dependencies-d8b0a98ef9
Bump the dev-dependencies group across 1 directory with 2 updates
2025-11-20 11:28:08 -05:00
Trevor Buckner
8d6438feda Merge branch 'master' into dependabot/npm_and_yarn/dev-dependencies-d8b0a98ef9 2025-11-20 11:24:38 -05:00
Trevor Buckner
e85a980ee0 Merge pull request #4536 from naturalcrit/dependabot/npm_and_yarn/prod-dependencies-3bcb05f39f
Bump the prod-dependencies group across 1 directory with 7 updates
2025-11-20 11:24:22 -05:00
Trevor Buckner
106de864ff Merge branch 'master' into dependabot/npm_and_yarn/prod-dependencies-3bcb05f39f 2025-11-20 11:15:43 -05:00
Trevor Buckner
d398cabb52 Merge pull request #4538 from 5e-Cleric/fix-counter-reset
fix .resetCounter
2025-11-20 11:15:05 -05:00
Trevor Buckner
13550c0267 Merge branch 'master' into fix-counter-reset 2025-11-20 11:08:47 -05:00
Trevor Buckner
3997ebfbdf Merge pull request #4540 from naturalcrit/ReworkHTMLRenderer
Rework Marked custom HTML renderer to skip preprocess step
2025-11-19 23:57:07 -05:00
Trevor Buckner
31c034c029 Rework Marked custom HTML renderer to skip preprocess step
Marked Variables are getting cleared when the custom HTML renderer runs, because Marked.parse re-runs the whole pipeline, including the preprocessor.

Preprocess should only be run once globally during the pipeline, or the original results get overwritten (Marked Variables clears its global array of variables each time it is run)
2025-11-19 23:53:39 -05:00
Víctor Losada Hernández
f991235694 fix .resetCounter 2025-11-19 23:36:43 +01:00
dependabot[bot]
9970dd0699 Bump the prod-dependencies group across 1 directory with 7 updates
Bumps the prod-dependencies group with 7 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) | `7.27.1` | `7.28.5` |
| [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) | `3.46.0` | `3.47.0` |
| [js-yaml](https://github.com/nodeca/js-yaml) | `4.1.0` | `4.1.1` |
| [marked-emoji](https://github.com/UziTech/marked-emoji) | `2.0.1` | `2.0.2` |
| [marked-gfm-heading-id](https://github.com/markedjs/marked-gfm-heading-id) | `4.1.2` | `4.1.3` |
| [mongoose](https://github.com/Automattic/mongoose) | `8.19.2` | `8.20.0` |
| [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router) | `7.9.5` | `7.9.6` |



Updates `@babel/preset-react` from 7.27.1 to 7.28.5
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.28.5/packages/babel-preset-react)

Updates `core-js` from 3.46.0 to 3.47.0
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.47.0/packages/core-js)

Updates `js-yaml` from 4.1.0 to 4.1.1
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1)

Updates `marked-emoji` from 2.0.1 to 2.0.2
- [Release notes](https://github.com/UziTech/marked-emoji/releases)
- [Changelog](https://github.com/UziTech/marked-emoji/blob/main/release.config.cjs)
- [Commits](https://github.com/UziTech/marked-emoji/compare/v2.0.1...v2.0.2)

Updates `marked-gfm-heading-id` from 4.1.2 to 4.1.3
- [Release notes](https://github.com/markedjs/marked-gfm-heading-id/releases)
- [Changelog](https://github.com/markedjs/marked-gfm-heading-id/blob/main/release.config.cjs)
- [Commits](https://github.com/markedjs/marked-gfm-heading-id/compare/v4.1.2...v4.1.3)

Updates `mongoose` from 8.19.2 to 8.20.0
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/8.19.2...8.20.0)

Updates `react-router` from 7.9.5 to 7.9.6
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router@7.9.6/packages/react-router)

---
updated-dependencies:
- dependency-name: "@babel/preset-react"
  dependency-version: 7.28.5
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-dependencies
- dependency-name: core-js
  dependency-version: 3.47.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-dependencies
- dependency-name: js-yaml
  dependency-version: 4.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-dependencies
- dependency-name: marked-emoji
  dependency-version: 2.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-dependencies
- dependency-name: marked-gfm-heading-id
  dependency-version: 4.1.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-dependencies
- dependency-name: mongoose
  dependency-version: 8.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-dependencies
- dependency-name: react-router
  dependency-version: 7.9.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-19 03:02:34 +00:00
dependabot[bot]
9f721ff2fc Bump the dev-dependencies group across 1 directory with 2 updates
Bumps the dev-dependencies group with 2 updates in the / directory: [eslint](https://github.com/eslint/eslint) and [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest).


Updates `eslint` from 9.39.0 to 9.39.1
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.39.0...v9.39.1)

Updates `eslint-plugin-jest` from 29.0.1 to 29.1.0
- [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases)
- [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v29.0.1...v29.1.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 9.39.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-dependencies
- dependency-name: eslint-plugin-jest
  dependency-version: 29.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-19 03:01:21 +00:00
Trevor Buckner
6a02ed410b Merge pull request #4534 from G-Ambatte/fixNewNavItem
Update New Item on NavBar
2025-11-17 23:49:42 -05:00
Trevor Buckner
429ad4d63b Linting and move checkLocalStorage inside confirmLocalStorageChange 2025-11-17 23:48:56 -05:00
Trevor Buckner
033893361d Merge branch 'master' into fixNewNavItem 2025-11-17 23:25:44 -05:00
Trevor Buckner
f1ae7e4d26 Merge pull request #4533 from naturalcrit/fix-editor-issues
Fix small bugs towards 3.20
2025-11-17 23:22:04 -05:00
Trevor Buckner
059d6d7939 Lint 2025-11-17 23:09:47 -05:00
G.Ambatte
73b7d6887b Fix typo in state property name for snippet bar height 2025-11-17 17:09:23 +13:00
Víctor Losada Hernández
f1891d9250 use state instead 2025-11-16 19:02:37 +01:00
G.Ambatte
a17ccdb2a2 Merge branch 'master' into fixNewNavItem 2025-11-16 13:19:08 +13:00
G.Ambatte
c784e2e63b Fix New item on Nav Bar 2025-11-16 13:12:40 +13:00
Víctor Losada Hernández
1d061e6d3f Merge branch 'master' of https://github.com/naturalcrit/homebrewery into fix-editor-issues 2025-11-15 23:41:10 +01:00
Víctor Losada Hernández
5e7fdb34a9 Revert "remove new brew nav item from new page"
This reverts commit b6478f3964.
2025-11-15 23:40:01 +01:00
Víctor Losada Hernández
677e8eaf6c Merge pull request #4532 from G-Ambatte/fixUnearthedArcanaTheme
Fix UnearthedArcana theme
2025-11-15 17:52:59 +01:00
Víctor Losada Hernández
b6478f3964 remove new brew nav item from new page 2025-11-15 17:25:25 +01:00
Víctor Losada Hernández
f18a73e1ff fix glitch in newPage 2025-11-15 17:25:05 +01:00
Víctor Losada Hernández
b78f5079df bring back update native func 2025-11-15 16:59:32 +01:00
Víctor Losada Hernández
7bc41f9b0d fix snippetbar hidden 2025-11-15 16:49:48 +01:00
Víctor Losada Hernández
a217779e76 fix snippetbar wrap 2025-11-15 16:05:21 +01:00
G.Ambatte
ad3d63a5b1 Merge branch 'master' into fixUnearthedArcanaTheme 2025-11-15 18:44:33 +13:00
G.Ambatte
93ef9bfd51 Set UnearthedArcana baseTheme to Blank 2025-11-15 18:33:22 +13:00
Trevor Buckner
a0cfec7668 test change 2025-11-15 04:35:23 +00:00
Trevor Buckner
972c675629 Merge pull request #4527 from MiniX16/master
Add unsaved-change warning to Home page editor
2025-11-14 23:04:19 -05:00
Trevor Buckner
fa9f180759 Modify slightly to follow the existing structure in editPage.jsx for easier merging of these pages later 2025-11-14 22:59:34 -05:00
G.Ambatte
435c6dcc6f Merge branch 'master' into experimentalGoogleServiceAccountChange 2025-11-15 16:40:47 +13:00
Trevor Buckner
5625121b82 Merge branch 'master' into master 2025-11-14 22:25:47 -05:00
Trevor Buckner
b6065dbcf5 Fix page break in changelog 2025-11-15 03:12:29 +00:00
Trevor Buckner
24065b43e9 bump version to 3.20.0 2025-11-15 03:07:56 +00:00
G.Ambatte
e063eab4e7 Make error messages more distinctive 2025-11-15 15:40:55 +13:00
G.Ambatte
1adbbc2ced Updated error message on failure to set permissions on Google Drive file 2025-11-15 15:37:01 +13:00
G.Ambatte
7547454084 Merge branch 'master' into experimentalGoogleServiceAccountChange 2025-11-15 15:33:54 +13:00
G.Ambatte
d73b695127 Merge branch 'master' into master 2025-11-15 14:34:13 +13:00
Trevor Buckner
acd37bff4f Merge pull request #4409 from G-Ambatte/fixUserPageLinks-#807
Change all links to User Page to use encodeURIComponent
2025-11-14 17:20:12 -05:00
Trevor Buckner
76a4ff11b3 Merge branch 'master' into fixUserPageLinks-#807 2025-11-14 17:19:45 -05:00
MiniX16
b66625e59d Handle unsaved warning with onbeforeunload 2025-11-13 12:16:37 +01:00
Trevor Buckner
885a59a05f Merge pull request #4526 from G-Ambatte/fixEditPageGoogleTransfer
Fix transferring brews to/from Google storage
2025-11-12 14:46:57 -05:00
Trevor Buckner
2012f373c0 Merge branch 'master' into fixEditPageGoogleTransfer 2025-11-12 14:46:41 -05:00
MiniX16
590688f123 Add unsaved-change warning to Home page editor 2025-11-12 17:59:28 +01:00
G.Ambatte
6a4ea2c6c9 Move toggleGoogleStorage's trySave call to useEffect block 2025-11-11 22:06:44 +13:00
Víctor Losada Hernández
ba2449f3d6 Merge branch 'master' into experimentalGoogleServiceAccountChange 2025-11-10 23:57:25 +01:00
Víctor Losada Hernández
6ccefc2399 Merge pull request #4510 from Gazook89/Move-Nav.JSX
Move nav.jsx from shared to client directory
2025-11-10 23:41:39 +01:00
Víctor Losada Hernández
8d2744d106 Merge branch 'master' into Move-Nav.JSX 2025-11-10 23:38:21 +01:00
Víctor Losada Hernández
fe616a534a Merge pull request #4517 from G-Ambatte/fixSaveOnNewPage
Fix CTRL+S triggering save on New Page
2025-11-10 23:38:06 +01:00
Víctor Losada Hernández
71462ef782 Merge branch 'master' into fixSaveOnNewPage 2025-11-10 23:33:43 +01:00
Víctor Losada Hernández
64589bfda6 Merge pull request #4514 from Gazook89/move-codeEditor-to-components
Move codeEditor to components directory
2025-11-10 23:26:22 +01:00
G.Ambatte
14ea286aa2 Remove Google permissions check function 2025-11-10 06:07:37 +00:00
G.Ambatte
de85c84685 Remove permissionsCheck from brew listing 2025-11-10 06:05:58 +00:00
G.Ambatte
35d93582d7 Remove unnecessary async map function 2025-11-10 06:04:10 +00:00
G.Ambatte
c2ceba2ff6 Merge branch 'master' into experimentalGoogleServiceAccountChange 2025-11-10 19:00:06 +13:00
Gazook89
f9f33955bc Merge branch 'master' into move-codeEditor-to-components 2025-11-09 23:30:53 -06:00
Gazook89
2ce13f61e1 update relative paths to absolute paths 2025-11-09 23:29:55 -06:00
Gazook89
6db4bf2274 Merge branch 'master' into Move-Nav.JSX 2025-11-09 23:24:21 -06:00
Trevor Buckner
e6e66ec1cc Merge branch 'master' into Move-Nav.JSX 2025-11-09 18:19:28 -05:00
G.Ambatte
20d38d03d6 Rename New Page save function to trySave for better Edit Page compatibility 2025-11-06 22:29:43 +13:00
Gazook89
29fe6430ce Move codeEditor to components directory
This simply moves the codeEditor folder to the components directory.  `codeEditor.jsx` simply builds a component which is then used elsewhere, and isn't shared between client and server, so it should be in the client directory.

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

When working on the editor right now it's a pain to switch between `shared` and `client` hunting for the right file.
2025-11-04 13:12:56 -06:00
Gazook89
081fd6f39d Move nav.jsx from shared to client directory
Moving the one file, changing a lot of imports (18 files), and deleting a directory.
2025-11-03 20:58:00 -06:00
G.Ambatte
9f3944d038 Merge branch 'master' into fixUserPageLinks-#807 2025-09-29 23:14:59 +13:00
G.Ambatte
e1fb0a42c3 Merge branch 'master' into fixUserPageLinks-#807 2025-09-20 20:23:58 +12:00
G.Ambatte
90de9c0af1 Change all links to User Page to use encodeURIComponent 2025-09-01 21:51:27 +12:00
G.Ambatte
06d1652f51 Merge branch 'master' into experimentalGoogleServiceAccountChange 2025-08-26 07:32:29 +12:00
G.Ambatte
8e2abb9f78 Basic Google file permission checking 2025-07-25 12:04:41 +12:00
G.Ambatte
b447d81b4c Add service account to file permissions 2025-07-22 18:23:11 +12:00
38 changed files with 2693 additions and 2551 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ const _ = require('lodash');
const dedent = require('dedent-tabs').default;
import Markdown from '../../../shared/markdown.js';
const CodeEditor = require('naturalcrit/codeEditor/codeEditor.jsx');
const CodeEditor = require('client/components/codeEditor/codeEditor.jsx');
const SnippetBar = require('./snippetbar/snippetbar.jsx');
const MetadataEditor = require('./metadataEditor/metadataEditor.jsx');
@@ -58,7 +58,7 @@ const Editor = createClass({
return {
editorTheme : this.props.editorTheme,
view : 'text', //'text', 'style', 'meta', 'snippet'
snippetbarHeight : 25
snippetBarHeight : 26,
};
},
@@ -85,7 +85,15 @@ const Editor = createClass({
editorTheme : editorTheme
});
}
this.setState({ snippetbarHeight: document.querySelector('.editor > .snippetBar').offsetHeight });
const snippetBar = document.querySelector('.editor > .snippetBar');
if (!snippetBar) return;
this.resizeObserver = new ResizeObserver(entries => {
const height = document.querySelector('.editor > .snippetBar').offsetHeight;
this.setState({ snippetBarHeight: height });
});
this.resizeObserver.observe(snippetBar);
},
componentDidUpdate : function(prevProps, prevState, snapshot) {
@@ -108,6 +116,10 @@ const Editor = createClass({
}
},
componentWillUnmount() {
if (this.resizeObserver) this.resizeObserver.disconnect();
},
handleControlKeys : function(e){
if(!(e.ctrlKey && e.metaKey && e.shiftKey)) return;
const LEFTARROW_KEY = 37;
@@ -408,11 +420,7 @@ const Editor = createClass({
},
//Called when there are changes to the editor's dimensions
update : function(){
const snipHeight = document.querySelector('.editor > .snippetBar').offsetHeight;
if(snipHeight !== this.state.snippetbarHeight)
this.setState({ snippetbarHeight: snipHeight });
},
update : function(){},
updateEditorTheme : function(newTheme){
window.localStorage.setItem(EDITOR_THEME_KEY, newTheme);
@@ -437,7 +445,7 @@ const Editor = createClass({
onChange={this.props.onBrewChange('text')}
editorTheme={this.state.editorTheme}
rerenderParent={this.rerenderParent}
style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
style={{ height: `calc(100% - ${this.state.snippetBarHeight}px)` }} />
</>;
}
if(this.isStyle()){
@@ -451,7 +459,7 @@ const Editor = createClass({
enableFolding={true}
editorTheme={this.state.editorTheme}
rerenderParent={this.rerenderParent}
style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
style={{ height: `calc(100% - ${this.state.snippetBarHeight}px)` }} />
</>;
}
if(this.isMeta()){
@@ -468,7 +476,6 @@ const Editor = createClass({
userThemes={this.props.userThemes}/>
</>;
}
if(this.isSnip()){
if(!this.props.brew.snippets) { this.props.brew.snippets = DEFAULT_SNIPPET_TEXT; }
return <>
@@ -481,7 +488,7 @@ const Editor = createClass({
enableFolding={true}
editorTheme={this.state.editorTheme}
rerenderParent={this.rerenderParent}
style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} />
style={{ height: `calc(100% -${this.state.snippetBarHeight}px)` }} />
</>;
}
},

View File

@@ -14,7 +14,7 @@
.snippets {
display : flex;
justify-content : flex-start;
min-width : 432.18px; //must be controlled every time an item is added, must be hardcoded for the wrapping as it is applied
min-width : 499.35px; //must be controlled every time an item is added, must be hardcoded for the wrapping as it is applied
}
.editors {
@@ -237,7 +237,7 @@
}
}
@container editor (width < 683px) {
@container editor (width < 750px) {
.snippetBar {
.editors {
flex : 1;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,21 +1,18 @@
const React = require('react');
const _ = require('lodash');
const Nav = require('naturalcrit/nav/nav.jsx');
const Nav = require('client/homebrew/navbar/nav.jsx');
const { splitTextStyleAndMetadata } = require('../../../shared/helpers.js'); // Importing the function from helpers.js
const BREWKEY = 'homebrewery-new';
const STYLEKEY = 'homebrewery-new-style';
const METAKEY = 'homebrewery-new-meta';
const BREWKEY = 'HB_newPage_content';
const STYLEKEY = 'HB_newPage_style';
const METAKEY = 'HB_newPage_meta';
const NewBrew = ()=>{
const handleFileChange = (e)=>{
const file = e.target.files[0];
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;
if(!confirmLocalStorageChange()) return;
const reader = new FileReader();
reader.onload = (e)=>{
@@ -37,12 +34,35 @@ const NewBrew = ()=>{
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);
};
const confirmLocalStorageChange = ()=>{
const currentText = localStorage.getItem(BREWKEY);
const currentStyle = localStorage.getItem(STYLEKEY);
const currentMeta = localStorage.getItem(METAKEY);
// TRUE if no data in any local storage key
// TRUE if data in any local storage key AND approval given
// FALSE if data in any local storage key AND approval declined
return (!(currentText || currentStyle || currentMeta) || confirm(
`You have made changes in the new brew space. If you continue, that information will be PERMANENTLY LOST.\nAre you sure you wish to continue?`
));
};
const clearLocalStorage = ()=>{
if(!confirmLocalStorageChange()) return;
localStorage.removeItem(BREWKEY);
localStorage.removeItem(STYLEKEY);
localStorage.removeItem(METAKEY);
window.location.href = '/new';
return;
};
return (
<Nav.dropdown>
@@ -50,24 +70,31 @@ const NewBrew = ()=>{
className='new'
color='purple'
icon='fa-solid fa-plus-square'>
new
new
</Nav.item>
<Nav.item
className='fromBlank'
className='new'
href='/new'
newTab={true}
color='purple'
icon='fa-solid fa-file'>
from blank
resume draft
</Nav.item>
<Nav.item
className='fromBlank'
newTab={true}
color='yellow'
icon='fa-solid fa-file-circle-plus'
onClick={()=>{ clearLocalStorage(); }}>
from blank
</Nav.item>
<Nav.item
className='fromFile'
color='purple'
color='green'
icon='fa-solid fa-upload'
onClick={()=>{ document.getElementById('uploadTxt').click(); }}>
<input id='uploadTxt' className='newFromLocal' type='file' onChange={handleFileChange} style={{ display: 'none' }} />
from file
from file
</Nav.item>
</Nav.dropdown>
);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,12 +1,15 @@
.newPage {
.navItem.save {
.fadeInRight();
.transition(opacity);
background-color : @orange;
transition:all 0.2s;
&:hover { background-color : @green; }
&.neverSaved {
.fadeOutRight();
translate:-100%;
opacity: 0;
background-color :#333;
cursor:auto;
}
}
}

View File

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

View File

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

View File

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

299
package-lock.json generated
View File

@@ -1,62 +1,62 @@
{
"name": "homebrewery",
"version": "3.19.3",
"version": "3.20.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "homebrewery",
"version": "3.19.3",
"version": "3.20.0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.28.4",
"@babel/plugin-transform-runtime": "^7.28.3",
"@babel/preset-env": "^7.28.3",
"@babel/preset-react": "^7.27.1",
"@babel/preset-react": "^7.28.5",
"@babel/runtime": "^7.28.4",
"@dmsnell/diff-match-patch": "^1.1.0",
"@googleapis/drive": "^18.0.0",
"@googleapis/drive": "^19.2.0",
"@sanity/diff-match-patch": "^3.2.0",
"body-parser": "^2.2.0",
"classnames": "^2.5.1",
"codemirror": "^5.65.6",
"cookie-parser": "^1.4.7",
"core-js": "^3.46.0",
"core-js": "^3.47.0",
"cors": "^2.8.5",
"create-react-class": "^15.7.0",
"dedent-tabs": "^0.10.3",
"expr-eval": "^2.0.2",
"express": "^5.1.0",
"express": "^5.2.0",
"express-async-handler": "^1.2.0",
"express-static-gzip": "3.0.0",
"fflate": "^0.8.2",
"fs-extra": "11.3.2",
"hash-wasm": "^4.12.0",
"idb-keyval": "^6.2.2",
"js-yaml": "^4.1.0",
"js-yaml": "^4.1.1",
"jwt-simple": "^0.5.6",
"less": "^3.13.1",
"lodash": "^4.17.21",
"marked": "15.0.12",
"marked-alignment-paragraphs": "^1.0.0",
"marked-definition-lists": "^1.0.1",
"marked-emoji": "^2.0.1",
"marked-emoji": "^2.0.2",
"marked-extended-tables": "^2.0.1",
"marked-gfm-heading-id": "^4.1.2",
"marked-gfm-heading-id": "^4.1.3",
"marked-nonbreaking-spaces": "^1.0.1",
"marked-smartypants-lite": "^1.0.3",
"marked-subsuper-text": "^1.0.4",
"marked-variables": "^1.0.4",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.30.1",
"mongoose": "^8.19.1",
"mongoose": "^8.20.0",
"nanoid": "5.1.6",
"nconf": "^0.13.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-frame-component": "^4.1.3",
"react-router": "^7.9.4",
"react-router": "^7.9.6",
"romans": "^3.1.0",
"sanitize-filename": "1.6.3",
"superagent": "^10.2.1",
@@ -66,8 +66,8 @@
"devDependencies": {
"@stylistic/stylelint-plugin": "^4.0.0",
"babel-plugin-transform-import-meta": "^2.3.3",
"eslint": "^9.37.0",
"eslint-plugin-jest": "^29.0.1",
"eslint": "^9.39.1",
"eslint-plugin-jest": "^29.1.0",
"eslint-plugin-react": "^7.37.5",
"globals": "^16.4.0",
"jest": "^30.2.0",
@@ -90,7 +90,6 @@
"integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@csstools/css-calc": "^2.1.3",
"@csstools/css-color-parser": "^3.0.9",
@@ -104,8 +103,7 @@
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true,
"license": "ISC",
"peer": true
"license": "ISC"
},
"node_modules/@babel/code-frame": {
"version": "7.27.1",
@@ -135,6 +133,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@@ -1427,9 +1426,9 @@
}
},
"node_modules/@babel/plugin-transform-react-display-name": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.27.1.tgz",
"integrity": "sha512-p9+Vl3yuHPmkirRrg021XiP+EETmPMQTLr6Ayjj85RLNEbb3Eya/4VI0vAdzQG9SEAl2Lnt7fy5lZyMzjYoZQQ==",
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz",
"integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==",
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.27.1"
@@ -1795,14 +1794,15 @@
}
},
"node_modules/@babel/preset-react": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.27.1.tgz",
"integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==",
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz",
"integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.27.1",
"@babel/helper-validator-option": "^7.27.1",
"@babel/plugin-transform-react-display-name": "^7.27.1",
"@babel/plugin-transform-react-display-name": "^7.28.0",
"@babel/plugin-transform-react-jsx": "^7.27.1",
"@babel/plugin-transform-react-jsx-development": "^7.27.1",
"@babel/plugin-transform-react-pure-annotations": "^7.27.1"
@@ -1920,6 +1920,7 @@
"integrity": "sha512-h0Un1ieD+HUrzBH6dJXhod3ifSghk5Hw/2Y4/KHBziPlZecrFyE9YOTPU6eOs0V9pYl8gOs86fkr/KN8lUX39A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@keyv/serialize": "^1.1.1"
}
@@ -1960,7 +1961,6 @@
}
],
"license": "MIT-0",
"peer": true,
"engines": {
"node": ">=18"
}
@@ -1981,7 +1981,6 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
},
@@ -2006,7 +2005,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"@csstools/color-helpers": "^5.0.2",
"@csstools/css-calc": "^2.1.4"
@@ -2035,6 +2033,7 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
},
@@ -2058,6 +2057,7 @@
}
],
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
}
@@ -2258,9 +2258,9 @@
}
},
"node_modules/@eslint/js": {
"version": "9.39.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.0.tgz",
"integrity": "sha512-BIhe0sW91JGPiaF1mOuPy5v8NflqfjIcDNpC+LbW9f609WVRX1rArrhi6Z2ymvrAry9jw+5POTj4t2t62o8Bmw==",
"version": "9.39.1",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz",
"integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2295,9 +2295,9 @@
}
},
"node_modules/@googleapis/drive": {
"version": "18.0.0",
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-18.0.0.tgz",
"integrity": "sha512-nk4TirsHttwZSOjBEBjltCPDKUqwFso59G3WitNE+EGNVSVseSEq981f8Dmjq2ah0/fk3i206wuCU4PUCwcoTQ==",
"version": "19.2.0",
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-19.2.0.tgz",
"integrity": "sha512-XzhQ+CNwW54umLecZLzQ5Q2RborJD1+u2YzJIT/BOpne+VJfsCyxWVG0nxYQmcGdiFXJPeW5+V3sdP/A/nt3eA==",
"license": "Apache-2.0",
"dependencies": {
"googleapis-common": "^8.0.0"
@@ -3810,6 +3810,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -4509,23 +4510,43 @@
"license": "MIT"
},
"node_modules/body-parser": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
"integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz",
"integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==",
"license": "MIT",
"dependencies": {
"bytes": "^3.1.2",
"content-type": "^1.0.5",
"debug": "^4.4.0",
"debug": "^4.4.3",
"http-errors": "^2.0.0",
"iconv-lite": "^0.6.3",
"iconv-lite": "^0.7.0",
"on-finished": "^2.4.1",
"qs": "^6.14.0",
"raw-body": "^3.0.0",
"type-is": "^2.0.0"
"raw-body": "^3.0.1",
"type-is": "^2.0.1"
},
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/body-parser/node_modules/iconv-lite": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz",
"integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/brace-expansion": {
@@ -4770,6 +4791,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001726",
"electron-to-chromium": "^1.5.173",
@@ -5343,9 +5365,9 @@
}
},
"node_modules/core-js": {
"version": "3.46.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.46.0.tgz",
"integrity": "sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA==",
"version": "3.47.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz",
"integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==",
"hasInstallScript": true,
"license": "MIT",
"funding": {
@@ -5548,7 +5570,6 @@
"integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@asamuzakjp/css-color": "^3.2.0",
"rrweb-cssom": "^0.8.0"
@@ -5578,7 +5599,6 @@
"integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"whatwg-mimetype": "^4.0.0",
"whatwg-url": "^14.0.0"
@@ -5663,8 +5683,7 @@
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz",
"integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/decode-uri-component": {
"version": "0.2.2",
@@ -6016,7 +6035,6 @@
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
"dev": true,
"license": "BSD-2-Clause",
"peer": true,
"engines": {
"node": ">=0.12"
},
@@ -6259,11 +6277,12 @@
}
},
"node_modules/eslint": {
"version": "9.39.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.0.tgz",
"integrity": "sha512-iy2GE3MHrYTL5lrCtMZ0X1KLEKKUjmK0kzwcnefhR66txcEmXZD2YWgR5GNdcEwkNx3a0siYkSvl0vIC+Svjmg==",
"version": "9.39.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz",
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -6271,7 +6290,7 @@
"@eslint/config-helpers": "^0.4.2",
"@eslint/core": "^0.17.0",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "9.39.0",
"@eslint/js": "9.39.1",
"@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
@@ -6319,9 +6338,9 @@
}
},
"node_modules/eslint-plugin-jest": {
"version": "29.0.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.0.1.tgz",
"integrity": "sha512-EE44T0OSMCeXhDrrdsbKAhprobKkPtJTbQz5yEktysNpHeDZTAL1SfDTNKmcFfJkY6yrQLtTKZALrD3j/Gpmiw==",
"version": "29.1.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.1.0.tgz",
"integrity": "sha512-LabxXbASXVjguqL+kBHTPMf3gUeSqwH4fsrEyHTY/MCs42I/p9+ctg09SJpYiD8eGaIsP6GwYr5xW6xWS9XgZg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6622,18 +6641,19 @@
"license": "MIT"
},
"node_modules/express": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz",
"integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/express/-/express-5.2.0.tgz",
"integrity": "sha512-XdpJDLxfztVY59X0zPI6sibRiGcxhTPXRD3IhJmjKf2jwMvkRGV1j7loB8U+heeamoU3XvihAaGRTR4aXXUN3A==",
"license": "MIT",
"dependencies": {
"accepts": "^2.0.0",
"body-parser": "^2.2.0",
"body-parser": "^2.2.1",
"content-disposition": "^1.0.0",
"content-type": "^1.0.5",
"cookie": "^0.7.1",
"cookie-signature": "^1.2.1",
"debug": "^4.4.0",
"depd": "^2.0.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
@@ -7768,7 +7788,6 @@
"integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"whatwg-encoding": "^3.1.1"
},
@@ -7806,28 +7825,23 @@
}
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
"integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"toidentifier": "1.0.1"
"depd": "~2.0.0",
"inherits": "~2.0.4",
"setprototypeof": "~1.2.0",
"statuses": "~2.0.2",
"toidentifier": "~1.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/http-errors/node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/http-proxy-agent": {
@@ -7836,7 +7850,6 @@
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"agent-base": "^7.1.0",
"debug": "^4.3.4"
@@ -7878,6 +7891,7 @@
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
@@ -8433,8 +8447,7 @@
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/is-promise": {
"version": "4.0.0",
@@ -8758,6 +8771,7 @@
"integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@jest/core": "30.2.0",
"@jest/types": "30.2.0",
@@ -9466,9 +9480,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
@@ -10000,6 +10014,7 @@
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz",
"integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==",
"license": "MIT",
"peer": true,
"bin": {
"marked": "bin/marked.js"
},
@@ -10026,12 +10041,12 @@
}
},
"node_modules/marked-emoji": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/marked-emoji/-/marked-emoji-2.0.1.tgz",
"integrity": "sha512-P+nRr02dD+yPOFhtGdaVBzp0qzwlksI2f5GumIdHW/3UadzJ5sVi78CZikiSLr9PmdtUOZodZUBNIO6k38pDMQ==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/marked-emoji/-/marked-emoji-2.0.2.tgz",
"integrity": "sha512-EFnLQn4wTyf+6pXfptkm83Z2mt3VbdEYedHBAsDpwUas5n5satsj42RGqAijBpmetgGerI1EzUuzf7NIccINUQ==",
"license": "MIT",
"peerDependencies": {
"marked": ">=4 <17"
"marked": ">=4 <18"
}
},
"node_modules/marked-extended-tables": {
@@ -10044,15 +10059,15 @@
}
},
"node_modules/marked-gfm-heading-id": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-4.1.2.tgz",
"integrity": "sha512-EQ1WiEGHJh0C8viU+hbXbhHyWTDgEia2i96fiSemm2wdYER6YBw/9QI5TB6YFTqFfmMOxBFXPcPJtlgD0fVV2w==",
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-4.1.3.tgz",
"integrity": "sha512-aR0i63LmFbuxU/gAgrgz1Ir+8HK6zAIFXMlckeKHpV+qKbYaOP95L4Ux5Gi+sKmCZU5qnN2rdKpvpb7PnUBIWg==",
"license": "MIT",
"dependencies": {
"github-slugger": "^2.0.0"
},
"peerDependencies": {
"marked": ">=13 <17"
"marked": ">=13 <18"
}
},
"node_modules/marked-nonbreaking-spaces": {
@@ -10436,9 +10451,9 @@
}
},
"node_modules/mongoose": {
"version": "8.19.2",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.19.2.tgz",
"integrity": "sha512-ww2T4dBV+suCbOfG5YPwj9pLCfUVyj8FEA1D3Ux1HHqutpLxGyOYEPU06iPRBW4cKr3PJfOSYsIpHWPTkz5zig==",
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.20.0.tgz",
"integrity": "sha512-SxqNb8yx+VOjIOx2l7HqkGvYuLC/T85d+jPvqGDdUbKJFz/5PVSsVxQzypQsX7chenYvq5bd8jIr4LtunedE7g==",
"license": "MIT",
"dependencies": {
"bson": "^6.10.4",
@@ -10463,7 +10478,6 @@
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"debug": "4"
},
@@ -10477,7 +10491,6 @@
"integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==",
"license": "Apache-2.0",
"optional": true,
"peer": true,
"dependencies": {
"extend": "^3.0.2",
"https-proxy-agent": "^5.0.0",
@@ -10488,28 +10501,12 @@
"node": ">=12"
}
},
"node_modules/mongoose/node_modules/gcp-metadata": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz",
"integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==",
"license": "Apache-2.0",
"optional": true,
"peer": true,
"dependencies": {
"gaxios": "^5.0.0",
"json-bigint": "^1.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/mongoose/node_modules/https-proxy-agent": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"agent-base": "6",
"debug": "4"
@@ -10570,7 +10567,6 @@
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"whatwg-url": "^5.0.0"
},
@@ -10591,16 +10587,14 @@
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT",
"optional": true,
"peer": true
"optional": true
},
"node_modules/mongoose/node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause",
"optional": true,
"peer": true
"optional": true
},
"node_modules/mongoose/node_modules/whatwg-url": {
"version": "5.0.0",
@@ -10608,7 +10602,6 @@
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
@@ -10988,8 +10981,7 @@
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.20.tgz",
"integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/object-assign": {
"version": "4.1.1",
@@ -11357,7 +11349,6 @@
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"entities": "^6.0.0"
},
@@ -11672,6 +11663,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -11734,6 +11726,7 @@
"integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -11748,7 +11741,6 @@
"integrity": "sha512-Mn8KJ45HNNG6JBpBizXcyf6LqY/qyqetGcou/nprDnFwBFBLGj0j/sNKV2lj2KMOVOwdXu14aEzqJv8CIV6e8g==",
"dev": true,
"license": "MIT",
"peer": true,
"peerDependencies": {
"postcss": "^8.4.20"
}
@@ -11837,6 +11829,7 @@
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@@ -12007,18 +12000,34 @@
}
},
"node_modules/raw-body": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
"integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
"integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.6.3",
"unpipe": "1.0.0"
"bytes": "~3.1.2",
"http-errors": "~2.0.1",
"iconv-lite": "~0.7.0",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
"node": ">= 0.10"
}
},
"node_modules/raw-body/node_modules/iconv-lite": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz",
"integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/react": {
@@ -12026,6 +12035,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -12038,6 +12048,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -12065,9 +12076,9 @@
"license": "MIT"
},
"node_modules/react-router": {
"version": "7.9.5",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.5.tgz",
"integrity": "sha512-JmxqrnBZ6E9hWmf02jzNn9Jm3UqyeimyiwzD69NjxGySG6lIz/1LVPsoTCwN7NBX2XjCEa1LIX5EMz1j2b6u6A==",
"version": "7.9.6",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.6.tgz",
"integrity": "sha512-Y1tUp8clYRXpfPITyuifmSoE2vncSME18uVLgaqyxh9H35JWpIfzHo+9y3Fzh5odk/jxPW29IgLgzcdwxGqyNA==",
"license": "MIT",
"dependencies": {
"cookie": "^1.0.1",
@@ -12530,8 +12541,7 @@
"resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz",
"integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/run-parallel": {
"version": "1.2.0",
@@ -12662,7 +12672,6 @@
"integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
"dev": true,
"license": "ISC",
"peer": true,
"dependencies": {
"xmlchars": "^2.2.0"
},
@@ -13605,6 +13614,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"@csstools/css-parser-algorithms": "^3.0.5",
"@csstools/css-tokenizer": "^3.0.4",
@@ -13884,8 +13894,7 @@
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/synckit": {
"version": "0.11.11",
@@ -14001,7 +14010,6 @@
"integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"tldts-core": "^6.1.86"
},
@@ -14014,8 +14022,7 @@
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz",
"integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/tmpl": {
"version": "1.0.5",
@@ -14176,7 +14183,6 @@
"integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
"dev": true,
"license": "BSD-3-Clause",
"peer": true,
"dependencies": {
"tldts": "^6.1.32"
},
@@ -14742,7 +14748,8 @@
},
"node_modules/vitreum": {
"version": "6.0.4",
"resolved": "git+https://git@github.com/calculuschild/vitreum.git#9d55fd6fb7e85e7070de798c4f9d5b983c1b7dba",
"resolved": "git+https://git@github.com/calculuschild/vitreum.git#929c351881c4229550374421c7e2890a94f4dca7",
"integrity": "sha512-dclfZIgvZU4pOeju1U7CjfGcAMNY+HwhYxF5O1cB6j9EtBrUXQh5+8XlYvNrw2XIcjWIxWcWaCpAQgJxKssfbQ==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@@ -14799,7 +14806,6 @@
"integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"xml-name-validator": "^5.0.0"
},
@@ -15149,7 +15155,6 @@
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"iconv-lite": "0.6.3"
},
@@ -15163,7 +15168,6 @@
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=18"
}
@@ -15374,7 +15378,6 @@
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=10.0.0"
},
@@ -15397,7 +15400,6 @@
"integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"engines": {
"node": ">=18"
}
@@ -15407,8 +15409,7 @@
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/xtend": {
"version": "4.0.2",

View File

@@ -1,7 +1,7 @@
{
"name": "homebrewery",
"description": "Create authentic looking D&D homebrews using only markdown",
"version": "3.19.3",
"version": "3.20.0",
"type": "module",
"engines": {
"npm": "^10.8.x",
@@ -88,50 +88,50 @@
"@babel/core": "^7.28.4",
"@babel/plugin-transform-runtime": "^7.28.3",
"@babel/preset-env": "^7.28.3",
"@babel/preset-react": "^7.27.1",
"@babel/preset-react": "^7.28.5",
"@babel/runtime": "^7.28.4",
"@dmsnell/diff-match-patch": "^1.1.0",
"@googleapis/drive": "^18.0.0",
"@googleapis/drive": "^19.2.0",
"@sanity/diff-match-patch": "^3.2.0",
"body-parser": "^2.2.0",
"classnames": "^2.5.1",
"codemirror": "^5.65.6",
"cookie-parser": "^1.4.7",
"core-js": "^3.46.0",
"core-js": "^3.47.0",
"cors": "^2.8.5",
"create-react-class": "^15.7.0",
"dedent-tabs": "^0.10.3",
"expr-eval": "^2.0.2",
"express": "^5.1.0",
"express": "^5.2.0",
"express-async-handler": "^1.2.0",
"express-static-gzip": "3.0.0",
"fflate": "^0.8.2",
"fs-extra": "11.3.2",
"hash-wasm": "^4.12.0",
"idb-keyval": "^6.2.2",
"js-yaml": "^4.1.0",
"js-yaml": "^4.1.1",
"jwt-simple": "^0.5.6",
"less": "^3.13.1",
"lodash": "^4.17.21",
"marked": "15.0.12",
"marked-alignment-paragraphs": "^1.0.0",
"marked-definition-lists": "^1.0.1",
"marked-emoji": "^2.0.1",
"marked-emoji": "^2.0.2",
"marked-extended-tables": "^2.0.1",
"marked-gfm-heading-id": "^4.1.2",
"marked-gfm-heading-id": "^4.1.3",
"marked-nonbreaking-spaces": "^1.0.1",
"marked-smartypants-lite": "^1.0.3",
"marked-subsuper-text": "^1.0.4",
"marked-variables": "^1.0.4",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.30.1",
"mongoose": "^8.19.1",
"mongoose": "^8.20.0",
"nanoid": "5.1.6",
"nconf": "^0.13.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-frame-component": "^4.1.3",
"react-router": "^7.9.4",
"react-router": "^7.9.6",
"romans": "^3.1.0",
"sanitize-filename": "1.6.3",
"superagent": "^10.2.1",
@@ -141,8 +141,8 @@
"devDependencies": {
"@stylistic/stylelint-plugin": "^4.0.0",
"babel-plugin-transform-import-meta": "^2.3.3",
"eslint": "^9.37.0",
"eslint-plugin-jest": "^29.0.1",
"eslint": "^9.39.1",
"eslint-plugin-jest": "^29.1.0",
"eslint-plugin-react": "^7.37.5",
"globals": "^16.4.0",
"jest": "^30.2.0",

View File

@@ -6,6 +6,7 @@ import config from './config.js';
let serviceAuth;
let clientEmail;
if(!config.get('service_account')){
const reset = '\x1b[0m'; // Reset to default style
const yellow = '\x1b[33m'; // yellow color
@@ -15,6 +16,10 @@ if(!config.get('service_account')){
JSON.parse(config.get('service_account')) :
config.get('service_account');
if(keys?.client_email) {
clientEmail = keys.client_email;
}
try {
serviceAuth = googleDrive.auth.fromJSON(keys);
serviceAuth.scopes = ['https://www.googleapis.com/auth/drive'];
@@ -227,14 +232,30 @@ const GoogleActions = {
if(!obj) return;
if(clientEmail) {
await drive.permissions.create({
resource : {
type : 'user',
emailAddress : clientEmail,
role : 'writer'
},
fileId : obj.data.id,
fields : 'id',
})
.catch((err)=>{
console.log('Error adding Service Account permissions on Google Drive file');
console.error(err);
});
}
await drive.permissions.create({
resource : { type : 'anyone',
role : 'writer' },
role : 'writer' },
fileId : obj.data.id,
fields : 'id',
})
.catch((err)=>{
console.log('Error updating permissions');
console.log('Error adding "Anyone" permissions on Google Drive file');
console.error(err);
});

View File

@@ -31,7 +31,12 @@ renderer.html = function (token) {
const openTag = html.substring(0, html.indexOf('>')+1);
html = html.substring(html.indexOf('>')+1);
html = html.substring(0, html.lastIndexOf('</div>'));
return `${openTag} ${Marked.parse(html)} </div>`;
// Repeat the markdown processing for content inside the div, minus the preprocessing and postprocessing hooks which should only run once globally
const opts = Marked.defaults;
const tokens = Marked.lexer(html, opts);
Marked.walkTokens(tokens, opts.walkTokens);
return `${openTag} ${Marked.parser(tokens, opts)} </div>`;
}
return html;
};

View File

@@ -492,7 +492,7 @@ body { counter-reset : page-numbers 0; }
.pageNumber { left : 30px; }
}
.resetCounting { counter-set : page-numbers 1; }
&:has(.resetCounting) { counter-set : page-numbers 1; }
&:not(:has(.skipCounting)) { counter-increment : page-numbers; }

View File

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

View File

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