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

Compare commits

...

185 Commits

Author SHA1 Message Date
Trevor Buckner
8a55658bd7 Rename printPage function to printCurrentBrew()
Avoid confusion with other "page" components.
2024-05-28 16:11:18 -04:00
Trevor Buckner
01d60c4520 lint 2024-05-28 13:22:33 -04:00
Trevor Buckner
b4349a0476 iframe hotkey printing only works in Edit/Share/New
Default browser printing still works
2024-05-28 12:51:58 -04:00
Trevor Buckner
695b9916dd Remove old /print page 2024-05-28 12:39:43 -04:00
Trevor Buckner
ac3168e365 Move "printPage()" to helpers.js for reuse in multiple pages 2024-05-24 19:28:02 -04:00
Trevor Buckner
e396211f92 remove duplicate button 2024-05-23 17:13:44 -04:00
Trevor Buckner
4ce68b86ed Fix hotkey printing on focused iframe 2024-05-23 17:09:03 -04:00
Trevor Buckner
24769d69d4 Force browser repaint after closing Print dialog 2024-05-23 17:08:24 -04:00
Trevor Buckner
a227a792c0 Replace print redirect with print contentWindow on all pages 2024-05-22 15:54:01 -04:00
Trevor Buckner
dcd34ccdaf Merge pull request #3477 from Gazook89/fix-refs
Fix `ref` issues
2024-05-21 17:50:07 -04:00
Trevor Buckner
2453b623db tweak names in editor.jsx 2024-05-21 17:45:50 -04:00
Trevor Buckner
783e88b5e6 Merge branch 'master' into pr/3477 2024-05-21 17:42:03 -04:00
Trevor Buckner
77c0af42d0 Merge pull request #3489 from naturalcrit/dependabot/npm_and_yarn/dompurify-3.1.4
Bump dompurify from 3.1.1 to 3.1.4
2024-05-21 17:35:56 -04:00
Trevor Buckner
c21b4eb2d6 Merge branch 'master' into dependabot/npm_and_yarn/dompurify-3.1.4 2024-05-21 17:35:48 -04:00
Trevor Buckner
6043af81e4 Merge pull request #3470 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.23.1
Bump react-router-dom from 6.23.0 to 6.23.1
2024-05-21 17:35:36 -04:00
Trevor Buckner
7c3321b62f Merge branch 'master' into dependabot/npm_and_yarn/react-router-dom-6.23.1 2024-05-21 17:34:17 -04:00
Trevor Buckner
d1955951e4 Merge pull request #3490 from naturalcrit/LintingPass
Lint a bunch of things
2024-05-21 17:33:45 -04:00
Trevor Buckner
e62e185214 Lint a bunch of things 2024-05-21 17:32:17 -04:00
Trevor Buckner
0c38415372 Merge pull request #3482 from 5e-Cleric/clean-up-unused-constants-and-requires
Clean up unused declarations
2024-05-21 17:29:28 -04:00
Trevor Buckner
73f879aa63 Merge branch 'master' into clean-up-unused-constants-and-requires 2024-05-21 17:28:51 -04:00
Trevor Buckner
f12de7d953 Undo Journal path change 2024-05-21 17:28:17 -04:00
Trevor Buckner
933ac41774 Merge pull request #3420 from Gazook89/RPG-Awesome-Redux
RPG Awesome Redux
2024-05-21 16:30:00 -04:00
Trevor Buckner
54b4d490f1 Adjust hyphenation 2024-05-21 16:21:24 -04:00
Trevor Buckner
193af61725 Merge branch 'master' into pr/3420 2024-05-21 14:50:02 -04:00
dependabot[bot]
8fb9f3f823 Bump dompurify from 3.1.1 to 3.1.4
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.1.1 to 3.1.4.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.1.1...3.1.4)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-20 17:39:53 +00:00
dependabot[bot]
7af919afd3 Bump react-router-dom from 6.23.0 to 6.23.1
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.23.0 to 6.23.1.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.23.1/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-20 17:39:49 +00:00
Trevor Buckner
5bbe4016d6 Merge pull request #3488 from naturalcrit/dependabot/npm_and_yarn/mongoose-8.4.0
Bump mongoose from 8.3.3 to 8.4.0
2024-05-20 13:39:00 -04:00
dependabot[bot]
0f3312a5d7 Bump mongoose from 8.3.3 to 8.4.0
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.3.3 to 8.4.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.3.3...8.4.0)

