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

Compare commits

...

91 Commits

Author SHA1 Message Date
dependabot[bot]
5882328326 Bump react from 18.3.1 to 19.2.0
Bumps [react](https://github.com/facebook/react/tree/HEAD/packages/react) from 18.3.1 to 19.2.0.
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.0/packages/react)

---
updated-dependencies:
- dependency-name: react
  dependency-version: 19.2.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-17 12:50:25 +00:00
Víctor Losada Hernández
05ffd97f3a Merge pull request #4473 from naturalcrit/dependabot/npm_and_yarn/googleapis/drive-18.0.0
Bump @googleapis/drive from 13.0.1 to 18.0.0
2025-10-17 14:49:01 +02:00
Víctor Losada Hernández
b120bac424 Merge branch 'master' into dependabot/npm_and_yarn/googleapis/drive-18.0.0 2025-10-17 14:42:15 +02:00
Trevor Buckner
a9280b65ee Merge pull request #4445 from dbolack-ab/issue_4201
Regex for parsing mustache blocks does not allow some expected characters - take 2
2025-10-16 21:35:02 -04:00
David Bolack
7e4facb478 Remove greater than and less than from evaluation.
Use calc's more concise regex

Remove errant space.
2025-10-16 10:45:00 -05:00
David Bolack
c9f1413a2d Merge branch 'master' into issue_4201 2025-10-16 10:34:26 -05:00
Trevor Buckner
85252abeb5 Merge pull request #4478 from 5e-Cleric/fix-footer-text
Add uppercase style to footnotes
2025-10-15 17:14:32 -04:00
Trevor Buckner
ac583c64bc Merge branch 'master' into fix-footer-text 2025-10-15 17:12:46 -04:00
Trevor Buckner
de75100200 Merge pull request #4476 from 5e-Cleric/fix-googleId-error
handle getid uncatched error
2025-10-15 17:09:17 -04:00
Trevor Buckner
d8aabb2f57 Merge branch 'master' into fix-googleId-error 2025-10-15 17:08:23 -04:00
Trevor Buckner
a823034d6e Merge pull request #4479 from 5e-Cleric/bring-some-visibility-to-the-search-bar
Increase visibility of the search bar
2025-10-15 17:07:52 -04:00
Trevor Buckner
aa2362d822 Merge branch 'master' into bring-some-visibility-to-the-search-bar 2025-10-15 17:07:00 -04:00
Trevor Buckner
2b58bf49d0 Merge pull request #4480 from 5e-Cleric/fix-cursor-on-navigation
Fix cursor on head navigation
2025-10-15 17:06:05 -04:00
Víctor Losada Hernández
11d3cddff0 Revert "initial commit"
This reverts commit 3c3ca7981b.
2025-10-15 22:25:36 +02:00
Víctor Losada Hernández
47c84428c7 initial commit 2025-10-15 22:24:45 +02:00
Víctor Losada Hernández
3c3ca7981b initial commit 2025-10-15 22:24:07 +02:00
Víctor Losada Hernández
d728126480 initial commit 2025-10-15 22:01:13 +02:00
Víctor Losada Hernández
27861ba796 add uppercase style to footnotes 2025-10-15 21:50:01 +02:00
Víctor Losada Hernández
3f29eb227a next for throw 2025-10-15 21:22:45 +02:00
Víctor Losada Hernández
f604d0a41f handle getid uncatched error 2025-10-15 20:52:34 +02:00
dependabot[bot]
9f48755f80 Bump @googleapis/drive from 13.0.1 to 18.0.0
Bumps [@googleapis/drive](https://github.com/googleapis/google-api-nodejs-client) from 13.0.1 to 18.0.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/iam-v13.0.1...run-v18.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-14 03:03:35 +00:00
Trevor Buckner
33f5d26b39 Merge pull request #4449 from dbolack-ab/d100-dicefont
Alternate Add d100/percentage support to dicefont icons
2025-10-13 20:11:30 -04:00
Trevor Buckner
3ad463cff7 Merge branch 'master' into d100-dicefont 2025-10-13 20:10:54 -04:00
Trevor Buckner
6c8265688f Restore missing empty d10 2025-10-13 20:10:31 -04:00
Trevor Buckner
d1f5c9da0d Update diceFont.less to use DiceFont100 instead of dicefont-percent 2025-10-13 20:06:13 -04:00
Trevor Buckner
43e465ceb8 Rename font to match format of existing diceFont font file. 2025-10-13 20:05:42 -04:00
Trevor Buckner
b864e9b677 Update diceFont.js to use d10 instead of dper 2025-10-13 20:05:09 -04:00
Víctor Losada Hernández
28e02f1863 Merge pull request #4466 from naturalcrit/dependabot/npm_and_yarn/prod-dependencies-f151d22b6b
Bump the prod-dependencies group across 1 directory with 10 updates
2025-10-13 23:50:02 +02:00
dependabot[bot]
333614f866 Bump the prod-dependencies group across 1 directory with 10 updates
Bumps the prod-dependencies group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) | `7.28.0` | `7.28.4` |
| [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) | `7.28.0` | `7.28.3` |
| [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) | `7.28.0` | `7.28.3` |
| [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) | `7.27.6` | `7.28.4` |
| [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) | `3.44.0` | `3.46.0` |
| [fs-extra](https://github.com/jprichardson/node-fs-extra) | `11.3.0` | `11.3.2` |
| [marked-subsuper-text](https://github.com/naturalcrit/marked-subsuper-text) | `1.0.3` | `1.0.4` |
| [mongoose](https://github.com/Automattic/mongoose) | `8.16.3` | `8.19.1` |
| [nanoid](https://github.com/ai/nanoid) | `5.1.5` | `5.1.6` |
| [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router) | `7.6.3` | `7.9.4` |



Updates `@babel/core` from 7.28.0 to 7.28.4
- [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.4/packages/babel-core)

Updates `@babel/plugin-transform-runtime` from 7.28.0 to 7.28.3
- [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.3/packages/babel-plugin-transform-runtime)

Updates `@babel/preset-env` from 7.28.0 to 7.28.3
- [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.3/packages/babel-preset-env)

Updates `@babel/runtime` from 7.27.6 to 7.28.4
- [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.4/packages/babel-runtime)

Updates `core-js` from 3.44.0 to 3.46.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.46.0/packages/core-js)

Updates `fs-extra` from 11.3.0 to 11.3.2
- [Changelog](https://github.com/jprichardson/node-fs-extra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jprichardson/node-fs-extra/compare/11.3.0...11.3.2)

Updates `marked-subsuper-text` from 1.0.3 to 1.0.4
- [Changelog](https://github.com/naturalcrit/marked-subsuper-text/blob/main/release.config.cjs)
- [Commits](https://github.com/naturalcrit/marked-subsuper-text/commits)

Updates `mongoose` from 8.16.3 to 8.19.1
- [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.16.3...8.19.1)

Updates `nanoid` from 5.1.5 to 5.1.6
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/5.1.5...5.1.6)

Updates `react-router` from 7.6.3 to 7.9.4
- [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.4/packages/react-router)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-version: 7.28.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-dependencies
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-version: 7.28.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-dependencies
- dependency-name: "@babel/preset-env"
  dependency-version: 7.28.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-dependencies
- dependency-name: "@babel/runtime"
  dependency-version: 7.28.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-dependencies
- dependency-name: core-js
  dependency-version: 3.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-dependencies
- dependency-name: fs-extra
  dependency-version: 11.3.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-dependencies
- dependency-name: marked-subsuper-text
  dependency-version: 1.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-dependencies
- dependency-name: mongoose
  dependency-version: 8.19.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-dependencies
- dependency-name: nanoid
  dependency-version: 5.1.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: prod-dependencies
- dependency-name: react-router
  dependency-version: 7.9.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: prod-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 21:45:46 +00:00
Trevor Buckner
efc8561447 Merge pull request #4450 from dbolack-ab/issue_2963
Keep the cursor in the active view page after a divider width change.
2025-10-13 13:40:47 -04:00
Trevor Buckner
9e80151eda Merge branch 'master' into issue_2963 2025-10-13 13:38:41 -04:00
Trevor Buckner
d695f8f7bc Merge pull request #4469 from 5e-Cleric/remove-config-enable-checks
Remove enable_themes and enable_v3 checks
2025-10-13 13:37:58 -04:00
Trevor Buckner
ae47442ed5 Merge branch 'master' into remove-config-enable-checks 2025-10-13 13:37:49 -04:00
Víctor Losada Hernández
34ee1853e1 Merge pull request #4459 from naturalcrit/dependabot/npm_and_yarn/dev-dependencies-8d5f5caba3
Bump the dev-dependencies group across 1 directory with 4 updates
2025-10-13 17:46:58 +02:00
David Bolack
fbf0d425e2 Don't pass isDragging to splitpane children. 2025-10-11 09:07:23 -05:00
David Bolack
8fcadd87d4 Remove comments 2025-10-09 20:24:01 -05:00
David Bolack
2de151d348 Rename font 2025-10-09 19:31:30 -05:00
David Bolack
1eff2dbedd Change dpercent to d10 2025-10-09 19:25:40 -05:00
dependabot[bot]
4ccec08f21 Bump the dev-dependencies group across 1 directory with 4 updates
Bumps the dev-dependencies group with 4 updates in the / directory: [eslint](https://github.com/eslint/eslint), [globals](https://github.com/sindresorhus/globals), [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest) and [stylelint](https://github.com/stylelint/stylelint).


Updates `eslint` from 9.35.0 to 9.37.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.35.0...v9.37.0)

Updates `globals` from 16.3.0 to 16.4.0
- [Release notes](https://github.com/sindresorhus/globals/releases)
- [Commits](https://github.com/sindresorhus/globals/compare/v16.3.0...v16.4.0)

Updates `jest` from 30.1.3 to 30.2.0
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.2.0/packages/jest)

Updates `stylelint` from 16.24.0 to 16.25.0
- [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.24.0...16.25.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-version: 9.37.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: globals
  dependency-version: 16.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: jest
  dependency-version: 30.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
- dependency-name: stylelint
  dependency-version: 16.25.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-07 03:01:39 +00:00
Trevor Buckner
3be62bd254 Merge pull request #4448 from G-Ambatte/addDBCheckMiddleware
Add DB check middleware
2025-10-06 14:20:28 -04:00
G.Ambatte
0d38b8607e Shift to router.use(dbCheck) instead of defining on every route 2025-10-06 18:51:05 +13:00
G.Ambatte
5e35ae0c8b Merge branch 'master' into addDBCheckMiddleware 2025-10-06 18:12:40 +13:00
Trevor Buckner
5f72dd2023 Merge pull request #4462 from naturalcrit/PreventInterruptedBrewJump
Move badly-placed scrollingTimeout that was doing nothing
2025-10-06 00:07:50 -04:00
Trevor Buckner
7fc03bb5a7 Merge branch 'master' into PreventInterruptedBrewJump 2025-10-06 00:07:43 -04:00
Trevor Buckner
ccf11661de Merge pull request #4461 from naturalcrit/LintEverythingOct2025
Lint everything
2025-10-06 00:07:29 -04:00
Trevor Buckner
811f274968 Move badly-placed scrollingTimeout that was doing nothing
When a user clicks brewJump or sourceJump, we disallow new jumps until the current scroll operation has finished for 150 ms. Unfortunately the timer being checked was always undefined, so you could keep clicking the jump button and get the brewRenderer or editor to keep bouncing around without finishing the jump action.

This just moves the scrollingTimeout up outside of the listener function so it isn't being reset to undefined every loop.
2025-10-06 00:06:34 -04:00
Trevor Buckner
63bebe1efd Lint everything
Catching up on a bunch of linting so random changes stop showing up on PRs when the linter is run.
2025-10-06 00:02:24 -04:00
G.Ambatte
8b2c8c0feb Merge branch 'master' into addDBCheckMiddleware 2025-10-06 16:48:37 +13:00
Trevor Buckner
22e26d635a Merge pull request #4460 from naturalcrit/cleanupLocalStorageKeysTest
Clean up localStorageMap code
2025-10-05 23:28:34 -04:00
Víctor Losada Hernández
4a5bb1efb1 initial commit 2025-10-05 22:14:13 +02:00
David Bolack
460b12e356 Proposed fix per calc.
This also works but has different currsor behavior.

Original fix left in place, commented pending decisions.
2025-10-05 11:26:43 -05:00
G.Ambatte
c17a5e72b9 Switch to Calc's simplified test spec 2025-10-05 15:40:40 +13:00
G.Ambatte
88bc9b79c9 Add new error message to nav bar error container 2025-10-05 15:31:53 +13:00
G.Ambatte
a14ea89562 Post-merge cleanup 2025-10-05 15:31:04 +13:00
G.Ambatte
bb0a840113 Fix HBErrorCode to string, not number 2025-10-05 15:30:47 +13:00
G.Ambatte
d40f8ff380 Merge branch 'master' into addDBCheckMiddleware 2025-10-05 14:58:56 +13:00
David Bolack
99a85ccbca Merge branch 'master' into issue_2963 2025-10-03 18:57:51 -05:00
David Bolack
5ae2f3fff7 Merge branch 'master' into d100-dicefont 2025-10-03 18:55:15 -05:00
David Bolack
8bc5f7312e Merge branch 'master' into issue_4201 2025-10-03 18:47:54 -05:00
G.Ambatte
2b138e56db Add dbCheck middleware to app.js routes that use DB 2025-10-04 12:29:06 +13:00
G.Ambatte
f141c0bebd Move dbCheck to only API calls that touch the database 2025-10-02 19:28:10 +13:00
G.Ambatte
7c050fb9a9 Merge branch 'master' into addDBCheckMiddleware 2025-09-27 22:00:30 +12:00
David Bolack
da134ffdcc Merge branch 'master' into d100-dicefont 2025-09-22 20:43:48 -05:00
David Bolack
a9b7a37c1b Merge branch 'master' into issue_2963 2025-09-22 20:37:32 -05:00
David Bolack
0ab882a33c Merge branch 'master' into issue_4201 2025-09-22 20:35:42 -05:00
G.Ambatte
917153e154 Merge branch 'master' into addDBCheckMiddleware 2025-09-03 19:13:45 +12:00
G.Ambatte
d6a7d0272a Update dbCheck test 2025-09-02 21:08:15 +12:00
G.Ambatte
4fca207e0e Change error result to use Error Page 2025-09-02 20:58:08 +12:00
G.Ambatte
d171077798 Merge branch 'master' into addDBCheckMiddleware 2025-09-02 20:51:12 +12:00
David Bolack
fdd4b3c1d5 Remove braces from consideration 2025-08-30 18:07:11 -05:00
David Bolack
785af639c7 Keep the cursor as close to the same place on the screen as possible. 2025-07-30 13:04:16 -05:00
David Bolack
4aadb0b238 Keep the cursor in the active view page after a divider width change.
Solves #2963
2025-07-30 12:28:06 -05:00
G.Ambatte
005c05376c Add DB connection/disconnections events to log 2025-07-26 14:11:20 +12:00
G.Ambatte
7af22c9da7 Return a basic error message when DB connection is lost 2025-07-26 12:13:59 +12:00
David Bolack
4b2142b00b Merge branch 'd100-dicefont' of github.com:dbolack-ab/homebrewery into d100-dicefont 2025-07-23 20:23:42 -05:00
David Bolack
fd8cc8d1a1 Merge branch 'master' into d100-dicefont 2025-07-23 20:23:22 -05:00
Trevor Buckner
1ae37e3a27 Merge branch 'master' into d100-dicefont 2025-07-15 17:00:07 -04:00
David Bolack
11335f0bda Merge branch 'd100-dicefont' of github.com:dbolack-ab/homebrewery into d100-dicefont 2025-06-30 10:56:04 -05:00
David Bolack
60b1ee7db8 Merge branch 'master' into d100-dicefont 2025-06-30 10:55:23 -05:00
Víctor Losada Hernández
b915584f59 Merge branch 'master' into d100-dicefont 2025-06-25 16:45:36 +02:00
David Bolack
0ab56788c1 Move d100 Source files 2025-05-11 18:39:25 -05:00
David Bolack
4d8ab13101 Merge branch 'master' into d100-dicefont 2025-05-11 18:33:36 -05:00
David Bolack
99d5c1b9e3 Merge branch 'd100-dicefont' of github.com:dbolack-ab/homebrewery into d100-dicefont 2025-05-11 18:33:31 -05:00
David Bolack
1a52347e9b Tweaked the Image source to use one for 2 digit numbers and one for centered numbers.
These results are much better.

Renamed the resulting face

subbed in d10s generated from teh same souce so they would match.
2025-05-11 18:31:45 -05:00
Víctor Losada Hernández
2ed17e44e4 Merge branch 'master' into d100-dicefont 2025-05-11 15:54:35 +02:00
David Bolack
a2dd8af6d7 Merge branch 'd100-dicefont' of github.com:dbolack-ab/homebrewery into d100-dicefont 2025-05-10 12:28:05 -05:00
David Bolack
f7e4e1aa2a Merge branch 'master' into d100-dicefont 2025-05-10 12:27:45 -05:00
David Bolack
f6869d9c13 Merge branch 'master' into d100-dicefont 2025-05-10 12:27:05 -05:00
David Bolack
6aa35de27e Add scripting for bus insurance. 2025-05-10 12:26:26 -05:00
Víctor Losada Hernández
5de7ea368e Merge branch 'master' into d100-dicefont 2025-05-08 13:49:48 +02:00
David Bolack
26a5cb9fab Add a percentile on single die representation to dicefont.
This is added as a new icon but inlined with the df icons for user conveniance.

used dper instead of dpercent for ease of use.
2025-04-19 22:47:33 -05:00
29 changed files with 1401 additions and 626 deletions

View File

@@ -47,9 +47,7 @@ Make an changes you need to `config/docker.json` then build the image. If it doe
"naturalcrit_url" : "local.naturalcrit.com:8010",
"secret" : "secret",
"web_port" : 8000,
"enable_v3" : true,
"mongodb_uri": "mongodb://172.17.0.2/homebrewery",
"enable_themes" : true
}
```

View File

@@ -325,10 +325,10 @@ const Editor = createClass({
const brewRenderer = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer')[0];
const currentPos = brewRenderer.scrollTop;
const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top;
const checkIfScrollComplete = ()=>{
let scrollingTimeout;
clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs
let scrollingTimeout;
const checkIfScrollComplete = ()=>{ // Prevent interrupting a scroll in progress if user clicks multiple times
clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs
scrollingTimeout = setTimeout(()=>{
isJumping = false;
brewRenderer.removeEventListener('scroll', checkIfScrollComplete);
@@ -369,8 +369,8 @@ const Editor = createClass({
let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top;
let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true);
const checkIfScrollComplete = ()=>{
let scrollingTimeout;
let scrollingTimeout;
const checkIfScrollComplete = ()=>{ // Prevent interrupting a scroll in progress if user clicks multiple times
clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs
scrollingTimeout = setTimeout(()=>{
isJumping = false;
@@ -409,7 +409,6 @@ const Editor = createClass({
//Called when there are changes to the editor's dimensions
update : function(){
this.codeEditor.current?.updateSize();
const snipHeight = document.querySelector('.editor > .snippetBar').offsetHeight;
if(snipHeight !== this.state.snippetbarHeight)
this.setState({ snippetbarHeight: snipHeight });

View File

@@ -207,8 +207,6 @@ const MetadataEditor = createClass({
},
renderThemeDropdown : function(){
if(!global.enable_themes) return;
const mergedThemes = _.merge(Themes, this.props.userThemes);
const listThemes = (renderer)=>{
@@ -307,8 +305,6 @@ const MetadataEditor = createClass({
},
renderRenderOptions : function(){
if(!global.enable_v3) return;
return <div className='field systems'>
<label>Renderer</label>
<div className='value'>

View File

@@ -18,7 +18,7 @@ module.exports = {
try {
Boolean(new URL(value));
return null;
} catch (e) {
} catch {
return 'Must be a valid URL';
}
}

View File

@@ -27,8 +27,6 @@ const Homebrew = (props)=>{
url = '',
version = '0.0.0',
account = null,
enable_v3 = false,
enable_themes,
config,
brew = {
title : '',
@@ -45,8 +43,6 @@ const Homebrew = (props)=>{
global.account = account;
global.version = version;
global.enable_v3 = enable_v3;
global.enable_themes = enable_themes;
global.config = config;
const backgroundObject = ()=>{

View File

@@ -2,9 +2,9 @@ require('./error-navitem.less');
const React = require('react');
const Nav = require('naturalcrit/nav/nav.jsx');
const ErrorNavItem = ({error = '', clearError})=>{
const ErrorNavItem = ({ error = '', clearError })=>{
const response = error.response;
const errorCode = error.code
const errorCode = error.code;
const status = response?.status;
const HBErrorCode = response?.body?.HBErrorCode;
const message = response?.body?.message;
@@ -15,7 +15,7 @@ const ErrorNavItem = ({error = '', clearError})=>{
errMsg += `\`\`\`\n${error.stack}\n`;
errMsg += `${JSON.stringify(response?.error, null, ' ')}\n\`\`\``;
console.log(errMsg);
} catch (e){}
} catch {}
if(status === 409) {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
@@ -112,6 +112,15 @@ const ErrorNavItem = ({error = '', clearError})=>{
</Nav.item>;
}
if(HBErrorCode === '13') {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
Server has lost connection to the database.
</div>
</Nav.item>;
}
if(errorCode === 'ECONNABORTED') {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!

View File

@@ -37,7 +37,10 @@
&:has(.brewTitle) {
flex-grow : 1;
min-width : 300px;
min-width : 300px;
}
>.brewTitle {
cursor:auto;
}
}
// "NaturalCrit" logo

View File

@@ -34,8 +34,8 @@ const NewBrew = ()=>{
}
const type = file.name.split('.').pop().toLowerCase();
alert(`This file is invalid: ${!type ? "Missing file extension" :`.${type} files are not supported`}. Only .txt files exported from the Homebrewery 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);

View File

@@ -2,22 +2,22 @@ import React from 'react';
import dedent from 'dedent-tabs';
import Nav from 'naturalcrit/nav/nav.jsx';
const getShareId = (brew)=>(
brew.googleId && !brew.stubbed
? brew.googleId + brew.shareId
: brew.shareId
);
const getShareId = (brew)=>(
brew.googleId && !brew.stubbed
? brew.googleId + brew.shareId
: brew.shareId
);
const getRedditLink = (brew)=>{
const text = dedent`
const getRedditLink = (brew)=>{
const text = dedent`
Hey guys! I've been working on this homebrew. I'd love your feedback. Check it out.
**[Homebrewery Link](${global.config.baseUrl}/share/${getShareId(brew)})**`;
return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(brew.title.toWellFormed())}&text=${encodeURIComponent(text)}`;
};
return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(brew.title.toWellFormed())}&text=${encodeURIComponent(text)}`;
};
export default ({brew}) => (
export default ({ brew })=>(
<Nav.dropdown>
<Nav.item color='teal' icon='fas fa-share-alt'>
share

View File

@@ -123,16 +123,16 @@ const EditPage = (props)=>{
editorRef.current?.update();
};
const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata'
if (subfield == 'renderer' || subfield == 'theme')
const handleBrewChange = (field)=>(value, subfield)=>{ //'text', 'style', 'snippets', 'metadata'
if(subfield == 'renderer' || subfield == 'theme')
fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme);
//If there are HTML errors, run the validator on every change to give quick feedback
if(HTMLErrors.length && (field == 'text' || field == 'snippets'))
setHTMLErrors(Markdown.validate(value));
if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value }));
else setCurrentBrew(prev => ({ ...prev, [field]: value }));
if(field == 'metadata') setCurrentBrew((prev)=>({ ...prev, ...value }));
else setCurrentBrew((prev)=>({ ...prev, [field]: value }));
if(useLocalStorage) {
if(field == 'text') localStorage.setItem(BREWKEY, value);

View File

@@ -196,6 +196,12 @@ const errorIndex = (props)=>{
**Brew ID:** ${props.brew.brewId}`,
// Database Connection Lost
'13' : dedent`
## Database connection has been lost.
The server could not communicate with the database.`,
//account page when account is not defined
'50' : dedent`
## You are not signed in

View File

@@ -39,8 +39,8 @@ const HomePage =(props)=>{
props = {
brew : DEFAULT_BREW,
ver : '0.0.0',
...props
};
...props
};
const [currentBrew , setCurrentBrew] = useState(props.brew);
const [error , setError] = useState(undefined);
@@ -71,7 +71,7 @@ const HomePage =(props)=>{
document.addEventListener('keydown', handleControlKeys);
return () => {
return ()=>{
document.removeEventListener('keydown', handleControlKeys);
};
}, []);
@@ -100,16 +100,16 @@ const HomePage =(props)=>{
editorRef.current.update();
};
const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata'
if (subfield == 'renderer' || subfield == 'theme')
const handleBrewChange = (field)=>(value, subfield)=>{ //'text', 'style', 'snippets', 'metadata'
if(subfield == 'renderer' || subfield == 'theme')
fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme);
//If there are HTML errors, run the validator on every change to give quick feedback
if(HTMLErrors.length && (field == 'text' || field == 'snippets'))
setHTMLErrors(Markdown.validate(value));
if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value }));
else setCurrentBrew(prev => ({ ...prev, [field]: value }));
if(field == 'metadata') setCurrentBrew((prev)=>({ ...prev, ...value }));
else setCurrentBrew((prev)=>({ ...prev, [field]: value }));
if(useLocalStorage) {
if(field == 'text') localStorage.setItem(BREWKEY, value);
@@ -218,7 +218,7 @@ const HomePage =(props)=>{
Create your own <i className='fas fa-magic' />
</a>
</div>
)
);
};
module.exports = HomePage;

View File

@@ -36,9 +36,9 @@ const SAVEKEYPREFIX = 'HB_editor_defaultSave_';
const useLocalStorage = true;
const neverSaved = true;
const NewPage = (props) => {
const NewPage = (props)=>{
props = {
brew: DEFAULT_BREW,
brew : DEFAULT_BREW,
...props
};
@@ -57,7 +57,7 @@ const NewPage = (props) => {
const editorRef = useRef(null);
const lastSavedBrew = useRef(_.cloneDeep(props.brew));
useEffect(() => {
useEffect(()=>{
loadBrew();
fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme);
@@ -73,7 +73,7 @@ const NewPage = (props) => {
document.addEventListener('keydown', handleControlKeys);
return () => {
return ()=>{
document.removeEventListener('keydown', handleControlKeys);
};
}, []);
@@ -118,16 +118,16 @@ const NewPage = (props) => {
editorRef.current.update();
};
const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata'
if (subfield == 'renderer' || subfield == 'theme')
const handleBrewChange = (field)=>(value, subfield)=>{ //'text', 'style', 'snippets', 'metadata'
if(subfield == 'renderer' || subfield == 'theme')
fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme);
//If there are HTML errors, run the validator on every change to give quick feedback
if(HTMLErrors.length && (field == 'text' || field == 'snippets'))
setHTMLErrors(Markdown.validate(value));
if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value }));
else setCurrentBrew(prev => ({ ...prev, [field]: value }));
if(field == 'metadata') setCurrentBrew((prev)=>({ ...prev, ...value }));
else setCurrentBrew((prev)=>({ ...prev, [field]: value }));
if(useLocalStorage) {
if(field == 'text') localStorage.setItem(BREWKEY, value);
@@ -141,10 +141,10 @@ const NewPage = (props) => {
}
};
const save = async () => {
const save = async ()=>{
setIsSaving(true);
let updatedBrew = { ...currentBrew };
const updatedBrew = { ...currentBrew };
splitTextStyleAndMetadata(updatedBrew);
const pageRegex = updatedBrew.renderer === 'legacy' ? /\\page/g : /^\\page$/gm;
@@ -153,13 +153,13 @@ const NewPage = (props) => {
const res = await request
.post(`/api${saveGoogle ? '?saveToGoogle=true' : ''}`)
.send(updatedBrew)
.catch((err) => {
.catch((err)=>{
setIsSaving(false);
setError(err);
});
setIsSaving(false)
if (!res) return;
setIsSaving(false);
if(!res) return;
const savedBrew = res.body;
@@ -209,7 +209,7 @@ const NewPage = (props) => {
setIsSaving(false);
};
const renderNavbar = () => (
const renderNavbar = ()=>(
<Navbar>
<Nav.section>
<Nav.item className='brewTitle'>{currentBrew.title}</Nav.item>
@@ -230,7 +230,7 @@ const NewPage = (props) => {
);
return (
<div className='newPage sitePage'>
<div className='newPage sitePage'>
{renderNavbar()}
<div className='content'>
<SplitPane onDragFinish={handleSplitMove}>

View File

@@ -4,8 +4,6 @@
"naturalcrit_url" : "local.naturalcrit.com:8010",
"secret" : "secret",
"web_port" : 8000,
"enable_v3" : true,
"enable_themes" : true,
"local_environments" : ["docker", "local"],
"publicUrl" : "https://homebrewery.naturalcrit.com",
"hb_images" : null,

1055
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -83,19 +83,19 @@
]
},
"dependencies": {
"@babel/core": "^7.27.1",
"@babel/plugin-transform-runtime": "^7.28.0",
"@babel/preset-env": "^7.28.0",
"@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/runtime": "^7.27.6",
"@babel/runtime": "^7.28.4",
"@dmsnell/diff-match-patch": "^1.1.0",
"@googleapis/drive": "^13.0.1",
"@googleapis/drive": "^18.0.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.44.0",
"core-js": "^3.46.0",
"cors": "^2.8.5",
"create-react-class": "^15.7.0",
"dedent-tabs": "^0.10.3",
@@ -104,7 +104,7 @@
"express-async-handler": "^1.2.0",
"express-static-gzip": "3.0.0",
"fflate": "^0.8.2",
"fs-extra": "11.3.0",
"fs-extra": "11.3.2",
"hash-wasm": "^4.12.0",
"idb-keyval": "^6.2.2",
"js-yaml": "^4.1.0",
@@ -119,16 +119,16 @@
"marked-gfm-heading-id": "^4.1.2",
"marked-nonbreaking-spaces": "^1.0.1",
"marked-smartypants-lite": "^1.0.3",
"marked-subsuper-text": "^1.0.3",
"marked-subsuper-text": "^1.0.4",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.30.1",
"mongoose": "^8.16.3",
"nanoid": "5.1.5",
"mongoose": "^8.19.1",
"nanoid": "5.1.6",
"nconf": "^0.13.0",
"react": "^18.3.1",
"react": "^19.2.0",
"react-dom": "^18.3.1",
"react-frame-component": "^4.1.3",
"react-router": "^7.6.3",
"react-router": "^7.9.4",
"romans": "^3.1.0",
"sanitize-filename": "1.6.3",
"superagent": "^10.2.1",
@@ -138,15 +138,15 @@
"devDependencies": {
"@stylistic/stylelint-plugin": "^4.0.0",
"babel-plugin-transform-import-meta": "^2.3.3",
"eslint": "^9.35.0",
"eslint": "^9.37.0",
"eslint-plugin-jest": "^29.0.1",
"eslint-plugin-react": "^7.37.5",
"globals": "^16.3.0",
"jest": "^30.1.3",
"globals": "^16.4.0",
"jest": "^30.2.0",
"jest-expect-message": "^1.1.3",
"jsdom-global": "^3.0.2",
"postcss-less": "^6.0.0",
"stylelint": "^16.24.0",
"stylelint": "^16.25.0",
"stylelint-config-recess-order": "^7.3.0",
"stylelint-config-recommended": "^17.0.0",
"supertest": "^7.1.4"

View File

@@ -35,6 +35,7 @@ import contentNegotiation from './middleware/content-negotiation.js';
import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
import forceSSL from './forcessl.mw.js';
import dbCheck from './middleware/dbCheck.js';
const sanitizeBrew = (brew, accessType)=>{
@@ -274,7 +275,7 @@ app.get('/metadata/:id', asyncHandler(getBrew('share')), (req, res)=>{
app.get('/css/:id', asyncHandler(getBrew('share')), (req, res)=>{getCSS(req, res);});
//User Page
app.get('/user/:username', async (req, res, next)=>{
app.get('/user/:username', dbCheck, async (req, res, next)=>{
const ownAccount = req.account && (req.account.username == req.params.username);
req.ogMeta = { ...defaultMetaTags,
@@ -346,7 +347,7 @@ app.get('/user/:username', async (req, res, next)=>{
});
//Change author name on brews
app.put('/api/user/rename', async (req, res)=>{
app.put('/api/user/rename', dbCheck, async (req, res)=>{
const { username, newUsername } = req.body;
const ownAccount = req.account && (req.account.username == newUsername);
@@ -432,7 +433,7 @@ app.get('/new', asyncHandler(async(req, res, next)=>{
}));
//Share Page
app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, res, next)=>{
app.get('/share/:id', dbCheck, asyncHandler(getBrew('share')), asyncHandler(async (req, res, next)=>{
const { brew } = req;
req.ogMeta = { ...defaultMetaTags,
title : `${req.brew.title || 'Untitled Brew'} - ${req.brew.authors[0] || 'No author.'}`,
@@ -459,7 +460,7 @@ app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, r
}));
//Account Page
app.get('/account', asyncHandler(async (req, res, next)=>{
app.get('/account', dbCheck, asyncHandler(async (req, res, next)=>{
const data = {};
data.title = 'Account Information Page';
@@ -562,8 +563,6 @@ const renderPage = async (req, res)=>{
brews : req.brews,
googleBrews : req.googleBrews,
account : req.account,
enable_v3 : config.get('enable_v3'),
enable_themes : config.get('enable_themes'),
config : configuration,
ogMeta : req.ogMeta,
userThemes : req.userThemes

View File

@@ -22,6 +22,14 @@ const handleConnectionError = (error)=>{
}
};
const addListeners = (conn)=>{
conn.connection.on('disconnecting', ()=>{console.log('Mongo disconnecting...');});
conn.connection.on('disconnected', ()=>{console.log('Mongo disconnected!');});
conn.connection.on('connecting', ()=>{console.log('Mongo connecting...');});
conn.connection.on('connected', ()=>{console.log('Mongo connected!');});
return conn;
};
const disconnect = async ()=>{
return await Mongoose.disconnect();
};
@@ -31,10 +39,12 @@ const connect = async (config)=>{
retryWrites : false,
autoIndex : (config.get('local_environments').includes(config.get('node_env')))
})
.catch((error)=>handleConnectionError(error));
.then(addListeners(Mongoose))
.catch((error)=>handleConnectionError(error));
};
export default {
connect,
disconnect
};

View File

@@ -8,11 +8,12 @@ import Markdown from '../shared/naturalcrit/markdown.js';
import yaml from 'js-yaml';
import asyncHandler from 'express-async-handler';
import { nanoid } from 'nanoid';
import {makePatches, applyPatches, stringifyPatches, parsePatch} from '@sanity/diff-match-patch';
import { makePatches, applyPatches, stringifyPatches, parsePatch } from '@sanity/diff-match-patch';
import { md5 } from 'hash-wasm';
import { splitTextStyleAndMetadata,
import { splitTextStyleAndMetadata,
brewSnippetsToJSON, debugTextMismatch } from '../shared/helpers.js';
import checkClientVersion from './middleware/check-client-version.js';
import dbCheck from './middleware/dbCheck.js';
const router = express.Router();
@@ -377,14 +378,14 @@ const api = {
// Patch to a throwaway variable while parallelizing - we're more concerned with error/no error.
const patchedResult = decodeURI(applyPatches(patches, encodeURI(brewFromServer.text))[0]);
if(patchedResult != brewFromClient.text)
throw("Patches did not apply cleanly, text mismatch detected");
throw ('Patches did not apply cleanly, text mismatch detected');
// brew.text = applyPatches(patches, brewFromServer.text)[0];
} catch (err) {
//debugTextMismatch(brewFromClient.text, brewFromServer.text, `edit/${brewFromClient.editId}`);
console.error('Failed to apply patches:', {
//patches : brewFromClient.patches,
brewId : brewFromClient.editId || 'unknown',
error : err
brewId : brewFromClient.editId || 'unknown',
error : err
});
// While running in parallel, don't throw the error upstream.
// throw err; // rethrow to preserve the 500 behavior
@@ -480,6 +481,7 @@ const api = {
await HomebrewModel.deleteOne({ editId: id });
return next();
}
throw(err);
}
let brew = req.brew;
@@ -530,6 +532,8 @@ const api = {
}
};
router.use(dbCheck);
router.post('/api', checkClientVersion, asyncHandler(api.newBrew));
router.put('/api/:id', checkClientVersion, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew));
router.put('/api/update/:id', checkClientVersion, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew));

View File

@@ -0,0 +1,15 @@
import mongoose from 'mongoose';
import config from '../config.js';
export default (req, res, next)=>{
// Bypass DB checks during testing
if(config.get('node_env') == 'test') return next();
if(mongoose.connection.readyState == 1) return next();
throw {
HBErrorCode : '13',
name : 'Database Connection Error',
message : 'Unable to connect to database',
status : mongoose.connection.readyState
};
};

View File

@@ -0,0 +1,28 @@
import mongoose from 'mongoose';
import dbCheck from './dbCheck.js';
import config from '../config.js';
describe('dbCheck middleware', ()=>{
const next = jest.fn();
afterEach(()=>jest.clearAllMocks());
it('should skip check in test mode', ()=>{
config.get = jest.fn(()=>'test');
expect(()=>dbCheck({}, {}, next)).not.toThrow();
expect(next).toHaveBeenCalled();
});
it('should call next if readyState == 1', ()=>{
config.get = jest.fn(()=>'production');
mongoose.connection.readyState = 1;
dbCheck({}, {}, next);
expect(next).toHaveBeenCalled();
});
it('should throw if readyState != 1', ()=>{
config.get = jest.fn(()=>'production');
mongoose.connection.readyState = 99;
expect(()=>dbCheck({}, {}, next)).toThrow(/Unable to connect/);
});
});

View File

@@ -8,7 +8,7 @@ const brewSnippetsToJSON = (menuTitle, userBrewSnippets, themeBundleSnippets=nul
const mpAsSnippets = [];
// Snippets from Themes first.
if(themeBundleSnippets) {
for (let themes of themeBundleSnippets) {
for (const themes of themeBundleSnippets) {
if(typeof themes !== 'string') {
const userSnippets = [];
const snipSplit = themes.snippets.trim().split(textSplit).slice(1);
@@ -76,9 +76,9 @@ const yamlSnippetsToText = (yamlObj)=>{
if(typeof yamlObj == 'string') return yamlObj;
let snippetsText = '';
for (let snippet of yamlObj) {
for (let subSnippet of snippet.subsnippets) {
for (const snippet of yamlObj) {
for (const subSnippet of snippet.subsnippets) {
snippetsText = `${snippetsText}\\snippet ${subSnippet.name}\n${subSnippet.gen || ''}\n`;
}
}
@@ -121,7 +121,7 @@ const fetchThemeBundle = async (setError, setThemeBundle, renderer, theme)=>{
const res = await request
.get(`/api/theme/${renderer}/${theme}`)
.catch((err)=>{
setError(err)
setError(err);
});
if(!res) {
setThemeBundle({});
@@ -133,14 +133,14 @@ const fetchThemeBundle = async (setError, setThemeBundle, renderer, theme)=>{
setError(null);
};
const debugTextMismatch = (clientTextRaw, serverTextRaw, label) => {
const debugTextMismatch = (clientTextRaw, serverTextRaw, label)=>{
const clientText = clientTextRaw?.normalize('NFC') || '';
const serverText = serverTextRaw?.normalize('NFC') || '';
const clientBuffer = Buffer.from(clientText, 'utf8');
const serverBuffer = Buffer.from(serverText, 'utf8');
if (clientBuffer.equals(serverBuffer)) {
if(clientBuffer.equals(serverBuffer)) {
console.log(`${label} text matches byte-for-byte.`);
return;
}
@@ -151,7 +151,7 @@ const debugTextMismatch = (clientTextRaw, serverTextRaw, label) => {
// Byte-level diff
for (let i = 0; i < Math.min(clientBuffer.length, serverBuffer.length); i++) {
if (clientBuffer[i] !== serverBuffer[i]) {
if(clientBuffer[i] !== serverBuffer[i]) {
console.log(`Byte mismatch at offset ${i}: client=0x${clientBuffer[i].toString(16)} server=0x${serverBuffer[i].toString(16)}`);
break;
}
@@ -159,14 +159,14 @@ const debugTextMismatch = (clientTextRaw, serverTextRaw, label) => {
// Char-level diff
for (let i = 0; i < Math.min(clientText.length, serverText.length); i++) {
if (clientText[i] !== serverText[i]) {
if(clientText[i] !== serverText[i]) {
console.log(`Char mismatch at index ${i}:`);
console.log(` Client: '${clientText[i]}' (U+${clientText.charCodeAt(i).toString(16).toUpperCase()})`);
console.log(` Server: '${serverText[i]}' (U+${serverText.charCodeAt(i).toString(16).toUpperCase()})`);
break;
}
}
}
};
export {
splitTextStyleAndMetadata,

View File

@@ -38,6 +38,11 @@
animation-duration : 0.4s;
}
.CodeMirror-search-field {
width:25em !important;
outline:1px inset #00000055 !important;
}
//.cm-tab {
// background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAQAAACOs/baAAAARUlEQVR4nGJgIAG8JkXxUAcCtDWemcGR1lY4MvgzCEKY7jSBjgxBDAG09UEQzAe0AMwMHrSOAwEGRtpaMIwAAAAA//8DAG4ID9EKs6YqAAAAAElFTkSuQmCC) no-repeat right;
//}

View File

@@ -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];
@@ -435,7 +435,7 @@ const replaceVar = function(input, hoist=false, allowUnresolved=false) {
try {
return mathParser.evaluate(replacedLabel);
} catch (error) {
} catch {
return undefined; // Return undefined if invalid math result
}
}
@@ -680,7 +680,7 @@ const tableTerminators = [
Marked.use(MarkedVariables());
Marked.use(MarkedDefinitionLists());
Marked.use({ extensions : [forcedParagraphBreaks, mustacheSpans, mustacheDivs, mustacheInjectInline] });
Marked.use({ extensions: [forcedParagraphBreaks, mustacheSpans, mustacheDivs, mustacheInjectInline] });
Marked.use(mustacheInjectBlock);
Marked.use(MarkedAlignedParagraphs());
Marked.use(MarkedSubSuperText());

View File

@@ -49,7 +49,7 @@ const cleanUrl = function (sanitize, base, href) {
prot = decodeURIComponent(unescape(href))
.replace(nonWordAndColonTest, '')
.toLowerCase();
} catch (e) {
} catch {
return null;
}
if(prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
@@ -58,7 +58,7 @@ const cleanUrl = function (sanitize, base, href) {
}
try {
href = encodeURI(href).replace(/%25/g, '%');
} catch (e) {
} catch {
return null;
}
return href;

View File

@@ -418,6 +418,7 @@
color : var(--HB_Color_Footnotes);
}
.footnote {
text-transform: uppercase;
position : absolute;
right : 80px;
bottom : 32px;

View File

@@ -14,6 +14,7 @@ const diceFont = {
'df_d10_7' : 'df d10-7',
'df_d10_8' : 'df d10-8',
'df_d10_9' : 'df d10-9',
'df_d10_0' : 'df d10-0',
'df_d12' : 'df d12',
'df_d12_1' : 'df d12-1',
'df_d12_10' : 'df d12-10',
@@ -90,7 +91,108 @@ const diceFont = {
'df_solid_small_dot_d6_3' : 'df solid-small-dot-d6-3',
'df_solid_small_dot_d6_4' : 'df solid-small-dot-d6-4',
'df_solid_small_dot_d6_5' : 'df solid-small-dot-d6-5',
'df_solid_small_dot_d6_6' : 'df solid-small-dot-d6-6'
'df_solid_small_dot_d6_6' : 'df solid-small-dot-d6-6',
'df_d10_00' : 'df d10-00',
'df_d10_01' : 'df d10-01',
'df_d10_02' : 'df d10-02',
'df_d10_03' : 'df d10-03',
'df_d10_04' : 'df d10-04',
'df_d10_05' : 'df d10-05',
'df_d10_06' : 'df d10-06',
'df_d10_07' : 'df d10-07',
'df_d10_08' : 'df d10-08',
'df_d10_09' : 'df d10-09',
'df_d10_10' : 'df d10-10',
'df_d10_11' : 'df d10-11',
'df_d10_12' : 'df d10-12',
'df_d10_13' : 'df d10-13',
'df_d10_14' : 'df d10-14',
'df_d10_15' : 'df d10-15',
'df_d10_16' : 'df d10-16',
'df_d10_17' : 'df d10-17',
'df_d10_18' : 'df d10-18',
'df_d10_19' : 'df d10-19',
'df_d10_20' : 'df d10-20',
'df_d10_21' : 'df d10-21',
'df_d10_22' : 'df d10-22',
'df_d10_23' : 'df d10-23',
'df_d10_24' : 'df d10-24',
'df_d10_25' : 'df d10-25',
'df_d10_26' : 'df d10-26',
'df_d10_27' : 'df d10-27',
'df_d10_28' : 'df d10-28',
'df_d10_29' : 'df d10-29',
'df_d10_30' : 'df d10-30',
'df_d10_31' : 'df d10-31',
'df_d10_32' : 'df d10-32',
'df_d10_33' : 'df d10-33',
'df_d10_34' : 'df d10-34',
'df_d10_35' : 'df d10-35',
'df_d10_36' : 'df d10-36',
'df_d10_37' : 'df d10-37',
'df_d10_38' : 'df d10-38',
'df_d10_39' : 'df d10-39',
'df_d10_40' : 'df d10-40',
'df_d10_41' : 'df d10-41',
'df_d10_42' : 'df d10-42',
'df_d10_43' : 'df d10-43',
'df_d10_44' : 'df d10-44',
'df_d10_45' : 'df d10-45',
'df_d10_46' : 'df d10-46',
'df_d10_47' : 'df d10-47',
'df_d10_48' : 'df d10-48',
'df_d10_49' : 'df d10-49',
'df_d10_50' : 'df d10-50',
'df_d10_51' : 'df d10-51',
'df_d10_52' : 'df d10-52',
'df_d10_53' : 'df d10-53',
'df_d10_54' : 'df d10-54',
'df_d10_55' : 'df d10-55',
'df_d10_56' : 'df d10-56',
'df_d10_57' : 'df d10-57',
'df_d10_58' : 'df d10-58',
'df_d10_59' : 'df d10-59',
'df_d10_60' : 'df d10-60',
'df_d10_61' : 'df d10-61',
'df_d10_62' : 'df d10-62',
'df_d10_63' : 'df d10-63',
'df_d10_64' : 'df d10-64',
'df_d10_65' : 'df d10-65',
'df_d10_66' : 'df d10-66',
'df_d10_67' : 'df d10-67',
'df_d10_68' : 'df d10-68',
'df_d10_69' : 'df d10-69',
'df_d10_70' : 'df d10-70',
'df_d10_71' : 'df d10-71',
'df_d10_72' : 'df d10-72',
'df_d10_73' : 'df d10-73',
'df_d10_74' : 'df d10-74',
'df_d10_75' : 'df d10-75',
'df_d10_76' : 'df d10-76',
'df_d10_77' : 'df d10-77',
'df_d10_78' : 'df d10-78',
'df_d10_79' : 'df d10-79',
'df_d10_80' : 'df d10-80',
'df_d10_81' : 'df d10-81',
'df_d10_82' : 'df d10-82',
'df_d10_83' : 'df d10-83',
'df_d10_84' : 'df d10-84',
'df_d10_85' : 'df d10-85',
'df_d10_86' : 'df d10-86',
'df_d10_87' : 'df d10-87',
'df_d10_88' : 'df d10-88',
'df_d10_89' : 'df d10-89',
'df_d10_90' : 'df d10-90',
'df_d10_91' : 'df d10-91',
'df_d10_92' : 'df d10-92',
'df_d10_93' : 'df d10-93',
'df_d10_94' : 'df d10-94',
'df_d10_95' : 'df d10-95',
'df_d10_96' : 'df d10-96',
'df_d10_97' : 'df d10-97',
'df_d10_98' : 'df d10-98',
'df_d10_99' : 'df d10-99',
'df_d10_100' : 'df d10-100'
};
export default diceFont;

View File

@@ -6,6 +6,14 @@
src : url('../../../fonts/iconFonts/diceFont.woff2');
}
@font-face {
font-family : 'DiceFontD100';
src : url('../../../fonts/iconFonts/diceFontD100.woff2') format('woff2');
font-weight : normal;
font-style : normal;
font-display : block;
}
.df {
display : inline;
font-family : 'DiceFont';
@@ -26,17 +34,6 @@
&.F-plus::before { content : '\f192'; }
&.F-zero::before { content : '\f193'; }
&.d10::before { content : '\f194'; }
&.d10-0::before { content : '\f100'; }
&.d10-1::before { content : '\f101'; }
&.d10-10::before { content : '\f102'; }
&.d10-2::before { content : '\f103'; }
&.d10-3::before { content : '\f104'; }
&.d10-4::before { content : '\f105'; }
&.d10-5::before { content : '\f106'; }
&.d10-6::before { content : '\f107'; }
&.d10-7::before { content : '\f108'; }
&.d10-8::before { content : '\f109'; }
&.d10-9::before { content : '\f10a'; }
&.d12::before { content : '\f195'; }
&.d12-1::before { content : '\f10b'; }
&.d12-10::before { content : '\f10c'; }
@@ -114,4 +111,568 @@
&.solid-small-dot-d6-4::before { content : '\f18c'; }
&.solid-small-dot-d6-5::before { content : '\f18d'; }
&.solid-small-dot-d6-6::before { content : '\f18e'; }
// Replacement d10
&.d10-0::before {
font-family : 'DiceFontD100';
content : '\e900';
}
&.d10-1::before {
font-family : 'DiceFontD100';
content : '\e901';
}
&.d10-2::before {
font-family : 'DiceFontD100';
content : '\e902';
}
&.d10-3::before {
font-family : 'DiceFontD100';
content : '\e903';
}
&.d10-4::before {
font-family : 'DiceFontD100';
content : '\e904';
}
&.d10-5::before {
font-family : 'DiceFontD100';
content : '\e905';
}
&.d10-6::before {
font-family : 'DiceFontD100';
content : '\e906';
}
&.d10-7::before {
font-family : 'DiceFontD100';
content : '\e907';
}
&.d10-8::before {
font-family : 'DiceFontD100';
content : '\e908';
}
&.d10-9::before {
font-family : 'DiceFontD100';
content : '\e909';
}
&.d10-10::before {
font-family : 'DiceFontD100';
content : '\e90a';
}
// d100
&.d10-00::before {
font-family : 'DiceFontD100';
content : '\e90b';
}
&.d10-01::before {
font-family : 'DiceFontD100';
content : '\e90c';
}
&.d10-02::before {
font-family : 'DiceFontD100';
content : '\e90d';
}
&.d10-03::before {
font-family : 'DiceFontD100';
content : '\e90e';
}
&.d10-04::before {
font-family : 'DiceFontD100';
content : '\e90f';
}
&.d10-05::before {
font-family : 'DiceFontD100';
content : '\e910';
}
&.d10-06::before {
font-family : 'DiceFontD100';
content : '\e911';
}
&.d10-07::before {
font-family : 'DiceFontD100';
content : '\e912';
}
&.d10-08::before {
font-family : 'DiceFontD100';
content : '\e913';
}
&.d10-09::before {
font-family : 'DiceFontD100';
content : '\e914';
}
&.d10-10::before {
font-family : 'DiceFontD100';
content : '\e915';
}
&.d10-11::before {
font-family : 'DiceFontD100';
content : '\e916';
}
&.d10-12::before {
font-family : 'DiceFontD100';
content : '\e917';
}
&.d10-13::before {
font-family : 'DiceFontD100';
content : '\e918';
}
&.d10-14::before {
font-family : 'DiceFontD100';
content : '\e919';
}
&.d10-15::before {
font-family : 'DiceFontD100';
content : '\e91a';
}
&.d10-16::before {
font-family : 'DiceFontD100';
content : '\e91b';
}
&.d10-17::before {
font-family : 'DiceFontD100';
content : '\e91c';
}
&.d10-18::before {
font-family : 'DiceFontD100';
content : '\e91d';
}
&.d10-19::before {
font-family : 'DiceFontD100';
content : '\e91e';
}
&.d10-20::before {
font-family : 'DiceFontD100';
content : '\e91f';
}
&.d10-21::before {
font-family : 'DiceFontD100';
content : '\e920';
}
&.d10-22::before {
font-family : 'DiceFontD100';
content : '\e921';
}
&.d10-23::before {
font-family : 'DiceFontD100';
content : '\e922';
}
&.d10-24::before {
font-family : 'DiceFontD100';
content : '\e923';
}
&.d10-25::before {
font-family : 'DiceFontD100';
content : '\e924';
}
&.d10-26::before {
font-family : 'DiceFontD100';
content : '\e925';
}
&.d10-27::before {
font-family : 'DiceFontD100';
content : '\e926';
}
&.d10-28::before {
font-family : 'DiceFontD100';
content : '\e927';
}
&.d10-29::before {
font-family : 'DiceFontD100';
content : '\e928';
}
&.d10-30::before {
font-family : 'DiceFontD100';
content : '\e929';
}
&.d10-31::before {
font-family : 'DiceFontD100';
content : '\e92a';
}
&.d10-32::before {
font-family : 'DiceFontD100';
content : '\e92b';
}
&.d10-33::before {
font-family : 'DiceFontD100';
content : '\e92c';
}
&.d10-34::before {
font-family : 'DiceFontD100';
content : '\e92d';
}
&.d10-35::before {
font-family : 'DiceFontD100';
content : '\e92e';
}
&.d10-36::before {
font-family : 'DiceFontD100';
content : '\e92f';
}
&.d10-37::before {
font-family : 'DiceFontD100';
content : '\e930';
}
&.d10-38::before {
font-family : 'DiceFontD100';
content : '\e931';
}
&.d10-39::before {
font-family : 'DiceFontD100';
content : '\e932';
}
&.d10-40::before {
font-family : 'DiceFontD100';
content : '\e933';
}
&.d10-41::before {
font-family : 'DiceFontD100';
content : '\e934';
}
&.d10-42::before {
font-family : 'DiceFontD100';
content : '\e935';
}
&.d10-43::before {
font-family : 'DiceFontD100';
content : '\e936';
}
&.d10-44::before {
font-family : 'DiceFontD100';
content : '\e937';
}
&.d10-45::before {
font-family : 'DiceFontD100';
content : '\e938';
}
&.d10-46::before {
font-family : 'DiceFontD100';
content : '\e939';
}
&.d10-47::before {
font-family : 'DiceFontD100';
content : '\e93a';
}
&.d10-48::before {
font-family : 'DiceFontD100';
content : '\e93b';
}
&.d10-49::before {
font-family : 'DiceFontD100';
content : '\e93c';
}
&.d10-50::before {
font-family : 'DiceFontD100';
content : '\e93d';
}
&.d10-51::before {
font-family : 'DiceFontD100';
content : '\e93e';
}
&.d10-52::before {
font-family : 'DiceFontD100';
content : '\e93f';
}
&.d10-53::before {
font-family : 'DiceFontD100';
content : '\e940';
}
&.d10-54::before {
font-family : 'DiceFontD100';
content : '\e941';
}
&.d10-55::before {
font-family : 'DiceFontD100';
content : '\e942';
}
&.d10-56::before {
font-family : 'DiceFontD100';
content : '\e943';
}
&.d10-57::before {
font-family : 'DiceFontD100';
content : '\e944';
}
&.d10-58::before {
font-family : 'DiceFontD100';
content : '\e945';
}
&.d10-59::before {
font-family : 'DiceFontD100';
content : '\e946';
}
&.d10-60::before {
font-family : 'DiceFontD100';
content : '\e947';
}
&.d10-61::before {
font-family : 'DiceFontD100';
content : '\e948';
}
&.d10-62::before {
font-family : 'DiceFontD100';
content : '\e949';
}
&.d10-63::before {
font-family : 'DiceFontD100';
content : '\e94a';
}
&.d10-64::before {
font-family : 'DiceFontD100';
content : '\e94b';
}
&.d10-65::before {
font-family : 'DiceFontD100';
content : '\e94c';
}
&.d10-66::before {
font-family : 'DiceFontD100';
content : '\e94d';
}
&.d10-67::before {
font-family : 'DiceFontD100';
content : '\e94e';
}
&.d10-68::before {
font-family : 'DiceFontD100';
content : '\e94f';
}
&.d10-69::before {
font-family : 'DiceFontD100';
content : '\e950';
}
&.d10-70::before {
font-family : 'DiceFontD100';
content : '\e951';
}
&.d10-71::before {
font-family : 'DiceFontD100';
content : '\e952';
}
&.d10-72::before {
font-family : 'DiceFontD100';
content : '\e953';
}
&.d10-73::before {
font-family : 'DiceFontD100';
content : '\e954';
}
&.d10-74::before {
font-family : 'DiceFontD100';
content : '\e955';
}
&.d10-75::before {
font-family : 'DiceFontD100';
content : '\e956';
}
&.d10-76::before {
font-family : 'DiceFontD100';
content : '\e957';
}
&.d10-77::before {
font-family : 'DiceFontD100';
content : '\e958';
}
&.d10-78::before {
font-family : 'DiceFontD100';
content : '\e959';
}
&.d10-79::before {
font-family : 'DiceFontD100';
content : '\e95a';
}
&.d10-80::before {
font-family : 'DiceFontD100';
content : '\e95b';
}
&.d10-81::before {
font-family : 'DiceFontD100';
content : '\e95c';
}
&.d10-82::before {
font-family : 'DiceFontD100';
content : '\e95d';
}
&.d10-83::before {
font-family : 'DiceFontD100';
content : '\e95e';
}
&.d10-84::before {
font-family : 'DiceFontD100';
content : '\e95f';
}
&.d10-85::before {
font-family : 'DiceFontD100';
content : '\e960';
}
&.d10-86::before {
font-family : 'DiceFontD100';
content : '\e961';
}
&.d10-87::before {
font-family : 'DiceFontD100';
content : '\e962';
}
&.d10-88::before {
font-family : 'DiceFontD100';
content : '\e963';
}
&.d10-89::before {
font-family : 'DiceFontD100';
content : '\e964';
}
&.d10-90::before {
font-family : 'DiceFontD100';
content : '\e965';
}
&.d10-91::before {
font-family : 'DiceFontD100';
content : '\e966';
}
&.d10-92::before {
font-family : 'DiceFontD100';
content : '\e967';
}
&.d10-93::before {
font-family : 'DiceFontD100';
content : '\e968';
}
&.d10-94::before {
font-family : 'DiceFontD100';
content : '\e969';
}
&.d10-95::before {
font-family : 'DiceFontD100';
content : '\e96a';
}
&.d10-96::before {
font-family : 'DiceFontD100';
content : '\e96b';
}
&.d10-97::before {
font-family : 'DiceFontD100';
content : '\e96c';
}
&.d10-98::before {
font-family : 'DiceFontD100';
content : '\e96d';
}
&.d10-99::before {
font-family : 'DiceFontD100';
content : '\e96e';
}
&.d10-100::before {
font-family : 'DiceFontD100';
content : '\e96f';
}
}

Binary file not shown.