0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2026-01-24 01:13:15 +00:00

Compare commits

...

742 Commits

Author SHA1 Message Date
Trevor Buckner
9a60fe4129 Update changelog.md 2023-02-28 22:50:02 -05:00
Trevor Buckner
b2f64d1094 Update changelog.md 2023-02-28 22:35:46 -05:00
Trevor Buckner
820582067e Merge branch 'master' into v3.7.0 2023-02-28 22:33:35 -05:00
Trevor Buckner
dae1106e50 Tweak icons 2023-02-28 22:33:15 -05:00
Trevor Buckner
239cc4d99e up version to 3.7.0 2023-02-28 22:25:20 -05:00
Trevor Buckner
48cd8bb6f7 Merge pull request #2694 from MichielDeMey/patch-1
Use secure protocol for Homebrewery mug image
2023-02-28 21:53:22 -05:00
Trevor Buckner
480d7d2b5e Merge pull request #2700 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.8.2
Bump react-router-dom from 6.8.1 to 6.8.2
2023-02-28 16:56:32 -05:00
Trevor Buckner
9ea80c0d31 Merge pull request #2698 from naturalcrit/dependabot/npm_and_yarn/eslint-8.35.0
Bump eslint from 8.34.0 to 8.35.0
2023-02-28 16:56:18 -05:00
Trevor Buckner
bd151efd51 Merge pull request #2705 from naturalcrit/DisableLayersFromCoreCSS
Disable @layers on core CSS due to crashing ios
2023-02-28 16:56:08 -05:00
Trevor Buckner
0ac1d1e87a Disable @layers on core CSS due to crashing ios 2023-02-28 16:54:59 -05:00
Trevor Buckner
a626f394df Merge pull request #2695 from MichielDeMey/patch-2
Fixed typo in Jest's modulePaths
2023-02-28 16:33:46 -05:00
Trevor Buckner
afa3fb434e Merge pull request #2703 from naturalcrit/Mark-snippets-as-experimental
Add "beta" badge on snippets marked "experimetal"
2023-02-28 16:31:39 -05:00
Trevor Buckner
7117d3caed Add "beta" badge on snippets marked "experimetal" 2023-02-28 16:26:23 -05:00
Trevor Buckner
3461c47a63 Merge pull request #2649 from 5e-Cleric/cover-snippet
Cover snippet
2023-02-28 14:08:22 -05:00
Trevor Buckner
4f715a316b Tweak CSS and snippet 2023-02-28 13:17:25 -05:00
Trevor Buckner
7a316060dd Change footnote font 2023-02-28 13:15:30 -05:00
Trevor Buckner
a96f9e2b76 Update Nodesto Font to be slightly more narrow 2023-02-28 13:14:34 -05:00
dependabot[bot]
cc3c429b58 Bump react-router-dom from 6.8.1 to 6.8.2
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.8.1 to 6.8.2.
- [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.8.2/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>
2023-02-28 03:56:52 +00:00
dependabot[bot]
35c257ed50 Bump eslint from 8.34.0 to 8.35.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.34.0 to 8.35.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.34.0...v8.35.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-27 03:57:15 +00:00
Michiel De Mey
8a6cc3c0aa Fixed typo in Jest's modulePaths 2023-02-26 14:24:21 +01:00
Michiel De Mey
9bb628da5a Use secure protocol for Homebrewery mug image
Fixes https://github.com/naturalcrit/homebrewery/issues/2687
2023-02-25 16:30:04 +01:00
Victor Losada Hernandez
5ae61e2c26 reviews plus naturalcrit logo 2023-02-23 23:28:32 +01:00
Trevor Buckner
2e7c8c0cab Remove @layer 2023-02-22 15:34:05 -05:00
Trevor Buckner
ed85e4eb0a Merge branch 'master' into cover-snippet 2023-02-22 15:06:49 -05:00
Trevor Buckner
91a2ce211d Merge branch 'cover-snippet' of https://github.com/5e-Cleric/homebrewery into pr/2649 2023-02-22 15:05:25 -05:00
Trevor Buckner
6e859aec1c Merge branch 'master' into pr/2649 2023-02-22 14:57:34 -05:00
Trevor Buckner
4d7e273f7d Merge pull request #2373 from naturalcrit/WatercolorImageMask
Watercolor image mask
2023-02-22 14:51:48 -05:00
Trevor Buckner
c3d53cfc10 Remove old comments 2023-02-22 14:51:16 -05:00
Trevor Buckner
90d5ac4603 Implement scaling, but not added to snippet 2023-02-22 14:49:11 -05:00
Trevor Buckner
096b3d00fc Fix corner snippet reversed Y position 2023-02-22 14:48:24 -05:00
Trevor Buckner
2a75c702b9 Merge branch 'master' into WatercolorImageMask 2023-02-22 13:06:20 -05:00
Trevor Buckner
c4719f0e0f Merge pull request #2682 from naturalcrit/dependabot/npm_and_yarn/babel/core-7.21.0
Bump @babel/core from 7.20.12 to 7.21.0
2023-02-22 10:04:54 -05:00
Trevor Buckner
fe6223c892 Merge pull request #2685 from naturalcrit/dependabot/npm_and_yarn/body-parser-1.20.2
Bump body-parser from 1.20.1 to 1.20.2
2023-02-22 10:03:27 -05:00
dependabot[bot]
5f01fa1add Bump body-parser from 1.20.1 to 1.20.2
Bumps [body-parser](https://github.com/expressjs/body-parser) from 1.20.1 to 1.20.2.
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.20.1...1.20.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-22 03:16:53 +00:00
Trevor Buckner
66c80c3891 Merge pull request #2684 from naturalcrit/undoLayers
Disable @layers for now
2023-02-21 15:36:39 -05:00
Trevor Buckner
767f03fba0 Disable @layers for now
@Layers have too many conflicts with custom CSS styling. Delay until V4 renderer.
2023-02-21 15:36:01 -05:00
dependabot[bot]
62692552b1 Bump @babel/core from 7.20.12 to 7.21.0
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.20.12 to 7.21.0.
- [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.21.0/packages/babel-core)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-21 14:40:42 +00:00
Trevor Buckner
8b3bef02e8 Merge pull request #2676 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.9.2
Bump mongoose from 6.9.1 to 6.9.2
2023-02-21 09:39:54 -05:00
Trevor Buckner
3a6e4ec385 Merge pull request #2683 from naturalcrit/dependabot/npm_and_yarn/babel/plugin-transform-runtime-7.21.0
Bump @babel/plugin-transform-runtime from 7.19.6 to 7.21.0
2023-02-21 09:39:20 -05:00
dependabot[bot]
d39148116b Bump @babel/plugin-transform-runtime from 7.19.6 to 7.21.0
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.19.6 to 7.21.0.
- [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.21.0/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-21 03:58:12 +00:00
Trevor Buckner
fe5e91c377 Merge pull request #2678 from naturalcrit/v3.6.1
Up version to 3.6.1
2023-02-18 13:57:00 -05:00
Trevor Buckner
512ef78e9e Up version to 3.6.1 2023-02-18 13:56:41 -05:00
Trevor Buckner
4fca81fd3f Merge pull request #2675 from G-Ambatte/fixAuthorDeletion-#2674
Fix author deletion #2674
2023-02-18 13:48:49 -05:00
Trevor Buckner
6a8a2f080c Lint 2023-02-18 13:48:32 -05:00
Trevor Buckner
298a10bc42 Clean up tests 2023-02-18 13:48:02 -05:00
Trevor Buckner
b6a95a2c01 Merge pull request #2677 from naturalcrit/FixDividerBarDots
Override FontAwesome conflict due to @layers
2023-02-18 13:30:32 -05:00
Trevor Buckner
b09a4ea5fa Override FontAwesome conflict due to @layers 2023-02-18 13:30:06 -05:00
G.Ambatte
1fb7fe2487 Add markModified mock function to test spec 2023-02-17 17:43:21 +13:00
G.Ambatte
e751f9a25c Remove mocking function from homebrew.api.js 2023-02-17 17:42:56 +13:00
Trevor Buckner
9e2aec18ad Get Corners fully working with x/y offset and rotate 2023-02-16 23:00:17 -05:00
dependabot[bot]
e8cf3bee34 Bump mongoose from 6.9.1 to 6.9.2
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.9.1 to 6.9.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/6.9.1...6.9.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-17 03:56:57 +00:00
G.Ambatte
41db670e63 Add mock markModified when it does not exist 2023-02-17 16:14:33 +13:00
G.Ambatte
74e14ca72a Restore coverage to .gitignore 2023-02-17 16:05:32 +13:00
G.Ambatte
860070b0c2 Remove coverage folder from .gitignore 2023-02-17 15:48:55 +13:00
G.Ambatte
43d1cb12db Add change log entry for v3.6.1 2023-02-17 11:30:16 +13:00
G.Ambatte
2bab0b50d2 Add coverage folder to gitignore 2023-02-17 11:26:29 +13:00
G.Ambatte
4b98c1ac89 Add markModified to fix authors array in DB 2023-02-17 11:26:11 +13:00
Trevor Buckner
d9f5e9d635 Merge pull request #2673 from naturalcrit/dependabot/npm_and_yarn/jest-29.4.3
Bump jest from 29.4.1 to 29.4.3
2023-02-16 15:19:49 -05:00
Trevor Buckner
1ce3e399a8 Merge pull request #2670 from naturalcrit/dependabot/npm_and_yarn/eslint-8.34.0
Bump eslint from 8.33.0 to 8.34.0
2023-02-16 15:19:26 -05:00
Trevor Buckner
4a12ccf2b6 Merge pull request #2669 from naturalcrit/dependabot/npm_and_yarn/googleapis-111.0.0
Bump googleapis from 110.0.0 to 111.0.0
2023-02-16 15:19:14 -05:00
Trevor Buckner
da83e1a252 Merge pull request #2666 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.8.1
Bump react-router-dom from 6.8.0 to 6.8.1
2023-02-16 15:18:31 -05:00
Trevor Buckner
a971dd4713 Merge pull request #2665 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.9.1
Bump mongoose from 6.9.0 to 6.9.1
2023-02-16 15:18:19 -05:00
dependabot[bot]
0a7e25a749 Bump jest from 29.4.1 to 29.4.3
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.4.1 to 29.4.3.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.4.3/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-16 03:57:59 +00:00
dependabot[bot]
c9ee1bc4b0 Bump eslint from 8.33.0 to 8.34.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.33.0 to 8.34.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.33.0...v8.34.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 03:58:32 +00:00
dependabot[bot]
d5c21c5881 Bump googleapis from 110.0.0 to 111.0.0
Bumps [googleapis](https://github.com/googleapis/google-api-nodejs-client) from 110.0.0 to 111.0.0.
- [Release notes](https://github.com/googleapis/google-api-nodejs-client/releases)
- [Changelog](https://github.com/googleapis/google-api-nodejs-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/google-api-nodejs-client/compare/googleapis-v110.0.0...googleapis-v111.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 03:57:01 +00:00
Victor Losada Hernandez
3d6842bf86 i forgot to change file extensions 2023-02-11 00:48:52 +01:00
Victor Losada Hernandez
e610194ace custom icon and vectorization of assets 2023-02-11 00:38:27 +01:00
Victor Losada Hernandez
3393e72481 Merge upstream into cover-snippet 2023-02-10 23:11:12 +01:00
Trevor Buckner
0355b52021 Custom icons for image masks in general 2023-02-07 15:36:52 -05:00
Trevor Buckner
c430e5a92b lint 2023-02-07 10:37:33 -05:00
Trevor Buckner
2ac09130a6 Remove switch statement 2023-02-07 10:36:51 -05:00
Trevor Buckner
63346cfd7a Add subsnippets for edge masks 2023-02-07 10:31:29 -05:00
Trevor Buckner
2ea639000b Update Corner snippets to use correct corner 2023-02-07 10:21:29 -05:00
Trevor Buckner
051fdbbc60 Fix snippet hover highlight not full button width 2023-02-07 10:20:43 -05:00
Trevor Buckner
d02fcc9252 Update custom position icons 2023-02-07 09:56:03 -05:00
dependabot[bot]
f157b57928 Bump react-router-dom from 6.8.0 to 6.8.1
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.8.0 to 6.8.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.8.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>
2023-02-07 03:01:39 +00:00
dependabot[bot]
e6318fefb6 Bump mongoose from 6.9.0 to 6.9.1
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.9.0 to 6.9.1.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/6.9.0...6.9.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-07 03:00:46 +00:00
Trevor Buckner
33c8291a55 Merge branch 'master' into WatercolorImageMask 2023-02-06 16:25:13 -05:00
Trevor Buckner
270b20aaaf Add position options to corner snippets 2023-02-06 16:25:02 -05:00
Trevor Buckner
7ea3ef8474 Merge pull request #2662 from naturalcrit/CustomSnippetIcons
Custom icons for snippets
2023-02-04 11:10:29 -05:00
Trevor Buckner
a0af588d75 Custom icons 2023-02-04 11:07:04 -05:00
Trevor Buckner
6f70994a77 Merge branch 'master' into WatercolorImageMask 2023-02-02 15:49:32 -05:00
Trevor Buckner
9b06380b9c Merge pull request #2656 from naturalcrit/SubSnippets
Add a side menu for sub-snippets
2023-02-02 15:49:10 -05:00
Trevor Buckner
5e38ff66da Add a side menu for sub-snippets
Subsnippets can be added to snippets as an additional property "subsnippets" which is an array of more snippets.
2023-02-02 15:29:12 -05:00
Trevor Buckner
5eb1d58059 Add rotation to corners snippet 2023-02-02 11:49:25 -05:00
Trevor Buckner
096e281a6c Rework Corner snippet and CSS to allow free rotation 2023-02-02 11:48:30 -05:00
Trevor Buckner
73f141613e Change classname from imageMask to imageMaskEdge 2023-01-31 17:03:12 -05:00
Trevor Buckner
aee240cf9b remove original text background 2023-01-31 16:00:43 -05:00
Trevor Buckner
7af2e8810a Fix snippet more, add link to imgur image 2023-01-31 16:00:31 -05:00
Trevor Buckner
24031fbfa0 Clarify snippet instructions 2023-01-31 13:33:19 -05:00
Trevor Buckner
b93e9ec95e Comment out Corners snippet for later PR 2023-01-31 13:32:10 -05:00
Trevor Buckner
347d132cde Keep fixing merge 2023-01-31 13:24:29 -05:00
Trevor Buckner
98c7ef9d12 Merge branch 'master' into WatercolorImageMask 2023-01-31 13:18:20 -05:00
Trevor Buckner
85b3741df8 Merge pull request #2651 from 5e-Cleric/cloning-fix-2
Thanks @5e-Cleric for this fix!
2023-01-30 17:19:19 -05:00
Trevor Buckner
4260f5197c Update specs to expect a views prop from default brew 2023-01-30 17:15:33 -05:00
Trevor Buckner
f628e1a5ae Use DEFAULT_BREW values instead of setting them here 2023-01-30 17:08:19 -05:00
Trevor Buckner
14bc7e45ab Merge pull request #2619 from 5e-Cleric/readme
Readme update
2023-01-30 14:44:19 -05:00
Trevor Buckner
4668d36a52 typo 2023-01-30 14:40:13 -05:00
Victor Losada Hernandez
91fc8a1a5e Suggested changes 2023-01-30 20:30:43 +01:00
Victor Losada Hernandez
341b53c603 veracruz to Alkalami 2023-01-30 20:27:15 +01:00
Trevor Buckner
6226f3376a Merge pull request #2604 from naturalcrit/CSS-Layers
Try @Layers to not need `.page` in user style
2023-01-30 12:41:36 -05:00
Trevor Buckner
ed8b0c51af Merge pull request #2653 from naturalcrit/dependabot/npm_and_yarn/eslint-plugin-react-7.32.2
Bump eslint-plugin-react from 7.32.1 to 7.32.2
2023-01-30 12:32:41 -05:00
dependabot[bot]
a19b961b0f Bump eslint-plugin-react from 7.32.1 to 7.32.2
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.32.1 to 7.32.2.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.32.1...v7.32.2)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 16:45:54 +00:00
Trevor Buckner
f4326616b4 Merge pull request #2652 from naturalcrit/dependabot/npm_and_yarn/eslint-8.33.0
Bump eslint from 8.32.0 to 8.33.0
2023-01-30 11:44:28 -05:00
dependabot[bot]
e8509dbbed Bump eslint from 8.32.0 to 8.33.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.32.0 to 8.33.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.32.0...v8.33.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 03:00:51 +00:00
Victor Losada Hernandez
541109e7b1 fix created, updated published last viewed 2023-01-28 11:47:26 +01:00
Trevor Buckner
625d3f7034 Add note about why we use !important on user page 2023-01-28 01:13:10 -05:00
Victor Losada Hernandez
78554603e8 coverPage initial draft 2023-01-28 00:43:43 +01:00
Víctor Losada Hernández
1ebbd9c8ce Merge pull request #2 from naturalcrit/master
pull from upstream
2023-01-28 00:38:48 +01:00
Trevor Buckner
5bb61a7c3c Fix userpage 2023-01-27 17:09:52 -05:00
Trevor Buckner
3c551daf16 Fix print page 2023-01-27 15:16:16 -05:00
Trevor Buckner
0bf96cb9e2 Add layers to all current themes 2023-01-27 14:57:20 -05:00
Trevor Buckner
bef4d9f41f Merge branch 'master' into CSS-Layers 2023-01-27 14:48:13 -05:00
Trevor Buckner
9ff0789387 Merge pull request #2622 from 5e-Cleric/previews
Theme previews updated
2023-01-27 14:45:47 -05:00
Trevor Buckner
a457058041 Resize dropdown button 2023-01-27 14:45:31 -05:00
Trevor Buckner
6d40e63e96 Merge branch 'master' into pr/2622 2023-01-27 14:26:05 -05:00
Trevor Buckner
964342a13d Merge pull request #2646 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.8.0
Bump react-router-dom from 6.7.0 to 6.8.0
2023-01-27 14:04:35 -05:00
Trevor Buckner
9067cbdced Merge pull request #2644 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.9.0
Bump mongoose from 6.8.4 to 6.9.0
2023-01-27 14:04:25 -05:00
Trevor Buckner
c9fd2c63af Merge pull request #2647 from naturalcrit/dependabot/npm_and_yarn/jest-29.4.1
Bump jest from 29.4.0 to 29.4.1
2023-01-27 14:04:16 -05:00
Trevor Buckner
ec8126eb8a Merge pull request #2648 from naturalcrit/FixNodestoFont
Update fonts.less path for Nodesto fonts
2023-01-27 14:04:03 -05:00
Trevor Buckner
6aa1920061 Update fonts.less 2023-01-27 14:02:11 -05:00
dependabot[bot]
07325a7550 Bump jest from 29.4.0 to 29.4.1
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.4.0 to 29.4.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.4.1/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-27 03:01:43 +00:00
dependabot[bot]
7fa50099a6 Bump react-router-dom from 6.7.0 to 6.8.0
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.7.0 to 6.8.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.8.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>
2023-01-27 03:00:56 +00:00
dependabot[bot]
12b1c41716 Bump mongoose from 6.8.4 to 6.9.0
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.8.4 to 6.9.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/6.8.4...6.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-26 03:02:15 +00:00
Trevor Buckner
62d193ddd1 Merge pull request #2639 from naturalcrit/dependabot/npm_and_yarn/jest-29.4.0
Bump jest from 29.3.1 to 29.4.0
2023-01-25 11:38:09 -05:00
dependabot[bot]
750c650b69 Bump jest from 29.3.1 to 29.4.0
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.3.1 to 29.4.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.4.0/packages/jest)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-25 03:01:12 +00:00
Trevor Buckner
70219f1bd4 Merge pull request #2628 from naturalcrit/v3.6.0
Update Version to v3.6.0
2023-01-23 16:02:07 -05:00
Trevor Buckner
c8f9e5bcf2 Update Version to v3.6.0 2023-01-23 16:01:32 -05:00
Trevor Buckner
0a9a5909d1 Merge pull request #2589 from jeddai/client-server-version-mismatch-middleware
adjust frontend error handling, add client/server mismatch middleware
2023-01-23 15:40:48 -05:00
Charlie Humphreys
8f75ea4728 fix error issue 2023-01-23 14:22:18 -06:00
Trevor Buckner
91ad46b202 Merge pull request #2627 from naturalcrit/dependabot/npm_and_yarn/cookiejar-2.1.4
Bump cookiejar from 2.1.3 to 2.1.4
2023-01-23 14:59:58 -05:00
Trevor Buckner
752806c0ef Merge pull request #2616 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.7.0
Bump react-router-dom from 6.6.1 to 6.7.0
2023-01-23 14:59:41 -05:00
dependabot[bot]
c39bb67bf3 Bump cookiejar from 2.1.3 to 2.1.4
Bumps [cookiejar](https://github.com/bmeck/node-cookiejar) from 2.1.3 to 2.1.4.
- [Release notes](https://github.com/bmeck/node-cookiejar/releases)
- [Commits](https://github.com/bmeck/node-cookiejar/commits)

---
updated-dependencies:
- dependency-name: cookiejar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-23 19:58:54 +00:00
Trevor Buckner
fe6097e0d9 Merge pull request #2607 from naturalcrit/dependabot/npm_and_yarn/eslint-8.32.0
Bump eslint from 8.31.0 to 8.32.0
2023-01-23 14:58:12 -05:00
Charlie Humphreys
6ddf0bb889 update metadata editor to include error handling 2023-01-23 09:35:19 -06:00
Trevor Buckner
8dcbad97df Merge pull request #2623 from 5e-Cleric/Cloning-views-fix
Cloning views fix
2023-01-23 10:14:23 -05:00
Trevor Buckner
64b3955bc9 Update Dependencies 2023-01-23 10:13:59 -05:00
Victor Losada Hernandez
0f88a13635 Merge branch 'master' of hb into Cloning-views-fix 2023-01-22 22:11:23 +01:00
Victor Losada Hernandez
e8c7d38608 setting view count to 0 2023-01-22 21:57:14 +01:00
Trevor Buckner
6020657529 Ensure getBrew returns an object if undefined 2023-01-22 21:57:14 +01:00
Trevor Buckner
a8c35f3967 Remove extra console log for getGoogleBrew
App.js already logs the thrown error, so we were getting double logs (and Google errors are long....). This should make the logs a bit easier to sift through.
2023-01-22 21:57:13 +01:00
Trevor Buckner
62fa8f511a Only fix stub if we actually found one. 2023-01-22 21:57:13 +01:00
Trevor Buckner
18cf202ac0 If no stub exists, start stub as {}, not undefined
Recent changes to handle bad brew properties (tags as strings, no renderer, etc.) didn't account for the case where an old Google brew is first being stubbed; since no stub exists, there is no object to perform the corrections on, and we crash.
2023-01-22 21:57:13 +01:00
Trevor Buckner
98d9018e13 Fix saving issue when tags do not exist
Rare case where tags don't exist at all; gets confused in the step of converting tag strings to arrays
2023-01-22 21:57:13 +01:00
Trevor Buckner
a9e14f6165 Enable brew version mismatch checking on server
Was commented out previously to allow users time to update client code so the proper error displays
2023-01-22 21:57:13 +01:00
dependabot[bot]
7005e9f760 Bump mongoose from 6.8.2 to 6.8.3
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.8.2 to 6.8.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/6.8.2...6.8.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-22 21:57:13 +01:00
dependabot[bot]
163bc4e0b3 Bump @babel/core from 7.20.7 to 7.20.12
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.20.7 to 7.20.12.
- [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.20.12/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>
2023-01-22 21:57:13 +01:00
dependabot[bot]
3420886192 Bump eslint from 8.31.0 to 8.32.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.31.0 to 8.32.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.31.0...v8.32.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-22 17:31:41 +00:00
Trevor Buckner
1704ef6557 Merge pull request #2610 from naturalcrit/dependabot/npm_and_yarn/eslint-plugin-react-7.32.1
Bump eslint-plugin-react from 7.31.11 to 7.32.1
2023-01-22 12:30:28 -05:00
Trevor Buckner
637b3311d6 Merge pull request #2612 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.8.4
Bump mongoose from 6.8.3 to 6.8.4
2023-01-22 12:30:09 -05:00
Trevor Buckner
4b8c34bcbd Merge pull request #2608 from naturalcrit/dependabot/npm_and_yarn/marked-4.2.12
Bump marked from 4.2.5 to 4.2.12
2023-01-22 12:29:50 -05:00
Victor Losada Hernandez
0c68e5870b admin privileges detail readme 2023-01-22 15:52:28 +01:00
Charlie Humphreys
d5a34eedb9 Merge branch 'master' into client-server-version-mismatch-middleware 2023-01-21 15:00:54 -06:00
Victor Losada Hernandez
d0dc83cf10 preview images updated 2023-01-21 17:15:50 +01:00
Trevor Buckner
c997908a49 Merge pull request #2621 from jeddai/adjust-coverage-thresholds
lower coverage thresholds for api
2023-01-21 11:11:31 -05:00
Victor Losada Hernandez
45c7ac4b85 Themes dropdown previews 2023-01-21 17:11:28 +01:00
Trevor Buckner
128b299f25 Ensure getBrew returns an object if undefined 2023-01-21 17:11:28 +01:00
Trevor Buckner
692daa88fc Remove extra console log for getGoogleBrew
App.js already logs the thrown error, so we were getting double logs (and Google errors are long....). This should make the logs a bit easier to sift through.
2023-01-21 17:11:28 +01:00
Trevor Buckner
bd6eb816f2 Only fix stub if we actually found one. 2023-01-21 17:11:28 +01:00
Trevor Buckner
2050028484 If no stub exists, start stub as {}, not undefined
Recent changes to handle bad brew properties (tags as strings, no renderer, etc.) didn't account for the case where an old Google brew is first being stubbed; since no stub exists, there is no object to perform the corrections on, and we crash.
2023-01-21 17:11:28 +01:00
Trevor Buckner
7e4018351d Fix saving issue when tags do not exist
Rare case where tags don't exist at all; gets confused in the step of converting tag strings to arrays
2023-01-21 17:11:28 +01:00
Trevor Buckner
01b03e8683 Enable brew version mismatch checking on server
Was commented out previously to allow users time to update client code so the proper error displays
2023-01-21 17:11:28 +01:00
dependabot[bot]
3538aa6da0 Bump mongoose from 6.8.2 to 6.8.3
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.8.2 to 6.8.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/6.8.2...6.8.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-21 17:11:28 +01:00
dependabot[bot]
13eb6cac17 Bump @babel/core from 7.20.7 to 7.20.12
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.20.7 to 7.20.12.
- [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.20.12/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>
2023-01-21 17:11:28 +01:00
Charlie Humphreys
bd594fa214 lower coverage thresholds for api 2023-01-21 09:22:58 -06:00
Charlie Humphreys
6bae21a578 Merge branch 'master' into client-server-version-mismatch-middleware 2023-01-21 00:26:18 -06:00
Charlie Humphreys
79db97efdf create error navitem and use it in all necessary use cases 2023-01-21 00:25:35 -06:00
Charlie Humphreys
7755affa1e update based on feedback 2023-01-20 23:07:24 -06:00
Victor Losada Hernandez
6b6e05ca11 Readme update, installation text improved 2023-01-21 00:05:54 +01:00
Trevor Buckner
ea04069fe5 Merge pull request #2618 from naturalcrit/FixGoogleBrewsDuplicatingOnStub
Fix Google Drive brews duplicating
2023-01-20 17:25:47 -05:00
Trevor Buckner
2c3a302c85 Merge branch 'master' into FixGoogleBrewsDuplicatingOnStub 2023-01-20 17:25:07 -05:00
Trevor Buckner
89d9bfe1f1 Merge pull request #2606 from G-Ambatte/addThemesToWatchList-#2605
[LOCAL] Add Themes directory to watch list
2023-01-20 17:21:15 -05:00
Trevor Buckner
c9241e2162 Fix Google Drive brews duplicating 2023-01-20 17:19:02 -05:00
dependabot[bot]
99f7668901 Bump react-router-dom from 6.6.1 to 6.7.0
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.6.1 to 6.7.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.7.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>
2023-01-19 03:01:37 +00:00
dependabot[bot]
187738ee11 Bump mongoose from 6.8.3 to 6.8.4
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.8.3 to 6.8.4.
- [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/6.8.3...6.8.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-18 03:01:47 +00:00
dependabot[bot]
68d3724e50 Bump eslint-plugin-react from 7.31.11 to 7.32.1
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.31.11 to 7.32.1.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.31.11...v7.32.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-17 03:00:45 +00:00
dependabot[bot]
8526faa041 Bump marked from 4.2.5 to 4.2.12
Bumps [marked](https://github.com/markedjs/marked) from 4.2.5 to 4.2.12.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Changelog](https://github.com/markedjs/marked/blob/master/.releaserc.json)
- [Commits](https://github.com/markedjs/marked/compare/v4.2.5...v4.2.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-16 03:01:52 +00:00
G.Ambatte
ac9fbb1f08 Move changes from 3.6.1 to 3.6.0 2023-01-15 18:24:23 +13:00
G.Ambatte
e82da3a6c1 Add buildDev to NPM scripts 2023-01-15 18:19:23 +13:00
G.Ambatte
40e36fd875 Fix minor version number 2023-01-15 17:26:56 +13:00
G.Ambatte
3c86984cf1 Add change to changelog 2023-01-15 14:13:25 +13:00
G.Ambatte
50d172bbd5 Add Themes directory to watch list 2023-01-15 14:11:33 +13:00
Trevor Buckner
a22d59475e Try @Layers to not need .page in user style 2023-01-13 17:08:12 -05:00
Trevor Buckner
da676c6ec1 Ensure getBrew returns an object if undefined 2023-01-12 13:33:55 -05:00
Trevor Buckner
901615d99e Remove extra console log for getGoogleBrew
App.js already logs the thrown error, so we were getting double logs (and Google errors are long....). This should make the logs a bit easier to sift through.
2023-01-10 21:08:21 -05:00
Trevor Buckner
6ed52f37cc Only fix stub if we actually found one. 2023-01-09 17:30:49 -05:00
Trevor Buckner
15e5a31767 If no stub exists, start stub as {}, not undefined
Recent changes to handle bad brew properties (tags as strings, no renderer, etc.) didn't account for the case where an old Google brew is first being stubbed; since no stub exists, there is no object to perform the corrections on, and we crash.
2023-01-09 14:53:35 -05:00
Trevor Buckner
8cbab4d4ce Fix saving issue when tags do not exist
Rare case where tags don't exist at all; gets confused in the step of converting tag strings to arrays
2023-01-09 14:12:57 -05:00
Trevor Buckner
a9c28e84d0 Enable brew version mismatch checking on server
Was commented out previously to allow users time to update client code so the proper error displays
2023-01-09 10:30:07 -05:00
Trevor Buckner
bafabb84b4 Merge pull request #2591 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.8.3
Bump mongoose from 6.8.2 to 6.8.3
2023-01-09 10:26:36 -05:00
dependabot[bot]
f5d592a291 Bump mongoose from 6.8.2 to 6.8.3
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.8.2 to 6.8.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/6.8.2...6.8.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 03:00:50 +00:00
Trevor Buckner
aa23da6ce4 Move curly CSS up so they don't overwrite styles 2023-01-07 00:25:46 -05:00
Charlie Humphreys
385bee964d adjust frontend error handling, add client/server mismatch middleware 2023-01-06 21:29:21 -06:00
Trevor Buckner
18f277182a Merge pull request #2588 from naturalcrit/dependabot/npm_and_yarn/babel/core-7.20.12
Bump @babel/core from 7.20.7 to 7.20.12
2023-01-06 13:08:12 -05:00
Trevor Buckner
344a9d8334 Merge pull request #2548 from jeddai/api-tests
Add api tests
2023-01-06 13:07:54 -05:00
Charlie Humphreys
67a76f9d86 adjust circleci command for API unit tests 2023-01-06 11:53:38 -06:00
Charlie Humphreys
93d6d1ac6a add unit test command 2023-01-06 11:48:00 -06:00
Charlie Humphreys
4b3edf053f add coverage thresholds and coverage command 2023-01-05 23:30:20 -06:00
Charlie Humphreys
0720ac6a15 update changelog 2023-01-05 23:29:58 -06:00
Charlie Humphreys
c0b9cd951e update circleci test config to run test coverage 2023-01-05 23:29:43 -06:00
Charlie Humphreys
a54ebabf53 fix tests after merge from master 2023-01-05 23:10:25 -06:00
Charlie Humphreys
676acb9e5a Merge branch 'master' into api-tests 2023-01-05 23:02:43 -06:00
Charlie Humphreys
387c468d84 add tests for deletion and address PR feedback 2023-01-05 22:56:54 -06:00
dependabot[bot]
64e7fe3422 Bump @babel/core from 7.20.7 to 7.20.12
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.20.7 to 7.20.12.
- [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.20.12/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>
2023-01-05 03:01:25 +00:00
Trevor Buckner
2b1466c51b Merge pull request #2587 from naturalcrit/FixThemesOnPrint
Fix Themes on /print
2023-01-04 21:41:15 -05:00
Trevor Buckner
332bcde4b2 Themes weren't being picked up for rendering 2023-01-04 21:39:51 -05:00
Trevor Buckner
db783179ce Merge pull request #2429 from G-Ambatte/fixThemesDefault
Add default brew on load and before save
2023-01-04 21:36:37 -05:00
Trevor Buckner
c78d687387 Fix all brews being forced to V3 on load 2023-01-04 21:32:16 -05:00
Trevor Buckner
b717059a39 Fix /new storing string "undefined" in Style tab 2023-01-04 20:58:29 -05:00
Trevor Buckner
e02bde5eed Cleanup; added more fields to DEFAULT_BREW 2023-01-04 17:33:23 -05:00
Trevor Buckner
e1765cad41 Merge branch 'fixThemesDefault' of https://github.com/G-Ambatte/homebrewery into pr/2429 2023-01-03 15:13:41 -05:00
Trevor Buckner
6dab5f836e Merge branch 'master' into pr/2429 2023-01-03 15:13:19 -05:00
Charlie Humphreys
e47f81698c Merge branch 'master' into api-tests 2023-01-03 13:47:09 -06:00
Trevor Buckner
2b824839c3 Merge pull request #2581 from naturalcrit/dependabot/npm_and_yarn/eslint-8.31.0
Bump eslint from 8.30.0 to 8.31.0
2023-01-03 14:05:28 -05:00
Trevor Buckner
26f009a295 Merge pull request #2577 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.6.1
Bump react-router-dom from 6.6.0 to 6.6.1
2023-01-03 14:05:18 -05:00
Trevor Buckner
9b4c997b57 Merge pull request #2578 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.8.2
Bump mongoose from 6.8.1 to 6.8.2
2023-01-03 14:05:10 -05:00
Trevor Buckner
39143295b1 Merge pull request #2576 from naturalcrit/dependabot/npm_and_yarn/marked-4.2.5
Bump marked from 4.2.4 to 4.2.5
2023-01-03 14:05:01 -05:00
Trevor Buckner
6eaf2feb40 Log version mismatch errors
To gauge how frequently they are occurring for future update.
2023-01-03 12:47:17 -05:00
Trevor Buckner
4fe0f1a7af Comment out server-side brew version checking
Requires client-side update to apply brew version correctly; temporarily disabling server-side checking for a few days until more users have updated their clients.
2023-01-03 12:38:00 -05:00
Trevor Buckner
7aac377ce8 Merge pull request #2575 from jeddai/google-brew-version-comparison-fix
add check for truthy version, and make sure the version exists when incrementing it
2023-01-03 11:22:37 -05:00
dependabot[bot]
77542c5f06 Bump eslint from 8.30.0 to 8.31.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.30.0 to 8.31.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.30.0...v8.31.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-02 03:01:18 +00:00
dependabot[bot]
3d365339e4 Bump mongoose from 6.8.1 to 6.8.2
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.8.1 to 6.8.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/6.8.1...6.8.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-29 03:01:18 +00:00
dependabot[bot]
66be400f5f Bump react-router-dom from 6.6.0 to 6.6.1
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.6.0 to 6.6.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.6.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>
2022-12-26 03:01:12 +00:00
dependabot[bot]
9880792c4d Bump marked from 4.2.4 to 4.2.5
Bumps [marked](https://github.com/markedjs/marked) from 4.2.4 to 4.2.5.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Changelog](https://github.com/markedjs/marked/blob/master/.releaserc.json)
- [Commits](https://github.com/markedjs/marked/compare/v4.2.4...v4.2.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-26 03:00:50 +00:00
Charlie Humphreys
ca03a473ec add check for truthy version, and make sure the version exists when incrementing it 2022-12-23 14:31:58 -06:00
Trevor Buckner
c364856942 Merge branch 'master' into fixThemesDefault 2022-12-23 13:40:12 -05:00
Trevor Buckner
4e7a96b67c Merge pull request #2571 from naturalcrit/v3.5.0
v3.5.0
2022-12-23 13:25:00 -05:00
Trevor Buckner
39bfc818a6 Merge pull request #2572 from jeddai/new-props-authors-fix
add elvis to fix invited authors editor
2022-12-23 13:24:48 -05:00
Charlie Humphreys
6d9982f735 add elvis to fix invited authors editor 2022-12-23 12:21:15 -06:00
Trevor Buckner
4f6ba7a388 v3.5.0 2022-12-23 12:07:31 -05:00
Trevor Buckner
0274fb214c Merge pull request #2566 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.8.1
Bump mongoose from 6.8.0 to 6.8.1
2022-12-23 01:57:27 -05:00
Trevor Buckner
15519f142d Merge pull request #2569 from naturalcrit/dependabot/npm_and_yarn/googleapis-110.0.0
Bump googleapis from 109.0.1 to 110.0.0
2022-12-23 01:53:09 -05:00
Trevor Buckner
6b258886a4 Merge pull request #2570 from naturalcrit/dependabot/npm_and_yarn/babel/core-7.20.7
Bump @babel/core from 7.20.5 to 7.20.7
2022-12-23 01:52:49 -05:00
Trevor Buckner
d23a88c997 Merge pull request #2568 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.6.0
Bump react-router-dom from 6.4.5 to 6.6.0
2022-12-23 01:52:42 -05:00
Trevor Buckner
096e17ab5a Merge pull request #2564 from naturalcrit/dependabot/npm_and_yarn/eslint-8.30.0
Bump eslint from 8.29.0 to 8.30.0
2022-12-23 01:52:32 -05:00
Charlie Humphreys
da9e20e96f add more tests and merge from main 2022-12-23 00:11:46 -06:00
dependabot[bot]
53d5f9f6e0 Bump @babel/core from 7.20.5 to 7.20.7
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.20.5 to 7.20.7.
- [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.20.7/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>
2022-12-23 03:01:08 +00:00
dependabot[bot]
43b4fe75e2 Bump googleapis from 109.0.1 to 110.0.0
Bumps [googleapis](https://github.com/googleapis/google-api-nodejs-client) from 109.0.1 to 110.0.0.
- [Release notes](https://github.com/googleapis/google-api-nodejs-client/releases)
- [Changelog](https://github.com/googleapis/google-api-nodejs-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/google-api-nodejs-client/compare/googleapis-v109.0.1...googleapis-v110.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-23 03:00:52 +00:00
Charlie Humphreys
925db96b08 Merge branch 'fixThemesDefault' into api-tests 2022-12-22 20:09:49 -06:00
G.Ambatte
efdb8e07b0 Merge branch 'master' into fixThemesDefault 2022-12-23 13:03:31 +13:00
Trevor Buckner
816860dc4f Merge pull request #2561 from jeddai/add-ability-to-invite-authors
Add ability to invite authors + version comparison check
2022-12-22 17:03:31 -05:00
Charlie
314f758d62 Update server/homebrew.api.js
Co-authored-by: Trevor Buckner <calculuschild@gmail.com>
2022-12-22 15:58:33 -06:00
dependabot[bot]
c799aaa7cb Bump react-router-dom from 6.4.5 to 6.6.0
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.4.5 to 6.6.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.6.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>
2022-12-22 03:00:35 +00:00
Charlie Humphreys
2f5bc8db54 remove redundant boolean comparison logic 2022-12-21 16:19:41 -06:00
Charlie Humphreys
7c61a27084 update authorship edit check and error 2022-12-21 15:59:00 -06:00
dependabot[bot]
ad3e83da22 Bump mongoose from 6.8.0 to 6.8.1
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.8.0 to 6.8.1.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/6.8.0...6.8.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-20 03:00:35 +00:00
dependabot[bot]
8888704b58 Bump eslint from 8.29.0 to 8.30.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.29.0 to 8.30.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.29.0...v8.30.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 03:00:45 +00:00
Charlie Humphreys
a3dc5e78fd remove console log 2022-12-14 10:04:43 -06:00
G.Ambatte
32506860dd Add additional fields to default 2022-12-14 21:26:57 +13:00
G.Ambatte
a89b20584f Apply default to EditPage 2022-12-14 21:26:40 +13:00
G.Ambatte
8e42c09721 Apply default to HomePage 2022-12-14 21:26:31 +13:00
G.Ambatte
bb5978dfea Apply default to SharePage 2022-12-14 21:26:20 +13:00
G.Ambatte
0dc491adfc Apply default to NewPage 2022-12-14 21:26:11 +13:00
G.Ambatte
f470a6185a Move default brew to app.js 2022-12-14 19:23:16 +13:00
Charlie Humphreys
e5febc1fef update ui to include invitedAuthors array 2022-12-13 21:06:47 -06:00
Charlie Humphreys
354d01e980 set the version in the ui from the server response on save 2022-12-13 21:05:45 -06:00
Charlie Humphreys
63e043593a add invitedAuthors key and move invited author to authors on save 2022-12-13 21:05:00 -06:00
Charlie Humphreys
770d0c141d add 409 return when server version is greater than updating version
This also moves the version back onto the stub
2022-12-13 21:03:51 -06:00
G.Ambatte
0a885c8581 Merge branch 'master' into fixThemesDefault 2022-12-14 12:30:28 +13:00
G.Ambatte
ec9c704e71 Merge branch 'master' into fixThemesDefault 2022-12-14 11:57:37 +13:00
Trevor Buckner
02c0176070 Merge pull request #2509 from jeddai/disable-changes-from-non-authors
Disable changes from non authors
2022-12-12 12:15:23 -05:00
Charlie Humphreys
f847de852b Merge branch 'master' into disable-changes-from-non-authors 2022-12-12 10:39:08 -06:00
Trevor Buckner
86413b5767 Merge pull request #2560 from naturalcrit/fixGoogleToMongoTransfer
Change findOneAndUpdate to FindOne and Save
2022-12-12 10:22:49 -05:00
Trevor Buckner
747c976a14 typo 2022-12-12 10:19:49 -05:00
Trevor Buckner
326c28a11d Change findOneAndUpdate to FindOne and Save
Setting an object property to `undefined` should tell Mongoose to remove that property (for example, remove the googleId from a brew). That doesn't seem to work with `findOneAndUpdate` however; the `undefined` property remains after the update.

Switching back to `save()` to make this work again.
2022-12-12 09:59:04 -05:00
Trevor Buckner
263471bcbb Fix changelog typo 2022-12-10 18:03:16 -05:00
Trevor Buckner
9478454063 Merge pull request #2558 from naturalcrit/v3.4.2
v3.4.2
2022-12-10 14:18:16 -05:00
Trevor Buckner
a9a9804517 v3.4.2 2022-12-10 14:15:09 -05:00
Trevor Buckner
0bde44ec2f Merge pull request #2470 from jeddai/remove-google-get-during-update
update getBrew usages to not fetch google brew during updates
2022-12-10 13:54:58 -05:00
Trevor Buckner
13ad179a1b Merge pull request #2523 from G-Ambatte/showGoogleAuthStatus-#2520
Add link to instructions to refresh Google creds
2022-12-10 13:34:17 -05:00
Trevor Buckner
b72acd9e59 cleanup 2022-12-10 13:31:57 -05:00
G.Ambatte
d0a1ef9571 Change to aggregate query, rename variables 2022-12-09 18:35:17 +13:00
G.Ambatte
d1f049871f Merge branch 'master' into showGoogleAuthStatus-#2520 2022-12-09 07:56:25 +13:00
Trevor Buckner
070184b309 Merge pull request #2553 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.4.5
Bump react-router-dom from 6.4.4 to 6.4.5
2022-12-07 22:49:39 -05:00
Trevor Buckner
cbb41676e0 Merge pull request #2551 from naturalcrit/dependabot/npm_and_yarn/marked-4.2.4
Bump marked from 4.2.3 to 4.2.4
2022-12-07 22:49:09 -05:00
Trevor Buckner
81130dd514 Merge pull request #2550 from naturalcrit/dependabot/npm_and_yarn/supertest-6.3.3
Bump supertest from 6.3.2 to 6.3.3
2022-12-07 22:48:59 -05:00
dependabot[bot]
61d3edca17 Bump react-router-dom from 6.4.4 to 6.4.5
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.4.4 to 6.4.5.
- [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.4.5/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>
2022-12-08 03:01:48 +00:00
dependabot[bot]
248b56a706 Bump marked from 4.2.3 to 4.2.4
Bumps [marked](https://github.com/markedjs/marked) from 4.2.3 to 4.2.4.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Changelog](https://github.com/markedjs/marked/blob/master/.releaserc.json)
- [Commits](https://github.com/markedjs/marked/compare/v4.2.3...v4.2.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-08 03:01:13 +00:00
dependabot[bot]
90f8d1d6da Bump supertest from 6.3.2 to 6.3.3
Bumps [supertest](https://github.com/visionmedia/supertest) from 6.3.2 to 6.3.3.
- [Release notes](https://github.com/visionmedia/supertest/releases)
- [Commits](https://github.com/visionmedia/supertest/compare/v6.3.2...v6.3.3)

---
updated-dependencies:
- dependency-name: supertest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-08 03:00:58 +00:00
Trevor Buckner
8f08b71475 Merge pull request #2547 from jeddai/tags-validation-fix
Fix tags validation issues
2022-12-07 12:54:22 -05:00
Trevor Buckner
cc6527029c Merge pull request #2546 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.8.0
Bump mongoose from 6.7.5 to 6.8.0
2022-12-07 11:32:27 -05:00
Charlie Humphreys
8a110567fc remove call to persist 2022-12-07 07:32:22 -06:00
Charlie Humphreys
a451e562fb add initial set of tests for api 2022-12-06 00:01:38 -06:00
Charlie Humphreys
4e2f6b1d26 move callIfExists to base file scope 2022-12-05 22:39:38 -06:00
Charlie Humphreys
6b8db74a2b add authors length check and account elvis operator 2022-12-05 22:31:56 -06:00
Charlie Humphreys
4c629772cc add a check for the accessType when editing a document 2022-12-05 22:11:24 -06:00
Charlie Humphreys
208593d203 add callIfExists, which will call a method only if it exists 2022-12-05 22:06:06 -06:00
Charlie Humphreys
99019be152 switch updateOne to findOneAndUpdate and return the saved instead of the brew passed in 2022-12-05 21:00:44 -06:00
dependabot[bot]
fa73e1707d Bump mongoose from 6.7.5 to 6.8.0
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.7.5 to 6.8.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/6.7.5...6.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-06 03:00:40 +00:00
Trevor Buckner
d7de2e3d21 Merge pull request #2545 from naturalcrit/v3.4.1
Up version to v3.4.1
2022-12-05 21:38:11 -05:00
Trevor Buckner
903ff4fd09 Merge pull request #2542 from naturalcrit/dependabot/npm_and_yarn/supertest-6.3.2
Bump supertest from 6.3.1 to 6.3.2
2022-12-05 21:37:55 -05:00
Trevor Buckner
feaabacc94 Merge pull request #2544 from naturalcrit/dependabot/npm_and_yarn/eslint-8.29.0
Bump eslint from 8.28.0 to 8.29.0
2022-12-05 21:37:40 -05:00
Trevor Buckner
a5827f66c9 Up version to v3.4.1 2022-12-05 21:36:01 -05:00
Trevor Buckner
bc0846c190 Merge pull request #2537 from Gazook89/Update-Injector-RegEx
change injector regex to work with safari
2022-12-05 21:18:24 -05:00
Gazook89
ecdcaadfa9 remove | from regexp 2022-12-05 11:25:24 -06:00
dependabot[bot]
db2478f73d Bump eslint from 8.28.0 to 8.29.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.28.0 to 8.29.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.28.0...v8.29.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 03:01:41 +00:00
dependabot[bot]
5d6a7e692f Bump supertest from 6.3.1 to 6.3.2
Bumps [supertest](https://github.com/visionmedia/supertest) from 6.3.1 to 6.3.2.
- [Release notes](https://github.com/visionmedia/supertest/releases)
- [Commits](https://github.com/visionmedia/supertest/compare/v6.3.1...v6.3.2)

---
updated-dependencies:
- dependency-name: supertest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 03:00:45 +00:00
Gazook89
0fbeca1536 Merge branch 'master' into Update-Injector-RegEx 2022-12-04 20:17:46 -06:00
Trevor Buckner
f5e1869a9b Merge pull request #2529 from naturalcrit/dependabot/npm_and_yarn/fs-extra-11.1.0
Bump fs-extra from 10.1.0 to 11.1.0
2022-12-02 21:39:08 -05:00
Trevor Buckner
10c8414ab0 Merge pull request #2536 from Gazook89/Prevent-Crash-with-Non-Latin-Characters
Encode Filename in Content-Disposition header
2022-12-02 21:31:46 -05:00
Trevor Buckner
6832e68ada Merge pull request #2528 from Gazook89/GoogleActions-error
Change error message about googleActions on local startup.
2022-12-02 21:29:39 -05:00
Trevor Buckner
24477327aa message tweaks 2022-12-02 21:28:57 -05:00
dependabot[bot]
52b11d9b38 Bump fs-extra from 10.1.0 to 11.1.0
Bumps [fs-extra](https://github.com/jprichardson/node-fs-extra) from 10.1.0 to 11.1.0.
- [Release notes](https://github.com/jprichardson/node-fs-extra/releases)
- [Changelog](https://github.com/jprichardson/node-fs-extra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jprichardson/node-fs-extra/compare/10.1.0...11.1.0)

---
updated-dependencies:
- dependency-name: fs-extra
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-03 01:58:32 +00:00
Trevor Buckner
c7b239f362 Merge pull request #2539 from naturalcrit/react17
update to react 17
2022-12-02 20:57:17 -05:00
Trevor Buckner
f1b67ad9d6 Update package-lock.json 2022-12-02 20:55:38 -05:00
Trevor Buckner
6279a85d2e Merge branch 'master' into react17 2022-12-02 17:14:45 -05:00
Trevor Buckner
7a4b5cca04 Merge pull request #2538 from naturalcrit/dependabot/npm_and_yarn/decode-uri-component-0.2.2
Bump decode-uri-component from 0.2.0 to 0.2.2
2022-12-02 17:13:55 -05:00
Trevor Buckner
c4eff2478a update dpendencies 2022-12-02 15:31:06 -05:00
Trevor Buckner
15c918b5d4 Merge pull request #2533 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.4.4
Bump react-router-dom from 6.4.3 to 6.4.4
2022-12-02 10:14:23 -05:00
Gazook89
0a5bfe2939 check if keys exist before trying for auth. 2022-12-01 19:51:36 -06:00
dependabot[bot]
05b9bbdf59 Bump decode-uri-component from 0.2.0 to 0.2.2
Bumps [decode-uri-component](https://github.com/SamVerschueren/decode-uri-component) from 0.2.0 to 0.2.2.
- [Release notes](https://github.com/SamVerschueren/decode-uri-component/releases)
- [Commits](https://github.com/SamVerschueren/decode-uri-component/compare/v0.2.0...v0.2.2)

---
updated-dependencies:
- dependency-name: decode-uri-component
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-02 01:23:25 +00:00
Trevor Buckner
b88c89d61b Merge pull request #2535 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.7.5
Bump mongoose from 6.7.4 to 6.7.5
2022-12-01 16:46:00 -05:00
Gazook89
31d58f9075 change regex to work with safari. 2022-12-01 11:55:37 -06:00
Trevor Buckner
743d0fa689 Merge pull request #2527 from Gazook89/OG-Meta-tag-fix
Fix og:image and og:site_name
2022-12-01 12:49:36 -05:00
Gazook89
3b6d3963f1 point to defaultMetatags.image 2022-12-01 11:01:40 -06:00
Gazook89
3a4c2d8f13 change image property to reference default image property
Co-authored-by: Trevor Buckner <calculuschild@gmail.com>
2022-12-01 10:58:27 -06:00
Gazook89
7d86a40261 encode filename string to allow non-latin characters 2022-12-01 10:52:30 -06:00
dependabot[bot]
5527aa7990 Bump mongoose from 6.7.4 to 6.7.5
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.7.4 to 6.7.5.
- [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/6.7.4...6.7.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-01 03:02:05 +00:00
dependabot[bot]
f48484520a Bump react-router-dom from 6.4.3 to 6.4.4
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.4.3 to 6.4.4.
- [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.4.4/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>
2022-12-01 03:00:49 +00:00
Trevor Buckner
5957ddd01c Merge pull request #2526 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.7.4
Bump mongoose from 6.7.3 to 6.7.4
2022-11-30 14:21:53 -05:00
Trevor Buckner
994b1584b7 Merge pull request #2524 from naturalcrit/dependabot/npm_and_yarn/babel/core-7.20.5
Bump @babel/core from 7.20.2 to 7.20.5
2022-11-30 14:21:43 -05:00
Gazook89
9647fbcc74 change default image on a few pages, and default description. 2022-11-29 19:12:54 -06:00
Gazook89
ca6f8d085a changing messaging about googleActions 2022-11-29 12:57:27 -06:00
Gazook89
c2637a7576 fix og:image and og:site_name 2022-11-29 11:27:15 -06:00
dependabot[bot]
4fd1cdd7e8 Bump mongoose from 6.7.3 to 6.7.4
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.7.3 to 6.7.4.
- [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/6.7.3...6.7.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-29 03:01:22 +00:00
dependabot[bot]
ad20ff514a Bump @babel/core from 7.20.2 to 7.20.5
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.20.2 to 7.20.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.20.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>
2022-11-29 03:00:35 +00:00
Trevor Buckner
5cd50f7138 Merge pull request #2522 from G-Ambatte/fixAccountLoginTime-#2521
[AccountPage] Fix last login time
2022-11-28 17:19:31 -05:00
G.Ambatte
89e6bada56 Add link to instructions to refresh Google creds 2022-11-29 10:26:44 +13:00
G.Ambatte
420d703f9d Add updateTokens param to GoogleActions/authCheck 2022-11-29 10:00:23 +13:00
Trevor Buckner
090da33f33 Merge pull request #2519 from naturalcrit/v3.4.0
V3.4.0
2022-11-28 13:43:43 -05:00
Trevor Buckner
134e260d7b Update changelog.md 2022-11-28 13:34:46 -05:00
Trevor Buckner
82c8ca55fc 3.4.0 2022-11-28 12:33:57 -05:00
Trevor Buckner
e92cd3be18 Merge pull request #2517 from G-Ambatte/fixPrintMargins-#2516
Update Style for V3 & Legacy
2022-11-28 11:11:25 -05:00
G.Ambatte
93c2d2d860 Add contain:size to Legacy 2022-11-25 17:53:28 +13:00
G.Ambatte
cd79a38755 Add contain:size to V3 2022-11-25 17:53:17 +13:00
Trevor Buckner
e4a9c73f56 Merge branch 'master' into WatercolorImageMask 2022-11-23 15:51:49 -05:00
Trevor Buckner
84286b7942 Merge pull request #2515 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.7.3
Bump mongoose from 6.7.2 to 6.7.3
2022-11-23 10:52:13 -05:00
dependabot[bot]
a16ca8c897 Bump mongoose from 6.7.2 to 6.7.3
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.7.2 to 6.7.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/6.7.2...6.7.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-23 03:01:09 +00:00
Charlie Humphreys
fec1766e26 switch fetchGoogle to stubOnly 2022-11-21 16:21:36 -06:00
Trevor Buckner
fea07429fe Merge pull request #2514 from naturalcrit/dependabot/npm_and_yarn/eslint-plugin-react-7.31.11
Bump eslint-plugin-react from 7.31.10 to 7.31.11
2022-11-21 12:57:35 -05:00
dependabot[bot]
fa29f2281d Bump eslint-plugin-react from 7.31.10 to 7.31.11
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.31.10 to 7.31.11.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.31.10...v7.31.11)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-21 17:41:10 +00:00
Trevor Buckner
002b88ab83 Merge pull request #2513 from naturalcrit/dependabot/npm_and_yarn/marked-4.2.3
Bump marked from 4.2.2 to 4.2.3
2022-11-21 12:38:37 -05:00
Trevor Buckner
54833f9fc6 Merge pull request #2512 from naturalcrit/dependabot/npm_and_yarn/eslint-8.28.0
Bump eslint from 8.27.0 to 8.28.0
2022-11-21 12:38:26 -05:00
dependabot[bot]
cba9286217 Bump marked from 4.2.2 to 4.2.3
Bumps [marked](https://github.com/markedjs/marked) from 4.2.2 to 4.2.3.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Changelog](https://github.com/markedjs/marked/blob/master/.releaserc.json)
- [Commits](https://github.com/markedjs/marked/compare/v4.2.2...v4.2.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-21 03:01:20 +00:00
dependabot[bot]
9ebbff49fb Bump eslint from 8.27.0 to 8.28.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.27.0 to 8.28.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.27.0...v8.28.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-21 03:01:06 +00:00
Charlie Humphreys
f26e3d6cd1 remove tags from google brew fetch 2022-11-18 17:53:47 -06:00
Trevor Buckner
9ee39a83c1 Merge pull request #2507 from Gazook89/OG-Meta-Tag-default-object
Move common meta tags to default object
2022-11-17 23:01:32 -05:00
Trevor Buckner
c09a4c4374 cleanup 2022-11-17 22:58:46 -05:00
Trevor Buckner
3e44d0ad13 Merge pull request #2488 from Gazook89/Field-Validation-System-2
Field validation system 2
2022-11-17 21:58:54 -05:00
Trevor Buckner
b23a09b1b8 cleanup 2022-11-17 21:58:24 -05:00
Trevor Buckner
421ed8f51d Remove comments 2022-11-17 21:53:46 -05:00
Gazook89
14a057cf55 change account page title to something generic 2022-11-17 11:37:29 -06:00
Charlie Humphreys
2e6fcafc68 Merge branch 'remove-google-get-during-update' into disable-changes-from-non-authors 2022-11-16 23:15:55 -06:00
Charlie Humphreys
13b43e8902 Merge branch 'master' into remove-google-get-during-update 2022-11-16 23:15:11 -06:00
Charlie Humphreys
837708fc0c prevent changes to brews from non-authors 2022-11-16 22:39:06 -06:00
Charlie Humphreys
2e305d5636 remove authorship piece from this PR 2022-11-16 22:37:59 -06:00
Charlie Humphreys
f9711de634 add elvis for the possibility that the save failed 2022-11-16 22:32:50 -06:00
Charlie Humphreys
2c6779bb1c adjust getBrew to check authorship, change update method to not perform a get 2022-11-16 22:28:00 -06:00
Trevor Buckner
ee05392d27 Merge pull request #2503 from Gazook89/Add-syntax-highlighting-for-injections
Add syntax highlighting for injections
2022-11-16 15:43:17 -05:00
Trevor Buckner
1cc84da976 Remove end/start bracket tracking for injectors 2022-11-16 15:42:45 -05:00
Gazook89
5cfdd504c1 Move common meta tags to default object 2022-11-16 12:52:59 -06:00
Gazook89
24debfc75c fix regexp to not include inside of curly spans 2022-11-15 11:09:27 -06:00
Gazook89
ffe6272299 Merge branch 'master' into Add-syntax-highlighting-for-injections 2022-11-15 10:36:06 -06:00
Trevor Buckner
64c3d69641 Merge pull request #2506 from Gazook89/FAQ-in-Navbar
Add link to FAQ in "Need Help" menu
2022-11-15 11:26:23 -05:00
Gazook89
67c19b79e3 Add link to FAQ in "Need Help" menu 2022-11-15 10:21:35 -06:00
Trevor Buckner
ea29106101 Merge pull request #2501 from Gazook89/RegExp-Crash-in-Curly-Syntax
Reg exp crash in curly syntax
2022-11-14 18:57:27 -05:00
Trevor Buckner
8016f82040 Tweak capture group order 2022-11-14 18:56:04 -05:00
Trevor Buckner
7c93e5879c Merge pull request #2442 from Gazook89/Delete-Recent-Items
Add Ability to Remove Brews from Recent Items
2022-11-14 10:01:03 -05:00
Trevor Buckner
dc86f89c4f Add title attribute 2022-11-14 09:58:48 -05:00
Trevor Buckner
d03be052aa Merge pull request #2504 from Gazook89/Remove-Checkboxes-from-GH-Forms
Remove Checkboxes from Github Issue Forms
2022-11-14 00:18:41 -05:00
Gazook89
fef79f4fc3 remove checkboxes 2022-11-13 22:09:50 -06:00
Gazook89
cc58721ccd give span tags to injection syntax for styling 2022-11-13 21:02:45 -06:00
Gazook89
5f2115da0e fix mustacheInjectBlock pattern as well (missed it earlier) 2022-11-13 20:32:01 -06:00
Gazook89
1dd1e677e4 adjust span regexp pattern to capture trailing spaces 2022-11-13 20:19:39 -06:00
Gazook89
29b89bdc00 Merge branch 'master' into RegExp-Crash-in-Curly-Syntax 2022-11-13 20:06:05 -06:00
Gazook89
4493d86fd5 fix injection curly syntax 2022-11-13 20:05:52 -06:00
Gazook89
6a600df19a Merge branch 'master' into Field-Validation-System-2 2022-11-13 19:11:21 -06:00
Trevor Buckner
e8c6e36521 Merge pull request #2499 from G-Ambatte/fixMissingMetaTagsCrash-#2498
Fix template.js crash when ogMeta undefined
2022-11-13 15:46:25 -05:00
G.Ambatte
3e3610a204 Move fix to template.js 2022-11-14 08:20:46 +13:00
G.Ambatte
3e626d91f0 Add empty object as ogMeta default 2022-11-14 08:12:27 +13:00
Gazook89
6a0d8d13b0 don't save errs to state 2022-11-13 12:56:17 -06:00
Gazook89
4f762b376f tweak validation rules on Thumbnail & prevent invalid field from block valid fields 2022-11-13 12:45:31 -06:00
Gazook89
bda80c9984 remove comments 2022-11-13 11:43:55 -06:00
Gazook89
7de60e2345 Merge branch 'master' into Delete-Recent-Items 2022-11-13 11:41:19 -06:00
Trevor Buckner
77ad2c8958 Merge pull request #2481 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.4.3
Bump react-router-dom from 6.4.2 to 6.4.3
2022-11-12 21:27:52 -05:00
Trevor Buckner
6cca821ba6 Merge pull request #2487 from naturalcrit/dependabot/npm_and_yarn/googleapis-109.0.1
Bump googleapis from 108.0.1 to 109.0.1
2022-11-12 21:27:44 -05:00
Trevor Buckner
96da053717 Merge branch 'master' into pr/2488 2022-11-11 20:33:20 -05:00
dependabot[bot]
3723006f39 Bump react-router-dom from 6.4.2 to 6.4.3
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.4.2 to 6.4.3.
- [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.4.3/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>
2022-11-11 03:21:08 +00:00
dependabot[bot]
6cfdc47760 Bump googleapis from 108.0.1 to 109.0.1
Bumps [googleapis](https://github.com/googleapis/google-api-nodejs-client) from 108.0.1 to 109.0.1.
- [Release notes](https://github.com/googleapis/google-api-nodejs-client/releases)
- [Changelog](https://github.com/googleapis/google-api-nodejs-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/google-api-nodejs-client/compare/googleapis-v108.0.1...googleapis-v109.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-11 03:21:02 +00:00
Trevor Buckner
00a5600768 Merge pull request #2490 from naturalcrit/dependabot/npm_and_yarn/marked-4.2.2
Bump marked from 4.1.1 to 4.2.2
2022-11-10 22:10:57 -05:00
Trevor Buckner
d8674d09a2 Merge pull request #2453 from Gazook89/Open-Graph-Meta-Changes
Change `<meta>` tags based on Current Page
2022-11-10 22:02:47 -05:00
dependabot[bot]
a46630f774 Bump marked from 4.1.1 to 4.2.2
Bumps [marked](https://github.com/markedjs/marked) from 4.1.1 to 4.2.2.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Changelog](https://github.com/markedjs/marked/blob/master/.releaserc.json)
- [Commits](https://github.com/markedjs/marked/compare/v4.1.1...v4.2.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-11 02:57:54 +00:00
Trevor Buckner
38fb9d467c Merge branch 'master' into pr/2453 2022-11-10 21:56:49 -05:00
Trevor Buckner
fee56ca8e0 Merge pull request #2496 from naturalcrit/fixV3_PreviewTest
Update Jest test  for moved legacy homepage
2022-11-10 21:55:32 -05:00
Trevor Buckner
de60419926 Update config.yml 2022-11-10 21:53:28 -05:00
Trevor Buckner
42a1410cc2 Update config.yml 2022-11-10 21:52:06 -05:00
Trevor Buckner
ddd4f93f01 Merge branch 'fixV3_PreviewTest' of https://github.com/naturalcrit/homebrewery into fixV3_PreviewTest 2022-11-10 21:50:09 -05:00
Trevor Buckner
21de3b31b6 Use lower npm version 2022-11-10 21:49:57 -05:00
Trevor Buckner
aea25119c0 Updated config.yml 2022-11-10 21:46:56 -05:00
Trevor Buckner
aa1100642d update circleCI config 2022-11-10 21:37:45 -05:00
Trevor Buckner
4121cc0e14 Update package-lock.json 2022-11-10 21:23:21 -05:00
Trevor Buckner
3b7b56c789 Update package-lock.json 2022-11-10 21:19:36 -05:00
Trevor Buckner
ebc03aee33 Update Jest test for moved legacy homepage 2022-11-10 21:04:25 -05:00
Gazook89
03c6edf31a change regexp to calculuschild's atomic fix 2022-11-07 10:01:22 -06:00
Gazook89
970d03a5e4 validate thumbnail is URL 2022-11-06 13:17:39 -06:00
Gazook89
ed4c090f21 finish setting OG tags 2022-11-06 12:34:24 -06:00
Gazook89
672d582caf move metaTag objects to app.js 2022-11-05 23:32:30 -05:00
Gazook89
b6c09683be add language field validation (for future pr)
fix an oversight in validations
2022-11-05 20:07:27 -05:00
Gazook89
a13fd48cda prevent crash on input to second field. small css change 2022-11-05 12:19:01 -05:00
Gazook89
aec1147aa5 set :invalid input to light red background 2022-11-05 11:56:48 -05:00
Gazook89
78da48b08d fix issue with async setState using Event.persist() 2022-11-05 11:42:21 -05:00
Gazook89
edce191c29 remove a silly rule 2022-11-05 11:32:35 -05:00
Gazook89
8c52a253dc log errs correctly, setCustomValidity and reportValidity 2022-11-04 20:22:59 -05:00
Gazook89
589ec0251a move validations into it's own file. 2022-11-04 15:32:20 -05:00
Gazook89
ffddc275c1 set removeItem icon to transparent background 2022-11-03 23:38:46 -05:00
Gazook89
4e26bb309c Merge branch 'master' into Open-Graph-Meta-Changes 2022-11-03 22:05:13 -05:00
Gazook89
7696be5d95 first commit 2022-11-03 22:00:45 -05:00
Trevor Buckner
ef80c23034 Merge pull request #2479 from G-Ambatte/excludeGoogleStubsFromAccountPage
[AccountPage] Modify query to exclude Google brew stubs
2022-10-31 22:37:40 -04:00
G.Ambatte
1f7be69624 Modify query to exclude Google brew stubs 2022-10-31 17:43:41 +13:00
Trevor Buckner
6e069dc29d Merge pull request #2161 from G-Ambatte/createUIBasePage
Create UI base page
2022-10-30 11:08:04 -04:00
G.Ambatte
e40bbf56c7 Merge branch 'master' into createUIBasePage 2022-10-30 18:21:45 +13:00
Trevor Buckner
65beb8d65e Merge branch 'master' into pr/2442 2022-10-28 14:07:14 -04:00
Trevor Buckner
ebf4f614c4 Merge pull request #2447 from Gazook89/autosave-default-fix
Fix Autosave Default
2022-10-28 14:05:45 -04:00
Trevor Buckner
26942e276a Merge branch 'master' into pr/2447 2022-10-28 14:04:45 -04:00
Trevor Buckner
0bcce67e39 Small logic simplification 2022-10-28 14:04:28 -04:00
Trevor Buckner
3318ba6277 Merge pull request #2450 from G-Ambatte/fixUserPageStyle-#2449
[UserPage] Fix UserPage groups styling
2022-10-28 14:00:17 -04:00
Trevor Buckner
c5eb7db432 Merge pull request #2448 from naturalcrit/dependabot/npm_and_yarn/dedent-tabs-0.10.2
Bump dedent-tabs from 0.10.1 to 0.10.2
2022-10-28 13:07:26 -04:00
Trevor Buckner
f35345f385 Actually update version number. 2022-10-28 13:03:09 -04:00
Trevor Buckner
a13ac2e0c5 Merge pull request #2469 from jeddai/update-twitter-card
update twitter:card meta tag to have "summary" as the content
2022-10-28 02:31:09 -04:00
Trevor Buckner
27eb95ece8 Simplify split-table margins, .blank should have no margins before or after 2022-10-28 02:10:22 -04:00
Trevor Buckner
7958bb4cda Missed one table style 2022-10-28 00:51:40 -04:00
Trevor Buckner
8fc01ebb12 Merge pull request #2472 from naturalcrit/Version3.3.1
Update changelog.md
2022-10-28 00:11:57 -04:00
Trevor Buckner
d2c10bb9ac Update changelog.md 2022-10-28 00:11:31 -04:00
Trevor Buckner
13eedc9f82 Merge pull request #2467 from naturalcrit/dependabot/npm_and_yarn/googleapis-108.0.1
Bump googleapis from 108.0.0 to 108.0.1
2022-10-28 00:05:45 -04:00
Trevor Buckner
6f919bc214 Merge pull request #2471 from naturalcrit/MoreThemesFixes
More themes fixes
2022-10-28 00:05:28 -04:00
Trevor Buckner
496328d511 Remove unnecessary spacing rules from Blank Theme 2022-10-27 23:46:47 -04:00
Trevor Buckner
d6af56c51c Move table line-height from TD to Table 2022-10-27 23:34:50 -04:00
Trevor Buckner
079d59695f Return :where(.page) to .page 2022-10-27 23:27:56 -04:00
Charlie Humphreys
0867b142da update getBrew usages to not fetch google brew during updates 2022-10-27 21:44:26 -05:00
Charlie Humphreys
ac7b2bce9f update twitter:card meta tag to have "summary" as the content 2022-10-27 21:14:14 -05:00
dependabot[bot]
4664d88aad Bump googleapis from 108.0.0 to 108.0.1
Bumps [googleapis](https://github.com/googleapis/google-api-nodejs-client) from 108.0.0 to 108.0.1.
- [Release notes](https://github.com/googleapis/google-api-nodejs-client/releases)
- [Changelog](https://github.com/googleapis/google-api-nodejs-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/google-api-nodejs-client/compare/googleapis-v108.0.0...googleapis-v108.0.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-26 03:01:07 +00:00
Trevor Buckner
7d6a3da2e2 Merge pull request #2465 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.7.0
Bump mongoose from 6.6.5 to 6.7.0
2022-10-24 23:20:42 -04:00
Trevor Buckner
4180a7cfb4 Merge pull request #2455 from naturalcrit/dependabot/npm_and_yarn/babel/plugin-transform-runtime-7.19.6
Bump @babel/plugin-transform-runtime from 7.19.1 to 7.19.6
2022-10-24 23:20:15 -04:00
Trevor Buckner
a2e11d12c9 Merge pull request #2452 from G-Ambatte/fixBrewItemError-#2451
[UserPage] Add key prop to Brew tags
2022-10-24 23:20:02 -04:00
dependabot[bot]
301c3fbdd2 Bump @babel/plugin-transform-runtime from 7.19.1 to 7.19.6
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.19.1 to 7.19.6.
- [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.19.6/packages/babel-plugin-transform-runtime)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-25 03:16:37 +00:00
Trevor Buckner
35088188b3 Merge pull request #2456 from naturalcrit/dependabot/npm_and_yarn/babel/core-7.19.6
Bump @babel/core from 7.19.3 to 7.19.6
2022-10-24 23:15:38 -04:00
Trevor Buckner
95cda71eb5 Merge pull request #2458 from naturalcrit/dependabot/npm_and_yarn/eslint-8.26.0
Bump eslint from 8.25.0 to 8.26.0
2022-10-24 23:15:26 -04:00
Trevor Buckner
a2e9fc67e4 Merge pull request #2463 from naturalcrit/dependabot/npm_and_yarn/jest-29.2.2
Bump jest from 29.2.1 to 29.2.2
2022-10-24 23:15:18 -04:00
dependabot[bot]
50c541f3fa Bump jest from 29.2.1 to 29.2.2
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.2.1 to 29.2.2.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.2.2/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-25 03:12:38 +00:00
dependabot[bot]
f98a3fe6c5 Bump eslint from 8.25.0 to 8.26.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.25.0 to 8.26.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.25.0...v8.26.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-25 03:11:05 +00:00
Trevor Buckner
d2c86bf619 Merge pull request #2464 from naturalcrit/dependabot/npm_and_yarn/supertest-6.3.1
Bump supertest from 6.3.0 to 6.3.1
2022-10-24 23:10:00 -04:00
dependabot[bot]
aeb4f85a48 Bump mongoose from 6.6.5 to 6.7.0
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.6.5 to 6.7.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/6.6.5...6.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-25 03:01:46 +00:00
dependabot[bot]
b8f32cc2cb Bump supertest from 6.3.0 to 6.3.1
Bumps [supertest](https://github.com/visionmedia/supertest) from 6.3.0 to 6.3.1.
- [Release notes](https://github.com/visionmedia/supertest/releases)
- [Commits](https://github.com/visionmedia/supertest/compare/v6.3.0...v6.3.1)

---
updated-dependencies:
- dependency-name: supertest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-25 03:01:25 +00:00
Trevor Buckner
d562308b63 Merge pull request #2461 from naturalcrit/FixPHBHeaderSpacings
Fix PHB Tables (again) + Header spacings
2022-10-24 19:37:20 -04:00
Trevor Buckner
2d26e7cd07 Handle spacing at bottom of side-by-side tables 2022-10-24 19:29:59 -04:00
Trevor Buckner
8b011804ca Merge branch 'master' into FixPHBHeaderSpacings 2022-10-24 17:08:49 -04:00
Trevor Buckner
93a90dbf13 Merge pull request #2460 from naturalcrit/FixPrintPageMissingBlankTheme
Fix "blank" theme not included on print page.
2022-10-24 17:08:33 -04:00
Trevor Buckner
2b6585545c Fix "blank" theme not included on print page. 2022-10-24 17:04:33 -04:00
Trevor Buckner
047160e4ec Further tweaks to table size/header spacings 2022-10-24 17:01:38 -04:00
Trevor Buckner
6a6ee9fc12 Tweak top margins for headers 2022-10-21 09:27:55 -04:00
dependabot[bot]
96577794e9 Bump @babel/core from 7.19.3 to 7.19.6
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.19.3 to 7.19.6.
- [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.19.6/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>
2022-10-21 03:01:56 +00:00
Gazook89
5c3f7b1b82 small fixes 2022-10-20 11:46:53 -05:00
Gazook89
bdf1bd1e8b add user page 2022-10-20 11:40:10 -05:00
Gazook89
df6d372243 Merge branch 'master' into Open-Graph-Meta-Changes 2022-10-20 11:19:48 -05:00
Gazook89
b237456420 add fn to change meta tags based on page 2022-10-20 11:19:17 -05:00
G.Ambatte
52a79b4f75 Add default loading properties using custom assign 2022-10-20 19:11:31 +13:00
G.Ambatte
99382adbf6 Add key prop to Brew tags 2022-10-20 17:34:06 +13:00
G.Ambatte
3f0c950e72 Fix UserPage groups styling 2022-10-20 17:26:46 +13:00
dependabot[bot]
2b71ff2dec Bump dedent-tabs from 0.10.1 to 0.10.2
Bumps [dedent-tabs](https://github.com/adrianjost/dedent-tabs) from 0.10.1 to 0.10.2.
- [Release notes](https://github.com/adrianjost/dedent-tabs/releases)
- [Commits](https://github.com/adrianjost/dedent-tabs/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-20 03:01:28 +00:00
G.Ambatte
9ccf9d0a83 Merge branch 'master' into fixThemesDefault 2022-10-20 08:03:43 +13:00
Gazook89
1801691f49 fix autosave default 2022-10-19 11:45:47 -05:00
Trevor Buckner
2bad0bfcb0 Further table tweaks for Chrome 106 2022-10-19 09:06:48 -04:00
Trevor Buckner
ac30b3df9d Merge pull request #2446 from naturalcrit/Update-to-v-3.3.0
Update to v 3.3.0
2022-10-19 00:54:29 -04:00
Trevor Buckner
f67ba7ecda Update changelog.md 2022-10-19 00:50:30 -04:00
Trevor Buckner
812b8350d3 3.3.0 2022-10-19 00:49:31 -04:00
Trevor Buckner
0c67a23b57 Update changelog.md 2022-10-19 00:49:24 -04:00
Trevor Buckner
976f6be3f0 Merge pull request #2441 from naturalcrit/TemporaryChromeTableHeightFix
Tweak table padding
2022-10-19 00:07:33 -04:00
Trevor Buckner
852d2a1d5f Merge pull request #2443 from naturalcrit/dependabot/npm_and_yarn/jest-29.2.1
Bump jest from 29.2.0 to 29.2.1
2022-10-19 00:07:11 -04:00
dependabot[bot]
bf39d4124c Bump jest from 29.2.0 to 29.2.1
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.2.0 to 29.2.1.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.2.1/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-19 03:01:25 +00:00
Gazook89
04eebae3ec Merge branch 'master' into Open-Graph-Meta-Changes 2022-10-18 21:19:55 -05:00
Gazook89
23a0a89ead autohide dropdown again 2022-10-18 21:02:44 -05:00
Gazook89
a7a67621a1 added removeItem() function 2022-10-18 21:01:24 -05:00
Trevor Buckner
2d2a81a3ca Tweak table padding 2022-10-18 21:29:34 -04:00
Gazook89
bebb06a36d Merge branch 'master' into Delete-Recent-Items 2022-10-18 19:22:01 -05:00
Trevor Buckner
c4e331ee7e Merge pull request #2438 from G-Ambatte/fixToC-#2437
Change ToC to use flexbox
2022-10-18 15:25:24 -04:00
Trevor Buckner
13192dc102 Merge pull request #2428 from G-Ambatte/fixSaveFromHomePage-#2427
Send entire brew to HomePage save function
2022-10-18 14:12:47 -04:00
Trevor Buckner
ab773f5f7b Merge pull request #2426 from G-Ambatte/ignoreVSCodeFIles
Add .vscode to .gitignore
2022-10-18 14:12:15 -04:00
Trevor Buckner
164a0fe8d5 Merge pull request #2425 from G-Ambatte/addURIEncodingToUserName-#2420
Add URI encoding to User Page link
2022-10-18 14:11:42 -04:00
Trevor Buckner
3032363aea Merge pull request #2392 from G-Ambatte/stopUnfoldingCode-#2135
[Editor] Prevent unfolding code in Editor when adding a Snippet
2022-10-18 13:55:21 -04:00
Trevor Buckner
3327712253 Focus on editor after snippet 2022-10-18 13:52:22 -04:00
Trevor Buckner
2abd0a871b Merge pull request #2416 from naturalcrit/dependabot/npm_and_yarn/supertest-6.3.0
Bump supertest from 6.2.4 to 6.3.0
2022-10-18 13:23:39 -04:00
Trevor Buckner
eff7fde8cf Merge pull request #2384 from Gazook89/Toggle-AutoSave
Add ability to toggle the Auto Save
2022-10-18 13:23:26 -04:00
Trevor Buckner
8b8a60c8ad tweak alert text 2022-10-18 13:22:29 -04:00
Trevor Buckner
5350f7d933 Merge pull request #2418 from naturalcrit/dependabot/npm_and_yarn/react-router-dom-6.4.2
Bump react-router-dom from 6.3.0 to 6.4.2
2022-10-18 11:57:36 -04:00
Trevor Buckner
30c9b35354 Merge pull request #2404 from naturalcrit/dependabot/npm_and_yarn/babel/core-7.19.3
Bump @babel/core from 7.19.1 to 7.19.3
2022-10-18 11:57:23 -04:00
Trevor Buckner
4c46388686 Merge pull request #2419 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.6.5
Bump mongoose from 6.6.1 to 6.6.5
2022-10-18 11:57:12 -04:00
dependabot[bot]
3bd9fe4c99 Bump supertest from 6.2.4 to 6.3.0
Bumps [supertest](https://github.com/visionmedia/supertest) from 6.2.4 to 6.3.0.
- [Release notes](https://github.com/visionmedia/supertest/releases)
- [Commits](https://github.com/visionmedia/supertest/compare/v6.2.4...v6.3.0)

---
updated-dependencies:
- dependency-name: supertest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-18 15:32:04 +00:00
Trevor Buckner
837554eb17 Merge pull request #2439 from naturalcrit/dependabot/npm_and_yarn/jest-29.2.0
Bump jest from 29.0.3 to 29.2.0
2022-10-18 11:30:45 -04:00
Gazook89
d8fe54b7b2 Merge branch 'master' into Toggle-AutoSave 2022-10-17 21:53:35 -05:00
Gazook89
c49be3391e change time delay between warnings to 15min 2022-10-17 21:52:48 -05:00
Gazook89
c56adcba76 only display 'off' warning if changes exist 2022-10-17 21:49:50 -05:00
dependabot[bot]
74e20bf7be Bump jest from 29.0.3 to 29.2.0
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.0.3 to 29.2.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.2.0/packages/jest)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-17 03:01:24 +00:00
G.Ambatte
7896fe3ed9 Remove footer on pages with ToC 2022-10-16 22:37:30 +13:00
G.Ambatte
0e0cdfe25b Fix font size in ToC 2022-10-16 21:20:01 +13:00
G.Ambatte
2c2a10730e Change style of page numbers 2022-10-16 21:01:45 +13:00
G.Ambatte
51f8786905 Change ToC to use flexbox 2022-10-16 20:34:18 +13:00
dependabot[bot]
78a5390917 Bump @babel/core from 7.19.1 to 7.19.3
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.19.1 to 7.19.3.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.19.3/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>
2022-10-11 01:18:32 +00:00
Trevor Buckner
d998381bbe Merge pull request #2435 from naturalcrit/dependabot/npm_and_yarn/babel/preset-env-7.19.4
Bump @babel/preset-env from 7.19.1 to 7.19.4
2022-10-10 21:17:48 -04:00
Trevor Buckner
6326a93d98 Merge pull request #2434 from naturalcrit/dependabot/npm_and_yarn/eslint-plugin-react-7.31.10
Bump eslint-plugin-react from 7.31.8 to 7.31.10
2022-10-10 21:17:42 -04:00
dependabot[bot]
e4e619ac1e Bump @babel/preset-env from 7.19.1 to 7.19.4
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.19.1 to 7.19.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.19.4/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>
2022-10-11 01:11:34 +00:00
dependabot[bot]
439afcb667 Bump eslint-plugin-react from 7.31.8 to 7.31.10
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.31.8 to 7.31.10.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.31.8...v7.31.10)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-11 01:11:10 +00:00
Trevor Buckner
f4108f241e Merge pull request #2422 from naturalcrit/dependabot/npm_and_yarn/body-parser-1.20.1
Bump body-parser from 1.20.0 to 1.20.1
2022-10-10 21:10:36 -04:00
Trevor Buckner
2e3c9114c6 Merge pull request #2412 from naturalcrit/dependabot/npm_and_yarn/marked-4.1.1
Bump marked from 4.1.0 to 4.1.1
2022-10-10 21:10:16 -04:00
Trevor Buckner
746b04646c Merge pull request #2431 from naturalcrit/dependabot/npm_and_yarn/express-4.18.2
Bump express from 4.18.1 to 4.18.2
2022-10-10 21:10:04 -04:00
Trevor Buckner
a7577bf83b Merge pull request #2432 from naturalcrit/dependabot/npm_and_yarn/eslint-8.25.0
Bump eslint from 8.24.0 to 8.25.0
2022-10-10 21:09:51 -04:00
dependabot[bot]
b283e8e66a Bump eslint from 8.24.0 to 8.25.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.24.0 to 8.25.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.24.0...v8.25.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-10 03:01:22 +00:00
dependabot[bot]
a129e887dd Bump express from 4.18.1 to 4.18.2
Bumps [express](https://github.com/expressjs/express) from 4.18.1 to 4.18.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.1...4.18.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-10 03:01:07 +00:00
G.Ambatte
9ad915c14a Remove unnecessary & incorrect default setting 2022-10-09 21:50:31 +13:00
G.Ambatte
9fd5fea50c Remove obsolete code in app.js 2022-10-09 21:50:11 +13:00
G.Ambatte
41fa0f2c77 Apply defaults on load and before saving 2022-10-09 21:49:25 +13:00
G.Ambatte
ed65d0c922 Send entire brew to HomePage save function 2022-10-09 11:55:05 +13:00
G.Ambatte
df53369ec1 Add .vscode to .gitignore 2022-10-08 14:56:42 +13:00
G.Ambatte
cc385462de Add URI encoding to User Page link 2022-10-08 14:47:59 +13:00
dependabot[bot]
269ba246ec Bump body-parser from 1.20.0 to 1.20.1
Bumps [body-parser](https://github.com/expressjs/body-parser) from 1.20.0 to 1.20.1.
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.20.0...1.20.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-07 03:01:00 +00:00
dependabot[bot]
a67b1b9c12 Bump mongoose from 6.6.1 to 6.6.5
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.6.1 to 6.6.5.
- [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/6.6.1...6.6.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-06 03:02:20 +00:00
dependabot[bot]
8c13d4d7ad Bump react-router-dom from 6.3.0 to 6.4.2
Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.3.0 to 6.4.2.
- [Release notes](https://github.com/remix-run/react-router/releases)
- [Changelog](https://github.com/remix-run/react-router/blob/react-router-dom@6.4.2/packages/react-router-dom/CHANGELOG.md)
- [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.4.2/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>
2022-10-06 03:01:39 +00:00
Gazook89
8562d328ff Merge remote-tracking branch 'upstream/master' into Toggle-AutoSave 2022-10-03 20:46:11 -05:00
G.Ambatte
1d8781da90 Modify how data is passed to UIPage 2022-10-03 20:27:34 +13:00
dependabot[bot]
dd64d19037 Bump marked from 4.1.0 to 4.1.1
Bumps [marked](https://github.com/markedjs/marked) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/markedjs/marked/releases)
- [Changelog](https://github.com/markedjs/marked/blob/master/.releaserc.json)
- [Commits](https://github.com/markedjs/marked/compare/v4.1.0...v4.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-03 03:01:09 +00:00
G.Ambatte
93918bc26c Nudge SVG size 2022-10-02 11:06:57 +13:00
Gazook89
bfb82e8a21 autosave warning conditional on elapsed time unsaved. 2022-09-30 12:20:59 -05:00
Gazook89
8609026531 add unsavedTime state for better notification 2022-09-30 11:24:15 -05:00
Gazook89
0cd598ae14 rework the whole thing 2022-09-30 10:42:50 -05:00
Gazook89
95497350e4 move test for autosave status to handleTextChange from trySave() 2022-09-28 20:20:11 -05:00
Gazook89
9bb1344538 tweak behavior per calculuschild notes
Default to autosave = true.   trySave() when autosave toggled on.  Display "auto-saved." when save is a result of autosave.
2022-09-28 12:17:14 -05:00
Gazook89
ab695d29fe refactor into handle... and render... methods 2022-09-28 11:13:16 -05:00
Trevor Buckner
89c091c630 Add 8 corner images.
Doesn't work well with --rotation but you can just set top,left or whatever. --offset works.
2022-09-27 23:55:24 -04:00
Gazook89
fa4b3338af save autosave setting to localStorage 2022-09-27 21:04:51 -05:00
Gazook89
c7ed9ea717 Create autosave toggle dropdown menu 2022-09-27 19:35:29 -05:00
G.Ambatte
7ae939623c Merge branch 'master' into createUIBasePage 2022-09-28 07:06:01 +13:00
G.Ambatte
de86a77dfc Change post-insertion selection option 2022-09-27 17:06:48 +13:00
G.Ambatte
b44a7d3236 Merge branch 'master' into stopUnfoldingCode-#2135 2022-09-27 13:01:30 +13:00
Trevor Buckner
a3c7e2f807 Merge pull request #2396 from G-Ambatte/adjustCodeFold-#1907
[Editor] Change folded code text generation
2022-09-26 16:40:40 -04:00
G.Ambatte
447f8d39dc Reduce variable use 2022-09-27 08:03:43 +13:00
G.Ambatte
7b961af45f Merge branch 'master' into adjustCodeFold-#1907 2022-09-27 07:54:05 +13:00
Gazook89
bc0ee8138e change title and description 2022-09-26 13:03:40 -05:00
G.Ambatte
91b2911bb0 Change capitalization of page title 2022-09-26 20:17:52 +13:00
G.Ambatte
9848dc54ba Add Nav bar items 2022-09-26 19:07:46 +13:00
G.Ambatte
9a3bd4db4b Merge branch 'master' into createUIBasePage 2022-09-26 19:02:07 +13:00
G.Ambatte
891bde6990 Merge branch 'createUIBasePage' of https://github.com/G-Ambatte/homebrewery into createUIBasePage 2022-09-26 18:44:45 +13:00
G.Ambatte
d9228b8c4b Add Account menu item 2022-09-26 18:43:47 +13:00
Trevor Buckner
edd58455f6 Merge pull request #2399 from naturalcrit/dependabot/npm_and_yarn/got-and-nodemon--removed
Bump got and nodemon
2022-09-25 23:56:57 -04:00
Trevor Buckner
e082167c39 Merge pull request #2398 from naturalcrit/dependabot/npm_and_yarn/eslint-8.24.0
Bump eslint from 8.23.1 to 8.24.0
2022-09-25 23:55:04 -04:00
G.Ambatte
5a3daf8ffd Merge branch 'master' into createUIBasePage 2022-09-26 16:34:44 +13:00
dependabot[bot]
3719614dee Bump got and nodemon
Removes [got](https://github.com/sindresorhus/got). It's no longer used after updating ancestor dependency [nodemon](https://github.com/remy/nodemon). These dependencies need to be updated together.


Removes `got`

Updates `nodemon` from 2.0.7 to 2.0.20
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.7...v2.0.20)

---
updated-dependencies:
- dependency-name: got
  dependency-type: indirect
- dependency-name: nodemon
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-26 03:27:43 +00:00
Trevor Buckner
e098dc21ce Merge pull request #2389 from naturalcrit/dependabot/npm_and_yarn/googleapis-108.0.0
Bump googleapis from 107.0.0 to 108.0.0
2022-09-25 23:26:55 -04:00
Trevor Buckner
f4580f9040 Merge pull request #2372 from Gazook89/CSS-Flex-Meta-Editor
Reposition Thumbnail Preview in Metadata Editor
2022-09-25 23:19:27 -04:00
Trevor Buckner
6e05186f1a Merge pull request #2395 from G-Ambatte/shiftThumbnailUrlToStub-#2351
[Stub] Shift thumbnail url to stub #2351
2022-09-25 23:16:50 -04:00
Trevor Buckner
9701c55195 Merge branch 'master' into pr/2395 2022-09-25 23:08:37 -04:00
dependabot[bot]
0d2eebe324 Bump eslint from 8.23.1 to 8.24.0
Bumps [eslint](https://github.com/eslint/eslint) from 8.23.1 to 8.24.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.23.1...v8.24.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-26 03:01:13 +00:00
Trevor Buckner
e21fe49359 Merge pull request #2387 from Gazook89/stat-block-color-tweak
Change Monster Stat background color
2022-09-25 22:54:42 -04:00
Trevor Buckner
bc94082eb6 Merge pull request #2383 from Gazook89/Prevent-Selection-on-splitPane-drag
Prevent text selection in editor when dragging splitPane divider.
2022-09-25 22:29:36 -04:00
Trevor Buckner
5d769d2297 Merge pull request #2382 from Gazook89/scroll-behavior-correction
Scroll behavior correction
2022-09-25 22:26:15 -04:00
Trevor Buckner
48d0434178 Merge branch 'master' into pr/2382 2022-09-25 22:23:19 -04:00
Trevor Buckner
f74b84bd12 Merge pull request #2379 from Gazook89/filter-sort-as-divs
Change User Page search bar to Divs
2022-09-25 22:21:58 -04:00
Trevor Buckner
910868cfdb Simplified sort arrow, removed duplicate "onClick" 2022-09-25 22:20:44 -04:00
Trevor Buckner
b8d7d1a8e4 Allow rotation and positioning up and down 2022-09-25 21:43:40 -04:00
G.Ambatte
5469ec6683 Format Issued datetime 2022-09-26 13:28:50 +13:00
G.Ambatte
764621f762 Add Homebrewery Icon 2022-09-26 12:12:21 +13:00
G.Ambatte
248687684a Add group styling 2022-09-26 11:31:00 +13:00
G.Ambatte
d7b1f89152 Change data items to a list 2022-09-26 11:30:45 +13:00
G.Ambatte
9a844dae39 Fix class=>className 2022-09-26 00:41:49 +13:00
G.Ambatte
5193271796 Fix Google Drive icon 2022-09-26 00:41:17 +13:00
G.Ambatte
ed5bef27e0 Shift renderUiItems to function 2022-09-26 00:35:12 +13:00
G.Ambatte
be25e90009 Change variable name 2022-09-26 00:34:54 +13:00
G.Ambatte
ab98bf5d6c Fix Routes 2022-09-26 00:05:53 +13:00
G.Ambatte
ffb1c77697 Merge branch 'createUIBasePage' 2022-09-25 23:54:20 +13:00
G.Ambatte
6bddba6762 Merge branch 'master' into createUIBasePage 2022-09-25 23:47:55 +13:00
G.Ambatte
57b0af54df Renamed functions, eliminate unnecessary variable 2022-09-25 23:29:45 +13:00
G.Ambatte
0ac50017c4 Change path to /account 2022-09-25 23:20:45 +13:00
G.Ambatte
9135ca1e43 Fix class => className 2022-09-25 23:20:03 +13:00
G.Ambatte
1dc6256aab Change fold-marker color to grey 2022-09-25 19:59:35 +13:00
G.Ambatte
227be5e3be Modify folded text generation 2022-09-25 13:55:46 +13:00
G.Ambatte
e18e3cf7e4 Remove thumbnail from Google brew properties 2022-09-24 23:51:08 +12:00
G.Ambatte
ca09e98d8f Exclude thumbnail from Google props 2022-09-24 23:50:20 +12:00
G.Ambatte
db174c9655 Add optional overwrite protection 2022-09-24 13:50:26 +12:00
G.Ambatte
22896470e3 Remove unused splice function 2022-09-24 13:36:14 +12:00
G.Ambatte
56fde5a448 Use cm.replaceSelection instead of split/join text 2022-09-24 13:34:26 +12:00
Trevor Buckner
6ade9925d7 Merge pull request #2388 from Gazook89/Display-Renderer-on-Page
Add renderer to pageInfo
2022-09-22 14:51:20 -04:00
Trevor Buckner
e755ab878d Merge pull request #2332 from G-Ambatte/showThumbnailOnUserPage-#2331
[UserPage] Show Brew's Meta thumbnail on UserPage
2022-09-22 14:23:06 -04:00
G.Ambatte
fa0d8e86fc Remove unnecessary empty element 2022-09-22 20:25:18 +12:00
dependabot[bot]
5458b8297c Bump googleapis from 107.0.0 to 108.0.0
Bumps [googleapis](https://github.com/googleapis/google-api-nodejs-client) from 107.0.0 to 108.0.0.
- [Release notes](https://github.com/googleapis/google-api-nodejs-client/releases)
- [Changelog](https://github.com/googleapis/google-api-nodejs-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/google-api-nodejs-client/compare/googleapis-v107.0.0...googleapis-v108.0.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-22 03:01:15 +00:00
Gazook89
f3c9dde801 thumbnail preview de-uglification 2022-09-21 20:50:10 -05:00
Gazook89
45aa8bdfae Add html node and css for Delete button 2022-09-21 20:27:16 -05:00
G.Ambatte
09d161f3a6 Adjust background image properties 2022-09-22 07:48:51 +12:00
Gazook89
90a65d0a57 Add renderer to pageInfo 2022-09-21 11:37:14 -05:00
Gazook89
0bf1328c17 change monster stat background color 2022-09-21 11:29:42 -05:00
Gazook89
3754468cf4 change sortDir by clicking on sort title. 2022-09-21 11:12:23 -05:00
Gazook89
6329cb2cec style changes for better contrast 2022-09-21 10:56:45 -05:00
G.Ambatte
f218f48f0f Apply Gazook89's thumbnail style 2022-09-21 18:38:45 +12:00
G.Ambatte
a179f8d124 Lint fix 2022-09-21 18:16:36 +12:00
Gazook89
f681948a35 pedantic change 2022-09-21 00:42:10 -05:00
Gazook89
475f3e75dd add simple toggle to 'save status' field for auto-save 2022-09-21 00:29:40 -05:00
Gazook89
f337925af9 add e.preventDefault() to mousedown event 2022-09-20 23:46:25 -05:00
G.Ambatte
918690e773 Merge branch 'master' into showThumbnailOnUserPage-#2331 2022-09-21 14:35:27 +12:00
Gazook89
7623d3e93a set scrollbar to 'thin' in recentItems dropdown 2022-09-20 20:37:55 -05:00
Gazook89
f2a8a6a03a match scroll bar style of recentItems to UI 2022-09-20 19:59:38 -05:00
Gazook89
49cc4180a7 set only listPage to overflow-y scroll.
The pages are not all quite set up the same way.  /new/, /edit/, and /share/ all use an iframe and those iframes have their own scroll behavior.  /user/ doesn't have an iframe and so the `.content` portion of the page needs to scroll.
2022-09-20 19:58:52 -05:00
Trevor Buckner
8ebfc772f3 Merge pull request #2381 from Gazook89/Effect-to-Affect-PPR
Update PPR notice with correct spelling.
2022-09-20 13:21:36 -04:00
Gazook89
38dccbae09 change 'effect' to 'affect' 2022-09-20 12:19:27 -05:00
Trevor Buckner
0f68f5a356 Merge pull request #2380 from Gazook89/reddit-issue-template-fix
Make Reddit Issue Template a List
2022-09-19 22:19:04 -04:00
Gazook89
7999553973 make reddit issue template a list 2022-09-19 20:44:31 -05:00
Gazook89
3c75ac6156 change some .less to reflect new focus of .active 2022-09-19 11:30:44 -05:00
Gazook89
9fcc7b84c3 set .sort-option to .active rather than button within. 2022-09-19 11:07:47 -05:00
Gazook89
8ac4d93581 change sort-container to baseline alignment 2022-09-19 10:47:35 -05:00
Gazook89
10a349ade8 change sortDir to always white. 2022-09-19 10:27:02 -05:00
Gazook89
87a9194189 remove unset on listPage height. 2022-09-19 10:08:52 -05:00
Gazook89
ac371946d8 Merge branch 'master' into filter-sort-as-divs 2022-09-19 10:04:47 -05:00
Trevor Buckner
158d47edde Merge pull request #2378 from Gazook89/github-forms
remove labels from dropdowns and add label
2022-09-19 11:00:34 -04:00
Gazook89
5ad4e6b1f1 remove labels from dropdowns and add label 2022-09-19 09:54:34 -05:00
Trevor Buckner
ce7c3dfb8a Merge pull request #2377 from Gazook89/github-forms
GitHub forms tweaks
2022-09-19 10:44:36 -04:00
Gazook89
208e9261ce fixed two more validations 2022-09-19 09:31:55 -05:00
Gazook89
af8d327ae2 fix editPage url query & Saving label 2022-09-18 19:37:40 -05:00
Gazook89
0d931ed5b5 add validation (required) to user-description in save_issue.yml 2022-09-18 19:33:53 -05:00
Gazook89
d8039b0cf2 removed 'title' from save_issue.yml 2022-09-18 19:32:15 -05:00
Gazook89
2e27c5957d fix checkboxes on feature_request.yml 2022-09-18 19:30:30 -05:00
Gazook89
1bfcb5a839 fix 'validations' on general_issue.yaml 2022-09-18 19:25:26 -05:00
Trevor Buckner
6d98119df2 Merge pull request #2367 from Gazook89/github-forms
Add different Issue forms
2022-09-18 17:20:25 -04:00
Trevor Buckner
a90028d93f Merge pull request #2360 from Gazook89/navbar-vs-content-sections
change overflow-y behavior to fix navbar
2022-09-18 17:16:48 -04:00
Gazook89
630ff9d86a add browser field 2022-09-18 10:32:50 -05:00
Gazook89
600b92cbce Move 'additional steps' to end of post. 2022-09-18 10:19:00 -05:00
Gazook89
7a609f5a78 set Report Save Issue to open save_issue.yaml template 2022-09-18 10:08:01 -05:00
Gazook89
4c3b9f8fb6 small requested changes 2022-09-17 23:59:25 -05:00
Trevor Buckner
d079985e6c Add checkerboard behind image to show position 2022-09-16 00:30:39 -04:00
Gazook89
b120c47faa add vertical scroll - auto 2022-09-15 13:38:09 -05:00
Gazook89
49a3057765 clear out some unused properties 2022-09-15 13:33:19 -05:00
Gazook89
fc5d06be0e fixed vertical spacing 2022-09-15 13:19:27 -05:00
Gazook89
bb25d30663 flex working, but odd vertical spacing 2022-09-15 12:29:25 -05:00
Trevor Buckner
aba2746f89 Initial commit 2022-09-15 00:35:35 -04:00
Trevor Buckner
d20bb15204 Merge pull request #2370 from naturalcrit/dependabot/npm_and_yarn/babel/preset-env-7.19.1
Bump @babel/preset-env from 7.19.0 to 7.19.1
2022-09-14 23:03:51 -04:00
Trevor Buckner
4261b515e6 Merge pull request #2368 from naturalcrit/dependabot/npm_and_yarn/babel/core-7.19.1
Bump @babel/core from 7.19.0 to 7.19.1
2022-09-14 23:03:43 -04:00
dependabot[bot]
283db495ad Bump @babel/preset-env from 7.19.0 to 7.19.1
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.19.0 to 7.19.1.
- [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.19.1/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>
2022-09-15 03:03:36 +00:00
dependabot[bot]
535bb34ed4 Bump @babel/core from 7.19.0 to 7.19.1
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.19.0 to 7.19.1.
- [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.19.1/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>
2022-09-15 03:03:35 +00:00
Trevor Buckner
1d4ebf48f2 Merge pull request #2363 from naturalcrit/dependabot/npm_and_yarn/classnames-2.3.2
Bump classnames from 2.3.1 to 2.3.2
2022-09-14 23:03:18 -04:00
Trevor Buckner
f637018b5d Merge pull request #2369 from naturalcrit/dependabot/npm_and_yarn/babel/plugin-transform-runtime-7.19.1
Bump @babel/plugin-transform-runtime from 7.18.10 to 7.19.1
2022-09-14 23:02:58 -04:00
Trevor Buckner
4dfbf8ecaf Merge pull request #2371 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.6.1
Bump mongoose from 6.6.0 to 6.6.1
2022-09-14 23:02:48 -04:00
Trevor Buckner
c3b17a6816 Merge pull request #2355 from naturalcrit/dependabot/npm_and_yarn/eslint-plugin-react-7.31.8
Bump eslint-plugin-react from 7.31.7 to 7.31.8
2022-09-14 23:02:37 -04:00
dependabot[bot]
f940a9181a Bump mongoose from 6.6.0 to 6.6.1
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.6.0 to 6.6.1.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Automattic/mongoose/compare/6.6.0...6.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-15 03:02:23 +00:00
dependabot[bot]
95a0151234 Bump @babel/plugin-transform-runtime from 7.18.10 to 7.19.1
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.18.10 to 7.19.1.
- [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.19.1/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-15 03:01:46 +00:00
Gazook89
3bae1565b2 Add different Issue forms 2022-09-14 21:30:01 -05:00
dependabot[bot]
66cf29e58f Bump classnames from 2.3.1 to 2.3.2
Bumps [classnames](https://github.com/JedWatson/classnames) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/JedWatson/classnames/releases)
- [Changelog](https://github.com/JedWatson/classnames/blob/main/HISTORY.md)
- [Commits](https://github.com/JedWatson/classnames/compare/v2.3.1...v2.3.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-14 03:01:24 +00:00
Gazook89
9f4920fd2a change overflow-y behavior to fix navbar 2022-09-13 15:55:50 -05:00
dependabot[bot]
2724eb6518 Bump eslint-plugin-react from 7.31.7 to 7.31.8
Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.31.7 to 7.31.8.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.31.7...v7.31.8)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-13 18:40:08 +00:00
Trevor Buckner
c8742289de Merge pull request #2358 from naturalcrit/dependabot/npm_and_yarn/eslint-8.23.1
Bump eslint from 8.23.0 to 8.23.1
2022-09-13 14:25:01 -04:00
Trevor Buckner
0e40da73f6 Merge pull request #2354 from naturalcrit/dependabot/npm_and_yarn/jest-29.0.3
Bump jest from 29.0.2 to 29.0.3
2022-09-13 14:24:46 -04:00
Trevor Buckner
93b1576de1 Merge pull request #2359 from Gazook89/mongodb-URL-change
Change MongoDB address from localhost to 127.0.0.1
2022-09-13 13:51:02 -04:00
Gazook89
cfdbe06d07 move dir button next to active sort option 2022-09-13 12:26:28 -05:00
Gazook89
46a45a8536 replace sort table with divs and give UI styling 2022-09-13 10:57:28 -05:00
Gazook89
f86ec64714 change localhost to 127.0.0.1
node v16+ better utilizes the address 127.0.01 rather than localhost, at least on MacOS while still working for Windows.
2022-09-13 09:19:34 -05:00
dependabot[bot]
08c7c8b10f Bump eslint from 8.23.0 to 8.23.1
Bumps [eslint](https://github.com/eslint/eslint) from 8.23.0 to 8.23.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.23.0...v8.23.1)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-12 20:01:09 -07:00
dependabot[bot]
8cd896fbfa Bump jest from 29.0.2 to 29.0.3
Bumps [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) from 29.0.2 to 29.0.3.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.0.3/packages/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-12 03:01:21 +00:00
G.Ambatte
abe7d858a8 Merge branch 'master' into showThumbnailOnUserPage-#2331 2022-09-11 12:21:44 +12:00
Trevor Buckner
5e076fc948 Merge pull request #1954 from naturalcrit/SwappableThemes-ReorganizeFolderStructure
Swappable themes
2022-09-09 11:00:57 -04:00
Trevor Buckner
0f566fe912 Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-09-09 10:51:08 -04:00
Trevor Buckner
be8abe9dcb Merge pull request #2349 from naturalcrit/Up-Version-to-v3.2.2
Up version to v3.2.2
2022-09-09 10:48:19 -04:00
Trevor Buckner
8efdf61143 Merge pull request #2348 from naturalcrit/dependabot/npm_and_yarn/mongoose-6.6.0
Bump mongoose from 6.5.5 to 6.6.0
2022-09-08 23:50:58 -04:00
dependabot[bot]
003b9dcd7f Bump mongoose from 6.5.5 to 6.6.0
Bumps [mongoose](https://github.com/Automattic/mongoose) from 6.5.5 to 6.6.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/6.5.5...6.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-09 03:01:35 +00:00
Trevor Buckner
eae5fc9be9 Hide themes behind flag "enable_themes" 2022-09-05 17:05:37 -04:00
Trevor Buckner
c2a5aad1e8 Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-09-05 16:13:11 -04:00
G.Ambatte
4a89d73f73 Update brewItem.less
Co-authored-by: Trevor Buckner <calculuschild@gmail.com>
2022-09-04 16:44:18 +12:00
G.Ambatte
3975c74b2b Add thumbnail styling to BrewItem.less 2022-09-04 00:19:26 +12:00
G.Ambatte
0f1c585567 Add thumbnail functionality to BrewItem 2022-09-04 00:19:05 +12:00
G.Ambatte
1fb3ec4057 Add thumbnail to UserPage data 2022-09-04 00:18:08 +12:00
Trevor Buckner
2c7fdd3993 Remove unused variables from Journal theme 2022-09-03 01:42:38 -04:00
Trevor Buckner
0828a9fe68 Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-09-03 01:38:59 -04:00
Trevor Buckner
66a5f51927 Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-08-31 23:57:46 -04:00
Trevor Buckner
a383995522 Cleaning up some redundant styles in Journal Theme 2022-08-27 21:20:35 -04:00
Trevor Buckner
eb9d76655e Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-08-27 18:24:35 -04:00
Trevor Buckner
fc20d73520 Journal theme "complete"? 2022-08-21 00:03:29 -04:00
Trevor Buckner
fd64215298 Make blank theme load by default behind all themes 2022-08-07 00:37:47 -04:00
Trevor Buckner
9d05ee56a3 Further trim Blank theme. Use :where(.page)
where(.page) lowers specificity so styles can be overwritten by the user style tab without needing `.page`
2022-08-07 00:10:14 -04:00
Trevor Buckner
7ff478b542 Make reset.less have lower specificity 2022-08-07 00:08:58 -04:00
Trevor Buckner
aee0337d01 Trim down the "blank" style a lot. 2022-08-06 13:17:01 -04:00
Trevor Buckner
ddcf34c006 Reorder snippets 2022-08-06 12:09:14 -04:00
Trevor Buckner
44dbb8f285 Fix merging again. 2022-08-04 22:49:52 -04:00
Trevor Buckner
58edf329f5 Remove basic print snippets from PHB theme 2022-08-04 22:32:04 -04:00
Trevor Buckner
0611c67651 Remove standard tables from PHB snippets 2022-08-04 22:23:28 -04:00
Trevor Buckner
3da2d094a0 Fix merging snippets with base snippets. 2022-08-04 22:20:29 -04:00
Trevor Buckner
993bcc2719 Start adding "Blank" theme 2022-07-30 00:28:15 -04:00
Trevor Buckner
947b2f5072 Start adding Journal theme, Add "snippetBase" property 2022-07-23 12:01:34 -04:00
Trevor Buckner
442c5e2d8a Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-07-23 11:39:06 -04:00
Trevor Buckner
5f5ff0023b Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-06-21 16:07:00 -04:00
Trevor Buckner
1e1a3d891a Change let to const 2022-06-21 15:59:28 -04:00
Trevor Buckner
2e27e9f8f6 Update styles/snippets to match current master 2022-06-21 15:53:24 -04:00
Trevor Buckner
9ff5818a0d Remove redundant helper files for DMG snippets 2022-05-18 16:25:44 -04:00
Trevor Buckner
59d267dff8 Remove redundant snippets from DMG theme 2022-05-18 16:23:01 -04:00
Trevor Buckner
8153bf7952 Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-05-18 16:21:20 -04:00
Trevor Buckner
7200889d8c Restore recent snippet changes from after this PR 2022-05-17 23:42:15 -04:00
Trevor Buckner
253db8304a Make dropdown close on clickoutside, not mouseout
Accomplished by adding an onClick event listener to the whole document and then closing if the click was not inside the dropdown.
2022-05-16 23:07:38 -04:00
Trevor Buckner
a17a9ac0a0 lint 2022-05-16 01:41:31 -04:00
Trevor Buckner
4f6555b522 Merge snippets between theme and basetheme
- Current theme has preference over the base theme
- Snippets with the same name are overwritten by the current theme.
- If the overwritten snippet has no `gen` property (or `gen` is falsy), it will remove the base Theme snippet.
- Snippets not overwritten will carry over from base Theme
- New snippets will be added on to base Theme
2022-05-16 01:40:40 -04:00
Trevor Buckner
4167026ca7 Point to new theme location for user page 2022-05-16 00:01:34 -04:00
Trevor Buckner
ef7b8f1ba4 Themes work on Print page 2022-05-15 23:48:23 -04:00
Trevor Buckner
ec57b209b6 Themes work on Share page 2022-05-15 23:36:07 -04:00
Trevor Buckner
1e64ca04d8 BaseTheme is a separate file; not duplicated inside child theme 2022-05-15 23:08:44 -04:00
Trevor Buckner
1f82dbe8ee Make DMG style use CSS variables 2022-05-15 22:45:59 -04:00
G.Ambatte
4f154922c0 Update client/homebrew/pages/accountPage/accountPage.jsx
Co-authored-by: Trevor Buckner <calculuschild@gmail.com>
2022-05-03 22:30:08 +12:00
G.Ambatte
2b1fe5d3fe Update client/homebrew/pages/accountPage/accountPage.jsx
Co-authored-by: Trevor Buckner <calculuschild@gmail.com>
2022-05-03 22:29:53 +12:00
G.Ambatte
03402e4342 Add Google icon
Co-authored-by: Trevor Buckner <calculuschild@gmail.com>
2022-05-03 22:29:33 +12:00
G.Ambatte
1d85eede43 Account information added 2022-05-03 11:38:24 +12:00
G.Ambatte
61f4456842 Styling updates. 2022-05-01 12:58:10 +12:00
G.Ambatte
c925e04f3c Remove unused require 2022-05-01 12:41:10 +12:00
G.Ambatte
00412a70e9 Remove test UI page, add initial Account page 2022-05-01 12:39:19 +12:00
G.Ambatte
0923c50218 Update UI page styling 2022-05-01 12:38:20 +12:00
G.Ambatte
fe536bc9df Initial pass at UI page and styling 2022-04-30 16:54:11 +12:00
G.Ambatte
e8937a285c Add UI route for testing 2022-04-30 16:53:30 +12:00
Trevor Buckner
96e704234c Convert LESS variables to CSS variables 2022-04-18 16:32:56 -04:00
Trevor Buckner
407528bd94 Don't embed base64 images
4+MB down to 17kb CSS file.

Images are only ~1.7MB. They were very bloated as base64
2022-04-18 16:32:35 -04:00
Trevor Buckner
5b107d4e62 Remove unneeded console log 2022-04-18 16:31:23 -04:00
Trevor Buckner
f71dc004c0 Themes list to use object instead of array. 2022-04-15 17:17:13 -04:00
Trevor Buckner
ff1f70afa8 Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-04-02 13:50:18 -04:00
Trevor Buckner
45969127f5 Merge pull request #2070 from Gazook89/z-index-on-dropdown
add z-index to dropdown container.
2022-03-15 21:42:00 -04:00
Gazook89
f13c16bb4f add z-index to dropdown container.
also just format spacing on css rules
2022-03-13 20:40:41 -05:00
Trevor Buckner
438c7eabdc Merge pull request #2065 from Gazook89/Small-Changes-to-Theme-Swapper
Small changes to theme swapper
2022-03-13 01:40:38 -05:00
Trevor Buckner
e12579a2a2 Restore original image size, shift position to not cover text 2022-03-13 01:38:48 -05:00
Gazook89
a6ede58d8e set dropdown items to appear *over* subsequent items
change navdropdown items to position:absolute; so they appear *over* the next metadata items, rather than pushing them down when dropdown is open.
2022-03-11 23:16:08 -06:00
Gazook89
3a82e2a24b fix *suppdorted* typo 2022-03-11 23:11:27 -06:00
Gazook89
28d45b89e0 set mask-image blends to fixed points
fixed blend points allows for different sized metadata panel without inadvertently masking text.
2022-03-11 23:10:50 -06:00
Trevor Buckner
01087ca302 Add preview texture to dropdown options 2022-03-01 11:21:13 -05:00
Trevor Buckner
297365407b Fixed comment showing up on page 2022-03-01 09:30:56 -05:00
Trevor Buckner
8e0629062d Fully disable theme selection when in Legacy mode
Making Legacy a "theme" implies we will add more themes to Legacy, which we aren't planning to.
2022-03-01 00:34:19 -05:00
Trevor Buckner
da5ce35c3c Make themes work on /new 2022-02-11 00:32:05 -05:00
Trevor Buckner
96d9d323d1 Fix merge 2022-02-10 23:42:05 -05:00
Trevor Buckner
dd0112f749 Update to Master 2022-02-10 23:38:33 -05:00
Trevor Buckner
d35c5c2719 Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-02-10 23:36:41 -05:00
Trevor Buckner
f84e2c316f DMG theme added 2022-01-21 00:27:52 -05:00
Trevor Buckner
65335162fc Merge branch 'master' into SwappableThemes-ReorganizeFolderStructure 2022-01-10 21:58:21 -05:00
Trevor Buckner
94157ec4d4 Theme switches on click 2022-01-09 23:19:03 -05:00
Trevor Buckner
87bb682836 Add dropdown selector (not clickable yet) 2022-01-09 22:35:53 -05:00
Trevor Buckner
9f12e2748d Swapping working. Splitting into separate JS bundles doesn't seem to work. 2022-01-02 23:54:48 -05:00
Trevor Buckner
714a425ae5 Split themes into folders by Renderer (Legacy, V3) 2021-12-30 01:21:34 -05:00
Trevor Buckner
183a8035dd Initial file restructuring 2021-12-29 16:42:25 -05:00
191 changed files with 19098 additions and 8360 deletions

View File

@@ -27,7 +27,7 @@ jobs:
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- node/install-npm
- run: sudo npm install -g npm@8.10.0
- node/install-packages:
app-dir: ~/homebrewery
cache-path: node_modules
@@ -55,13 +55,19 @@ jobs:
at: .
# run tests!
- run:
- run:
name: Test - API Unit Tests
command: npm run test:api-unit
- run:
name: Test - Basic
command: npm run test:basic
- run:
- run:
name: Test - Coverage
command: npm run test:coverage
- run:
name: Test - Mustache Spans
command: npm run test:mustache-span
- run:
- run:
name: Test - Routes
command: npm run test:route
@@ -71,4 +77,4 @@ workflows:
- build
- test:
requires:
- build
- build

7
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
contact_links:
- name: /r/Homebrewery Subreddit
url: https://www.reddit.com/r/homebrewery
about: The Homebrewery community on Reddit!
- name: Discord of Many Things
url: https://discord.gg/domt
about: "Join the conversation in the #formatting channel on DoMT!"

View File

@@ -0,0 +1,17 @@
name: Feature Request
description: Have an idea to improve the Homebrewery? Let us know!
labels: ["feature request"]
body:
- type: markdown
attributes:
value: "We'd love to hear your idea! Please be sure to [search the current Issues](https://github.com/naturalcrit/homebrewery/issues) for any duplicate requests."
- type: textarea
id: user-request
attributes:
label: "Your idea:"
description: The best feature requests provide an explanation of the current issue and then an explanation of how it could be improved. Screenshots/images can be pasted right in as well!
validations:
required: true
- type: markdown
attributes:
value: "Please be sure to search for any close matches to your request in the GitHub Issues tracker before opening a new request, thanks!"

View File

@@ -0,0 +1,55 @@
name: General Issue
description: Report an issue unrelated to Saving
body:
- type: markdown
attributes:
value: Please include as much information as possible.
- type: dropdown
id: renderer
attributes:
label: Renderer
description: Which renderer does this issue occur on? If you are unsure, you can check the renderer in the Properties Editor (click the "i" in the Snippet Menu bar above the editor).
options:
- v3
- Legacy
- Both
validations:
required: true
- type: dropdown
id: browser
attributes:
label: Browser
description: Which browser were you using when the issue occurred?
options:
- Chrome
- Firefox
- Edge
- Safari
- other
validations:
required: true
- type: dropdown
id: operating-system
attributes:
label: Operating System
description: Which OS were you using when the issue occurred?
options:
- Windows
- MacOS
- Linux
- other
validations:
required: true
- type: textarea
id: user-description
attributes:
label: "What happened?"
description: Please include any steps you took leading up to the issue and if you can reproduce it. Let us know what you expected to happen, and what did happen.
validations:
required: true
- type: textarea
id: code
attributes:
label: Code
description: Paste in any relevant code snippet below.
render: gfm

26
.github/ISSUE_TEMPLATE/save_issue.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Saving Issue
description: Report an issue Saving
labels: ["Saving"]
body:
- type: markdown
attributes:
value: |
Woops, sorry there was an issue Saving. Please add any detail you can to this report and check back soon!
- type: textarea
id: error-code
attributes:
label: Error Code
render: shell
- type: textarea
id: user-description
attributes:
label: "Your description of what happened:"
validations:
required: true
- type: markdown
attributes:
value: |
Thanks for the report. Here are some steps that may help in the meantime:
1. Refreshing your Google credentials in Homebrewery by signing out, and back in (they expire after one year).
2. Waiting a few minutes and trying again - sometimes there is just a momentary blip in the server.
3. Check the Issues in Github or the /r/homebrewery subreddit to see if others are experiencing the same issue.

3
.gitignore vendored
View File

@@ -11,3 +11,6 @@ config/docker.*
todo.md
startDB.bat
startMViewer.bat
.vscode
coverage

View File

@@ -21,24 +21,29 @@ below.
First, install three programs that The Homebrewery requires to run and retrieve
updates:
1. install [node](https://nodejs.org/en/)
1. install [node](https://nodejs.org/en/), version v16 or higher.
1. install [mongodb](https://www.mongodb.com/try/download/community) (Community version)
For the easiest installation, follow these steps:
1. In the installer, uncheck the option to run as a service.
1. You can install MongoDB Compass if you want a GUI to view your database documents.
1. If you install any version over 6.0, you will have to install [MongoDB Shell](https://www.mongodb.com/try/download/shell).
1. Go to the C:\ drive and create a folder called "data".
1. Inside the "data" folder, create a new folder called "db".
1. Open a command prompt or other terminal and navigate to your MongoDB install folder (C:\Program Files\Mongo\Server\4.4\bin).
1. Open a command prompt or other terminal and navigate to your MongoDB install folder (C:\Program Files\Mongo\Server\6.0\bin).
1. In the command prompt, run "mongod", which will start up your local database server.
1. While MongoD is running, open a second command prompt and navigate to the MongoDB install folder.
1. In the second command prompt, run "mongo", which allows you to edit the database.
1. Type `use homebrewery` to create The Homebrewery database. You should see `switched to db homebrewery`.
1. Type `db.brews.insert({"title":"test"})` to create a blank document. You should see `WriteResult({ "nInserted" : 1 })`.
1. Search in Windows for "Advanced system settings" and open it.
1. Click "Environment variables", find the "path" variable, and double-click to open it.
1. Click "New" and paste in the path to the MongoDB "bin" folder.
1. Click "OK" three times to close all the windows.
1. In the second command prompt, run "mongo", which allows you to edit the database.
1. Type `use homebrewery` to create The Homebrewery database. You should see `switched to db homebrewery`.
1. Type `db.brews.insertOne({"title":"test"})` to create a blank document. You should see `{
acknowledged: true,
insertedId: ObjectId("63c2fce9e5ac5a94fe2410cf")
}`
1. install [git](https://git-scm.com/downloads) (select the option that allows Git to run from the command prompt).
Checkout the repo ([documentation][github-clone-repo-docs-url]):
@@ -51,11 +56,19 @@ git clone https://github.com/naturalcrit/homebrewery.git
Second, you will need to add the environment variable `NODE_ENV=local` to allow
the project to run locally.
You can set this temporarily in your shell of choice:
You can set this **temporarily** (until you close the terminal) in your shell of choice with admin privileges:
* Windows Powershell: `$env:NODE_ENV="local"`
* Windows CMD: `set NODE_ENV=local`
* Linux / macOS: `export NODE_ENV=local`
If you want to add this variable **permanently** the steps are as follows:
1. Search in Windows for "Advanced system settings" and open it.
1. Click "Environment variables".
1. In System Variables, click "New"
1. Click "New" and write `NODE_ENV` as a name and `local` as the value.
1. Click "OK" three times to close all the windows.
This can be undone at any time if needed.
Third, you will need to install the Node dependencies, compile the app, and run
it using the two commands:
@@ -65,6 +78,13 @@ it using the two commands:
You should now be able to go to [http://localhost:8000](http://localhost:8000)
in your browser and use The Homebrewery offline.
If you had any issue at all, here are some links that may be useful:
- [Course](https://learn.mongodb.com/courses/m103-basic-cluster-administration) on cluster administration, useful for beginners
- [Mongo community forums](https://www.mongodb.com/community/forums/)
- Useful Stack Overflow links for your most probable errors: [1](https://stackoverflow.com/questions/44962540/mongod-and-mongo-commands-not-working-on-windows-10), [2](https://stackoverflow.com/questions/15053893/mongo-command-not-recognized-when-trying-to-connect-to-a-mongodb-server/41507803#41507803), [3](https://stackoverflow.com/questions/51224959/mongo-is-not-recognized-as-an-internal-or-external-command-operable-program-o)
If you still have problems, post in [Our Subreddit](https://www.reddit.com/r/homebrewery/) and we will help you.
### Running the application via Docker
Please see the docs here: [README.DOCKER.md](./README.DOCKER.md)

View File

@@ -1,4 +1,23 @@
```css
.beta {
color : white;
padding : 4px 6px;
line-height : 1em;
background : grey;
border-radius : 12px;
font-family : monospace;
font-size : 10px;
font-weight : 800;
margin-top : -5px;
margin-bottom : -5px;
}
.fac {
height: 1em;
line-height: 2em;
margin-bottom: -0.05cm
}
h5 {
font-size: .35cm !important;
}
@@ -7,6 +26,11 @@ h5 {
margin-left: 0px;
}
.page .taskList {
display:block;
break-inside:auto;
}
.taskList li input {
list-style-type : none;
margin-left : -0.52cm;
@@ -14,6 +38,11 @@ h5 {
filter: brightness(1.1) drop-shadow(1px 2px 1px #222);
}
.taskList ul {
margin-bottom: 0px;
margin-top: 0px;
}
.taskList li input[checked] {
filter: sepia(100%) hue-rotate(60deg) saturate(3.5) contrast(4) brightness(1.1) drop-shadow(1px 2px 1px #222);
}
@@ -30,15 +59,250 @@ pre {
margin-top : 0.1cm;
}
.page ul + h5 {
margin-top: 0.25cm;
}
.page p + h5 {
margin-top: 0.25cm;
}
.page .openSans {
font-family: 'Open Sans';
font-size: 0.9em;
}
.page {
padding-bottom: 1.5cm;
}
```
## changelog
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
### Tuesday 28/02/2023 - v3.7.0
{{taskList
{{note
**NOTE:** Some new snippets will now show a {{beta BETA}} tag. Feel free to use them, but be aware we may change how they work depending on your feedback.
}}
##### Calculuschild
* [x] New {{openSans **IMAGES → WATERCOLOR EDGE** {{fac,mask-edge}} }} and {{openSans **WATERCOLOR CORNER** {{fac,mask-corner}} }} snippets for V3, which adds a stylish watercolor texture to the edge of your images! (Thanks to /u/flamableconcrete on Reddit for providing these image masks!)
* [x] Fix site not displaying on iOS devices
##### 5e-Cleric
* [x] New {{openSans **PHB → COVER PAGE** {{fac,book-front-cover}} }} snippet for V3, which adds a stylish coverpage to your brew! (Thanks to /u/Kaiburr_Kath-Hound on Reddit for providing some of these resources!)
##### MichielDeMey (new contribuor!)
* [x] Fix typo in testing scripts
* [x] Fix "mug" image not using HTTPS
Fixes issues [#2687](https://github.com/naturalcrit/homebrewery/issues/2687)
}}
### Saturday 18/02/2023 - v3.6.1
{{taskList
##### G-Ambatte
* [x] Fix users not being removed from Authors list correctly
Fixes issues [#2674](https://github.com/naturalcrit/homebrewery/issues/2674)
}}
### Monday 23/01/2023 - v3.6.0
{{taskList
##### calculuschild
* [x] Fix Google Drive brews sometimes duplicating
Fixes issues [#2603](https://github.com/naturalcrit/homebrewery/issues/2603)
##### Jeddai
* [x] Add unit tests with full coverage for the Homebrewery API
* [x] Add message to refresh the browser if the user is missing an update to the Homebrewery
Fixes issues [#2583](https://github.com/naturalcrit/homebrewery/issues/2583)
##### G-Ambatte
* [x] Auto-compile Themes CSS on development server
##### 5e-Cleric
* [x] Fix cloned brews inheriting the parent view count
}}
\column
### Friday 23/12/2022 - v3.5.0
{{taskList
##### Jeddai
* [x] Only brew owners or invited authors can edit a brew
- Visiting an `/edit` page of a brew that does not list you as an author will result in an error page. Authors can be added to any brew by opening its {{fa,fa-info-circle}} **Properties** menu and typing the author's username (case-sensitive) into the **Invited Authors** bubble.
- Warn user if a newer brew version has been saved on another device
Fixes issues [#1987](https://github.com/naturalcrit/homebrewery/issues/1987)
}}
\page
### Saturday 10/12/2022 - v3.4.2
{{taskList
##### Jeddai
* [x] Fix broken tags editor
* [x] Reduce server load to fix some saving issues
Fixes issues [#2322](https://github.com/naturalcrit/homebrewery/issues/2322)
##### G-Ambatte
* [x] Account page help link for Google Drive errors
Fixes issues [#2520](https://github.com/naturalcrit/homebrewery/issues/2520)
}}
### Monday 05/12/2022 - v3.4.1
{{taskList
##### G-Ambatte
* [x] Fix Account page incorrect last login time
Fixes issues [#2521](https://github.com/naturalcrit/homebrewery/issues/2521)
##### Gazook
* [x] Fix crashing on iOS and Safari browsers
Fixes issues [#2531](https://github.com/naturalcrit/homebrewery/issues/2531)
}}
### Monday 28/11/2022 - v3.4.0
{{taskList
##### G-Ambatte
* [x] Fix for Chrome v108 handling of page size
Fixes issues [#2445](https://github.com/naturalcrit/homebrewery/issues/2445), [#2516](https://github.com/naturalcrit/homebrewery/issues/2516)
* [x] New account page with some user info, at {{openSans **USERNAME {{fa,fa-user}} → ACCOUNT {{fa,fa-user}}**}}
Fixes issues [#2049](https://github.com/naturalcrit/homebrewery/issues/2049), [#2043](https://github.com/naturalcrit/homebrewery/issues/2043)
* [x] Fix "Published/Private Brews" buttons on userpage
Fixes issues [#2449](https://github.com/naturalcrit/homebrewery/issues/2449)
##### Gazook
* [x] Make autosave default on for new users
* [x] Added link to our FAQ at {{openSans **NEED HELP? {{fa,fa-question-circle}} → FAQ {{fa,fa-question-circle}}**}}
* [x] Fix curly blocks freezing with long property lists
Fixes issues [#2393](https://github.com/naturalcrit/homebrewery/issues/2393)
* [x] Items can now be removed from {{openSans **RECENT BREWS** {{fas,fa-history}} }}
Fixes issues [#1918](https://github.com/naturalcrit/homebrewery/issues/1918)
* [x] Curly injector syntax `{blue}` highlighting in editor
Fixes issues [#1670](https://github.com/naturalcrit/homebrewery/issues/1670)
}}
### Thursday 28/10/2022 - v3.3.1
{{taskList
##### Calculuschild
* [x] Fixes to several broken CSS styles from v3.3.0
Fixes issues [#2468](https://github.com/naturalcrit/homebrewery/issues/2468)
##### Jeddai
* [x] Reduce size of thumbnails on social media links
}}
### Friday 19/10/2022 - v3.3.0
{{taskList
##### Calculuschild
* [x] Fix for tables broken by Chrome v106
##### G-Ambatte:
* [x] Fix Table of Contents broken by Chrome v106
Fixes issues [#2437](https://github.com/naturalcrit/homebrewery/issues/2437)
* [x] Show brew thumbnails on user page
Fixes issues [#2331](https://github.com/naturalcrit/homebrewery/issues/2331)
* [x] Allow longer URLs for brew thumbnails
Fixes issues [#2351](https://github.com/naturalcrit/homebrewery/issues/2351)
* [x] Code no longer unfolds when inserting a snippet
Fixes issues [#2135](https://github.com/naturalcrit/homebrewery/issues/2135)
* [x] Fix brew settings being lost on first save
Fixes issues [#2427](https://github.com/naturalcrit/homebrewery/issues/2427)
##### Gazook:
* [x] Several updates to bug reporting and error popups
Fixes issues [#2376](https://github.com/naturalcrit/homebrewery/issues/2376)
* [x] Fixes to userpage search bar
Fixes issues [#1675](https://github.com/naturalcrit/homebrewery/issues/1675), [#2353](https://github.com/naturalcrit/homebrewery/issues/2353)
* [x] Renderer *(legacy / V3)* now shown next to page #
Fixes issues [#1928](https://github.com/naturalcrit/homebrewery/issues/1928)
* [x] Prevent text selection when moving divider bar
Fixes issues [#1632](https://github.com/naturalcrit/homebrewery/issues/1632)
* [x] Tweak Monster Stat Block coloring
Fixes issues [#2123](https://github.com/naturalcrit/homebrewery/issues/2123)
* [x] Added dropdown button to toggle autosave
Fixes issues [#1546](https://github.com/naturalcrit/homebrewery/issues/1546)
}}
### Friday 08/09/2022 - v3.2.2
{{taskList
@@ -59,6 +323,10 @@ Fixes issues [#2317](https://github.com/naturalcrit/homebrewery/issues/2317), [
Fixes issues: [#1797](https://github.com/naturalcrit/homebrewery/issues/1797), [#2315](https://github.com/naturalcrit/homebrewery/issues/2315), [#2326](https://github.com/naturalcrit/homebrewery/issues/2326), [#2328](https://github.com/naturalcrit/homebrewery/issues/2328)
}}
\page
### Wednesday 31/08/2022 - v3.2.1
{{taskList
@@ -85,8 +353,6 @@ Fixes issues [#2317](https://github.com/naturalcrit/homebrewery/issues/2317), [
Fixes issues: [#2301](https://github.com/naturalcrit/homebrewery/issues/2301), [#2303](https://github.com/naturalcrit/homebrewery/issues/2303), [#2121](https://github.com/naturalcrit/homebrewery/issues/2121)
}}
\page
### Saturday 27/08/2022 - v3.2.0
{{taskList

View File

@@ -1,3 +1,4 @@
/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/
require('./brewRenderer.less');
const React = require('react');
const createClass = require('create-react-class');
@@ -13,6 +14,8 @@ const RenderWarnings = require('homebrewery/renderWarnings/renderWarnings.jsx');
const NotificationPopup = require('./notificationPopup/notificationPopup.jsx');
const Frame = require('react-frame-component').default;
const Themes = require('themes/themes.json');
const PAGE_HEIGHT = 1056;
const PPR_THRESHOLD = 50;
@@ -23,6 +26,7 @@ const BrewRenderer = createClass({
text : '',
style : '',
renderer : 'legacy',
theme : '5ePHB',
errors : []
};
},
@@ -105,7 +109,12 @@ const BrewRenderer = createClass({
renderPageInfo : function(){
return <div className='pageInfo' ref='main'>
{this.state.viewablePageNumber + 1} / {this.state.pages.length}
<div>
{this.props.renderer}
</div>
<div>
{this.state.viewablePageNumber + 1} / {this.state.pages.length}
</div>
</div>;
},
@@ -113,7 +122,7 @@ const BrewRenderer = createClass({
if(!this.state.usePPR) return;
return <div className='ppr_msg'>
Partial Page Renderer enabled, because your brew is so large. May effect rendering.
Partial Page Renderer is enabled, because your brew is so large. May affect rendering.
</div>;
},
@@ -125,7 +134,8 @@ const BrewRenderer = createClass({
renderStyle : function() {
if(!this.props.style) return;
return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style> ${this.props.style} </style>` }} />;
//return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>@layer styleTab {\n${this.props.style}\n} </style>` }} />;
return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style>\n${this.props.style}\n</style>` }} />;
},
renderPage : function(pageText, index){
@@ -177,6 +187,9 @@ const BrewRenderer = createClass({
render : function(){
//render in iFrame so broken code doesn't crash the site.
//Also render dummy page while iframe is mounting.
const rendererPath = this.props.renderer == 'V3' ? 'V3' : 'Legacy';
const themePath = this.props.theme ?? '5ePHB';
const baseThemePath = Themes[rendererPath][themePath].baseTheme;
return (
<React.Fragment>
@@ -200,7 +213,11 @@ const BrewRenderer = createClass({
<RenderWarnings />
<NotificationPopup />
</div>
<link href={`${this.props.renderer == 'legacy' ? '/themes/5ePhbLegacy.style.css' : '/themes/5ePhb.style.css'}`} rel='stylesheet'/>
<link href={`/themes/${rendererPath}/Blank/style.css`} rel='stylesheet'/>
{baseThemePath &&
<link href={`/themes/${rendererPath}/${baseThemePath}/style.css`} rel='stylesheet'/>
}
<link href={`/themes/${rendererPath}/${themePath}/style.css`} rel='stylesheet'/>
{/* Apply CSS from Style tab and render pages from Markdown tab */}
{this.state.isMounted
&&

View File

@@ -21,11 +21,17 @@
right : 17px;
bottom : 0;
z-index : 1000;
padding : 8px 10px;
background-color : #333;
font-size : 10px;
font-weight : 800;
color : white;
div {
display: inline-block;
padding : 8px 10px;
&:not(:last-child){
border-right: 1px solid #666;
}
}
}
.ppr_msg{
position : absolute;

View File

@@ -19,11 +19,6 @@ const DEFAULT_STYLE_TEXT = dedent`
color: black;
}`;
const splice = function(str, index, inject){
return str.slice(0, index) + inject + str.slice(index);
};
const Editor = createClass({
displayName : 'Editor',
@@ -37,6 +32,7 @@ const Editor = createClass({
onTextChange : ()=>{},
onStyleChange : ()=>{},
onMetaChange : ()=>{},
reportError : ()=>{},
renderer : 'legacy'
};
@@ -80,19 +76,7 @@ const Editor = createClass({
},
handleInject : function(injectText){
let text;
if(this.isText()) text = this.props.brew.text;
if(this.isStyle()) text = this.props.brew.style ?? DEFAULT_STYLE_TEXT;
const lines = text.split('\n');
const cursorPos = this.refs.codeEditor.getCursorPosition();
lines[cursorPos.line] = splice(lines[cursorPos.line], cursorPos.ch, injectText);
const injectLines = injectText.split('\n');
this.refs.codeEditor.setCursorPosition(cursorPos.line + injectLines.length, cursorPos.ch + injectLines[injectLines.length - 1].length);
if(this.isText()) this.props.onTextChange(lines.join('\n'));
if(this.isStyle()) this.props.onStyleChange(lines.join('\n'));
this.refs.codeEditor?.injectText(injectText, false);
},
handleViewChange : function(newView){
@@ -154,9 +138,17 @@ const Editor = createClass({
codeMirror.addLineClass(lineNumber, 'text', 'columnSplit');
}
// Highlight injectors {style}
if(line.includes('{') && line.includes('}')){
const regex = /(?:^|[^{\n])({(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\2})/gm;
let match;
while ((match = regex.exec(line)) != null) {
codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length }, { className: 'injection' });
}
}
// Highlight inline spans {{content}}
if(line.includes('{{') && line.includes('}}')){
const regex = /{{(?::(?:"[\w,\-()#%. ]*"|[\w\,\-()#%.]*)|[^"'{}\s])*\s*|}}/g;
const regex = /{{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *|}}/g;
let match;
let blockCount = 0;
while ((match = regex.exec(line)) != null) {
@@ -175,7 +167,7 @@ const Editor = createClass({
// Highlight block divs {{\n Content \n}}
let endCh = line.length+1;
const match = line.match(/^ *{{(?::(?:"[\w,\-()#%. ]*"|[\w\,\-()#%.]*)|[^"'{}\s])* *$|^ *}}$/);
const match = line.match(/^ *{{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *$|^ *}}$/);
if(match)
endCh = match.index+match[0].length;
codeMirror.markText({ line: lineNumber, ch: 0 }, { line: lineNumber, ch: endCh }, { className: 'block' });
@@ -300,7 +292,8 @@ const Editor = createClass({
rerenderParent={this.rerenderParent} />
<MetadataEditor
metadata={this.props.brew}
onChange={this.props.onMetaChange} />
onChange={this.props.onMetaChange}
reportError={this.props.reportError}/>
</>;
}
},
@@ -327,6 +320,7 @@ const Editor = createClass({
onInject={this.handleInject}
showEditButtons={this.props.showEditButtons}
renderer={this.props.renderer}
theme={this.props.brew.theme}
undo={this.undo}
redo={this.redo}
historySize={this.historySize()} />

View File

@@ -29,6 +29,10 @@
font-weight : bold;
//font-style: italic;
}
.injection{
color : green;
font-weight : bold;
}
}
.brewJump{

View File

@@ -4,13 +4,23 @@ const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const request = require('superagent');
const request = require('../../utils/request-middleware.js');
const Nav = require('naturalcrit/nav/nav.jsx');
const StringArrayEditor = require('../stringArrayEditor/stringArrayEditor.jsx');
const Themes = require('themes/themes.json');
const validations = require('./validations.js');
const SYSTEMS = ['5e', '4e', '3.5e', 'Pathfinder'];
const homebreweryThumbnail = require('../../thumbnail.png');
const callIfExists = (val, fn, ...args)=>{
if(val[fn]) {
val[fn](...args);
}
};
const MetadataEditor = createClass({
displayName : 'MetadataEditor',
getDefaultProps : function() {
@@ -19,13 +29,16 @@ const MetadataEditor = createClass({
editId : null,
title : '',
description : '',
thumbnail : '',
tags : [],
published : false,
authors : [],
systems : [],
renderer : 'legacy'
renderer : 'legacy',
theme : '5ePHB'
},
onChange : ()=>{}
onChange : ()=>{},
reportError : ()=>{}
};
},
@@ -47,11 +60,27 @@ const MetadataEditor = createClass({
},
handleFieldChange : function(name, e){
this.props.onChange({
...this.props.metadata,
[name] : e.target.value
});
// load validation rules, and check input value against them
const inputRules = validations[name] ?? [];
const validationErr = inputRules.map((rule)=>rule(e.target.value)).filter(Boolean);
// if no validation rules, save to props
if(validationErr.length === 0){
callIfExists(e.target, 'setCustomValidity', '');
this.props.onChange({
...this.props.metadata,
[name] : e.target.value
});
} else {
// if validation issues, display built-in browser error popup with each error.
const errMessage = validationErr.map((err)=>{
return `- ${err}`;
}).join('\n');
callIfExists(e.target, 'setCustomValidity', errMessage);
callIfExists(e.target, 'reportValidity');
}
},
handleSystem : function(system, e){
if(e.target.checked){
this.props.metadata.systems.push(system);
@@ -60,9 +89,12 @@ const MetadataEditor = createClass({
}
this.props.onChange(this.props.metadata);
},
handleRenderer : function(renderer, e){
if(e.target.checked){
this.props.metadata.renderer = renderer;
if(renderer == 'legacy')
this.props.metadata.theme = '5ePHB';
}
this.props.onChange(this.props.metadata);
},
@@ -73,6 +105,12 @@ const MetadataEditor = createClass({
});
},
handleTheme : function(theme){
this.props.metadata.renderer = theme.renderer;
this.props.metadata.theme = theme.path;
this.props.onChange(this.props.metadata);
},
handleDelete : function(){
if(this.props.metadata.authors && this.props.metadata.authors.length <= 1){
if(!confirm('Are you sure you want to delete this brew? Because you are the only owner of this brew, the document will be deleted permanently.')) return;
@@ -84,8 +122,12 @@ const MetadataEditor = createClass({
request.delete(`/api/${this.props.metadata.googleId ?? ''}${this.props.metadata.editId}`)
.send()
.end(function(err, res){
window.location.href = '/';
.end((err, res)=>{
if(err) {
this.props.reportError(err);
} else {
window.location.href = '/';
}
});
},
@@ -139,6 +181,49 @@ const MetadataEditor = createClass({
</div>;
},
renderThemeDropdown : function(){
if(!global.enable_themes) return;
const listThemes = (renderer)=>{
return _.map(_.values(Themes[renderer]), (theme)=>{
return <div className='item' key={''} onClick={()=>this.handleTheme(theme)} title={''}>
{`${theme.renderer} : ${theme.name}`}
<img src={`/themes/${theme.renderer}/${theme.path}/dropdownTexture.png`}/>
<div className='preview'>
<h6>{`${theme.name}`} preview</h6>
<img src={`/themes/${theme.renderer}/${theme.path}/dropdownPreview.png`}/>
</div>
</div>;
});
};
const currentTheme = Themes[`${_.upperFirst(this.props.metadata.renderer)}`][this.props.metadata.theme];
let dropdown;
if(this.props.metadata.renderer == 'legacy') {
dropdown =
<Nav.dropdown className='disabled value' trigger='disabled'>
<div>
{`Themes are not supported in the Legacy Renderer`} <i className='fas fa-caret-down'></i>
</div>
</Nav.dropdown>;
} else {
dropdown =
<Nav.dropdown className='value' trigger='click'>
<div>
{`${_.upperFirst(currentTheme.renderer)} : ${currentTheme.name}`} <i className='fas fa-caret-down'></i>
</div>
{/*listThemes('Legacy')*/}
{listThemes('V3')}
</Nav.dropdown>;
}
return <div className='field themes'>
<label>theme</label>
{dropdown}
</div>;
},
renderRenderOptions : function(){
if(!global.enable_v3) return;
@@ -174,27 +259,33 @@ const MetadataEditor = createClass({
render : function(){
return <div className='metadataEditor'>
<h1 className='sectionHead'>Brew</h1>
<div className='field title'>
<label>title</label>
<input type='text' className='value'
value={this.props.metadata.title}
defaultValue={this.props.metadata.title}
onChange={(e)=>this.handleFieldChange('title', e)} />
</div>
<div className='field description'>
<label>description</label>
<textarea value={this.props.metadata.description} className='value'
onChange={(e)=>this.handleFieldChange('description', e)} />
</div>
<div className='field thumbnail'>
<label>thumbnail</label>
<input type='text'
value={this.props.metadata.thumbnail}
placeholder='my.thumbnail.url'
className='value'
onChange={(e)=>this.handleFieldChange('thumbnail', e)} />
<button className='display' onClick={this.toggleThumbnailDisplay}>
<i className={`fas fa-caret-${this.state.showThumbnail ? 'right' : 'left'}`} />
</button>
<div className='field-group'>
<div className='field-column'>
<div className='field description'>
<label>description</label>
<textarea defaultValue={this.props.metadata.description} className='value'
onChange={(e)=>this.handleFieldChange('description', e)} />
</div>
<div className='field thumbnail'>
<label>thumbnail</label>
<input type='text'
defaultValue={this.props.metadata.thumbnail}
placeholder='https://my.thumbnail.url'
className='value'
onChange={(e)=>this.handleFieldChange('thumbnail', e)} />
<button className='display' onClick={this.toggleThumbnailDisplay}>
<i className={`fas fa-caret-${this.state.showThumbnail ? 'right' : 'left'}`} />
</button>
</div>
</div>
{this.renderThumbnail()}
</div>
@@ -203,8 +294,6 @@ const MetadataEditor = createClass({
values={this.props.metadata.tags}
onChange={(e)=>this.handleFieldChange('tags', e)}/>
{this.renderAuthors()}
<div className='field systems'>
<label>systems</label>
<div className='value'>
@@ -212,8 +301,27 @@ const MetadataEditor = createClass({
</div>
</div>
{this.renderThemeDropdown()}
{this.renderRenderOptions()}
<hr/>
<h1 className='sectionHead'>Authors</h1>
{this.renderAuthors()}
<StringArrayEditor label='invited authors' valuePatterns={[/.+/]}
validators={[(v)=>!this.props.metadata.authors?.includes(v)]}
placeholder='invite author' unique={true}
values={this.props.metadata.invitedAuthors}
notes={['Invited authors are case sensitive.', 'After adding an invited author, send them the edit link. There, they can choose to accept or decline the invitation.']}
onChange={(e)=>this.handleFieldChange('invitedAuthors', e)}/>
<hr/>
<h1 className='sectionHead'>Privacy</h1>
<div className='field publish'>
<label>publish</label>
<div className='value'>

View File

@@ -7,23 +7,56 @@
width : 100%;
padding : 25px;
background-color : #999;
height : calc(100vh - 54px); // 54px is the height of the navbar + snippet bar. probably a better way to dynamic get this.
overflow-y : auto;
.sectionHead {
font-weight: 1000;
margin: 20px 0;
&:first-of-type {
margin-top: 0;
}
}
& > div {
margin-bottom: 10px;
}
.field-group {
display: flex;
width: 100%;
flex-wrap: wrap;
gap: 10px;
}
.field-column {
display: flex;
flex-direction: column;
flex: 5 0 200px;
gap: 10px;
}
.field{
display : flex;
flex-wrap : wrap;
width : 100%;
margin-bottom : 10px;
min-width : 200px;
&>label{
display : inline-block;
vertical-align : top;
width : 80px;
font-size : 0.7em;
font-size : 11px;
font-weight : 800;
line-height : 1.8em;
text-transform : uppercase;
flex : 0 0 auto;
}
&>.value{
flex : 1 1 auto;
min-width : 200px;
width : 50px;
&:invalid {
background : #ffb9b9;
}
}
input[type='text'], textarea {
border : 1px solid gray;
}
&.thumbnail{
height : 1.4em;
@@ -43,22 +76,37 @@
background-color: #777;
}
}
.thumbnail-preview{
position : relative;
width : 80px;
height : min-content;
border : 2px solid white;
margin-left : 5px;
max-height : 115px;
}
&.description {
flex: 1;
textarea.value {
resize : none;
height : auto;
font-family : 'Open Sans', sans-serif;
font-size : 0.8em;
}
}
small {
font-size : 0.6em;
font-style : italic;
}
}
.description.field textarea.value{
resize : none;
height : 5em;
font-family : 'Open Sans', sans-serif;
font-size : 0.8em;
.thumbnail-preview {
position: relative;
justify-self: center;
width: 80px;
height: min-content;
flex: 1 1;
max-height: 115px;
aspect-ratio: 1 / 1;
object-fit: contain;
background-color: #AAA;
}
.systems.field .value{
label{
vertical-align : middle;
@@ -94,10 +142,6 @@
button.unpublish{
.button(@silver);
}
small{
font-size : 0.6em;
font-style : italic;
}
}
.delete.field .value{
@@ -110,8 +154,85 @@
line-height : 1.5em;
}
.themes.field{
font-size : 13.33px;
.navDropdownContainer {
background-color : white;
position : relative;
z-index : 500;
&.disabled {
font-style :italic;
font-style : italic;
background-color : darkgray;
color : dimgray;
}
&>div:first-child {
border : 2px solid rgb(118,118,118);
padding : 6px 3px;
background-color : inherit;
i {
float : right;
}
&:hover {
background-color : @blue;
color : white;
}
}
.navDropdown {
box-shadow : 0px 5px 10px rgba(0, 0, 0, 0.3);
position : absolute;
width : 100%;
.item {
padding : 3px 3px;
border-top : 1px solid rgb(118, 118, 118);
position : relative;
overflow : visible;
background-color : white;
.preview {
display : flex;
flex-direction: column;
background : #ccc;
border-radius : 5px;
box-shadow : 0 0 5px black;
width : 200px;
color :black;
position : absolute;
top : 0;
right : 0;
opacity : 0;
transition : opacity 250ms ease;
z-index : 1;
overflow :hidden;
h6 {
font-weight : 900;
padding-inline:1em;
padding-block :.5em;
border-bottom :2px solid hsl(0,0%,40%);
}
}
&:hover {
background-color : @blue;
color : white;
}
&:hover > .preview {
opacity: 1;
}
>img {
mask-image : linear-gradient(90deg, transparent, black 20%);
-webkit-mask-image : linear-gradient(90deg, transparent, black 20%);
position : absolute;
right : 0;
top : 0px;
width : 50%;
height : 100%;
}
}
}
}
}
.field .list {
display: flex;
flex: 1 0;
flex-wrap: wrap;
> * {

View File

@@ -0,0 +1,34 @@
module.exports = {
title : [
(value)=>{
return value?.length > 100 ? 'Max title length of 100 characters' : null;
}
],
description : [
(value)=>{
return value?.length > 500 ? 'Max description length of 500 characters.' : null;
}
],
thumbnail : [
(value)=>{
return value?.length > 256 ? 'Max URL length of 256 characters.' : null;
},
(value)=>{
if(value?.length == 0){return null;}
try {
Boolean(new URL(value));
return null;
} catch (e) {
return 'Must be a valid URL';
}
}
],
language : [
(value)=>{
return new RegExp(/[a-z]{2,3}(-.*)?/).test(value || '') === false ? 'Invalid language code.' : null;
}
]
};

View File

@@ -4,9 +4,16 @@ const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
//Import all themes
const SnippetsLegacy = require('./snippetsLegacy/snippets.js');
const SnippetsV3 = require('./snippets/snippets.js');
const Themes = require('themes/themes.json');
const ThemeSnippets = {};
ThemeSnippets['Legacy_5ePHB'] = require('themes/Legacy/5ePHB/snippets.js');
ThemeSnippets['V3_5ePHB'] = require('themes/V3/5ePHB/snippets.js');
ThemeSnippets['V3_5eDMG'] = require('themes/V3/5eDMG/snippets.js');
ThemeSnippets['V3_Journal'] = require('themes/V3/Journal/snippets.js');
ThemeSnippets['V3_Blank'] = require('themes/V3/Blank/snippets.js');
const execute = function(val, brew){
if(_.isFunction(val)) return val(brew);
@@ -32,21 +39,63 @@ const Snippetbar = createClass({
getInitialState : function() {
return {
renderer : this.props.renderer
renderer : this.props.renderer,
snippets : []
};
},
componentDidMount : async function() {
const rendererPath = this.props.renderer == 'V3' ? 'V3' : 'Legacy';
const themePath = this.props.theme ?? '5ePHB';
let snippets = _.cloneDeep(ThemeSnippets[`${rendererPath}_${themePath}`]);
snippets = this.compileSnippets(rendererPath, themePath, snippets);
this.setState({
snippets : snippets
});
},
componentDidUpdate : async function(prevProps) {
if(prevProps.renderer != this.props.renderer || prevProps.theme != this.props.theme) {
const rendererPath = this.props.renderer == 'V3' ? 'V3' : 'Legacy';
const themePath = this.props.theme ?? '5ePHB';
let snippets = _.cloneDeep(ThemeSnippets[`${rendererPath}_${themePath}`]);
snippets = this.compileSnippets(rendererPath, themePath, snippets);
this.setState({
snippets : snippets
});
}
},
mergeCustomizer : function(valueA, valueB, key) {
if(key == 'snippets') {
const result = _.reverse(_.unionBy(_.reverse(valueB), _.reverse(valueA), 'name')); // Join snippets together, with preference for the current theme over the base theme
return _.filter(result, 'gen'); //Only keep snippets with a 'gen' property.
}
},
compileSnippets : function(rendererPath, themePath, snippets) {
let compiledSnippets = snippets;
const baseSnippetsPath = Themes[rendererPath][themePath].baseSnippets;
const objB = _.keyBy(compiledSnippets, 'groupName');
if(baseSnippetsPath) {
const objA = _.keyBy(_.cloneDeep(ThemeSnippets[`${rendererPath}_${baseSnippetsPath}`]), 'groupName');
compiledSnippets = _.values(_.mergeWith(objA, objB, this.mergeCustomizer));
compiledSnippets = this.compileSnippets(rendererPath, baseSnippetsPath, _.cloneDeep(compiledSnippets));
} else {
const objA = _.keyBy(_.cloneDeep(ThemeSnippets[`${rendererPath}_Blank`]), 'groupName');
compiledSnippets = _.values(_.mergeWith(objA, objB, this.mergeCustomizer));
}
return compiledSnippets;
},
handleSnippetClick : function(injectedText){
this.props.onInject(injectedText);
},
renderSnippetGroups : function(){
let snippets = [];
if(this.props.renderer === 'V3')
snippets = SnippetsV3.filter((snippetGroup)=>snippetGroup.view === this.props.view);
else
snippets = SnippetsLegacy.filter((snippetGroup)=>snippetGroup.view === this.props.view);
const snippets = this.state.snippets.filter((snippetGroup)=>snippetGroup.view === this.props.view);
return _.map(snippets, (snippetGroup)=>{
return <SnippetGroup
@@ -114,15 +163,23 @@ const SnippetGroup = createClass({
onSnippetClick : function(){},
};
},
handleSnippetClick : function(snippet){
handleSnippetClick : function(e, snippet){
e.stopPropagation();
this.props.onSnippetClick(execute(snippet.gen, this.props.brew));
},
renderSnippets : function(){
return _.map(this.props.snippets, (snippet)=>{
return <div className='snippet' key={snippet.name} onClick={()=>this.handleSnippetClick(snippet)}>
renderSnippets : function(snippets){
return _.map(snippets, (snippet)=>{
return <div className='snippet' key={snippet.name} onClick={(e)=>this.handleSnippetClick(e, snippet)}>
<i className={snippet.icon} />
{snippet.name}
<span className='name'>{snippet.name}</span>
{snippet.experimental && <span className='beta'>beta</span>}
{snippet.subsnippets && <>
<i className='fas fa-caret-right'></i>
<div className='dropdown side'>
{this.renderSnippets(snippet.subsnippets)}
</div></>}
</div>;
});
},
@@ -133,7 +190,7 @@ const SnippetGroup = createClass({
<span className='groupName'>{this.props.groupName}</span>
</div>
<div className='dropdown'>
{this.renderSnippets()}
{this.renderSnippets(this.props.snippets)}
</div>
</div>;
},

View File

@@ -1,4 +1,4 @@
@import (less) './client/icons/customIcons.less';
.snippetBar{
@menuHeight : 25px;
position : relative;
@@ -83,7 +83,7 @@
.snippetGroup{
border-right : 1px solid black;
&:hover{
.dropdown{
&>.dropdown{
visibility : visible;
}
}
@@ -97,15 +97,45 @@
background-color : #ddd;
.snippet{
.animate(background-color);
padding : 5px;
cursor : pointer;
font-size : 10px;
display : flex;
align-items : center;
min-width : max-content;
padding : 5px;
cursor : pointer;
font-size : 10px;
i{
margin-right : 8px;
font-size : 1.2em;
height : 1.2em;
&~i{
margin-right: 0;
margin-left: 5px;
}
}
.name {
margin-right : auto;
}
.beta {
color : white;
padding : 4px 6px;
line-height : 1em;
margin-left : 5px;
align-self : center;
background : grey;
border-radius : 12px;
font-family : monospace;
}
&:hover{
background-color : #999;
&>.dropdown{
visibility : visible;
&.side {
left: 100%;
top: 0%;
margin-left:0;
box-shadow: -1px 1px 2px 0px #999;
}
}
}
}
}

View File

@@ -1,124 +0,0 @@
const _ = require('lodash');
const titles = [
'The Burning Gallows',
'The Ring of Nenlast',
'Below the Blind Tavern',
'Below the Hungering River',
'Before Bahamut\'s Land',
'The Cruel Grave from Within',
'The Strength of Trade Road',
'Through The Raven Queen\'s Worlds',
'Within the Settlement',
'The Crown from Within',
'The Merchant Within the Battlefield',
'Ioun\'s Fading Traveler',
'The Legion Ingredient',
'The Explorer Lure',
'Before the Charming Badlands',
'The Living Dead Above the Fearful Cage',
'Vecna\'s Hidden Sage',
'Bahamut\'s Demonspawn',
'Across Gruumsh\'s Elemental Chaos',
'The Blade of Orcus',
'Beyond Revenge',
'Brain of Insanity',
'Breed Battle!, A New Beginning',
'Evil Lake, A New Beginning',
'Invasion of the Gigantic Cat, Part II',
'Kraken War 2020',
'The Body Whisperers',
'The Diabolical Tales of the Ape-Women',
'The Doctor Immortal',
'The Doctor from Heaven',
'The Graveyard',
'Azure Core',
'Core Battle',
'Core of Heaven: The Guardian of Amazement',
'Deadly Amazement III',
'Dry Chaos IX',
'Gate Thunder',
'Guardian: Skies of the Dark Wizard',
'Lute of Eternity',
'Mercury\'s Planet: Brave Evolution',
'Ruby of Atlantis: The Quake of Peace',
'Sky of Zelda: The Thunder of Force',
'Vyse\'s Skies',
'White Greatness III',
'Yellow Divinity',
'Zidane\'s Ghost'
];
const subtitles = [
'In an ominous universe, a botanist opposes terrorism.',
'In a demon-haunted city, in an age of lies and hate, a physicist tries to find an ancient treasure and battles a mob of aliens.',
'In a land of corruption, two cyberneticists and a dungeon delver search for freedom.',
'In an evil empire of horror, two rangers battle the forces of hell.',
'In a lost city, in an age of sorcery, a librarian quests for revenge.',
'In a universe of illusions and danger, three time travellers and an adventurer search for justice.',
'In a forgotten universe of barbarism, in an era of terror and mysticism, a virtual reality programmer and a spy try to find vengance and battle crime.',
'In a universe of demons, in an era of insanity and ghosts, three bodyguards and a bodyguard try to find vengance.',
'In a kingdom of corruption and battle, seven artificial intelligences try to save the last living fertile woman.',
'In a universe of virutal reality and agony, in an age of ghosts and ghosts, a fortune-teller and a wanderer try to avert the apocalypse.',
'In a crime-infested kingdom, three martial artists quest for the truth and oppose evil.',
'In a terrifying universe of lost souls, in an era of lost souls, eight dancers fight evil.',
'In a galaxy of confusion and insanity, three martial artists and a duke battle a mob of psychics.',
'In an amazing kingdom, a wizard and a secretary hope to prevent the destruction of mankind.',
'In a kingdom of deception, a reporter searches for fame.',
'In a hellish empire, a swordswoman and a duke try to find the ultimate weapon and battle a conspiracy.',
'In an evil galaxy of illusion, in a time of technology and misery, seven psychiatrists battle crime.',
'In a dark city of confusion, three swordswomen and a singer battle lawlessness.',
'In an ominous empire, in an age of hate, two philosophers and a student try to find justice and battle a mob of mages intent on stealing the souls of the innocent.',
'In a kingdom of panic, six adventurers oppose lawlessness.',
'In a land of dreams and hopelessness, three hackers and a cyborg search for justice.',
'On a planet of mysticism, three travelers and a fire fighter quest for the ultimate weapon and oppose evil.',
'In a wicked universe, five seers fight lawlessness.',
'In a kingdom of death, in an era of illusion and blood, four colonists search for fame.',
'In an amazing kingdom, in an age of sorcery and lost souls, eight space pirates quest for freedom.',
'In a cursed empire, five inventors oppose terrorism.',
'On a crime-ridden planet of conspiracy, a watchman and an artificial intelligence try to find love and oppose lawlessness.',
'In a forgotten land, a reporter and a spy try to stop the apocalypse.',
'In a forbidden land of prophecy, a scientist and an archivist oppose a cabal of barbarians intent on stealing the souls of the innocent.',
'On an infernal world of illusion, a grave robber and a watchman try to find revenge and combat a syndicate of mages intent on stealing the source of all magic.',
'In a galaxy of dark magic, four fighters seek freedom.',
'In an empire of deception, six tomb-robbers quest for the ultimate weapon and combat an army of raiders.',
'In a kingdom of corruption and lost souls, in an age of panic, eight planetologists oppose evil.',
'In a galaxy of misery and hopelessness, in a time of agony and pain, five planetologists search for vengance.',
'In a universe of technology and insanity, in a time of sorcery, a computer techician quests for hope.',
'On a planet of dark magic and barbarism, in an age of horror and blasphemy, seven librarians search for fame.',
'In an empire of dark magic, in a time of blood and illusions, four monks try to find the ultimate weapon and combat terrorism.',
'In a forgotten empire of dark magic, six kings try to prevent the destruction of mankind.',
'In a galaxy of dark magic and horror, in an age of hopelessness, four marines and an outlaw combat evil.',
'In a mysterious city of illusion, in an age of computerization, a witch-hunter tries to find the ultimate weapon and opposes an evil corporation.',
'In a damned kingdom of technology, a virtual reality programmer and a fighter seek fame.',
'In a hellish kingdom, in an age of blasphemy and blasphemy, an astrologer searches for fame.',
'In a damned world of devils, an alien and a ranger quest for love and oppose a syndicate of demons.',
'In a cursed galaxy, in a time of pain, seven librarians hope to avert the apocalypse.',
'In a crime-infested galaxy, in an era of hopelessness and panic, three champions and a grave robber try to solve the ultimate crime.'
];
module.exports = ()=>{
return `<style>
.page#p1{ text-align:center; counter-increment: none; }
.page#p1:after{ display:none; }
.page:nth-child(2n) .pageNumber { left: inherit !important; right: 2px !important; }
.page:nth-child(2n+1) .pageNumber { right: inherit !important; left: 2px !important; }
.page:nth-child(2n)::after { transform: scaleX(1); }
.page:nth-child(2n+1)::after { transform: scaleX(-1); }
.page:nth-child(2n) .footnote { left: inherit; text-align: right; }
.page:nth-child(2n+1) .footnote { left: 80px; text-align: left; }
</style>
{{margin-top:225px}}
# ${_.sample(titles)}
{{margin-top:25px}}
{{wide
##### ${_.sample(subtitles)}
}}
\\page`;
};

View File

@@ -9,7 +9,9 @@ const StringArrayEditor = createClass({
label : '',
values : [],
valuePatterns : null,
validators : [],
placeholder : '',
notes : [],
unique : false,
cannotEdit : [],
onChange : ()=>{}
@@ -83,7 +85,8 @@ const StringArrayEditor = createClass({
}
const matchesPatterns = !this.props.valuePatterns || this.props.valuePatterns.some((pattern)=>!!(value || '').match(pattern));
const uniqueIfSet = !this.props.unique || !values.includes(value);
return matchesPatterns && uniqueIfSet;
const passesValidators = !this.props.validators || this.props.validators.every((validator)=>validator(value));
return matchesPatterns && uniqueIfSet && passesValidators;
},
handleValueInputKeyDown : function(event, index) {
@@ -123,17 +126,21 @@ const StringArrayEditor = createClass({
</div>
);
return <div className='field values'>
return <div className='field'>
<label>{this.props.label}</label>
<div className='list'>
{valueElements}
<div className='input-group'>
<input type='text' className={`value ${this.valueIsValid(this.state.temporaryValue) ? '' : 'invalid'}`} placeholder={this.props.placeholder}
value={this.state.temporaryValue}
onKeyDown={(e)=>this.handleValueInputKeyDown(e)}
onChange={(e)=>this.setState({ temporaryValue: e.target.value })}/>
{this.valueIsValid(this.state.temporaryValue) ? <div className='icon steel' onClick={(e)=>{ e.stopPropagation(); this.addValue(this.state.temporaryValue); }}><i className='fa fa-check fa-fw'/></div> : null}
<div style={{ flex: '1 0' }}>
<div className='list'>
{valueElements}
<div className='input-group'>
<input type='text' className={`value ${this.valueIsValid(this.state.temporaryValue) ? '' : 'invalid'}`} placeholder={this.props.placeholder}
value={this.state.temporaryValue}
onKeyDown={(e)=>this.handleValueInputKeyDown(e)}
onChange={(e)=>this.setState({ temporaryValue: e.target.value })}/>
{this.valueIsValid(this.state.temporaryValue) ? <div className='icon steel' onClick={(e)=>{ e.stopPropagation(); this.addValue(this.state.temporaryValue); }}><i className='fa fa-check fa-fw'/></div> : null}
</div>
</div>
{this.props.notes ? this.props.notes.map((n)=><p><small>{n}</small></p>) : null}
</div>
</div>;
}

View File

@@ -11,6 +11,7 @@ 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)=>{
const params = useParams();
@@ -54,30 +55,34 @@ const Homebrew = createClass({
global.account = this.props.account;
global.version = this.props.version;
global.enable_v3 = this.props.enable_v3;
global.enable_themes = this.props.enable_themes;
global.config = this.props.config;
return {};
},
render : function (){
return <Router location={this.props.url}>
<div className='homebrew'>
<Routes>
<Route path='/edit/:id' element={<WithRoute el={EditPage} brew={this.props.brew} />} />
<Route path='/share/:id' element={<WithRoute el={SharePage} brew={this.props.brew} />} />
<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='/legacy' 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>;
return (
<Router location={this.props.url}>
<div className='homebrew'>
<Routes>
<Route path='/edit/:id' element={<WithRoute el={EditPage} brew={this.props.brew} />} />
<Route path='/share/:id' element={<WithRoute el={SharePage} brew={this.props.brew} />} />
<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} uiItems={this.props.brew.uiItems} />} />
<Route path='/legacy' 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>
);
}
});

View File

@@ -6,10 +6,15 @@
height : 100%;
background-color : @steel;
flex-direction : column;
overflow-y : hidden;
.content{
position : relative;
height : calc(~"100% - 29px"); //Navbar height
flex : auto;
overflow-y : hidden;
}
&.listPage .content {
overflow-y : scroll;
}
}
}
}

View File

@@ -70,12 +70,20 @@ const Account = createClass({
{global.account.username}
</Nav.item>
<Nav.item
href={`/user/${global.account.username}`}
href={`/user/${encodeURI(global.account.username)}`}
color='yellow'
icon='fas fa-beer'
>
brews
</Nav.item>
<Nav.item
className='account'
color='orange'
icon='fas fa-user'
href='/account'
>
account
</Nav.item>
<Nav.item
className='logout'
color='red'

View File

@@ -0,0 +1,85 @@
require('./error-navitem.less');
const React = require('react');
const Nav = require('naturalcrit/nav/nav.jsx');
const createClass = require('create-react-class');
const ErrorNavItem = createClass({
getDefaultProps : function() {
return {
error : '',
parent : null
};
},
render : function() {
const clearError = ()=>{
const state = {
error : null
};
if(this.props.parent.state.isSaving) {
state.isSaving = false;
}
this.props.parent.setState(state);
};
const error = this.props.error;
const response = error.response;
const status = response.status;
const message = response.body?.message;
let errMsg = '';
try {
errMsg += `${error.toString()}\n\n`;
errMsg += `\`\`\`\n${error.stack}\n`;
errMsg += `${JSON.stringify(response.error, null, ' ')}\n\`\`\``;
console.log(errMsg);
} catch (e){}
if(status === 409) {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
{message ?? 'Conflict: please refresh to get latest changes'}
</div>
</Nav.item>;
} else if(status === 412) {
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
{message ?? 'Your client is out of date. Please save your changes elsewhere and refresh.'}
</div>
</Nav.item>;
}
if(response.req.url.match(/^\/api.*Google.*$/m)){
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={clearError}>
Looks like your Google credentials have
expired! Visit our log in page to sign out
and sign back in with Google,
then try saving again!
<a target='_blank' rel='noopener noreferrer'
href={`https://www.naturalcrit.com/login?redirect=${window.location.href}`}>
<div className='confirm'>
Sign In
</div>
</a>
<div className='deny'>
Not Now
</div>
</div>
</Nav.item>;
}
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer'>
Looks like there was a problem saving. <br />
Report the issue <a target='_blank' rel='noopener noreferrer' href={`https://github.com/naturalcrit/homebrewery/issues/new?template=save_issue.yml&error-code=${encodeURIComponent(errMsg)}`}>
here
</a>.
</div>
</Nav.item>;
}
});
module.exports = ErrorNavItem;

View File

@@ -0,0 +1,77 @@
.navItem {
&.error {
position : relative;
background-color : @red;
}
.errorContainer{
animation-name: glideDown;
animation-duration: 0.4s;
position : absolute;
top : 100%;
left : 50%;
z-index : 1000;
width : 140px;
padding : 3px;
color : white;
background-color : #333;
border : 3px solid #444;
border-radius : 5px;
transform : translate(-50% + 3px, 10px);
text-align : center;
font-size : 10px;
font-weight : 800;
text-transform : uppercase;
a{
color : @teal;
}
&:before {
content: "";
width: 0px;
height: 0px;
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid transparent;
border-bottom: 10px solid #444;
left: 53px;
top: -23px;
}
&:after {
content: "";
width: 0px;
height: 0px;
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid transparent;
border-bottom: 10px solid #333;
left: 53px;
top: -19px;
}
.deny {
width : 48%;
margin : 1px;
padding : 5px;
background-color : #333;
display : inline-block;
border-left : 1px solid #666;
.animate(background-color);
&:hover{
background-color : red;
}
}
.confirm {
width : 48%;
margin : 1px;
padding : 5px;
background-color : #333;
display : inline-block;
color : white;
.animate(background-color);
&:hover{
background-color : teal;
}
}
}
}

View File

@@ -12,14 +12,20 @@ module.exports = function(props){
</Nav.item>
<Nav.item color='red' icon='fas fa-fw fa-bug'
href={`https://www.reddit.com/r/homebrewery/submit?selftext=true&text=${encodeURIComponent(dedent`
**Browser(s)** :
**Operating System** :
**Legacy or v3 Renderer** :
**Issue** : `)}`}
- **Browser(s)** :
- **Operating System** :
- **Legacy or v3 Renderer** :
- **Issue** : `)}`}
newTab={true}
rel='noopener noreferrer'>
report issue
</Nav.item>
<Nav.item color='green' icon='fas fa-question-circle'
href='/faq'
newTab={true}
rel='noopener noreferrer'>
FAQ
</Nav.item>
<Nav.item color='blue' icon='fas fa-fw fa-file-import'
href='/migrate'
newTab={true}

View File

@@ -55,6 +55,18 @@
text-align : center;
text-transform : initial;
}
.save-menu {
.dropdown {
z-index: 1000;
}
.navItem i.fa-power-off {
color : red;
&.active {
color : rgb(0, 182, 52);
filter : drop-shadow(0 0 2px rgba(0, 182, 52, 0.765))
}
}
}
.patreon.navItem{
border-left : 1px solid #666;
border-right : 1px solid #666;
@@ -78,6 +90,8 @@
width : 100%;
overflow : hidden auto;
max-height : ~"calc(100vh - 28px)";
scrollbar-color : #666 #333;
scrollbar-width : thin;
h4{
display : block;
box-sizing : border-box;
@@ -101,8 +115,36 @@
color : white;
text-decoration : none;
border-top : 1px solid #888;
overflow : clip;
.clear{
display : none;
position : absolute;
top : 50%;
transform : translateY(-50%);
right : 0px;
width : 20px;
height : 100%;
background-color : #333;
opacity : 70%;
border-radius : 3px;
&:hover {
opacity : 100%;
}
i {
text-align : center;
font-size : 10px;
margin : 0;
height :100%;
width :100%;
}
}
&:hover{
background-color : @blue;
.clear{
display : grid;
place-content : center;
}
}
.title{
display : inline-block;

View File

@@ -119,6 +119,25 @@ const RecentItems = createClass({
});
},
removeItem : function(url, evt){
evt.preventDefault();
let edited = JSON.parse(localStorage.getItem(EDIT_KEY) || '[]');
let viewed = JSON.parse(localStorage.getItem(VIEW_KEY) || '[]');
edited = edited.filter((item)=>{ return (item.url !== url);});
viewed = viewed.filter((item)=>{ return (item.url !== url);});
localStorage.setItem(EDIT_KEY, JSON.stringify(edited));
localStorage.setItem(VIEW_KEY, JSON.stringify(viewed));
this.setState({
edit : edited,
view : viewed
});
},
renderDropdown : function(){
if(!this.state.showDropdown) return null;
@@ -127,6 +146,7 @@ const RecentItems = createClass({
return <a href={brew.url} className='item' key={`${brew.id}-${i}`} target='_blank' rel='noopener noreferrer' title={brew.title || '[ no title ]'}>
<span className='title'>{brew.title || '[ no title ]'}</span>
<span className='time'>{Moment(brew.ts).fromNow()}</span>
<div className='clear' title='Remove from Recents' onClick={(e)=>{this.removeItem(`${brew.url}`, e);}}><i className='fas fa-times'></i></div>
</a>;
});
};

View File

@@ -0,0 +1,74 @@
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const moment = require('moment');
const UIPage = require('../basePages/uiPage/uiPage.jsx');
const Nav = require('naturalcrit/nav/nav.jsx');
const Navbar = require('../../navbar/navbar.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const Account = require('../../navbar/account.navitem.jsx');
const NewBrew = require('../../navbar/newbrew.navitem.jsx');
const HelpNavItem = require('../../navbar/help.navitem.jsx');
const NaturalCritIcon = require('naturalcrit/svg/naturalcrit.svg.jsx');
const AccountPage = createClass({
displayName : 'AccountPage',
getDefaultProps : function() {
return {
brew : {},
uiItems : {}
};
},
getInitialState : function() {
return {
uiItems : this.props.uiItems
};
},
renderNavItems : function() {
return <Navbar>
<Nav.section>
<NewBrew />
<HelpNavItem />
<RecentNavItem />
<Account />
</Nav.section>
</Navbar>;
},
renderUiItems : function() {
return <>
<div className='dataGroup'>
<h1>Account Information <i className='fas fa-user'></i></h1>
<p><strong>Username: </strong> {this.props.uiItems.username || 'No user currently logged in'}</p>
<p><strong>Last Login: </strong> {moment(this.props.uiItems.issued).format('dddd, MMMM Do YYYY, h:mm:ss a ZZ') || '-'}</p>
</div>
<div className='dataGroup'>
<h3>Homebrewery Information <NaturalCritIcon /></h3>
<p><strong>Brews on Homebrewery: </strong> {this.props.uiItems.mongoCount}</p>
</div>
<div className='dataGroup'>
<h3>Google Information <i className='fab fa-google-drive'></i></h3>
<p><strong>Linked to Google: </strong> {this.props.uiItems.googleId ? 'YES' : 'NO'}</p>
{this.props.uiItems.googleId &&
<p>
<strong>Brews on Google Drive: </strong> {this.props.uiItems.googleCount ?? <>Unable to retrieve files - <a href='https://github.com/naturalcrit/homebrewery/discussions/1580'>follow these steps to renew your Google credentials.</a></>}
</p>
}
</div>
</>;
},
render : function(){
return <UIPage brew={this.props.brew}>
{this.renderUiItems()}
</UIPage>;
}
});
module.exports = AccountPage;

View File

@@ -4,7 +4,7 @@ const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const moment = require('moment');
const request = require('superagent');
const request = require('../../../../utils/request-middleware.js');
const googleDriveIcon = require('../../../../googleDrive.png');
const dedent = require('dedent-tabs').default;
@@ -18,7 +18,8 @@ const BrewItem = createClass({
description : '',
authors : [],
stubbed : true
}
},
reportError : ()=>{}
};
},
@@ -33,8 +34,12 @@ const BrewItem = createClass({
request.delete(`/api/${this.props.brew.googleId ?? ''}${this.props.brew.editId}`)
.send()
.end(function(err, res){
location.reload();
.end((err, res)=>{
if(err) {
this.props.reportError(err);
} else {
location.reload();
}
});
},
@@ -96,11 +101,15 @@ const BrewItem = createClass({
render : function(){
const brew = this.props.brew;
if(Array.isArray(brew.tags)) { // temporary fix until dud tags are cleaned
brew.tags = brew.tags?.filter(tag => tag); //remove tags that are empty strings
brew.tags = brew.tags?.filter((tag)=>tag); //remove tags that are empty strings
}
const dateFormatString = 'YYYY-MM-DD HH:mm:ss';
return <div className='brewItem'>
{brew.thumbnail &&
<div className='thumbnail' style={{ backgroundImage: `url(${brew.thumbnail})` }} >
</div>
}
<div className='text'>
<h2>{brew.title}</h2>
<p className='description'>{brew.description}</p>
@@ -112,8 +121,8 @@ const BrewItem = createClass({
<div className='brewTags' title={`Tags:\n${brew.tags.join('\n')}`}>
<i className='fas fa-tags'/>
{brew.tags.map((tag, idx)=>{
let matches = tag.match(/^(?:([^:]+):)?([^:]+)$/);
return <span className={matches[1]}>{matches[2]}</span>;
const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/);
return <span key={idx} className={matches[1]}>{matches[2]}</span>;
})}
</div>
</> : <></>

View File

@@ -10,7 +10,7 @@
min-height : 105px;
margin-right : 15px;
margin-bottom : 15px;
padding : 5px 15px 2px 8px;
padding : 5px 15px 2px 6px;
padding-right : 15px;
border : 1px solid #c9ad6a;
border-radius : 5px;
@@ -19,6 +19,20 @@
break-inside : avoid;
box-shadow : 0px 4px 5px 0px #333;
background-color : #cab2802e;
.thumbnail {
position: absolute;
width: 150px;
height: 100%;
top: 0;
right: 0;
z-index: -1;
background-size: contain;
background-repeat: no-repeat;
background-position: right top;
mask-image: linear-gradient(80deg, #0000 20%, #050 40%);
-webkit-mask-image: linear-gradient(80deg, #0000 20%, #050 40%);
opacity: 50%;
}
.text {
min-height : 54px;
h4{

View File

@@ -23,7 +23,8 @@ const ListPage = createClass({
brews : []
}
],
navItems : <></>
navItems : <></>,
reportError : null
};
},
getInitialState : function() {
@@ -81,7 +82,7 @@ const ListPage = createClass({
if(!brews || !brews.length) return <div className='noBrews'>No Brews.</div>;
return _.map(brews, (brew, idx)=>{
return <BrewItem brew={brew} key={idx}/>;
return <BrewItem brew={brew} key={idx} reportError={this.props.reportError}/>;
});
},
@@ -114,15 +115,17 @@ const ListPage = createClass({
},
renderSortOption : function(sortTitle, sortValue){
return <td>
<button
value={`${sortValue}`}
onClick={this.handleSortOptionChange}
className={`${(this.state.sortType == sortValue ? 'active' : '')}`}
>
{`${sortTitle}`}
</button>
</td>;
return <div className={`sort-option ${(this.state.sortType == sortValue ? 'active' : '')}`}>
<button
value={`${sortValue}`}
onClick={this.state.sortType == sortValue ? this.handleSortDirChange : this.handleSortOptionChange}
>
{`${sortTitle}`}
</button>
{this.state.sortType == sortValue &&
<i className={`sortDir fas ${this.state.sortDir == 'asc' ? 'fa-sort-up' : 'fa-sort-down'}`}></i>
}
</div>;
},
handleFilterTextChange : function(e){
@@ -150,7 +153,7 @@ const ListPage = createClass({
},
renderFilterOption : function(){
return <td>
return <div className='filter-option'>
<label>
<i className='fas fa-search'></i>
<input
@@ -160,37 +163,22 @@ const ListPage = createClass({
value={this.state.filterString}
/>
</label>
</td>;
</div>;
},
renderSortOptions : function(){
return <div className='sort-container'>
<table>
<tbody>
<tr>
<td>
<h6>Sort by :</h6>
</td>
{this.renderSortOption('Title', 'alpha')}
{this.renderSortOption('Created Date', 'created')}
{this.renderSortOption('Updated Date', 'updated')}
{this.renderSortOption('Views', 'views')}
{/* {this.renderSortOption('Latest', 'latest')} */}
<td>
<h6>Direction :</h6>
</td>
<td>
<button
onClick={this.handleSortDirChange}
className='sortDir'
>
{`${(this.state.sortDir == 'asc' ? '\u25B2 ASC' : '\u25BC DESC')}`}
</button>
</td>
{this.renderFilterOption()}
</tr>
</tbody>
</table>
<h6>Sort by :</h6>
{this.renderSortOption('Title', 'alpha')}
{this.renderSortOption('Created Date', 'created')}
{this.renderSortOption('Updated Date', 'updated')}
{this.renderSortOption('Views', 'views')}
{/* {this.renderSortOption('Latest', 'latest')} */}
{this.renderFilterOption()}
</div>;
},
@@ -231,12 +219,13 @@ const ListPage = createClass({
render : function(){
return <div className='listPage sitePage'>
<link href='/themes/5ePhb.style.css' rel='stylesheet'/>
<style>@layer V3_5ePHB, bundle;</style>
<link href='/themes/V3/5ePHB/style.css' rel='stylesheet'/>
{this.props.navItems}
{this.renderSortOptions()}
<div className='content V3'>
<div className='phb page'>
{this.renderSortOptions()}
<div className='page'>
{this.renderBrewCollection(this.state.brewCollection)}
</div>
</div>

View File

@@ -10,15 +10,14 @@
-moz-column-width : auto;
-webkit-column-gap : auto;
-moz-column-gap : auto;
height : auto;
min-height : 279.4mm;
margin : 20px auto;
}
.listPage{
.content{
overflow-y : overlay;
.phb{
.noColumns();
height : auto;
min-height : 279.4mm;
margin : 20px auto;
.page{
.noColumns() !important; //Needed to override PHB Theme since this is on a lower @layer
&::after{
display : none;
}
@@ -27,73 +26,101 @@
font-size : 1.3em;
font-style : italic;
}
.brewCollection {
h1:hover{
cursor: pointer;
}
.active::before, .inactive::before {
font-family: 'Font Awesome 5 Free';
font-weight: 900;
font-size: 0.6cm;
padding-right: 0.5em;
}
.active {
color: var(--HB_Color_HeaderText);
}
.active::before {
content: '\f107';
}
.inactive {
color: #707070;
}
.inactive::before {
content: '\f105';
}
}
}
}
.sort-container{
font-family : 'Open Sans', sans-serif;
position : fixed;
top : 35px;
left : calc(50vw - 400px);
border : 2px solid #58180D;
width : 800px;
background-color : #EEE5CE;
padding : 2px;
position : sticky;
top : 0;
left : 0;
width : 100%;
height : 30px;
background-color : #555;
border-top : 1px solid #666;
border-bottom : 1px solid #666;
color : white;
text-align : center;
z-index : 15;
z-index : 500;
display : flex;
justify-content : center;
align-items : baseline;
column-gap : 15px;
row-gap : 5px;
flex-wrap : wrap;
h6{
text-transform : uppercase;
font-family : 'Open Sans', sans-serif;
font-size : 11px;
font-weight : bold;
color : #58180D;
}
table{
margin : 0px;
vertical-align : middle;
tbody tr{
background-color: transparent !important;
i{
padding-right : 5px
}
button{
background-color : transparent;
color : #58180D;
font-family : 'Open Sans', sans-serif;
font-size : 11px;
text-transform : uppercase;
font-weight : normal;
&.active{
font-weight : bold;
border : 2px solid #58180D;
}
&.sortDir{
width : 75px;
}
.sort-option {
display: flex;
align-items: center;
padding: 0 8px;
color: #ccc;
height: 100%;
&:hover{
background-color : #444;
}
&.active {
font-weight: bold;
color: #ddd;
background-color: #333;
button {
color: white;
font-weight: 800;
height: 100%;
& + .sortDir {
padding-left: 5px;
}
}
}
}
h1 {
cursor: pointer;
&.active {
color: #58180D;
}
&.inactive {
color: #707070;
}
&.active::before, &.inactive::before {
font-family: 'Font Awesome 5 Free';
font-weight: 900;
font-size: 0.6cm;
padding-right: 0.5em;
}
&.active::before {
content: '\f107';
}
&.inactive::before {
content: '\f105';
.filter-option {
margin-left: 20px;
background-color : transparent !important;
font-size : 11px;
i{
padding-right : 5px;
}
}
button{
background-color : transparent;
font-family : 'Open Sans', sans-serif;
text-transform : uppercase;
font-weight : normal;
font-size : 11px;
color : #ccc;
padding : 0;
}
}
}

View File

@@ -0,0 +1,38 @@
require('./uiPage.less');
const React = require('react');
const createClass = require('create-react-class');
const Nav = require('naturalcrit/nav/nav.jsx');
const Navbar = require('../../../navbar/navbar.jsx');
const NewBrewItem = require('../../../navbar/newbrew.navitem.jsx');
const HelpNavItem = require('../../../navbar/help.navitem.jsx');
const RecentNavItem = require('../../../navbar/recent.navitem.jsx').both;
const Account = require('../../../navbar/account.navitem.jsx');
const UIPage = createClass({
displayName : 'UIPage',
render : function(){
return <div className='uiPage sitePage'>
<Navbar>
<Nav.section>
<Nav.item className='brewTitle'>{this.props.brew.title}</Nav.item>
</Nav.section>
<Nav.section>
<NewBrewItem />
<HelpNavItem />
<RecentNavItem />
<Account />
</Nav.section>
</Navbar>
<div className='content'>
{this.props.children}
</div>
</div>;
}
});
module.exports = UIPage;

View File

@@ -0,0 +1,47 @@
.uiPage{
.content{
overflow-y : hidden;
width : 90vw;
background-color: #f0f0f0;
font-family: 'Open Sans';
margin-left: auto;
margin-right: auto;
margin-top: 25px;
padding: 2% 4%;
font-size: 0.8em;
line-height: 1.8em;
.dataGroup{
padding: 6px 20px 15px;
border: 2px solid black;
border-radius: 5px;
margin: 5px 0px;
}
h1, h2, h3, h4{
font-weight: 900;
text-transform: uppercase;
margin: 0.5em 30% 0.25em 0;
border-bottom: 2px solid slategrey;
}
h1 {
font-size: 2em;
border-bottom: 2px solid darkslategrey;
margin-bottom: 0.5em;
margin-right: 0;
}
h2 {
font-size: 1.75em;
}
h3 {
font-size: 1.5em;
svg {
width: 19px;
}
}
h4 {
font-size: 1.25em;
}
strong {
font-weight: bold;
}
}
}

View File

@@ -3,7 +3,7 @@ require('./editPage.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const request = require('superagent');
const request = require('../../utils/request-middleware.js');
const { Meta } = require('vitreum/headtags');
const Nav = require('naturalcrit/nav/nav.jsx');
@@ -12,6 +12,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 ErrorNavItem = require('../../navbar/error-navitem.jsx');
const Account = require('../../navbar/account.navitem.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
@@ -21,6 +22,8 @@ const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
const Markdown = require('naturalcrit/markdown.js');
const { DEFAULT_BREW_LOAD } = require('../../../../server/brewDefaults.js');
const googleDriveActive = require('../../googleDrive.png');
const googleDriveInactive = require('../../googleDriveMono.png');
@@ -30,24 +33,7 @@ const EditPage = createClass({
displayName : 'EditPage',
getDefaultProps : function() {
return {
brew : {
text : '',
style : '',
shareId : null,
editId : null,
createdAt : null,
updatedAt : null,
gDrive : false,
trashed : false,
title : '',
description : '',
tags : '',
published : false,
authors : [],
systems : [],
renderer : 'legacy'
}
brew : DEFAULT_BREW_LOAD
};
},
@@ -60,9 +46,12 @@ const EditPage = createClass({
alertLoginToTransfer : false,
saveGoogle : this.props.brew.googleId ? true : false,
confirmGoogleTransfer : false,
errors : null,
error : null,
htmlErrors : Markdown.validate(this.props.brew.text),
url : ''
url : '',
autoSave : true,
autoSaveWarning : false,
unsavedTime : new Date()
};
},
savedBrew : null,
@@ -74,7 +63,14 @@ const EditPage = createClass({
this.savedBrew = JSON.parse(JSON.stringify(this.props.brew)); //Deep copy
this.trySave();
this.setState({ autoSave: JSON.parse(localStorage.getItem('AUTOSAVE_ON')) ?? true }, ()=>{
if(this.state.autoSave){
this.trySave();
} else {
this.setState({ autoSaveWarning: true });
}
});
window.onbeforeunload = ()=>{
if(this.state.isSaving || this.state.isPending){
return 'You have unsaved changes!';
@@ -117,14 +113,14 @@ const EditPage = createClass({
brew : { ...prevState.brew, text: text },
isPending : true,
htmlErrors : htmlErrors
}), ()=>this.trySave());
}), ()=>{if(this.state.autoSave) this.trySave();});
},
handleStyleChange : function(style){
this.setState((prevState)=>({
brew : { ...prevState.brew, style: style },
isPending : true
}), ()=>this.trySave());
}), ()=>{if(this.state.autoSave) this.trySave();});
},
handleMetaChange : function(metadata){
@@ -134,7 +130,7 @@ const EditPage = createClass({
...metadata
},
isPending : true,
}), ()=>this.trySave());
}), ()=>{if(this.state.autoSave) this.trySave();});
},
@@ -161,7 +157,10 @@ const EditPage = createClass({
this.setState((prevState)=>({
confirmGoogleTransfer : !prevState.confirmGoogleTransfer
}));
this.clearErrors();
this.setState({
error : null,
isSaving : false
});
},
closeAlerts : function(event){
@@ -177,24 +176,16 @@ const EditPage = createClass({
this.setState((prevState)=>({
saveGoogle : !prevState.saveGoogle,
isSaving : false,
errors : null
error : null
}), ()=>this.save());
},
clearErrors : function(){
this.setState({
errors : null,
isSaving : false
});
},
save : async function(){
if(this.debounceSave && this.debounceSave.cancel) this.debounceSave.cancel();
this.setState((prevState)=>({
isSaving : true,
errors : null,
error : null,
htmlErrors : Markdown.validate(prevState.brew.text)
}));
@@ -209,8 +200,9 @@ const EditPage = createClass({
.send(brew)
.catch((err)=>{
console.log('Error Updating Local Brew');
this.setState({ errors: err });
this.setState({ error: err });
});
if(!res) return;
this.savedBrew = res.body;
history.replaceState(null, null, `/edit/${this.savedBrew.editId}`);
@@ -219,10 +211,12 @@ const EditPage = createClass({
brew : { ...prevState.brew,
googleId : this.savedBrew.googleId ? this.savedBrew.googleId : null,
editId : this.savedBrew.editId,
shareId : this.savedBrew.shareId
shareId : this.savedBrew.shareId,
version : this.savedBrew.version
},
isPending : false,
isSaving : false,
isPending : false,
isSaving : false,
unsavedTime : new Date()
}));
},
@@ -268,63 +262,15 @@ const EditPage = createClass({
},
renderSaveButton : function(){
if(this.state.errors){
let errMsg = '';
try {
errMsg += `${this.state.errors.toString()}\n\n`;
errMsg += `\`\`\`\n${this.state.errors.stack}\n`;
errMsg += `${JSON.stringify(this.state.errors.response.error, null, ' ')}\n\`\`\``;
console.log(errMsg);
} catch (e){}
if(this.state.autoSaveWarning && this.hasChanges()){
this.setAutosaveWarning();
const elapsedTime = Math.round((new Date() - this.state.unsavedTime) / 1000 / 60);
const text = elapsedTime == 0 ? 'Autosave is OFF.' : `Autosave is OFF, and you haven't saved for ${elapsedTime} minutes.`;
// if(this.state.errors.status == '401'){
// return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
// Oops!
// <div className='errorContainer' onClick={this.clearErrors}>
// You must be signed in to a Google account
// to save this to<br />Google Drive!<br />
// <a target='_blank' rel='noopener noreferrer'
// href={`https://www.naturalcrit.com/login?redirect=${this.state.url}`}>
// <div className='confirm'>
// Sign In
// </div>
// </a>
// <div className='deny'>
// Not Now
// </div>
// </div>
// </Nav.item>;
// }
if(this.state.errors.response.req.url.match(/^\/api.*Google.*$/m)){
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={this.clearErrors}>
Looks like your Google credentials have
expired! Visit our log in page to sign out
and sign back in with Google,
then try saving again!
<a target='_blank' rel='noopener noreferrer'
href={`https://www.naturalcrit.com/login?redirect=${this.state.url}`}>
<div className='confirm'>
Sign In
</div>
</a>
<div className='deny'>
Not Now
</div>
</div>
</Nav.item>;
}
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
return <Nav.item className='save error' icon='fas fa-exclamation-circle'>
Reminder...
<div className='errorContainer'>
Looks like there was a problem saving. <br />
Report the issue <a target='_blank' rel='noopener noreferrer'
href={`https://github.com/naturalcrit/homebrewery/issues/new?body=${encodeURIComponent(errMsg)}`}>
here
</a>.
{text}
</div>
</Nav.item>;
}
@@ -335,11 +281,42 @@ const EditPage = createClass({
if(this.state.isPending && this.hasChanges()){
return <Nav.item className='save' onClick={this.save} color='blue' icon='fas fa-save'>Save Now</Nav.item>;
}
if(!this.state.isPending && !this.state.isSaving && this.state.autoSave){
return <Nav.item className='save saved'>auto-saved.</Nav.item>;
}
if(!this.state.isPending && !this.state.isSaving){
return <Nav.item className='save saved'>saved.</Nav.item>;
}
},
handleAutoSave : function(){
if(this.warningTimer) clearTimeout(this.warningTimer);
this.setState((prevState)=>({
autoSave : !prevState.autoSave,
autoSaveWarning : prevState.autoSave
}), ()=>{
localStorage.setItem('AUTOSAVE_ON', JSON.stringify(this.state.autoSave));
});
},
setAutosaveWarning : function(){
setTimeout(()=>this.setState({ autoSaveWarning: false }), 4000); // 4 seconds to display
this.warningTimer = setTimeout(()=>{this.setState({ autoSaveWarning: true });}, 900000); // 15 minutes between warnings
this.warningTimer;
},
errorReported : function(error) {
this.setState({
error
});
},
renderAutoSaveButton : function(){
return <Nav.item onClick={this.handleAutoSave}>
Autosave <i className={this.state.autoSave ? 'fas fa-power-off active' : 'fas fa-power-off'}></i>
</Nav.item>;
},
processShareId : function() {
return this.state.brew.googleId && !this.state.brew.stubbed ?
this.state.brew.googleId + this.state.brew.shareId :
@@ -378,7 +355,13 @@ const EditPage = createClass({
<Nav.section>
{this.renderGoogleDriveIcon()}
{this.renderSaveButton()}
{this.state.error ?
<ErrorNavItem error={this.state.error} parent={this}></ErrorNavItem> :
<Nav.dropdown className='save-menu'>
{this.renderSaveButton()}
{this.renderAutoSaveButton()}
</Nav.dropdown>
}
<NewBrew />
<HelpNavItem/>
<Nav.dropdown>
@@ -416,9 +399,10 @@ const EditPage = createClass({
onTextChange={this.handleTextChange}
onStyleChange={this.handleStyleChange}
onMetaChange={this.handleMetaChange}
reportError={this.errorReported}
renderer={this.state.brew.renderer}
/>
<BrewRenderer text={this.state.brew.text} style={this.state.brew.style} renderer={this.state.brew.renderer} errors={this.state.htmlErrors} />
<BrewRenderer text={this.state.brew.text} style={this.state.brew.style} renderer={this.state.brew.renderer} theme={this.state.brew.theme} errors={this.state.htmlErrors} />
</SplitPane>
</div>
</div>;

View File

@@ -13,10 +13,6 @@
cursor : initial;
color : #666;
}
&.error{
position : relative;
background-color : @red;
}
}
.googleDriveStorage {
position : relative;
@@ -26,74 +22,4 @@
padding : 0px;
margin : -5px;
}
.errorContainer{
animation-name: glideDown;
animation-duration: 0.4s;
position : absolute;
top : 100%;
left : 50%;
z-index : 100000;
width : 140px;
padding : 3px;
color : white;
background-color : #333;
border : 3px solid #444;
border-radius : 5px;
transform : translate(-50% + 3px, 10px);
text-align : center;
font-size : 10px;
font-weight : 800;
text-transform : uppercase;
a{
color : @teal;
}
&:before {
content: "";
width: 0px;
height: 0px;
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid transparent;
border-bottom: 10px solid #444;
left: 53px;
top: -23px;
}
&:after {
content: "";
width: 0px;
height: 0px;
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid transparent;
border-bottom: 10px solid #333;
left: 53px;
top: -19px;
}
.deny {
width : 48%;
margin : 1px;
padding : 5px;
background-color : #333;
display : inline-block;
border-left : 1px solid #666;
.animate(background-color);
&:hover{
background-color : red;
}
}
.confirm {
width : 48%;
margin : 1px;
padding : 5px;
background-color : #333;
display : inline-block;
color : white;
.animate(background-color);
&:hover{
background-color : teal;
}
}
}
}

View File

@@ -3,7 +3,7 @@ const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const cx = require('classnames');
const request = require('superagent');
const request = require('../../utils/request-middleware.js');
const { Meta } = require('vitreum/headtags');
const Nav = require('naturalcrit/nav/nav.jsx');
@@ -12,37 +12,38 @@ const NewBrewItem = require('../../navbar/newbrew.navitem.jsx');
const HelpNavItem = require('../../navbar/help.navitem.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const AccountNavItem = require('../../navbar/account.navitem.jsx');
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
const SplitPane = require('naturalcrit/splitPane/splitPane.jsx');
const Editor = require('../../editor/editor.jsx');
const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
const { DEFAULT_BREW } = require('../../../../server/brewDefaults.js');
const HomePage = createClass({
displayName : 'HomePage',
getDefaultProps : function() {
return {
brew : {
text : '',
},
ver : '0.0.0'
brew : DEFAULT_BREW,
ver : '0.0.0'
};
},
getInitialState : function() {
return {
brew : this.props.brew,
welcomeText : this.props.brew.text
welcomeText : this.props.brew.text,
error : undefined
};
},
handleSave : function(){
request.post('/api')
.send({
text : this.state.brew.text
})
.send(this.state.brew)
.end((err, res)=>{
if(err) return;
if(err) {
this.setState({ error: err });
return;
}
const brew = res.body;
window.location = `/edit/${brew.editId}`;
});
@@ -58,6 +59,10 @@ const HomePage = createClass({
renderNavbar : function(){
return <Navbar ver={this.props.ver}>
<Nav.section>
{this.state.error ?
<ErrorNavItem error={this.state.error} parent={this}></ErrorNavItem> :
null
}
<NewBrewItem />
<HelpNavItem />
<RecentNavItem />

View File

@@ -40,4 +40,11 @@
right : 350px;
}
}
.navItem.save{
background-color: @orange;
&:hover{
background-color: @green;
}
}
}

View File

@@ -36,7 +36,7 @@ After clicking the "Print" item in the navbar a new page will open and a print d
If you want to save ink or have a monochrome printer, add the **PRINT → {{fas,fa-tint}} Ink Friendly** snippet to your brew!
}}
![homebrew mug](http://i.imgur.com/hMna6G0.png) {position:absolute,bottom:20px,left:130px,width:220px}
![homebrew mug](https://i.imgur.com/hMna6G0.png) {position:absolute,bottom:20px,left:130px,width:220px}
{{artist,bottom:160px,left:100px
##### Homebrew Mug

View File

@@ -3,13 +3,14 @@ require('./newPage.less');
const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
const request = require('superagent');
const request = require('../../utils/request-middleware.js');
const Markdown = require('naturalcrit/markdown.js');
const Nav = require('naturalcrit/nav/nav.jsx');
const Navbar = require('../../navbar/navbar.jsx');
const AccountNavItem = require('../../navbar/account.navitem.jsx');
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const HelpNavItem = require('../../navbar/help.navitem.jsx');
@@ -17,6 +18,8 @@ const SplitPane = require('naturalcrit/splitPane/splitPane.jsx');
const Editor = require('../../editor/editor.jsx');
const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
const { DEFAULT_BREW } = require('../../../../server/brewDefaults.js');
const BREWKEY = 'homebrewery-new';
const STYLEKEY = 'homebrewery-new-style';
const METAKEY = 'homebrewery-new-meta';
@@ -26,34 +29,18 @@ const NewPage = createClass({
displayName : 'NewPage',
getDefaultProps : function() {
return {
brew : {
text : '',
style : undefined,
title : '',
description : '',
renderer : 'V3'
}
brew : DEFAULT_BREW
};
},
getInitialState : function() {
let brew = this.props.brew;
if(this.props.brew.shareId) {
brew = {
text : brew.text ?? '',
style : brew.style ?? undefined,
title : brew.title ?? '',
description : brew.description ?? '',
renderer : brew.renderer ?? 'legacy'
};
}
const brew = this.props.brew;
return {
brew : brew,
isSaving : false,
saveGoogle : (global.account && global.account.googleId ? true : false),
errors : null,
error : null,
htmlErrors : Markdown.validate(brew.text)
};
},
@@ -73,6 +60,7 @@ const NewPage = createClass({
// brew.title = metaStorage?.title || this.state.brew.title;
// brew.description = metaStorage?.description || this.state.brew.description;
brew.renderer = metaStorage?.renderer ?? brew.renderer;
brew.theme = metaStorage?.theme ?? brew.theme;
this.setState({
brew : brew
@@ -80,8 +68,9 @@ const NewPage = createClass({
}
localStorage.setItem(BREWKEY, brew.text);
localStorage.setItem(STYLEKEY, brew.style);
localStorage.setItem(METAKEY, JSON.stringify({ 'renderer': brew.renderer }));
if(brew.style)
localStorage.setItem(STYLEKEY, brew.style);
localStorage.setItem(METAKEY, JSON.stringify({ 'renderer': brew.renderer, 'theme': brew.theme }));
},
componentWillUnmount : function() {
document.removeEventListener('keydown', this.handleControlKeys);
@@ -129,18 +118,11 @@ const NewPage = createClass({
localStorage.setItem(METAKEY, JSON.stringify({
// 'title' : this.state.brew.title,
// 'description' : this.state.brew.description,
'renderer' : this.state.brew.renderer
'renderer' : this.state.brew.renderer,
'theme' : this.state.brew.theme
}));
},
clearErrors : function(){
this.setState({
errors : null,
isSaving : false
});
},
save : async function(){
this.setState({
isSaving : true
@@ -163,7 +145,7 @@ const NewPage = createClass({
.send(brew)
.catch((err)=>{
console.log(err);
this.setState({ isSaving: false, errors: err });
this.setState({ isSaving: false, error: err });
});
if(!res) return;
@@ -175,67 +157,6 @@ const NewPage = createClass({
},
renderSaveButton : function(){
if(this.state.errors){
let errMsg = '';
try {
errMsg += `${this.state.errors.toString()}\n\n`;
errMsg += `\`\`\`\n${this.state.errors.stack}\n`;
errMsg += `${JSON.stringify(this.state.errors.response.error, null, ' ')}\n\`\`\``;
console.log(errMsg);
} catch (e){}
// if(this.state.errors.status == '401'){
// return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
// Oops!
// <div className='errorContainer' onClick={this.clearErrors}>
// You must be signed in to a Google account
// to save this to<br />Google Drive!<br />
// <a target='_blank' rel='noopener noreferrer'
// href={`https://www.naturalcrit.com/login?redirect=${this.state.url}`}>
// <div className='confirm'>
// Sign In
// </div>
// </a>
// <div className='deny'>
// Not Now
// </div>
// </div>
// </Nav.item>;
// }
if(this.state.errors.response.req.url.match(/^\/api.*Google.*$/m)){
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer' onClick={this.clearErrors}>
Looks like your Google credentials have
expired! Visit our log in page to sign out
and sign back in with Google,
then try saving again!
<a target='_blank' rel='noopener noreferrer'
href={`https://www.naturalcrit.com/login?redirect=${this.state.url}`}>
<div className='confirm'>
Sign In
</div>
</a>
<div className='deny'>
Not Now
</div>
</div>
</Nav.item>;
}
return <Nav.item className='save error' icon='fas fa-exclamation-triangle'>
Oops!
<div className='errorContainer'>
Looks like there was a problem saving. <br />
Report the issue <a target='_blank' rel='noopener noreferrer'
href={`https://github.com/naturalcrit/homebrewery/issues/new?body=${encodeURIComponent(errMsg)}`}>
here
</a>.
</div>
</Nav.item>;
}
if(this.state.isSaving){
return <Nav.item icon='fas fa-spinner fa-spin' className='save'>
save...
@@ -265,7 +186,10 @@ const NewPage = createClass({
</Nav.section>
<Nav.section>
{this.renderSaveButton()}
{this.state.error ?
<ErrorNavItem error={this.state.error} parent={this}></ErrorNavItem> :
this.renderSaveButton()
}
{this.renderLocalPrintButton()}
<HelpNavItem />
<RecentNavItem />
@@ -287,7 +211,7 @@ const NewPage = createClass({
onMetaChange={this.handleMetaChange}
renderer={this.state.brew.renderer}
/>
<BrewRenderer text={this.state.brew.text} style={this.state.brew.style} renderer={this.state.brew.renderer} errors={this.state.htmlErrors}/>
<BrewRenderer text={this.state.brew.text} style={this.state.brew.style} renderer={this.state.brew.renderer} theme={this.state.brew.theme} errors={this.state.htmlErrors}/>
</SplitPane>
</div>
</div>;

View File

@@ -4,79 +4,5 @@
&:hover{
background-color: @green;
}
&.error{
position : relative;
background-color : @red;
}
}
.errorContainer{
animation-name: glideDown;
animation-duration: 0.4s;
position : absolute;
top : 100%;
left : 50%;
z-index : 100000;
width : 140px;
padding : 3px;
color : white;
background-color : #333;
border : 3px solid #444;
border-radius : 5px;
transform : translate(-50% + 3px, 10px);
text-align : center;
font-size : 10px;
font-weight : 800;
text-transform : uppercase;
a{
color : @teal;
}
&:before {
content: "";
width: 0px;
height: 0px;
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid transparent;
border-bottom: 10px solid #444;
left: 53px;
top: -23px;
}
&:after {
content: "";
width: 0px;
height: 0px;
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid transparent;
border-bottom: 10px solid #333;
left: 53px;
top: -19px;
}
.deny {
width : 48%;
margin : 1px;
padding : 5px;
background-color : #333;
display : inline-block;
border-left : 1px solid #666;
.animate(background-color);
&:hover{
background-color : red;
}
}
.confirm {
width : 48%;
margin : 1px;
padding : 5px;
background-color : #333;
display : inline-block;
color : white;
.animate(background-color);
&:hover{
background-color : teal;
}
}
}
}

View File

@@ -7,6 +7,8 @@ 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';
@@ -27,9 +29,10 @@ const PrintPage = createClass({
getInitialState : function() {
return {
brew : {
text : this.props.brew.text || '',
style : this.props.brew.style || undefined,
renderer : this.props.brew.renderer || 'legacy'
text : this.props.brew.text || '',
style : this.props.brew.style || undefined,
renderer : this.props.brew.renderer || 'legacy',
theme : this.props.brew.theme || '5ePHB'
}
};
},
@@ -45,7 +48,8 @@ const PrintPage = createClass({
brew : {
text : brewStorage,
style : styleStorage,
renderer : metaStorage?.renderer || 'legacy'
renderer : metaStorage?.renderer || 'legacy',
theme : metaStorage?.theme || '5ePHB'
}
};
});
@@ -56,7 +60,8 @@ const PrintPage = createClass({
renderStyle : function() {
if(!this.state.brew.style) return;
return <div style={{ display: 'none' }} dangerouslySetInnerHTML={{ __html: `<style> ${this.state.brew.style} </style>` }} />;
//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(){
@@ -82,9 +87,17 @@ const PrintPage = createClass({
},
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={`${this.state.brew.renderer == 'legacy' ? '/themes/5ePhbLegacy.style.css' : '/themes/5ePhb.style.css'}`} rel='stylesheet'/>
<link href={`/themes/${rendererPath}/Blank/style.css`} rel='stylesheet'/>
{baseThemePath &&
<link href={`/themes/${rendererPath}/${baseThemePath}/style.css`} rel='stylesheet'/>
}
<link href={`/themes/${rendererPath}/${themePath}/style.css`} rel='stylesheet'/>
{/* Apply CSS from Style tab */}
{this.renderStyle()}
<div className='pages' ref='pages'>

View File

@@ -12,21 +12,13 @@ const Account = require('../../navbar/account.navitem.jsx');
const BrewRenderer = require('../../brewRenderer/brewRenderer.jsx');
const { DEFAULT_BREW_LOAD } = require('../../../../server/brewDefaults.js');
const SharePage = createClass({
displayName : 'SharePage',
getDefaultProps : function() {
return {
brew : {
title : '',
text : '',
style : '',
shareId : null,
createdAt : null,
updatedAt : null,
views : 0,
renderer : ''
}
brew : DEFAULT_BREW_LOAD
};
},
@@ -86,7 +78,7 @@ const SharePage = createClass({
</Navbar>
<div className='content'>
<BrewRenderer text={this.props.brew.text} style={this.props.brew.style} renderer={this.props.brew.renderer} />
<BrewRenderer text={this.props.brew.text} style={this.props.brew.style} renderer={this.props.brew.renderer} theme={this.props.brew.theme} />
</div>
</div>;
}

View File

@@ -12,6 +12,7 @@ const RecentNavItem = require('../../navbar/recent.navitem.jsx').both;
const Account = require('../../navbar/account.navitem.jsx');
const NewBrew = require('../../navbar/newbrew.navitem.jsx');
const HelpNavItem = require('../../navbar/help.navitem.jsx');
const ErrorNavItem = require('../../navbar/error-navitem.jsx');
const UserPage = createClass({
displayName : 'UserPage',
@@ -19,7 +20,8 @@ const UserPage = createClass({
return {
username : '',
brews : [],
query : ''
query : '',
error : null
};
},
getInitialState : function() {
@@ -50,10 +52,19 @@ const UserPage = createClass({
brewCollection : brewCollection
};
},
errorReported : function(error) {
this.setState({
error
});
},
navItems : function() {
return <Navbar>
<Nav.section>
{this.state.error ?
<ErrorNavItem error={this.state.error} parent={this}></ErrorNavItem> :
null
}
<NewBrew />
<HelpNavItem />
<RecentNavItem />
@@ -63,7 +74,7 @@ const UserPage = createClass({
},
render : function(){
return <ListPage brewCollection={this.state.brewCollection} navItems={this.navItems()} query={this.props.query}></ListPage>;
return <ListPage brewCollection={this.state.brewCollection} navItems={this.navItems()} query={this.props.query} reportError={this.errorReported}></ListPage>;
}
});

View File

@@ -0,0 +1,12 @@
const request = require('superagent');
const addHeader = (request)=>request.set('Homebrewery-Version', global.version);
const requestMiddleware = {
get : (path)=>addHeader(request.get(path)),
put : (path)=>addHeader(request.put(path)),
post : (path)=>addHeader(request.post(path)),
delete : (path)=>addHeader(request.delete(path)),
};
module.exports = requestMiddleware;

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 541.53217 512"
version="1.1"
id="svg22127"
sodipodi:docname="book-front-cover.svg"
width="541.53217"
height="512"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs22131" />
<sodipodi:namedview
id="namedview22129"
pagecolor="#ffffff"
bordercolor="#111111"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="0.39257813"
inkscape:cx="-263.64179"
inkscape:cy="444.49751"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg22127" />
<!--! Font Awesome Pro 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<g
id="g20308"
transform="matrix(3.7795276,0,0,3.7795276,-201.76367,-251.58203)">
<path
id="rect20232"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:17.9;stroke-linejoin:bevel;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke markers fill;stop-color:#000000"
d="m 78.783305,66.564412 c -14.022889,0 -25.4,11.377111 -25.4,25.4 v 84.666668 c 0,14.02289 11.377111,25.4 25.4,25.4 h 76.199995 8.46667 c 4.68312,0 8.46667,-3.78355 8.46667,-8.46667 0,-4.68311 -3.78355,-8.46666 -8.46667,-8.46666 v -16.93334 c 4.68312,0 8.46667,-3.78355 8.46667,-8.46666 v -1.9327 c -0.0322,-0.27545 -0.0652,-0.54693 -0.0946,-0.83923 -0.17511,-1.74441 -0.30542,-3.81626 -0.37672,-6.02909 -0.18285,-5.67612 -0.29322,-5.86808 -0.63459,-6.62698 -0.74838,-1.66366 -2.65792,-3.64941 -4.38681,-4.49844 -1.41973,-0.69716 -0.72585,-0.45434 -1.20923,-0.51934 -0.47548,-0.0639 -2.54581,-0.13856 -6.47454,-0.14056 -0.0907,2.9929 -0.0862,4.81682 -0.58601,7.244 -0.28023,1.36071 -0.97957,3.42078 -2.40812,5.10356 -1.42519,1.67884 -2.81498,2.35811 -3.28145,2.61896 -3.14428,1.76375 -5.09549,2.43427 -9.41597,1.33997 -2.05224,-0.5197 -2.32631,-0.92288 -2.76159,-1.19527 -0.43528,-0.27239 -0.71007,-0.47684 -0.97461,-0.67593 -0.52909,-0.39816 -0.97871,-0.77171 -1.48622,-1.20664 -1.015,-0.86987 -2.20927,-1.95397 -3.6096,-3.26182 -2.80065,-2.61568 -6.38094,-6.09226 -10.18335,-9.90844 -6.19117,-6.21357 -9.5466,-9.59164 -11.7874,-12.16412 -1.1204,-1.28623 -2.03413,-2.38181 -2.90576,-4.03127 -0.87162,-1.64948 -1.40664,-4.21493 -1.40664,-5.61103 0,-1.4012 0.54783,-3.99366 1.42989,-5.64668 0.88206,-1.65304 1.8039,-2.74855 2.94142,-4.04679 2.27504,-2.59646 5.70131,-6.03358 12.03699,-12.369267 7.37691,-7.376888 10.87768,-11.090687 14.75208,-13.810527 1.45289,-1.019939 3.46378,-2.249133 6.08386,-2.580204 0.87337,-0.110323 1.8133,-0.120299 2.82412,0.0098 4.0433,0.520471 6.12413,2.832857 7.01973,3.728454 1.29782,1.297845 3.1373,4.826955 3.46852,7.049182 0.29817,2.00025 0.26393,3.770666 0.25993,6.212541 0.57954,0.0034 0.50388,0.0217 1.17564,0.0217 4.54211,0 8.44363,0.111537 11.991,0.50953 v -21.41004 c 0,-4.683115 -3.78355,-8.466667 -8.46667,-8.466667 h -8.46667 z m 0,101.599998 h 67.733335 v 16.93334 H 78.783305 c -4.683115,0 -8.466667,-3.78357 -8.466667,-8.46667 0,-4.68313 3.783552,-8.46667 8.466667,-8.46667 z" />
<path
style="color:#000000;fill:#000000;stroke-width:17.9;stroke-linejoin:round;-inkscape-stroke:none;paint-order:stroke markers fill"
d="m 186.69094,157.95633 c 2.67243,-2.24871 7.17957,-9.39389 8.63888,-13.69528 1.03796,-3.05942 1.31928,-5.13546 1.33362,-9.84167 0.0278,-9.1246 -2.25302,-14.5915 -8.79325,-21.07662 -6.8535,-6.79576 -12.35348,-8.46107 -27.94423,-8.46107 -8.05417,0 -9.45684,-0.12924 -9.75203,-0.89852 -0.18964,-0.49417 -0.34479,-3.81715 -0.34479,-7.384389 0,-5.728497 -0.13266,-6.618534 -1.13607,-7.621956 -2.57777,-2.57775 -3.29907,-2.07141 -18.02212,12.651595 -12.64444,12.64444 -13.78771,13.94921 -13.78771,15.73575 0,1.78396 1.13629,3.08846 13.49078,15.48766 7.47518,7.50224 14.10644,13.69554 14.8715,13.88928 0.78576,0.19902 2.0096,-0.002 2.84016,-0.46789 1.42969,-0.80092 1.46523,-0.97351 1.74346,-8.46583 l 0.28402,-7.64825 h 8.52049 c 8.16738,0 8.65373,0.0655 11.73586,1.579 3.72428,1.82893 6.9202,5.12058 8.60236,8.86006 0.94352,2.09748 1.22898,4.1112 1.41901,10.01012 0.13083,4.06143 0.49647,7.70394 0.81253,8.09446 0.94895,1.17251 3.64241,0.80611 5.48753,-0.74645 z"
id="path20297" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1,39 @@
.fac {
display : inline-block;
}
.position-top-left {
content: url('../icons/position-top-left.svg');
}
.position-top-right {
content: url('../icons/position-top-right.svg');
}
.position-bottom-left {
content: url('../icons/position-bottom-left.svg');
}
.position-bottom-right {
content: url('../icons/position-bottom-right.svg');
}
.position-top {
content: url('../icons/position-top.svg');
}
.position-right {
content: url('../icons/position-right.svg');
}
.position-bottom {
content: url('../icons/position-bottom.svg');
}
.position-left {
content: url('../icons/position-left.svg');
}
.mask-edge {
content: url('../icons/mask-edge.svg');
}
.mask-corner {
content: url('../icons/mask-corner.svg');
}
.fa-file-c {
content: url('../icons/fa-file-c.svg');
}
.book-front-cover {
content: url('../icons/book-front-cover.svg');
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 610.4 816.5" style="enable-background:new 0 0 610.4 816.5;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#FFFFFF;stroke:#FFFFFF;stroke-width:20;stroke-miterlimit:10;}
</style>
<title>fa-file-c</title>
<g id="Layer_2_1_">
<g id="Layer_1-2">
<g id="page">
<path id="page-2" d="M610.3,468.3c0,77.3,0.2,154.5,0,231.8s-39.8,116.5-116.8,116.4c-127.6,0-255.1,0-382.7,0
c-68.1,0-110.5-41.7-110.6-109.8c-0.2-197.7-0.2-395.5,0-593.2c0-68.4,43.2-110.9,112.1-111c90-0.1,180,0.2,270-0.2
c12.8,0,21.5,0.6,32.9,4c17.1,5,152.7,150.7,190.7,188.8c-0.7,18-6,5.7,1.4,35.1c0,6.8,3.1,11.2,3.1,18.1
C610.2,320.8,610.3,395.7,610.3,468.3z"/>
<path id="white_corner" class="st0" d="M364.1,0v200c0,9.3,1.7,25.6,13.1,36.8c12,11.7,28.8,12.1,37.5,12.2
c119.8,1.3,195.6,0.4,195.6,0.4l0,0l-0.3-54.3l-197,1l3-192L364.1,0z"/>
</g>
<path class="st1" d="M317.7,719.8c-38.3,0-71-8.1-98.3-24.3c-27.2-16.2-48.1-39.2-62.7-69C142.3,596.8,135,561.2,135,520
c0-30.9,4.1-58.6,12.4-83.1c8.3-24.5,20.2-45.3,35.9-62.4c15.6-17.1,34.9-30.4,57.7-39.8s48.4-14.1,76.7-14.1
c22.1-0.1,44,3.1,65.1,9.7c20.6,6.4,38.4,15.9,53.5,28.4c4.8,3.7,8,7.8,9.7,12.4c1.6,4.2,1.8,8.9,0.6,13.2
c-1.2,4.1-3.5,7.7-6.6,10.5c-3.1,2.8-7.2,4.2-11.3,4.1c-4.4,0-9.4-1.8-14.9-5.5c-13-10.5-27.7-18.6-43.6-23.7
c-16.6-5.3-33.9-7.9-51.3-7.7c-29.1,0-53.7,6.2-74,18.5s-35.5,30.3-45.8,53.8c-10.3,23.6-15.4,52.1-15.4,85.5s5.1,62.1,15.4,85.9
c10.3,23.7,25.6,41.8,45.8,54.1c20.2,12.3,44.9,18.5,74,18.5c17.4,0.1,34.8-2.6,51.3-8c16.2-5.3,31.3-13.5,44.7-24
c5.5-3.7,10.5-5.4,14.9-5.3c4,0.1,7.9,1.5,11,4.1c3,2.7,5.2,6.1,6.4,9.9c1.3,4.1,1.3,8.6,0,12.7c-1.3,4.4-4.1,8.3-8.6,11.6
c-15.5,13.3-33.6,23.3-54.4,30.1C362.7,716.6,340.3,720,317.7,719.8z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 448 512"
version="1.1"
id="svg135"
sodipodi:docname="mask-corner.svg"
width="448"
height="512"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs139"><pattern
inkscape:collect="always"
xlink:href="#Strips1_1"
id="pattern3077"
patternTransform="matrix(23.131931,-23.131931,19.25517,19.25517,26.214281,-26.952711)" /><pattern
inkscape:collect="always"
patternUnits="userSpaceOnUse"
width="2"
height="1"
patternTransform="translate(0,0) scale(10,10)"
id="Strips1_1"
inkscape:stockid="Stripes 1:1"><rect
style="fill:black;stroke:none"
x="0"
y="-0.5"
width="1"
height="2"
id="rect2097" /></pattern></defs><sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
showguides="false"
inkscape:zoom="0.95758074"
inkscape:cx="275.17262"
inkscape:cy="306.50157"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
id="rect12201"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
d="M 48,-5.2e-6 C 21.40803,-5.2e-6 1.98e-5,21.408025 1.98e-5,47.999995 V 464 C 1.98e-5,490.59197 21.40803,512 48,512 h 352 c 26.59198,0 48,-21.40803 48,-48 V 47.999995 C 448,21.408025 426.59198,-5.2e-6 400,-5.2e-6 Z M 64,63.999995 H 384 V 448 H 64 Z" /><rect
style="fill:url(#pattern3077);fill-opacity:1;stroke:#000000;stroke-width:48;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
id="rect12206"
width="208"
height="240"
x="32.000011"
y="32.000011"
rx="48"
ry="48" /></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 448 512"
version="1.1"
id="svg135"
sodipodi:docname="mask-edge.svg"
width="448"
height="512"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs139"><pattern
inkscape:collect="always"
xlink:href="#Strips1_1"
id="pattern3077"
patternTransform="matrix(23.131931,-23.13193,19.25517,19.25517,26.214281,-26.952711)" /><pattern
inkscape:collect="always"
patternUnits="userSpaceOnUse"
width="2"
height="1"
patternTransform="translate(0,0) scale(10,10)"
id="Strips1_1"
inkscape:stockid="Stripes 1:1"><rect
style="fill:black;stroke:none"
x="0"
y="-0.5"
width="1"
height="2"
id="rect2097" /></pattern></defs><sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
showguides="false"
inkscape:zoom="0.95758074"
inkscape:cx="231.31209"
inkscape:cy="171.78708"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
id="rect12201"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
d="M 48,-5.2e-6 C 21.40803,-5.2e-6 1.98e-5,21.408025 1.98e-5,47.999995 V 464 C 1.98e-5,490.59197 21.40803,512 48,512 h 352 c 26.59198,0 48,-21.40803 48,-48 V 47.999995 C 448,21.408025 426.59198,-5.2e-6 400,-5.2e-6 Z M 64,63.999995 H 384 V 448 H 64 Z" /><rect
style="fill:url(#pattern3077);fill-opacity:1;stroke:#000000;stroke-width:48;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
id="rect12206"
width="208"
height="447.99997"
x="32.000011"
y="32.000011"
rx="48"
ry="48" /><rect
style="fill:#000000;fill-opacity:1;stroke-width:47.9999;stroke-linejoin:round;stroke-dasharray:none;paint-order:fill markers stroke;stop-color:#000000"
id="rect4640"
width="48"
height="512"
x="216"
y="0" /></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 448 512"
version="1.1"
id="svg135"
sodipodi:docname="position-bottom-left.svg"
width="448"
height="512"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs139" /><sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
showguides="false"
inkscape:zoom="0.70792086"
inkscape:cx="174.45453"
inkscape:cy="325.60137"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
id="rect12201"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
d="m 48,511.99998 c -26.59197,0 -48.00000035682677,-21.40803 -48.00000035682677,-48 v -416 C -3.5682677e-7,21.40801 21.40803,-1.9692461e-5 48,-1.9692461e-5 h 352 c 26.59198,0 48,21.408029692461 48,47.999999692461 v 416 c 0,26.59197 -21.40802,48 -48,48 z m 16,-64 h 320 v -384 H 64 Z" /><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
id="rect12206"
width="208"
height="240"
x="-3.5682677e-07"
y="-512"
rx="48"
ry="48"
transform="scale(1,-1)" /></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 448 512"
version="1.1"
id="svg135"
sodipodi:docname="position-bottom-right.svg"
width="448"
height="512"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs139" /><sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
showguides="false"
inkscape:zoom="0.70792086"
inkscape:cx="174.45453"
inkscape:cy="325.60137"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
id="rect12201"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
d="m 400,511.99998 c 26.59197,0 48,-21.40803 48,-48 v -416 C 448,21.40801 426.59197,-1.9692461e-5 400,-1.9692461e-5 H 48 C 21.40802,-1.9692461e-5 -3.5682677e-7,21.40801 -3.5682677e-7,47.99998 v 416 c 0,26.59197 21.40802035682677,48 48.00000035682677,48 z m -16,-64 H 64 v -384 h 320 z" /><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
id="rect12206"
width="208"
height="240"
x="-448"
y="-512"
rx="48"
ry="48"
transform="scale(-1)" /></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 448 512"
version="1.1"
id="svg135"
sodipodi:docname="position-bottom.svg"
width="448"
height="512"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs139" /><sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
showguides="false"
inkscape:zoom="1.0011513"
inkscape:cx="273.18549"
inkscape:cy="216.25103"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
id="rect12201-2"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
d="m 48,512.00004 c -26.5919,0 -48,-21.4081 -48,-48 V 47.999996 C 0,21.408026 21.4081,-3.8146973e-6 48,-3.8146973e-6 h 352 c 26.592,0 48,21.4080298146973 48,47.9999998146973 V 464.00004 c 0,26.5919 -21.408,48 -48,48 z m 16,-64 H 384 V 63.999996 H 64 Z" /><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30.0001;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
id="rect12206-8"
width="447.99997"
height="240"
x="1.40625e-05"
y="-512.00006"
rx="48"
ry="48"
transform="scale(1,-1)" /></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 448 512"
version="1.1"
id="svg135"
sodipodi:docname="position-left.svg"
width="448"
height="512"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs139" /><sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
showguides="false"
inkscape:zoom="0.70792086"
inkscape:cx="164.56642"
inkscape:cy="243.6713"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
id="rect12201-0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
d="M 48,0 C 21.4081,0 0,21.40803 0,48 v 416 c 0,26.59197 21.4081,48 48,48 h 352.0001 c 26.5919,0 48,-21.40803 48,-48 V 48 c 0,-26.59197 -21.4081,-48 -48,-48 z M 64,64 H 384.0001 V 448 H 64 Z" /><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
id="rect12206-2"
width="208"
height="512.00006"
x="7.0762391e-05"
y="-8.8710935e-05"
rx="48"
ry="48.000004" /></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 448 512"
version="1.1"
id="svg135"
sodipodi:docname="position-right.svg"
width="448"
height="512"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs139" /><sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
showguides="false"
inkscape:zoom="0.70792086"
inkscape:cx="164.56642"
inkscape:cy="243.6713"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
id="rect12201-0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
d="m 400.0001,0 c 26.5919,0 48,21.40803 48,48 v 416 c 0,26.59197 -21.4081,48 -48,48 H 48 C 21.4081,512 0,490.59197 0,464 V 48 C 0,21.40803 21.4081,0 48,0 Z m -16,64 H 64 v 384 h 320.0001 z" /><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
id="rect12206-2"
width="208"
height="512.00006"
x="-448.00003"
y="-8.8710935e-05"
rx="48"
ry="48.000004"
transform="scale(-1,1)" /></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 448 512"
version="1.1"
id="svg135"
sodipodi:docname="position-top-left.svg"
width="448"
height="512"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs139" /><sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
showguides="false"
inkscape:zoom="0.70792086"
inkscape:cx="174.45453"
inkscape:cy="325.60137"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
id="rect12201"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
d="M 48,0 C 21.40803,0 0,21.40803 0,48 v 416 c 0,26.59197 21.40803,48 48,48 h 352 c 26.59198,0 48,-21.40803 48,-48 V 48 C 448,21.40803 426.59198,0 400,0 Z M 64,64 H 384 V 448 H 64 Z" /><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
id="rect12206"
width="208"
height="240"
x="-3.5682677e-07"
y="-1.9692461e-05"
rx="48"
ry="48" /></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 448 512"
version="1.1"
id="svg135"
sodipodi:docname="position-top-right.svg"
width="448"
height="512"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs139" /><sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
showguides="false"
inkscape:zoom="0.70792086"
inkscape:cx="174.45453"
inkscape:cy="325.60137"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
id="rect12201"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
d="m 400,0 c 26.59197,0 48,21.40803 48,48 v 416 c 0,26.59197 -21.40803,48 -48,48 H 48 C 21.40802,512 -3.5682677e-7,490.59197 -3.5682677e-7,464 V 48 C -3.5682677e-7,21.40803 21.40802,0 48,0 Z M 384,64 H 64 v 384 h 320 z" /><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
id="rect12206"
width="208"
height="240"
x="-448"
y="-1.9692461e-05"
rx="48"
ry="48"
transform="scale(-1,1)" /></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 448 512"
version="1.1"
id="svg135"
sodipodi:docname="position-top.svg"
width="448"
height="512"
xml:space="preserve"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs139" /><sodipodi:namedview
id="namedview137"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
showguides="false"
inkscape:zoom="1.0011513"
inkscape:cx="273.18549"
inkscape:cy="216.25103"
inkscape:window-width="1920"
inkscape:window-height="991"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="svg135" /><!--! Font Awesome Pro 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path
id="rect12201-2"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
d="M 48,0 C 21.4081,0 0,21.4081 0,48 v 416.00004 c 0,26.59197 21.4081,48 48,48 h 352 c 26.592,0 48,-21.40803 48,-48 V 48 C 448,21.4081 426.592,0 400,0 Z M 64,64 H 384 V 448.00004 H 64 Z" /><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:30.0001;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000"
id="rect12206-8"
width="447.99997"
height="240"
x="1.40625e-05"
y="-3.8146973e-06"
rx="48"
ry="48" /></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,28 +1,31 @@
module.exports = async(name, title = '', props = {})=>{
const HOMEBREWERY_PUBLIC_URL=props.config.publicUrl;
const template = async function(name, title='', props = {}){
const ogTags = [];
const ogMeta = props.ogMeta ?? {};
Object.entries(ogMeta).forEach(([key, value])=>{
if(!value) return;
const tag = `<meta property="og:${key}" content="${value}">`;
ogTags.push(tag);
});
const ogMetaTags = ogTags.join('\n');
return `
<!DOCTYPE html>
<html>
<head>
<link href="//use.fontawesome.com/releases/v5.15.1/css/all.css" rel="stylesheet" />
<link href="//fonts.googleapis.com/css?family=Open+Sans:400,300,600,700" rel="stylesheet" type="text/css" />
<link href=${`/${name}/bundle.css`} rel='stylesheet' />
<link rel="icon" href="/assets/favicon.ico" type="image/x-icon" />
<meta property="og:title" content="${props.brew?.title || 'Homebrewery - Untitled Brew'}">
<meta property="og:url" content="${HOMEBREWERY_PUBLIC_URL}/${props.brew?.shareId ? `share/${props.brew.shareId}` : ''}">
<meta property="og:image" content="${props.brew?.thumbnail || `${HOMEBREWERY_PUBLIC_URL}/thumbnail.png`}">
<meta property="og:description" content="${props.brew?.description || 'No description.'}">
<meta property="og:site_name" content="The Homebrewery - Make your Homebrew content look legit!">
<meta property="og:type" content="article">
<meta name="twitter:card" content="summary_large_image">
<title>${title.length ? `${title} - The Homebrewery`: 'The Homebrewery - NaturalCrit'}</title>
</head>
<body>
<main id="reactRoot">${require(`../build/${name}/ssr.js`)(props)}</main>
<script src=${`/${name}/bundle.js`}></script>
<script>start_app(${JSON.stringify(props)})</script>
</body>
</html>
`;
return `<!DOCTYPE html>
<html>
<head>
<link href="//use.fontawesome.com/releases/v5.15.1/css/all.css" rel="stylesheet" />
<link href="//fonts.googleapis.com/css?family=Open+Sans:400,300,600,700" rel="stylesheet" type="text/css" />
<link href=${`/${name}/bundle.css`} rel='stylesheet' />
<link rel="icon" href="/assets/favicon.ico" type="image/x-icon" />
${ogMetaTags}
<meta name="twitter:card" content="summary">
<title>${title.length ? `${title} - The Homebrewery`: 'The Homebrewery - NaturalCrit'}</title>
</head>
<body>
<main id="reactRoot">${require(`../build/${name}/ssr.js`)(props)}</main>
<script src=${`/${name}/bundle.js`}></script>
<script>start_app(${JSON.stringify(props)})</script>
</body>
</html>
`;
};
module.exports = template;

19962
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "homebrewery",
"description": "Create authentic looking D&D homebrews using only markdown",
"version": "3.2.2",
"version": "3.7.0",
"engines": {
"node": "16.11.x"
},
@@ -14,11 +14,14 @@
"quick": "node scripts/quick.js",
"build": "node scripts/buildHomebrew.js",
"buildall": "node scripts/buildHomebrew.js && node scripts/buildAdmin.js",
"builddev": "node scripts/buildHomebrew.js --dev",
"lint": "eslint --fix **/*.{js,jsx}",
"lint:dry": "eslint **/*.{js,jsx}",
"circleci": "npm test && eslint **/*.{js,jsx} --max-warnings=0",
"verify": "npm run lint && npm test",
"test": "jest",
"test:api-unit": "jest server/*.spec.js --verbose",
"test:coverage": "jest --coverage --silent",
"test:dev": "jest --verbose --watch",
"test:basic": "jest tests/markdown/basic.test.js --verbose",
"test:mustache-span": "jest tests/markdown/mustache-span.test.js --verbose",
@@ -36,10 +39,24 @@
"jest": {
"testTimeout": 15000,
"modulePaths": [
"mode_modules",
"node_modules",
"shared",
"server"
]
],
"coverageThreshold" : {
"global" : {
"statements" : 25,
"branches" : 10,
"functions" : 22,
"lines" : 25
},
"server/homebrew.api.js" : {
"statements" : 65,
"branches" : 50,
"functions" : 60,
"lines" : 70
}
}
},
"babel": {
"presets": [
@@ -51,44 +68,45 @@
]
},
"dependencies": {
"@babel/core": "^7.19.0",
"@babel/plugin-transform-runtime": "^7.18.10",
"@babel/preset-env": "^7.19.0",
"@babel/core": "^7.21.0",
"@babel/plugin-transform-runtime": "^7.21.0",
"@babel/preset-env": "^7.19.4",
"@babel/preset-react": "^7.18.6",
"body-parser": "^1.20.0",
"classnames": "^2.3.1",
"body-parser": "^1.20.2",
"classnames": "^2.3.2",
"codemirror": "^5.65.6",
"cookie-parser": "^1.4.6",
"create-react-class": "^15.7.0",
"dedent-tabs": "^0.10.1",
"express": "^4.18.1",
"dedent-tabs": "^0.10.2",
"express": "^4.18.2",
"express-async-handler": "^1.2.0",
"express-static-gzip": "2.1.7",
"fs-extra": "10.1.0",
"googleapis": "107.0.0",
"fs-extra": "11.1.0",
"googleapis": "111.0.0",
"js-yaml": "^4.1.0",
"jwt-simple": "^0.5.6",
"less": "^3.13.1",
"lodash": "^4.17.21",
"marked": "4.1.0",
"marked": "4.2.12",
"marked-extended-tables": "^1.0.5",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.29.4",
"mongoose": "^6.5.5",
"mongoose": "^6.9.2",
"nanoid": "3.3.4",
"nconf": "^0.12.0",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"npm": "^8.10.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-frame-component": "4.1.3",
"react-router-dom": "6.3.0",
"react-router-dom": "6.8.2",
"sanitize-filename": "1.6.3",
"superagent": "^6.1.0",
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
},
"devDependencies": {
"eslint": "^8.23.0",
"eslint-plugin-react": "^7.31.7",
"jest": "^29.0.2",
"supertest": "^6.2.4"
"eslint": "^8.35.0",
"eslint-plugin-react": "^7.32.2",
"jest": "^29.4.3",
"supertest": "^6.3.3"
}
}

View File

@@ -10,7 +10,7 @@ const assetTransform = require('vitreum/transforms/asset.js');
const babel = require('@babel/core');
const less = require('less');
const babelify = async (code)=>(await babel.transformAsync(code, { presets: ['@babel/preset-env', '@babel/preset-react'], plugins: ['@babel/plugin-transform-runtime'] })).code;
const babelify = async (code)=>(await babel.transformAsync(code, { presets: [['@babel/preset-env', { 'exclude': ['proposal-dynamic-import'] }], '@babel/preset-react'], plugins: ['@babel/plugin-transform-runtime'] })).code;
const transforms = {
'.js' : (code, filename, opts)=>babelify(code),
@@ -21,32 +21,12 @@ const transforms = {
const build = async ({ bundle, render, ssr })=>{
const css = await lessTransform.generate({ paths: './shared' });
//css = `@layer bundle {\n${css}\n}`;
await fs.outputFile('./build/homebrew/bundle.css', css);
await fs.outputFile('./build/homebrew/bundle.js', bundle);
await fs.outputFile('./build/homebrew/ssr.js', ssr);
await fs.copy('./themes/fonts', './build/fonts');
await fs.copy('./themes/assets', './build/assets');
await fs.copy('./client/homebrew/favicon.ico', './build/assets/favicon.ico');
let src = './themes/5ePhbLegacy.style.less';
//Parse brew theme files
less.render(fs.readFileSync(src).toString(), {
compress : !isDev
}, function(e, output) {
fs.outputFile('./build/themes/5ePhbLegacy.style.css', output.css);
});
src = './themes/5ePhb.style.less';
less.render(fs.readFileSync(src).toString(), {
compress : !isDev
}, function(e, output) {
fs.outputFile('./build/themes/5ePhb.style.css', output.css);
});
// await less.render(lessCode, {
// compress : !dev,
// sourceMap : (dev ? {
// sourceMapFileInline: true,
// outputSourceFiles: true
// } : false),
// })
//compress files in production
if(!isDev){
@@ -61,20 +41,104 @@ const build = async ({ bundle, render, ssr })=>{
};
fs.emptyDirSync('./build');
pack('./client/homebrew/homebrew.jsx', {
paths : ['./shared'],
libs : Proj.libs,
dev : isDev && build,
transforms
})
.then(build)
.catch(console.error);
(async ()=>{
//v==----------------------------- COMPILE THEMES --------------------------------==v//
// Update list of all Theme files
const themes = { Legacy: {}, V3: {} };
let themeFiles = fs.readdirSync('./themes/Legacy');
for (dir of themeFiles) {
const themeData = JSON.parse(fs.readFileSync(`./themes/Legacy/${dir}/settings.json`).toString());
themeData.path = dir;
themes.Legacy[dir] = (themeData);
//fs.copy(`./themes/Legacy/${dir}/dropdownTexture.png`, `./build/themes/Legacy/${dir}/dropdownTexture.png`);
const src = `./themes/Legacy/${dir}/style.less`;
((outputDirectory)=>{
less.render(fs.readFileSync(src).toString(), {
compress : !isDev
}, function(e, output) {
fs.outputFile(outputDirectory, output.css);
});
})(`./build/themes/Legacy/${dir}/style.css`);
}
themeFiles = fs.readdirSync('./themes/V3');
for (dir of themeFiles) {
const themeData = JSON.parse(fs.readFileSync(`./themes/V3/${dir}/settings.json`).toString());
themeData.path = dir;
themes.V3[dir] = (themeData);
fs.copy(`./themes/V3/${dir}/dropdownTexture.png`, `./build/themes/V3/${dir}/dropdownTexture.png`);
fs.copy(`./themes/V3/${dir}/dropdownPreview.png`, `./build/themes/V3/${dir}/dropdownPreview.png`);
const src = `./themes/V3/${dir}/style.less`;
((outputDirectory)=>{
less.render(fs.readFileSync(src).toString(), {
compress : !isDev
}, function(e, output) {
fs.outputFile(outputDirectory, output.css);
});
})(`./build/themes/V3/${dir}/style.css`);
}
await fs.outputFile('./themes/themes.json', JSON.stringify(themes, null, 2));
// await less.render(lessCode, {
// compress : !dev,
// sourceMap : (dev ? {
// sourceMapFileInline: true,
// outputSourceFiles: true
// } : false),
// })
// Move assets
await fs.copy('./themes/fonts', './build/fonts');
await fs.copy('./themes/assets', './build/assets');
await fs.copy('./client/icons', './build/icons');
//v==----------------------------- BUNDLE PACKAGES --------------------------------==v//
const bundles = await pack('./client/homebrew/homebrew.jsx', {
paths : ['./shared', './'],
libs : Proj.libs,
dev : isDev && build,
transforms
});
build(bundles);
// Possible method for generating separate bundles for theme snippets: factor-bundle first sending all common files to bundle.js, then again using default settings, keeping only snippet bundles
// await fs.outputFile('./build/junk.js', '');
// await fs.outputFile('./build/themes/Legacy/5ePHB/snippets.js', '');
//
// const files = ['./client/homebrew/homebrew.jsx','./themes/Legacy/5ePHB/snippets.js'];
//
// bundles = await pack(files, {
// dedupe: false,
// plugin : [['factor-bundle', { outputs: [ './build/junk.js','./build/themes/Legacy/5ePHB/snippets.js'], threshold : function(row, groups) {
// console.log(groups);
// if (groups.some(group => /.*homebrew.jsx$/.test(group))) {
// console.log("found homebrewery")
// return true;
// }
// return this._defaultThreshold(row, groups);
// }}]],
// paths : ['./shared','./','./build'],
// libs : Proj.libs,
// dev : isDev && build,
// transforms
// });
// build(bundles);
//
})().catch(console.error);
//In development set up a watch server and livereload
if(isDev){
livereload('./build');
watchFile('./server.js', {
watch : ['./client', './server'] // Watch additional folders if you want
watch : ['./client', './server', './themes'] // Watch additional folders if you want
});
}

View File

@@ -1,4 +1,4 @@
/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/
/*eslint max-lines: ["warn", {"max": 400, "skipBlankLines": true, "skipComments": true}]*/
// Set working directory to project root
process.chdir(`${__dirname}/..`);
@@ -15,13 +15,15 @@ const serveCompressedStaticAssets = require('./static-assets.mv.js');
const sanitizeFilename = require('sanitize-filename');
const asyncHandler = require('express-async-handler');
const { DEFAULT_BREW } = require('./brewDefaults.js');
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']));
Object.assign(brew, _.pick(metadata, ['title', 'description', 'tags', 'systems', 'renderer', 'theme']));
brew.text = brew.text.slice(index + 5);
}
if(brew.text.startsWith('```css')) {
@@ -76,6 +78,14 @@ const faqText = require('fs').readFileSync('faq.md', 'utf8');
String.prototype.replaceAll = function(s, r){return this.split(s).join(r);};
const defaultMetaTags = {
site_name : 'The Homebrewery - Make your Homebrew content look legit!',
title : 'The Homebrewery',
description : 'A NaturalCrit Tool for creating authentic Homebrews using Markdown.',
image : `${config.get('publicUrl')}/thumbnail.png`,
type : 'website'
};
//Robots.txt
app.get('/robots.txt', (req, res)=>{
return res.sendFile(`robots.txt`, { root: process.cwd() });
@@ -86,17 +96,29 @@ app.get('/', (req, res, next)=>{
req.brew = {
text : welcomeText,
renderer : 'V3'
},
req.ogMeta = { ...defaultMetaTags,
title : 'Homepage',
description : 'Homepage'
};
splitTextStyleAndMetadata(req.brew);
return next();
});
//Home page v3
//Home page Legacy
app.get('/legacy', (req, res, next)=>{
req.brew = {
text : welcomeTextLegacy,
renderer : 'legacy'
},
req.ogMeta = { ...defaultMetaTags,
title : 'Homepage (Legacy)',
description : 'Homepage'
};
splitTextStyleAndMetadata(req.brew);
return next();
});
@@ -106,7 +128,13 @@ app.get('/migrate', (req, res, next)=>{
req.brew = {
text : migrateText,
renderer : 'V3'
},
req.ogMeta = { ...defaultMetaTags,
title : 'v3 Migration Guide',
description : 'A brief guide to converting Legacy documents to the v3 renderer.'
};
splitTextStyleAndMetadata(req.brew);
return next();
});
@@ -117,7 +145,13 @@ app.get('/changelog', async (req, res, next)=>{
title : 'Changelog',
text : changelogText,
renderer : 'V3'
},
req.ogMeta = { ...defaultMetaTags,
title : 'Changelog',
description : 'Development changelog.'
};
splitTextStyleAndMetadata(req.brew);
return next();
});
@@ -128,7 +162,13 @@ app.get('/faq', async (req, res, next)=>{
title : 'FAQ',
text : faqText,
renderer : 'V3'
},
req.ogMeta = { ...defaultMetaTags,
title : 'FAQ',
description : 'Frequently Asked Questions'
};
splitTextStyleAndMetadata(req.brew);
return next();
});
@@ -152,12 +192,19 @@ app.get('/download/:id', asyncHandler(getBrew('share')), (req, res)=>{
sanitizeBrew(brew, 'share');
const prefix = 'HB - ';
const encodeRFC3986ValueChars = (str)=>{
return (
encodeURIComponent(str)
.replace(/[!'()*]/g, (char)=>{`%${char.charCodeAt(0).toString(16).toUpperCase()}`;})
);
};
let fileName = sanitizeFilename(`${prefix}${brew.title}`).replaceAll(' ', '');
if(!fileName || !fileName.length) { fileName = `${prefix}-Untitled-Brew`; };
res.set({
'Cache-Control' : 'no-cache',
'Content-Type' : 'text/plain',
'Content-Disposition' : `attachment; filename="${fileName}.txt"`
'Content-Disposition' : `attachment; filename*=UTF-8''${encodeRFC3986ValueChars(fileName)}.txt`
});
res.status(200).send(brew.text);
});
@@ -166,6 +213,12 @@ app.get('/download/:id', asyncHandler(getBrew('share')), (req, res)=>{
app.get('/user/:username', async (req, res, next)=>{
const ownAccount = req.account && (req.account.username == req.params.username);
req.ogMeta = { ...defaultMetaTags,
title : `${req.params.username}'s Collection`,
description : 'View my collection of homebrew on the Homebrewery.'
// type : could be 'profile'?
};
const fields = [
'googleId',
'title',
@@ -179,6 +232,7 @@ app.get('/user/:username', async (req, res, next)=>{
'createdAt',
'updatedAt',
'lastViewed',
'thumbnail',
'tags'
];
@@ -222,6 +276,14 @@ app.get('/user/:username', async (req, res, next)=>{
//Edit Page
app.get('/edit/:id', asyncHandler(getBrew('edit')), (req, res, next)=>{
req.brew = req.brew.toObject ? req.brew.toObject() : req.brew;
req.ogMeta = { ...defaultMetaTags,
title : req.brew.title || 'Untitled Brew',
description : req.brew.description || 'No description.',
image : req.brew.thumbnail || defaultMetaTags.image,
type : 'article'
};
sanitizeBrew(req.brew, 'edit');
splitTextStyleAndMetadata(req.brew);
res.header('Cache-Control', 'no-cache, no-store'); //reload the latest saved brew when pressing back button, not the cached version before save.
@@ -232,7 +294,21 @@ app.get('/edit/:id', asyncHandler(getBrew('edit')), (req, res, next)=>{
app.get('/new/:id', asyncHandler(getBrew('share')), (req, res, next)=>{
sanitizeBrew(req.brew, 'share');
splitTextStyleAndMetadata(req.brew);
req.brew.title = `CLONE - ${req.brew.title}`;
const brew = {
shareId : req.brew.shareId,
title : `CLONE - ${req.brew.title}`,
text : req.brew.text,
style : req.brew.style,
renderer : req.brew.renderer,
theme : req.brew.theme
};
req.brew = _.defaults(brew, DEFAULT_BREW);
req.ogMeta = { ...defaultMetaTags,
title : 'New',
description : 'Start crafting your homebrew on the Homebrewery!'
};
return next();
});
@@ -240,6 +316,13 @@ app.get('/new/:id', asyncHandler(getBrew('share')), (req, res, next)=>{
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.',
image : req.brew.thumbnail || defaultMetaTags.image,
type : 'article'
};
if(req.params.id.length > 12 && !brew._id) {
const googleId = req.params.id.slice(0, -12);
const shareId = req.params.id.slice(-12);
@@ -260,6 +343,61 @@ app.get('/print/:id', asyncHandler(getBrew('share')), (req, res, next)=>{
next();
});
//Account Page
app.get('/account', asyncHandler(async (req, res, next)=>{
const data = {};
data.title = 'Account Information Page';
let auth;
let googleCount = [];
if(req.account) {
if(req.account.googleId) {
try {
auth = await GoogleActions.authCheck(req.account, res, false);
} catch (e) {
auth = undefined;
console.log('Google auth check failed!');
console.log(e);
}
if(auth.credentials.access_token) {
try {
googleCount = await GoogleActions.listGoogleBrews(auth);
} catch (e) {
googleCount = undefined;
console.log('List Google files failed!');
console.log(e);
}
}
}
const query = { authors: req.account.username, googleId: { $exists: false } };
const mongoCount = await HomebrewModel.countDocuments(query)
.catch((err)=>{
mongoCount = 0;
console.log(err);
});
data.uiItems = {
username : req.account.username,
issued : req.account.issued,
googleId : Boolean(req.account.googleId),
authCheck : Boolean(req.account.googleId && auth.credentials.access_token),
mongoCount : mongoCount,
googleCount : googleCount?.length
};
}
req.brew = data;
req.ogMeta = { ...defaultMetaTags,
title : `Account Page`,
description : null
};
return next();
}));
const nodeEnv = config.get('node_env');
const isLocalEnvironment = config.get('local_environments').includes(nodeEnv);
// Local only
@@ -274,11 +412,10 @@ if(isLocalEnvironment){
});
}
//Render the page
const templateFn = require('./../client/template.js');
app.use(asyncHandler(async (req, res, next)=>{
// Create configuration object
const configuration = {
local : isLocalEnvironment,
@@ -286,14 +423,16 @@ app.use(asyncHandler(async (req, res, next)=>{
environment : nodeEnv
};
const props = {
version : require('./../package.json').version,
url : req.originalUrl,
brew : req.brew,
brews : req.brews,
googleBrews : req.googleBrews,
account : req.account,
enable_v3 : config.get('enable_v3'),
config : configuration
version : require('./../package.json').version,
url : req.originalUrl,
brew : req.brew,
brews : req.brews,
googleBrews : req.googleBrews,
account : req.account,
enable_v3 : config.get('enable_v3'),
enable_themes : config.get('enable_themes'),
config : configuration,
ogMeta : req.ogMeta
};
const title = req.brew ? req.brew.title : '';
const page = await templateFn('homebrew', title, props)

37
server/brewDefaults.js Normal file
View File

@@ -0,0 +1,37 @@
const _ = require('lodash');
// Default properties for newly-created brews
const DEFAULT_BREW = {
title : '',
text : '',
style : undefined,
description : '',
editId : undefined,
shareId : undefined,
createdAt : undefined,
updatedAt : undefined,
renderer : 'V3',
theme : '5ePHB',
authors : [],
tags : [],
systems : [],
thumbnail : '',
views : 0,
published : false,
pageCount : 1,
gDrive : false,
trashed : false
};
// Default values for older brews with missing properties
// e.g., missing "renderer" is assumed to be "legacy"
const DEFAULT_BREW_LOAD = _.defaults(
{
renderer : 'legacy',
},
DEFAULT_BREW);
module.exports = {
DEFAULT_BREW,
DEFAULT_BREW_LOAD
};

View File

@@ -10,7 +10,7 @@ const Mongoose = require('mongoose');
const getMongoDBURL = (config)=>{
return config.get('mongodb_uri') ||
config.get('mongolab_uri') ||
'mongodb://localhost/homebrewery';
'mongodb://127.0.0.1/homebrewery'; // changed from mongodb://localhost/homebrewery to accommodate versions 16+ of node.
};
const handleConnectionError = (error)=>{

View File

@@ -5,24 +5,28 @@ const { nanoid } = require('nanoid');
const token = require('./token.js');
const config = require('./config.js');
const keys = typeof(config.get('service_account')) == 'string' ?
JSON.parse(config.get('service_account')) :
config.get('service_account');
let serviceAuth;
try {
serviceAuth = google.auth.fromJSON(keys);
serviceAuth.scopes = [
'https://www.googleapis.com/auth/drive'
];
} catch (err) {
console.warn(err);
console.log('Please make sure that a Google Service Account is set up properly in your config files.');
if(!config.get('service_account')){
console.log('No Google Service Account in config files - Google Drive integration will not be available.');
} else {
const keys = typeof(config.get('service_account')) == 'string' ?
JSON.parse(config.get('service_account')) :
config.get('service_account');
try {
serviceAuth = google.auth.fromJSON(keys);
serviceAuth.scopes = ['https://www.googleapis.com/auth/drive'];
} catch (err) {
console.warn(err);
console.log('Please make sure the Google Service Account is set up properly in your config files.');
}
}
google.options({ auth: serviceAuth || config.get('google_api_key') });
const GoogleActions = {
authCheck : (account, res)=>{
authCheck : (account, res, updateTokens=true)=>{
if(!account || !account.googleId){ // If not signed into Google
const err = new Error('Not Signed In');
err.status = 401;
@@ -40,7 +44,7 @@ const GoogleActions = {
refresh_token : account.googleRefreshToken
});
oAuth2Client.on('tokens', (tokens)=>{
updateTokens && oAuth2Client.on('tokens', (tokens)=>{
if(tokens.refresh_token) {
account.googleRefreshToken = tokens.refresh_token;
}
@@ -125,8 +129,7 @@ const GoogleActions = {
description : file.description,
views : parseInt(file.properties.views),
published : file.properties.published ? file.properties.published == 'true' : false,
systems : [],
thumbnail : file.properties.thumbnail
systems : []
};
});
return brews;
@@ -146,8 +149,7 @@ const GoogleActions = {
editId : brew.editId || nanoid(12),
pageCount : brew.pageCount,
renderer : brew.renderer || 'legacy',
isStubbed : true,
thumbnail : brew.thumbnail
isStubbed : true
}
},
media : {
@@ -185,8 +187,7 @@ const GoogleActions = {
pageCount : brew.pageCount,
renderer : brew.renderer || 'legacy',
isStubbed : true,
version : 1,
thumbnail : brew.thumbnail || ''
version : 1
}
};
@@ -252,7 +253,6 @@ const GoogleActions = {
text : file.data,
description : obj.data.description,
tags : obj.data.properties.tags ? obj.data.properties.tags : '',
systems : obj.data.properties.systems ? obj.data.properties.systems.split(',') : [],
authors : [],
published : obj.data.properties.published ? obj.data.properties.published == 'true' : false,
@@ -265,7 +265,6 @@ const GoogleActions = {
views : parseInt(obj.data.properties.views) || 0, //brews with no view parameter will return undefined
version : parseInt(obj.data.properties.version) || 0,
renderer : obj.data.properties.renderer ? obj.data.properties.renderer : 'legacy',
thumbnail : obj.data.properties.thumbnail || '',
googleId : id
};

View File

@@ -9,330 +9,339 @@ const yaml = require('js-yaml');
const asyncHandler = require('express-async-handler');
const { nanoid } = require('nanoid');
const { DEFAULT_BREW, DEFAULT_BREW_LOAD } = require('./brewDefaults.js');
// const getTopBrews = (cb) => {
// HomebrewModel.find().sort({ views: -1 }).limit(5).exec(function(err, brews) {
// cb(brews);
// });
// };
const getId = (req)=>{
// Set the id and initial potential google id, where the google id is present on the existing brew.
let id = req.params.id, googleId = req.body?.googleId;
// If the id is longer than 12, then it's a google id + the edit id. This splits the longer id up.
if(id.length > 12) {
googleId = id.slice(0, -12);
id = id.slice(-12);
}
return { id, googleId };
};
const getBrew = (accessType)=>{
// Create middleware with the accessType passed in as part of the scope
return async (req, res, next)=>{
// Get relevant IDs for the brew
const { id, googleId } = getId(req);
// Try to find the document in the Homebrewery database -- if it doesn't exist, that's fine.
let stub = await HomebrewModel.get(accessType === 'edit' ? { editId: id } : { shareId: id })
.catch((err)=>{
if(googleId) {
console.warn(`Unable to find document stub for ${accessType}Id ${id}`);
} else {
console.warn(err);
}
});
stub = stub?.toObject();
// If there is a google id, try to find the google brew
if(googleId || stub?.googleId) {
let googleError;
const googleBrew = await GoogleActions.getGoogleBrew(googleId || stub?.googleId, id, accessType)
.catch((err)=>{
console.warn(err);
googleError = err;
});
// If we can't find the google brew and there is a google id for the brew, throw an error.
if(!googleBrew) throw googleError;
// Combine the Homebrewery stub with the google brew, or if the stub doesn't exist just use the google brew
stub = stub ? _.assign({ ...excludeStubProps(stub), stubbed: true }, excludeGoogleProps(googleBrew)) : googleBrew;
}
// If after all of that we still don't have a brew, throw an exception
if(!stub) {
throw 'Brew not found in Homebrewery database or Google Drive';
}
if(typeof stub.tags === 'string') {
stub.tags = [];
}
req.brew = stub;
next();
};
};
const mergeBrewText = (brew)=>{
let text = brew.text;
if(brew.style !== undefined) {
text = `\`\`\`css\n` +
`${brew.style || ''}\n` +
`\`\`\`\n\n` +
`${text}`;
}
const metadata = _.pick(brew, ['title', 'description', 'tags', 'systems', 'renderer']);
text = `\`\`\`metadata\n` +
`${yaml.dump(metadata)}\n` +
`\`\`\`\n\n` +
`${text}`;
return text;
};
const MAX_TITLE_LENGTH = 100;
const getGoodBrewTitle = (text)=>{
const tokens = Markdown.marked.lexer(text);
return (tokens.find((token)=>token.type === 'heading' || token.type === 'paragraph')?.text || 'No Title')
.slice(0, MAX_TITLE_LENGTH);
};
const api = {
homebrewApi : router,
getId : (req)=>{
// Set the id and initial potential google id, where the google id is present on the existing brew.
let id = req.params.id, googleId = req.body?.googleId;
const excludePropsFromUpdate = (brew)=>{
// Remove undesired properties
const modified = _.clone(brew);
const propsToExclude = ['_id', 'views', 'lastViewed', 'editId', 'shareId', 'googleId'];
for (const prop of propsToExclude) {
delete modified[prop];
}
return modified;
};
const excludeGoogleProps = (brew)=>{
const modified = _.clone(brew);
const propsToExclude = ['tags', 'systems', 'published', 'authors', 'owner', 'views'];
for (const prop of propsToExclude) {
delete modified[prop];
}
return modified;
};
const excludeStubProps = (brew)=>{
const propsToExclude = ['text', 'textBin', 'renderer', 'pageCount', 'version'];
for (const prop of propsToExclude) {
brew[prop] = undefined;
}
return brew;
};
const beforeNewSave = (account, brew)=>{
if(!brew.title) {
brew.title = getGoodBrewTitle(brew.text);
}
brew.authors = (account) ? [account.username] : [];
brew.text = mergeBrewText(brew);
};
const newGoogleBrew = async (account, brew, res)=>{
const oAuth2Client = GoogleActions.authCheck(account, res);
const newBrew = excludeGoogleProps(brew);
return await GoogleActions.newGoogleBrew(oAuth2Client, newBrew);
};
const newBrew = async (req, res)=>{
const brew = req.body;
const { saveToGoogle } = req.query;
delete brew.editId;
delete brew.shareId;
delete brew.googleId;
beforeNewSave(req.account, brew);
const newHomebrew = new HomebrewModel(brew);
newHomebrew.editId = nanoid(12);
newHomebrew.shareId = nanoid(12);
let googleId, saved;
if(saveToGoogle) {
googleId = await newGoogleBrew(req.account, newHomebrew, res)
.catch((err)=>{
console.error(err);
res.status(err?.status || err?.response?.status || 500).send(err?.message || err);
});
if(!googleId) return;
excludeStubProps(newHomebrew);
newHomebrew.googleId = googleId;
} else {
// Compress brew text to binary before saving
newHomebrew.textBin = zlib.deflateRawSync(newHomebrew.text);
// Delete the non-binary text field since it's not needed anymore
newHomebrew.text = undefined;
}
saved = await newHomebrew.save()
.catch((err)=>{
console.error(err, err.toString(), err.stack);
throw `Error while creating new brew, ${err.toString()}`;
});
if(!saved) return;
saved = saved.toObject();
res.status(200).send(saved);
};
const updateBrew = async (req, res)=>{
// Initialize brew from request and body, destructure query params, set a constant for the google id, and set the initial value for the after-save method
let brew = _.assign(req.brew, excludePropsFromUpdate(req.body));
const { saveToGoogle, removeFromGoogle } = req.query;
const googleId = brew.googleId;
let afterSave = async ()=>true;
brew.text = mergeBrewText(brew);
if(brew.googleId && removeFromGoogle) {
// If the google id exists and we're removing it from google, set afterSave to delete the google brew and mark the brew's google id as undefined
afterSave = async ()=>{
return await deleteGoogleBrew(req.account, googleId, brew.editId, res)
.catch((err)=>{
console.error(err);
res.status(err?.status || err?.response?.status || 500).send(err.message || err);
});
};
brew.googleId = undefined;
} else if(!brew.googleId && saveToGoogle) {
// If we don't have a google id and the user wants to save to google, create the google brew and set the google id on the brew
brew.googleId = await newGoogleBrew(req.account, excludeGoogleProps(brew), res)
.catch((err)=>{
console.error(err);
res.status(err.status || err.response.status).send(err.message || err);
});
if(!brew.googleId) return;
} else if(brew.googleId) {
// If the google id exists and no other actions are being performed, update the google brew
const updated = await GoogleActions.updateGoogleBrew(excludeGoogleProps(brew))
.catch((err)=>{
console.error(err);
res.status(err?.response?.status || 500).send(err);
});
if(!updated) return;
}
if(brew.googleId) {
// If the google id exists after all those actions, exclude the props that are stored in google and aren't needed for rendering the brew items
excludeStubProps(brew);
} else {
// Compress brew text to binary before saving
brew.textBin = zlib.deflateRawSync(brew.text);
// Delete the non-binary text field since it's not needed anymore
brew.text = undefined;
}
brew.updatedAt = new Date();
if(req.account) {
brew.authors = _.uniq(_.concat(brew.authors, req.account.username));
}
// Fetch the brew from the database again (if it existed there to begin with), and assign the existing brew to it
brew = _.assign(await HomebrewModel.findOne({ _id: brew._id }), brew);
if(!brew.markModified) {
// If it wasn't in the database, create a new db brew
brew = new HomebrewModel(brew);
}
brew.markModified('authors');
brew.markModified('systems');
// Save the database brew
const saved = await brew.save()
.catch((err)=>{
console.error(err);
res.status(err.status || 500).send(err.message || 'Unable to save brew to Homebrewery database');
});
if(!saved) return;
// Call and wait for afterSave to complete
const after = await afterSave();
if(!after) return;
res.status(200).send(saved);
};
const deleteGoogleBrew = async (account, id, editId, res)=>{
const auth = await GoogleActions.authCheck(account, res);
await GoogleActions.deleteGoogleBrew(auth, id, editId);
return true;
};
const deleteBrew = async (req, res, next)=>{
// Delete an orphaned stub if its Google brew doesn't exist
try {
await getBrew('edit')(req, res, ()=>{});
} catch (err) {
const { id, googleId } = getId(req);
console.warn(`No google brew found for id ${googleId}, the stub with id ${id} will be deleted.`);
await HomebrewModel.deleteOne({ editId: id });
return next();
}
let brew = req.brew;
const { googleId, editId } = brew;
const account = req.account;
const isOwner = account && (brew.authors.length === 0 || brew.authors[0] === account.username);
// If the user is the owner and the file is saved to google, mark the google brew for deletion
const shouldDeleteGoogleBrew = googleId && isOwner;
if(brew._id) {
brew = _.assign(await HomebrewModel.findOne({ _id: brew._id }), brew);
if(account) {
// Remove current user as author
brew.authors = _.pull(brew.authors, account.username);
brew.markModified('authors');
// If the id is longer than 12, then it's a google id + the edit id. This splits the longer id up.
if(id.length > 12) {
googleId = id.slice(0, -12);
id = id.slice(-12);
}
return { id, googleId };
},
getBrew : (accessType, stubOnly = false)=>{
// Create middleware with the accessType passed in as part of the scope
return async (req, res, next)=>{
// Get relevant IDs for the brew
const { id, googleId } = api.getId(req);
if(brew.authors.length === 0) {
// Delete brew if there are no authors left
await brew.remove()
// Try to find the document in the Homebrewery database -- if it doesn't exist, that's fine.
let stub = await HomebrewModel.get(accessType === 'edit' ? { editId: id } : { shareId: id })
.catch((err)=>{
console.error(err);
throw { status: 500, message: 'Error while removing' };
if(googleId) {
console.warn(`Unable to find document stub for ${accessType}Id ${id}`);
} else {
console.warn(err);
}
});
} else {
if(shouldDeleteGoogleBrew) {
// When there are still authors remaining, we delete the google brew but store the full brew in the Homebrewery database
brew.googleId = undefined;
brew.textBin = zlib.deflateRawSync(brew.text);
brew.text = undefined;
stub = stub?.toObject();
// If there is a google id, try to find the google brew
if(!stubOnly && (googleId || stub?.googleId)) {
let googleError;
const googleBrew = await GoogleActions.getGoogleBrew(googleId || stub?.googleId, id, accessType)
.catch((err)=>{
googleError = err;
});
// Throw any error caught while attempting to retrieve Google brew.
if(googleError) throw googleError;
// Combine the Homebrewery stub with the google brew, or if the stub doesn't exist just use the google brew
stub = stub ? _.assign({ ...api.excludeStubProps(stub), stubbed: true }, api.excludeGoogleProps(googleBrew)) : googleBrew;
}
const authorsExist = stub?.authors?.length > 0;
const isAuthor = stub?.authors?.includes(req.account?.username);
const isInvited = stub?.invitedAuthors?.includes(req.account?.username);
if(accessType === 'edit' && (authorsExist && !(isAuthor || isInvited))) {
throw `The current logged in user does not have editor access to this brew.
If you believe you should have access to this brew, ask the file owner to invite you as an author by opening the brew, viewing the Properties tab, and adding your username to the "invited authors" list. You can then try to access this document again.`;
}
// Otherwise, save the brew with updated author list
await brew.save()
.catch((err)=>{
throw { status: 500, message: err };
});
// If after all of that we still don't have a brew, throw an exception
if(!stub && !stubOnly) {
throw 'Brew not found in Homebrewery database or Google Drive';
}
// Clean up brew: fill in missing fields with defaults / fix old invalid values
if(stub) {
stub.tags = stub.tags || undefined; // Clear empty strings
stub.renderer = stub.renderer || undefined; // Clear empty strings
stub = _.defaults(stub, DEFAULT_BREW_LOAD); // Fill in blank fields
}
req.brew = stub ?? {};
next();
};
},
mergeBrewText : (brew)=>{
let text = brew.text;
if(brew.style !== undefined) {
text = `\`\`\`css\n` +
`${brew.style || ''}\n` +
`\`\`\`\n\n` +
`${text}`;
}
}
if(shouldDeleteGoogleBrew) {
const deleted = await deleteGoogleBrew(account, googleId, editId, res)
const metadata = _.pick(brew, ['title', 'description', 'tags', 'systems', 'renderer', 'theme']);
text = `\`\`\`metadata\n` +
`${yaml.dump(metadata)}\n` +
`\`\`\`\n\n` +
`${text}`;
return text;
},
getGoodBrewTitle : (text)=>{
const tokens = Markdown.marked.lexer(text);
return (tokens.find((token)=>token.type === 'heading' || token.type === 'paragraph')?.text || 'No Title')
.slice(0, MAX_TITLE_LENGTH);
},
excludePropsFromUpdate : (brew)=>{
// Remove undesired properties
const modified = _.clone(brew);
const propsToExclude = ['_id', 'views', 'lastViewed'];
for (const prop of propsToExclude) {
delete modified[prop];
}
return modified;
},
excludeGoogleProps : (brew)=>{
const modified = _.clone(brew);
const propsToExclude = ['version', 'tags', 'systems', 'published', 'authors', 'owner', 'views', 'thumbnail'];
for (const prop of propsToExclude) {
delete modified[prop];
}
return modified;
},
excludeStubProps : (brew)=>{
const propsToExclude = ['text', 'textBin', 'renderer', 'pageCount'];
for (const prop of propsToExclude) {
brew[prop] = undefined;
}
return brew;
},
beforeNewSave : (account, brew)=>{
if(!brew.title) {
brew.title = api.getGoodBrewTitle(brew.text);
}
brew.authors = (account) ? [account.username] : [];
brew.text = api.mergeBrewText(brew);
_.defaults(brew, DEFAULT_BREW);
},
newGoogleBrew : async (account, brew, res)=>{
const oAuth2Client = GoogleActions.authCheck(account, res);
const newBrew = api.excludeGoogleProps(brew);
return await GoogleActions.newGoogleBrew(oAuth2Client, newBrew);
},
newBrew : async (req, res)=>{
const brew = req.body;
const { saveToGoogle } = req.query;
delete brew.editId;
delete brew.shareId;
delete brew.googleId;
api.beforeNewSave(req.account, brew);
const newHomebrew = new HomebrewModel(brew);
newHomebrew.editId = nanoid(12);
newHomebrew.shareId = nanoid(12);
let googleId, saved;
if(saveToGoogle) {
googleId = await api.newGoogleBrew(req.account, newHomebrew, res)
.catch((err)=>{
console.error(err);
res.status(err?.status || err?.response?.status || 500).send(err?.message || err);
});
if(!googleId) return;
api.excludeStubProps(newHomebrew);
newHomebrew.googleId = googleId;
} else {
// Compress brew text to binary before saving
newHomebrew.textBin = zlib.deflateRawSync(newHomebrew.text);
// Delete the non-binary text field since it's not needed anymore
newHomebrew.text = undefined;
}
saved = await newHomebrew.save()
.catch((err)=>{
console.error(err);
res.status(500).send(err);
console.error(err, err.toString(), err.stack);
throw `Error while creating new brew, ${err.toString()}`;
});
if(!deleted) return;
if(!saved) return;
saved = saved.toObject();
res.status(200).send(saved);
},
updateBrew : async (req, res)=>{
// Initialize brew from request and body, destructure query params, and set the initial value for the after-save method
const brewFromClient = api.excludePropsFromUpdate(req.body);
const brewFromServer = req.brew;
if(brewFromServer.version && brewFromClient.version && brewFromServer.version > brewFromClient.version) {
console.log(`Version mismatch on brew ${brewFromClient.editId}`);
res.setHeader('Content-Type', 'application/json');
return res.status(409).send(JSON.stringify({ message: `The brew has been changed on a different device. Please save your changes elsewhere, refresh, and try again.` }));
}
let brew = _.assign(brewFromServer, brewFromClient);
const googleId = brew.googleId;
const { saveToGoogle, removeFromGoogle } = req.query;
let afterSave = async ()=>true;
brew.text = api.mergeBrewText(brew);
if(brew.googleId && removeFromGoogle) {
// If the google id exists and we're removing it from google, set afterSave to delete the google brew and mark the brew's google id as undefined
afterSave = async ()=>{
return await api.deleteGoogleBrew(req.account, googleId, brew.editId, res)
.catch((err)=>{
console.error(err);
res.status(err?.status || err?.response?.status || 500).send(err.message || err);
});
};
brew.googleId = undefined;
} else if(!brew.googleId && saveToGoogle) {
// If we don't have a google id and the user wants to save to google, create the google brew and set the google id on the brew
brew.googleId = await api.newGoogleBrew(req.account, api.excludeGoogleProps(brew), res)
.catch((err)=>{
console.error(err);
res.status(err.status || err.response.status).send(err.message || err);
});
if(!brew.googleId) return;
} else if(brew.googleId) {
// If the google id exists and no other actions are being performed, update the google brew
const updated = await GoogleActions.updateGoogleBrew(api.excludeGoogleProps(brew))
.catch((err)=>{
console.error(err);
res.status(err?.response?.status || 500).send(err);
});
if(!updated) return;
}
if(brew.googleId) {
// If the google id exists after all those actions, exclude the props that are stored in google and aren't needed for rendering the brew items
api.excludeStubProps(brew);
} else {
// Compress brew text to binary before saving
brew.textBin = zlib.deflateRawSync(brew.text);
// Delete the non-binary text field since it's not needed anymore
brew.text = undefined;
}
brew.updatedAt = new Date();
brew.version = (brew.version || 1) + 1;
if(req.account) {
brew.authors = _.uniq(_.concat(brew.authors, req.account.username));
brew.invitedAuthors = _.uniq(_.filter(brew.invitedAuthors, (a)=>req.account.username !== a));
}
// define a function to catch our save errors
const saveError = (err)=>{
console.error(err);
res.status(err.status || 500).send(err.message || 'Unable to save brew to Homebrewery database');
};
let saved;
if(!brew._id) {
// if the brew does not have a stub id, create and save it, then write the new value back to the brew.
saved = await new HomebrewModel(brew).save().catch(saveError);
} else {
// if the brew does have a stub id, update it using the stub id as the key.
brew = _.assign(await HomebrewModel.findOne({ _id: brew._id }), brew);
saved = await brew.save()
.catch(saveError);
}
if(!saved) return;
// Call and wait for afterSave to complete
const after = await afterSave();
if(!after) return;
res.status(200).send(saved);
},
deleteGoogleBrew : async (account, id, editId, res)=>{
const auth = await GoogleActions.authCheck(account, res);
await GoogleActions.deleteGoogleBrew(auth, id, editId);
return true;
},
deleteBrew : async (req, res, next)=>{
// Delete an orphaned stub if its Google brew doesn't exist
try {
await api.getBrew('edit')(req, res, ()=>{});
} catch (err) {
const { id, googleId } = api.getId(req);
console.warn(`No google brew found for id ${googleId}, the stub with id ${id} will be deleted.`);
await HomebrewModel.deleteOne({ editId: id });
return next();
}
let brew = req.brew;
const { googleId, editId } = brew;
const account = req.account;
const isOwner = account && (brew.authors.length === 0 || brew.authors[0] === account.username);
// If the user is the owner and the file is saved to google, mark the google brew for deletion
const shouldDeleteGoogleBrew = googleId && isOwner;
if(brew._id) {
brew = _.assign(await HomebrewModel.findOne({ _id: brew._id }), brew);
if(account) {
// Remove current user as author
brew.authors = _.pull(brew.authors, account.username);
}
if(brew.authors.length === 0) {
// Delete brew if there are no authors left
await brew.remove()
.catch((err)=>{
console.error(err);
throw { status: 500, message: 'Error while removing' };
});
} else {
if(shouldDeleteGoogleBrew) {
// When there are still authors remaining, we delete the google brew but store the full brew in the Homebrewery database
brew.googleId = undefined;
brew.textBin = zlib.deflateRawSync(brew.text);
brew.text = undefined;
}
brew.markModified('authors'); //Mongo will not properly update arrays without markModified()
await brew.save()
.catch((err)=>{
throw { status: 500, message: err };
});
}
}
if(shouldDeleteGoogleBrew) {
const deleted = await api.deleteGoogleBrew(account, googleId, editId, res)
.catch((err)=>{
console.error(err);
res.status(500).send(err);
});
if(!deleted) return;
}
res.status(204).send();
}
res.status(204).send();
};
router.post('/api', asyncHandler(newBrew));
router.put('/api/:id', asyncHandler(getBrew('edit')), asyncHandler(updateBrew));
router.put('/api/update/:id', asyncHandler(getBrew('edit')), asyncHandler(updateBrew));
router.delete('/api/:id', asyncHandler(deleteBrew));
router.get('/api/remove/:id', asyncHandler(deleteBrew));
router.use('/api', require('./middleware/check-client-version.js'));
router.post('/api', asyncHandler(api.newBrew));
router.put('/api/:id', asyncHandler(api.getBrew('edit', true)), asyncHandler(api.updateBrew));
router.put('/api/update/:id', asyncHandler(api.getBrew('edit', true)), asyncHandler(api.updateBrew));
router.delete('/api/:id', asyncHandler(api.deleteBrew));
router.get('/api/remove/:id', asyncHandler(api.deleteBrew));
module.exports = {
homebrewApi : router,
getBrew
};
module.exports = api;

758
server/homebrew.api.spec.js Normal file
View File

@@ -0,0 +1,758 @@
/* eslint-disable max-lines */
describe('Tests for api', ()=>{
let api;
let google;
let model;
let hbBrew;
let googleBrew;
let res;
let modelBrew;
let saveFunc;
let removeFunc;
let markModifiedFunc;
let saved;
beforeEach(()=>{
saved = undefined;
saveFunc = jest.fn(async function() {
saved = { ...this, _id: '1' };
return saved;
});
removeFunc = jest.fn(async function() {});
markModifiedFunc = jest.fn(()=>true);
modelBrew = (brew)=>({
...brew,
save : saveFunc,
remove : removeFunc,
markModified : markModifiedFunc,
toObject : function() {
delete this.save;
delete this.toObject;
delete this.remove;
delete this.markModified;
return this;
}
});
google = require('./googleActions.js');
model = require('./homebrew.model.js').model;
jest.mock('./googleActions.js');
google.authCheck = jest.fn(()=>'client');
google.newGoogleBrew = jest.fn(()=>'id');
google.deleteGoogleBrew = jest.fn(()=>true);
jest.mock('./homebrew.model.js');
model.mockImplementation((brew)=>modelBrew(brew));
res = {
status : jest.fn(()=>res),
send : jest.fn(()=>{})
};
api = require('./homebrew.api');
hbBrew = {
text : `brew text`,
style : 'hello yes i am css',
title : 'some title',
description : 'this is a description',
tags : ['something', 'fun'],
systems : ['D&D 5e'],
renderer : 'v3',
theme : 'phb',
published : true,
authors : ['1', '2'],
owner : '1',
thumbnail : '',
_id : 'mongoid',
editId : 'abcdefg',
shareId : 'hijklmnop',
views : 1,
lastViewed : new Date(),
version : 1,
pageCount : 1,
textBin : '',
views : 0
};
googleBrew = {
...hbBrew,
googleId : '12345'
};
});
afterEach(()=>{
jest.restoreAllMocks();
});
describe('getId', ()=>{
it('should return only id if google id is not present', ()=>{
const { id, googleId } = api.getId({
params : {
id : 'abcdefgh'
}
});
expect(id).toEqual('abcdefgh');
expect(googleId).toBeUndefined();
});
it('should return id and google id from request body', ()=>{
const { id, googleId } = api.getId({
params : {
id : 'abcdefgh'
},
body : {
googleId : '12345'
}
});
expect(id).toEqual('abcdefgh');
expect(googleId).toEqual('12345');
});
it('should return id and google id from params', ()=>{
const { id, googleId } = api.getId({
params : {
id : '123456789012abcdefghijkl'
}
});
expect(id).toEqual('abcdefghijkl');
expect(googleId).toEqual('123456789012');
});
});
describe('getBrew', ()=>{
const toBrewPromise = (brew)=>new Promise((res)=>res({ toObject: ()=>brew }));
const notFoundError = 'Brew not found in Homebrewery database or Google Drive';
it('returns middleware', ()=>{
const getFn = api.getBrew('share');
expect(getFn).toBeInstanceOf(Function);
});
it('should fetch from mongoose', async ()=>{
const testBrew = { title: 'test brew', authors: [] };
api.getId = jest.fn(()=>({ id: '1', googleId: undefined }));
model.get = jest.fn(()=>toBrewPromise(testBrew));
const fn = api.getBrew('share', true);
const req = { brew: {} };
const next = jest.fn();
await fn(req, null, next);
expect(req.brew).toEqual(testBrew);
expect(next).toHaveBeenCalled();
expect(api.getId).toHaveBeenCalledWith(req);
expect(model.get).toHaveBeenCalledWith({ shareId: '1' });
});
it('should handle mongoose error', async ()=>{
api.getId = jest.fn(()=>({ id: '1', googleId: undefined }));
model.get = jest.fn(()=>new Promise((_, rej)=>rej('Unable to find brew')));
const fn = api.getBrew('share', false);
const req = { brew: {} };
const next = jest.fn();
let err;
try {
await fn(req, null, next);
} catch (e) {
err = e;
}
expect(err).toEqual(notFoundError);
expect(req.brew).toEqual({});
expect(next).not.toHaveBeenCalled();
expect(api.getId).toHaveBeenCalledWith(req);
expect(model.get).toHaveBeenCalledWith({ shareId: '1' });
});
it('changes tags from string to array', async ()=>{
const testBrew = { title: 'test brew', authors: [], tags: '' };
api.getId = jest.fn(()=>({ id: '1', googleId: undefined }));
model.get = jest.fn(()=>toBrewPromise(testBrew));
const fn = api.getBrew('share', true);
const req = { brew: {} };
const next = jest.fn();
await fn(req, null, next);
expect(req.brew.tags).toEqual([]);
expect(next).toHaveBeenCalled();
});
it('throws if invalid author', async ()=>{
api.getId = jest.fn(()=>({ id: '1', googleId: undefined }));
model.get = jest.fn(()=>toBrewPromise({ title: 'test brew', authors: ['a'] }));
const fn = api.getBrew('edit', true);
const req = { brew: {} };
let err;
try {
await fn(req, null, null);
} catch (e) {
err = e;
}
expect(err).toEqual(`The current logged in user does not have editor access to this brew.
If you believe you should have access to this brew, ask the file owner to invite you as an author by opening the brew, viewing the Properties tab, and adding your username to the "invited authors" list. You can then try to access this document again.`);
});
it('does not throw if no authors', async ()=>{
api.getId = jest.fn(()=>({ id: '1', googleId: undefined }));
model.get = jest.fn(()=>toBrewPromise({ title: 'test brew', authors: [] }));
const fn = api.getBrew('edit', true);
const req = { brew: {} };
const next = jest.fn();
await fn(req, null, next);
expect(next).toHaveBeenCalled();
expect(req.brew.title).toEqual('test brew');
expect(req.brew.authors).toEqual([]);
});
it('does not throw if valid author', async ()=>{
api.getId = jest.fn(()=>({ id: '1', googleId: undefined }));
model.get = jest.fn(()=>toBrewPromise({ title: 'test brew', authors: ['a'] }));
const fn = api.getBrew('edit', true);
const req = { brew: {}, account: { username: 'a' } };
const next = jest.fn();
await fn(req, null, next);
expect(next).toHaveBeenCalled();
expect(req.brew.title).toEqual('test brew');
expect(req.brew.authors).toEqual(['a']);
});
it('fetches google brew if needed', async()=>{
const stubBrew = { title: 'test brew', authors: ['a'] };
const googleBrew = { title: 'test google brew', text: 'brew text' };
api.getId = jest.fn(()=>({ id: '1', googleId: '2' }));
model.get = jest.fn(()=>toBrewPromise(stubBrew));
google.getGoogleBrew = jest.fn(()=>new Promise((res)=>res(googleBrew)));
const fn = api.getBrew('share', false);
const req = { brew: {} };
const next = jest.fn();
await fn(req, null, next);
expect(req.brew).toEqual({
title : 'test google brew',
authors : ['a'],
text : 'brew text',
stubbed : true,
description : '',
editId : undefined,
pageCount : 1,
published : false,
renderer : 'legacy',
shareId : undefined,
systems : [],
tags : [],
theme : '5ePHB',
thumbnail : '',
textBin : undefined,
version : undefined,
createdAt : undefined,
gDrive : false,
style : undefined,
trashed : false,
updatedAt : undefined,
views : 0
});
expect(next).toHaveBeenCalled();
expect(api.getId).toHaveBeenCalledWith(req);
expect(model.get).toHaveBeenCalledWith({ shareId: '1' });
expect(google.getGoogleBrew).toHaveBeenCalledWith('2', '1', 'share');
});
});
describe('mergeBrewText', ()=>{
it('should set metadata and no style if it is not present', ()=>{
const result = api.mergeBrewText({
text : `brew`,
title : 'some title',
description : 'this is a description',
tags : ['something', 'fun'],
systems : ['D&D 5e'],
renderer : 'v3',
theme : 'phb',
googleId : '12345'
});
expect(result).toEqual(`\`\`\`metadata
title: some title
description: this is a description
tags:
- something
- fun
systems:
- D&D 5e
renderer: v3
theme: phb
\`\`\`
brew`);
});
it('should set metadata and style', ()=>{
const result = api.mergeBrewText({
text : `brew`,
style : 'hello yes i am css',
title : 'some title',
description : 'this is a description',
tags : ['something', 'fun'],
systems : ['D&D 5e'],
renderer : 'v3',
theme : 'phb',
googleId : '12345'
});
expect(result).toEqual(`\`\`\`metadata
title: some title
description: this is a description
tags:
- something
- fun
systems:
- D&D 5e
renderer: v3
theme: phb
\`\`\`
\`\`\`css
hello yes i am css
\`\`\`
brew`);
});
});
describe('exclusion methods', ()=>{
it('excludePropsFromUpdate removes the correct keys', ()=>{
const sent = Object.assign({}, googleBrew);
const result = api.excludePropsFromUpdate(sent);
expect(sent).toEqual(googleBrew);
expect(result._id).toBeUndefined();
expect(result.views).toBeUndefined();
expect(result.lastViewed).toBeUndefined();
});
it('excludeGoogleProps removes the correct keys', ()=>{
const sent = Object.assign({}, googleBrew);
const result = api.excludeGoogleProps(sent);
expect(sent).toEqual(googleBrew);
expect(result.tags).toBeUndefined();
expect(result.systems).toBeUndefined();
expect(result.published).toBeUndefined();
expect(result.authors).toBeUndefined();
expect(result.owner).toBeUndefined();
expect(result.views).toBeUndefined();
expect(result.thumbnail).toBeUndefined();
expect(result.version).toBeUndefined();
});
it('excludeStubProps removes the correct keys from the original object', ()=>{
const sent = Object.assign({}, googleBrew);
const result = api.excludeStubProps(sent);
expect(sent).not.toEqual(googleBrew);
expect(result.text).toBeUndefined();
expect(result.textBin).toBeUndefined();
expect(result.renderer).toBeUndefined();
expect(result.pageCount).toBeUndefined();
});
});
describe('beforeNewSave', ()=>{
it('sets the title if none', ()=>{
const brew = {
...hbBrew,
title : undefined
};
api.beforeNewSave({}, brew);
expect(brew.title).toEqual('brew text');
});
it('does not override the title if present', ()=>{
const brew = {
...hbBrew,
title : 'test'
};
api.beforeNewSave({}, brew);
expect(brew.title).toEqual('test');
});
it('does not set authors if account missing username', ()=>{
api.beforeNewSave({}, hbBrew);
expect(hbBrew.authors).toEqual([]);
});
it('sets authors if account has username', ()=>{
api.beforeNewSave({ username: 'hi' }, hbBrew);
expect(hbBrew.authors).toEqual(['hi']);
});
it('merges brew text', ()=>{
api.mergeBrewText = jest.fn(()=>'merged');
api.beforeNewSave({}, hbBrew);
expect(api.mergeBrewText).toHaveBeenCalled();
expect(hbBrew.text).toEqual('merged');
});
});
describe('newGoogleBrew', ()=>{
it('should call the correct methods', ()=>{
api.excludeGoogleProps = jest.fn(()=>'newBrew');
const acct = { username: 'test' };
const brew = { title: 'test title' };
api.newGoogleBrew(acct, brew, res);
expect(google.authCheck).toHaveBeenCalledWith(acct, res);
expect(api.excludeGoogleProps).toHaveBeenCalledWith(brew);
expect(google.newGoogleBrew).toHaveBeenCalledWith('client', 'newBrew');
});
});
describe('newBrew', ()=>{
it('should set up a default brew via Homebrew model', async ()=>{
await api.newBrew({ body: { text: 'asdf' }, query: {}, account: { username: 'test user' } }, res);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.send).toHaveBeenCalledWith({
_id : '1',
authors : ['test user'],
createdAt : undefined,
description : '',
editId : expect.any(String),
gDrive : false,
pageCount : 1,
published : false,
renderer : 'V3',
shareId : expect.any(String),
style : undefined,
systems : [],
tags : [],
text : undefined,
textBin : expect.objectContaining({}),
theme : '5ePHB',
thumbnail : '',
title : 'asdf',
trashed : false,
updatedAt : undefined,
views : 0
});
});
it('should remove edit/share/google ids', async ()=>{
await api.newBrew({ body: { editId: '1234', shareId: '1234', googleId: '1234', text: 'asdf', title: '' }, query: {} }, res);
expect(res.status).toHaveBeenCalledWith(200);
expect(res.send).toHaveBeenCalled();
const sent = res.send.mock.calls[0][0];
expect(sent.editId).not.toEqual('1234');
expect(sent.shareId).not.toEqual('1234');
expect(sent.googleId).toBeUndefined();
});
it('should handle mongo error', async ()=>{
saveFunc = jest.fn(async function() {
throw 'err';
});
model.mockImplementation((brew)=>modelBrew(brew));
let err;
try {
await api.newBrew({ body: { editId: '1234', shareId: '1234', googleId: '1234', text: 'asdf', title: '' }, query: {} }, res);
} catch (e) {
err = e;
}
expect(res.send).not.toHaveBeenCalled();
expect(err).not.toBeUndefined();
});
it('should save to google if requested', async()=>{
await api.newBrew({ body: { text: 'asdf', title: '' }, query: { saveToGoogle: true }, account: { username: 'test user' } }, res);
expect(google.newGoogleBrew).toHaveBeenCalled();
expect(res.status).toHaveBeenCalledWith(200);
expect(res.send).toHaveBeenCalledWith({
_id : '1',
authors : ['test user'],
createdAt : undefined,
description : '',
editId : expect.any(String),
gDrive : false,
pageCount : undefined,
published : false,
renderer : undefined,
shareId : expect.any(String),
googleId : expect.any(String),
style : undefined,
systems : [],
tags : [],
text : undefined,
textBin : undefined,
theme : '5ePHB',
thumbnail : '',
title : 'asdf',
trashed : false,
updatedAt : undefined,
views : 0
});
});
it('should handle google error', async()=>{
google.newGoogleBrew = jest.fn(()=>{
throw 'err';
});
await api.newBrew({ body: { text: 'asdf', title: '' }, query: { saveToGoogle: true }, account: { username: 'test user' } }, res);
expect(res.status).toHaveBeenCalledWith(500);
expect(res.send).toHaveBeenCalledWith('err');
});
});
describe('deleteGoogleBrew', ()=>{
it('should check auth and delete brew', async ()=>{
const result = await api.deleteGoogleBrew({ username: 'test user' }, 'id', 'editId', res);
expect(result).toBe(true);
expect(google.authCheck).toHaveBeenCalledWith({ username: 'test user' }, expect.objectContaining({}));
expect(google.deleteGoogleBrew).toHaveBeenCalledWith('client', 'id', 'editId');
});
});
describe('deleteBrew', ()=>{
it('should handle case where fetching the brew returns an error', async ()=>{
api.getBrew = jest.fn(()=>async ()=>{ throw 'err'; });
api.getId = jest.fn(()=>({ id: '1', googleId: '2' }));
model.deleteOne = jest.fn(async ()=>{});
const next = jest.fn(()=>{});
await api.deleteBrew(null, null, next);
expect(next).toHaveBeenCalled();
expect(model.deleteOne).toHaveBeenCalledWith({ editId: '1' });
});
it('should delete if no authors', async ()=>{
const brew = {
...hbBrew,
authors : []
};
api.getBrew = jest.fn(()=>async (req)=>{
req.brew = brew;
});
model.findOne = jest.fn(async ()=>modelBrew(brew));
const req = {};
await api.deleteBrew(req, res);
expect(api.getBrew).toHaveBeenCalled();
expect(model.findOne).toHaveBeenCalled();
expect(removeFunc).toHaveBeenCalled();
});
it('should throw on delete error', async ()=>{
const brew = {
...hbBrew,
authors : []
};
api.getBrew = jest.fn(()=>async (req)=>{
req.brew = brew;
});
model.findOne = jest.fn(async ()=>modelBrew(brew));
removeFunc = jest.fn(async ()=>{ throw 'err'; });
const req = {};
let err;
try {
await api.deleteBrew(req, res);
} catch (e) {
err = e;
}
expect(err).not.toBeUndefined();
expect(api.getBrew).toHaveBeenCalled();
expect(model.findOne).toHaveBeenCalled();
expect(removeFunc).toHaveBeenCalled();
});
it('should delete when one author', async ()=>{
const brew = {
...hbBrew,
authors : ['test']
};
api.getBrew = jest.fn(()=>async (req)=>{
req.brew = brew;
});
model.findOne = jest.fn(async ()=>modelBrew(brew));
const req = { account: { username: 'test' } };
await api.deleteBrew(req, res);
expect(api.getBrew).toHaveBeenCalled();
expect(model.findOne).toHaveBeenCalled();
expect(removeFunc).toHaveBeenCalled();
});
it('should remove one author when multiple present', async ()=>{
const brew = {
...hbBrew,
authors : ['test', 'test2']
};
api.getBrew = jest.fn(()=>async (req)=>{
req.brew = brew;
});
model.findOne = jest.fn(async ()=>modelBrew(brew));
const req = { account: { username: 'test' } };
await api.deleteBrew(req, res);
expect(api.getBrew).toHaveBeenCalled();
expect(markModifiedFunc).toHaveBeenCalled();
expect(model.findOne).toHaveBeenCalled();
expect(removeFunc).not.toHaveBeenCalled();
expect(saveFunc).toHaveBeenCalled();
expect(saved.authors).toEqual(['test2']);
});
it('should handle save error', async ()=>{
const brew = {
...hbBrew,
authors : ['test', 'test2']
};
api.getBrew = jest.fn(()=>async (req)=>{
req.brew = brew;
});
model.findOne = jest.fn(async ()=>modelBrew(brew));
saveFunc = jest.fn(async ()=>{ throw 'err'; });
const req = { account: { username: 'test' } };
let err;
try {
await api.deleteBrew(req, res);
} catch (e) {
err = e;
}
expect(err).not.toBeUndefined();
expect(api.getBrew).toHaveBeenCalled();
expect(model.findOne).toHaveBeenCalled();
expect(removeFunc).not.toHaveBeenCalled();
expect(saveFunc).toHaveBeenCalled();
});
it('should delete google brew', async ()=>{
const brew = {
...googleBrew,
authors : ['test']
};
api.getBrew = jest.fn(()=>async (req)=>{
req.brew = brew;
});
model.findOne = jest.fn(async ()=>modelBrew(brew));
api.deleteGoogleBrew = jest.fn(async ()=>true);
const req = { account: { username: 'test' } };
await api.deleteBrew(req, res);
expect(api.getBrew).toHaveBeenCalled();
expect(model.findOne).toHaveBeenCalled();
expect(removeFunc).toHaveBeenCalled();
expect(api.deleteGoogleBrew).toHaveBeenCalled();
});
it('should handle google brew delete error', async ()=>{
const brew = {
...googleBrew,
authors : ['test']
};
api.getBrew = jest.fn(()=>async (req)=>{
req.brew = brew;
});
model.findOne = jest.fn(async ()=>modelBrew(brew));
api.deleteGoogleBrew = jest.fn(async ()=>{
throw 'err';
});
const req = { account: { username: 'test' } };
await api.deleteBrew(req, res);
expect(api.getBrew).toHaveBeenCalled();
expect(model.findOne).toHaveBeenCalled();
expect(removeFunc).toHaveBeenCalled();
expect(api.deleteGoogleBrew).toHaveBeenCalled();
});
it('should delete google brew and retain stub when multiple authors and owner request deletion', async ()=>{
const brew = {
...googleBrew,
authors : ['test', 'test2']
};
api.getBrew = jest.fn(()=>async (req)=>{
req.brew = brew;
});
model.findOne = jest.fn(async ()=>modelBrew(brew));
api.deleteGoogleBrew = jest.fn(async ()=>true);
const req = { account: { username: 'test' } };
await api.deleteBrew(req, res);
expect(api.getBrew).toHaveBeenCalled();
expect(markModifiedFunc).toHaveBeenCalled();
expect(model.findOne).toHaveBeenCalled();
expect(removeFunc).not.toHaveBeenCalled();
expect(api.deleteGoogleBrew).toHaveBeenCalled();
expect(saveFunc).toHaveBeenCalled();
expect(saved.authors).toEqual(['test2']);
expect(saved.googleId).toEqual(undefined);
expect(saved.text).toEqual(undefined);
expect(saved.textBin).not.toEqual(undefined);
});
it('should retain google brew and update stub when multiple authors and extra author requests deletion', async ()=>{
const brew = {
...googleBrew,
authors : ['test', 'test2']
};
api.getBrew = jest.fn(()=>async (req)=>{
req.brew = brew;
});
model.findOne = jest.fn(async ()=>modelBrew(brew));
api.deleteGoogleBrew = jest.fn(async ()=>true);
const req = { account: { username: 'test2' } };
await api.deleteBrew(req, res);
expect(api.getBrew).toHaveBeenCalled();
expect(model.findOne).toHaveBeenCalled();
expect(removeFunc).not.toHaveBeenCalled();
expect(api.deleteGoogleBrew).not.toHaveBeenCalled();
expect(saveFunc).toHaveBeenCalled();
expect(saved.authors).toEqual(['test']);
expect(saved.googleId).toEqual(brew.googleId);
});
});
});

View File

@@ -12,13 +12,14 @@ const HomebrewSchema = mongoose.Schema({
textBin : { type: Buffer },
pageCount : { type: Number, default: 1 },
description : { type: String, default: '' },
tags : [String],
systems : [String],
renderer : { type: String, default: '' },
authors : [String],
published : { type: Boolean, default: false },
thumbnail : { type: String, default: '' },
description : { type: String, default: '' },
tags : [String],
systems : [String],
renderer : { type: String, default: '' },
authors : [String],
invitedAuthors : [String],
published : { type: Boolean, default: false },
thumbnail : { type: String, default: '' },
createdAt : { type: Date, default: Date.now },
updatedAt : { type: Date, default: Date.now },
@@ -46,8 +47,6 @@ HomebrewSchema.statics.get = function(query, fields=null){
unzipped = zlib.inflateRawSync(brews[0].textBin);
brews[0].text = unzipped.toString();
}
if(!brews[0].renderer)
brews[0].renderer = 'legacy';
return resolve(brews[0]);
});
});

View File

@@ -0,0 +1,12 @@
module.exports = (req, res, next)=>{
const userVersion = req.get('Homebrewery-Version');
const version = require('../../package.json').version;
if(userVersion != version) {
return res.status(412).send({
message : `Client version ${userVersion} is out of date. Please save your changes elsewhere and refresh to pick up client version ${version}.`
});
}
next();
};

View File

@@ -229,6 +229,15 @@ const CodeEditor = createClass({
this.codeMirror.replaceSelection('\n\\page\n\n', 'end');
},
injectText : function(injectText, overwrite=true) {
const cm = this.codeMirror;
if(!overwrite) {
cm.setCursor(cm.getCursor('from'));
}
cm.replaceSelection(injectText, 'end');
cm.focus();
},
makeUnderline : function() {
const selection = this.codeMirror.getSelection(), t = selection.slice(0, 3) === '<u>' && selection.slice(-4) === '</u>';
this.codeMirror.replaceSelection(t ? selection.slice(3, -4) : `<u>${selection}</u>`, 'around');
@@ -355,12 +364,20 @@ const CodeEditor = createClass({
let text = '';
let currentLine = from.line;
const maxLength = 50;
let foldPreviewText = '';
while (currentLine <= to.line && text.length <= maxLength) {
text += this.codeMirror.getLine(currentLine);
if(currentLine < to.line)
text += ' ';
currentLine += 1;
const currentText = this.codeMirror.getLine(currentLine);
currentLine++;
if(currentText[0] == '#'){
foldPreviewText = currentText;
break;
}
if(!foldPreviewText && currentText != '\n') {
foldPreviewText = currentText;
}
}
text = foldPreviewText || `Lines ${from.line+1}-${to.line+1}`;
text = text.trim();
if(text.length > maxLength)

View File

@@ -13,7 +13,8 @@
font-family: inherit;
text-shadow: none;
font-weight: 600;
}
color: grey;
}
.sourceMoveFlash .CodeMirror-line{
animation-name: sourceMoveAnimation;

View File

@@ -32,7 +32,7 @@ const mustacheSpans = {
start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match
tokenizer(src, tokens) {
const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token
const inlineRegex = /{{(?::(?:"[\w,\-()#%. ]*"|[\w\,\-()#%.]*)|[^"'{}\s])*\s*|}}/g;
const inlineRegex = /{{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *|}}/g;
const match = completeSpan.exec(src);
if(match) {
//Find closing delimiter
@@ -82,7 +82,7 @@ const mustacheDivs = {
start(src) { return src.match(/\n *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match
tokenizer(src, tokens) {
const completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token
const blockRegex = /^ *{{(?::(?:"[\w,\-()#%. ]*"|[\w\,\-()#%.]*)|[^"'{}\s])* *$|^ *}}$/gm;
const blockRegex = /^ *{{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *$|^ *}}$/gm;
const match = completeBlock.exec(src);
if(match) {
//Find closing delimiter
@@ -130,7 +130,7 @@ const mustacheInjectInline = {
level : 'inline',
start(src) { return src.match(/ *{[^{\n]/)?.index; }, // Hint to Marked.js to stop and check for a match
tokenizer(src, tokens) {
const inlineRegex = /^ *{((?::(?:"[\w,\-()#%. ]*"|[\w\,\-()#%.]*)|[^"'{}\s])*)}/g;
const inlineRegex = /^ *{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1}/g;
const match = inlineRegex.exec(src);
if(match) {
const lastToken = tokens[tokens.length - 1];
@@ -165,7 +165,7 @@ const mustacheInjectBlock = {
level : 'block',
start(src) { return src.match(/\n *{[^{\n]/m)?.index; }, // Hint to Marked.js to stop and check for a match
tokenizer(src, tokens) {
const inlineRegex = /^ *{((?::(?:"[\w,\-()#%. ]*"|[\w\,\-()#%.]*)|[^"'{}\s])*)}/ym;
const inlineRegex = /^ *{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1}/ym;
const match = inlineRegex.exec(src);
if(match) {
const lastToken = tokens[tokens.length - 1];

View File

@@ -73,18 +73,35 @@ const Nav = {
dropdown : createClass({
displayName : 'Nav.dropdown',
getDefaultProps : function() {
return {
trigger : 'hover'
};
},
getInitialState : function() {
return {
showDropdown : false
};
},
componentDidMount : function() {
if(this.props.trigger == 'click')
document.addEventListener('click', this.handleClickOutside);
},
componentWillUnmount : function() {
if(this.props.trigger == 'click')
document.removeEventListener('click', this.handleClickOutside);
},
handleClickOutside : function(e){
// Close dropdown when clicked outside
if(this.refs.dropdown && !this.refs.dropdown.contains(e.target)) {
this.handleDropdown(false);
}
},
handleDropdown : function(show){
this.setState({
showDropdown : show
});
},
renderDropdown : function(dropdownChildren){
if(!this.state.showDropdown) return null;
@@ -94,7 +111,6 @@ const Nav = {
</div>
);
},
render : function () {
const dropdownChildren = React.Children.map(this.props.children, (child, i)=>{
// Ignore the first child
@@ -102,10 +118,12 @@ const Nav = {
return child;
});
return (
<div className='navDropdownContainer'
onMouseEnter={()=>this.handleDropdown(true)}
onMouseLeave={()=>this.handleDropdown(false)}>
{this.props.children[0]}
<div className={`navDropdownContainer ${this.props.className}`}
ref='dropdown'
onMouseEnter={this.props.trigger == 'hover' ? ()=>{this.handleDropdown(true);} : undefined}
onClick= {this.props.trigger == 'click' ? ()=>{this.handleDropdown(true);} : undefined}
onMouseLeave={this.props.trigger == 'hover' ? ()=>{this.handleDropdown(false);} : undefined}>
{this.props.children[0] || this.props.children /*children is not an array when only one child*/}
{this.renderDropdown(dropdownChildren)}
</div>
);

View File

@@ -69,7 +69,8 @@ const SplitPane = createClass({
this.setState({ isDragging: false });
},
handleDown : function(){
handleDown : function(e){
e.preventDefault();
this.setState({ isDragging: true });
//this.unFocus()
},

View File

@@ -22,7 +22,7 @@
vertical-align : middle;
text-align : center;
i{
display : block;
display : block !important;
margin : 10px 0px;
font-size : 6px;
color : #666;

View File

@@ -1 +1,27 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0}
:where(html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video){
border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0
}
:where(article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section){
display:block
}
:where(body){
line-height:1
}
:where(ol,ul){
list-style:none
}
:where(blockquote,q){
quotes:none
}
:where(blockquote:before,blockquote:after,q:before,q:after){
content:none
}
:where(table){
border-collapse:collapse;border-spacing:0
}

View File

@@ -9,8 +9,8 @@ describe('Tests for static pages', ()=>{
return app.get('/').expect(200);
});
it('Home page v3 works', ()=>{
return app.get('/v3_preview').expect(200);
it('Home page legacy works', ()=>{
return app.get('/legacy').expect(200);
});
it('Changelog page works', ()=>{

View File

@@ -0,0 +1,5 @@
{
"name" : "5e PHB",
"renderer" : "legacy",
"baseTheme" : false
}

View File

@@ -1,12 +1,12 @@
/* eslint-disable max-lines */
const MagicGen = require('./magic.gen.js');
const ClassTableGen = require('./classtable.gen.js');
const MonsterBlockGen = require('./monsterblock.gen.js');
const ClassFeatureGen = require('./classfeature.gen.js');
const CoverPageGen = require('./coverpage.gen.js');
const TableOfContentsGen = require('./tableOfContents.gen.js');
const dedent = require('dedent-tabs').default;
const MagicGen = require('./snippets/magic.gen.js');
const ClassTableGen = require('./snippets/classtable.gen.js');
const MonsterBlockGen = require('./snippets/monsterblock.gen.js');
const ClassFeatureGen = require('./snippets/classfeature.gen.js');
const CoverPageGen = require('./snippets/coverpage.gen.js');
const TableOfContentsGen = require('./snippets/tableOfContents.gen.js');
const dedent = require('dedent-tabs').default;
module.exports = [

View File

@@ -58,6 +58,7 @@ body {
text-rendering : optimizeLegibility;
page-break-before : always;
page-break-after : always;
contain : size;
//*****************************
// * BASE
// *****************************/

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -0,0 +1,6 @@
{
"name" : "5e DMG",
"renderer" : "V3",
"baseTheme" : "5ePHB",
"baseSnippets" : "5ePHB"
}

View File

@@ -0,0 +1,4 @@
/* eslint-disable max-lines */
module.exports = [
];

View File

@@ -0,0 +1,19 @@
:root {
//Colors
--HB_Color_Accent : #EBCEC3; // Salmon
--HB_Color_Footnotes : #5C5C5C; // Dark gray
}
.page {
background-image : url(/assets/DMG_background.png);
background-size : cover;
&:after {
background-image : url(/assets/DMG_footerAccent.png);
height: 58px;
}
.footnote {
bottom : 40px;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,6 @@
{
"name" : "5e PHB",
"renderer" : "V3",
"baseTheme" : false,
"baseSnippets" : false
}

265
themes/V3/5ePHB/snippets.js Normal file
View File

@@ -0,0 +1,265 @@
/* eslint-disable max-lines */
const MagicGen = require('./snippets/magic.gen.js');
const ClassTableGen = require('./snippets/classtable.gen.js');
const MonsterBlockGen = require('./snippets/monsterblock.gen.js');
const ClassFeatureGen = require('./snippets/classfeature.gen.js');
const CoverPageGen = require('./snippets/coverpage.gen.js');
const TableOfContentsGen = require('./snippets/tableOfContents.gen.js');
const dedent = require('dedent-tabs').default;
module.exports = [
{
groupName : 'Text Editor',
icon : 'fas fa-pencil-alt',
view : 'text',
snippets : [
{
name : 'Page Number',
icon : 'fas fa-bookmark',
gen : '{{pageNumber 1}}\n{{footnote PART 1 | SECTION NAME}}\n\n'
},
{
name : 'Auto-incrementing Page Number',
icon : 'fas fa-sort-numeric-down',
gen : '{{pageNumber,auto}}\n{{footnote PART 1 | SECTION NAME}}\n\n'
},
{
name : 'Table of Contents',
icon : 'fas fa-book',
gen : TableOfContentsGen
}
]
},
{
groupName : 'Style Editor',
icon : 'fas fa-pencil-alt',
view : 'style',
snippets : [
{
name : 'Remove Drop Cap',
icon : 'fas fa-remove-format',
gen : dedent`/* Removes Drop Caps */
.page h1+p:first-letter {
all: unset;
}\n\n
/* Removes Small-Caps in first line */
.page h1+p:first-line {
all: unset;
}`
},
{
name : 'Tweak Drop Cap',
icon : 'fas fa-sliders-h',
gen : dedent`/* Drop Cap settings */
.page h1 + p::first-letter {
font-family: SolberaImitationRemake;
font-size: 3.5cm;
background-image: linear-gradient(-45deg, #322814, #998250, #322814);
line-height: 1em;
}\n\n`
}
]
},
/*********************** IMAGES *******************/
{
groupName : 'Images',
icon : 'fas fa-images',
view : 'text',
snippets : [
{
name : 'Image',
icon : 'fas fa-image',
gen : dedent`
![cat warrior](https://s-media-cache-ak0.pinimg.com/736x/4a/81/79/4a8179462cfdf39054a418efd4cb743e.jpg) {width:325px,mix-blend-mode:multiply}
{{artist,position:relative,top:-230px,left:10px,margin-bottom:-30px
##### Cat Warrior
[Kyoung Hwan Kim](https://www.artstation.com/tahra)
}}`
},
{
name : 'Background Image',
icon : 'fas fa-tree',
gen : dedent`
![homebrew mug](http://i.imgur.com/hMna6G0.png) {position:absolute,top:50px,right:30px,width:280px}
{{artist,top:80px,right:30px
##### Homebrew Mug
[naturalcrit](https://homebrew.naturalcrit.com)
}}`
},
{
name : 'Watermark',
icon : 'fas fa-id-card',
gen : dedent`
{{watermark Homebrewery}}\n`
},
]
},
/************************* PHB ********************/
{
groupName : 'PHB',
icon : 'fas fa-book',
view : 'text',
snippets : [
{
name : 'Spell',
icon : 'fas fa-magic',
gen : MagicGen.spell,
},
{
name : 'Spell List',
icon : 'fas fa-scroll',
gen : MagicGen.spellList,
},
{
name : 'Class Feature',
icon : 'fas fa-mask',
gen : ClassFeatureGen,
},
{
name : 'Note',
icon : 'fas fa-sticky-note',
gen : function(){
return dedent`
{{note
##### Time to Drop Knowledge
Use notes to point out some interesting information.
**Tables and lists** both work within a note.
}}
\n`;
},
},
{
name : 'Descriptive Text Box',
icon : 'fas fa-comment-alt',
gen : function(){
return dedent`
{{descriptive
##### Time to Drop Knowledge
Use descriptive boxes to highlight text that should be read aloud.
**Tables and lists** both work within a descriptive box.
}}
\n`;
},
},
{
name : 'Monster Stat Block (unframed)',
icon : 'fas fa-paw',
gen : MonsterBlockGen.monster('monster', 2),
},
{
name : 'Monster Stat Block',
icon : 'fas fa-spider',
gen : MonsterBlockGen.monster('monster,frame', 2),
},
{
name : 'Wide Monster Stat Block',
icon : 'fas fa-dragon',
gen : MonsterBlockGen.monster('monster,frame,wide', 4),
},
{
name : 'Cover Page',
icon : 'fac book-front-cover',
gen : CoverPageGen,
experimental : true
},
{
name : 'Magic Item',
icon : 'fas fa-hat-wizard',
gen : MagicGen.item,
},
{
name : 'Artist Credit',
icon : 'fas fa-signature',
gen : function(){
return dedent`
{{artist,top:90px,right:30px
##### Starry Night
[Van Gogh](https://www.vangoghmuseum.nl/en)
}}
\n`;
},
},
]
},
/********************* TABLES *********************/
{
groupName : 'Tables',
icon : 'fas fa-table',
view : 'text',
snippets : [
{
name : 'Class Table',
icon : 'fas fa-table',
gen : ClassTableGen.full('classTable,frame,decoration,wide'),
},
{
name : 'Class Table (unframed)',
icon : 'fas fa-border-none',
gen : ClassTableGen.full('classTable,wide'),
},
{
name : '1/2 Class Table',
icon : 'fas fa-list-alt',
gen : ClassTableGen.half('classTable,decoration,frame'),
},
{
name : '1/2 Class Table (unframed)',
icon : 'fas fa-border-none',
gen : ClassTableGen.half('classTable'),
},
{
name : '1/3 Class Table',
icon : 'fas fa-border-all',
gen : ClassTableGen.third('classTable,frame'),
},
{
name : '1/3 Class Table (unframed)',
icon : 'fas fa-border-none',
gen : ClassTableGen.third('classTable'),
}
]
},
/**************** PAGE *************/
{
groupName : 'Print',
icon : 'fas fa-print',
view : 'style',
snippets : [
{
name : 'Ink Friendly',
icon : 'fas fa-tint',
gen : dedent`
/* Ink Friendly */
*:is(.page,.monster,.note,.descriptive) {
background : white !important;
filter : drop-shadow(0px 0px 3px #888) !important;
}
.page img {
visibility : hidden;
}\n\n`
},
]
}
];

View File

@@ -17,15 +17,15 @@ module.exports = function(classname){
return dedent`
## Class Features
As a ${classname}, you gain the following class features
#### Hit Points
As a ${classname}, you gain the following class features
#### Hit Points
**Hit Dice:** :: 1d${hitDie} per ${classname} level
**Hit Points at 1st Level:** :: ${hitDie} + your Constitution modifier
**Hit Points at Higher Levels:** :: 1d${hitDie} (or ${hitDie/2 + 1}) + your Constitution modifier per ${classname} level after 1st
#### Proficiencies
**Armor:** :: ${_.sampleSize(['Light armor', 'Medium armor', 'Heavy armor', 'Shields'], _.random(0, 3)).join(', ') || 'None'}
**Weapons:** :: ${_.sampleSize(['Squeegee', 'Rubber Chicken', 'Simple weapons', 'Martial weapons'], _.random(0, 2)).join(', ') || 'None'}
**Tools:** :: ${_.sampleSize(['Artisan\'s tools', 'one musical instrument', 'Thieves\' tools'], _.random(0, 2)).join(', ') || 'None'}
@@ -34,7 +34,6 @@ module.exports = function(classname){
**Skills:** :: Choose two from ${_.sampleSize(skillList, _.random(4, 6)).join(', ')}
#### Spellcasting Ability
{{text-align:center
**Spell save DC**:: = ${_.sample([6, 8, 10])} + your proficiency bonus + your ${spellSkill} modifier
@@ -46,6 +45,5 @@ module.exports = function(classname){
- *(a)* a martial weapon and a shield or *(b)* two martial weapons
- *(a)* five javelins or *(b)* any simple melee weapon
- ${_.sample(['10 lint fluffs', '1 button', 'a cherished lost sock'])}
`;
};

View File

@@ -0,0 +1,90 @@
const _ = require('lodash');
const dedent = require('dedent-tabs').default;
const titles = [
'The Burning Gallows', 'The Ring of Nenlast',
'Below the Blind Tavern', 'Below the Hungering River',
'Before Bahamut\'s Land', 'The Cruel Grave from Within',
'The Strength of Trade Road', 'Through The Raven Queen\'s Worlds',
'Within the Settlement', 'The Crown from Within',
'The Merchant Within the Battlefield', 'Ioun\'s Fading Traveler',
'The Legion Ingredient', 'The Explorer Lure',
'Before the Charming Badlands', 'Vecna\'s Hidden Sage',
'The Living Dead Above the Fearful Cage', 'Bahamut\'s Demonspawn',
'Across Gruumsh\'s Elemental Chaos', 'The Blade of Orcus',
'Beyond Revenge', 'Brain of Insanity',
'Breed Battle!, A New Beginning', 'Evil Lake, A New Beginning',
'Invasion of the Gigantic Cat, Part II', 'Kraken War 2020',
'The Body Whisperers', 'The Doctor from Heaven',
'The Diabolical Tales of the Ape-Women', 'The Doctor Immortal',
'Core of Heaven: Guardian of Amazement', 'The Graveyard',
'Guardian: Skies of the Dark Wizard', 'Lute of Eternity',
'Mercury\'s Planet: Brave Evolution', 'Azure Core',
'Sky of Zelda: The Thunder of Force', 'Core Battle',
'Ruby of Atlantis: The Quake of Peace', 'Deadly Amazement III',
'Dry Chaos IX', 'Gate Thunder',
'Vyse\'s Skies', 'White Greatness III',
'Yellow Divinity', 'Zidane\'s Ghost'
];
const subtitles = [
'Tomb of Shadows', 'Dragon\'s Lair',
'Lost Caverns', 'The Necromancer',
'Mystic Forest', 'Cursed Ruins',
'The Dark Abyss', 'Enchanted Maze',
'Haunted Castle', 'Sands of Fate',
'Dragon\'s Hoard', 'Undead Menace',
'Lost City Ruins', 'Goblin Ambush',
'Enchanted Forest', 'Darkness Rising',
'Quest for Glory', 'Ancient Prophecy',
'Shadowy Depths', 'Mystic Isles'
];
const footnote = [
'In an ominous universe, a botanist opposes terrorism.',
'In a demon-haunted city, in an age of lies and hate, a physicist tries to find an ancient treasure and battles a mob of aliens.',
'In a land of corruption, two cyberneticists and a dungeon delver search for freedom.',
'In an evil empire of horror, two rangers battle the forces of hell.',
'In a lost city, in an age of sorcery, a librarian quests for revenge.',
'In a universe of illusions and danger, three time travellers and an adventurer search for justice.',
'In a forgotten universe of barbarism, in an era of terror and mysticism, a virtual reality programmer and a spy try to find vengance and battle crime.',
'In a universe of demons, in an era of insanity and ghosts, three bodyguards and a bodyguard try to find vengance.',
'In a kingdom of corruption and battle, seven artificial intelligences try to save the last living fertile woman.',
'In a universe of virutal reality and agony, in an age of ghosts and ghosts, a fortune-teller and a wanderer try to avert the apocalypse.',
'In a crime-infested kingdom, three martial artists quest for the truth and oppose evil.',
'In a terrifying universe of lost souls, in an era of lost souls, eight dancers fight evil.',
'In a galaxy of confusion and insanity, three martial artists and a duke battle a mob of psychics.',
'In an amazing kingdom, a wizard and a secretary hope to prevent the destruction of mankind.',
'In a kingdom of deception, a reporter searches for fame.',
'In a hellish empire, a swordswoman and a duke try to find the ultimate weapon and battle a conspiracy.',
'In an evil galaxy of illusion, in a time of technology and misery, seven psychiatrists battle crime.',
'In a dark city of confusion, three swordswomen and a singer battle lawlessness.',
'In an ominous empire, in an age of hate, two philosophers and a student try to find justice and battle a mob of mages intent on stealing the souls of the innocent.',
'In a kingdom of panic, six adventurers oppose lawlessness.',
'In a land of dreams and hopelessness, three hackers and a cyborg search for justice.',
'On a planet of mysticism, three travelers and a fire fighter quest for the ultimate weapon and oppose evil.',
'In a wicked universe, five seers fight lawlessness.',
'In a kingdom of death, in an era of illusion and blood, four colonists search for fame.',
'In an amazing kingdom, in an age of sorcery and lost souls, eight space pirates quest for freedom.'
];
module.exports = ()=>{
return dedent`
{{coverPage }}
{{logo ![](/assets/naturalCritLogo.svg)}}
# ${_.sample(titles)}
## ${_.sample(subtitles)}
__________
{{banner HOMEBREW}}
{{footnote
${_.sample(footnote)}
}}
![background image](https://i.imgur.com/Mqx8Vf7.png)
\page`;
};

Some files were not shown because too many files have changed in this diff Show More