---
updated-dependencies:
- dependency-name: mongoose
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-20 17:38:10 +00:00
Trevor Buckner
0bf432dd76 Merge pull request #3486 from naturalcrit/dependabot/npm_and_yarn/vitreum-9d55fd6
Bump vitreum from `49994da` to `9d55fd6`
2024-05-20 13:37:27 -04:00
dependabot[bot]
27b3da0144 Bump vitreum from 49994da to 9d55fd6
Bumps [vitreum](https://github.com/calculuschild/vitreum) from `49994da` to `9d55fd6`.
- [Commits](49994da405...9d55fd6fb7)

---
updated-dependencies:
- dependency-name: vitreum
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-20 03:13:40 +00:00
Trevor Buckner
b8b1b9660f Merge pull request #3404 from MurdoMaclachlan/master
Add proficiency bonus to monster statblocks
2024-05-18 17:28:38 -04:00
Trevor Buckner
f40d851d49 Merge branch 'master' into master 2024-05-17 16:53:58 -04:00
Víctor Losada Hernández
b64c835706 Aparently it wasn't redundant as VSCode said
This reverts commit aef6605225.
2024-05-17 22:38:54 +02:00
Víctor Losada Hernández
b7717171b3 Server and shared folders 2024-05-17 22:34:40 +02:00
Víctor Losada Hernández
92e27cda6c "Removed unused imports of 'classnames' and 'create-react-class' from various JSX files. in the Client folder" 2024-05-17 22:31:55 +02:00
Víctor Losada Hernández
aef6605225 Remove redundant snippetBar import from editor.jsx 2024-05-17 22:28:01 +02:00
Gazook89
7c9cc25923 update editor ref's in edit, home, and new pages. 2024-05-16 23:29:30 -05:00
Gazook89
78ce8aa6e3 remove unused ref attributes
from editPage, homePage, newPage, and printPage, as well as splitPane.   The refs were declared, but never used.
2024-05-16 23:25:22 -05:00
Gazook89
8ae22bdc27 fix refs in codeEditor.jsx 2024-05-16 23:15:54 -05:00
Gazook89
46c14ef23b fix refs in editor.jsx
now has refs `editorWrapper` and `editor`-- the former includes the snippet bar and codemirror editor, and the latter includes only the codemirror editor.
2024-05-16 23:12:10 -05:00
Trevor Buckner
d3080c03a4 Merge pull request #3432 from 5e-Cleric/fix-icon-fonts
Fix icon fonts
2024-05-16 17:22:39 -04:00
Trevor Buckner
12eead3379 Small typos 2024-05-16 17:19:13 -04:00
Trevor Buckner
a2e065c5d8 Adjustments to match Emojis PR 2024-05-16 17:04:02 -04:00
Trevor Buckner
0d1a3d55cf Merge branch 'master' into fix-icon-fonts 2024-05-16 16:53:54 -04:00
Gazook89
b748a597d2 some fixes post merge. 2024-05-15 21:25:45 -05:00
Gazook89
5fb0e123e3 install new dependencies from merging master 2024-05-15 20:50:52 -05:00
Gazook89
9a4a14fa97 add license, rename files for clarity, update references 2024-05-15 20:48:58 -05:00
Gazook89
0c76a546e4 Merge branch 'master' into RPG-Awesome-Redux 2024-05-15 20:19:00 -05:00
Trevor Buckner
fb299f898e Merge pull request #3434 from G-Ambatte/experimentalHTMLSanitization
Add DOM Purify to BrewRenderer
2024-05-15 17:07:42 -04:00
G.Ambatte
b4ee62a1bd Merge branch 'master' into experimentalHTMLSanitization 2024-05-11 08:58:21 +12:00
Víctor Losada Hernández
25b4b3d906 Merge branch 'master' into master 2024-05-09 08:50:51 +02:00
Víctor Losada Hernández
f21d636846 changes as requested 2024-05-09 08:00:02 +02:00
Víctor Losada Hernández
8365841b89 Merge branch 'master' of https://github.com/naturalcrit/homebrewery into fix-icon-fonts 2024-05-09 07:59:31 +02:00
Víctor Losada Hernández
e6bf8b59a1 fix further errors 2024-05-09 07:49:17 +02:00
Trevor Buckner
b4a4934c5c Merge pull request #3405 from naturalcrit/EmojiSyntax
Emoji syntax
2024-05-08 15:55:01 -04:00
Trevor Buckner
a6b2dab9cc Linting 2024-05-08 14:53:24 -04:00
Trevor Buckner
d692e88b96 Merge branch 'EmojiSyntax' of https://github.com/naturalcrit/homebrewery into EmojiSyntax 2024-05-08 14:24:19 -04:00
Trevor Buckner
62c9e081e6 typos 2024-05-08 14:24:15 -04:00
Trevor Buckner
5a52e76ff0 Merge branch 'master' into EmojiSyntax 2024-05-08 11:01:15 -04:00
Trevor Buckner
3b1f4a0d13 Add Tests for emoji markdown 2024-05-08 09:51:29 -04:00
G.Ambatte
cdad9af453 Merge branch 'master' into experimentalHTMLSanitization 2024-05-08 23:30:49 +12:00
Trevor Buckner
5fd92ee72d Remove redundant font inclusion 2024-05-07 15:55:34 -04:00
Trevor Buckner
5bcd3a1b01 Clear up steps 2024-05-07 15:54:08 -04:00
Trevor Buckner
d49d9fd755 typo 2024-05-07 15:35:00 -04:00
Trevor Buckner
41d817823b Don't autosuggest emojis inside injectors 2024-05-07 15:30:56 -04:00
Trevor Buckner
cfffb4961b Rename files, add some instructions to markdown.js 2024-05-07 15:28:05 -04:00
Trevor Buckner
6bd2f4d98d Add rest of Font-Awesome icons 2024-05-07 15:07:30 -04:00
Trevor Buckner
dd82a1bebd Merge pull request #3457 from 5e-Cleric/icons-for-share-dropdown
icon for edit link in sharepage
2024-05-06 07:54:41 -04:00
Víctor Losada Hernández
d3f1fde9d9 icon for edit link 2024-05-06 07:43:45 +02:00
Trevor Buckner
d83e7bce0a Merge pull request #3456 from 5e-Cleric/icons-for-share-dropdown
Adding icons to the share dropdown
2024-05-05 21:43:40 -04:00
Trevor Buckner
8cd4a58304 Merge branch 'master' into icons-for-share-dropdown 2024-05-05 21:43:12 -04:00
Trevor Buckner
0ef683222d Merge pull request #3447 from 5e-Cleric/link-to-edit-if-author
Add edit link to share page if user is author
2024-05-05 21:42:25 -04:00
Trevor Buckner
ebbf162318 Merge branch 'master' into link-to-edit-if-author 2024-05-05 21:25:43 -04:00
Víctor Losada Hernández
268d202562 initial commit 2024-05-06 00:32:38 +02:00
G.Ambatte
4e0ec75e58 Revert template.js changes for separate PR 2024-05-06 09:46:34 +12:00
G.Ambatte
1af989c4a3 Case insensitive matching 2024-05-06 07:27:22 +12:00
G.Ambatte
53480fdd5f Merge branch 'master' into experimentalHTMLSanitization 2024-05-05 20:50:46 +12:00
G.Ambatte
ffa90c397c Add script sanitization to template.js 2024-05-05 20:18:53 +12:00
Trevor Buckner
df3d1078f1 Add FontAwesome Solid to emoji list 2024-05-05 01:50:38 -04:00
Trevor Buckner
22bdb85dff Convert dicefont and elderberry icon names to snake_case 2024-05-04 00:40:51 -04:00
Trevor Buckner
2f5081156d Merge pull request #3438 from naturalcrit/dependabot/npm_and_yarn/react-dom-18.3.1
Bump react-dom from 18.2.0 to 18.3.1
2024-05-03 21:56:23 -04:00
dependabot[bot]
c3f153a5fa Bump react-dom from 18.2.0 to 18.3.1
Bumps [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) from 18.2.0 to 18.3.1.
- [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/v18.3.1/packages/react-dom)

---
updated-dependencies:
- dependency-name: react-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-04 01:54:01 +00:00
Trevor Buckner
5e0dda1bde Merge pull request #3437 from naturalcrit/dependabot/npm_and_yarn/react-18.3.1
Bump react from 18.2.0 to 18.3.1
2024-05-03 21:52:58 -04:00
Trevor Buckner
b0379b0821 Merge branch 'master' into EmojiSyntax 2024-05-03 21:47:55 -04:00
dependabot[bot]
c506c9cee5 Bump react from 18.2.0 to 18.3.1
Bumps [react](https://github.com/facebook/react/tree/HEAD/packages/react) from 18.2.0 to 18.3.1.
- [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/v18.3.1/packages/react)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-04 01:47:47 +00:00
Trevor Buckner
9184593bc0 Merge pull request #3442 from naturalcrit/dependabot/npm_and_yarn/babel/core-7.24.5
Bump @babel/core from 7.24.4 to 7.24.5
2024-05-03 21:46:46 -04:00
dependabot[bot]
1da70d54e8 Bump @babel/core from 7.24.4 to 7.24.5
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.24.4 to 7.24.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.24.5/packages/babel-core)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-04 01:45:56 +00:00
Trevor Buckner
55cdd016da Merge pull request #3455 from naturalcrit/addMarkedEmojiPackage
Just installs the marked-emoji package
2024-05-03 21:44:53 -04:00
Trevor Buckner
10997898b9 Just installs the marked-emoji package 2024-05-03 21:43:53 -04:00
Trevor Buckner
76b66977e9 Update with master 2024-05-03 21:41:41 -04:00
Trevor Buckner
d695648d9b Tweaks to Editor highlighting. Maybe still ugly. 2024-05-03 21:40:09 -04:00
Trevor Buckner
72160f5daf missed one commit 2024-05-03 21:40:09 -04:00
Trevor Buckner
0751da42b6 Add emoji highlighting to editor 2024-05-03 21:40:08 -04:00
Trevor Buckner
babe1f30a2 Prevent autosuggest inside curly span/div properties 2024-05-03 21:40:08 -04:00
Trevor Buckner
cd35e91ea2 add elderberryInn to emoji syntax 2024-05-03 21:40:08 -04:00
Trevor Buckner
8d8a965241 Rename font-icons to elderberryInn 2024-05-03 21:40:08 -04:00
Trevor Buckner
2309887c92 Change diceFont to camelCase to match existing naming convention 2024-05-03 21:40:08 -04:00
Trevor Buckner
d36e6e5834 Hack to avoid conflict with emojis 2024-05-03 21:40:07 -04:00
Trevor Buckner
dd205a14bc typo 2024-05-03 21:40:07 -04:00
Trevor Buckner
d854fe1202 Clean up redundant code 2024-05-03 21:40:07 -04:00
Trevor Buckner
58f487ac58 Sort alphabetically and numerically
i.e.,

"d2, d6, d8, d10, d12, d20", not "d10, d12, d2, d20, d6, d8"
2024-05-03 21:40:07 -04:00
Trevor Buckner
1761c506be Exclude : from the autocomplete trigger 2024-05-03 21:40:07 -04:00
Trevor Buckner
9f19514b03 CodeMirror Dropdown working 2024-05-03 21:40:07 -04:00
Trevor Buckner
ade1056a02 Include Dicefont 2024-05-03 21:40:07 -04:00
Trevor Buckner
e5fecaf9b6 Include marked-emoji package 2024-05-03 21:40:06 -04:00
Trevor Buckner
5b8b0aa641 Merge pull request #3443 from naturalcrit/dependabot/npm_and_yarn/superagent-9.0.2
Bump superagent from 9.0.1 to 9.0.2
2024-05-03 21:35:29 -04:00
Trevor Buckner
b7bc5cbad7 Merge branch 'master' into dependabot/npm_and_yarn/superagent-9.0.2 2024-05-03 21:33:37 -04:00
Trevor Buckner
f2fc47a719 Merge pull request #3454 from naturalcrit/cleanUpMustacheTests
Just linting and spacing for mustache-syntax.tests.js
2024-05-03 21:32:57 -04:00
Trevor Buckner
a5f9ab7897 Merge branch 'master' into cleanUpMustacheTests 2024-05-03 21:32:40 -04:00
Trevor Buckner
39368c1a38 Merge branch 'master' into fix-icon-fonts 2024-05-03 21:31:31 -04:00
Trevor Buckner
d879cf3cbb Merge pull request #3451 from naturalcrit/dependabot/npm_and_yarn/eslint-plugin-jest-28.5.0
Bump eslint-plugin-jest from 28.2.0 to 28.5.0
2024-05-03 21:31:15 -04:00
Trevor Buckner
ae59c56ddd Merge branch 'master' into dependabot/npm_and_yarn/eslint-plugin-jest-28.5.0 2024-05-03 21:30:40 -04:00
Trevor Buckner
35431384bd Merge pull request #3453 from naturalcrit/dependabot/npm_and_yarn/googleapis/drive-8.8.0
Bump @googleapis/drive from 8.7.0 to 8.8.0
2024-05-03 21:30:26 -04:00
dependabot[bot]
dd31c0138b Bump @googleapis/drive from 8.7.0 to 8.8.0
Bumps [@googleapis/drive](https://github.com/googleapis/google-api-nodejs-client) from 8.7.0 to 8.8.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-config.json)
- [Commits](https://github.com/googleapis/google-api-nodejs-client/compare/drive-v8.7.0...drive-v8.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-04 01:24:32 +00:00
dependabot[bot]
11f1e3fee8 Bump eslint-plugin-jest from 28.2.0 to 28.5.0
Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 28.2.0 to 28.5.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/v28.2.0...v28.5.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-jest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-04 01:23:59 +00:00
Trevor Buckner
aaaa8ed693 Merge pull request #3446 from naturalcrit/makeCurlyInjectorsAppendNotOverwrite
Make Curly Injectors append properties, not overwrite
2024-05-03 21:23:01 -04:00
Víctor Losada Hernández
fec6bf290b Merge branch 'master' into makeCurlyInjectorsAppendNotOverwrite 2024-05-04 01:27:36 +02:00
Trevor Buckner
2418e42655 Align input texts for mustache tests 2024-05-03 17:10:12 -04:00
Trevor Buckner
dce86580ce Added additional tests for injection 2024-05-03 17:02:12 -04:00
Trevor Buckner
f6997871be Try to make tests work on both circleCI and windows 2024-05-03 15:01:21 -04:00
Trevor Buckner
660a586a7c Clarify comments 2024-05-03 15:01:04 -04:00
Trevor Buckner
193cde0925 Passes all tests 2024-05-03 14:31:34 -04:00
Trevor Buckner
1a33e6e631 Passing almost all tests 2024-05-03 12:48:19 -04:00
Trevor Buckner
bb8ade435d Now passing many previously failing tests 2024-05-03 12:40:03 -04:00
Trevor Buckner
94905f8151 Back to passing all tests (not the "failing" tests yet) 2024-05-03 12:12:55 -04:00
Víctor Losada Hernández
05a30f00e3 Merge branch 'master' into link-to-edit-if-author 2024-05-02 11:39:48 +02:00
Víctor Losada Hernández
3c1f8804af initial commit 2024-05-02 11:38:00 +02:00
Trevor Buckner
716e3d7143 Merge pull request #3428 from 5e-Cleric/paint-order-fix
drop shadow filter to text stroke
2024-05-01 17:21:15 -04:00
Víctor Losada Hernández
a0e6487a7b Merge branch 'master' into paint-order-fix 2024-05-01 21:58:31 +02:00
Víctor Losada Hernández
076599f05c to cm 2024-05-01 21:58:15 +02:00
Trevor Buckner
9fb0f37718 Pass CSS props from curly spans/divs as an object for finer control 2024-04-30 23:52:19 -04:00
dependabot[bot]
822f8a2cd0 Bump superagent from 9.0.1 to 9.0.2
Bumps [superagent](https://github.com/ladjs/superagent) from 9.0.1 to 9.0.2.
- [Release notes](https://github.com/ladjs/superagent/releases)
- [Changelog](https://github.com/ladjs/superagent/blob/master/HISTORY.md)
- [Commits](https://github.com/ladjs/superagent/compare/v9.0.1...v9.0.2)

---
updated-dependencies:
- dependency-name: superagent
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-30 14:10:06 -04:00
Trevor Buckner
d2965e1122 Merge pull request #3444 from naturalcrit/dependabot/npm_and_yarn/mongoose-8.3.3
Bump mongoose from 8.3.2 to 8.3.3
2024-04-30 14:09:57 -04:00
dependabot[bot]
37e211937c Bump mongoose from 8.3.2 to 8.3.3
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.3.2 to 8.3.3.
- [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.3.2...8.3.3)

---
updated-dependencies:
- dependency-name: mongoose
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-30 14:08:20 -04:00
Trevor Buckner
e7a03dc7d6 Merge pull request #3445 from naturalcrit/dependabot/npm_and_yarn/babel/preset-env-7.24.5
Bump @babel/preset-env from 7.24.4 to 7.24.5
2024-04-30 14:07:57 -04:00
Trevor Buckner
a469b88fd2 Merge branch 'master' into dependabot/npm_and_yarn/babel/preset-env-7.24.5 2024-04-30 14:05:44 -04:00
Trevor Buckner
45244c8e5d Merge pull request #3407 from Gazook89/errorPage.jsx-cleanup
Convert errorPage.jsx to functional component.
2024-04-30 13:43:20 -04:00
Trevor Buckner
fad5817353 Merge branch 'master' into errorPage.jsx-cleanup 2024-04-30 13:41:10 -04:00
Trevor Buckner
c0a8b79acc Small tweak 2024-04-30 13:40:39 -04:00
dependabot[bot]
34a41fd610 Bump @babel/preset-env from 7.24.4 to 7.24.5
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.24.4 to 7.24.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.24.5/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-30 03:58:07 +00:00
G.Ambatte
eb0440d36d Fix ID removal 2024-04-28 01:13:12 +12:00
G.Ambatte
cd82db16d5 Add DOMPurify config options 2024-04-28 00:49:03 +12:00
G.Ambatte
bdad601ebc Remove now-obsolete sanitization function 2024-04-27 23:58:55 +12:00
G.Ambatte
97a74902ef Add DOMPurify to BrewRenderer 2024-04-27 23:58:23 +12:00
G.Ambatte
ab30b6a799 Add DOM-Purify package 2024-04-27 23:38:55 +12:00
Víctor Losada Hernández
da6bc497fc eldeberry misstype rise dead 2024-04-26 23:07:06 +02:00
Trevor Buckner
06c3168868 Merge pull request #3429 from naturalcrit/dependabot/npm_and_yarn/multi-812b0dc3fc
Bump formidable, superagent and supertest
2024-04-25 10:45:55 -04:00
dependabot[bot]
86be90adb2 Bump formidable, superagent and supertest
Bumps [formidable](https://github.com/node-formidable/formidable) to 3.5.1 and updates ancestor dependencies [formidable](https://github.com/node-formidable/formidable), [superagent](https://github.com/ladjs/superagent) and [supertest](https://github.com/ladjs/supertest). These dependencies need to be updated together.


Updates `formidable` from 2.1.2 to 3.5.1
- [Release notes](https://github.com/node-formidable/formidable/releases)
- [Changelog](https://github.com/node-formidable/formidable/blob/master/CHANGELOG.md)
- [Commits](https://github.com/node-formidable/formidable/commits/v3.5.1)

Updates `superagent` from 8.1.2 to 9.0.1
- [Release notes](https://github.com/ladjs/superagent/releases)
- [Changelog](https://github.com/ladjs/superagent/blob/master/HISTORY.md)
- [Commits](https://github.com/ladjs/superagent/compare/v8.1.2...v9.0.1)

Updates `supertest` from 6.3.4 to 7.0.0
- [Release notes](https://github.com/ladjs/supertest/releases)
- [Commits](https://github.com/ladjs/supertest/compare/v6.3.4...v7.0.0)

---
updated-dependencies:
- dependency-name: formidable
  dependency-type: indirect
- dependency-name: superagent
  dependency-type: direct:production
- dependency-name: supertest
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-25 14:28:34 +00:00
Trevor Buckner
a296678d20 Merge pull request #3409 from naturalcrit/dependabot/npm_and_yarn/mongoose-8.3.2
Bump mongoose from 8.3.1 to 8.3.2
2024-04-25 10:27:36 -04:00
Trevor Buckner
f768990fb1 Merge branch 'master' into dependabot/npm_and_yarn/mongoose-8.3.2 2024-04-25 09:39:13 -04:00
Trevor Buckner
313543d0d1 Merge pull request #3424 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.23.0
Bump react-router-dom from 6.22.3 to 6.23.0
2024-04-25 09:39:03 -04:00
Víctor Losada Hernández
2ebe8d80e9 fix ei poison piercing 2024-04-25 15:15:07 +02:00
Víctor Losada Hernández
8c20422fef initial commit 2024-04-25 15:09:25 +02:00
dependabot[bot]
2197a9b782 Bump react-router-dom from 6.22.3 to 6.23.0
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.22.3 to 6.23.0.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.23.0/packages/react-router-dom)

---
updated-dependencies:
- dependency-name: react-router-dom
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-24 03:27:56 +00:00
Gazook89
928a8b351e Merge branch 'master' into RPG-Awesome-Redux 2024-04-21 20:12:56 -05:00
Gazook89
7ca38b88ad add RPG awesome icons
This branch just does the same thing as the RPG Awesome repo, but more closely aligns with the code used in the other icon fonts and isn't an NPM package.
2024-04-19 23:15:02 -05:00
Trevor Buckner
1891d7c90a Merge branch 'master' into dependabot/npm_and_yarn/mongoose-8.3.2 2024-04-19 12:10:55 -04:00
Trevor Buckner
98d032913b Update pr-check.yml 2024-04-19 12:00:11 -04:00
Trevor Buckner
80bcf92fa3 Update pr-check.yml 2024-04-19 11:57:44 -04:00
Trevor Buckner
41d536b7ff Merge pull request #3418 from naturalcrit/calculuschild-patch-2
Rename limit-pull-requests.yml to action.yml
2024-04-19 11:50:14 -04:00
Trevor Buckner
1e5e3d5f41 Rename limit-pull-requests.yml to action.yml 2024-04-19 11:50:01 -04:00
Trevor Buckner
19961c7ec5 Update pr-check.yml 2024-04-19 11:48:30 -04:00
Trevor Buckner
08e273bfd6 Update pr-check.yml 2024-04-19 11:37:23 -04:00
Trevor Buckner
9f45456066 Delete .github/workflows/limit-pull-requests.yml 2024-04-19 11:34:26 -04:00
Trevor Buckner
6e69696b4a Update pr-check.yml 2024-04-19 11:34:06 -04:00
Trevor Buckner
8b6be1cab8 Create limit-pull-requests.yml 2024-04-19 11:33:55 -04:00
Trevor Buckner
93a490e881 Merge pull request #3413 from naturalcrit/calculuschild-patch-1
Update pr-check.yml
2024-04-19 11:24:28 -04:00
Trevor Buckner
83103a893a add elderberryInn to emoji syntax 2024-04-18 23:06:21 -04:00
Trevor Buckner
8cbc7a68e5 Rename font-icons to elderberryInn 2024-04-18 23:06:02 -04:00
Trevor Buckner
1177fd721c Change diceFont to camelCase to match existing naming convention 2024-04-18 16:57:35 -04:00
Trevor Buckner
2c8908850b Merge branch 'master' into EmojiSyntax 2024-04-18 16:52:38 -04:00
Trevor Buckner
4622a74786 Merge branch 'master' into EmojiSyntax 2024-04-17 01:08:19 -04:00
Trevor Buckner
72cfca1158 Hack to avoid conflict with emojis 2024-04-17 00:56:43 -04:00
dependabot[bot]
67d824cac9 Bump mongoose from 8.3.1 to 8.3.2
Bumps [mongoose](https://github.com/Automattic/mongoose) from 8.3.1 to 8.3.2.
- [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.3.1...8.3.2)

---
updated-dependencies:
- dependency-name: mongoose
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-17 03:56:30 +00:00
Trevor Buckner
4f010d77e8 typo 2024-04-14 16:06:43 -04:00
Trevor Buckner
3b1f9b10e7 Clean up redundant code 2024-04-14 16:06:12 -04:00
Trevor Buckner
5e33d8b6c4 Sort alphabetically and numerically
i.e.,

"d2, d6, d8, d10, d12, d20", not "d10, d12, d2, d20, d6, d8"
2024-04-14 16:02:04 -04:00
Trevor Buckner
f7a2509405 Exclude : from the autocomplete trigger 2024-04-14 15:38:01 -04:00
Gazook89
52904eea09 add a comment 2024-04-13 20:47:38 -05:00
Gazook89
ff84ded547 Convert page to functional component 2024-04-13 11:10:43 -05:00
Gazook89
6220e4f63f Remove unused defaultProps
The defaultProps are not used, and may be a relic of previous error page function.
2024-04-13 10:30:04 -05:00
Trevor Buckner
b0c2521101 CodeMirror Dropdown working 2024-04-12 14:12:30 -04:00
Murdo B. Maclachlan
30d2a03fd0 Added proficiency bonus to monster statblocks 2024-04-12 11:19:48 +01:00
Trevor Buckner
61a4b558a8 Include Dicefont 2024-04-10 18:25:45 -04:00
Trevor Buckner
3771d4bfd8 Include marked-emoji package 2024-04-10 17:50:33 -04:00
69 changed files with 4682 additions and 1028 deletions

View File

@@ -11,14 +11,18 @@ permissions:
statuses: write
jobs:
limit-pull-requests:
if: always() && github.repository_owner == 'Homebrew'
if: always() && github.repository_owner == 'naturalcrit'
runs-on: ubuntu-latest
steps:
- uses: Homebrew/actions/limit-pull-requests@master
- name: Checkout
uses: actions/checkout@v2
- name : Run limit-pull-requests action
uses: ./.github/actions/limit-pull-requests
with:
except-users: |
dependabot
comment-limit: 1
comment-limit: 3
comment: |
Hi, thanks for your contribution to the Homebrewery! You already have >=3 open pull requests. Consider completing some of your existing PRs before opening new ones. Thanks!
close-limit: 5

View File

@@ -1,7 +1,6 @@
require('./brewCleanup.less');
const React = require('react');
const createClass = require('create-react-class');
const cx = require('classnames');
const request = require('superagent');

View File

@@ -1,7 +1,6 @@
require('./brewCompress.less');
const React = require('react');
const createClass = require('create-react-class');
const cx = require('classnames');
const request = require('superagent');

View File

@@ -1,7 +1,6 @@
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
require('./combobox.less');
const Combobox = createClass({

View File

@@ -13,6 +13,10 @@ const RenderWarnings = require('homebrewery/renderWarnings/renderWarnings.jsx');
const NotificationPopup = require('./notificationPopup/notificationPopup.jsx');
const Frame = require('react-frame-component').default;
const dedent = require('dedent-tabs').default;
const { printCurrentBrew } = require('../../../shared/helpers.js');
const DOMPurify = require('dompurify');
const purifyConfig = { FORCE_BODY: true, SANITIZE_DOM: false };
const Themes = require('themes/themes.json');
@@ -33,8 +37,9 @@ const BrewPage = (props)=>{
index : 0,
...props
};
const cleanText = DOMPurify.sanitize(props.contents, purifyConfig);
return <div className={props.className} id={`p${props.index + 1}`} >
<div className='columnWrapper' dangerouslySetInnerHTML={{ __html: props.contents }} />
<div className='columnWrapper' dangerouslySetInnerHTML={{ __html: cleanText }} />
</div>;
};
@@ -102,13 +107,6 @@ const BrewRenderer = (props)=>{
return false;
};
const sanitizeScriptTags = (content)=>{
return content
?.replace(/<script/ig, '&lt;script')
.replace(/<\/script>/ig, '&lt;/script&gt;')
|| '';
};
const renderPageInfo = ()=>{
return <div className='pageInfo' ref={mainRef}>
<div>
@@ -128,19 +126,18 @@ const BrewRenderer = (props)=>{
const renderStyle = ()=>{
if(!props.style) return;
const cleanStyle = sanitizeScriptTags(props.style);
const cleanStyle = DOMPurify.sanitize(props.style, purifyConfig);
//return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>@layer styleTab {\n${sanitizeScriptTags(props.style)}\n} </style>` }} />;
return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style> ${cleanStyle} </style>` }} />;
};
const renderPage = (pageText, index)=>{
let cleanPageText = sanitizeScriptTags(pageText);
if(props.renderer == 'legacy') {
const html = MarkdownLegacy.render(cleanPageText);
const html = MarkdownLegacy.render(pageText);
return <BrewPage className='page phb' index={index} key={index} contents={html} />;
} else {
cleanPageText += `\n\n&nbsp;\n\\column\n&nbsp;`; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear)
const html = Markdown.render(cleanPageText, index);
pageText += `\n\n&nbsp;\n\\column\n&nbsp;`; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear)
const html = Markdown.render(pageText, index);
return <BrewPage className='page' index={index} key={index} contents={html} />;
}
};
@@ -163,6 +160,16 @@ const BrewRenderer = (props)=>{
return renderedPages;
};
const handleControlKeys = (e)=>{
if(!(e.ctrlKey || e.metaKey)) return;
const P_KEY = 80;
if(e.keyCode == P_KEY && props.allowPrint) printCurrentBrew();
if(e.keyCode == P_KEY) {
e.stopPropagation();
e.preventDefault();
}
};
const frameDidMount = ()=>{ //This triggers when iFrame finishes internal "componentDidMount"
setTimeout(()=>{ //We still see a flicker where the style isn't applied yet, so wait 100ms before showing iFrame
updateSize();
@@ -204,6 +211,8 @@ const BrewRenderer = (props)=>{
>
<div className={'brewRenderer'}
onScroll={handleScroll}
onKeyDown={handleControlKeys}
tabIndex={-1}
style={{ height: state.height }}>
<ErrorBar errors={props.errors} />
@@ -211,11 +220,11 @@ const BrewRenderer = (props)=>{
<RenderWarnings />
<NotificationPopup />
</div>
<link href={`/themes/${rendererPath}/Blank/style.css`} type="text/css" rel='stylesheet'/>
<link href={`/themes/${rendererPath}/Blank/style.css`} type='text/css' rel='stylesheet'/>
{baseThemePath &&
<link href={`/themes/${rendererPath}/${baseThemePath}/style.css`} type="text/css" rel='stylesheet'/>
<link href={`/themes/${rendererPath}/${baseThemePath}/style.css`} type='text/css' rel='stylesheet'/>
}
<link href={`/themes/${rendererPath}/${themePath}/style.css`} type="text/css" rel='stylesheet'/>
<link href={`/themes/${rendererPath}/${themePath}/style.css`} type='text/css' rel='stylesheet'/>
{/* Apply CSS from Style tab and render pages from Markdown tab */}
{state.isMounted

View File

@@ -64,3 +64,16 @@
color : white;
background-color : #333333;
}
@media print {
.brewRenderer {
height: 100%;
overflow-y: unset;
.pages {
margin: 0px;
&>.page {
box-shadow: unset;
}
}
}
}

View File

@@ -2,7 +2,6 @@ require('./errorBar.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const ErrorBar = createClass({
displayName : 'ErrorBar',

View File

@@ -2,7 +2,6 @@ require('./notificationPopup.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames'); //Unused variable
const DISMISS_KEY = 'dismiss_notification12-04-23';
@@ -26,8 +25,8 @@ const NotificationPopup = createClass({
<>
<li key='psa'>
<em>Don't store IMAGES in Google Drive</em><br />
Google Drive is not an image service, and will block images from being used
in brews if they get more views than expected. Google has confirmed they won't fix
Google Drive is not an image service, and will block images from being used
in brews if they get more views than expected. Google has confirmed they won't fix
this, so we recommend you look for another image hosting service such as imgur, ImgBB or Google Photos.
</li>

View File

@@ -5,6 +5,7 @@ const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const dedent = require('dedent-tabs').default;
const Markdown = require('../../../shared/naturalcrit/markdown.js');
const CodeEditor = require('naturalcrit/codeEditor/codeEditor.jsx');
const SnippetBar = require('./snippetbar/snippetbar.jsx');
@@ -47,6 +48,9 @@ const Editor = createClass({
};
},
editor : React.createRef(null),
codeEditor : React.createRef(null),
isText : function() {return this.state.view == 'text';},
isStyle : function() {return this.state.view == 'style';},
isMeta : function() {return this.state.view == 'meta';},
@@ -79,15 +83,15 @@ const Editor = createClass({
},
updateEditorSize : function() {
if(this.refs.codeEditor) {
let paneHeight = this.refs.main.parentNode.clientHeight;
if(this.codeEditor.current) {
let paneHeight = this.editor.current.parentNode.clientHeight;
paneHeight -= SNIPPETBAR_HEIGHT;
this.refs.codeEditor.codeMirror.setSize(null, paneHeight);
this.codeEditor.current.codeMirror.setSize(null, paneHeight);
}
},
handleInject : function(injectText){
this.refs.codeEditor?.injectText(injectText, false);
this.codeEditor.current?.injectText(injectText, false);
},
handleViewChange : function(newView){
@@ -98,7 +102,7 @@ const Editor = createClass({
},
getCurrentPage : function(){
const lines = this.props.brew.text.split('\n').slice(0, this.refs.codeEditor.getCursorPosition().line + 1);
const lines = this.props.brew.text.split('\n').slice(0, this.codeEditor.current.getCursorPosition().line + 1);
return _.reduce(lines, (r, line)=>{
if(
(this.props.renderer == 'legacy' && line.indexOf('\\page') !== -1)
@@ -110,9 +114,9 @@ const Editor = createClass({
},
highlightCustomMarkdown : function(){
if(!this.refs.codeEditor) return;
if(!this.codeEditor.current) return;
if(this.state.view === 'text') {
const codeMirror = this.refs.codeEditor.codeMirror;
const codeMirror = this.codeEditor.current.codeMirror;
codeMirror.operation(()=>{ // Batch CodeMirror styling
//reset custom text styles
@@ -219,6 +223,34 @@ const Editor = createClass({
endCh = match.index+match[0].length;
codeMirror.markText({ line: lineNumber, ch: 0 }, { line: lineNumber, ch: endCh }, { className: 'block' });
}
// Emojis
if(line.match(/:[^\s:]+:/g)) {
let startIndex = line.indexOf(':');
const emojiRegex = /:[^\s:]+:/gy;
while (startIndex >= 0) {
emojiRegex.lastIndex = startIndex;
let match = emojiRegex.exec(line);
if (match) {
let tokens = Markdown.marked.lexer(match[0]);
tokens = tokens[0].tokens.filter(t => t.type == 'emoji')
if (!tokens.length)
return;
let startPos = { line: lineNumber, ch: match.index };
let endPos = { line: lineNumber, ch: match.index + match[0].length };
// Iterate over conflicting marks and clear them
var marks = codeMirror.findMarks(startPos, endPos);
marks.forEach(function(marker) {
marker.clear();
});
codeMirror.markText(startPos, endPos, { className: 'emoji' });
}
startIndex = line.indexOf(':', Math.max(startIndex + 1, emojiRegex.lastIndex));
}
}
}
});
});
@@ -273,23 +305,23 @@ const Editor = createClass({
targetLine = lineCount - 1; //Scroll to `\page`, which is one line back.
let currentY = this.refs.codeEditor.codeMirror.getScrollInfo().top;
let targetY = this.refs.codeEditor.codeMirror.heightAtLine(targetLine, 'local', true);
let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top;
let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true);
//Scroll 1/10 of the way every 10ms until 1px off.
const incrementalScroll = setInterval(()=>{
currentY += (targetY - currentY) / 10;
this.refs.codeEditor.codeMirror.scrollTo(null, currentY);
this.codeEditor.current.codeMirror.scrollTo(null, currentY);
// Update target: target height is not accurate until within +-10 lines of the visible window
if(Math.abs(targetY - currentY > 100))
targetY = this.refs.codeEditor.codeMirror.heightAtLine(targetLine, 'local', true);
targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true);
// End when close enough
if(Math.abs(targetY - currentY) < 1) {
this.refs.codeEditor.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference
this.refs.codeEditor.setCursorPosition({ line: targetLine + 1, ch: 0 });
this.refs.codeEditor.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash');
this.codeEditor.current.codeMirror.scrollTo(null, targetY); // Scroll any remaining difference
this.codeEditor.current.setCursorPosition({ line: targetLine + 1, ch: 0 });
this.codeEditor.current.codeMirror.addLineClass(targetLine + 1, 'wrap', 'sourceMoveFlash');
clearInterval(incrementalScroll);
}
}, 10);
@@ -299,7 +331,7 @@ const Editor = createClass({
//Called when there are changes to the editor's dimensions
update : function(){
this.refs.codeEditor?.updateSize();
this.codeEditor.current?.updateSize();
},
updateEditorTheme : function(newTheme){
@@ -318,7 +350,7 @@ const Editor = createClass({
if(this.isText()){
return <>
<CodeEditor key='codeEditor'
ref='codeEditor'
ref={this.codeEditor}
language='gfm'
view={this.state.view}
value={this.props.brew.text}
@@ -330,7 +362,7 @@ const Editor = createClass({
if(this.isStyle()){
return <>
<CodeEditor key='codeEditor'
ref='codeEditor'
ref={this.codeEditor}
language='css'
view={this.state.view}
value={this.props.brew.style ?? DEFAULT_STYLE_TEXT}
@@ -355,28 +387,28 @@ const Editor = createClass({
},
redo : function(){
return this.refs.codeEditor?.redo();
return this.codeEditor.current?.redo();
},
historySize : function(){
return this.refs.codeEditor?.historySize();
return this.codeEditor.current?.historySize();
},
undo : function(){
return this.refs.codeEditor?.undo();
return this.codeEditor.current?.undo();
},
foldCode : function(){
return this.refs.codeEditor?.foldAllCode();
return this.codeEditor.current?.foldAllCode();
},
unfoldCode : function(){
return this.refs.codeEditor?.unfoldAllCode();
return this.codeEditor.current?.unfoldAllCode();
},
render : function(){
return (
<div className='editor' ref='main'>
<div className='editor' ref={this.editor}>
<SnippetBar
brew={this.props.brew}
view={this.state.view}
@@ -392,7 +424,7 @@ const Editor = createClass({
historySize={this.historySize()}
currentEditorTheme={this.state.editorTheme}
updateEditorTheme={this.updateEditorTheme}
cursorPos={this.refs.codeEditor?.getCursorPosition() || {}} />
cursorPos={this.codeEditor.current?.getCursorPosition() || {}} />
{this.renderEditor()}
</div>

View File

@@ -43,6 +43,16 @@
font-weight : bold;
color : green;
}
.emoji:not(.cm-comment) {
margin-left : 2px;
color : #360034;
background : #ffc8ff;
border-radius : 6px;
font-weight : bold;
padding-bottom : 1px;
outline-offset : -2px;
outline : solid 2px #ff96fc;
}
.superscript:not(.cm-comment) {
font-weight : bold;
color : goldenrod;

View File

@@ -3,7 +3,6 @@ require('./metadataEditor.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const request = require('../../utils/request-middleware.js');
const Nav = require('naturalcrit/nav/nav.jsx');
const Combobox = require('client/components/combobox.jsx');

View File

@@ -161,7 +161,7 @@ const Snippetbar = createClass({
onClick={this.props.unfoldCode} >
<i className='fas fa-expand-alt' />
</div>
</>
</>;
}
@@ -181,7 +181,7 @@ const Snippetbar = createClass({
<i className='fas fa-palette' />
{this.state.themeSelector && this.renderThemeSelector()}
</div>
<div className='divider'></div>
<div className={cx('text', { selected: this.props.view === 'text' })}
onClick={()=>this.props.onViewChange('text')}>

View File

@@ -10,7 +10,6 @@ const UserPage = require('./pages/userPage/userPage.jsx');
const SharePage = require('./pages/sharePage/sharePage.jsx');
const NewPage = require('./pages/newPage/newPage.jsx');
const ErrorPage = require('./pages/errorPage/errorPage.jsx');
const PrintPage = require('./pages/printPage/printPage.jsx');
const AccountPage = require('./pages/accountPage/accountPage.jsx');
const WithRoute = (props)=>{
@@ -72,15 +71,13 @@ const Homebrew = createClass({
<Route path='/new/:id' element={<WithRoute el={NewPage} brew={this.props.brew} />} />
<Route path='/new' element={<WithRoute el={NewPage}/>} />
<Route path='/user/:username' element={<WithRoute el={UserPage} brews={this.props.brews} />} />
<Route path='/print/:id' element={<WithRoute el={PrintPage} brew={this.props.brew} />} />
<Route path='/print' element={<WithRoute el={PrintPage} />} />
<Route path='/changelog' element={<WithRoute el={SharePage} brew={this.props.brew} />} />
<Route path='/faq' element={<WithRoute el={SharePage} brew={this.props.brew} />} />
<Route path='/account' element={<WithRoute el={AccountPage} brew={this.props.brew} accountDetails={this.props.brew.accountDetails} />} />
<Route path='/legacy' element={<WithRoute el={HomePage} brew={this.props.brew} />} />
<Route path='/error' element={<WithRoute el={ErrorPage} brew={this.props.brew} />} />
<Route path='/' element={<WithRoute el={HomePage} brew={this.props.brew} />} />
<Route path='/*' element={<WithRoute el={HomePage} brew={this.props.brew} />} />
<Route path='/' element={<WithRoute el={HomePage} brew={this.props.brew} />} />
<Route path='/*' element={<WithRoute el={HomePage} brew={this.props.brew} />} />
</Routes>
</div>
</Router>
@@ -88,15 +85,4 @@ const Homebrew = createClass({
}
});
module.exports = Homebrew;
//TODO: Nicer Error page instead of just "cant get that"
// '/share/:id' : (args)=>{
// if(!this.props.brew.shareId){
// return <ErrorPage errorId={args.id}/>;
// }
//
// return <SharePage
// id={args.id}
// brew={this.props.brew} />;
// },
module.exports = Homebrew;

View File

@@ -42,7 +42,7 @@ const ErrorNavItem = createClass({
</div>
</Nav.item>;
}
if(status === 412) {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
@@ -51,7 +51,7 @@ const ErrorNavItem = createClass({
</div>
</Nav.item>;
}
if(HBErrorCode === '04') {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
@@ -76,10 +76,10 @@ const ErrorNavItem = createClass({
if(response.body?.errors?.[0].reason == 'storageQuotaExceeded') {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
<div className='errorContainer' onClick={clearError}>
Can't save because your Google Drive seems to be full!
</div>
</Nav.item>;
</div>
</Nav.item>;
}
if(response.req.url.match(/^\/api.*Google.*$/m)){

View File

@@ -1,6 +1,4 @@
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const dedent = require('dedent-tabs').default;
const Nav = require('naturalcrit/nav/nav.jsx');

View File

@@ -1,6 +1,5 @@
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const Moment = require('moment');
const Nav = require('naturalcrit/nav/nav.jsx');

View File

@@ -7,58 +7,58 @@ const BREWKEY = 'homebrewery-new';
const STYLEKEY = 'homebrewery-new-style';
const METAKEY = 'homebrewery-new-meta';
const NewBrew = () => {
const handleFileChange = (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
const fileContent = e.target.result;
const newBrew = {
text: fileContent,
style: ''
};
if(fileContent.startsWith('```metadata')) {
splitTextStyleAndMetadata(newBrew); // Modify newBrew directly
localStorage.setItem(BREWKEY, newBrew.text);
localStorage.setItem(STYLEKEY, newBrew.style);
localStorage.setItem(METAKEY, JSON.stringify(_.pick(newBrew, ['title', 'description', 'tags', 'systems', 'renderer', 'theme', 'lang'])));
window.location.href = '/new';
} else {
alert('This file is invalid, please, enter a valid file');
}
};
reader.readAsText(file);
}
};
const NewBrew = ()=>{
const handleFileChange = (e)=>{
const file = e.target.files[0];
if(file) {
const reader = new FileReader();
reader.onload = (e)=>{
const fileContent = e.target.result;
const newBrew = {
text : fileContent,
style : ''
};
if(fileContent.startsWith('```metadata')) {
splitTextStyleAndMetadata(newBrew); // Modify newBrew directly
localStorage.setItem(BREWKEY, newBrew.text);
localStorage.setItem(STYLEKEY, newBrew.style);
localStorage.setItem(METAKEY, JSON.stringify(_.pick(newBrew, ['title', 'description', 'tags', 'systems', 'renderer', 'theme', 'lang'])));
window.location.href = '/new';
} else {
alert('This file is invalid, please, enter a valid file');
}
};
reader.readAsText(file);
}
};
return (
<Nav.dropdown>
<Nav.item
className='new'
color='purple'
icon='fa-solid fa-plus-square'>
return (
<Nav.dropdown>
<Nav.item
className='new'
color='purple'
icon='fa-solid fa-plus-square'>
new
</Nav.item>
<Nav.item
className='fromBlank'
href='/new'
newTab={true}
color='purple'
icon='fa-solid fa-file'>
</Nav.item>
<Nav.item
className='fromBlank'
href='/new'
newTab={true}
color='purple'
icon='fa-solid fa-file'>
from blank
</Nav.item>
</Nav.item>
<Nav.item
className='fromFile'
color='purple'
icon='fa-solid fa-upload'
onClick={() => { document.getElementById('uploadTxt').click(); }}>
<input id="uploadTxt" className='newFromLocal' type="file" onChange={handleFileChange} style={{ display: 'none' }} />
<Nav.item
className='fromFile'
color='purple'
icon='fa-solid fa-upload'
onClick={()=>{ document.getElementById('uploadTxt').click(); }}>
<input id='uploadTxt' className='newFromLocal' type='file' onChange={handleFileChange} style={{ display: 'none' }} />
from file
</Nav.item>
</Nav.dropdown>
);
</Nav.item>
</Nav.dropdown>
);
};
module.exports = NewBrew;

View File

@@ -1,9 +1,9 @@
const React = require('react');
const createClass = require('create-react-class');
const Nav = require('naturalcrit/nav/nav.jsx');
const { printCurrentBrew } = require('../../../shared/helpers.js');
module.exports = function(props){
return <Nav.item newTab={true} href={`/print/${props.shareId}?dialog=true`} color='purple' icon='far fa-file-pdf'>
module.exports = function(){
return <Nav.item onClick={printCurrentBrew} color='purple' icon='far fa-file-pdf'>
get PDF
</Nav.item>;
};

View File

@@ -1,9 +1,7 @@
const React = require('react');
const createClass = require('create-react-class');
const cx = require('classnames');
const Nav = require('naturalcrit/nav/nav.jsx');
const MAX_URL_SIZE = 2083;
const MAIN_URL = 'https://www.reddit.com/r/UnearthedArcana/submit?selftext=true';

View File

@@ -1,8 +1,6 @@
require('./brewItem.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const moment = require('moment');
const request = require('../../../../utils/request-middleware.js');

View File

@@ -262,8 +262,8 @@ const ListPage = createClass({
render : function(){
return <div className='listPage sitePage'>
{/*<style>@layer V3_5ePHB, bundle;</style>*/}
<link href='/themes/V3/Blank/style.css' type="text/css" rel='stylesheet'/>
<link href='/themes/V3/5ePHB/style.css' type="text/css" rel='stylesheet'/>
<link href='/themes/V3/Blank/style.css' type='text/css' rel='stylesheet'/>
<link href='/themes/V3/5ePHB/style.css' type='text/css' rel='stylesheet'/>
{this.props.navItems}
{this.renderSortOptions()}
{this.renderTagsOptions()}

View File

@@ -11,7 +11,7 @@ const Navbar = require('../../navbar/navbar.jsx');
const NewBrew = require('../../navbar/newbrew.navitem.jsx');
const HelpNavItem = require('../../navbar/help.navitem.jsx');
const PrintLink = require('../../navbar/print.navitem.jsx');
const PrintNavItem = require('../../navbar/print.navitem.jsx');
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
const Account = require('../../navbar/account.navitem.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
@@ -23,6 +23,7 @@ const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
const Markdown = require('naturalcrit/markdown.js');
const { DEFAULT_BREW_LOAD } = require('../../../../server/brewDefaults.js');
const { printCurrentBrew } = require('../../../../shared/helpers.js');
const googleDriveIcon = require('../../googleDrive.svg');
@@ -54,6 +55,8 @@ const EditPage = createClass({
currentEditorPage : 0
};
},
editor : React.createRef(null),
savedBrew : null,
componentDidMount : function(){
@@ -93,7 +96,7 @@ const EditPage = createClass({
const S_KEY = 83;
const P_KEY = 80;
if(e.keyCode == S_KEY) this.trySave(true);
if(e.keyCode == P_KEY) window.open(`/print/${this.processShareId()}?dialog=true`, '_blank').focus();
if(e.keyCode == P_KEY) printCurrentBrew();
if(e.keyCode == P_KEY || e.keyCode == S_KEY){
e.stopPropagation();
e.preventDefault();
@@ -101,7 +104,7 @@ const EditPage = createClass({
},
handleSplitMove : function(){
this.refs.editor.update();
this.editor.current.update();
},
handleTextChange : function(text){
@@ -113,7 +116,7 @@ const EditPage = createClass({
brew : { ...prevState.brew, text: text },
isPending : true,
htmlErrors : htmlErrors,
currentEditorPage : this.refs.editor.getCurrentPage() - 1 //Offset index since Marked starts pages at 0
currentEditorPage : this.editor.current.getCurrentPage() - 1 //Offset index since Marked starts pages at 0
}), ()=>{if(this.state.autoSave) this.trySave();});
},
@@ -376,7 +379,7 @@ const EditPage = createClass({
post to reddit
</Nav.item>
</Nav.dropdown>
<PrintLink shareId={this.processShareId()} />
<PrintNavItem />
<RecentNavItem brew={this.state.brew} storageKey='edit' />
<Account />
</Nav.section>
@@ -390,9 +393,9 @@ const EditPage = createClass({
{this.renderNavbar()}
<div className='content'>
<SplitPane onDragFinish={this.handleSplitMove} ref='pane'>
<SplitPane onDragFinish={this.handleSplitMove}>
<Editor
ref='editor'
ref={this.editor}
brew={this.state.brew}
onTextChange={this.handleTextChange}
onStyleChange={this.handleStyleChange}
@@ -408,6 +411,7 @@ const EditPage = createClass({
errors={this.state.htmlErrors}
lang={this.state.brew.lang}
currentEditorPage={this.state.currentEditorPage}
allowPrint={true}
/>
</SplitPane>
</div>

View File

@@ -1,41 +1,25 @@
require('./errorPage.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const UIPage = require('../basePages/uiPage/uiPage.jsx');
const Markdown = require('../../../../shared/naturalcrit/markdown.js');
const React = require('react');
const UIPage = require('../basePages/uiPage/uiPage.jsx');
const Markdown = require('../../../../shared/naturalcrit/markdown.js');
const ErrorIndex = require('./errors/errorIndex.js');
const ErrorPage = createClass({
displayName : 'ErrorPage',
const ErrorPage = ({ brew })=>{
// Retrieving the error text based on the brew's error code from ErrorIndex
const errorText = ErrorIndex({ brew })[brew.HBErrorCode.toString()] || '';
getDefaultProps : function() {
return {
ver : '0.0.0',
errorId : '',
text : '# Oops \n We could not find a brew with that id. **Sorry!**',
error : {}
};
},
render : function(){
const errorText = ErrorIndex(this.props)[this.props.brew.HBErrorCode.toString()] || '';
return <UIPage brew={{ title: 'Crit Fail!' }}>
return (
<UIPage brew={{ title: 'Crit Fail!' }}>
<div className='dataGroup'>
<div className='errorTitle'>
<h1>{`Error ${this.props.brew.status || '000'}`}</h1>
<h4>{this.props.brew.text || 'No error text'}</h4>
<h1>{`Error ${brew?.status || '000'}`}</h1>
<h4>{brew?.text || 'No error text'}</h4>
</div>
<hr />
<div dangerouslySetInnerHTML={{ __html: Markdown.render(errorText) }} />
</div>
</UIPage>;
}
});
</UIPage>
);
};
module.exports = ErrorPage;

View File

@@ -95,7 +95,7 @@ const errorIndex = (props)=>{
**Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'}
[Click here to be redirected to the brew's share page.](/share/${props.brew.shareId})`,
// Brew load error
'05' : dedent`

View File

@@ -1,12 +0,0 @@
//TODO: Depricate
module.exports = function(shareId){
return function(event){
event = event || window.event;
if((event.ctrlKey || event.metaKey) && event.keyCode == 80){
const win = window.open(`/homebrew/print/${shareId}?dialog=true`, '_blank');
win.focus();
event.preventDefault();
}
};
};

View File

@@ -37,6 +37,9 @@ const HomePage = createClass({
currentEditorPage : 0
};
},
editor : React.createRef(null),
handleSave : function(){
request.post('/api')
.send(this.state.brew)
@@ -50,12 +53,12 @@ const HomePage = createClass({
});
},
handleSplitMove : function(){
this.refs.editor.update();
this.editor.current.update();
},
handleTextChange : function(text){
this.setState((prevState)=>({
brew : { ...prevState.brew, text: text },
currentEditorPage : this.refs.editor.getCurrentPage() - 1 //Offset index since Marked starts pages at 0
currentEditorPage : this.editor.current.getCurrentPage() - 1 //Offset index since Marked starts pages at 0
}));
},
renderNavbar : function(){
@@ -79,9 +82,9 @@ const HomePage = createClass({
{this.renderNavbar()}
<div className='content'>
<SplitPane onDragFinish={this.handleSplitMove} ref='pane'>
<SplitPane onDragFinish={this.handleSplitMove}>
<Editor
ref='editor'
ref={this.editor}
brew={this.state.brew}
onTextChange={this.handleTextChange}
renderer={this.state.brew.renderer}

View File

@@ -2,12 +2,12 @@
require('./newPage.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const request = require('../../utils/request-middleware.js');
const Markdown = require('naturalcrit/markdown.js');
const Nav = require('naturalcrit/nav/nav.jsx');
const PrintNavItem = require('../../navbar/print.navitem.jsx');
const Navbar = require('../../navbar/navbar.jsx');
const AccountNavItem = require('../../navbar/account.navitem.jsx');
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
@@ -19,6 +19,7 @@ const Editor = require('../../editor/editor.jsx');
const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
const { DEFAULT_BREW } = require('../../../../server/brewDefaults.js');
const { printCurrentBrew } = require('../../../../shared/helpers.js');
const BREWKEY = 'homebrewery-new';
const STYLEKEY = 'homebrewery-new-style';
@@ -47,6 +48,8 @@ const NewPage = createClass({
};
},
editor : React.createRef(null),
componentDidMount : function() {
document.addEventListener('keydown', this.handleControlKeys);
@@ -88,7 +91,7 @@ const NewPage = createClass({
const S_KEY = 83;
const P_KEY = 80;
if(e.keyCode == S_KEY) this.save();
if(e.keyCode == P_KEY) this.print();
if(e.keyCode == P_KEY) printCurrentBrew();
if(e.keyCode == P_KEY || e.keyCode == S_KEY){
e.stopPropagation();
e.preventDefault();
@@ -96,7 +99,7 @@ const NewPage = createClass({
},
handleSplitMove : function(){
this.refs.editor.update();
this.editor.current.update();
},
handleTextChange : function(text){
@@ -107,7 +110,7 @@ const NewPage = createClass({
this.setState((prevState)=>({
brew : { ...prevState.brew, text: text },
htmlErrors : htmlErrors,
currentEditorPage : this.refs.editor.getCurrentPage() - 1 //Offset index since Marked starts pages at 0
currentEditorPage : this.editor.current.getCurrentPage() - 1 //Offset index since Marked starts pages at 0
}));
localStorage.setItem(BREWKEY, text);
},
@@ -179,16 +182,6 @@ const NewPage = createClass({
}
},
print : function(){
window.open('/print?dialog=true&local=print', '_blank');
},
renderLocalPrintButton : function(){
return <Nav.item color='purple' icon='far fa-file-pdf' onClick={this.print}>
get PDF
</Nav.item>;
},
renderNavbar : function(){
return <Navbar>
@@ -201,7 +194,7 @@ const NewPage = createClass({
<ErrorNavItem error={this.state.error} parent={this}></ErrorNavItem> :
this.renderSaveButton()
}
{this.renderLocalPrintButton()}
<PrintNavItem />
<HelpNavItem />
<RecentNavItem />
<AccountNavItem />
@@ -213,9 +206,9 @@ const NewPage = createClass({
return <div className='newPage sitePage'>
{this.renderNavbar()}
<div className='content'>
<SplitPane onDragFinish={this.handleSplitMove} ref='pane'>
<SplitPane onDragFinish={this.handleSplitMove}>
<Editor
ref='editor'
ref={this.editor}
brew={this.state.brew}
onTextChange={this.handleTextChange}
onStyleChange={this.handleStyleChange}
@@ -230,6 +223,7 @@ const NewPage = createClass({
errors={this.state.htmlErrors}
lang={this.state.brew.lang}
currentEditorPage={this.state.currentEditorPage}
allowPrint={true}
/>
</SplitPane>
</div>

View File

@@ -1,113 +0,0 @@
require('./printPage.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const { Meta } = require('vitreum/headtags');
const MarkdownLegacy = require('naturalcrit/markdownLegacy.js');
const Markdown = require('naturalcrit/markdown.js');
const Themes = require('themes/themes.json');
const BREWKEY = 'homebrewery-new';
const STYLEKEY = 'homebrewery-new-style';
const METAKEY = 'homebrewery-new-meta';
const PrintPage = createClass({
displayName : 'PrintPage',
getDefaultProps : function() {
return {
query : {},
brew : {
text : '',
style : '',
renderer : 'legacy',
lang : ''
}
};
},
getInitialState : function() {
return {
brew : {
text : this.props.brew.text || '',
style : this.props.brew.style || undefined,
renderer : this.props.brew.renderer || 'legacy',
theme : this.props.brew.theme || '5ePHB',
lang : this.props.brew.lang || 'en'
}
};
},
componentDidMount : function() {
if(this.props.query.local == 'print'){
const brewStorage = localStorage.getItem(BREWKEY);
const styleStorage = localStorage.getItem(STYLEKEY);
const metaStorage = JSON.parse(localStorage.getItem(METAKEY));
this.setState((prevState, prevProps)=>{
return {
brew : {
text : brewStorage,
style : styleStorage,
renderer : metaStorage?.renderer || 'legacy',
theme : metaStorage?.theme || '5ePHB',
lang : metaStorage?.lang || 'en'
}
};
});
}
if(this.props.query.dialog) window.print();
},
renderStyle : function() {
if(!this.state.brew.style) return;
//return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>@layer styleTab {\n${this.state.brew.style}\n} </style>` }} />;
return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>\n${this.state.brew.style}\n</style>` }} />;
},
renderPages : function(){
if(this.state.brew.renderer == 'legacy') {
return _.map(this.state.brew.text.split('\\page'), (pageText, index)=>{
return <div
className='phb page'
id={`p${index + 1}`}
dangerouslySetInnerHTML={{ __html: MarkdownLegacy.render(pageText) }}
key={index} />;
});
} else {
return _.map(this.state.brew.text.split(/^\\page$/gm), (pageText, index)=>{
pageText += `\n\n&nbsp;\n\\column\n&nbsp;`; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear)
return (
<div className='page' id={`p${index + 1}`} key={index} >
<div className='columnWrapper' dangerouslySetInnerHTML={{ __html: Markdown.render(pageText) }} />
</div>
);
});
}
},
render : function(){
const rendererPath = this.state.brew.renderer == 'V3' ? 'V3' : 'Legacy';
const themePath = this.state.brew.theme ?? '5ePHB';
const baseThemePath = Themes[rendererPath][themePath].baseTheme;
return <div>
<Meta name='robots' content='noindex, nofollow' />
<link href={`/themes/${rendererPath}/Blank/style.css`} type="text/css" rel='stylesheet'/>
{baseThemePath &&
<link href={`/themes/${rendererPath}/${baseThemePath}/style.css`} type="text/css" rel='stylesheet'/>
}
<link href={`/themes/${rendererPath}/${themePath}/style.css`} type="text/css" rel='stylesheet'/>
{/* Apply CSS from Style tab */}
{this.renderStyle()}
<div className='pages' ref='pages' lang={this.state.brew.lang}>
{this.renderPages()}
</div>
</div>;
}
});
module.exports = PrintPage;

View File

@@ -1,3 +0,0 @@
.printPage{
}

View File

@@ -6,14 +6,13 @@ 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 PrintLink = require('../../navbar/print.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 BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
const { DEFAULT_BREW_LOAD } = require('../../../../server/brewDefaults.js');
const { printCurrentBrew } = require('../../../../shared/helpers.js');
const SharePage = createClass({
displayName : 'SharePage',
@@ -35,7 +34,7 @@ const SharePage = createClass({
if(!(e.ctrlKey || e.metaKey)) return;
const P_KEY = 80;
if(e.keyCode == P_KEY){
window.open(`/print/${this.processShareId()}?dialog=true`, '_blank').focus();
if(e.keyCode == P_KEY) printCurrentBrew();
e.stopPropagation();
e.preventDefault();
}
@@ -47,6 +46,19 @@ const SharePage = createClass({
this.props.brew.shareId;
},
renderEditLink : function(){
if(!this.props.brew.editId) return;
let editLink = this.props.brew.editId;
if(this.props.brew.googleId && !this.props.brew.stubbed) {
editLink = this.props.brew.googleId + editLink;
}
return <Nav.item color='orange' icon='fas fa-pencil-alt' href={`/edit/${editLink}`}>
edit
</Nav.item>;
},
render : function(){
return <div className='sharePage sitePage'>
<Meta name='robots' content='noindex, nofollow' />
@@ -59,18 +71,19 @@ const SharePage = createClass({
<Nav.section>
{this.props.brew.shareId && <>
<PrintLink shareId={this.processShareId()} />
<PrintNavItem/>
<Nav.dropdown>
<Nav.item color='red' icon='fas fa-code'>
source
</Nav.item>
<Nav.item color='blue' href={`/source/${this.processShareId()}`}>
<Nav.item color='blue' icon='fas fa-eye' href={`/source/${this.processShareId()}`}>
view
</Nav.item>
<Nav.item color='blue' href={`/download/${this.processShareId()}`}>
{this.renderEditLink()}
<Nav.item color='blue' icon='fas fa-download' href={`/download/${this.processShareId()}`}>
download
</Nav.item>
<Nav.item color='blue' href={`/new/${this.processShareId()}`}>
<Nav.item color='blue' icon='fas fa-clone' href={`/new/${this.processShareId()}`}>
clone to new
</Nav.item>
</Nav.dropdown>
@@ -81,7 +94,13 @@ const SharePage = createClass({
</Navbar>
<div className='content'>
<BrewRenderer text={this.props.brew.text} style={this.props.brew.style} renderer={this.props.brew.renderer} theme={this.props.brew.theme} />
<BrewRenderer
text={this.props.brew.text}
style={this.props.brew.style}
renderer={this.props.brew.renderer}
theme={this.props.brew.theme}
allowPrint={true}
/>
</div>
</div>;
}

View File

@@ -1,7 +1,6 @@
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const ListPage = require('../basePages/listPage/listPage.jsx');

457
package-lock.json generated
View File

@@ -10,17 +10,18 @@
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.24.4",
"@babel/core": "^7.24.5",
"@babel/plugin-transform-runtime": "^7.24.3",
"@babel/preset-env": "^7.24.4",
"@babel/preset-env": "^7.24.5",
"@babel/preset-react": "^7.24.1",
"@googleapis/drive": "^8.7.0",
"@googleapis/drive": "^8.8.0",
"body-parser": "^1.20.2",
"classnames": "^2.5.1",
"codemirror": "^5.65.6",
"cookie-parser": "^1.4.6",
"create-react-class": "^15.7.0",
"dedent-tabs": "^0.10.3",
"dompurify": "^3.1.4",
"expr-eval": "^2.0.2",
"express": "^4.19.2",
"express-async-handler": "^1.2.0",
@@ -31,25 +32,26 @@
"less": "^3.13.1",
"lodash": "^4.17.21",
"marked": "11.2.0",
"marked-emoji": "^1.4.0",
"marked-extended-tables": "^1.0.8",
"marked-gfm-heading-id": "^3.1.3",
"marked-smartypants-lite": "^1.0.2",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.30.1",
"mongoose": "^8.3.1",
"mongoose": "^8.4.0",
"nanoid": "3.3.4",
"nconf": "^0.12.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-frame-component": "^4.1.3",
"react-router-dom": "6.22.3",
"react-router-dom": "6.23.1",
"sanitize-filename": "1.6.3",
"superagent": "^8.1.2",
"superagent": "^9.0.2",
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
},
"devDependencies": {
"eslint": "^8.57.0",
"eslint-plugin-jest": "^28.2.0",
"eslint-plugin-jest": "^28.5.0",
"eslint-plugin-react": "^7.34.1",
"jest": "^29.7.0",
"jest-expect-message": "^1.1.3",
@@ -58,7 +60,7 @@
"stylelint-config-recess-order": "^4.6.0",
"stylelint-config-recommended": "^13.0.0",
"stylelint-stylistic": "^0.4.3",
"supertest": "^6.3.4"
"supertest": "^7.0.0"
},
"engines": {
"node": "^20.8.x",
@@ -107,20 +109,20 @@
}
},
"node_modules/@babel/core": {
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz",
"integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz",
"integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.24.2",
"@babel/generator": "^7.24.4",
"@babel/generator": "^7.24.5",
"@babel/helper-compilation-targets": "^7.23.6",
"@babel/helper-module-transforms": "^7.23.3",
"@babel/helpers": "^7.24.4",
"@babel/parser": "^7.24.4",
"@babel/helper-module-transforms": "^7.24.5",
"@babel/helpers": "^7.24.5",
"@babel/parser": "^7.24.5",
"@babel/template": "^7.24.0",
"@babel/traverse": "^7.24.1",
"@babel/types": "^7.24.0",
"@babel/traverse": "^7.24.5",
"@babel/types": "^7.24.5",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -141,11 +143,11 @@
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
},
"node_modules/@babel/generator": {
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz",
"integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz",
"integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==",
"dependencies": {
"@babel/types": "^7.24.0",
"@babel/types": "^7.24.5",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^2.5.1"
@@ -205,18 +207,18 @@
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz",
"integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz",
"integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==",
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-member-expression-to-functions": "^7.23.0",
"@babel/helper-member-expression-to-functions": "^7.24.5",
"@babel/helper-optimise-call-expression": "^7.22.5",
"@babel/helper-replace-supers": "^7.24.1",
"@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/helper-split-export-declaration": "^7.24.5",
"semver": "^6.3.1"
},
"engines": {
@@ -289,11 +291,11 @@
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz",
"integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz",
"integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==",
"dependencies": {
"@babel/types": "^7.23.0"
"@babel/types": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -311,15 +313,15 @@
}
},
"node_modules/@babel/helper-module-transforms": {
"version": "7.23.3",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz",
"integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz",
"integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==",
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-module-imports": "^7.22.15",
"@babel/helper-simple-access": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/helper-validator-identifier": "^7.22.20"
"@babel/helper-module-imports": "^7.24.3",
"@babel/helper-simple-access": "^7.24.5",
"@babel/helper-split-export-declaration": "^7.24.5",
"@babel/helper-validator-identifier": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -340,9 +342,9 @@
}
},
"node_modules/@babel/helper-plugin-utils": {
"version": "7.24.0",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz",
"integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz",
"integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==",
"engines": {
"node": ">=6.9.0"
}
@@ -380,11 +382,11 @@
}
},
"node_modules/@babel/helper-simple-access": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
"integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz",
"integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==",
"dependencies": {
"@babel/types": "^7.22.5"
"@babel/types": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -402,28 +404,28 @@
}
},
"node_modules/@babel/helper-split-export-declaration": {
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz",
"integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==",
"dependencies": {
"@babel/types": "^7.22.5"
"@babel/types": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
"integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz",
"integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz",
"integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==",
"engines": {
"node": ">=6.9.0"
}
@@ -450,13 +452,13 @@
}
},
"node_modules/@babel/helpers": {
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz",
"integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz",
"integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==",
"dependencies": {
"@babel/template": "^7.24.0",
"@babel/traverse": "^7.24.1",
"@babel/types": "^7.24.0"
"@babel/traverse": "^7.24.5",
"@babel/types": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -477,9 +479,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz",
"integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz",
"integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==",
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -488,12 +490,12 @@
}
},
"node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz",
"integrity": "sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz",
"integrity": "sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==",
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-plugin-utils": "^7.24.0"
"@babel/helper-plugin-utils": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -878,11 +880,11 @@
}
},
"node_modules/@babel/plugin-transform-block-scoping": {
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz",
"integrity": "sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.5.tgz",
"integrity": "sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.0"
"@babel/helper-plugin-utils": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -923,17 +925,17 @@
}
},
"node_modules/@babel/plugin-transform-classes": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz",
"integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.5.tgz",
"integrity": "sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==",
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-compilation-targets": "^7.23.6",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-plugin-utils": "^7.24.0",
"@babel/helper-plugin-utils": "^7.24.5",
"@babel/helper-replace-supers": "^7.24.1",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/helper-split-export-declaration": "^7.24.5",
"globals": "^11.1.0"
},
"engines": {
@@ -959,11 +961,11 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz",
"integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.5.tgz",
"integrity": "sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.0"
"@babel/helper-plugin-utils": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -1258,14 +1260,14 @@
}
},
"node_modules/@babel/plugin-transform-object-rest-spread": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz",
"integrity": "sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.5.tgz",
"integrity": "sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==",
"dependencies": {
"@babel/helper-compilation-targets": "^7.23.6",
"@babel/helper-plugin-utils": "^7.24.0",
"@babel/helper-plugin-utils": "^7.24.5",
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
"@babel/plugin-transform-parameters": "^7.24.1"
"@babel/plugin-transform-parameters": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -1305,11 +1307,11 @@
}
},
"node_modules/@babel/plugin-transform-optional-chaining": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz",
"integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.5.tgz",
"integrity": "sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.0",
"@babel/helper-plugin-utils": "^7.24.5",
"@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
"@babel/plugin-syntax-optional-chaining": "^7.8.3"
},
@@ -1321,11 +1323,11 @@
}
},
"node_modules/@babel/plugin-transform-parameters": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz",
"integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.5.tgz",
"integrity": "sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.0"
"@babel/helper-plugin-utils": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -1350,13 +1352,13 @@
}
},
"node_modules/@babel/plugin-transform-private-property-in-object": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz",
"integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.5.tgz",
"integrity": "sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==",
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-create-class-features-plugin": "^7.24.1",
"@babel/helper-plugin-utils": "^7.24.0",
"@babel/helper-create-class-features-plugin": "^7.24.5",
"@babel/helper-plugin-utils": "^7.24.5",
"@babel/plugin-syntax-private-property-in-object": "^7.14.5"
},
"engines": {
@@ -1547,11 +1549,11 @@
}
},
"node_modules/@babel/plugin-transform-typeof-symbol": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz",
"integrity": "sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.5.tgz",
"integrity": "sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.0"
"@babel/helper-plugin-utils": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -1620,15 +1622,15 @@
}
},
"node_modules/@babel/preset-env": {
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.4.tgz",
"integrity": "sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.5.tgz",
"integrity": "sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==",
"dependencies": {
"@babel/compat-data": "^7.24.4",
"@babel/helper-compilation-targets": "^7.23.6",
"@babel/helper-plugin-utils": "^7.24.0",
"@babel/helper-plugin-utils": "^7.24.5",
"@babel/helper-validator-option": "^7.23.5",
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.4",
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.5",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1",
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1",
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1",
@@ -1655,12 +1657,12 @@
"@babel/plugin-transform-async-generator-functions": "^7.24.3",
"@babel/plugin-transform-async-to-generator": "^7.24.1",
"@babel/plugin-transform-block-scoped-functions": "^7.24.1",
"@babel/plugin-transform-block-scoping": "^7.24.4",
"@babel/plugin-transform-block-scoping": "^7.24.5",
"@babel/plugin-transform-class-properties": "^7.24.1",
"@babel/plugin-transform-class-static-block": "^7.24.4",
"@babel/plugin-transform-classes": "^7.24.1",
"@babel/plugin-transform-classes": "^7.24.5",
"@babel/plugin-transform-computed-properties": "^7.24.1",
"@babel/plugin-transform-destructuring": "^7.24.1",
"@babel/plugin-transform-destructuring": "^7.24.5",
"@babel/plugin-transform-dotall-regex": "^7.24.1",
"@babel/plugin-transform-duplicate-keys": "^7.24.1",
"@babel/plugin-transform-dynamic-import": "^7.24.1",
@@ -1680,13 +1682,13 @@
"@babel/plugin-transform-new-target": "^7.24.1",
"@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1",
"@babel/plugin-transform-numeric-separator": "^7.24.1",
"@babel/plugin-transform-object-rest-spread": "^7.24.1",
"@babel/plugin-transform-object-rest-spread": "^7.24.5",
"@babel/plugin-transform-object-super": "^7.24.1",
"@babel/plugin-transform-optional-catch-binding": "^7.24.1",
"@babel/plugin-transform-optional-chaining": "^7.24.1",
"@babel/plugin-transform-parameters": "^7.24.1",
"@babel/plugin-transform-optional-chaining": "^7.24.5",
"@babel/plugin-transform-parameters": "^7.24.5",
"@babel/plugin-transform-private-methods": "^7.24.1",
"@babel/plugin-transform-private-property-in-object": "^7.24.1",
"@babel/plugin-transform-private-property-in-object": "^7.24.5",
"@babel/plugin-transform-property-literals": "^7.24.1",
"@babel/plugin-transform-regenerator": "^7.24.1",
"@babel/plugin-transform-reserved-words": "^7.24.1",
@@ -1694,7 +1696,7 @@
"@babel/plugin-transform-spread": "^7.24.1",
"@babel/plugin-transform-sticky-regex": "^7.24.1",
"@babel/plugin-transform-template-literals": "^7.24.1",
"@babel/plugin-transform-typeof-symbol": "^7.24.1",
"@babel/plugin-transform-typeof-symbol": "^7.24.5",
"@babel/plugin-transform-unicode-escapes": "^7.24.1",
"@babel/plugin-transform-unicode-property-regex": "^7.24.1",
"@babel/plugin-transform-unicode-regex": "^7.24.1",
@@ -1775,18 +1777,18 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz",
"integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz",
"integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==",
"dependencies": {
"@babel/code-frame": "^7.24.1",
"@babel/generator": "^7.24.1",
"@babel/code-frame": "^7.24.2",
"@babel/generator": "^7.24.5",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.24.1",
"@babel/types": "^7.24.0",
"@babel/helper-split-export-declaration": "^7.24.5",
"@babel/parser": "^7.24.5",
"@babel/types": "^7.24.5",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -1795,12 +1797,12 @@
}
},
"node_modules/@babel/types": {
"version": "7.24.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz",
"integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==",
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz",
"integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==",
"dependencies": {
"@babel/helper-string-parser": "^7.23.4",
"@babel/helper-validator-identifier": "^7.22.20",
"@babel/helper-string-parser": "^7.24.1",
"@babel/helper-validator-identifier": "^7.24.5",
"to-fast-properties": "^2.0.0"
},
"engines": {
@@ -1983,9 +1985,9 @@
}
},
"node_modules/@googleapis/drive": {
"version": "8.7.0",
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.7.0.tgz",
"integrity": "sha512-XAi6kfySIU4H3ivX2DpzTDce5UhNke5NxEWCL6tySEdcVqx+cmXJmkMqwfOAHJalEB5s9PPfdLBU29Xd5XlLSQ==",
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.8.0.tgz",
"integrity": "sha512-EOZ9GZCOUdej9PJVnkai7qu5RPyFLYse8FlpgijzfnZPOACXWFf4XOFuAuMcMw4Zue8xPhAPHu1qYcy8u362Xw==",
"dependencies": {
"googleapis-common": "^7.0.0"
},
@@ -2811,9 +2813,9 @@
}
},
"node_modules/@mongodb-js/saslprep": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.5.tgz",
"integrity": "sha512-XLNOMH66KhJzUJNwT/qlMnS4WsNDWD5ASdyaSH3EtK+F4r/CFGa3jT4GNi4mfOitGvWXtdLgQJkQjxSVrio+jA==",
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.7.tgz",
"integrity": "sha512-dCHW/oEX0KJ4NjDULBo3JiOaK5+6axtpBbS+ao2ZInoAL9/YRQLhXzSNAFz7hP4nzLkIqsfYAK/PDE3+XHny0Q==",
"dependencies": {
"sparse-bitfield": "^3.0.3"
}
@@ -2854,9 +2856,9 @@
}
},
"node_modules/@remix-run/router": {
"version": "1.15.3",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz",
"integrity": "sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==",
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz",
"integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==",
"engines": {
"node": ">=14.0.0"
}
@@ -3001,9 +3003,9 @@
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
},
"node_modules/@types/whatwg-url": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz",
"integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==",
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
"integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
"dependencies": {
"@types/webidl-conversions": "*"
}
@@ -4325,9 +4327,9 @@
}
},
"node_modules/bson": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.6.0.tgz",
"integrity": "sha512-BVINv2SgcMjL4oYbBuCQTpE3/VKOSxrOA8Cj/wQP7izSzlBGVomdm+TcUd0Pzy0ytLSSDweCKQ6X3f5veM5LQA==",
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.7.0.tgz",
"integrity": "sha512-w2IquM5mYzYZv6rs3uN2DZTOBe2a0zXLj53TGDqwF4l6Sz/XsISrisXOJihArF9+BZ6Cq/GjVht7Sjfmri7ytQ==",
"engines": {
"node": ">=16.20.1"
}
@@ -5413,6 +5415,11 @@
"npm": ">=1.2"
}
},
"node_modules/dompurify": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.4.tgz",
"integrity": "sha512-2gnshi6OshmuKil8rMZuQCGiUF3cUxHY3NGDzUAdUx/NPEe5DVnO8BDoAQouvgwnx0R/+a6jUn36Z0FSdq8vww=="
},
"node_modules/duplexer2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
@@ -5748,12 +5755,12 @@
}
},
"node_modules/eslint-plugin-jest": {
"version": "28.2.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.2.0.tgz",
"integrity": "sha512-yRDti/a+f+SMSmNTiT9/M/MzXGkitl8CfzUxnpoQcTyfq8gUrXMriVcWU36W1X6BZSUoyUCJrDAWWUA2N4hE5g==",
"version": "28.5.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.5.0.tgz",
"integrity": "sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/utils": "^6.0.0"
"@typescript-eslint/utils": "^6.0.0 || ^7.0.0"
},
"engines": {
"node": "^16.10.0 || ^18.12.0 || >=20.0.0"
@@ -6516,14 +6523,13 @@
}
},
"node_modules/formidable": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz",
"integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==",
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.1.tgz",
"integrity": "sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og==",
"dependencies": {
"dezalgo": "^1.0.4",
"hexoid": "^1.0.0",
"once": "^1.4.0",
"qs": "^6.11.0"
"once": "^1.4.0"
},
"funding": {
"url": "https://ko-fi.com/tunnckoCore/commissions"
@@ -10145,6 +10151,14 @@
"node": ">= 18"
}
},
"node_modules/marked-emoji": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/marked-emoji/-/marked-emoji-1.4.0.tgz",
"integrity": "sha512-/2TJfGzXpiBBq+X3akHHbTrAjZPJDwR+7FV6SyQLECnQEfaoVkrpKZJzHhPTAq3Sl/A1l2frMT0u6b38VBBlNg==",
"peerDependencies": {
"marked": ">=4 <13"
}
},
"node_modules/marked-extended-tables": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/marked-extended-tables/-/marked-extended-tables-1.0.8.tgz",
@@ -10538,26 +10552,26 @@
}
},
"node_modules/mongodb-connection-string-url": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz",
"integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz",
"integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==",
"dependencies": {
"@types/whatwg-url": "^11.0.2",
"whatwg-url": "^13.0.0"
}
},
"node_modules/mongoose": {
"version": "8.3.1",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.3.1.tgz",
"integrity": "sha512-D78C+s7QI4+pJQhs3XbOxzrHFEti4x+BDhaH94QrdV1/cmMA7fHc50LgLSXjzA/5q89TBK8DAXyf3VwDZbQJlA==",
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.4.0.tgz",
"integrity": "sha512-fgqRMwVEP1qgRYfh+tUe2YBBFnPO35FIg2lfFH+w9IhRGg1/ataWGIqvf/MjwM29cZ60D5vSnqtN2b8Qp0sOZA==",
"dependencies": {
"bson": "^6.5.0",
"bson": "^6.7.0",
"kareem": "2.6.3",
"mongodb": "6.5.0",
"mongodb": "6.6.2",
"mpath": "0.9.0",
"mquery": "5.0.0",
"ms": "2.1.3",
"sift": "16.0.1"
"sift": "17.1.3"
},
"engines": {
"node": ">=16.20.1"
@@ -10625,12 +10639,12 @@
}
},
"node_modules/mongoose/node_modules/mongodb": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.5.0.tgz",
"integrity": "sha512-Fozq68InT+JKABGLqctgtb8P56pRrJFkbhW0ux+x1mdHeyinor8oNzJqwLjV/t5X5nJGfTlluxfyMnOXNggIUA==",
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.6.2.tgz",
"integrity": "sha512-ZF9Ugo2JCG/GfR7DEb4ypfyJJyiKbg5qBYKRintebj8+DNS33CyGMkWbrS9lara+u+h+yEOGSRiLhFO/g1s1aw==",
"dependencies": {
"@mongodb-js/saslprep": "^1.1.5",
"bson": "^6.4.0",
"bson": "^6.7.0",
"mongodb-connection-string-url": "^3.0.0"
},
"engines": {
@@ -11937,9 +11951,9 @@
}
},
"node_modules/react": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -11948,15 +11962,15 @@
}
},
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.0"
"scheduler": "^0.23.2"
},
"peerDependencies": {
"react": "^18.2.0"
"react": "^18.3.1"
}
},
"node_modules/react-frame-component": {
@@ -11976,11 +11990,11 @@
"dev": true
},
"node_modules/react-router": {
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz",
"integrity": "sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==",
"version": "6.23.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz",
"integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==",
"dependencies": {
"@remix-run/router": "1.15.3"
"@remix-run/router": "1.16.1"
},
"engines": {
"node": ">=14.0.0"
@@ -11990,12 +12004,12 @@
}
},
"node_modules/react-router-dom": {
"version": "6.22.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz",
"integrity": "sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==",
"version": "6.23.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz",
"integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==",
"dependencies": {
"@remix-run/router": "1.15.3",
"react-router": "6.22.3"
"@remix-run/router": "1.16.1",
"react-router": "6.23.1"
},
"engines": {
"node": ">=14.0.0"
@@ -12523,9 +12537,9 @@
}
},
"node_modules/scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dependencies": {
"loose-envify": "^1.1.0"
}
@@ -12720,9 +12734,9 @@
}
},
"node_modules/sift": {
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz",
"integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ=="
"version": "17.1.3",
"resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz",
"integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ=="
},
"node_modules/signal-exit": {
"version": "3.0.7",
@@ -13598,34 +13612,22 @@
}
},
"node_modules/superagent": {
"version": "8.1.2",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz",
"integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==",
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-9.0.2.tgz",
"integrity": "sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==",
"dependencies": {
"component-emitter": "^1.3.0",
"cookiejar": "^2.1.4",
"debug": "^4.3.4",
"fast-safe-stringify": "^2.1.1",
"form-data": "^4.0.0",
"formidable": "^2.1.2",
"formidable": "^3.5.1",
"methods": "^1.1.2",
"mime": "2.6.0",
"qs": "^6.11.0",
"semver": "^7.3.8"
"qs": "^6.11.0"
},
"engines": {
"node": ">=6.4.0 <13 || >=14"
}
},
"node_modules/superagent/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
"node": ">=14.18.0"
}
},
"node_modules/superagent/node_modules/mime": {
@@ -13639,36 +13641,17 @@
"node": ">=4.0.0"
}
},
"node_modules/superagent/node_modules/semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/superagent/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/supertest": {
"version": "6.3.4",
"resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz",
"integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/supertest/-/supertest-7.0.0.tgz",
"integrity": "sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA==",
"dev": true,
"dependencies": {
"methods": "^1.1.2",
"superagent": "^8.1.2"
"superagent": "^9.0.1"
},
"engines": {
"node": ">=6.4.0"
"node": ">=14.18.0"
}
},
"node_modules/supports-color": {
@@ -14481,12 +14464,14 @@
}
},
"node_modules/vitreum": {
"version": "6.0.1",
"resolved": "git+https://git@github.com/calculuschild/vitreum.git#49994da4055f914269318b2b9ae953707aa771b6",
"version": "6.0.4",
"resolved": "git+https://git@github.com/calculuschild/vitreum.git#9d55fd6fb7e85e7070de798c4f9d5b983c1b7dba",
"integrity": "sha512-6b5A4XEXnpyl6JDRWWOhe5lHxtzMVqNA+0Xrl7mPXqh7cYwTUm0yhkYEUkV+mz7rrHTpH7bYEWYsWEE/qTZMpg==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"browserify": "^16.5.0",
"fs-extra": "^9.0.0",
"fs-extra": "^9.0.1",
"livereload": "^0.9.1",
"nodemon": "^2.0.2",
"source-map-support": "^0.5.16",
@@ -14497,8 +14482,8 @@
"@babel/core": "^7.9.0",
"@babel/preset-react": "^7.9.4",
"less": "^3.11.1",
"react": ">=16.13.1",
"react-dom": ">=16.13.1"
"react": "^18.3.1",
"react-dom": "^18.3.1"
}
},
"node_modules/vitreum/node_modules/fs-extra": {

View File

@@ -27,11 +27,12 @@
"test:dev": "jest --verbose --watch",
"test:basic": "jest tests/markdown/basic.test.js --verbose",
"test:variables": "jest tests/markdown/variables.test.js --verbose",
"test:mustache-syntax": "jest '.*(mustache-syntax).*' --verbose --noStackTrace",
"test:mustache-syntax:inline": "jest '.*(mustache-syntax).*' -t '^Inline:.*' --verbose --noStackTrace",
"test:mustache-syntax:block": "jest '.*(mustache-syntax).*' -t '^Block:.*' --verbose --noStackTrace",
"test:mustache-syntax:injection": "jest '.*(mustache-syntax).*' -t '^Injection:.*' --verbose --noStackTrace",
"test:definition-lists": "jest tests/markdown/definition-lists.test.js --verbose --noStackTrace",
"test:mustache-syntax": "jest \".*(mustache-syntax).*\" --verbose --noStackTrace",
"test:mustache-syntax:inline": "jest \".*(mustache-syntax).*\" -t '^Inline:.*' --verbose --noStackTrace",
"test:mustache-syntax:block": "jest \".*(mustache-syntax).*\" -t '^Block:.*' --verbose --noStackTrace",
"test:mustache-syntax:injection": "jest \".*(mustache-syntax).*\" -t '^Injection:.*' --verbose --noStackTrace",
"test:definition-lists": "jest tests/markdown/definition-lists.test.js --verbose --noStackTrace",
"test:emojis": "jest tests/markdown/emojis.test.js --verbose --noStackTrace",
"test:route": "jest tests/routes/static-pages.test.js --verbose",
"phb": "node scripts/phb.js",
"prod": "set NODE_ENV=production && npm run build",
@@ -81,17 +82,18 @@
]
},
"dependencies": {
"@babel/core": "^7.24.4",
"@babel/core": "^7.24.5",
"@babel/plugin-transform-runtime": "^7.24.3",
"@babel/preset-env": "^7.24.4",
"@babel/preset-env": "^7.24.5",
"@babel/preset-react": "^7.24.1",
"@googleapis/drive": "^8.7.0",
"@googleapis/drive": "^8.8.0",
"body-parser": "^1.20.2",
"classnames": "^2.5.1",
"codemirror": "^5.65.6",
"cookie-parser": "^1.4.6",
"create-react-class": "^15.7.0",
"dedent-tabs": "^0.10.3",
"dompurify": "^3.1.4",
"expr-eval": "^2.0.2",
"express": "^4.19.2",
"express-async-handler": "^1.2.0",
@@ -102,25 +104,26 @@
"less": "^3.13.1",
"lodash": "^4.17.21",
"marked": "11.2.0",
"marked-emoji": "^1.4.0",
"marked-extended-tables": "^1.0.8",
"marked-gfm-heading-id": "^3.1.3",
"marked-smartypants-lite": "^1.0.2",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.30.1",
"mongoose": "^8.3.1",
"mongoose": "^8.4.0",
"nanoid": "3.3.4",
"nconf": "^0.12.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-frame-component": "^4.1.3",
"react-router-dom": "6.22.3",
"react-router-dom": "6.23.1",
"sanitize-filename": "1.6.3",
"superagent": "^8.1.2",
"superagent": "^9.0.2",
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
},
"devDependencies": {
"eslint": "^8.57.0",
"eslint-plugin-jest": "^28.2.0",
"eslint-plugin-jest": "^28.5.0",
"eslint-plugin-react": "^7.34.1",
"jest": "^29.7.0",
"jest-expect-message": "^1.1.3",
@@ -129,6 +132,6 @@
"stylelint-config-recess-order": "^4.6.0",
"stylelint-config-recommended": "^13.0.0",
"stylelint-stylistic": "^0.4.3",
"supertest": "^6.3.4"
"supertest": "^7.0.0"
}
}

View File

@@ -25,6 +25,7 @@
"codemirror/addon/edit/closetag.js",
"codemirror/addon/edit/trailingspace.js",
"codemirror/addon/selection/active-line.js",
"codemirror/addon/hint/show-hint.js",
"moment",
"superagent"
]

View File

@@ -14,7 +14,7 @@ DB.connect(config).then(()=>{
console.log(`\n\tserver started at: ${new Date().toLocaleString()}`);
console.log(`\tserver on port: ${PORT}`);
console.log(`\t${bright + cyan}Open in browser: ${reset}${underline + bright + cyan}http://localhost:${PORT}${reset}\n\n`)
console.log(`\t${bright + cyan}Open in browser: ${reset}${underline + bright + cyan}http://localhost:${PORT}${reset}\n\n`);
});
});

View File

@@ -30,7 +30,7 @@ const junkBrewPipeline = [
{ $match : {
updatedAt : { $lt: Moment().subtract(30, 'days').toDate() },
lastViewed : { $lt: Moment().subtract(30, 'days').toDate() }
}},
} },
{ $project: { textBinSize: { $binarySize: '$textBin' } } },
{ $match: { textBinSize: { $lt: 140 } } },
{ $limit: 100 }

View File

@@ -23,7 +23,7 @@ const { splitTextStyleAndMetadata } = require('../shared/helpers.js');
const sanitizeBrew = (brew, accessType)=>{
brew._id = undefined;
brew.__v = undefined;
if(accessType !== 'edit'){
if(accessType !== 'edit' && accessType !== 'shareAuthor') {
brew.editId = undefined;
}
return brew;
@@ -307,7 +307,6 @@ app.get('/new/:id', asyncHandler(getBrew('share')), (req, res, next)=>{
//Share Page
app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, res, next)=>{
const { brew } = req;
req.ogMeta = { ...defaultMetaTags,
title : req.brew.title || 'Untitled Brew',
description : req.brew.description || 'No description.',
@@ -326,18 +325,12 @@ app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, r
await HomebrewModel.increaseView({ shareId: brew.shareId });
}
};
sanitizeBrew(req.brew, 'share');
brew.authors.includes(req.account?.username) ? sanitizeBrew(req.brew, 'shareAuthor') : sanitizeBrew(req.brew, 'share');
splitTextStyleAndMetadata(req.brew);
return next();
}));
//Print Page
app.get('/print/:id', asyncHandler(getBrew('share')), (req, res, next)=>{
sanitizeBrew(req.brew, 'share');
splitTextStyleAndMetadata(req.brew);
next();
});
//Account Page
app.get('/account', asyncHandler(async (req, res, next)=>{
const data = {};

View File

@@ -1,5 +1,4 @@
/* eslint-disable max-lines */
const _ = require('lodash');
const googleDrive = require('@googleapis/drive');
const { nanoid } = require('nanoid');
const token = require('./token.js');

View File

@@ -83,9 +83,9 @@ const api = {
if(accessType === 'edit' && (authorsExist && !(isAuthor || isInvited))) {
const accessError = { name: 'Access Error', status: 401 };
if(req.account){
throw { ...accessError, message: 'User is not an Author', HBErrorCode: '03', authors: stub.authors, brewTitle: stub.title, shareId: stub.shareId};
throw { ...accessError, message: 'User is not an Author', HBErrorCode: '03', authors: stub.authors, brewTitle: stub.title, shareId: stub.shareId };
}
throw { ...accessError, message: 'User is not logged in', HBErrorCode: '04', authors: stub.authors, brewTitle: stub.title, shareId: stub.shareId};
throw { ...accessError, message: 'User is not logged in', HBErrorCode: '04', authors: stub.authors, brewTitle: stub.title, shareId: stub.shareId };
}
// If after all of that we still don't have a brew, throw an exception

View File

@@ -1,22 +1,34 @@
const _ = require('lodash');
const yaml = require('js-yaml');
const splitTextStyleAndMetadata = (brew) => {
brew.text = brew.text.replaceAll('\r\n', '\n');
if (brew.text.startsWith('```metadata')) {
const index = brew.text.indexOf('```\n\n');
const metadataSection = brew.text.slice(12, index - 1);
const metadata = yaml.load(metadataSection);
Object.assign(brew, _.pick(metadata, ['title', 'description', 'tags', 'systems', 'renderer', 'theme', 'lang']));
brew.text = brew.text.slice(index + 5);
}
if (brew.text.startsWith('```css')) {
const index = brew.text.indexOf('```\n\n');
brew.style = brew.text.slice(7, index - 1);
brew.text = brew.text.slice(index + 5);
}
const splitTextStyleAndMetadata = (brew)=>{
brew.text = brew.text.replaceAll('\r\n', '\n');
if(brew.text.startsWith('```metadata')) {
const index = brew.text.indexOf('```\n\n');
const metadataSection = brew.text.slice(12, index - 1);
const metadata = yaml.load(metadataSection);
Object.assign(brew, _.pick(metadata, ['title', 'description', 'tags', 'systems', 'renderer', 'theme', 'lang']));
brew.text = brew.text.slice(index + 5);
}
if(brew.text.startsWith('```css')) {
const index = brew.text.indexOf('```\n\n');
brew.style = brew.text.slice(7, index - 1);
brew.text = brew.text.slice(index + 5);
}
};
const printCurrentBrew = ()=>{
if(window.typeof !== 'undefined') {
window.frames['BrewRenderer'].contentWindow.print();
//Force DOM reflow; Print dialog causes a repaint, and @media print CSS somehow makes out-of-view pages disappear
const node = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer').item(0);
node.style.display='none';
node.offsetHeight; // accessing this is enough to trigger a reflow
node.style.display='';
}
};
module.exports = {
splitTextStyleAndMetadata
splitTextStyleAndMetadata,
printCurrentBrew
};

View File

@@ -2,7 +2,6 @@ require('./renderWarnings.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const DISMISS_KEY = 'dismiss_render_warning';

View File

@@ -0,0 +1,84 @@
const diceFont = require('../../../themes/fonts/iconFonts/diceFont.js');
const elderberryInn = require('../../../themes/fonts/iconFonts/elderberryInn.js');
const fontAwesome = require('../../../themes/fonts/iconFonts/fontAwesome.js');
const gameIcons = require('../../../themes/fonts/iconFonts/gameIcons.js');
const emojis = {
...diceFont,
...elderberryInn,
...fontAwesome,
...gameIcons
};
const showAutocompleteEmoji = function(CodeMirror, editor) {
CodeMirror.commands.autocomplete = function(editor) {
editor.showHint({
completeSingle : false,
hint : function(editor) {
const cursor = editor.getCursor();
const line = cursor.line;
const lineContent = editor.getLine(line);
const start = lineContent.lastIndexOf(':', cursor.ch - 1) + 1;
const end = cursor.ch;
const currentWord = lineContent.slice(start, end);
const list = Object.keys(emojis).filter(function(emoji) {
return emoji.toLowerCase().indexOf(currentWord.toLowerCase()) >= 0;
}).sort((a, b)=>{
const lowerA = a.replace(/\d+/g, function(match) { // Temporarily convert any numbers in emoji string
return match.padStart(4, '0'); // to 4-digits, left-padded with 0's, to aid in
}).toLowerCase(); // sorting numbers, i.e., "d6, d10, d20", not "d10, d20, d6"
const lowerB = b.replace(/\d+/g, function(match) { // Also make lowercase for case-insensitive alpha sorting
return match.padStart(4, '0');
}).toLowerCase();
if(lowerA < lowerB)
return -1;
return 1;
}).map(function(emoji) {
return {
text : `${emoji}:`, // Text to output to editor when option is selected
render : function(element, self, data) { // How to display the option in the dropdown
const div = document.createElement('div');
div.innerHTML = `<i class="emojiPreview ${emojis[emoji]}"></i> ${emoji}`;
element.appendChild(div);
}
};
});
return {
list : list.length ? list : [],
from : CodeMirror.Pos(line, start),
to : CodeMirror.Pos(line, end)
};
}
});
};
editor.on('inputRead', function(instance, change) {
const cursor = editor.getCursor();
const line = editor.getLine(cursor.line);
// Get the text from the start of the line to the cursor
const textToCursor = line.slice(0, cursor.ch);
// Do not autosuggest emojis in curly span/div/injector properties
if(line.includes('{')) {
const curlyToCursor = textToCursor.slice(textToCursor.indexOf(`{`));
const curlySpanRegex = /{(?=((?:[:=](?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':={}\s]*)*))\1$/g;
if(curlySpanRegex.test(curlyToCursor))
return;
}
// Check if the text ends with ':xyz'
if(/:[^\s:]+$/.test(textToCursor)) {
CodeMirror.commands.autocomplete(editor);
}
});
};
module.exports = {
showAutocompleteEmoji
};

View File

@@ -3,8 +3,8 @@ require('./codeEditor.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const closeTag = require('./close-tag');
const autoCompleteEmoji = require('./autocompleteEmoji');
let CodeMirror;
if(typeof window !== 'undefined'){
@@ -36,6 +36,8 @@ if(typeof window !== 'undefined'){
//XML code folding is a requirement of the auto-closing tag feature and is not enabled
require('codemirror/addon/fold/xml-fold.js');
require('codemirror/addon/edit/closetag.js');
//Autocompletion
require('codemirror/addon/hint/show-hint.js');
const foldCode = require('./fold-code');
foldCode.registerHomebreweryHelper(CodeMirror);
@@ -60,6 +62,8 @@ const CodeEditor = createClass({
};
},
editor : React.createRef(null),
componentDidMount : function() {
this.buildEditor();
const newDoc = CodeMirror.Doc(this.props.value, this.props.language);
@@ -99,7 +103,7 @@ const CodeEditor = createClass({
},
buildEditor : function() {
this.codeMirror = CodeMirror(this.refs.editor, {
this.codeMirror = CodeMirror(this.editor.current, {
lineNumbers : true,
lineWrapping : this.props.wrap,
indentWithTabs : false,
@@ -177,7 +181,10 @@ const CodeEditor = createClass({
// return el;
// }
});
// Add custom behaviors (auto-close curlies and auto-complete emojis)
closeTag.autoCloseCurlyBraces(CodeMirror, this.codeMirror);
autoCompleteEmoji.showAutocompleteEmoji(CodeMirror, this.codeMirror);
// Note: codeMirror passes a copy of itself in this callback. cm === this.codeMirror. Either one works.
this.codeMirror.on('change', (cm)=>{this.props.onChange(cm.getValue());});
@@ -436,8 +443,8 @@ const CodeEditor = createClass({
render : function(){
return <>
<link href={`../homebrew/cm-themes/${this.props.editorTheme}.css`} type="text/css" rel='stylesheet' />
<div className='codeEditor' ref='editor' style={this.props.style}/>
<link href={`../homebrew/cm-themes/${this.props.editorTheme}.css`} type='text/css' rel='stylesheet' />
<div className='codeEditor' ref={this.editor} style={this.props.style}/>
</>;
}
});

View File

@@ -2,6 +2,12 @@
@import (less) 'codemirror/addon/fold/foldgutter.css';
@import (less) 'codemirror/addon/search/matchesonscrollbar.css';
@import (less) 'codemirror/addon/dialog/dialog.css';
@import (less) 'codemirror/addon/hint/show-hint.css';
//Icon fonts included so they can appear in emoji autosuggest dropdown
@import (less) './themes/fonts/iconFonts/diceFont.less';
@import (less) './themes/fonts/iconFonts/elderberryInn.less';
@import (less) './themes/fonts/iconFonts/gameIcons.less';
@keyframes sourceMoveAnimation {
50% {background-color: red; color: white;}
@@ -34,6 +40,7 @@
}
}
//.cm-tab {
// background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAQAAACOs/baAAAARUlEQVR4nGJgIAG8JkXxUAcCtDWemcGR1lY4MvgzCEKY7jSBjgxBDAG09UEQzAe0AMwMHrSOAwEGRtpaMIwAAAAA//8DAG4ID9EKs6YqAAAAAElFTkSuQmCC) no-repeat right;
//}
@@ -44,3 +51,8 @@
// }
//}
}
.emojiPreview {
font-size: 1.5em;
line-height: 1.2em;
}

View File

@@ -4,6 +4,14 @@ const Marked = require('marked');
const MarkedExtendedTables = require('marked-extended-tables');
const { markedSmartypantsLite: MarkedSmartypantsLite } = require('marked-smartypants-lite');
const { gfmHeadingId: MarkedGFMHeadingId } = require('marked-gfm-heading-id');
const { markedEmoji: MarkedEmojis } = require('marked-emoji');
//Icon fonts included so they can appear in emoji autosuggest dropdown
const diceFont = require('../../themes/fonts/iconFonts/diceFont.js');
const elderberryInn = require('../../themes/fonts/iconFonts/elderberryInn.js');
const fontAwesome = require('../../themes/fonts/iconFonts/fontAwesome.js');
const gameIcons = require('../../themes/fonts/iconFonts/gameIcons.js');
const MathParser = require('expr-eval').Parser;
const renderer = new Marked.Renderer();
const tokenizer = new Marked.Tokenizer();
@@ -50,7 +58,7 @@ renderer.html = function (html) {
return html;
};
// Don't wrap {{ Divs or {{ empty Spans in <p> tags
// Don't wrap {{ Spans alone on a line, or {{ Divs in <p> tags
renderer.paragraph = function(text){
let match;
if(text.startsWith('<div') || text.startsWith('</div'))
@@ -99,13 +107,13 @@ const mustacheSpans = {
if(match) {
//Find closing delimiter
let blockCount = 0;
let tags = '';
let tags = {};
let endTags = 0;
let endToken = 0;
let delim;
while (delim = inlineRegex.exec(match[0])) {
if(!tags) {
tags = `${processStyleTags(delim[0].substring(2))}`;
if(_.isEmpty(tags)) {
tags = processStyleTags(delim[0].substring(2));
endTags = delim[0].length;
}
if(delim[0].startsWith('{{')) {
@@ -134,7 +142,14 @@ const mustacheSpans = {
}
},
renderer(token) {
return `<span class="inline-block${token.tags}>${this.parser.parseInline(token.tokens)}</span>`; // parseInline to turn child tokens into HTML
const tags = token.tags;
tags.classes = ['inline-block', tags.classes].join(' ').trim();
return `<span` +
`${tags.classes ? ` class="${tags.classes}"` : ''}` +
`${tags.id ? ` id="${tags.id}"` : ''}` +
`${tags.styles ? ` style="${tags.styles}"` : ''}` +
`${tags.attributes ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` +
`>${this.parser.parseInline(token.tokens)}</span>`; // parseInline to turn child tokens into HTML
}
};
@@ -149,13 +164,13 @@ const mustacheDivs = {
if(match) {
//Find closing delimiter
let blockCount = 0;
let tags = '';
let tags = {};
let endTags = 0;
let endToken = 0;
let delim;
while (delim = blockRegex.exec(match[0])?.[0].trim()) {
if(!tags) {
tags = `${processStyleTags(delim.substring(2))}`;
if(_.isEmpty(tags)) {
tags = processStyleTags(delim.substring(2));
endTags = delim.length + src.indexOf(delim);
}
if(delim.startsWith('{{')) {
@@ -183,7 +198,14 @@ const mustacheDivs = {
}
},
renderer(token) {
return `<div class="block${token.tags}>${this.parser.parse(token.tokens)}</div>`; // parseInline to turn child tokens into HTML
const tags = token.tags;
tags.classes = ['block', tags.classes].join(' ').trim();
return `<div` +
`${tags.classes ? ` class="${tags.classes}"` : ''}` +
`${tags.id ? ` id="${tags.id}"` : ''}` +
`${tags.styles ? ` style="${tags.styles}"` : ''}` +
`${tags.attributes ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` +
`>${this.parser.parse(token.tokens)}</div>`; // parse to turn child tokens into HTML
}
};
@@ -199,23 +221,39 @@ const mustacheInjectInline = {
if(!lastToken || lastToken.type == 'mustacheInjectInline')
return false;
const tags = `${processStyleTags(match[1])}`;
const tags = processStyleTags(match[1]);
lastToken.originalType = lastToken.type;
lastToken.type = 'mustacheInjectInline';
lastToken.tags = tags;
lastToken.injectedTags = tags;
return {
type : 'text', // Should match "name" above
type : 'mustacheInjectInline', // Should match "name" above
raw : match[0], // Text to consume from the source
text : ''
};
}
},
renderer(token) {
if(!token.originalType){
return;
}
token.type = token.originalType;
const text = this.parser.parseInline([token]);
const openingTag = /(<[^\s<>]+)([^\n<>]*>.*)/s.exec(text);
const originalTags = extractHTMLStyleTags(text);
const injectedTags = token.injectedTags;
const tags = {
id : injectedTags.id || originalTags.id || null,
classes : [originalTags.classes, injectedTags.classes].join(' ').trim() || null,
styles : [originalTags.styles, injectedTags.styles].join(' ').trim() || null,
attributes : Object.assign(originalTags.attributes ?? {}, injectedTags.attributes ?? {})
};
const openingTag = /(<[^\s<>]+)[^\n<>]*(>.*)/s.exec(text);
if(openingTag) {
return `${openingTag[1]} class="${token.tags}${openingTag[2]}`;
return `${openingTag[1]}` +
`${tags.classes ? ` class="${tags.classes}"` : ''}` +
`${tags.id ? ` id="${tags.id}"` : ''}` +
`${tags.styles ? ` style="${tags.styles}"` : ''}` +
`${!_.isEmpty(tags.attributes) ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` +
`${openingTag[2]}`; // parse to turn child tokens into HTML
}
return text;
}
@@ -235,7 +273,7 @@ const mustacheInjectBlock = {
return false;
lastToken.originalType = 'mustacheInjectBlock';
lastToken.tags = `${processStyleTags(match[1])}`;
lastToken.injectedTags = processStyleTags(match[1]);
return {
type : 'mustacheInjectBlock', // Should match "name" above
raw : match[0], // Text to consume from the source
@@ -249,9 +287,22 @@ const mustacheInjectBlock = {
}
token.type = token.originalType;
const text = this.parser.parse([token]);
const openingTag = /(<[^\s<>]+)([^\n<>]*>.*)/s.exec(text);
const originalTags = extractHTMLStyleTags(text);
const injectedTags = token.injectedTags;
const tags = {
id : injectedTags.id || originalTags.id || null,
classes : [originalTags.classes, injectedTags.classes].join(' ').trim() || null,
styles : [originalTags.styles, injectedTags.styles].join(' ').trim() || null,
attributes : Object.assign(originalTags.attributes ?? {}, injectedTags.attributes ?? {})
};
const openingTag = /(<[^\s<>]+)[^\n<>]*(>.*)/s.exec(text);
if(openingTag) {
return `${openingTag[1]} class="${token.tags}${openingTag[2]}`;
return `${openingTag[1]}` +
`${tags.classes ? ` class="${tags.classes}"` : ''}` +
`${tags.id ? ` id="${tags.id}"` : ''}` +
`${tags.styles ? ` style="${tags.styles}"` : ''}` +
`${!_.isEmpty(tags.attributes) ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` +
`${openingTag[2]}`; // parse to turn child tokens into HTML
}
return text;
}
@@ -304,10 +355,19 @@ const definitionListsSingleLine = {
let endIndex = 0;
const definitions = [];
while (match = regex.exec(src)) {
definitions.push({
dt : this.lexer.inlineTokens(match[1].trim()),
dd : this.lexer.inlineTokens(match[2].trim())
});
const originalLine = match[0]; // This line and below to handle conflict with emojis
let firstLine = originalLine; // Remove in V4 when definitionListsInline updated to
this.lexer.inlineTokens(firstLine.trim()) // require spaces around `::`
.filter((t)=>t.type == 'emoji')
.map((emoji)=>firstLine = firstLine.replace(emoji.raw, 'x'.repeat(emoji.raw.length)));
const newMatch = /^([^\n]*?)::([^\n]*)(?:\n|$)/ym.exec(firstLine);
if(newMatch) {
definitions.push({
dt : this.lexer.inlineTokens(originalLine.slice(0, newMatch[1].length).trim()),
dd : this.lexer.inlineTokens(originalLine.slice(newMatch[1].length + 2).trim())
});
} // End of emoji hack.
endIndex = regex.lastIndex;
}
if(definitions.length) {
@@ -616,11 +676,30 @@ function MarkedVariables() {
};
//^=====--------------------< Variable Handling >-------------------=====^//
// Emoji options
// To add more icon fonts, need to do these things
// 1) Add the font file as .woff2 to themes/fonts/iconFonts folder
// 2) Create a .less file mapping CSS class names to the font character
// 3) Create a .js file mapping Autosuggest names to CSS class names
// 4) Import the .less file into shared/naturalcrit/codeEditor/codeEditor.less
// 5) Import the .less file into themes/V3/blank.style.less
// 6) Import the .js file to shared/naturalcrit/codeEditor/autocompleteEmoji.js and add to `emojis` object
// 7) Import the .js file here to markdown.js, and add to `emojis` object below
const MarkedEmojiOptions = {
emojis : {
...diceFont,
...elderberryInn,
...fontAwesome,
...gameIcons,
},
renderer : (token)=>`<i class="${token.emoji}"></i>`
};
Marked.use(MarkedVariables());
Marked.use({ extensions: [definitionListsMultiLine, definitionListsSingleLine, superSubScripts, mustacheSpans, mustacheDivs, mustacheInjectInline] });
Marked.use(mustacheInjectBlock);
Marked.use({ renderer: renderer, tokenizer: tokenizer, mangle: false });
Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId(), MarkedSmartypantsLite());
Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId(), MarkedSmartypantsLite(), MarkedEmojis(MarkedEmojiOptions));
const nonWordAndColonTest = /[^\w:]/g;
const cleanUrl = function (sanitize, base, href) {
@@ -687,15 +766,45 @@ const processStyleTags = (string)=>{
//TODO: can we simplify to just split on commas?
const tags = string.match(/(?:[^, ":=]+|[:=](?:"[^"]*"|))+/g);
const id = _.remove(tags, (tag)=>tag.startsWith('#')).map((tag)=>tag.slice(1))[0];
const classes = _.remove(tags, (tag)=>(!tag.includes(':')) && (!tag.includes('=')));
const attributes = _.remove(tags, (tag)=>(tag.includes('='))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"'));
const styles = tags?.length ? tags.map((tag)=>tag.replace(/:"?([^"]*)"?/g, ':$1;').trim()) : [];
const id = _.remove(tags, (tag)=>tag.startsWith('#')).map((tag)=>tag.slice(1))[0] || null;
const classes = _.remove(tags, (tag)=>(!tag.includes(':')) && (!tag.includes('='))).join(' ') || null;
const attributes = _.remove(tags, (tag)=>(tag.includes('='))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"'))
?.filter((attr)=>!attr.startsWith('class="') && !attr.startsWith('style="') && !attr.startsWith('id="'))
.reduce((obj, attr)=>{
let [key, value] = attr.split('=');
value = value.replace(/"/g, '');
obj[key] = value;
return obj;
}, {}) || null;
const styles = tags?.length ? tags.map((tag)=>tag.replace(/:"?([^"]*)"?/g, ':$1;').trim()).join(' ') : null;
return `${classes?.length ? ` ${classes.join(' ')}` : ''}"` +
`${id ? ` id="${id}"` : ''}` +
`${styles?.length ? ` style="${styles.join(' ')}"` : ''}` +
`${attributes?.length ? ` ${attributes.join(' ')}` : ''}`;
return {
id : id,
classes : classes,
styles : styles,
attributes : _.isEmpty(attributes) ? null : attributes
};
};
const extractHTMLStyleTags = (htmlString)=>{
const id = htmlString.match(/id="([^"]*)"/)?.[1] || null;
const classes = htmlString.match(/class="([^"]*)"/)?.[1] || null;
const styles = htmlString.match(/style="([^"]*)"/)?.[1] || null;
const attributes = htmlString.match(/[a-zA-Z]+="[^"]*"/g)
?.filter((attr)=>!attr.startsWith('class="') && !attr.startsWith('style="') && !attr.startsWith('id="'))
.reduce((obj, attr)=>{
let [key, value] = attr.split('=');
value = value.replace(/"/g, '');
obj[key] = value;
return obj;
}, {}) || null;
return {
id : id,
classes : classes,
styles : styles,
attributes : _.isEmpty(attributes) ? null : attributes
};
};
const globalVarsList = {};

View File

@@ -1,7 +1,6 @@
require('./splitPane.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const SplitPane = createClass({
@@ -24,6 +23,9 @@ const SplitPane = createClass({
};
},
pane1 : React.createRef(null),
pane2 : React.createRef(null),
componentDidMount : function() {
const dividerPos = window.localStorage.getItem(this.props.storageKey);
if(dividerPos){
@@ -137,7 +139,6 @@ const SplitPane = createClass({
render : function(){
return <div className='splitPane' onPointerMove={this.handleMove} onPointerUp={this.handleUp}>
<Pane
ref='pane1'
width={this.state.currentDividerPos}
>
{React.cloneElement(this.props.children[0], {
@@ -147,7 +148,7 @@ const SplitPane = createClass({
})}
</Pane>
{this.renderDivider()}
<Pane ref='pane2' isDragging={this.state.isDragging}>{this.props.children[1]}</Pane>
<Pane isDragging={this.state.isDragging}>{this.props.children[1]}</Pane>
</div>;
}
});

View File

@@ -0,0 +1,58 @@
const Markdown = require('naturalcrit/markdown.js');
const dedent = require('dedent-tabs').default;
// Marked.js adds line returns after closing tags on some default tokens.
// This removes those line returns for comparison sake.
String.prototype.trimReturns = function(){
return this.replace(/\r?\n|\r/g, '');
};
const emoji = 'df_d12_2';
describe(`When emojis/icons are active`, ()=>{
it('when a word is between two colons (:word:), and a matching emoji exists, it is rendered as an emoji', function() {
const source = `:${emoji}:`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><i class="df d12-2"></i></p>`);
});
it('when a word is between two colons (:word:), and no matching emoji exists, it is not parsed', function() {
const source = `:invalid:`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p>:invalid:</p>`);
});
it('two valid emojis with no whitespace are prioritized over definition lists', function() {
const source = `:${emoji}::${emoji}:`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><i class="df d12-2"></i><i class="df d12-2"></i></p>`);
});
it('definition lists that are not also part of an emoji can coexist with normal emojis', function() {
const source = `definition :: term ${emoji}::${emoji}:`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<dl><dt>definition</dt><dd>term df_d12_2:<i class="df d12-2"></i></dd></dl>`);
});
it('A valid emoji is compatible with curly injectors', function() {
const source = `:${emoji}:{color:blue,myClass}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><i class="df d12-2 myClass" style="color:blue;"></i></p>`);
});
it('Emojis are not parsed inside of curly span CSS blocks', function() {
const source = `{{color:${emoji} text}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<span class="inline-block" style="color:df_d12_2;">text</span>`);
});
it('Emojis are not parsed inside of curly div CSS blocks', function() {
const source = dedent`{{color:${emoji}
text
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="color:df_d12_2;"><p>text</p></div>`);
});
// another test of the editor to confirm an autocomplete menu opens
});

View File

@@ -130,8 +130,8 @@ describe('Inline: When using the Inline syntax {{ }}', ()=>{
describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
it('Renders a div with text only', function() {
const source = dedent`{{
text
}}`;
text
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block"><p>text</p></div>`);
});
@@ -139,14 +139,14 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
it('Renders an empty div', function() {
const source = dedent`{{
}}`;
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block"></div>`);
});
it('Renders a single paragraph with opening and closing brackets', function() {
const source = dedent`{{
}}`;
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p>{{}}</p>`);
});
@@ -154,79 +154,79 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
it('Renders a div with a single class', function() {
const source = dedent`{{cat
}}`;
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat"></div>`);
});
it('Renders a div with a single class and text', function() {
const source = dedent`{{cat
Sample text.
}}`;
Sample text.
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat"><p>Sample text.</p></div>`);
});
it('Renders a div with two classes and text', function() {
const source = dedent`{{cat,dog
Sample text.
}}`;
Sample text.
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat dog"><p>Sample text.</p></div>`);
});
it('Renders a div with a style and text', function() {
const source = dedent`{{color:red
Sample text.
}}`;
Sample text.
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="color:red;"><p>Sample text.</p></div>`);
});
it('Renders a div with a style that has a string variable, and text', function() {
const source = dedent`{{--stringVariable:"'string'"
Sample text.
}}`;
Sample text.
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="--stringVariable:'string';"><p>Sample text.</p></div>`);
});
it('Renders a div with a style that has a string variable, and text', function() {
const source = dedent`{{--stringVariable:"'string'"
Sample text.
}}`;
Sample text.
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="--stringVariable:'string';"><p>Sample text.</p></div>`);
});
it('Renders a div with a class, style and text', function() {
const source = dedent`{{cat,color:red
Sample text.
}}`;
Sample text.
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat" style="color:red;"><p>Sample text.</p></div>`);
});
it('Renders a div with an ID, class, style and text (different order)', function() {
const source = dedent`{{color:red,cat,#dog
Sample text.
}}`;
Sample text.
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat" id="dog" style="color:red;"><p>Sample text.</p></div>`);
});
it('Renders a div with a single ID', function() {
const source = dedent`{{#cat,#dog
Sample text.
}}`;
Sample text.
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" id="cat"><p>Sample text.</p></div>`);
});
it('Renders a div with an ID, class, style and text, and a variable assignment', function() {
const source = dedent`{{color:red,cat,#dog,a="b and c",d="e"
Sample text.
}}`;
Sample text.
}}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class=\"block cat\" id=\"dog\" style=\"color:red;\" a=\"b and c\" d=\"e\"><p>Sample text.</p></div>`);
});
@@ -243,61 +243,91 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
describe('Injection: When an injection tag follows an element', ()=>{
// FIXME: Most of these fail because injections currently replace attributes, rather than append to. Or just minor extra whitespace issues.
describe('and that element is an inline-block', ()=>{
it.failing('Renders a span "text" with no injection', function() {
it('Renders a span "text" with no injection', function() {
const source = '{{ text}}{}';
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block">text</span>');
});
it.failing('Renders a span "text" with injected Class name', function() {
it('Renders a span "text" with injected Class name', function() {
const source = '{{ text}}{ClassName}';
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block ClassName">text</span>');
});
it.failing('Renders a span "text" with injected attribute', function() {
it('Renders a span "text" with injected attribute', function() {
const source = '{{ text}}{a="b and c"}';
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span a="b and c" class="inline-block ">text</span>');
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" a="b and c">text</span>');
});
it.failing('Renders a span "text" with injected style', function() {
it('Renders a span "text" with injected style', function() {
const source = '{{ text}}{color:red}';
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="color:red;">text</span>');
});
it.failing('Renders a span "text" with injected style using a string variable', function() {
it('Renders a span "text" with injected style using a string variable', function() {
const source = `{{ text}}{--stringVariable:"'string'"}`;
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<span class="inline-block" style="--stringVariable:'string';">text</span>`);
});
it.failing('Renders a span "text" with two injected styles', function() {
it('Renders a span "text" with two injected styles', function() {
const source = '{{ text}}{color:red,background:blue}';
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="color:red; background:blue;">text</span>');
});
it.failing('Renders an emphasis element with injected Class name', function() {
it('Renders a span "text" with its own ID, overwritten with an injected ID', function() {
const source = '{{#oldId text}}{#newId}';
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" id="newId">text</span>');
});
it('Renders a span "text" with its own attributes, overwritten with an injected attribute, plus a new one', function() {
const source = '{{attrA="old",attrB="old" text}}{attrA="new",attrC="new"}';
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" attrA="new" attrB="old" attrC="new">text</span>');
});
it('Renders a span "text" with its own attributes, overwritten with an injected attribute, ignoring "class", "style", and "id"', function() {
const source = '{{attrA="old",attrB="old" text}}{attrA="new",attrC="new",class="new",style="new",id="new"}';
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" attrA="new" attrB="old" attrC="new">text</span>');
});
it('Renders a span "text" with its own styles, appended with injected styles', function() {
const source = '{{color:blue,height:10px text}}{width:10px,color:red}';
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="color:blue; height:10px; width:10px; color:red;">text</span>');
});
it('Renders a span "text" with its own classes, appended with injected classes', function() {
const source = '{{classA,classB text}}{classA,classC}';
const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block classA classB classA classC">text</span>');
});
it('Renders an emphasis element with injected Class name', function() {
const source = '*emphasis*{big}';
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><em class="big">emphasis</em></p>');
});
it.failing('Renders a code element with injected style', function() {
it('Renders a code element with injected style', function() {
const source = '`code`{background:gray}';
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><code style="background:gray;">code</code></p>');
});
it.failing('Renders an image element with injected style', function() {
it('Renders an image element with injected style', function() {
const source = '![alt text](http://i.imgur.com/hMna6G0.png){position:absolute}';
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><img src="http://i.imgur.com/hMna6G0.png" alt="homebrew mug" style="position:absolute;"></p>');
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><img style="position:absolute;" src="http://i.imgur.com/hMna6G0.png" alt="alt text"></p>');
});
it.failing('Renders an element modified by only the first of two consecutive injections', function() {
it('Renders an element modified by only the first of two consecutive injections', function() {
const source = '{{ text}}{color:red}{background:blue}';
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><span class="inline-block" style="color:red;">text</span>{background:blue}</p>');
@@ -306,61 +336,106 @@ describe('Injection: When an injection tag follows an element', ()=>{
it('Renders an image with added attributes', function() {
const source = `![homebrew mug](https://i.imgur.com/hMna6G0.png) {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><img class="" style="position:absolute; bottom:20px; left:130px; width:220px;" a="b and c" d="e" src="https://i.imgur.com/hMna6G0.png" alt="homebrew mug"></p>`);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><img style="position:absolute; bottom:20px; left:130px; width:220px;" src="https://i.imgur.com/hMna6G0.png" alt="homebrew mug" a="b and c" d="e"></p>`);
});
});
describe('and that element is a block', ()=>{
it.failing('renders a div "text" with no injection', function() {
it('renders a div "text" with no injection', function() {
const source = '{{\ntext\n}}\n{}';
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block"><p>text</p></div>');
});
it.failing('renders a div "text" with injected Class name', function() {
it('renders a div "text" with injected Class name', function() {
const source = '{{\ntext\n}}\n{ClassName}';
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block ClassName"><p>text</p></div>');
});
it.failing('renders a div "text" with injected style', function() {
it('renders a div "text" with injected style', function() {
const source = '{{\ntext\n}}\n{color:red}';
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" style="color:red;"><p>text</p></div>');
});
it.failing('renders a div "text" with two injected styles', function() {
it('renders a div "text" with two injected styles', function() {
const source = dedent`{{
text
}}
{color:red,background:blue}`;
text
}}
{color:red,background:blue}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="color:red; background:blue"><p>text</p></div>`);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="color:red; background:blue;"><p>text</p></div>`);
});
it.failing('renders a div "text" with injected variable string', function() {
it('renders a div "text" with injected variable string', function() {
const source = dedent`{{
text
}}
{--stringVariable:"'string'"}`;
text
}}
{--stringVariable:"'string'"}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="--stringVariable:'string'"><p>text</p></div>`);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="--stringVariable:'string';"><p>text</p></div>`);
});
it.failing('renders an h2 header "text" with injected class name', function() {
it('Renders a span "text" with its own ID, overwritten with an injected ID', function() {
const source = dedent`{{#oldId
text
}}
{#newId}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" id="newId"><p>text</p></div>');
});
it('Renders a span "text" with its own attributes, overwritten with an injected attribute, plus a new one', function() {
const source = dedent`{{attrA="old",attrB="old"
text
}}
{attrA="new",attrC="new"}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" attrA="new" attrB="old" attrC="new"><p>text</p></div>');
});
it('Renders a span "text" with its own attributes, overwritten with an injected attribute, ignoring "class", "style", and "id"', function() {
const source = dedent`{{attrA="old",attrB="old"
text
}}
{attrA="new",attrC="new",class="new",style="new",id="new"}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" attrA="new" attrB="old" attrC="new"><p>text</p></div>');
});
it('Renders a span "text" with its own styles, appended with injected styles', function() {
const source = dedent`{{color:blue,height:10px
text
}}
{width:10px,color:red}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" style="color:blue; height:10px; width:10px; color:red;"><p>text</p></div>');
});
it('Renders a span "text" with its own classes, appended with injected classes', function() {
const source = dedent`{{classA,classB
text
}}
{classA,classC}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block classA classB classA classC"><p>text</p></div>');
});
it('renders an h2 header "text" with injected class name', function() {
const source = dedent`## text
{ClassName}`;
{ClassName}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<h2 class="ClassName">text</h2>');
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<h2 class="ClassName" id="text">text</h2>');
});
it.failing('renders a table with injected class name', function() {
it('renders a table with injected class name', function() {
const source = dedent`| Experience Points | Level |
|:------------------|:-----:|
| 0 | 1 |
| 300 | 2 |
|:------------------|:-----:|
| 0 | 1 |
| 300 | 2 |
{ClassName}`;
{ClassName}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<table class="ClassName"><thead><tr><th align=left>Experience Points</th><th align=center>Level</th></tr></thead><tbody><tr><td align=left>0</td><td align=center>1</td></tr><tr><td align=left>300</td><td align=center>2</td></tr></tbody></table>`);
});
@@ -376,23 +451,23 @@ describe('Injection: When an injection tag follows an element', ()=>{
// expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`...`); // FIXME: expect this to be injected into <ul>? Currently injects into last <li>
// });
it.failing('renders an h2 header "text" with injected class name, and "secondInjection" as regular text on the next line.', function() {
it('renders an h2 header "text" with injected class name, and "secondInjection" as regular text on the next line.', function() {
const source = dedent`## text
{ClassName}
{secondInjection}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<h2 class="ClassName">text</h2><p>{secondInjection}</p>');
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<h2 class="ClassName" id="text">text</h2><p>{secondInjection}</p>');
});
it.failing('renders a div nested into another div, the inner with class=innerDiv and the other class=outerDiv', function() {
it('renders a div nested into another div, the inner with class=innerDiv and the other class=outerDiv', function() {
const source = dedent`{{
outer text
{{
inner text
}}
{innerDiv}
}}
{outerDiv}`;
outer text
{{
inner text
}}
{innerDiv}
}}
{outerDiv}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block outerDiv"><p>outer text</p><div class="block innerDiv"><p>inner text</p></div></div>');
});

View File

@@ -329,7 +329,7 @@ describe('Normal Links and Images', ()=>{
const source = `![alt text](url){width:100px}`;
const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
<p><img class="" style="width:100px;" src="url" alt="alt text"></p>`.trimReturns());
<p><img style="width:100px;" src="url" alt="alt text"></p>`.trimReturns());
});
it('Renders normal links', function() {

View File

@@ -171,7 +171,7 @@ module.exports = {
**Condition Immunities** :: ${genList(['groggy', 'swagged', 'weak-kneed', 'buzzed', 'groovy', 'melancholy', 'drunk'], 3)}
**Senses** :: darkvision 60 ft., passive Perception ${_.random(3, 20)}
**Languages** :: ${genList(['Common', 'Pottymouth', 'Gibberish', 'Latin', 'Jive'], 2)}
**Challenge** :: ${_.random(0, 15)} (${_.random(10, 10000)} XP)
**Challenge** :: ${_.random(0, 15)} (${_.random(10, 10000)} XP) {{bonus **Proficiency Bonus** +${_.random(2, 6)}}}
___
${_.times(_.random(genLines, genLines + 2), function(){return genAbilities();}).join('\n:\n')}
:

View File

@@ -1,47 +1,47 @@
const _ = require("lodash");
const _ = require('lodash');
const quotes = [
"The sword glinted in the dim light, its edges keen and deadly. As the adventurer reached for it, he couldn't help but feel a surge of excitement mixed with fear. This was no ordinary blade.",
"The dragon's roar shook the ground beneath their feet, and the brave knight stood tall, his sword at the ready. He knew that this would be the battle of his life, but he was determined to emerge victorious.",
"The wizard's laboratory was a sight to behold, filled with bubbling cauldrons, ancient tomes, and strange artifacts from distant lands. As the apprentice gazed around in wonder, she knew that she was about to embark on a journey unlike any other.",
"The tavern was packed with rowdy patrons, their voices raised in song and laughter. The bard took center stage, strumming his lute and launching into a tale of adventure and heroism that had the crowd hanging on his every word.",
"The thief crept through the shadows, his eyes scanning the room for any sign of danger. He knew that one false move could mean the difference between success and failure, and he was determined to come out on top.",
"The elf queen stood atop her castle walls, surveying the kingdom below with a mix of pride and sadness. She knew that the coming war would be brutal, but she was determined to protect her people at all costs.",
"The necromancer's tower loomed in the distance, its dark spires piercing the sky. As the adventurers approached, they could feel the chill of death emanating from within",
"The ranger moved through the forest like a shadow, his senses attuned to every sound and movement around him. He knew that danger lurked behind every tree, but he was ready for whatever came his way.",
"The paladin knelt before the altar, his hands clasped in prayer. He knew that his faith would be tested in the days ahead, but he was ready to face whatever trials lay in store for him.",
"The druid communed with the spirits of nature, his mind merging with the trees, the animals, and the very earth itself. He knew that his power came with a great responsibility, and he was determined to use it for the greater good.",
'The sword glinted in the dim light, its edges keen and deadly. As the adventurer reached for it, he couldn\'t help but feel a surge of excitement mixed with fear. This was no ordinary blade.',
'The dragon\'s roar shook the ground beneath their feet, and the brave knight stood tall, his sword at the ready. He knew that this would be the battle of his life, but he was determined to emerge victorious.',
'The wizard\'s laboratory was a sight to behold, filled with bubbling cauldrons, ancient tomes, and strange artifacts from distant lands. As the apprentice gazed around in wonder, she knew that she was about to embark on a journey unlike any other.',
'The tavern was packed with rowdy patrons, their voices raised in song and laughter. The bard took center stage, strumming his lute and launching into a tale of adventure and heroism that had the crowd hanging on his every word.',
'The thief crept through the shadows, his eyes scanning the room for any sign of danger. He knew that one false move could mean the difference between success and failure, and he was determined to come out on top.',
'The elf queen stood atop her castle walls, surveying the kingdom below with a mix of pride and sadness. She knew that the coming war would be brutal, but she was determined to protect her people at all costs.',
'The necromancer\'s tower loomed in the distance, its dark spires piercing the sky. As the adventurers approached, they could feel the chill of death emanating from within',
'The ranger moved through the forest like a shadow, his senses attuned to every sound and movement around him. He knew that danger lurked behind every tree, but he was ready for whatever came his way.',
'The paladin knelt before the altar, his hands clasped in prayer. He knew that his faith would be tested in the days ahead, but he was ready to face whatever trials lay in store for him.',
'The druid communed with the spirits of nature, his mind merging with the trees, the animals, and the very earth itself. He knew that his power came with a great responsibility, and he was determined to use it for the greater good.',
];
const authors = [
"Unknown",
"James Wyatt",
"Eolande Blackwood",
"Ragnar Ironheart",
"Lyra Nightshade",
"Valtorius Darkstar",
"Isadora Fireheart",
"Theron Shadowbane",
"Lirien Starweaver",
"Drogathar Bonecrusher",
"Kaelen Frostblade",
'Unknown',
'James Wyatt',
'Eolande Blackwood',
'Ragnar Ironheart',
'Lyra Nightshade',
'Valtorius Darkstar',
'Isadora Fireheart',
'Theron Shadowbane',
'Lirien Starweaver',
'Drogathar Bonecrusher',
'Kaelen Frostblade',
];
const books = [
"The Blade of Destiny",
"Dragonfire and Steel",
"The Bard's Tale",
"Darkness Rising",
"The Sacred Quest",
"Shadows in the Forest",
"The Starweaver Chronicles",
"Beneath the Bones",
"Moonlit Magic",
"Frost and Fury",
'The Blade of Destiny',
'Dragonfire and Steel',
'The Bard\'s Tale',
'Darkness Rising',
'The Sacred Quest',
'Shadows in the Forest',
'The Starweaver Chronicles',
'Beneath the Bones',
'Moonlit Magic',
'Frost and Fury',
];
module.exports = () => {
return `
module.exports = ()=>{
return `
{{quote
${_.sample(quotes)}

View File

@@ -29,7 +29,7 @@ const getTOC = (pages)=>{
const res = [];
_.each(pages, (page, pageNum)=>{
if(!page.includes("{{frontCover}}") && !page.includes("{{insideCover}}") && !page.includes("{{partCover}}") && !page.includes("{{backCover}}")) {
if(!page.includes('{{frontCover}}') && !page.includes('{{insideCover}}') && !page.includes('{{partCover}}') && !page.includes('{{backCover}}')) {
const lines = page.split('\n');
_.each(lines, (line)=>{
if(_.startsWith(line, '# ')){

View File

@@ -1,6 +1,4 @@
@import (less) './themes/assets/assets.less';
@import (less) './themes/fonts/icon fonts/font-icons.less';
@import (less) './themes/fonts/icon fonts/diceFont.less';
:root {
//Colors
@@ -356,6 +354,11 @@
}
}
.bonus {
float: right;
padding-right: 0.5em;
}
// Monster Ability table
hr + table:first-of-type {
margin : 0;
@@ -543,10 +546,8 @@
color : white;
text-shadow : unset;
text-transform : uppercase;
filter : drop-shadow(0 0 1.5px black) drop-shadow(0 0 0 black)
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black);
-webkit-text-stroke: 0.2cm black;
paint-order:stroke;
}
h2 {
font-family : 'NodestoCapsCondensed';
@@ -554,10 +555,8 @@
font-weight : normal;
color : white;
letter-spacing : 0.1cm;
filter : drop-shadow(0 0 1px black) drop-shadow(0 0 0 black)
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black);
-webkit-text-stroke: 0.14cm black;
paint-order:stroke;
}
hr {
position : relative;
@@ -603,10 +602,8 @@
font-size : 0.496cm;
color : white;
text-align : center;
filter : drop-shadow(0 0 0.7px black) drop-shadow(0 0 0 black)
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black);
-webkit-text-stroke: 0.1cm black;
paint-order:stroke;
}
.logo {
position : absolute;

View File

@@ -307,8 +307,8 @@ module.exports = [
/**************** FONTS *************/
{
groupName : 'Fonts',
icon : 'fas fa-keyboard',
view : 'text',
icon : 'fas fa-keyboard',
view : 'text',
snippets : [
{
name : 'Open Sans',
@@ -341,59 +341,59 @@ module.exports = [
gen : dedent`{{font-family:MrEavesRemake Dummy Text}}`
},
{
name: 'Solbera Imitation',
icon: 'font SolberaImitationRemake',
gen: dedent`{{font-family:SolberaImitationRemake Dummy Text}}`
name : 'Solbera Imitation',
icon : 'font SolberaImitationRemake',
gen : dedent`{{font-family:SolberaImitationRemake Dummy Text}}`
},
{
name: 'Scaly Sans Small Caps',
icon: 'font ScalySansSmallCapsRemake',
gen: dedent`{{font-family:ScalySansSmallCapsRemake Dummy Text}}`
name : 'Scaly Sans Small Caps',
icon : 'font ScalySansSmallCapsRemake',
gen : dedent`{{font-family:ScalySansSmallCapsRemake Dummy Text}}`
},
{
name: 'Walter Turncoat',
icon: 'font WalterTurncoat',
gen: dedent`{{font-family:WalterTurncoat Dummy Text}}`
name : 'Walter Turncoat',
icon : 'font WalterTurncoat',
gen : dedent`{{font-family:WalterTurncoat Dummy Text}}`
},
{
name: 'Lato',
icon: 'font Lato',
gen: dedent`{{font-family:Lato Dummy Text}}`
name : 'Lato',
icon : 'font Lato',
gen : dedent`{{font-family:Lato Dummy Text}}`
},
{
name: 'Courier',
icon: 'font Courier',
gen: dedent`{{font-family:Courier Dummy Text}}`
name : 'Courier',
icon : 'font Courier',
gen : dedent`{{font-family:Courier Dummy Text}}`
},
{
name: 'Nodesto Caps Condensed',
icon: 'font NodestoCapsCondensed',
gen: dedent`{{font-family:NodestoCapsCondensed Dummy Text}}`
name : 'Nodesto Caps Condensed',
icon : 'font NodestoCapsCondensed',
gen : dedent`{{font-family:NodestoCapsCondensed Dummy Text}}`
},
{
name: 'Overpass',
icon: 'font Overpass',
gen: dedent`{{font-family:Overpass Dummy Text}}`
name : 'Overpass',
icon : 'font Overpass',
gen : dedent`{{font-family:Overpass Dummy Text}}`
},
{
name: 'Davek',
icon: 'font Davek',
gen: dedent`{{font-family:Davek Dummy Text}}`
name : 'Davek',
icon : 'font Davek',
gen : dedent`{{font-family:Davek Dummy Text}}`
},
{
name: 'Iokharic',
icon: 'font Iokharic',
gen: dedent`{{font-family:Iokharic Dummy Text}}`
name : 'Iokharic',
icon : 'font Iokharic',
gen : dedent`{{font-family:Iokharic Dummy Text}}`
},
{
name: 'Rellanic',
icon: 'font Rellanic',
gen: dedent`{{font-family:Rellanic Dummy Text}}`
name : 'Rellanic',
icon : 'font Rellanic',
gen : dedent`{{font-family:Rellanic Dummy Text}}`
},
{
name: 'Times New Roman',
icon: 'font TimesNewRoman',
gen: dedent`{{font-family:"Times New Roman" Dummy Text}}`
name : 'Times New Roman',
icon : 'font TimesNewRoman',
gen : dedent`{{font-family:"Times New Roman" Dummy Text}}`
}
]
},

View File

@@ -1,6 +1,8 @@
@import (less) './themes/fonts/5e/fonts.less';
@import (less) './themes/assets/assets.less';
@import (less) './themes/fonts/icon fonts/diceFont.less';
@import (less) './themes/fonts/iconFonts/elderberryInn.less';
@import (less) './themes/fonts/iconFonts/diceFont.less';
@import (less) './themes/fonts/iconFonts/gameIcons.less';
:root {
//Colors

View File

@@ -1,224 +0,0 @@
/* Icon Font: Elderberry Inn */
@font-face {
font-family : 'Elderberry-Inn';
font-style : normal;
font-weight : normal;
src : url('../../../fonts/icon fonts/Elderberry-Inn-Icons.woff2');
}
.page {
span.ei {
display : inline-block;
margin-right : 3px;
font-family : 'Elderberry-Inn';
line-height : 1;
vertical-align : baseline;
-moz-osx-font-smoothing : grayscale;
-webkit-font-smoothing : antialiased;
text-rendering : auto;
&.book::before { content : '\E900'; }
&.screen::before { content : '\E901'; }
/* Spell levels */
&.spell-0::before { content : '\E902'; }
&.spell-1::before { content : '\E903'; }
&.spell-2::before { content : '\E904'; }
&.spell-3::before { content : '\E905'; }
&.spell-4::before { content : '\E906'; }
&.spell-5::before { content : '\E907'; }
&.spell-6::before { content : '\E908'; }
&.spell-7::before { content : '\E909'; }
&.spell-8::before { content : '\E90A'; }
&.spell-9::before { content : '\E90B'; }
/* Damage types */
&.acid::before { content : '\E90C'; }
&.bludgeoning::before { content : '\E90D'; }
&.cold::before { content : '\E90E'; }
&.fire::before { content : '\E90F'; }
&.force::before { content : '\E910'; }
&.lightning::before { content : '\E911'; }
&.necrotic::before { content : '\E912'; }
&.piercing::before { content : '\E914'; }
&.poison::before { content : '\E913'; }
&.psychic::before { content : '\E915'; }
&.radiant::before { content : '\E916'; }
&.slashing::before { content : '\E917'; }
&.thunder::before { content : '\E918'; }
/* DnD Conditions */
&.blinded::before { content : '\E919'; }
&.charmed::before { content : '\E91A'; }
&.deafened::before { content : '\E91B'; }
&.exhaust-1::before { content : '\E91C'; }
&.exhaust-2::before { content : '\E91D'; }
&.exhaust-3::before { content : '\E91E'; }
&.exhaust-4::before { content : '\E91F'; }
&.exhaust-5::before { content : '\E920'; }
&.exhaust-6::before { content : '\E921'; }
&.frightened::before { content : '\E922'; }
&.grappled::before { content : '\E923'; }
&.incapacitated::before { content : '\E924'; }
&.invisible::before { content : '\E926'; }
&.paralyzed::before { content : '\E927'; }
&.petrified::before { content : '\E928'; }
&.poisoned::before { content : '\E929'; }
&.prone::before { content : '\E92A'; }
&.restrained::before { content : '\E92B'; }
&.stunned::before { content : '\E92C'; }
&.unconscious::before { content : '\E925'; }
/* Character Classes and Features */
&.barbarian-rage::before { content : '\E92D'; }
&.barbarian-reckless-attack::before { content : '\E92E'; }
&.bardic-inspiration::before { content : '\E92F'; }
&.cleric-channel-divinity::before { content : '\E930'; }
&.druid-wild-shape::before { content : '\E931'; }
&.fighter-action-surge::before { content : '\E932'; }
&.fighter-second-wind::before { content : '\E933'; }
&.monk-flurry-blows::before { content : '\E934'; }
&.monk-patient-defense::before { content : '\E935'; }
&.monk-step-of-the-wind::before { content : '\E936'; }
&.monk-step-of-the-wind-2::before { content : '\E937'; }
&.monk-step-of-the-wind-3::before { content : '\E938'; }
&.monk-stunning-strike::before { content : '\E939'; }
&.monk-stunning-strike-2::before { content : '\E939'; }
&.paladin-divine-smite::before { content : '\E93B'; }
&.paladin-lay-on-hands::before { content : '\E93C'; }
&.barbarian-abilities::before { content : '\E93D'; }
&.barbarian::before { content : '\E93E'; }
&.bard-abilities::before { content : '\E93F'; }
&.bard::before { content : '\E940'; }
&.cleric-abilities::before { content : '\E941'; }
&.cleric::before { content : '\E942'; }
&.druid-abilities::before { content : '\E943'; }
&.druid::before { content : '\E944'; }
&.fighter-abilities::before { content : '\E945'; }
&.fighter::before { content : '\E946'; }
&.monk-abilities::before { content : '\E947'; }
&.monk::before { content : '\E948'; }
&.paladin-abilities::before { content : '\E949'; }
&.paladin::before { content : '\E94A'; }
&.ranger-abilities::before { content : '\E94B'; }
&.ranger::before { content : '\E94C'; }
&.rogue-abilities::before { content : '\E94D'; }
&.rogue::before { content : '\E94E'; }
&.sorcerer-abilities::before { content : '\E94F'; }
&.sorcerer::before { content : '\E950'; }
&.warlock-abilities::before { content : '\E951'; }
&.warlock::before { content : '\E952'; }
&.wizard-abilities::before { content : '\E953'; }
&.wizard::before { content : '\E954'; }
/* Types of actions */
&.movement::before { content : '\E955'; }
&.action::before { content : '\E956'; }
&.bonus-action::before { content : '\E957'; }
&.reaction::before { content : '\E958'; }
/* SRD Spells */
&.acid-arrow::before { content : '\E959'; }
&.action-1::before { content : '\E95A'; }
&.alter-self::before { content : '\E95B'; }
&.alter-self-2::before { content : '\E95C'; }
&.animal-friendship::before { content : '\E95E'; }
&.animate-dead::before { content : '\E95F'; }
&.animate-objects::before { content : '\E960'; }
&.animate-objects-2::before { content : '\E961'; }
&.bane::before { content : '\E962'; }
&.bless::before { content : '\E963'; }
&.blur::before { content : '\E964'; }
&.bonus::before { content : '\E965'; }
&.branding-smite::before { content : '\E966'; }
&.burning-hands::before { content : '\E967'; }
&.charm-person::before { content : '\E968'; }
&.chill-touch::before { content : '\E969'; }
&.cloudkill::before { content : '\E96A'; }
&.comprehend-languages::before { content : '\E96B'; }
&.cone-of-cold::before { content : '\E96C'; }
&.conjure-elemental::before { content : '\E96D'; }
&.conjure-minor-elemental::before { content : '\E96E'; }
&.control-water::before { content : '\E96F'; }
&.counterspell::before { content : '\E970'; }
&.cure-wounds::before { content : '\E971'; }
&.dancing-lights::before { content : '\E972'; }
&.darkness::before { content : '\E973'; }
&.detect-magic::before { content : '\E974'; }
&.disguise-self::before { content : '\E975'; }
&.disintegrate::before { content : '\E976'; }
&.dispel-evil-and-good::before { content : '\E977'; }
&.dispel-magic::before { content : '\E978'; }
&.dominate-monster::before { content : '\E979'; }
&.dominate-person::before { content : '\E97A'; }
&.eldritch-blast::before { content : '\E97B'; }
&.enlarge-reduce::before { content : '\E97C'; }
&.entangle::before { content : '\E97D'; }
&.faerie-fire::before { content : '\E97E'; }
&.faerie-fire2::before { content : '\E97F'; }
&.feather-fall::before { content : '\E980'; }
&.find-familiar::before { content : '\E981'; }
&.finger-of-death::before { content : '\E982'; }
&.fireball::before { content : '\E983'; }
&.floating-disk::before { content : '\E984'; }
&.fly::before { content : '\E985'; }
&.fog-cloud::before { content : '\E986'; }
&.gaseous-form::before { content : '\E987'; }
&.gaseous-form2::before { content : '\E988'; }
&.gentle-repose::before { content : '\E989'; }
&.gentle-repose2::before { content : '\E98A'; }
&.globe-of-invulnerability::before { content : '\E98B'; }
&.guiding-bolt::before { content : '\E98C'; }
&.healing-word::before { content : '\E98D'; }
&.heat-metal::before { content : '\E98E'; }
&.hellish-rebuke::before { content : '\E98F'; }
&.heroes-feast::before { content : '\E990'; }
&.heroism::before { content : '\E991'; }
&.hideous-laughter::before { content : '\E992'; }
&.identify::before { content : '\E993'; }
&.illusory-script::before { content : '\E994'; }
&.inflict-wounds::before { content : '\E995'; }
&.light::before { content : '\E996'; }
&.longstrider::before { content : '\E997'; }
&.mage-armor::before { content : '\E998'; }
&.mage-hand::before { content : '\E999'; }
&.magic-missile::before { content : '\E99A'; }
&.mass-cure-wounds::before { content : '\E99B'; }
&.mass-healing-word::before { content : '\E99C'; }
&.Mending::before { content : '\E99D'; }
&.message::before { content : '\E99E'; }
&.Minor-illusion::before { content : '\E99F'; }
&.movement1::before { content : '\E9A0'; }
&.polymorph::before { content : '\E9A1'; }
&.power-word-kill::before { content : '\E9A2'; }
&.power-word-stun::before { content : '\E9A3'; }
&.prayer-of-healing::before { content : '\E9A4'; }
&.prestidigitation::before { content : '\E9A5'; }
&.protection-from-evil-and-good::before { content : '\E9A6'; }
&.raise-read::before { content : '\E9A7'; }
&.raise-read2::before { content : '\E9A8'; }
&.reaction1::before { content : '\E9A9'; }
&.resurrection::before { content : '\E9AA'; }
&.resurrection2::before { content : '\E9AB'; }
&.revivify::before { content : '\E9AC'; }
&.revivify2::before { content : '\E9AD'; }
&.sacred-flame::before { content : '\E9AE'; }
&.sanctuary::before { content : '\E9AF'; }
&.scorching-ray::before { content : '\E9B0'; }
&.sending::before { content : '\E9B1'; }
&.shatter::before { content : '\E9B2'; }
&.shield::before { content : '\E9B3'; }
&.silent-image::before { content : '\E9B4'; }
&.sleep::before { content : '\E9B5'; }
&.speak-with-animals::before { content : '\E9B6'; }
&.telekinesis::before { content : '\E9B7'; }
&.true-strike::before { content : '\E9B8'; }
&.vicious-mockery::before { content : '\E9B9'; }
&.wall-of-fire::before { content : '\E9BA'; }
&.wall-of-force::before { content : '\E9BB'; }
&.wall-of-ice::before { content : '\E9BC'; }
&.wall-of-stone::before { content : '\E9BD'; }
&.wall-of-thorns::before { content : '\E9BE'; }
&.wish::before { content : '\E9BF'; }
}
}

View File

@@ -0,0 +1,96 @@
const diceFont = {
'df_f' : 'df F',
'df_f_minus' : 'df F-minus',
'df_f_plus' : 'df F-plus',
'df_f_zero' : 'df F-zero',
'df_d10' : 'df d10',
'df_d10_1' : 'df d10-1',
'df_d10_10' : 'df d10-10',
'df_d10_2' : 'df d10-2',
'df_d10_3' : 'df d10-3',
'df_d10_4' : 'df d10-4',
'df_d10_5' : 'df d10-5',
'df_d10_6' : 'df d10-6',
'df_d10_7' : 'df d10-7',
'df_d10_8' : 'df d10-8',
'df_d10_9' : 'df d10-9',
'df_d12' : 'df d12',
'df_d12_1' : 'df d12-1',
'df_d12_10' : 'df d12-10',
'df_d12_11' : 'df d12-11',
'df_d12_12' : 'df d12-12',
'df_d12_2' : 'df d12-2',
'df_d12_3' : 'df d12-3',
'df_d12_4' : 'df d12-4',
'df_d12_5' : 'df d12-5',
'df_d12_6' : 'df d12-6',
'df_d12_7' : 'df d12-7',
'df_d12_8' : 'df d12-8',
'df_d12_9' : 'df d12-9',
'df_d2' : 'df d2',
'df_d2_1' : 'df d2-1',
'df_d2_2' : 'df d2-2',
'df_d20' : 'df d20',
'df_d20_1' : 'df d20-1',
'df_d20_10' : 'df d20-10',
'df_d20_11' : 'df d20-11',
'df_d20_12' : 'df d20-12',
'df_d20_13' : 'df d20-13',
'df_d20_14' : 'df d20-14',
'df_d20_15' : 'df d20-15',
'df_d20_16' : 'df d20-16',
'df_d20_17' : 'df d20-17',
'df_d20_18' : 'df d20-18',
'df_d20_19' : 'df d20-19',
'df_d20_2' : 'df d20-2',
'df_d20_20' : 'df d20-20',
'df_d20_3' : 'df d20-3',
'df_d20_4' : 'df d20-4',
'df_d20_5' : 'df d20-5',
'df_d20_6' : 'df d20-6',
'df_d20_7' : 'df d20-7',
'df_d20_8' : 'df d20-8',
'df_d20_9' : 'df d20-9',
'df_d4' : 'df d4',
'df_d4_1' : 'df d4-1',
'df_d4_2' : 'df d4-2',
'df_d4_3' : 'df d4-3',
'df_d4_4' : 'df d4-4',
'df_d6' : 'df d6',
'df_d6_1' : 'df d6-1',
'df_d6_2' : 'df d6-2',
'df_d6_3' : 'df d6-3',
'df_d6_4' : 'df d6-4',
'df_d6_5' : 'df d6-5',
'df_d6_6' : 'df d6-6',
'df_d8' : 'df d8',
'df_d8_1' : 'df d8-1',
'df_d8_2' : 'df d8-2',
'df_d8_3' : 'df d8-3',
'df_d8_4' : 'df d8-4',
'df_d8_5' : 'df d8-5',
'df_d8_6' : 'df d8-6',
'df_d8_7' : 'df d8-7',
'df_d8_8' : 'df d8-8',
'df_dot_d6' : 'df dot-d6',
'df_dot_d6_1' : 'df dot-d6-1',
'df_dot_d6_2' : 'df dot-d6-2',
'df_dot_d6_3' : 'df dot-d6-3',
'df_dot_d6_4' : 'df dot-d6-4',
'df_dot_d6_5' : 'df dot-d6-5',
'df_dot_d6_6' : 'df dot-d6-6',
'df_small_dot_d6_1' : 'df small-dot-d6-1',
'df_small_dot_d6_2' : 'df small-dot-d6-2',
'df_small_dot_d6_3' : 'df small-dot-d6-3',
'df_small_dot_d6_4' : 'df small-dot-d6-4',
'df_small_dot_d6_5' : 'df small-dot-d6-5',
'df_small_dot_d6_6' : 'df small-dot-d6-6',
'df_solid_small_dot_d6_1' : 'df solid-small-dot-d6-1',
'df_solid_small_dot_d6_2' : 'df solid-small-dot-d6-2',
'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'
};
module.exports = diceFont;

View File

@@ -3,7 +3,7 @@
font-family : 'DiceFont';
font-style : normal;
font-weight : normal;
src : url('../../../fonts/icon fonts/diceFont.woff2');
src : url('../../../fonts/iconFonts/diceFont.woff2');
}
.df {

View File

@@ -0,0 +1,209 @@
const elderberryInn = {
'ei_book' : 'ei book',
'ei_screen' : 'ei screen',
/* Spell levels */
'ei_spell_0' : 'ei spell-0',
'ei_spell_1' : 'ei spell-1',
'ei_spell_2' : 'ei spell-2',
'ei_spell_3' : 'ei spell-3',
'ei_spell_4' : 'ei spell-4',
'ei_spell_5' : 'ei spell-5',
'ei_spell_6' : 'ei spell-6',
'ei_spell_7' : 'ei spell-7',
'ei_spell_8' : 'ei spell-8',
'ei_spell_9' : 'ei spell-9',
/* Damage types */
'ei_acid' : 'ei acid',
'ei_bludgeoning' : 'ei bludgeoning',
'ei_cold' : 'ei cold',
'ei_fire' : 'ei fire',
'ei_force' : 'ei force',
'ei_lightning' : 'ei lightning',
'ei_necrotic' : 'ei necrotic',
'ei_piercing' : 'ei piercing',
'ei_poison' : 'ei poison',
'ei_psychic' : 'ei psychic',
'ei_radiant' : 'ei radiant',
'ei_slashing' : 'ei slashing',
'ei_thunder' : 'ei thunder',
/* DnD Conditions */
'ei_blinded' : 'ei blinded',
'ei_charmed' : 'ei charmed',
'ei_deafened' : 'ei deafened',
'ei_exhaust1' : 'ei exhaust-1',
'ei_blinded' : 'ei blinded',
'ei_exhaust2' : 'ei exhaust-2',
'ei_exhaust3' : 'ei exhaust-3',
'ei_exhaust4' : 'ei exhaust-4',
'ei_exhaust5' : 'ei exhaust-5',
'ei_exhaust6' : 'ei exhaust-6',
'ei_frightened' : 'ei frightened',
'ei_grappled' : 'ei grappled',
'ei_incapacitated' : 'ei incapacitated',
'ei_invisible' : 'ei invisible',
'ei_paralyzed' : 'ei paralyzed',
'ei_petrified' : 'ei petrified',
'ei_poisoned' : 'ei poisoned',
'ei_prone' : 'ei prone',
'ei_restrained' : 'ei restrained',
'ei_stunned' : 'ei stunned',
'ei_unconscious' : 'ei unconscious',
/* Character Classes and Features */
'ei_barbarian_rage' : 'ei barbarian-rage',
'ei_barbarian_reckless_attack' : 'ei barbarian-reckless-attack',
'ei_bardic_inspiration' : 'ei bardic-inspiration',
'ei_cleric_channel_divinity' : 'ei cleric-channel-divinity',
'ei_druid_wild_shape' : 'ei druid-wild-shape',
'ei_fighter_action_surge' : 'ei fighter-action-surge',
'ei_fighter_second_wind' : 'ei fighter-second-wind',
'ei_monk_flurry_blows' : 'ei monk-flurry-blows',
'ei_monk_patient_defense' : 'ei monk-patient-defense',
'ei_monk_step_of_the_wind' : 'ei monk-step-of-the-wind',
'ei_monk_step_of_the_wind2' : 'ei monk-step-of-the-wind-2',
'ei_monk_step_of_the_wind3' : 'ei monk-step-of-the-wind-3',
'ei_monk_stunning_strike' : 'ei monk-stunning-strike',
'ei_monk_stunning_strike2' : 'ei monk-stunning-strike-2',
'ei_paladin_divine_smite' : 'ei paladin-divine-smite',
'ei_paladin_lay_on_hands' : 'ei paladin-lay-on-hands',
'ei_barbarian_abilities' : 'ei barbarian-abilities',
'ei_barbarian' : 'ei barbarian',
'ei_bard_abilities' : 'ei bard-abilities',
'ei_bard' : 'ei bard',
'ei_cleric_abilities' : 'ei cleric-abilities',
'ei_cleric' : 'ei cleric',
'ei_druid_abilities' : 'ei druid-abilities',
'ei_druid' : 'ei druid',
'ei_fighter_abilities' : 'ei fighter-abilities',
'ei_fighter' : 'ei fighter',
'ei_monk_abilities' : 'ei monk-abilities',
'ei_monk' : 'ei monk',
'ei_paladin_abilities' : 'ei paladin-abilities',
'ei_paladin' : 'ei paladin',
'ei_ranger_abilities' : 'ei ranger-abilities',
'ei_ranger' : 'ei ranger',
'ei_rogue_abilities' : 'ei rogue-abilities',
'ei_rogue' : 'ei rogue',
'ei_sorcerer_abilities' : 'ei sorcerer-abilities',
'ei_sorcerer' : 'ei sorcerer',
'ei_warlock_abilities' : 'ei warlock-abilities',
'ei_warlock' : 'ei warlock',
'ei_wizard_abilities' : 'ei wizard-abilities',
'ei_wizard' : 'ei wizard',
/* Types of actions */
'ei_movement' : 'ei movement',
'ei_action' : 'ei action',
'ei_bonus_action' : 'ei bonus-action',
'ei_reaction' : 'ei reaction',
/* SRD Spells */
'ei_acid_arrow' : 'ei acid-arrow',
'ei_action1' : 'ei action-1',
'ei_alter_self' : 'ei alter-self',
'ei_alter_self2' : 'ei alter-self-2',
'ei_magic_beans' : 'ei magic-beans',
'ei_animal_friendship' : 'ei animal-friendship',
'ei_animate_dead' : 'ei animate-dead',
'ei_animate_objects' : 'ei animate-objects',
'ei_animate_objects2' : 'ei animate-objects-2',
'ei_bane' : 'ei bane',
'ei_bless' : 'ei bless',
'ei_blur' : 'ei blur',
'ei_bonus' : 'ei bonus',
'ei_branding_smite' : 'ei branding-smite',
'ei_burning_hands' : 'ei burning-hands',
'ei_charm_person' : 'ei charm-person',
'ei_chill_touch' : 'ei chill-touch',
'ei_cloudkill' : 'ei cloudkill',
'ei_comprehend_languages' : 'ei comprehend-languages',
'ei_cone_of_cold' : 'ei cone-of-cold',
'ei_conjure_elemental' : 'ei conjure-elemental',
'ei_conjure_minor_elemental' : 'ei conjure-minor-elemental',
'ei_control_water' : 'ei control-water',
'ei_counterspell' : 'ei counterspell',
'ei_cure_wounds' : 'ei cure-wounds',
'ei_dancing_lights' : 'ei dancing-lights',
'ei_darkness' : 'ei darkness',
'ei_detect_magic' : 'ei detect-magic',
'ei_disguise_self' : 'ei disguise-self',
'ei_disintegrate' : 'ei disintegrate',
'ei_dispel_evil_and_good' : 'ei dispel-evil-and-good',
'ei_dispel_magic' : 'ei dispel-magic',
'ei_dominate_monster' : 'ei dominate-monster',
'ei_dominate_person' : 'ei dominate-person',
'ei_eldritch_blast' : 'ei eldritch-blast',
'ei_enlarge_reduce' : 'ei enlarge-reduce',
'ei_entangle' : 'ei entangle',
'ei_faerie_fire' : 'ei faerie-fire',
'ei_faerie_fire2' : 'ei faerie-fire2',
'ei_feather_fall' : 'ei feather-fall',
'ei_find_familiar' : 'ei find-familiar',
'ei_finger_of_death' : 'ei finger-of-death',
'ei_fireball' : 'ei fireball',
'ei_floating_disk' : 'ei floating-disk',
'ei_fly' : 'ei fly',
'ei_fog_cloud' : 'ei fog-cloud',
'ei_gaseous_form' : 'ei gaseous-form',
'ei_gaseous_form2' : 'ei gaseous-form2',
'ei_gentle_repose' : 'ei gentle-repose',
'ei_gentle_repose2' : 'ei gentle-repose2',
'ei_globe_of_invulnerability' : 'ei globe-of-invulnerability',
'ei_guiding_bolt' : 'ei guiding-bolt',
'ei_healing_word' : 'ei healing-word',
'ei_heat_metal' : 'ei heat-metal',
'ei_hellish_rebuke' : 'ei hellish-rebuke',
'ei_heroes_feast' : 'ei heroes-feast',
'ei_heroism' : 'ei heroism',
'ei_hideous_laughter' : 'ei hideous-laughter',
'ei_identify' : 'ei identify',
'ei_illusory_script' : 'ei illusory-script',
'ei_inflict_wounds' : 'ei inflict-wounds',
'ei_light' : 'ei light',
'ei_longstrider' : 'ei longstrider',
'ei_mage_armor' : 'ei mage-armor',
'ei_mage_hand' : 'ei mage-hand',
'ei_magic_missile' : 'ei magic-missile',
'ei_mass_cure_wounds' : 'ei mass-cure-wounds',
'ei_mass_healing_word' : 'ei mass-healing-word',
'ei_mending' : 'ei _mending',
'ei_message' : 'ei message',
'ei_minor_illusion' : 'ei _minor-illusion',
'ei_movement1' : 'ei movement1',
'ei_polymorph' : 'ei polymorph',
'ei_power_word_kill' : 'ei power-word-kill',
'ei_power_word_stun' : 'ei power-word-stun',
'ei_prayer_of_healing' : 'ei prayer-of-healing',
'ei_prestidigitation' : 'ei prestidigitation',
'ei_protection_from_evil_and_good' : 'ei protection-from-evil-and-good',
'ei_raise_dead' : 'ei raise-dead',
'ei_raise_dead2' : 'ei raise-dead2',
'ei_reaction1' : 'ei reaction1',
'ei_resurrection' : 'ei resurrection',
'ei_resurrection2' : 'ei resurrection2',
'ei_revivify' : 'ei revivify',
'ei_revivify2' : 'ei revivify2',
'ei_sacred_flame' : 'ei sacred-flame',
'ei_sanctuary' : 'ei sanctuary',
'ei_scorching_ray' : 'ei scorching-ray',
'ei_sending' : 'ei sending',
'ei_shatter' : 'ei shatter',
'ei_shield' : 'ei shield',
'ei_silent_image' : 'ei silent-image',
'ei_sleep' : 'ei sleep',
'ei_speak_with_animals' : 'ei speak-with-animals',
'ei_telekinesis' : 'ei telekinesis',
'ei_true_strike' : 'ei true-strike',
'ei_vicious_mockery' : 'ei vicious-mockery',
'ei_wall_of_fire' : 'ei wall-of-fire',
'ei_wall_of_force' : 'ei wall-of-force',
'ei_wall_of_ice' : 'ei wall-of-ice',
'ei_wall_of_stone' : 'ei wall-of-stone',
'ei_wall_of_thorns' : 'ei wall-of-thorns',
'ei_wish' : 'ei wish'
};
module.exports = elderberryInn;

View File

@@ -0,0 +1,224 @@
/* Icon Font: Elderberry Inn */
@font-face {
font-family : 'Elderberry-Inn';
font-style : normal;
font-weight : normal;
src : url('../../../fonts/iconFonts/elderberryInn.woff2');
}
.ei {
display : inline-block;
margin-right : 3px;
font-family : 'Elderberry-Inn';
line-height : 1;
vertical-align : baseline;
-moz-osx-font-smoothing : grayscale;
-webkit-font-smoothing : antialiased;
text-rendering : auto;
&.book::before { content : '\E900'; }
&.screen::before { content : '\E901'; }
/* Spell levels */
&.spell-0::before { content : '\E902'; }
&.spell-1::before { content : '\E903'; }
&.spell-2::before { content : '\E904'; }
&.spell-3::before { content : '\E905'; }
&.spell-4::before { content : '\E906'; }
&.spell-5::before { content : '\E907'; }
&.spell-6::before { content : '\E908'; }
&.spell-7::before { content : '\E909'; }
&.spell-8::before { content : '\E90A'; }
&.spell-9::before { content : '\E90B'; }
/* Damage types */
&.acid::before { content : '\E90C'; }
&.bludgeoning::before { content : '\E90D'; }
&.cold::before { content : '\E90E'; }
&.fire::before { content : '\E90F'; }
&.force::before { content : '\E910'; }
&.lightning::before { content : '\E911'; }
&.necrotic::before { content : '\E912'; }
&.piercing::before { content : '\E913'; }
&.poison::before { content : '\E914'; }
&.psychic::before { content : '\E915'; }
&.radiant::before { content : '\E916'; }
&.slashing::before { content : '\E917'; }
&.thunder::before { content : '\E918'; }
/* DnD Conditions */
&.blinded::before { content : '\E919'; }
&.charmed::before { content : '\E91A'; }
&.deafened::before { content : '\E91B'; }
&.exhaust-1::before { content : '\E91C'; }
&.exhaust-2::before { content : '\E91D'; }
&.exhaust-3::before { content : '\E91E'; }
&.exhaust-4::before { content : '\E91F'; }
&.exhaust-5::before { content : '\E920'; }
&.exhaust-6::before { content : '\E921'; }
&.frightened::before { content : '\E922'; }
&.grappled::before { content : '\E923'; }
&.incapacitated::before { content : '\E924'; }
&.unconscious::before { content : '\E925'; }
&.invisible::before { content : '\E926'; }
&.paralyzed::before { content : '\E927'; }
&.petrified::before { content : '\E928'; }
&.poisoned::before { content : '\E929'; }
&.prone::before { content : '\E92A'; }
&.restrained::before { content : '\E92B'; }
&.stunned::before { content : '\E92C'; }
/* Character Classes and Features */
&.barbarian-rage::before { content : '\E92D'; }
&.barbarian-reckless-attack::before { content : '\E92E'; }
&.bardic-inspiration::before { content : '\E92F'; }
&.cleric-channel-divinity::before { content : '\E930'; }
&.druid-wild-shape::before { content : '\E931'; }
&.fighter-action-surge::before { content : '\E932'; }
&.fighter-second-wind::before { content : '\E933'; }
&.monk-flurry-blows::before { content : '\E934'; }
&.monk-patient-defense::before { content : '\E935'; }
&.monk-step-of-the-wind::before { content : '\E936'; }
&.monk-step-of-the-wind-2::before { content : '\E937'; }
&.monk-step-of-the-wind-3::before { content : '\E938'; }
&.monk-stunning-strike::before { content : '\E939'; }
&.monk-stunning-strike-2::before { content : '\E93A'; }
&.paladin-divine-smite::before { content : '\E93B'; }
&.paladin-lay-on-hands::before { content : '\E93C'; }
&.barbarian-abilities::before { content : '\E93D'; }
&.barbarian::before { content : '\E93E'; }
&.bard-abilities::before { content : '\E93F'; }
&.bard::before { content : '\E940'; }
&.cleric-abilities::before { content : '\E941'; }
&.cleric::before { content : '\E942'; }
&.druid-abilities::before { content : '\E943'; }
&.druid::before { content : '\E944'; }
&.fighter-abilities::before { content : '\E945'; }
&.fighter::before { content : '\E946'; }
&.monk-abilities::before { content : '\E947'; }
&.monk::before { content : '\E948'; }
&.paladin-abilities::before { content : '\E949'; }
&.paladin::before { content : '\E94A'; }
&.ranger-abilities::before { content : '\E94B'; }
&.ranger::before { content : '\E94C'; }
&.rogue-abilities::before { content : '\E94D'; }
&.rogue::before { content : '\E94E'; }
&.sorcerer-abilities::before { content : '\E94F'; }
&.sorcerer::before { content : '\E950'; }
&.warlock-abilities::before { content : '\E951'; }
&.warlock::before { content : '\E952'; }
&.wizard-abilities::before { content : '\E953'; }
&.wizard::before { content : '\E954'; }
/* Types of actions */
&.movement::before { content : '\E955'; }
&.action::before { content : '\E956'; }
&.bonus-action::before { content : '\E957'; }
&.reaction::before { content : '\E958'; }
/* SRD Spells */
&.acid-arrow::before { content : '\E959'; }
&.action-1::before { content : '\E95A'; }
&.alter-self::before { content : '\E95B'; }
&.alter-self-2::before { content : '\E95C'; }
&.magic-beans::before { content : '\E95D'; }
&.animal-friendship::before { content : '\E95E'; }
&.animate-dead::before { content : '\E95F'; }
&.animate-objects::before { content : '\E960'; }
&.animate-objects-2::before { content : '\E961'; }
&.bane::before { content : '\E962'; }
&.bless::before { content : '\E963'; }
&.blur::before { content : '\E964'; }
&.bonus::before { content : '\E965'; }
&.branding-smite::before { content : '\E966'; }
&.burning-hands::before { content : '\E967'; }
&.charm-person::before { content : '\E968'; }
&.chill-touch::before { content : '\E969'; }
&.cloudkill::before { content : '\E96A'; }
&.comprehend-languages::before { content : '\E96B'; }
&.cone-of-cold::before { content : '\E96C'; }
&.conjure-elemental::before { content : '\E96D'; }
&.conjure-minor-elemental::before { content : '\E96E'; }
&.control-water::before { content : '\E96F'; }
&.counterspell::before { content : '\E970'; }
&.cure-wounds::before { content : '\E971'; }
&.dancing-lights::before { content : '\E972'; }
&.darkness::before { content : '\E973'; }
&.detect-magic::before { content : '\E974'; }
&.disguise-self::before { content : '\E975'; }
&.disintegrate::before { content : '\E976'; }
&.dispel-evil-and-good::before { content : '\E977'; }
&.dispel-magic::before { content : '\E978'; }
&.dominate-monster::before { content : '\E979'; }
&.dominate-person::before { content : '\E97A'; }
&.eldritch-blast::before { content : '\E97B'; }
&.enlarge-reduce::before { content : '\E97C'; }
&.entangle::before { content : '\E97D'; }
&.faerie-fire::before { content : '\E97E'; }
&.faerie-fire2::before { content : '\E97F'; }
&.feather-fall::before { content : '\E980'; }
&.find-familiar::before { content : '\E981'; }
&.finger-of-death::before { content : '\E982'; }
&.fireball::before { content : '\E983'; }
&.floating-disk::before { content : '\E984'; }
&.fly::before { content : '\E985'; }
&.fog-cloud::before { content : '\E986'; }
&.gaseous-form::before { content : '\E987'; }
&.gaseous-form2::before { content : '\E988'; }
&.gentle-repose::before { content : '\E989'; }
&.gentle-repose2::before { content : '\E98A'; }
&.globe-of-invulnerability::before { content : '\E98B'; }
&.guiding-bolt::before { content : '\E98C'; }
&.healing-word::before { content : '\E98D'; }
&.heat-metal::before { content : '\E98E'; }
&.hellish-rebuke::before { content : '\E98F'; }
&.heroes-feast::before { content : '\E990'; }
&.heroism::before { content : '\E991'; }
&.hideous-laughter::before { content : '\E992'; }
&.identify::before { content : '\E993'; }
&.illusory-script::before { content : '\E994'; }
&.inflict-wounds::before { content : '\E995'; }
&.light::before { content : '\E996'; }
&.longstrider::before { content : '\E997'; }
&.mage-armor::before { content : '\E998'; }
&.mage-hand::before { content : '\E999'; }
&.magic-missile::before { content : '\E99A'; }
&.mass-cure-wounds::before { content : '\E99B'; }
&.mass-healing-word::before { content : '\E99C'; }
&.Mending::before { content : '\E99D'; }
&.message::before { content : '\E99E'; }
&.Minor-illusion::before { content : '\E99F'; }
&.movement1::before { content : '\E9A0'; }
&.polymorph::before { content : '\E9A1'; }
&.power-word-kill::before { content : '\E9A2'; }
&.power-word-stun::before { content : '\E9A3'; }
&.prayer-of-healing::before { content : '\E9A4'; }
&.prestidigitation::before { content : '\E9A5'; }
&.protection-from-evil-and-good::before { content : '\E9A6'; }
&.raise-dead::before { content : '\E9A7'; }
&.raise-dead2::before { content : '\E9A8'; }
&.reaction1::before { content : '\E9A9'; }
&.resurrection::before { content : '\E9AA'; }
&.resurrection2::before { content : '\E9AB'; }
&.revivify::before { content : '\E9AC'; }
&.revivify2::before { content : '\E9AD'; }
&.sacred-flame::before { content : '\E9AE'; }
&.sanctuary::before { content : '\E9AF'; }
&.scorching-ray::before { content : '\E9B0'; }
&.sending::before { content : '\E9B1'; }
&.shatter::before { content : '\E9B2'; }
&.shield::before { content : '\E9B3'; }
&.silent-image::before { content : '\E9B4'; }
&.sleep::before { content : '\E9B5'; }
&.speak-with-animals::before { content : '\E9B6'; }
&.telekinesis::before { content : '\E9B7'; }
&.true-strike::before { content : '\E9B8'; }
&.vicious-mockery::before { content : '\E9B9'; }
&.wall-of-fire::before { content : '\E9BA'; }
&.wall-of-force::before { content : '\E9BB'; }
&.wall-of-ice::before { content : '\E9BC'; }
&.wall-of-stone::before { content : '\E9BD'; }
&.wall-of-thorns::before { content : '\E9BE'; }
&.wish::before { content : '\E9BF'; }
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
# Game Icons License
The font used in gameIcons.woff / gameIcons.less / gameIcons.js, and usable in the Homebrewery as "gi" icons, are a subset of the Game-Icons.net library of icons.
## The license
Game-Icons has this to say about their license:
> Game-icons.net is an online repository providing heaps of cool game related graphics.
>
> They are provided provided under the terms of the Creative Commons 3.0 BY license.
>
> It means that you can use them freely as long as you credit the original author in your creation(see below). A mention like "Icons made by {author;}. Available on https://game-icons.net" is fine.

View File

@@ -0,0 +1,509 @@
/* eslint-disable max-lines */
// This is a subset of the library of icons at game-icons.net -- the subset is from RPG-Awesome repo
// The entire font can be downloaded as svg from game-icons.net,
// and then loaded through icomoon.io to create webfont from svg,
// and the css font file can be turned into below list using regex
// regex used: \.([^:-]*)-([^:]*)(.*)
// substitution: "$1$2" : "$1-$2",
const gameIcons = {
'gi_zigzag_leaf' : 'gi zigzag-leaf',
'gi_zebra_shield' : 'gi zebra-shield',
'gi_x_mark' : 'gi x-mark',
'gi_wyvern' : 'gi wyvern',
'gi_wrench' : 'gi wrench',
'gi_wooden_sign' : 'gi wooden-sign',
'gi_wolf_howl' : 'gi wolf-howl',
'gi_wolf_head' : 'gi wolf-head',
'gi_wireless_signal' : 'gi wireless-signal',
'gi_wifi' : 'gi wifi',
'gi_water_drop' : 'gi water-drop',
'gi_virgo' : 'gi virgo',
'gi_vine_whip' : 'gi vine-whip',
'gi_vial' : 'gi vial',
'gi_vest' : 'gi vest',
'gi_venomous_snake' : 'gi venomous-snake',
'gi_vase' : 'gi vase',
'gi_unplugged' : 'gi unplugged',
'gi_underhand' : 'gi underhand',
'gi_uncertainty' : 'gi uncertainty',
'gi_two_hearts' : 'gi two-hearts',
'gi_two_dragons' : 'gi two-dragons',
'gi_turd' : 'gi turd',
'gi_trophy' : 'gi trophy',
'gi_triforce' : 'gi triforce',
'gi_trident' : 'gi trident',
'gi_trefoil_lily' : 'gi trefoil-lily',
'gi_trail' : 'gi trail',
'gi_tower' : 'gi tower',
'gi_torch' : 'gi torch',
'gi_tooth' : 'gi tooth',
'gi_tombstone' : 'gi tombstone',
'gi_toast' : 'gi toast',
'gi_tic_tac_toe' : 'gi tic-tac-toe',
'gi_three_keys' : 'gi three-keys',
'gi_thorny_vine' : 'gi thorny-vine',
'gi_thorn_arrow' : 'gi thorn-arrow',
'gi_tesla' : 'gi tesla',
'gi_tentacle' : 'gi tentacle',
'gi_telescope' : 'gi telescope',
'gi_taurus' : 'gi taurus',
'gi_targeted' : 'gi targeted',
'gi_target_laser' : 'gi target-laser',
'gi_target_arrows' : 'gi target-arrows',
'gi_syringe' : 'gi syringe',
'gi_surveillance_camera' : 'gi surveillance-camera',
'gi_supersonic_arrow' : 'gi supersonic-arrow',
'gi_super_mushroom' : 'gi super-mushroom',
'gi_sunbeams' : 'gi sunbeams',
'gi_sun' : 'gi sun',
'gi_sun_symbol' : 'gi sun-symbol',
'gi_suits' : 'gi suits',
'gi_suckered_tentacle' : 'gi suckered-tentacle',
'gi_stopwatch' : 'gi stopwatch',
'gi_sprout' : 'gi sprout',
'gi_sprout_emblem' : 'gi sprout-emblem',
'gi_spray_can' : 'gi spray-can',
'gi_splash' : 'gi splash',
'gi_spiral_shell' : 'gi spiral-shell',
'gi_spinning_sword' : 'gi spinning-sword',
'gi_spiked_tentacle' : 'gi spiked-tentacle',
'gi_spiked_mace' : 'gi spiked-mace',
'gi_spikeball' : 'gi spikeball',
'gi_spider_face' : 'gi spider-face',
'gi_speech_bubbles' : 'gi speech-bubbles',
'gi_speech_bubble' : 'gi speech-bubble',
'gi_spear_head' : 'gi spear-head',
'gi_spawn_node' : 'gi spawn-node',
'gi_spades' : 'gi spades',
'gi_spades_card' : 'gi spades-card',
'gi_soccer_ball' : 'gi soccer-ball',
'gi_snowflake' : 'gi snowflake',
'gi_snorkel' : 'gi snorkel',
'gi_snake' : 'gi snake',
'gi_snail' : 'gi snail',
'gi_small_fire' : 'gi small-fire',
'gi_slash_ring' : 'gi slash-ring',
'gi_skull' : 'gi skull',
'gi_skull_trophy' : 'gi skull-trophy',
'gi_site' : 'gi site',
'gi_sideswipe' : 'gi sideswipe',
'gi_sickle' : 'gi sickle',
'gi_shuriken' : 'gi shuriken',
'gi_shovel' : 'gi shovel',
'gi_shotgun_shell' : 'gi shotgun-shell',
'gi_shot_through_the_heart' : 'gi shot-through-the-heart',
'gi_shoe_prints' : 'gi shoe-prints',
'gi_ship_emblem' : 'gi ship-emblem',
'gi_shield' : 'gi shield',
'gi_sheriff' : 'gi sheriff',
'gi_sheep' : 'gi sheep',
'gi_shark' : 'gi shark',
'gi_seagull' : 'gi seagull',
'gi_sea_serpent' : 'gi sea-serpent',
'gi_scythe' : 'gi scythe',
'gi_scroll_unfurled' : 'gi scroll-unfurled',
'gi_scorpio' : 'gi scorpio',
'gi_save' : 'gi save',
'gi_satellite' : 'gi satellite',
'gi_sapphire' : 'gi sapphire',
'gi_sagittarius' : 'gi sagittarius',
'gi_rune_stone' : 'gi rune-stone',
'gi_rss' : 'gi rss',
'gi_round_shield' : 'gi round-shield',
'gi_round_bottom_flask' : 'gi round-bottom-flask',
'gi_robot_arm' : 'gi robot-arm',
'gi_roast_chicken' : 'gi roast-chicken',
'gi_ringing_bell' : 'gi ringing-bell',
'gi_rifle' : 'gi rifle',
'gi_revolver' : 'gi revolver',
'gi_reverse' : 'gi reverse',
'gi_repair' : 'gi repair',
'gi_relic_blade' : 'gi relic-blade',
'gi_regeneration' : 'gi regeneration',
'gi_recycle' : 'gi recycle',
'gi_reactor' : 'gi reactor',
'gi_raven' : 'gi raven',
'gi_radioactive' : 'gi radioactive',
'gi_radial_balance' : 'gi radial-balance',
'gi_radar_dish' : 'gi radar-dish',
'gi_rabbit' : 'gi rabbit',
'gi_quill_ink' : 'gi quill-ink',
'gi_queen_crown' : 'gi queen-crown',
'gi_pyramids' : 'gi pyramids',
'gi_potion' : 'gi potion',
'gi_poison_cloud' : 'gi poison-cloud',
'gi_podium' : 'gi podium',
'gi_player' : 'gi player',
'gi_player_thunder_struck' : 'gi player-thunder-struck',
'gi_player_teleport' : 'gi player-teleport',
'gi_player_shot' : 'gi player-shot',
'gi_player_pyromaniac' : 'gi player-pyromaniac',
'gi_player_pain' : 'gi player-pain',
'gi_player_lift' : 'gi player-lift',
'gi_player_king' : 'gi player-king',
'gi_player_dodge' : 'gi player-dodge',
'gi_player_despair' : 'gi player-despair',
'gi_plain_dagger' : 'gi plain-dagger',
'gi_pisces' : 'gi pisces',
'gi_ping_pong' : 'gi ping-pong',
'gi_pine_tree' : 'gi pine-tree',
'gi_pills' : 'gi pills',
'gi_pill' : 'gi pill',
'gi_perspective_dice_three' : 'gi perspective-dice-three',
'gi_perspective_dice_six' : 'gi perspective-dice-six',
'gi_perspective_dice_six_two' : 'gi perspective-dice-six-two',
'gi_perspective_dice_random' : 'gi perspective-dice-random',
'gi_perspective_dice_one' : 'gi perspective-dice-one',
'gi_perspective_dice_four' : 'gi perspective-dice-four',
'gi_perspective_dice_five' : 'gi perspective-dice-five',
'gi_pawprint' : 'gi pawprint',
'gi_pawn' : 'gi pawn',
'gi_palm_tree' : 'gi palm-tree',
'gi_overmind' : 'gi overmind',
'gi_overhead' : 'gi overhead',
'gi_ophiuchus' : 'gi ophiuchus',
'gi_on_target' : 'gi on-target',
'gi_omega' : 'gi omega',
'gi_octopus' : 'gi octopus',
'gi_ocean_emblem' : 'gi ocean-emblem',
'gi_ocarina' : 'gi ocarina',
'gi_nuclear' : 'gi nuclear',
'gi_noose' : 'gi noose',
'gi_nodular' : 'gi nodular',
'gi_nails' : 'gi nails',
'gi_musket' : 'gi musket',
'gi_muscle_up' : 'gi muscle-up',
'gi_muscle_fat' : 'gi muscle-fat',
'gi_mp5' : 'gi mp5',
'gi_moon_sun' : 'gi moon-sun',
'gi_montains' : 'gi montains',
'gi_monster_skull' : 'gi monster-skull',
'gi_mirror' : 'gi mirror',
'gi_mining_diamonds' : 'gi mining-diamonds',
'gi_mine_wagon' : 'gi mine-wagon',
'gi_microphone' : 'gi microphone',
'gi_metal_gate' : 'gi metal-gate',
'gi_medical_pack' : 'gi medical-pack',
'gi_meat' : 'gi meat',
'gi_meat_hook' : 'gi meat-hook',
'gi_match' : 'gi match',
'gi_mass_driver' : 'gi mass-driver',
'gi_magnet' : 'gi magnet',
'gi_maggot' : 'gi maggot',
'gi_love_howl' : 'gi love-howl',
'gi_locked_fortress' : 'gi locked-fortress',
'gi_load' : 'gi load',
'gi_lit_candelabra' : 'gi lit-candelabra',
'gi_lion' : 'gi lion',
'gi_lightning' : 'gi lightning',
'gi_lightning_trio' : 'gi lightning-trio',
'gi_lightning_sword' : 'gi lightning-sword',
'gi_lightning_storm' : 'gi lightning-storm',
'gi_lightning_bolt' : 'gi lightning-bolt',
'gi_lighthouse' : 'gi lighthouse',
'gi_light_bulb' : 'gi light-bulb',
'gi_libra' : 'gi libra',
'gi_lever' : 'gi lever',
'gi_level_two' : 'gi level-two',
'gi_level_two_advanced' : 'gi level-two-advanced',
'gi_level_three' : 'gi level-three',
'gi_level_three_advanced' : 'gi level-three-advanced',
'gi_level_four' : 'gi level-four',
'gi_level_four_advanced' : 'gi level-four-advanced',
'gi_leo' : 'gi leo',
'gi_leaf' : 'gi leaf',
'gi_lava' : 'gi lava',
'gi_laser_site' : 'gi laser-site',
'gi_laser_blast' : 'gi laser-blast',
'gi_large_hammer' : 'gi large-hammer',
'gi_lantern_flame' : 'gi lantern-flame',
'gi_kunai' : 'gi kunai',
'gi_knight_helmet' : 'gi knight-helmet',
'gi_knife' : 'gi knife',
'gi_knife_fork' : 'gi knife-fork',
'gi_kitchen_knives' : 'gi kitchen-knives',
'gi_key' : 'gi key',
'gi_key_basic' : 'gi key-basic',
'gi_kettlebell' : 'gi kettlebell',
'gi_kaleidoscope' : 'gi kaleidoscope',
'gi_jigsaw_piece' : 'gi jigsaw-piece',
'gi_jetpack' : 'gi jetpack',
'gi_interdiction' : 'gi interdiction',
'gi_insect_jaws' : 'gi insect-jaws',
'gi_incense' : 'gi incense',
'gi_implosion' : 'gi implosion',
'gi_ice_cube' : 'gi ice-cube',
'gi_hydra' : 'gi hydra',
'gi_hydra_shot' : 'gi hydra-shot',
'gi_hourglass' : 'gi hourglass',
'gi_hot_surface' : 'gi hot-surface',
'gi_hospital_cross' : 'gi hospital-cross',
'gi_horseshoe' : 'gi horseshoe',
'gi_horns' : 'gi horns',
'gi_horn_call' : 'gi horn-call',
'gi_hood' : 'gi hood',
'gi_honeycomb' : 'gi honeycomb',
'gi_hole_ladder' : 'gi hole-ladder',
'gi_hive_emblem' : 'gi hive-emblem',
'gi_help' : 'gi help',
'gi_helmet' : 'gi helmet',
'gi_heavy_shield' : 'gi heavy-shield',
'gi_heavy_fall' : 'gi heavy-fall',
'gi_heat_haze' : 'gi heat-haze',
'gi_hearts' : 'gi hearts',
'gi_hearts_card' : 'gi hearts-card',
'gi_heartburn' : 'gi heartburn',
'gi_heart_tower' : 'gi heart-tower',
'gi_heart_bottle' : 'gi heart-bottle',
'gi_health' : 'gi health',
'gi_health_increase' : 'gi health-increase',
'gi_health_decrease' : 'gi health-decrease',
'gi_harpoon_trident' : 'gi harpoon-trident',
'gi_hand' : 'gi hand',
'gi_hand_saw' : 'gi hand-saw',
'gi_hand_emblem' : 'gi hand-emblem',
'gi_hammer' : 'gi hammer',
'gi_hammer_drop' : 'gi hammer-drop',
'gi_halberd' : 'gi halberd',
'gi_guillotine' : 'gi guillotine',
'gi_guarded_tower' : 'gi guarded-tower',
'gi_groundbreaker' : 'gi groundbreaker',
'gi_grenade' : 'gi grenade',
'gi_grass' : 'gi grass',
'gi_grass_patch' : 'gi grass-patch',
'gi_grappling_hook' : 'gi grappling-hook',
'gi_gold_bar' : 'gi gold-bar',
'gi_gloop' : 'gi gloop',
'gi_glass_heart' : 'gi glass-heart',
'gi_gemini' : 'gi gemini',
'gi_gem' : 'gi gem',
'gi_gem_pendant' : 'gi gem-pendant',
'gi_gecko' : 'gi gecko',
'gi_gears' : 'gi gears',
'gi_gear_heart' : 'gi gear-heart',
'gi_gear_hammer' : 'gi gear-hammer',
'gi_gavel' : 'gi gavel',
'gi_gamepad_cross' : 'gi gamepad-cross',
'gi_frozen_arrow' : 'gi frozen-arrow',
'gi_frostfire' : 'gi frostfire',
'gi_frost_emblem' : 'gi frost-emblem',
'gi_fox' : 'gi fox',
'gi_forward' : 'gi forward',
'gi_forging' : 'gi forging',
'gi_footprint' : 'gi footprint',
'gi_food_chain' : 'gi food-chain',
'gi_focused_lightning' : 'gi focused-lightning',
'gi_fluffy_swirl' : 'gi fluffy-swirl',
'gi_flowers' : 'gi flowers',
'gi_flower' : 'gi flower',
'gi_flat_hammer' : 'gi flat-hammer',
'gi_flask' : 'gi flask',
'gi_flaming_trident' : 'gi flaming-trident',
'gi_flaming_claw' : 'gi flaming-claw',
'gi_flaming_arrow' : 'gi flaming-arrow',
'gi_flame_symbol' : 'gi flame-symbol',
'gi_fizzing_flask' : 'gi fizzing-flask',
'gi_fish' : 'gi fish',
'gi_fireball_sword' : 'gi fireball-sword',
'gi_fire' : 'gi fire',
'gi_fire_symbol' : 'gi fire-symbol',
'gi_fire_shield' : 'gi fire-shield',
'gi_fire_ring' : 'gi fire-ring',
'gi_fire_breath' : 'gi fire-breath',
'gi_fire_bomb' : 'gi fire-bomb',
'gi_fedora' : 'gi fedora',
'gi_feathered_wing' : 'gi feathered-wing',
'gi_feather_wing' : 'gi feather-wing',
'gi_fast_ship' : 'gi fast-ship',
'gi_falling' : 'gi falling',
'gi_fall_down' : 'gi fall-down',
'gi_fairy' : 'gi fairy',
'gi_fairy_wand' : 'gi fairy-wand',
'gi_eyeball' : 'gi eyeball',
'gi_eye_shield' : 'gi eye-shield',
'gi_eye_monster' : 'gi eye-monster',
'gi_explosive_materials' : 'gi explosive-materials',
'gi_explosion' : 'gi explosion',
'gi_energise' : 'gi energise',
'gi_emerald' : 'gi emerald',
'gi_eggplant' : 'gi eggplant',
'gi_egg' : 'gi egg',
'gi_egg_pod' : 'gi egg-pod',
'gi_duel' : 'gi duel',
'gi_droplets' : 'gi droplets',
'gi_droplet' : 'gi droplet',
'gi_droplet_splash' : 'gi droplet-splash',
'gi_dripping_sword' : 'gi dripping-sword',
'gi_dripping_knife' : 'gi dripping-knife',
'gi_dripping_blade' : 'gi dripping-blade',
'gi_drill' : 'gi drill',
'gi_dragonfly' : 'gi dragonfly',
'gi_dragon' : 'gi dragon',
'gi_dragon_wing' : 'gi dragon-wing',
'gi_dragon_breath' : 'gi dragon-breath',
'gi_doubled' : 'gi doubled',
'gi_double_team' : 'gi double-team',
'gi_diving_dagger' : 'gi diving-dagger',
'gi_divert' : 'gi divert',
'gi_dinosaur' : 'gi dinosaur',
'gi_dice_two' : 'gi dice-two',
'gi_dice_three' : 'gi dice-three',
'gi_dice_six' : 'gi dice-six',
'gi_dice_one' : 'gi dice-one',
'gi_dice_four' : 'gi dice-four',
'gi_dice_five' : 'gi dice-five',
'gi_diamonds' : 'gi diamonds',
'gi_diamonds_card' : 'gi diamonds-card',
'gi_diamond' : 'gi diamond',
'gi_desert_skull' : 'gi desert-skull',
'gi_dervish_swords' : 'gi dervish-swords',
'gi_demolish' : 'gi demolish',
'gi_defibrillate' : 'gi defibrillate',
'gi_decapitation' : 'gi decapitation',
'gi_death_skull' : 'gi death-skull',
'gi_dead_tree' : 'gi dead-tree',
'gi_daisy' : 'gi daisy',
'gi_daggers' : 'gi daggers',
'gi_cycle' : 'gi cycle',
'gi_cut_palm' : 'gi cut-palm',
'gi_cubes' : 'gi cubes',
'gi_crystals' : 'gi crystals',
'gi_crystal_wand' : 'gi crystal-wand',
'gi_crystal_cluster' : 'gi crystal-cluster',
'gi_crystal_ball' : 'gi crystal-ball',
'gi_crush' : 'gi crush',
'gi_crowned_heart' : 'gi crowned-heart',
'gi_crown' : 'gi crown',
'gi_crown_of_thorns' : 'gi crown-of-thorns',
'gi_crossed_swords' : 'gi crossed-swords',
'gi_crossed_sabres' : 'gi crossed-sabres',
'gi_crossed_pistols' : 'gi crossed-pistols',
'gi_crossed_bones' : 'gi crossed-bones',
'gi_crossed_axes' : 'gi crossed-axes',
'gi_crossbow' : 'gi crossbow',
'gi_croc_sword' : 'gi croc-sword',
'gi_cracked_shield' : 'gi cracked-shield',
'gi_cracked_helm' : 'gi cracked-helm',
'gi_crab_claw' : 'gi crab-claw',
'gi_corked_tube' : 'gi corked-tube',
'gi_compass' : 'gi compass',
'gi_cold_heart' : 'gi cold-heart',
'gi_cog' : 'gi cog',
'gi_cog_wheel' : 'gi cog-wheel',
'gi_coffee_mug' : 'gi coffee-mug',
'gi_cluster_bomb' : 'gi cluster-bomb',
'gi_clovers' : 'gi clovers',
'gi_clovers_card' : 'gi clovers-card',
'gi_clover' : 'gi clover',
'gi_clockwork' : 'gi clockwork',
'gi_cloak_and_dagger' : 'gi cloak-and-dagger',
'gi_circular_shield' : 'gi circular-shield',
'gi_circular_saw' : 'gi circular-saw',
'gi_circle_of_circles' : 'gi circle-of-circles',
'gi_chicken_leg' : 'gi chicken-leg',
'gi_chessboard' : 'gi chessboard',
'gi_chemical_arrow' : 'gi chemical-arrow',
'gi_cheese' : 'gi cheese',
'gi_chain' : 'gi chain',
'gi_cat' : 'gi cat',
'gi_castle_flag' : 'gi castle-flag',
'gi_castle_emblem' : 'gi castle-emblem',
'gi_carrot' : 'gi carrot',
'gi_capricorn' : 'gi capricorn',
'gi_capitol' : 'gi capitol',
'gi_cannon_shot' : 'gi cannon-shot',
'gi_candle' : 'gi candle',
'gi_candle_fire' : 'gi candle-fire',
'gi_cancer' : 'gi cancer',
'gi_cancel' : 'gi cancel',
'gi_campfire' : 'gi campfire',
'gi_butterfly' : 'gi butterfly',
'gi_burst_blob' : 'gi burst-blob',
'gi_burning_meteor' : 'gi burning-meteor',
'gi_burning_eye' : 'gi burning-eye',
'gi_burning_embers' : 'gi burning-embers',
'gi_burning_book' : 'gi burning-book',
'gi_bullets' : 'gi bullets',
'gi_bubbling_potion' : 'gi bubbling-potion',
'gi_broken_skull' : 'gi broken-skull',
'gi_broken_shield' : 'gi broken-shield',
'gi_broken_heart' : 'gi broken-heart',
'gi_broken_bottle' : 'gi broken-bottle',
'gi_broken_bone' : 'gi broken-bone',
'gi_broadsword' : 'gi broadsword',
'gi_broadhead_arrow' : 'gi broadhead-arrow',
'gi_bridge' : 'gi bridge',
'gi_brandy_bottle' : 'gi brandy-bottle',
'gi_brain_freeze' : 'gi brain-freeze',
'gi_bowling_pin' : 'gi bowling-pin',
'gi_bowie_knife' : 'gi bowie-knife',
'gi_bottom_right' : 'gi bottom-right',
'gi_bottled_bolt' : 'gi bottled-bolt',
'gi_bottle_vapors' : 'gi bottle-vapors',
'gi_boot_stomp' : 'gi boot-stomp',
'gi_boomerang' : 'gi boomerang',
'gi_book' : 'gi book',
'gi_bone_knife' : 'gi bone-knife',
'gi_bone_bite' : 'gi bone-bite',
'gi_bombs' : 'gi bombs',
'gi_bomb_explosion' : 'gi bomb-explosion',
'gi_bolt_shield' : 'gi bolt-shield',
'gi_bleeding_hearts' : 'gi bleeding-hearts',
'gi_bleeding_eye' : 'gi bleeding-eye',
'gi_blaster' : 'gi blaster',
'gi_blast' : 'gi blast',
'gi_blade_bite' : 'gi blade-bite',
'gi_bird_mask' : 'gi bird-mask',
'gi_bird_claw' : 'gi bird-claw',
'gi_biohazard' : 'gi biohazard',
'gi_bell' : 'gi bell',
'gi_beetle' : 'gi beetle',
'gi_beer' : 'gi beer',
'gi_bear_trap' : 'gi bear-trap',
'gi_beam_wake' : 'gi beam-wake',
'gi_batwings' : 'gi batwings',
'gi_battery_white' : 'gi battery-white',
'gi_battery_positive' : 'gi battery-positive',
'gi_battery_negative' : 'gi battery-negative',
'gi_battery_black' : 'gi battery-black',
'gi_battery_75' : 'gi battery-75',
'gi_battery_50' : 'gi battery-50',
'gi_battery_25' : 'gi battery-25',
'gi_battery_100' : 'gi battery-100',
'gi_battery_0' : 'gi battery-0',
'gi_batteries' : 'gi batteries',
'gi_battered_axe' : 'gi battered-axe',
'gi_bat_sword' : 'gi bat-sword',
'gi_barrier' : 'gi barrier',
'gi_barbed_arrow' : 'gi barbed-arrow',
'gi_ball' : 'gi ball',
'gi_axe' : 'gi axe',
'gi_axe_swing' : 'gi axe-swing',
'gi_aware' : 'gi aware',
'gi_aura' : 'gi aura',
'gi_arson' : 'gi arson',
'gi_arrow_flights' : 'gi arrow-flights',
'gi_arrow_cluster' : 'gi arrow-cluster',
'gi_aries' : 'gi aries',
'gi_arena' : 'gi arena',
'gi_archery_target' : 'gi archery-target',
'gi_archer' : 'gi archer',
'gi_arcane_mask' : 'gi arcane-mask',
'gi_aquarius' : 'gi aquarius',
'gi_apple' : 'gi apple',
'gi_anvil' : 'gi anvil',
'gi_ankh' : 'gi ankh',
'gi_angel_wings' : 'gi angel-wings',
'gi_anchor' : 'gi anchor',
'gi_ammo_bag' : 'gi ammo-bag',
'gi_alligator_clip' : 'gi alligator-clip',
'gi_all_for_one' : 'gi all-for-one',
'gi_alien_fire' : 'gi alien-fire',
'gi_acorn' : 'gi acorn',
'gi_acid' : 'gi acid'
};
module.exports = gameIcons;

View File

@@ -0,0 +1,520 @@
@font-face {
font-family : 'Game-Icons';
font-style : normal;
font-weight : normal;
src : url('../../../fonts/iconFonts/gameIcons.woff') format('woff');
font-display : block;
}
.gi {
/* use !important to prevent issues with browser extensions that change fonts */
display : inline-block;
margin-right : 3px;
font-family : 'Game-Icons' !important;
line-height : 1;
vertical-align : baseline;
-moz-osx-font-smoothing : grayscale;
-webkit-font-smoothing : antialiased;
text-rendering : auto;
/* Better Font Rendering =========== */
-webkit-font-smoothing : antialiased;
-moz-osx-font-smoothing : grayscale;
&.zigzag-leaf::before { content : '\e900'; }
&.zebra-shield::before { content : '\e901'; }
&.x-mark::before { content : '\e902'; }
&.wyvern::before { content : '\e903'; }
&.wrench::before { content : '\e904'; }
&.wooden-sign::before { content : '\e905'; }
&.wolf-howl::before { content : '\e906'; }
&.wolf-head::before { content : '\e907'; }
&.wireless-signal::before { content : '\e908'; }
&.wifi::before { content : '\e909'; }
&.water-drop::before { content : '\e90a'; }
&.virgo::before { content : '\e90b'; }
&.vine-whip::before { content : '\e90c'; }
&.vial::before { content : '\e90d'; }
&.vest::before { content : '\e90e'; }
&.venomous-snake::before { content : '\e90f'; }
&.vase::before { content : '\e910'; }
&.unplugged::before { content : '\e911'; }
&.underhand::before { content : '\e912'; }
&.uncertainty::before { content : '\e913'; }
&.two-hearts::before { content : '\e914'; }
&.two-dragons::before { content : '\e915'; }
&.turd::before { content : '\e916'; }
&.trophy::before { content : '\e917'; }
&.triforce::before { content : '\e918'; }
&.trident::before { content : '\e919'; }
&.trefoil-lily::before { content : '\e91a'; }
&.trail::before { content : '\e91b'; }
&.tower::before { content : '\e91c'; }
&.torch::before { content : '\e91d'; }
&.tooth::before { content : '\e91e'; }
&.tombstone::before { content : '\e91f'; }
&.toast::before { content : '\e920'; }
&.tic-tac-toe::before { content : '\e921'; }
&.three-keys::before { content : '\e922'; }
&.thorny-vine::before { content : '\e923'; }
&.thorn-arrow::before { content : '\e924'; }
&.tesla::before { content : '\e925'; }
&.tentacle::before { content : '\e926'; }
&.telescope::before { content : '\e927'; }
&.taurus::before { content : '\e928'; }
&.targeted::before { content : '\e929'; }
&.target-laser::before { content : '\e92a'; }
&.target-arrows::before { content : '\e92b'; }
&.syringe::before { content : '\e92c'; }
&.surveillance-camera::before { content : '\e92d'; }
&.supersonic-arrow::before { content : '\e92e'; }
&.super-mushroom::before { content : '\e92f'; }
&.sunbeams::before { content : '\e930'; }
&.sun::before { content : '\e931'; }
&.sun-symbol::before { content : '\e932'; }
&.suits::before { content : '\e933'; }
&.suckered-tentacle::before { content : '\e934'; }
&.stopwatch::before { content : '\e935'; }
&.sprout::before { content : '\e936'; }
&.sprout-emblem::before { content : '\e937'; }
&.spray-can::before { content : '\e938'; }
&.splash::before { content : '\e939'; }
&.spiral-shell::before { content : '\e93a'; }
&.spinning-sword::before { content : '\e93b'; }
&.spiked-tentacle::before { content : '\e93c'; }
&.spiked-mace::before { content : '\e93d'; }
&.spikeball::before { content : '\e93e'; }
&.spider-face::before { content : '\e93f'; }
&.speech-bubbles::before { content : '\e940'; }
&.speech-bubble::before { content : '\e941'; }
&.spear-head::before { content : '\e942'; }
&.spawn-node::before { content : '\e943'; }
&.spades::before { content : '\e944'; }
&.spades-card::before { content : '\e945'; }
&.soccer-ball::before { content : '\e946'; }
&.snowflake::before { content : '\e947'; }
&.snorkel::before { content : '\e948'; }
&.snake::before { content : '\e949'; }
&.snail::before { content : '\e94a'; }
&.small-fire::before { content : '\e94b'; }
&.slash-ring::before { content : '\e94c'; }
&.skull::before { content : '\e94d'; }
&.skull-trophy::before { content : '\e94e'; }
&.site::before { content : '\e94f'; }
&.sideswipe::before { content : '\e950'; }
&.sickle::before { content : '\e951'; }
&.shuriken::before { content : '\e952'; }
&.shovel::before { content : '\e953'; }
&.shotgun-shell::before { content : '\e954'; }
&.shot-through-the-heart::before { content : '\e955'; }
&.shoe-prints::before { content : '\e956'; }
&.ship-emblem::before { content : '\e957'; }
&.shield::before { content : '\e958'; }
&.sheriff::before { content : '\e959'; }
&.sheep::before { content : '\e95a'; }
&.shark::before { content : '\e95b'; }
&.seagull::before { content : '\e95c'; }
&.sea-serpent::before { content : '\e95d'; }
&.scythe::before { content : '\e95e'; }
&.scroll-unfurled::before { content : '\e95f'; }
&.scorpio::before { content : '\e960'; }
&.save::before { content : '\e961'; }
&.satellite::before { content : '\e962'; }
&.sapphire::before { content : '\e963'; }
&.sagittarius::before { content : '\e964'; }
&.rune-stone::before { content : '\e965'; }
&.rss::before { content : '\e966'; }
&.round-shield::before { content : '\e967'; }
&.round-bottom-flask::before { content : '\e968'; }
&.robot-arm::before { content : '\e969'; }
&.roast-chicken::before { content : '\e96a'; }
&.ringing-bell::before { content : '\e96b'; }
&.rifle::before { content : '\e96c'; }
&.revolver::before { content : '\e96d'; }
&.reverse::before { content : '\e96e'; }
&.repair::before { content : '\e96f'; }
&.relic-blade::before { content : '\e970'; }
&.regeneration::before { content : '\e971'; }
&.recycle::before { content : '\e972'; }
&.reactor::before { content : '\e973'; }
&.raven::before { content : '\e974'; }
&.radioactive::before { content : '\e975'; }
&.radial-balance::before { content : '\e976'; }
&.radar-dish::before { content : '\e977'; }
&.rabbit::before { content : '\e978'; }
&.quill-ink::before { content : '\e979'; }
&.queen-crown::before { content : '\e97a'; }
&.pyramids::before { content : '\e97b'; }
&.potion::before { content : '\e97c'; }
&.poison-cloud::before { content : '\e97d'; }
&.podium::before { content : '\e97e'; }
&.player::before { content : '\e97f'; }
&.player-thunder-struck::before { content : '\e980'; }
&.player-teleport::before { content : '\e981'; }
&.player-shot::before { content : '\e982'; }
&.player-pyromaniac::before { content : '\e983'; }
&.player-pain::before { content : '\e984'; }
&.player-lift::before { content : '\e985'; }
&.player-king::before { content : '\e986'; }
&.player-dodge::before { content : '\e987'; }
&.player-despair::before { content : '\e988'; }
&.plain-dagger::before { content : '\e989'; }
&.pisces::before { content : '\e98a'; }
&.ping-pong::before { content : '\e98b'; }
&.pine-tree::before { content : '\e98c'; }
&.pills::before { content : '\e98d'; }
&.pill::before { content : '\e98e'; }
&.perspective-dice-three::before { content : '\e98f'; }
&.perspective-dice-six::before { content : '\e990'; }
&.perspective-dice-six-two::before { content : '\e991'; }
&.perspective-dice-random::before { content : '\e992'; }
&.perspective-dice-one::before { content : '\e993'; }
&.perspective-dice-four::before { content : '\e994'; }
&.perspective-dice-five::before { content : '\e995'; }
&.pawprint::before { content : '\e996'; }
&.pawn::before { content : '\e997'; }
&.palm-tree::before { content : '\e998'; }
&.overmind::before { content : '\e999'; }
&.overhead::before { content : '\e99a'; }
&.ophiuchus::before { content : '\e99b'; }
&.on-target::before { content : '\e99c'; }
&.omega::before { content : '\e99d'; }
&.octopus::before { content : '\e99e'; }
&.ocean-emblem::before { content : '\e99f'; }
&.ocarina::before { content : '\e9a0'; }
&.nuclear::before { content : '\e9a1'; }
&.noose::before { content : '\e9a2'; }
&.nodular::before { content : '\e9a3'; }
&.nails::before { content : '\e9a4'; }
&.musket::before { content : '\e9a5'; }
&.muscle-up::before { content : '\e9a6'; }
&.muscle-fat::before { content : '\e9a7'; }
&.mp5::before { content : '\e9a8'; }
&.moon-sun::before { content : '\e9a9'; }
&.montains::before { content : '\e9aa'; }
&.monster-skull::before { content : '\e9ab'; }
&.mirror::before { content : '\e9ac'; }
&.mining-diamonds::before { content : '\e9ad'; }
&.mine-wagon::before { content : '\e9ae'; }
&.microphone::before { content : '\e9af'; }
&.metal-gate::before { content : '\e9b0'; }
&.medical-pack::before { content : '\e9b1'; }
&.meat::before { content : '\e9b2'; }
&.meat-hook::before { content : '\e9b3'; }
&.match::before { content : '\e9b4'; }
&.mass-driver::before { content : '\e9b5'; }
&.magnet::before { content : '\e9b6'; }
&.maggot::before { content : '\e9b7'; }
&.love-howl::before { content : '\e9b8'; }
&.locked-fortress::before { content : '\e9b9'; }
&.load::before { content : '\e9ba'; }
&.lit-candelabra::before { content : '\e9bb'; }
&.lion::before { content : '\e9bc'; }
&.lightning::before { content : '\e9bd'; }
&.lightning-trio::before { content : '\e9be'; }
&.lightning-sword::before { content : '\e9bf'; }
&.lightning-storm::before { content : '\e9c0'; }
&.lightning-bolt::before { content : '\e9c1'; }
&.lighthouse::before { content : '\e9c2'; }
&.light-bulb::before { content : '\e9c3'; }
&.libra::before { content : '\e9c4'; }
&.lever::before { content : '\e9c5'; }
&.level-two::before { content : '\e9c6'; }
&.level-two-advanced::before { content : '\e9c7'; }
&.level-three::before { content : '\e9c8'; }
&.level-three-advanced::before { content : '\e9c9'; }
&.level-four::before { content : '\e9ca'; }
&.level-four-advanced::before { content : '\e9cb'; }
&.leo::before { content : '\e9cc'; }
&.leaf::before { content : '\e9cd'; }
&.lava::before { content : '\e9ce'; }
&.laser-site::before { content : '\e9cf'; }
&.laser-blast::before { content : '\e9d0'; }
&.large-hammer::before { content : '\e9d1'; }
&.lantern-flame::before { content : '\e9d2'; }
&.kunai::before { content : '\e9d3'; }
&.knight-helmet::before { content : '\e9d4'; }
&.knife::before { content : '\e9d5'; }
&.knife-fork::before { content : '\e9d6'; }
&.kitchen-knives::before { content : '\e9d7'; }
&.key::before { content : '\e9d8'; }
&.key-basic::before { content : '\e9d9'; }
&.kettlebell::before { content : '\e9da'; }
&.kaleidoscope::before { content : '\e9db'; }
&.jigsaw-piece::before { content : '\e9dc'; }
&.jetpack::before { content : '\e9dd'; }
&.interdiction::before { content : '\e9de'; }
&.insect-jaws::before { content : '\e9df'; }
&.incense::before { content : '\e9e0'; }
&.implosion::before { content : '\e9e1'; }
&.ice-cube::before { content : '\e9e2'; }
&.hydra::before { content : '\e9e3'; }
&.hydra-shot::before { content : '\e9e4'; }
&.hourglass::before { content : '\e9e5'; }
&.hot-surface::before { content : '\e9e6'; }
&.hospital-cross::before { content : '\e9e7'; }
&.horseshoe::before { content : '\e9e8'; }
&.horns::before { content : '\e9e9'; }
&.horn-call::before { content : '\e9ea'; }
&.hood::before { content : '\e9eb'; }
&.honeycomb::before { content : '\e9ec'; }
&.hole-ladder::before { content : '\e9ed'; }
&.hive-emblem::before { content : '\e9ee'; }
&.help::before { content : '\e9ef'; }
&.helmet::before { content : '\e9f0'; }
&.heavy-shield::before { content : '\e9f1'; }
&.heavy-fall::before { content : '\e9f2'; }
&.heat-haze::before { content : '\e9f3'; }
&.hearts::before { content : '\e9f4'; }
&.hearts-card::before { content : '\e9f5'; }
&.heartburn::before { content : '\e9f6'; }
&.heart-tower::before { content : '\e9f7'; }
&.heart-bottle::before { content : '\e9f8'; }
&.health::before { content : '\e9f9'; }
&.health-increase::before { content : '\e9fa'; }
&.health-decrease::before { content : '\e9fb'; }
&.harpoon-trident::before { content : '\e9fc'; }
&.hand::before { content : '\e9fd'; }
&.hand-saw::before { content : '\e9fe'; }
&.hand-emblem::before { content : '\e9ff'; }
&.hammer::before { content : '\ea00'; }
&.hammer-drop::before { content : '\ea01'; }
&.halberd::before { content : '\ea02'; }
&.guillotine::before { content : '\ea03'; }
&.guarded-tower::before { content : '\ea04'; }
&.groundbreaker::before { content : '\ea05'; }
&.grenade::before { content : '\ea06'; }
&.grass::before { content : '\ea07'; }
&.grass-patch::before { content : '\ea08'; }
&.grappling-hook::before { content : '\ea09'; }
&.gold-bar::before { content : '\ea0a'; }
&.gloop::before { content : '\ea0b'; }
&.glass-heart::before { content : '\ea0c'; }
&.gemini::before { content : '\ea0d'; }
&.gem::before { content : '\ea0e'; }
&.gem-pendant::before { content : '\ea0f'; }
&.gecko::before { content : '\ea10'; }
&.gears::before { content : '\ea11'; }
&.gear-heart::before { content : '\ea12'; }
&.gear-hammer::before { content : '\ea13'; }
&.gavel::before { content : '\ea14'; }
&.gamepad-cross::before { content : '\ea15'; }
&.frozen-arrow::before { content : '\ea16'; }
&.frostfire::before { content : '\ea17'; }
&.frost-emblem::before { content : '\ea18'; }
&.fox::before { content : '\ea19'; }
&.forward::before { content : '\ea1a'; }
&.forging::before { content : '\ea1b'; }
&.footprint::before { content : '\ea1c'; }
&.food-chain::before { content : '\ea1d'; }
&.focused-lightning::before { content : '\ea1e'; }
&.fluffy-swirl::before { content : '\ea1f'; }
&.flowers::before { content : '\ea20'; }
&.flower::before { content : '\ea21'; }
&.flat-hammer::before { content : '\ea22'; }
&.flask::before { content : '\ea23'; }
&.flaming-trident::before { content : '\ea24'; }
&.flaming-claw::before { content : '\ea25'; }
&.flaming-arrow::before { content : '\ea26'; }
&.flame-symbol::before { content : '\ea27'; }
&.fizzing-flask::before { content : '\ea28'; }
&.fish::before { content : '\ea29'; }
&.fireball-sword::before { content : '\ea2a'; }
&.fire::before { content : '\ea2b'; }
&.fire-symbol::before { content : '\ea2c'; }
&.fire-shield::before { content : '\ea2d'; }
&.fire-ring::before { content : '\ea2e'; }
&.fire-breath::before { content : '\ea2f'; }
&.fire-bomb::before { content : '\ea30'; }
&.fedora::before { content : '\ea31'; }
&.feathered-wing::before { content : '\ea32'; }
&.feather-wing::before { content : '\ea33'; }
&.fast-ship::before { content : '\ea34'; }
&.falling::before { content : '\ea35'; }
&.fall-down::before { content : '\ea36'; }
&.fairy::before { content : '\ea37'; }
&.fairy-wand::before { content : '\ea38'; }
&.eyeball::before { content : '\ea39'; }
&.eye-shield::before { content : '\ea3a'; }
&.eye-monster::before { content : '\ea3b'; }
&.explosive-materials::before { content : '\ea3c'; }
&.explosion::before { content : '\ea3d'; }
&.energise::before { content : '\ea3e'; }
&.emerald::before { content : '\ea3f'; }
&.eggplant::before { content : '\ea40'; }
&.egg::before { content : '\ea41'; }
&.egg-pod::before { content : '\ea42'; }
&.duel::before { content : '\ea43'; }
&.droplets::before { content : '\ea44'; }
&.droplet::before { content : '\ea45'; }
&.droplet-splash::before { content : '\ea46'; }
&.dripping-sword::before { content : '\ea47'; }
&.dripping-knife::before { content : '\ea48'; }
&.dripping-blade::before { content : '\ea49'; }
&.drill::before { content : '\ea4a'; }
&.dragonfly::before { content : '\ea4b'; }
&.dragon::before { content : '\ea4c'; }
&.dragon-wing::before { content : '\ea4d'; }
&.dragon-breath::before { content : '\ea4e'; }
&.doubled::before { content : '\ea4f'; }
&.double-team::before { content : '\ea50'; }
&.diving-dagger::before { content : '\ea51'; }
&.divert::before { content : '\ea52'; }
&.dinosaur::before { content : '\ea53'; }
&.dice-two::before { content : '\ea54'; }
&.dice-three::before { content : '\ea55'; }
&.dice-six::before { content : '\ea56'; }
&.dice-one::before { content : '\ea57'; }
&.dice-four::before { content : '\ea58'; }
&.dice-five::before { content : '\ea59'; }
&.diamonds::before { content : '\ea5a'; }
&.diamonds-card::before { content : '\ea5b'; }
&.diamond::before { content : '\ea5c'; }
&.desert-skull::before { content : '\ea5d'; }
&.dervish-swords::before { content : '\ea5e'; }
&.demolish::before { content : '\ea5f'; }
&.defibrillate::before { content : '\ea60'; }
&.decapitation::before { content : '\ea61'; }
&.death-skull::before { content : '\ea62'; }
&.dead-tree::before { content : '\ea63'; }
&.daisy::before { content : '\ea64'; }
&.daggers::before { content : '\ea65'; }
&.cycle::before { content : '\ea66'; }
&.cut-palm::before { content : '\ea67'; }
&.cubes::before { content : '\ea68'; }
&.crystals::before { content : '\ea69'; }
&.crystal-wand::before { content : '\ea6a'; }
&.crystal-cluster::before { content : '\ea6b'; }
&.crystal-ball::before { content : '\ea6c'; }
&.crush::before { content : '\ea6d'; }
&.crowned-heart::before { content : '\ea6e'; }
&.crown::before { content : '\ea6f'; }
&.crown-of-thorns::before { content : '\ea70'; }
&.crossed-swords::before { content : '\ea71'; }
&.crossed-sabres::before { content : '\ea72'; }
&.crossed-pistols::before { content : '\ea73'; }
&.crossed-bones::before { content : '\ea74'; }
&.crossed-axes::before { content : '\ea75'; }
&.crossbow::before { content : '\ea76'; }
&.croc-sword::before { content : '\ea77'; }
&.cracked-shield::before { content : '\ea78'; }
&.cracked-helm::before { content : '\ea79'; }
&.crab-claw::before { content : '\ea7a'; }
&.corked-tube::before { content : '\ea7b'; }
&.compass::before { content : '\ea7c'; }
&.cold-heart::before { content : '\ea7d'; }
&.cog::before { content : '\ea7e'; }
&.cog-wheel::before { content : '\ea7f'; }
&.coffee-mug::before { content : '\ea80'; }
&.cluster-bomb::before { content : '\ea81'; }
&.clovers::before { content : '\ea82'; }
&.clovers-card::before { content : '\ea83'; }
&.clover::before { content : '\ea84'; }
&.clockwork::before { content : '\ea85'; }
&.cloak-and-dagger::before { content : '\ea86'; }
&.circular-shield::before { content : '\ea87'; }
&.circular-saw::before { content : '\ea88'; }
&.circle-of-circles::before { content : '\ea89'; }
&.chicken-leg::before { content : '\ea8a'; }
&.chessboard::before { content : '\ea8b'; }
&.chemical-arrow::before { content : '\ea8c'; }
&.cheese::before { content : '\ea8d'; }
&.chain::before { content : '\ea8e'; }
&.cat::before { content : '\ea8f'; }
&.castle-flag::before { content : '\ea90'; }
&.castle-emblem::before { content : '\ea91'; }
&.carrot::before { content : '\ea92'; }
&.capricorn::before { content : '\ea93'; }
&.capitol::before { content : '\ea94'; }
&.cannon-shot::before { content : '\ea95'; }
&.candle::before { content : '\ea96'; }
&.candle-fire::before { content : '\ea97'; }
&.cancer::before { content : '\ea98'; }
&.cancel::before { content : '\ea99'; }
&.campfire::before { content : '\ea9a'; }
&.butterfly::before { content : '\ea9b'; }
&.burst-blob::before { content : '\ea9c'; }
&.burning-meteor::before { content : '\ea9d'; }
&.burning-eye::before { content : '\ea9e'; }
&.burning-embers::before { content : '\ea9f'; }
&.burning-book::before { content : '\eaa0'; }
&.bullets::before { content : '\eaa1'; }
&.bubbling-potion::before { content : '\eaa2'; }
&.broken-skull::before { content : '\eaa3'; }
&.broken-shield::before { content : '\eaa4'; }
&.broken-heart::before { content : '\eaa5'; }
&.broken-bottle::before { content : '\eaa6'; }
&.broken-bone::before { content : '\eaa7'; }
&.broadsword::before { content : '\eaa8'; }
&.broadhead-arrow::before { content : '\eaa9'; }
&.bridge::before { content : '\eaaa'; }
&.brandy-bottle::before { content : '\eaab'; }
&.brain-freeze::before { content : '\eaac'; }
&.bowling-pin::before { content : '\eaad'; }
&.bowie-knife::before { content : '\eaae'; }
&.bottom-right::before { content : '\eaaf'; }
&.bottled-bolt::before { content : '\eab0'; }
&.bottle-vapors::before { content : '\eab1'; }
&.boot-stomp::before { content : '\eab2'; }
&.boomerang::before { content : '\eab3'; }
&.book::before { content : '\eab4'; }
&.bone-knife::before { content : '\eab5'; }
&.bone-bite::before { content : '\eab6'; }
&.bombs::before { content : '\eab7'; }
&.bomb-explosion::before { content : '\eab8'; }
&.bolt-shield::before { content : '\eab9'; }
&.bleeding-hearts::before { content : '\eaba'; }
&.bleeding-eye::before { content : '\eabb'; }
&.blaster::before { content : '\eabc'; }
&.blast::before { content : '\eabd'; }
&.blade-bite::before { content : '\eabe'; }
&.bird-mask::before { content : '\eabf'; }
&.bird-claw::before { content : '\eac0'; }
&.biohazard::before { content : '\eac1'; }
&.bell::before { content : '\eac2'; }
&.beetle::before { content : '\eac3'; }
&.beer::before { content : '\eac4'; }
&.bear-trap::before { content : '\eac5'; }
&.beam-wake::before { content : '\eac6'; }
&.batwings::before { content : '\eac7'; }
&.battery-white::before { content : '\eac8'; }
&.battery-positive::before { content : '\eac9'; }
&.battery-negative::before { content : '\eaca'; }
&.battery-black::before { content : '\eacb'; }
&.battery-75::before { content : '\eacc'; }
&.battery-50::before { content : '\eacd'; }
&.battery-25::before { content : '\eace'; }
&.battery-100::before { content : '\eacf'; }
&.battery-0::before { content : '\ead0'; }
&.batteries::before { content : '\ead1'; }
&.battered-axe::before { content : '\ead2'; }
&.bat-sword::before { content : '\ead3'; }
&.barrier::before { content : '\ead4'; }
&.barbed-arrow::before { content : '\ead5'; }
&.ball::before { content : '\ead6'; }
&.axe::before { content : '\ead7'; }
&.axe-swing::before { content : '\ead8'; }
&.aware::before { content : '\ead9'; }
&.aura::before { content : '\eada'; }
&.arson::before { content : '\eadb'; }
&.arrow-flights::before { content : '\eadc'; }
&.arrow-cluster::before { content : '\eadd'; }
&.aries::before { content : '\eade'; }
&.arena::before { content : '\eadf'; }
&.archery-target::before { content : '\eae0'; }
&.archer::before { content : '\eae1'; }
&.arcane-mask::before { content : '\eae2'; }
&.aquarius::before { content : '\eae3'; }
&.apple::before { content : '\eae4'; }
&.anvil::before { content : '\eae5'; }
&.ankh::before { content : '\eae6'; }
&.angel-wings::before { content : '\eae7'; }
&.anchor::before { content : '\eae8'; }
&.ammo-bag::before { content : '\eae9'; }
&.alligator-clip::before { content : '\eaea'; }
&.all-for-one::before { content : '\eaeb'; }
&.alien-fire::before { content : '\eaec'; }
&.acorn::before { content : '\eaed'; }
&.acid::before { content : '\eaee'; }
}

Binary file not shown.