diff --git a/.circleci/config.yml b/.circleci/config.yml index 461a0dfa6..666a9564a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,12 +5,12 @@ version: 2.1 orbs: - node: circleci/node@3.0.0 + node: circleci/node@5.1.0 jobs: build: docker: - - image: cimg/node:16.11.0 + - image: cimg/node:20.8.0 - image: mongo:4.4 working_directory: ~/homebrewery @@ -27,7 +27,7 @@ jobs: # fallback to using the latest cache if no exact match is found - v1-dependencies- - - run: sudo npm install -g npm@8.10.0 + - run: sudo npm install -g npm@10.2.0 - node/install-packages: app-dir: ~/homebrewery cache-path: node_modules @@ -45,7 +45,7 @@ jobs: test: docker: - - image: cimg/node:16.11.0 + - image: cimg/node:20.8.0 working_directory: ~/homebrewery parallelism: 1 diff --git a/changelog.md b/changelog.md index 626a992d9..e86c2ea0f 100644 --- a/changelog.md +++ b/changelog.md @@ -75,11 +75,238 @@ pre { .page { padding-bottom: 1.5cm; } + +.varSyntaxTable th:first-of-type { + width:6cm; +} ``` ## changelog For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery). +### Wednesday 21/2/2024 - v3.11.0 +{{taskList + +##### Gazook89 + +* [x] Brew view count no longer increases when viewed by owner + +Fixes issue [#3037](https://github.com/naturalcrit/homebrewery/issues/3037) + +* [x] Small tweak to PHB H3 sizing + +Fixes issue [#2989](https://github.com/naturalcrit/homebrewery/issues/2989) + +* [x] Add **Fold/Unfold All** {{fas,fa-compress-alt}} / {{fas,fa-expand-alt}} buttons to editor bar + +Fixes issue [#2965](https://github.com/naturalcrit/homebrewery/issues/2965) + + +##### G-Ambatte + +* [x] Share link added to Editor Access error page + +Fixes issue [#3086](https://github.com/naturalcrit/homebrewery/issues/3086) + +* [x] Add Darkbrewery theme to Editor theme selector {{fas,fa-palette}} + +Fixes issue [#3034](https://github.com/naturalcrit/homebrewery/issues/3034) + +* [x] Fix Firefox prints with alternating blank pages + +Fixes issue [#3115](https://github.com/naturalcrit/homebrewery/issues/3115) + +* [x] Admin page working again + +Fixes issue [#2657](https://github.com/naturalcrit/homebrewery/issues/2657) + + +##### 5e-Cleric + +* [x] Fix indenting issue with Monster Blocks and italics in Class Feature + +Fixes issues [#527](https://github.com/naturalcrit/homebrewery/issues/527), +[#3247](https://github.com/naturalcrit/homebrewery/issues/3247) + +* [x] Allow CSS vars in curly syntax to be formatted as strings using single quotes + +`{{--customVar:"'a string'"}}` + +Fixes issue [#3066](https://github.com/naturalcrit/homebrewery/issues/3066) + +* [x] Add *Elderberry Inn* icons {{ei,action}} `{{ei,icon-name}}` + +Fixes issue [#3171](https://github.com/naturalcrit/homebrewery/issues/3171) + +* [x] New {{openSans **{{fas,fa-keyboard}} FONTS** }} snippets! + +Fixes issue [#3171](https://github.com/naturalcrit/homebrewery/issues/3171) + +* [x] New page now opens in a new tab + + +##### abquintic (new contributor!) + +* [x] Add ^super^ `^abc^` and ^^sub^^ `^^abc^^` syntax. + +Fixes issue [#2171](https://github.com/naturalcrit/homebrewery/issues/2171) + +* [x] Add HTML tag assignment to curly syntax `{{tag=value}}` + +Fixes issue [1488](https://github.com/naturalcrit/homebrewery/issues/1488) + +* [x] {{openSans **Brew → Clone to New**}} now clones tags + +Fixes issue [1488](https://github.com/naturalcrit/homebrewery/issues/1488) + +##### calculuschild + +* [x] Better error messages for "Out of Google Drive Storage" and "Not logged in to edit" + +Fixes issues [2510](https://github.com/naturalcrit/homebrewery/issues/2510), +[2975](https://github.com/naturalcrit/homebrewery/issues/2975) + +* [x] New Variables syntax. See below for details. +}} + +{{wide + +### Brew Variable Syntax + +You may already be familiar with `[link](url)` and `![image](url)` syntax. We have expanded this to include a third `$[variable](text)` syntax. All three of these syntaxes now share a common set of features: + +{{varSyntaxTable +| syntax | description | +|:-------|-------------| +| `[var]:content` | Assigns a variable (must start on a line by itself, and ends at the next blank line) | +| `[var](content)` | Assigns a variable and outputs it (can be inline) | +| `[var]` | Outputs the variable contents as a link, if formatted as a valid link | +| `![var]` | Outputs as an image, if formatted as a valid image | +| `$[var]` | Outputs as Markdown | +| `$[var1 + var2 - 2 * var3]` | Performs math operations and outputs result if all variables are valid numbers | +}} + +}} + +{{wide,margin-top:0,margin-bottom:0 +### Examples +}} + +{{wide,columns:2,margin-top:0,margin-bottom:0 + +``` +[first]: Bob + +[last]: Jones + +My name is $[first] $[last]. +``` + +\column + +[first]: Bob + +[last]: Jones + +My name is $[first] $[last]. + +}} + +{{wide,columns:2,margin-top:0,margin-bottom:0 + +``` +[myTable]: +| h1 | h2 | +|----|----| +| c1 | c2 | + +Here is my table: +$[myTable] +``` + +\column + +[myTable]: +| h1 | h2 | +|----|----| +| c1 | c2 | + +Here is my table: +$[myTable] +}} + +{{wide,columns:2,margin-top:0,margin-bottom:0 + +``` +There are $[TableNum] tables total. + +#### Table $[TableNum](1): Horses + +#### Table $[TableNum]($[TableNum + 1]): Cows +``` + +\column + +There are $[TableNum] tables in this document. *(note: final value of `$[TableNum]` gets hoisted up if available)* + + +#### Table $[TableNum](1): Horses + +#### Table $[TableNum]($[TableNum + 1]): Cows +}} + +\page + +### Friday 13/10/2023 - v3.10.0 +{{taskList + +##### G-Ambatte + +* [x] Fix user preferred save location being ignored + +Fixes issue [#2993](https://github.com/naturalcrit/homebrewery/issues/2993) + +* [x] Fix crash to white screen when starting new brews while not signed in + +Fixes issue [#2999](https://github.com/naturalcrit/homebrewery/issues/2999) + +* [x] Fix FreeBSD install script + +Fixes issue [#3005](https://github.com/naturalcrit/homebrewery/issues/3005) + +* [x] Fix *"This brew has been changed on another device"* triggering when manually saving during auto-save + +Fixes issue [#2641](https://github.com/naturalcrit/homebrewery/issues/2641) + +* [x] Fix Firefox different column-flow behavior + +Fixes issue [#2982](https://github.com/naturalcrit/homebrewery/issues/2982) + +* [x] Fix brew titles being mis-sorted on user page + +Fixes issue [#2775](https://github.com/naturalcrit/homebrewery/issues/2775) + +* [x] Text Editor themes now available via new drop-down + +Fixes issue [#362](https://github.com/naturalcrit/homebrewery/issues/362) + +##### 5e-Cleric + +* [x] New {{openSans **PHB → {{fas,fa-quote-right}} QUOTE** }} snippet for V3! + +Fixes issue [#2920](https://github.com/naturalcrit/homebrewery/issues/2920) + +* [x] Several updates and fixes to FAQ and Welcome page + +Fixes issue [#2729](https://github.com/naturalcrit/homebrewery/issues/2729), +[#2787](https://github.com/naturalcrit/homebrewery/issues/2787) + +##### Gazook89 + +* [x] Add syntax highlighting for Definition Lists :\: +}} + + ### Thursday 17/08/2023 - v3.9.2 {{taskList @@ -119,14 +346,15 @@ Fixes issue [#2943](https://github.com/naturalcrit/homebrewery/issues/2943) * [x] Exclude cover pages from Table of Content generation (editing on mobile is still not recommended) -Fixes issue [#2920](https://github.com/naturalcrit/homebrewery/issues/2920) +Fixes issue [#2920](https://github.com/naturalcrit/homebrewery/issues/2920) ##### Gazook89 * [x] Adjustments to improve mobile viewing - }} + + ### Wednesday 28/06/2023 - v3.9.1 {{taskList @@ -171,6 +399,8 @@ Fixes issue [#2790](https://github.com/naturalcrit/homebrewery/issues/2790) Fixes issue [#2784](https://github.com/naturalcrit/homebrewery/issues/2784) }} +\page + ### Wednesday 12/04/2023 - v3.8.0 {{taskList @@ -232,8 +462,6 @@ Fixes issues [#2731](https://github.com/naturalcrit/homebrewery/issues/2731) }} -\page - ### Monday 13/03/2023 - v3.7.2 {{taskList @@ -314,7 +542,11 @@ Fixes issues [#2603](https://github.com/naturalcrit/homebrewery/issues/2603) * [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) +}} +\page + +{{taskList ##### G-Ambatte * [x] Auto-compile Themes CSS on development server @@ -324,7 +556,6 @@ Fixes issues [#2583](https://github.com/naturalcrit/homebrewery/issues/2583) * [x] Fix cloned brews inheriting the parent view count }} -\page ### Friday 23/12/2022 - v3.5.0 {{taskList @@ -1408,4 +1639,4 @@ Massive changelog incoming: * Added `phb.standalone.css` plus a build system for creating it * Added page numbers and footer text -* Page accent now flips each page +* Page accent now flips each page \ No newline at end of file diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 51921c8ca..f1c9cdeda 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -1,9 +1,8 @@ /*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/ require('./brewRenderer.less'); const React = require('react'); -const createClass = require('create-react-class'); +const { useState, useRef, useEffect } = React; const _ = require('lodash'); -const cx = require('classnames'); const MarkdownLegacy = require('naturalcrit/markdownLegacy.js'); const Markdown = require('naturalcrit/markdown.js'); @@ -13,244 +12,226 @@ const ErrorBar = require('./errorBar/errorBar.jsx'); const RenderWarnings = require('homebrewery/renderWarnings/renderWarnings.jsx'); const NotificationPopup = require('./notificationPopup/notificationPopup.jsx'); const Frame = require('react-frame-component').default; +const dedent = require('dedent-tabs').default; const Themes = require('themes/themes.json'); const PAGE_HEIGHT = 1056; -const PPR_THRESHOLD = 50; -const BrewRenderer = createClass({ - displayName : 'BrewRenderer', - getDefaultProps : function() { - return { - text : '', - style : '', - renderer : 'legacy', - theme : '5ePHB', - lang : '', - errors : [] - }; - }, - getInitialState : function() { - let pages; - if(this.props.renderer == 'legacy') { - pages = this.props.text.split('\\page'); - } else { - pages = this.props.text.split(/^\\page$/gm); - } +const INITIAL_CONTENT = dedent` + + + + + +
`; - return { - viewablePageNumber : 0, - height : 0, - isMounted : false, +//v=====----------------------< Brew Page Component >---------------------=====v// +const BrewPage = (props)=>{ + props = { + contents : '', + index : 0, + ...props + }; + return
+
+
; +}; - pages : pages, - usePPR : pages.length >= PPR_THRESHOLD, - visibility : 'hidden', - initialContent : ` - - - - -
` - }; - }, - height : 0, - lastRender :
, - componentWillUnmount : function() { - window.removeEventListener('resize', this.updateSize); - }, +//v=====--------------------< Brew Renderer Component >-------------------=====v// +const renderedPages = []; +let rawPages = []; - componentDidUpdate : function(prevProps) { - if(prevProps.text !== this.props.text) { - let pages; - if(this.props.renderer == 'legacy') { - pages = this.props.text.split('\\page'); - } else { - pages = this.props.text.split(/^\\page$/gm); - } - this.setState({ - pages : pages, - usePPR : pages.length >= PPR_THRESHOLD - }); - } - }, +const BrewRenderer = (props)=>{ + props = { + text : '', + style : '', + renderer : 'legacy', + theme : '5ePHB', + lang : '', + errors : [], + currentEditorPage : 0, + ...props + }; - updateSize : function() { - this.setState({ - height : this.refs.main.parentNode.clientHeight, - }); - }, + const [state, setState] = useState({ + viewablePageNumber : 0, + height : PAGE_HEIGHT, + isMounted : false, + visibility : 'hidden', + }); - handleScroll : function(e){ - const target = e.target; - this.setState((prevState)=>({ - viewablePageNumber : Math.floor(target.scrollTop / target.scrollHeight * prevState.pages.length) + const mainRef = useRef(null); + + if(props.renderer == 'legacy') { + rawPages = props.text.split('\\page'); + } else { + rawPages = props.text.split(/^\\page$/gm); + } + + useEffect(()=>{ // Unmounting steps + return ()=>{window.removeEventListener('resize', updateSize);}; + }, []); + + const updateSize = ()=>{ + setState((prevState)=>({ + ...prevState, + height : mainRef.current.parentNode.clientHeight, })); - }, + }; - shouldRender : function(pageText, index){ - if(!this.state.isMounted) return false; + const handleScroll = (e)=>{ + const target = e.target; + setState((prevState)=>({ + ...prevState, + viewablePageNumber : Math.floor(target.scrollTop / target.scrollHeight * rawPages.length) + })); + }; - const viewIndex = this.state.viewablePageNumber; - if(index == viewIndex - 3) return true; - if(index == viewIndex - 2) return true; - if(index == viewIndex - 1) return true; - if(index == viewIndex) return true; - if(index == viewIndex + 1) return true; - if(index == viewIndex + 2) return true; - if(index == viewIndex + 3) return true; + const isInView = (index)=>{ + if(!state.isMounted) + return false; - //Check for style tages - if(pageText.indexOf('` }} />; + const renderStyle = ()=>{ + if(!props.style) return; + const cleanStyle = sanitizeScriptTags(props.style); + //return
@layer styleTab {\n${sanitizeScriptTags(props.style)}\n} ` }} />; return
${cleanStyle} ` }} />; - }, + }; - renderPage : function(pageText, index){ - let cleanPageText = this.sanitizeScriptTags(pageText); - if(this.props.renderer == 'legacy') - return
; - else { + const renderPage = (pageText, index)=>{ + let cleanPageText = sanitizeScriptTags(pageText); + if(props.renderer == 'legacy') { + const html = MarkdownLegacy.render(cleanPageText); + return ; + } else { cleanPageText += `\n\n \n\\column\n `; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear) - return ( -
-
-
- ); + const html = Markdown.render(cleanPageText, index); + return ; } - }, + }; - renderPages : function(){ - if(this.state.usePPR){ - return _.map(this.state.pages, (page, index)=>{ - if(this.shouldRender(page, index) && typeof window !== 'undefined'){ - return this.renderPage(page, index); - } else { - return this.renderDummyPage(index); - } - }); - } - if(this.props.errors && this.props.errors.length) return this.lastRender; - this.lastRender = _.map(this.state.pages, (page, index)=>{ - if(typeof window !== 'undefined') { - return this.renderPage(page, index); - } else { - return this.renderDummyPage(index); + const renderPages = ()=>{ + if(props.errors && props.errors.length) + return renderedPages; + + if(rawPages.length != renderedPages.length) // Re-render all pages when page count changes + renderedPages.length = 0; + + // Render currently-edited page first so cross-page effects (variables, links) can propagate out first + renderedPages[props.currentEditorPage] = renderPage(rawPages[props.currentEditorPage], props.currentEditorPage); + + _.forEach(rawPages, (page, index)=>{ + if((isInView(index) || !renderedPages[index]) && typeof window !== 'undefined'){ + renderedPages[index] = renderPage(page, index); // Render any page not yet rendered, but only re-render those in PPR range } }); - return this.lastRender; - }, + return renderedPages; + }; - frameDidMount : function(){ //This triggers when iFrame finishes internal "componentDidMount" + const frameDidMount = ()=>{ //This triggers when iFrame finishes internal "componentDidMount" setTimeout(()=>{ //We still see a flicker where the style isn't applied yet, so wait 100ms before showing iFrame - this.updateSize(); - window.addEventListener('resize', this.updateSize); - this.renderPages(); //Make sure page is renderable before showing - this.setState({ + updateSize(); + window.addEventListener('resize', updateSize); + renderPages(); //Make sure page is renderable before showing + setState((prevState)=>({ + ...prevState, isMounted : true, visibility : 'visible' - }); + })); }, 100); - }, + }; - emitClick : function(){ - // console.log('iFrame clicked'); + const emitClick = ()=>{ // Allow clicks inside iFrame to interact with dropdowns, etc. from outside if(!window || !document) return; document.dispatchEvent(new MouseEvent('click')); - }, + }; - 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 ( - - {!this.state.isMounted - ?
-
- {this.renderDummyPage(1)} -
+ const rendererPath = props.renderer == 'V3' ? 'V3' : 'Legacy'; + const themePath = props.theme ?? '5ePHB'; + const baseThemePath = Themes[rendererPath][themePath].baseTheme; + + return ( + <> + {/*render dummy page while iFrame is mounting.*/} + {!state.isMounted + ?
+
+ {renderDummyPage(1)}
- : null} +
+ : null} - {this.emitClick();}} - > -
+ {/*render in iFrame so broken code doesn't crash the site.*/} + {emitClick();}} + > +
- -
- - -
- - {baseThemePath && - - } - - {/* Apply CSS from Style tab and render pages from Markdown tab */} - {this.state.isMounted - && - <> - {this.renderStyle()} -
- {this.renderPages()} -
- - } + +
+ +
- - {this.renderPageInfo()} - {this.renderPPRmsg()} - - ); - } -}); + + {baseThemePath && + + } + + + {/* Apply CSS from Style tab and render pages from Markdown tab */} + {state.isMounted + && + <> + {renderStyle()} +
+ {renderPages()} +
+ + } +
+ + {renderPageInfo()} + + ); +}; module.exports = BrewRenderer; diff --git a/client/homebrew/brewRenderer/brewRenderer.less b/client/homebrew/brewRenderer/brewRenderer.less index bde91c92e..17aa146fb 100644 --- a/client/homebrew/brewRenderer/brewRenderer.less +++ b/client/homebrew/brewRenderer/brewRenderer.less @@ -1,46 +1,44 @@ @import (multiple, less) 'shared/naturalcrit/styles/reset.less'; -.brewRenderer{ +.brewRenderer { will-change : transform; overflow-y : scroll; - .pages{ + :where(.pages) { margin : 30px 0px; - &>.page{ + & > :where(.page) { + width : 215.9mm; + height : 279.4mm; margin-right : auto; margin-bottom : 30px; margin-left : auto; - box-shadow : 1px 4px 14px #000; + box-shadow : 1px 4px 14px #000000; } } } -.pane{ - position : relative; -} -.pageInfo{ +.pane { position : relative; } +.pageInfo { position : absolute; right : 17px; bottom : 0; z-index : 1000; - background-color : #333; font-size : 10px; font-weight : 800; color : white; + background-color : #333333; div { - display: inline-block; + display : inline-block; padding : 8px 10px; - &:not(:last-child){ - border-right: 1px solid #666; - } + &:not(:last-child) { border-right : 1px solid #666666; } } } -.ppr_msg{ +.ppr_msg { position : absolute; - left : 0px; bottom : 0; + left : 0px; z-index : 1000; padding : 8px 10px; - background-color : #333; font-size : 10px; font-weight : 800; color : white; + background-color : #333333; } diff --git a/client/homebrew/brewRenderer/notificationPopup/notificationPopup.jsx b/client/homebrew/brewRenderer/notificationPopup/notificationPopup.jsx index 3c706d6f7..5a870c108 100644 --- a/client/homebrew/brewRenderer/notificationPopup/notificationPopup.jsx +++ b/client/homebrew/brewRenderer/notificationPopup/notificationPopup.jsx @@ -25,13 +25,10 @@ const NotificationPopup = createClass({ return ( <>
  • - Broken default logo on CoverPage
    - If you have used the Cover Page snippet and notice the Naturalcrit - logo is showing as a broken image, this is due to some small tweaks - of this BETA feature. To fix the logo in your cover page, rename - the image link "/assets/naturalCritLogoRed.svg". Remember - that any snippet marked "BETA" may have a similar change in the - future as we encounter any bugs or reworks. + Don't store IMAGES in Google Drive
    + Google Drive is not an image service, and will block images from being used + in brews if they get more views than expected. Google has confirmed they won't fix + this, so we recommend you look for another image hosting service such as imgur, ImgBB or Google Photos.
  • diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index d6502e985..d79d2ce4e 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -149,9 +149,38 @@ const Editor = createClass({ codeMirror.addLineClass(lineNumber, 'text', 'columnSplit'); } + // definition lists + if(line.includes('::')){ + const regex = /^([^\n]*?)::([^\n]*)(?:\n|$)/ym; + let match; + while ((match = regex.exec(line)) != null){ + codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[0]) }, { line: lineNumber, ch: line.indexOf(match[0]) + match[0].length }, { className: 'define' }); + codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length }, { className: 'term' }); + codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[2]) }, { line: lineNumber, ch: line.indexOf(match[2]) + match[2].length }, { className: 'definition' }); + } + } + + // Superscript + if(line.includes('\^')) { + const regex = /\^(?!\s)(?=([^\n\^]*[^\s\^]))\1\^/g; + let match; + while ((match = regex.exec(line)) != null) { + codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) - 1 }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length + 1 }, { className: 'superscript' }); + } + } + + // Subscript + if(line.includes('^^')) { + const regex = /\^\^(?!\s)(?=([^\n\^]*[^\s\^]))\1\^\^/g; + let match; + while ((match = regex.exec(line)) != null) { + codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) - 2 }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length + 2 }, { className: 'subscript' }); + } + } + // Highlight injectors {style} if(line.includes('{') && line.includes('}')){ - const regex = /(?:^|[^{\n])({(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\2})/gm; + 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' }); @@ -159,7 +188,7 @@ const Editor = createClass({ } // Highlight inline spans {{content}} if(line.includes('{{') && line.includes('}}')){ - const regex = /{{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *|}}/g; + const regex = /{{(?=((?:[:=](?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':={}\s]*)*))\1 *|}}/g; let match; let blockCount = 0; while ((match = regex.exec(line)) != null) { @@ -178,7 +207,7 @@ const Editor = createClass({ // Highlight block divs {{\n Content \n}} let endCh = line.length+1; - const match = line.match(/^ *{{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *$|^ *}}$/); + 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' }); @@ -330,6 +359,14 @@ const Editor = createClass({ return this.refs.codeEditor?.undo(); }, + foldCode : function(){ + return this.refs.codeEditor?.foldAllCode(); + }, + + unfoldCode : function(){ + return this.refs.codeEditor?.unfoldAllCode(); + }, + render : function(){ return (
    @@ -343,6 +380,8 @@ const Editor = createClass({ theme={this.props.brew.theme} undo={this.undo} redo={this.redo} + foldCode={this.foldCode} + unfoldCode={this.unfoldCode} historySize={this.historySize()} currentEditorTheme={this.state.editorTheme} updateEditorTheme={this.updateEditorTheme} diff --git a/client/homebrew/editor/editor.less b/client/homebrew/editor/editor.less index db88b5b0f..b165f91db 100644 --- a/client/homebrew/editor/editor.less +++ b/client/homebrew/editor/editor.less @@ -1,65 +1,85 @@ @import 'themes/codeMirror/customEditorStyles.less'; -.editor{ +.editor { position : relative; width : 100%; - .codeEditor{ + .codeEditor { height : 100%; - .pageLine{ + .pageLine { background : #33333328; - border-top : #339 solid 1px; + border-top : #333399 solid 1px; } - .editor-page-count{ - color : grey; + .editor-page-count { float : right; + color : grey; } - .columnSplit{ - font-style : italic; - color : grey; - background-color : fade(#299, 15%); - border-bottom : #299 solid 1px; + .columnSplit { + font-style : italic; + color : grey; + background-color : fade(#229999, 15%); + border-bottom : #229999 solid 1px; } - .block:not(.cm-comment){ - color : purple; + .define { + &:not(.term):not(.definition) { + font-weight : bold; + color : #949494; + background : #E5E5E5; + border-radius : 3px; + } + &.term { color : rgb(96, 117, 143); } + &.definition { color : rgb(97, 57, 178); } + } + .block:not(.cm-comment) { font-weight : bold; + color : purple; //font-style: italic; } - .inline-block:not(.cm-comment){ - color : red; + .inline-block:not(.cm-comment) { font-weight : bold; + color : red; //font-style: italic; } - .injection:not(.cm-comment){ + .injection:not(.cm-comment) { + font-weight : bold; color : green; - font-weight : bold; + } + .superscript:not(.cm-comment) { + font-weight : bold; + color : goldenrod; + vertical-align : super; + font-size : 0.9em; + } + .subscript:not(.cm-comment) { + font-weight : bold; + color : rgb(123, 123, 15); + vertical-align : sub; + font-size : 0.9em; } } - .brewJump{ - position : absolute; - background-color : @teal; - cursor : pointer; - width : 30px; - height : 30px; - display : flex; - align-items : center; - bottom : 20px; - right : 20px; - z-index : 1000000; - justify-content : center; - .tooltipLeft("Jump to brew page"); + .brewJump { + position : absolute; + right : 20px; + bottom : 20px; + z-index : 1000000; + display : flex; + align-items : center; + justify-content : center; + width : 30px; + height : 30px; + cursor : pointer; + background-color : @teal; + .tooltipLeft('Jump to brew page'); } - .editorToolbar{ - position: absolute; - top: 5px; - left: 50%; - color: black; - font-size: 13px; - z-index: 9; - span { - padding: 2px 5px; - } + .editorToolbar { + position : absolute; + top : 5px; + left : 50%; + z-index : 9; + font-size : 13px; + color : black; + span { padding : 2px 5px; } } } diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.less b/client/homebrew/editor/metadataEditor/metadataEditor.less index 5678c2554..7f7ce3060 100644 --- a/client/homebrew/editor/metadataEditor/metadataEditor.less +++ b/client/homebrew/editor/metadataEditor/metadataEditor.less @@ -2,7 +2,7 @@ .metadataEditor{ position : absolute; - z-index : 10000; + z-index : 5; box-sizing : border-box; width : 100%; padding : 25px; diff --git a/client/homebrew/editor/snippetbar/snippetbar.jsx b/client/homebrew/editor/snippetbar/snippetbar.jsx index 246d534a9..75fe0d736 100644 --- a/client/homebrew/editor/snippetbar/snippetbar.jsx +++ b/client/homebrew/editor/snippetbar/snippetbar.jsx @@ -37,6 +37,8 @@ const Snippetbar = createClass({ undo : ()=>{}, redo : ()=>{}, historySize : ()=>{}, + foldCode : ()=>{}, + unfoldCode : ()=>{}, updateEditorTheme : ()=>{}, cursorPos : {} }; @@ -72,6 +74,7 @@ const Snippetbar = createClass({ } }, + 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 @@ -100,10 +103,12 @@ const Snippetbar = createClass({ this.props.onInject(injectedText); }, - toggleThemeSelector : function(){ - this.setState({ - themeSelector : !this.state.themeSelector - }); + toggleThemeSelector : function(e){ + if(e.target.tagName != 'SELECT'){ + this.setState({ + themeSelector : !this.state.themeSelector + }); + } }, changeTheme : function(e){ @@ -117,7 +122,7 @@ const Snippetbar = createClass({ renderThemeSelector : function(){ return
    - {EditorThemes.map((theme, key)=>{ return ; })} @@ -144,6 +149,22 @@ const Snippetbar = createClass({ renderEditorButtons : function(){ if(!this.props.showEditButtons) return; + let foldButtons; + if(this.props.view == 'text'){ + foldButtons = + <> +
    + +
    +
    + +
    + + + } + return
    @@ -154,11 +175,13 @@ const Snippetbar = createClass({
    + {foldButtons}
    + {this.state.themeSelector && this.renderThemeSelector()}
    - {this.state.themeSelector && this.renderThemeSelector()} +
    this.props.onViewChange('text')}> @@ -209,7 +232,7 @@ const SnippetGroup = createClass({ return _.map(snippets, (snippet)=>{ return
    this.handleSnippetClick(e, snippet)}> - {snippet.name} + {snippet.name} {snippet.experimental && beta} {snippet.subsnippets && <> diff --git a/client/homebrew/editor/snippetbar/snippetbar.less b/client/homebrew/editor/snippetbar/snippetbar.less index ed2dcebce..be6ebe11a 100644 --- a/client/homebrew/editor/snippetbar/snippetbar.less +++ b/client/homebrew/editor/snippetbar/snippetbar.less @@ -1,162 +1,190 @@ @import (less) './client/icons/customIcons.less'; -.snippetBar{ +@import (less) '././././themes/fonts/5e/fonts.less'; + +.snippetBar { @menuHeight : 25px; position : relative; height : @menuHeight; - background-color : #ddd; - .editors{ + color : black; + background-color : #DDDDDD; + + .editors { position : absolute; - display : flex; top : 0px; right : 0px; - height : @menuHeight; - width : 125px; + display : flex; justify-content : space-between; - &>div{ - height : @menuHeight; + height : @menuHeight; + & > div { width : @menuHeight; - cursor : pointer; + height : @menuHeight; line-height : @menuHeight; text-align : center; - &:hover,&.selected{ - background-color : #999; - } - &.text{ + cursor : pointer; + &:hover,&.selected { background-color : #999999; } + &.text { .tooltipLeft('Brew Editor'); } - &.style{ + &.style { .tooltipLeft('Style Editor'); } - &.meta{ + &.meta { .tooltipLeft('Properties'); } - &.undo{ + &.undo { .tooltipLeft('Undo'); font-size : 0.75em; color : grey; - &.active{ - color : black; - } + &.active { color : inherit; } } - &.redo{ + &.redo { .tooltipLeft('Redo'); font-size : 0.75em; color : grey; - &.active{ - color : black; - } + &.active { color : inherit; } } - &.editorTheme{ + &.foldAll { + .tooltipLeft('Fold All'); + font-size : 0.75em; + color : inherit; + } + &.unfoldAll { + .tooltipLeft('Unfold All'); + font-size : 0.75em; + color : inherit; + } + &.editorTheme { .tooltipLeft('Editor Themes'); font-size : 0.75em; color : black; - &.active{ - color : white; - background-color: black; + &.active { + position : relative; + background-color : #999999; } } &.divider { - background: linear-gradient(#000, #000) no-repeat center/1px 100%; - width: 5px; - &:hover{ - background-color: inherit; - } + width : 5px; + background : linear-gradient(currentColor, currentColor) no-repeat center/1px 100%; + &:hover { background-color : inherit; } } } - .themeSelector{ - position: absolute; - left: -65px; - top: 30px; - z-index: 999; - width: 170px; - background-color: black; - border-radius: 5px; + .themeSelector { + position : absolute; + top : 25px; + right : 0; + z-index : 10; + display : flex; + align-items : center; + justify-content : center; + width : 170px; + height : inherit; + background-color : inherit; } } - .snippetBarButton{ - height : @menuHeight; - line-height : @menuHeight; + .snippetBarButton { display : inline-block; + height : @menuHeight; padding : 0px 5px; - font-weight : 800; font-size : 0.625em; + font-weight : 800; + line-height : @menuHeight; text-transform : uppercase; cursor : pointer; - &:hover, &.selected{ - background-color : #999; - } - i{ - vertical-align : middle; + &:hover, &.selected { background-color : #999999; } + i { margin-right : 3px; font-size : 1.4em; + vertical-align : middle; } } - .toggleMeta{ - position : absolute; - top : 0px; - right : 0px; - border-left : 1px solid black; - .tooltipLeft("Edit Brew Properties"); + .toggleMeta { + position : absolute; + top : 0px; + right : 0px; + border-left : 1px solid black; + .tooltipLeft('Edit Brew Properties'); } - .snippetGroup{ - border-right : 1px solid black; - &:hover{ - &>.dropdown{ - visibility : visible; - } + .snippetGroup { + border-right : 1px solid currentColor; + &:hover { + & > .dropdown { visibility : visible; } } - .dropdown{ + .dropdown { position : absolute; top : 100%; - visibility : hidden; z-index : 1000; - margin-left : -5px; padding : 0px; - background-color : #ddd; - .snippet{ - position: relative; - .animate(background-color); + margin-left : -5px; + visibility : hidden; + background-color : #DDDDDD; + .snippet { + position : relative; display : flex; align-items : center; min-width : max-content; padding : 5px; - cursor : pointer; font-size : 10px; - i{ + cursor : pointer; + .animate(background-color); + i { + height : 1.2em; margin-right : 8px; font-size : 1.2em; - height : 1.2em; - &~i{ - margin-right: 0; - margin-left: 5px; + & ~ i { + margin-right : 0; + margin-left : 5px; + } + /* Fonts */ + &.font { + height : auto; + &::before { + font-size : 1.4em; + content : 'ABC'; + } + + &.OpenSans {font-family : 'OpenSans';} + &.CodeBold {font-family : 'CodeBold';} + &.CodeLight {font-family : 'CodeLight';} + &.ScalySansRemake {font-family : 'ScalySansRemake';} + &.BookInsanityRemake {font-family : 'BookInsanityRemake';} + &.MrEavesRemake {font-family : 'MrEavesRemake';} + &.SolberaImitationRemake {font-family : 'SolberaImitationRemake';} + &.ScalySansSmallCapsRemake {font-family : 'ScalySansSmallCapsRemake';} + &.WalterTurncoat {font-family : 'WalterTurncoat';} + &.Lato {font-family : 'Lato';} + &.Courier {font-family : 'Courier';} + &.NodestoCapsCondensed {font-family : 'NodestoCapsCondensed';} + &.Overpass {font-family : 'Overpass';} + &.Davek {font-family : 'Davek';} + &.Iokharic {font-family : 'Iokharic';} + &.Rellanic {font-family : 'Rellanic';} + &.TimesNewRoman {font-family : 'Times New Roman';} } } - .name { - margin-right : auto; - } + .name { margin-right : auto; } .beta { - color : white; - padding : 4px 6px; - line-height : 1em; - margin-left : 5px; align-self : center; + padding : 4px 6px; + margin-left : 5px; + font-family : monospace; + line-height : 1em; + color : white; background : grey; border-radius : 12px; - font-family : monospace; } - &:hover{ - background-color : #999; - &>.dropdown{ + &:hover { + background-color : #999999; + & > .dropdown { visibility : visible; &.side { - left: 100%; - top: 0%; - margin-left:0; - box-shadow: -1px 1px 2px 0px #999; + top : 0%; + left : 100%; + margin-left : 0; + box-shadow : -1px 1px 2px 0px #999999; } } } } } } -} +} \ No newline at end of file diff --git a/client/homebrew/navbar/error-navitem.jsx b/client/homebrew/navbar/error-navitem.jsx index eb2872c22..8551408c5 100644 --- a/client/homebrew/navbar/error-navitem.jsx +++ b/client/homebrew/navbar/error-navitem.jsx @@ -21,10 +21,11 @@ const ErrorNavItem = createClass({ this.props.parent.setState(state); }; - const error = this.props.error; - const response = error.response; - const status = response.status; - const message = response.body?.message; + const error = this.props.error; + const response = error.response; + const status = response.status; + const HBErrorCode = response.body?.HBErrorCode; + const message = response.body?.message; let errMsg = ''; try { errMsg += `${error.toString()}\n\n`; @@ -40,7 +41,9 @@ const ErrorNavItem = createClass({ {message ?? 'Conflict: please refresh to get latest changes'}
    ; - } else if(status === 412) { + } + + if(status === 412) { return Oops!
    @@ -48,6 +51,36 @@ const ErrorNavItem = createClass({
    ; } + + if(HBErrorCode === '04') { + return + Oops! +
    + You are no longer signed in as an author of + this brew! Were you signed out from a different + window? Visit our log in page, then try again! +

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

    diff --git a/client/homebrew/navbar/newbrew.navitem.jsx b/client/homebrew/navbar/newbrew.navitem.jsx index 2cbbce466..cc833013d 100644 --- a/client/homebrew/navbar/newbrew.navitem.jsx +++ b/client/homebrew/navbar/newbrew.navitem.jsx @@ -4,6 +4,7 @@ const Nav = require('naturalcrit/nav/nav.jsx'); module.exports = function(props){ return new diff --git a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx index 56c08e2af..90f9d32f2 100644 --- a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx +++ b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx @@ -125,7 +125,7 @@ const BrewItem = createClass({
    {brew.tags?.length ? <> -
    +
    {brew.tags.map((tag, idx)=>{ const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/); @@ -135,7 +135,11 @@ const BrewItem = createClass({ : <> } - {brew.authors?.join(', ')} + {brew.authors?.map((author, index)=>( + <> + {author} + {index < brew.authors.length - 1 && ', '} + ))}
    diff --git a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less index e8c7aa39a..5a1bb3d92 100644 --- a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less +++ b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less @@ -48,6 +48,10 @@ &>span{ margin-right : 12px; line-height : 1.5em; + + a { + color:inherit; + } } } .brewTags span { diff --git a/client/homebrew/pages/basePages/listPage/listPage.jsx b/client/homebrew/pages/basePages/listPage/listPage.jsx index 2696d4e7a..d0cd11ec6 100644 --- a/client/homebrew/pages/basePages/listPage/listPage.jsx +++ b/client/homebrew/pages/basePages/listPage/listPage.jsx @@ -220,6 +220,7 @@ const ListPage = createClass({ render : function(){ return
    {/**/} + {this.props.navItems} {this.renderSortOptions()} diff --git a/client/homebrew/pages/basePages/listPage/listPage.less b/client/homebrew/pages/basePages/listPage/listPage.less index bcffbf3e7..00d753429 100644 --- a/client/homebrew/pages/basePages/listPage/listPage.less +++ b/client/homebrew/pages/basePages/listPage/listPage.less @@ -2,17 +2,18 @@ .noColumns(){ column-count : auto; column-fill : auto; - column-gap : auto; + column-gap : normal; column-width : auto; -webkit-column-count : auto; -moz-column-count : auto; -webkit-column-width : auto; -moz-column-width : auto; - -webkit-column-gap : auto; - -moz-column-gap : auto; + -webkit-column-gap : normal; + -moz-column-gap : normal; height : auto; min-height : 279.4mm; margin : 20px auto; + contain : unset; } .listPage{ .content{ diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index bb9b5ca52..d5af310b5 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -50,7 +50,8 @@ const EditPage = createClass({ url : '', autoSave : true, autoSaveWarning : false, - unsavedTime : new Date() + unsavedTime : new Date(), + currentEditorPage : 0 }; }, savedBrew : null, @@ -109,9 +110,10 @@ const EditPage = createClass({ if(htmlErrors.length) htmlErrors = Markdown.validate(text); this.setState((prevState)=>({ - brew : { ...prevState.brew, text: text }, - isPending : true, - htmlErrors : htmlErrors + brew : { ...prevState.brew, text: text }, + isPending : true, + htmlErrors : htmlErrors, + currentEditorPage : this.refs.editor.getCurrentPage() - 1 //Offset index since Marked starts pages at 0 }), ()=>{if(this.state.autoSave) this.trySave();}); }, @@ -405,6 +407,7 @@ const EditPage = createClass({ theme={this.state.brew.theme} errors={this.state.htmlErrors} lang={this.state.brew.lang} + currentEditorPage={this.state.currentEditorPage} />
    diff --git a/client/homebrew/pages/errorPage/errors/errorIndex.js b/client/homebrew/pages/errorPage/errors/errorIndex.js index a7e61d08d..c2de04142 100644 --- a/client/homebrew/pages/errorPage/errors/errorIndex.js +++ b/client/homebrew/pages/errorPage/errors/errorIndex.js @@ -22,18 +22,18 @@ const errorIndex = (props)=>{ ## We can't find this brew in Google Drive! This file was saved on Google Drive, but this link doesn't work anymore. - ${ props.brew.authors?.length > 0 - ? `Note that this brew belongs to the Homebrewery account **${ props.brew.authors[0] }**, - ${ props.brew.account - ? `which is + ${props.brew.authors?.length > 0 + ? `Note that this brew belongs to the Homebrewery account **${props.brew.authors[0]}**, + ${props.brew.account + ? `which is ${props.brew.authors[0] == props.brew.account - ? `your account.` - : `not your account (you are currently signed in as **${props.brew.account}**).` - }` - : 'and you are not currently signed in to any account.' - }` - : '' - } + ? `your account.` + : `not your account (you are currently signed in as **${props.brew.account}**).` +}` + : 'and you are not currently signed in to any account.' +}` + : '' +} The Homebrewery cannot delete files from Google Drive on its own, so there are three most likely possibilities: : @@ -75,7 +75,9 @@ const errorIndex = (props)=>{ **Brew Title:** ${props.brew.brewTitle || 'Unable to show title'} - **Current Authors:** ${props.brew.authors?.map((author)=>{return `${author}`;}).join(', ') || 'Unable to list authors'}`, + **Current Authors:** ${props.brew.authors?.map((author)=>{return `${author}`;}).join(', ') || 'Unable to list authors'} + + [Click here to be redirected to the brew's share page.](/share/${props.brew.shareId})`, // User is not signed in; must be a user on the Authors List '04' : dedent` diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 9802517b1..3d3139e74 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -31,9 +31,10 @@ const HomePage = createClass({ }, getInitialState : function() { return { - brew : this.props.brew, - welcomeText : this.props.brew.text, - error : undefined + brew : this.props.brew, + welcomeText : this.props.brew.text, + error : undefined, + currentEditorPage : 0 }; }, handleSave : function(){ @@ -53,7 +54,8 @@ const HomePage = createClass({ }, handleTextChange : function(text){ this.setState((prevState)=>({ - brew : { ...prevState.brew, text: text } + brew : { ...prevState.brew, text: text }, + currentEditorPage : this.refs.editor.getCurrentPage() - 1 //Offset index since Marked starts pages at 0 })); }, renderNavbar : function(){ @@ -85,7 +87,12 @@ const HomePage = createClass({ renderer={this.state.brew.renderer} showEditButtons={false} /> - +
    diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 470c90b89..9877651c2 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -38,11 +38,12 @@ const NewPage = createClass({ const brew = this.props.brew; return { - brew : brew, - isSaving : false, - saveGoogle : (global.account && global.account.googleId ? true : false), - error : null, - htmlErrors : Markdown.validate(brew.text) + brew : brew, + isSaving : false, + saveGoogle : (global.account && global.account.googleId ? true : false), + error : null, + htmlErrors : Markdown.validate(brew.text), + currentEditorPage : 0 }; }, @@ -104,8 +105,9 @@ const NewPage = createClass({ if(htmlErrors.length) htmlErrors = Markdown.validate(text); this.setState((prevState)=>({ - brew : { ...prevState.brew, text: text }, - htmlErrors : htmlErrors + brew : { ...prevState.brew, text: text }, + htmlErrors : htmlErrors, + currentEditorPage : this.refs.editor.getCurrentPage() - 1 //Offset index since Marked starts pages at 0 })); localStorage.setItem(BREWKEY, text); }, @@ -220,7 +222,15 @@ const NewPage = createClass({ onMetaChange={this.handleMetaChange} renderer={this.state.brew.renderer} /> - +
    ; diff --git a/client/homebrew/pages/printPage/printPage.jsx b/client/homebrew/pages/printPage/printPage.jsx index 37376d4b2..083410804 100644 --- a/client/homebrew/pages/printPage/printPage.jsx +++ b/client/homebrew/pages/printPage/printPage.jsx @@ -21,7 +21,8 @@ const PrintPage = createClass({ brew : { text : '', style : '', - renderer : 'legacy' + renderer : 'legacy', + lang : '' } }; }, @@ -32,7 +33,8 @@ const PrintPage = createClass({ text : this.props.brew.text || '', style : this.props.brew.style || undefined, renderer : this.props.brew.renderer || 'legacy', - theme : this.props.brew.theme || '5ePHB' + theme : this.props.brew.theme || '5ePHB', + lang : this.props.brew.lang || 'en' } }; }, @@ -49,7 +51,8 @@ const PrintPage = createClass({ text : brewStorage, style : styleStorage, renderer : metaStorage?.renderer || 'legacy', - theme : metaStorage?.theme || '5ePHB' + theme : metaStorage?.theme || '5ePHB', + lang : metaStorage?.lang || 'en' } }; }); @@ -100,7 +103,7 @@ const PrintPage = createClass({ {/* Apply CSS from Style tab */} {this.renderStyle()} -
    +
    {this.renderPages()}
    ; diff --git a/faq.md b/faq.md index 72e6a7d1f..c7254952b 100644 --- a/faq.md +++ b/faq.md @@ -102,7 +102,7 @@ The best way to avoid this is to leave space at the end of a column equal to one ### Why do I need to manually create a new page? Why doesn't text flow between pages? -A Homebrewery document is at it's core an HTML & CSS document, and currently limited by the specs of those technologies. It is currently not possible to flow content from inside one box ("page") to the inside of another box. It seems likely that someday CSS will add this capability, and if/when that happens, Homebrewery will adopt it as soon as possible. +A Homebrewery document is at its core an HTML & CSS document, and currently limited by the specs of those technologies. It is currently not possible to flow content from inside one box ("page") to the inside of another box. It seems likely that someday CSS will add this capability, and if/when that happens, Homebrewery will adopt it as soon as possible. ### Where do I get images? The Homebrewery does not provide images for use besides some page elements and example images for snippets. You will need to find your own images for use and be sure you are following the appropriate license requirements. @@ -126,4 +126,4 @@ The Homebrewery defaults to creating US Letter page sizes. If you are printing ### Typing `#### Adhesion` in the text editor doesn't show the header at all in the completed page? -Your ad-blocking software is mistakenly assuming your text to be an ad. Whitelist homebrewery.naturalcrit.com in your ad-blocking software. \ No newline at end of file +Your ad-blocking software is mistakenly assuming your text to be an ad. Whitelist homebrewery.naturalcrit.com in your ad-blocking software. diff --git a/package-lock.json b/package-lock.json index cfe68facd..770ff6716 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,67 +1,68 @@ { "name": "homebrewery", - "version": "3.9.2", + "version": "3.11.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "homebrewery", - "version": "3.9.2", + "version": "3.11.0", "hasInstallScript": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.22.20", - "@babel/plugin-transform-runtime": "^7.22.15", - "@babel/preset-env": "^7.22.20", - "@babel/preset-react": "^7.22.15", - "@googleapis/drive": "^8.3.1", + "@babel/core": "^7.23.9", + "@babel/plugin-transform-runtime": "^7.23.9", + "@babel/preset-env": "^7.23.9", + "@babel/preset-react": "^7.23.3", + "@googleapis/drive": "^8.7.0", "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.3", + "expr-eval": "^2.0.2", "express": "^4.18.2", "express-async-handler": "^1.2.0", "express-static-gzip": "2.1.7", - "fs-extra": "11.1.1", + "fs-extra": "11.2.0", "js-yaml": "^4.1.0", "jwt-simple": "^0.5.6", "less": "^3.13.1", "lodash": "^4.17.21", - "marked": "5.1.1", - "marked-extended-tables": "^1.0.6", - "marked-gfm-heading-id": "^3.1.0", - "marked-smartypants-lite": "^1.0.0", + "marked": "11.2.0", + "marked-extended-tables": "^1.0.8", + "marked-gfm-heading-id": "^3.1.3", + "marked-smartypants-lite": "^1.0.2", "markedLegacy": "npm:marked@^0.3.19", - "moment": "^2.29.4", - "mongoose": "^7.5.2", + "moment": "^2.30.1", + "mongoose": "^8.2.0", "nanoid": "3.3.4", - "nconf": "^0.12.0", + "nconf": "^0.12.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-frame-component": "^4.1.3", - "react-router-dom": "6.16.0", + "react-router-dom": "6.22.1", "sanitize-filename": "1.6.3", "superagent": "^8.1.2", "vitreum": "git+https://git@github.com/calculuschild/vitreum.git" }, "devDependencies": { - "eslint": "^8.50.0", - "eslint-plugin-jest": "^27.4.0", + "eslint": "^8.56.0", + "eslint-plugin-jest": "^27.9.0", "eslint-plugin-react": "^7.33.2", "jest": "^29.7.0", "jest-expect-message": "^1.1.3", "postcss-less": "^6.0.0", - "stylelint": "^15.10.3", - "stylelint-config-recess-order": "^4.3.0", + "stylelint": "^15.11.0", + "stylelint-config-recess-order": "^4.6.0", "stylelint-config-recommended": "^13.0.0", "stylelint-stylistic": "^0.4.3", - "supertest": "^6.3.3" + "supertest": "^6.3.4" }, "engines": { - "node": ">=20.7.x", - "npm": "^10.1.x" + "node": "^20.8.x", + "npm": "^10.2.x" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -86,11 +87,11 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -98,29 +99,29 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", - "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.20.tgz", - "integrity": "sha512-Y6jd1ahLubuYweD/zJH+vvOY141v4f9igNQAQ+MBgq9JlHS2iTsZKn1aMsb3vGccZsXI16VzTBw52Xx0DWmtnA==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.22.15", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.22.20", - "@babel/helpers": "^7.22.15", - "@babel/parser": "^7.22.16", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.20", - "@babel/types": "^7.22.19", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", @@ -134,12 +135,17 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, "node_modules/@babel/generator": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz", - "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dependencies": { - "@babel/types": "^7.22.15", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -173,24 +179,24 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.5.tgz", - "integrity": "sha512-m1EP3lVOPptR+2DwD125gziZNcmoNSHGmJROKoy87loWUQyJaVXDgpmruWqDARZSmtYQ+Dl25okU8+qhVzuykw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", + "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -221,13 +227,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.5.tgz", - "integrity": "sha512-1VpEFOIbMRaXyDeUwUfmTIxExLwQ+zkW+Bh5zXpApA3oQedBx9v/updixWxnx/bZpKw7u8VxWjb/qWpIcmPq8A==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", + "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "regexpu-core": "^5.3.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -237,9 +243,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz", - "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -260,12 +266,12 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -283,11 +289,11 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.15.tgz", - "integrity": "sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", + "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -305,9 +311,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.20.tgz", - "integrity": "sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-module-imports": "^7.22.15", @@ -342,13 +348,13 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", - "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", + "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-wrap-function": "^7.22.9" + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-wrap-function": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -358,12 +364,12 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", - "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", + "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-member-expression-to-functions": "^7.22.15", "@babel/helper-optimise-call-expression": "^7.22.5" }, "engines": { @@ -407,9 +413,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "engines": { "node": ">=6.9.0" } @@ -423,45 +429,45 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz", - "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", + "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", "dependencies": { "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.10" + "@babel/template": "^7.22.15", + "@babel/types": "^7.22.19" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz", - "integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", - "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, @@ -470,9 +476,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", - "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -481,9 +487,9 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz", - "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", + "integrity": "sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -495,13 +501,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz", - "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz", + "integrity": "sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.22.15" + "@babel/plugin-transform-optional-chaining": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -510,6 +516,21 @@ "@babel/core": "^7.13.0" } }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz", + "integrity": "sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", @@ -592,9 +613,9 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", - "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz", + "integrity": "sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -606,9 +627,9 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", - "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz", + "integrity": "sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -780,9 +801,9 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", - "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz", + "integrity": "sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -794,13 +815,13 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.15.tgz", - "integrity": "sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz", + "integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.9", + "@babel/helper-remap-async-to-generator": "^7.22.20", "@babel/plugin-syntax-async-generators": "^7.8.4" }, "engines": { @@ -811,13 +832,13 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", - "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz", + "integrity": "sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==", "dependencies": { - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-remap-async-to-generator": "^7.22.5" + "@babel/helper-remap-async-to-generator": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -827,9 +848,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", - "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz", + "integrity": "sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -841,9 +862,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.15.tgz", - "integrity": "sha512-G1czpdJBZCtngoK1sJgloLiOHUnkb/bLZwqVZD8kXmq0ZnVfTTWUcs9OWtp0mBtYJ+4LQY1fllqBkOIPhXmFmw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz", + "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -855,11 +876,11 @@ } }, "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", - "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz", + "integrity": "sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -870,11 +891,11 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.11.tgz", - "integrity": "sha512-GMM8gGmqI7guS/llMFk1bJDkKfn3v3C4KHK9Yg1ey5qcHcOlKb0QvcMrgzvxo+T03/4szNh5lghY+fEC98Kq9g==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz", + "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, @@ -886,17 +907,16 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", - "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz", + "integrity": "sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-replace-supers": "^7.22.20", "@babel/helper-split-export-declaration": "^7.22.6", "globals": "^11.1.0" }, @@ -908,12 +928,12 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", - "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz", + "integrity": "sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.5" + "@babel/template": "^7.22.15" }, "engines": { "node": ">=6.9.0" @@ -923,9 +943,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.15.tgz", - "integrity": "sha512-HzG8sFl1ZVGTme74Nw+X01XsUTqERVQ6/RLHo3XjGRzm7XD6QTtfS3NJotVgCGy8BzkDqRjRBD8dAyJn5TuvSQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz", + "integrity": "sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -937,11 +957,11 @@ } }, "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", - "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz", + "integrity": "sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -952,9 +972,9 @@ } }, "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", - "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz", + "integrity": "sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -966,9 +986,9 @@ } }, "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.11.tgz", - "integrity": "sha512-g/21plo58sfteWjaO0ZNVb+uEOkJNjAaHhbejrnBmu011l/eNDScmkbjCC3l4FKb10ViaGU4aOkFznSu2zRHgA==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz", + "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -981,11 +1001,11 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", - "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz", + "integrity": "sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -996,9 +1016,9 @@ } }, "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.11.tgz", - "integrity": "sha512-xa7aad7q7OiT8oNZ1mU7NrISjlSkVdMbNxn9IuLZyL9AJEhs1Apba3I+u5riX1dIkdptP5EKDG5XDPByWxtehw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz", + "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -1011,11 +1031,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", - "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz", + "integrity": "sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1025,12 +1046,12 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", - "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz", + "integrity": "sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1041,9 +1062,9 @@ } }, "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.11.tgz", - "integrity": "sha512-CxT5tCqpA9/jXFlme9xIBCc5RPtdDq3JpkkhgHQqtDdiTnTI0jtZ0QzXhr5DILeYifDPp2wvY2ad+7+hLMW5Pw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz", + "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -1056,9 +1077,9 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", - "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz", + "integrity": "sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1070,9 +1091,9 @@ } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.11.tgz", - "integrity": "sha512-qQwRTP4+6xFCDV5k7gZBF3C31K34ut0tbEcTKxlX/0KXxm9GLcO14p570aWxFvVzx6QAfPgq7gaeIHXJC8LswQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz", + "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -1085,9 +1106,9 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", - "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz", + "integrity": "sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1099,11 +1120,11 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", - "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz", + "integrity": "sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==", "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1114,11 +1135,11 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.15.tgz", - "integrity": "sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", + "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", "dependencies": { - "@babel/helper-module-transforms": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-simple-access": "^7.22.5" }, @@ -1130,14 +1151,14 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.11.tgz", - "integrity": "sha512-rIqHmHoMEOhI3VkVf5jQ15l539KrwhzqcBO6wdCNWPWc/JWt9ILNYNUssbRpeq0qWns8svuw8LnMNCvWBIJ8wA==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz", + "integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==", "dependencies": { "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.22.9", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -1147,11 +1168,11 @@ } }, "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", - "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz", + "integrity": "sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==", "dependencies": { - "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-module-transforms": "^7.23.3", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1177,9 +1198,9 @@ } }, "node_modules/@babel/plugin-transform-new-target": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", - "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz", + "integrity": "sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1191,9 +1212,9 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.11.tgz", - "integrity": "sha512-YZWOw4HxXrotb5xsjMJUDlLgcDXSfO9eCmdl1bgW4+/lAGdkjaEvOnQ4p5WKKdUgSzO39dgPl0pTnfxm0OAXcg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz", + "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -1206,9 +1227,9 @@ } }, "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.11.tgz", - "integrity": "sha512-3dzU4QGPsILdJbASKhF/V2TVP+gJya1PsueQCxIPCEcerqF21oEcrob4mzjsp2Py/1nLfF5m+xYNMDpmA8vffg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz", + "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-numeric-separator": "^7.10.4" @@ -1221,15 +1242,15 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz", - "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz", + "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==", "dependencies": { - "@babel/compat-data": "^7.22.9", + "@babel/compat-data": "^7.23.3", "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.22.15" + "@babel/plugin-transform-parameters": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -1239,12 +1260,12 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", - "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz", + "integrity": "sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5" + "@babel/helper-replace-supers": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -1254,9 +1275,9 @@ } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.11.tgz", - "integrity": "sha512-rli0WxesXUeCJnMYhzAglEjLWVDF6ahb45HuprcmQuLidBJFWjNnOzssk2kuc6e33FlLaiZhG/kUIzUMWdBKaQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz", + "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -1269,9 +1290,9 @@ } }, "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.15.tgz", - "integrity": "sha512-ngQ2tBhq5vvSJw2Q2Z9i7ealNkpDMU0rGWnHPKqRZO0tzZ5tlaoz4hDvhXioOoaE0X2vfNss1djwg0DXlfu30A==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz", + "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", @@ -1285,9 +1306,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", - "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz", + "integrity": "sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1299,11 +1320,11 @@ } }, "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", - "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz", + "integrity": "sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1314,12 +1335,12 @@ } }, "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.22.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.11.tgz", - "integrity": "sha512-sSCbqZDBKHetvjSwpyWzhuHkmW5RummxJBVbYLkGkaiTOWGxml7SXt0iWa03bzxFIx7wOj3g/ILRd0RcJKBeSQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz", + "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.22.11", + "@babel/helper-create-class-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, @@ -1331,9 +1352,9 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", - "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz", + "integrity": "sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1345,9 +1366,9 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", - "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz", + "integrity": "sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1391,9 +1412,9 @@ } }, "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", - "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz", + "integrity": "sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.22.5", "@babel/helper-plugin-utils": "^7.22.5" @@ -1406,9 +1427,9 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", - "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz", + "integrity": "sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "regenerator-transform": "^0.15.2" @@ -1421,9 +1442,9 @@ } }, "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", - "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz", + "integrity": "sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1435,15 +1456,15 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.15.tgz", - "integrity": "sha512-tEVLhk8NRZSmwQ0DJtxxhTrCht1HVo8VaMzYT4w6lwyKBuHsgoioAUA7/6eT2fRfc5/23fuGdlwIxXhRVgWr4g==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.9.tgz", + "integrity": "sha512-A7clW3a0aSjm3ONU9o2HAILSegJCYlEZmOhmBRReVtIpY/Z/p7yIZ+wR41Z+UipwdGuqwtID/V/dOdZXjwi9gQ==", "dependencies": { "@babel/helper-module-imports": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5", - "babel-plugin-polyfill-corejs2": "^0.4.5", - "babel-plugin-polyfill-corejs3": "^0.8.3", - "babel-plugin-polyfill-regenerator": "^0.5.2", + "babel-plugin-polyfill-corejs2": "^0.4.8", + "babel-plugin-polyfill-corejs3": "^0.9.0", + "babel-plugin-polyfill-regenerator": "^0.5.5", "semver": "^6.3.1" }, "engines": { @@ -1454,9 +1475,9 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", - "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz", + "integrity": "sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1468,9 +1489,9 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", - "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz", + "integrity": "sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" @@ -1483,9 +1504,9 @@ } }, "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", - "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz", + "integrity": "sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1497,9 +1518,9 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", - "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz", + "integrity": "sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1511,9 +1532,9 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", - "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz", + "integrity": "sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1525,9 +1546,9 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", - "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz", + "integrity": "sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" }, @@ -1539,11 +1560,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", - "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz", + "integrity": "sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1554,11 +1575,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", - "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz", + "integrity": "sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1569,11 +1590,11 @@ } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", - "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz", + "integrity": "sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-create-regexp-features-plugin": "^7.22.15", "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { @@ -1584,24 +1605,25 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.20.tgz", - "integrity": "sha512-11MY04gGC4kSzlPHRfvVkNAZhUxOvm7DCJ37hPDnUENwe06npjIRAfInEMTGSb4LZK5ZgDFkv5hw0lGebHeTyg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz", + "integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==", "dependencies": { - "@babel/compat-data": "^7.22.20", - "@babel/helper-compilation-targets": "^7.22.15", + "@babel/compat-data": "^7.23.5", + "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/helper-validator-option": "^7.23.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.22.5", - "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-assertions": "^7.23.3", + "@babel/plugin-syntax-import-attributes": "^7.23.3", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", @@ -1613,59 +1635,58 @@ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.22.5", - "@babel/plugin-transform-async-generator-functions": "^7.22.15", - "@babel/plugin-transform-async-to-generator": "^7.22.5", - "@babel/plugin-transform-block-scoped-functions": "^7.22.5", - "@babel/plugin-transform-block-scoping": "^7.22.15", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-class-static-block": "^7.22.11", - "@babel/plugin-transform-classes": "^7.22.15", - "@babel/plugin-transform-computed-properties": "^7.22.5", - "@babel/plugin-transform-destructuring": "^7.22.15", - "@babel/plugin-transform-dotall-regex": "^7.22.5", - "@babel/plugin-transform-duplicate-keys": "^7.22.5", - "@babel/plugin-transform-dynamic-import": "^7.22.11", - "@babel/plugin-transform-exponentiation-operator": "^7.22.5", - "@babel/plugin-transform-export-namespace-from": "^7.22.11", - "@babel/plugin-transform-for-of": "^7.22.15", - "@babel/plugin-transform-function-name": "^7.22.5", - "@babel/plugin-transform-json-strings": "^7.22.11", - "@babel/plugin-transform-literals": "^7.22.5", - "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", - "@babel/plugin-transform-member-expression-literals": "^7.22.5", - "@babel/plugin-transform-modules-amd": "^7.22.5", - "@babel/plugin-transform-modules-commonjs": "^7.22.15", - "@babel/plugin-transform-modules-systemjs": "^7.22.11", - "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-arrow-functions": "^7.23.3", + "@babel/plugin-transform-async-generator-functions": "^7.23.9", + "@babel/plugin-transform-async-to-generator": "^7.23.3", + "@babel/plugin-transform-block-scoped-functions": "^7.23.3", + "@babel/plugin-transform-block-scoping": "^7.23.4", + "@babel/plugin-transform-class-properties": "^7.23.3", + "@babel/plugin-transform-class-static-block": "^7.23.4", + "@babel/plugin-transform-classes": "^7.23.8", + "@babel/plugin-transform-computed-properties": "^7.23.3", + "@babel/plugin-transform-destructuring": "^7.23.3", + "@babel/plugin-transform-dotall-regex": "^7.23.3", + "@babel/plugin-transform-duplicate-keys": "^7.23.3", + "@babel/plugin-transform-dynamic-import": "^7.23.4", + "@babel/plugin-transform-exponentiation-operator": "^7.23.3", + "@babel/plugin-transform-export-namespace-from": "^7.23.4", + "@babel/plugin-transform-for-of": "^7.23.6", + "@babel/plugin-transform-function-name": "^7.23.3", + "@babel/plugin-transform-json-strings": "^7.23.4", + "@babel/plugin-transform-literals": "^7.23.3", + "@babel/plugin-transform-logical-assignment-operators": "^7.23.4", + "@babel/plugin-transform-member-expression-literals": "^7.23.3", + "@babel/plugin-transform-modules-amd": "^7.23.3", + "@babel/plugin-transform-modules-commonjs": "^7.23.3", + "@babel/plugin-transform-modules-systemjs": "^7.23.9", + "@babel/plugin-transform-modules-umd": "^7.23.3", "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.22.5", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", - "@babel/plugin-transform-numeric-separator": "^7.22.11", - "@babel/plugin-transform-object-rest-spread": "^7.22.15", - "@babel/plugin-transform-object-super": "^7.22.5", - "@babel/plugin-transform-optional-catch-binding": "^7.22.11", - "@babel/plugin-transform-optional-chaining": "^7.22.15", - "@babel/plugin-transform-parameters": "^7.22.15", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/plugin-transform-private-property-in-object": "^7.22.11", - "@babel/plugin-transform-property-literals": "^7.22.5", - "@babel/plugin-transform-regenerator": "^7.22.10", - "@babel/plugin-transform-reserved-words": "^7.22.5", - "@babel/plugin-transform-shorthand-properties": "^7.22.5", - "@babel/plugin-transform-spread": "^7.22.5", - "@babel/plugin-transform-sticky-regex": "^7.22.5", - "@babel/plugin-transform-template-literals": "^7.22.5", - "@babel/plugin-transform-typeof-symbol": "^7.22.5", - "@babel/plugin-transform-unicode-escapes": "^7.22.10", - "@babel/plugin-transform-unicode-property-regex": "^7.22.5", - "@babel/plugin-transform-unicode-regex": "^7.22.5", - "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.23.3", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4", + "@babel/plugin-transform-numeric-separator": "^7.23.4", + "@babel/plugin-transform-object-rest-spread": "^7.23.4", + "@babel/plugin-transform-object-super": "^7.23.3", + "@babel/plugin-transform-optional-catch-binding": "^7.23.4", + "@babel/plugin-transform-optional-chaining": "^7.23.4", + "@babel/plugin-transform-parameters": "^7.23.3", + "@babel/plugin-transform-private-methods": "^7.23.3", + "@babel/plugin-transform-private-property-in-object": "^7.23.4", + "@babel/plugin-transform-property-literals": "^7.23.3", + "@babel/plugin-transform-regenerator": "^7.23.3", + "@babel/plugin-transform-reserved-words": "^7.23.3", + "@babel/plugin-transform-shorthand-properties": "^7.23.3", + "@babel/plugin-transform-spread": "^7.23.3", + "@babel/plugin-transform-sticky-regex": "^7.23.3", + "@babel/plugin-transform-template-literals": "^7.23.3", + "@babel/plugin-transform-typeof-symbol": "^7.23.3", + "@babel/plugin-transform-unicode-escapes": "^7.23.3", + "@babel/plugin-transform-unicode-property-regex": "^7.23.3", + "@babel/plugin-transform-unicode-regex": "^7.23.3", + "@babel/plugin-transform-unicode-sets-regex": "^7.23.3", "@babel/preset-modules": "0.1.6-no-external-plugins", - "@babel/types": "^7.22.19", - "babel-plugin-polyfill-corejs2": "^0.4.5", - "babel-plugin-polyfill-corejs3": "^0.8.3", - "babel-plugin-polyfill-regenerator": "^0.5.2", + "babel-plugin-polyfill-corejs2": "^0.4.8", + "babel-plugin-polyfill-corejs3": "^0.9.0", + "babel-plugin-polyfill-regenerator": "^0.5.5", "core-js-compat": "^3.31.0", "semver": "^6.3.1" }, @@ -1690,16 +1711,16 @@ } }, "node_modules/@babel/preset-react": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.15.tgz", - "integrity": "sha512-Csy1IJ2uEh/PecCBXXoZGAZBeCATTuePzCSB7dLYWS0vOEj6CNpjxIhW4duWwZodBNueH7QO14WbGn8YyeuN9w==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.23.3.tgz", + "integrity": "sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w==", "dependencies": { "@babel/helper-plugin-utils": "^7.22.5", "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-transform-react-display-name": "^7.22.5", + "@babel/plugin-transform-react-display-name": "^7.23.3", "@babel/plugin-transform-react-jsx": "^7.22.15", "@babel/plugin-transform-react-jsx-development": "^7.22.5", - "@babel/plugin-transform-react-pure-annotations": "^7.22.5" + "@babel/plugin-transform-react-pure-annotations": "^7.23.3" }, "engines": { "node": ">=6.9.0" @@ -1714,9 +1735,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz", - "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -1725,32 +1746,32 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.20.tgz", - "integrity": "sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.22.15", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.22.5", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.16", - "@babel/types": "^7.22.19", - "debug": "^4.1.0", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -1758,12 +1779,12 @@ } }, "node_modules/@babel/types": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz", - "integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.19", + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1887,9 +1908,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -1910,9 +1931,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -1937,18 +1958,18 @@ } }, "node_modules/@eslint/js": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz", - "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@googleapis/drive": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.3.1.tgz", - "integrity": "sha512-6uh7cC6nzulB5Q76a4OmWF54pfFmDSy6IdF95DKF8yVJVaO6/CfyRtJJsAKmXOZkXIEs9sZZeSzBd4eXwJMlag==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.7.0.tgz", + "integrity": "sha512-XAi6kfySIU4H3ivX2DpzTDce5UhNke5NxEWCL6tySEdcVqx+cmXJmkMqwfOAHJalEB5s9PPfdLBU29Xd5XlLSQ==", "dependencies": { "googleapis-common": "^7.0.0" }, @@ -1957,12 +1978,12 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -1984,9 +2005,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@istanbuljs/load-nyc-config": { @@ -2774,10 +2795,9 @@ } }, "node_modules/@mongodb-js/saslprep": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", - "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", - "optional": true, + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz", + "integrity": "sha512-8zJ8N1x51xo9hwPh6AWnKdLGEC5N3lDa6kms1YHmFBoRhTpJR6HG8wWk0td1MVCu9cD4YBrvjZEtd5Obw0Fbnw==", "dependencies": { "sparse-bitfield": "^3.0.3" } @@ -2818,9 +2838,9 @@ } }, "node_modules/@remix-run/router": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.9.0.tgz", - "integrity": "sha512-bV63itrKBC0zdT27qYm6SDZHlkXwFL1xMBuhkn+X7l0+IIhNaH5wuuvZKp6eKhCD4KFhujhfhCT1YxXW6esUIA==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", + "integrity": "sha512-zcU0gM3z+3iqj8UX45AmWY810l3oUmXM7uH4dt5xtzvMhRtYVhKGOmgOd1877dOPPepfCjUv57w+syamWIYe7w==", "engines": { "node": ">=14.0.0" } @@ -2938,7 +2958,8 @@ "node_modules/@types/node": { "version": "18.15.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.5.tgz", - "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==" + "integrity": "sha512-Ark2WDjjZO7GmvsyFFf81MXuGTA/d6oP38anyxWOL6EREyBKAxKoFHwBhaZxCfLRLpO8JgVXwqOwSwa7jRcjew==", + "dev": true }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -2959,16 +2980,15 @@ "dev": true }, "node_modules/@types/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" }, "node_modules/@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", "dependencies": { - "@types/node": "*", "@types/webidl-conversions": "*" } }, @@ -3175,6 +3195,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -3193,9 +3219,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3709,12 +3735,12 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz", - "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==", + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", + "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==", "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.2", + "@babel/helper-define-polyfill-provider": "^0.5.0", "semver": "^6.3.1" }, "peerDependencies": { @@ -3722,23 +3748,23 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz", - "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", + "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.2", - "core-js-compat": "^3.31.0" + "@babel/helper-define-polyfill-provider": "^0.5.0", + "core-js-compat": "^3.34.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz", - "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", + "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.2" + "@babel/helper-define-polyfill-provider": "^0.5.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -4134,19 +4160,22 @@ } }, "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz", + "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==", "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", + "elliptic": "^6.5.4", "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "parse-asn1": "^5.1.6", + "readable-stream": "^3.6.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 4" } }, "node_modules/browserify-zlib": { @@ -4199,9 +4228,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "funding": [ { "type": "opencollective", @@ -4217,10 +4246,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", - "update-browserslist-db": "^1.0.11" + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -4239,11 +4268,11 @@ } }, "node_modules/bson": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", - "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.2.0.tgz", + "integrity": "sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==", "engines": { - "node": ">=14.20.1" + "node": ">=16.20.1" } }, "node_modules/buffer": { @@ -4380,9 +4409,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001512", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001512.tgz", - "integrity": "sha512-2S9nK0G/mE+jasCUsMPlARhRCts1ebcp2Ji8Y8PWi4NDE1iRdLCnEPHkEfeBrGC45L4isBx5ur3IQ6yTE2mRZw==", + "version": "1.0.30001570", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", + "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", "funding": [ { "type": "opencollective", @@ -4690,7 +4719,8 @@ "node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true }, "node_modules/cookie": { "version": "0.4.1", @@ -4742,11 +4772,11 @@ } }, "node_modules/core-js-compat": { - "version": "3.31.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.31.1.tgz", - "integrity": "sha512-wIDWd2s5/5aJSdpOJHfSibxNODxoGoWOBHt8JSPB41NOE94M7kuTPZCYLOlTtuoXTsBPKobpJ6T+y0SSy5L9SA==", + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.35.0.tgz", + "integrity": "sha512-5blwFAddknKeNgsjBzilkdQ0+YK8L1PfqPYq40NOYMYFSS38qj+hpTcLLWwpIwA2A5bje/x5jmVn2tzUMg9IVw==", "dependencies": { - "browserslist": "^4.21.9" + "browserslist": "^4.22.2" }, "funding": { "type": "opencollective", @@ -4951,12 +4981,12 @@ } }, "node_modules/css-functions-list": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.0.tgz", - "integrity": "sha512-d/jBMPyYybkkLVypgtGv12R+pIFw4/f/IHtCTxWpZc8ofTYOPigIgmA6vu5rMHartZC+WuXhBUHfnyNUIQSYrg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz", + "integrity": "sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==", "dev": true, "engines": { - "node": ">=12.22" + "node": ">=12 || >=16" } }, "node_modules/css-tree": { @@ -5352,9 +5382,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.451", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.451.tgz", - "integrity": "sha512-YYbXHIBxAHe3KWvGOJOuWa6f3tgow44rBW+QAuwVp2DvGqNZeE//K2MowNdWS7XE8li5cgQDrX1LdBr41LufkA==" + "version": "1.4.612", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.612.tgz", + "integrity": "sha512-dM8BMtXtlH237ecSMnYdYuCkib2QHq0kpWfUnavjdYsyr/6OsAwg5ZGUfnQ9KD1Ga4QgB2sqXlB2NT8zy2GnVg==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -5558,18 +5588,19 @@ } }, "node_modules/eslint": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz", - "integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==", + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", + "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.50.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -5612,9 +5643,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.4.0.tgz", - "integrity": "sha512-ukVeKmMPAUA5SWjHenvyyXnirKfHKMdOsTZdn5tZx5EW05HGVQwBohigjFZGGj3zuv1cV6hc82FvWv6LdIbkgg==", + "version": "27.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", + "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -5623,7 +5654,7 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", "eslint": "^7.0.0 || ^8.0.0", "jest": "*" }, @@ -6006,6 +6037,11 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/expr-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expr-eval/-/expr-eval-2.0.2.tgz", + "integrity": "sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg==" + }, "node_modules/express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -6360,22 +6396,23 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "node_modules/for-each": { @@ -6450,9 +6487,9 @@ } }, "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -7339,11 +7376,6 @@ "node": ">= 0.4" } }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -9592,6 +9624,12 @@ "bignumber.js": "^9.0.0" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -9719,6 +9757,15 @@ "node": ">=12.0.0" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -9740,9 +9787,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.28.0.tgz", - "integrity": "sha512-9pSL5XB4J+ifHP0e0jmmC98OGC1nL8/JjS+fi6mnTlIf//yt/MfVLtKg7S6nCtj/8KTcWX7nRlY0XywoYY1ISQ==", + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", + "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", "dev": true }, "node_modules/labeled-stream-splicer": { @@ -10000,9 +10047,9 @@ } }, "node_modules/marked": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.1.tgz", - "integrity": "sha512-bTmmGdEINWmOMDjnPWDxGPQ4qkDLeYorpYbEtFOXzOruTwUE671q4Guiuchn4N8h/v6NGd7916kXsm3Iz4iUSg==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz", + "integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==", "bin": { "marked": "bin/marked.js" }, @@ -10011,30 +10058,30 @@ } }, "node_modules/marked-extended-tables": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/marked-extended-tables/-/marked-extended-tables-1.0.6.tgz", - "integrity": "sha512-l3bgWsVHxJLaZhDGYdg3tREoUt+Jzq05fGAoKfeORAyz149N/jxDOimcg4wYV27G2M/6meZR28jVgtV+qTXD1g==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/marked-extended-tables/-/marked-extended-tables-1.0.8.tgz", + "integrity": "sha512-GcVQP7EnfQ98o09ooqM4t4M0qfpKdKuk7/z4qZfgkLyXTXsIyFS1eeBmfC36o1NbR6aSq8ynL/LeTz3w4RS27Q==", "peerDependencies": { - "marked": "^3.0.0 || ^4.0.0 || ^5.0.0" + "marked": ">=3 <12" } }, "node_modules/marked-gfm-heading-id": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-3.1.0.tgz", - "integrity": "sha512-PYgLXDbL64Ga6kCpvVuKVoIVsV6MKUtkOXnR8mIqyjiycAeKNhQxcGpO0mHEogOTzyY8A8TcK49k5VwYMUCCbg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-3.1.3.tgz", + "integrity": "sha512-A0cRU4PCueX/5m8VE4mT8uTQ36l3xMYRojz3Eqnk4BmUFZ0T+9Xhn2KvHcANP4qbhfOeuMrWJCTQbASIBR5xeg==", "dependencies": { "github-slugger": "^2.0.0" }, "peerDependencies": { - "marked": ">=4 <10" + "marked": ">=4 <13" } }, "node_modules/marked-smartypants-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/marked-smartypants-lite/-/marked-smartypants-lite-1.0.0.tgz", - "integrity": "sha512-+EGU6lP4VVoQBJp1OMoM3wDG0m/n9z2pek9hA9NtOG1EDrW0DCQc6T4KzdEzaVAghc2XMyEBDqlUsN/3/QvD9g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/marked-smartypants-lite/-/marked-smartypants-lite-1.0.2.tgz", + "integrity": "sha512-cEANts+s3+gnTzXPvPT2z4V8NfbMEL9QooKUviug0DkaKkXQWrUwDAmFnQAkLSJCw2BQcD8YPDyxu0HJ3mg36w==", "peerDependencies": { - "marked": "^4 || ^5" + "marked": ">=4 <12" } }, "node_modules/markedLegacy": { @@ -10086,8 +10133,7 @@ "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" }, "node_modules/meow": { "version": "10.1.5", @@ -10396,34 +10442,120 @@ } }, "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "engines": { "node": "*" } }, - "node_modules/mongodb": { - "version": "5.8.1", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.8.1.tgz", - "integrity": "sha512-wKyh4kZvm6NrCPH8AxyzXm3JBoEf4Xulo0aUWh3hCgwgYJxyQ1KLST86ZZaSWdj6/kxYUA3+YZuyADCE61CMSg==", + "node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", "dependencies": { - "bson": "^5.4.0", - "mongodb-connection-string-url": "^2.6.0", - "socks": "^2.7.1" + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.2.0.tgz", + "integrity": "sha512-la93n6zCYRbPS+c5N9oTDAktvREy5OT9OCljp1Tah0y3+p8UPMTAoabWaLZMdzYruOtF9/9GRf6MasaZjiZP1A==", + "dependencies": { + "bson": "^6.2.0", + "kareem": "2.5.1", + "mongodb": "6.3.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" }, "engines": { - "node": ">=14.20.1" + "node": ">=16.20.1" }, - "optionalDependencies": { - "@mongodb-js/saslprep": "^1.1.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "peer": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/mongoose/node_modules/gaxios": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", + "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", + "optional": true, + "peer": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongoose/node_modules/gcp-metadata": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", + "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", + "optional": true, + "peer": true, + "dependencies": { + "gaxios": "^5.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongoose/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "peer": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/mongoose/node_modules/mongodb": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz", + "integrity": "sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^6.2.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" }, "peerDependencies": { "@aws-sdk/credential-providers": "^3.188.0", - "@mongodb-js/zstd": "^1.0.0", - "kerberos": "^1.0.0 || ^2.0.0", - "mongodb-client-encryption": ">=2.3.0 <3", - "snappy": "^7.2.2" + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" }, "peerDependenciesMeta": { "@aws-sdk/credential-providers": { @@ -10432,6 +10564,9 @@ "@mongodb-js/zstd": { "optional": true }, + "gcp-metadata": { + "optional": true + }, "kerberos": { "optional": true }, @@ -10440,39 +10575,12 @@ }, "snappy": { "optional": true + }, + "socks": { + "optional": true } } }, - "node_modules/mongodb-connection-string-url": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", - "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", - "dependencies": { - "@types/whatwg-url": "^8.2.1", - "whatwg-url": "^11.0.0" - } - }, - "node_modules/mongoose": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.5.2.tgz", - "integrity": "sha512-yEkmI1jfiog7QUvMWz3eB/XoA3/5DrVvSz+z3V5hnq8VtZIHC7ujEV0RKzRXwr8QNMOs+OTB7+aK7R/N/V3yXA==", - "dependencies": { - "bson": "^5.4.0", - "kareem": "2.5.1", - "mongodb": "5.8.1", - "mpath": "0.9.0", - "mquery": "5.0.0", - "ms": "2.1.3", - "sift": "16.0.1" - }, - "engines": { - "node": ">=14.20.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mongoose" - } - }, "node_modules/mongoose/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -10631,9 +10739,9 @@ "dev": true }, "node_modules/nconf": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.12.0.tgz", - "integrity": "sha512-T3fZPw3c7Dfrz8JBQEbEcZJ2s8f7cUMpKuyBtsGQe0b71pcXx6gNh4oti2xh5dxB+gO9ufNfISBlGvvWtfyMcA==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.12.1.tgz", + "integrity": "sha512-p2cfF+B3XXacQdswUYWZ0w6Vld0832A/tuqjLBu3H1sfUcby4N2oVbGhyuCkZv+t3iY3aiFEj7gZGqax9Q2c1w==", "dependencies": { "async": "^3.0.0", "ini": "^2.0.0", @@ -10732,9 +10840,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", - "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==" + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/nodemon": { "version": "2.0.21", @@ -11375,9 +11483,9 @@ } }, "node_modules/postcss": { - "version": "8.4.28", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz", - "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "funding": [ { @@ -11771,11 +11879,11 @@ "dev": true }, "node_modules/react-router": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.16.0.tgz", - "integrity": "sha512-VT4Mmc4jj5YyjpOi5jOf0I+TYzGpvzERy4ckNSvSh2RArv8LLoCxlsZ2D+tc7zgjxcY34oTz2hZaeX5RVprKqA==", + "version": "6.22.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.1.tgz", + "integrity": "sha512-0pdoRGwLtemnJqn1K0XHUbnKiX0S4X8CgvVVmHGOWmofESj31msHo/1YiqcJWK7Wxfq2a4uvvtS01KAQyWK/CQ==", "dependencies": { - "@remix-run/router": "1.9.0" + "@remix-run/router": "1.15.1" }, "engines": { "node": ">=14.0.0" @@ -11785,12 +11893,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.16.0.tgz", - "integrity": "sha512-aTfBLv3mk/gaKLxgRDUPbPw+s4Y/O+ma3rEN1u8EgEpLpPe6gNjIsWt9rxushMHHMb7mSwxRGdGlGdvmFsyPIg==", + "version": "6.22.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.1.tgz", + "integrity": "sha512-iwMyyyrbL7zkKY7MRjOVRy+TMnS/OPusaFVxM2P11x9dzSzGmLsebkCvYirGq0DWB9K9hOspHYYtDz33gE5Duw==", "dependencies": { - "@remix-run/router": "1.9.0", - "react-router": "6.16.0" + "@remix-run/router": "1.15.1", + "react-router": "6.22.1" }, "engines": { "node": ">=14.0.0" @@ -12592,15 +12700,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, "node_modules/snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -12729,19 +12828,6 @@ "node": ">=0.10.0" } }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -12792,7 +12878,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "optional": true, "dependencies": { "memory-pager": "^1.0.2" } @@ -13190,9 +13275,9 @@ "dev": true }, "node_modules/stylelint": { - "version": "15.10.3", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.10.3.tgz", - "integrity": "sha512-aBQMMxYvFzJJwkmg+BUUg3YfPyeuCuKo2f+LOw7yYbU8AZMblibwzp9OV4srHVeQldxvSFdz0/Xu8blq2AesiA==", + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.11.0.tgz", + "integrity": "sha512-78O4c6IswZ9TzpcIiQJIN49K3qNoXTM8zEJzhaTE/xRTCZswaovSEVIa/uwbOltZrk16X4jAxjaOhzz/hTm1Kw==", "dev": true, "dependencies": { "@csstools/css-parser-algorithms": "^2.3.1", @@ -13202,12 +13287,12 @@ "balanced-match": "^2.0.0", "colord": "^2.9.3", "cosmiconfig": "^8.2.0", - "css-functions-list": "^3.2.0", + "css-functions-list": "^3.2.1", "css-tree": "^2.3.1", "debug": "^4.3.4", "fast-glob": "^3.3.1", "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^7.0.0", "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", @@ -13216,13 +13301,13 @@ "import-lazy": "^4.0.0", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.28.0", + "known-css-properties": "^0.29.0", "mathml-tag-names": "^2.1.3", "meow": "^10.1.5", "micromatch": "^4.0.5", "normalize-path": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.27", + "postcss": "^8.4.28", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", "postcss-selector-parser": "^6.0.13", @@ -13248,9 +13333,9 @@ } }, "node_modules/stylelint-config-recess-order": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recess-order/-/stylelint-config-recess-order-4.3.0.tgz", - "integrity": "sha512-EWVtxZ8oq4/meTrRNUDrS5TqMz6TX72JjKDwVQq0JJDXE+P/o7UuFw3wWV/0O9yvJfh/da6nJY71ZUn/wSfB4g==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recess-order/-/stylelint-config-recess-order-4.6.0.tgz", + "integrity": "sha512-V76fhv3YtcNXh/hyAuAdSzi5FmcrG54Mp2AThJ3D/PTMTSYzUPd7GIhP6z9mTqnRhmkk6YTfcu/JWB8h+Yrcaw==", "dev": true, "dependencies": { "stylelint-order": "6.x" @@ -13315,6 +13400,18 @@ "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", "dev": true }, + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.1.tgz", + "integrity": "sha512-uLfFktPmRetVCbHe5UPuekWrQ6hENufnA46qEGbfACkK5drjTTdQYUragRgMjHldcbYG+nslUerqMPjbBSHXjQ==", + "dev": true, + "dependencies": { + "flat-cache": "^3.1.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/stylelint/node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -13428,13 +13525,13 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/supertest": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", - "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", + "version": "6.3.4", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.4.tgz", + "integrity": "sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw==", "dev": true, "dependencies": { "methods": "^1.1.2", - "superagent": "^8.0.5" + "superagent": "^8.1.2" }, "engines": { "node": ">=6.4.0" @@ -13752,14 +13849,14 @@ } }, "node_modules/tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", "dependencies": { - "punycode": "^2.1.1" + "punycode": "^2.3.0" }, "engines": { - "node": ">=12" + "node": ">=14" } }, "node_modules/trim-newlines": { @@ -14099,9 +14196,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "funding": [ { "type": "opencollective", @@ -14669,15 +14766,15 @@ } }, "node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", "dependencies": { - "tr46": "^3.0.0", + "tr46": "^4.1.1", "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=12" + "node": ">=16" } }, "node_modules/which": { diff --git a/package.json b/package.json index afbb332a4..884d293ec 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "homebrewery", "description": "Create authentic looking D&D homebrews using only markdown", - "version": "3.9.2", + "version": "3.11.0", "engines": { - "npm": "^10.1.x", - "node": ">=20.7.x" + "npm": "^10.2.x", + "node": "^20.8.x" }, "repository": { "type": "git", @@ -26,6 +26,7 @@ "test:coverage": "jest --coverage --silent --runInBand", "test:dev": "jest --verbose --watch", "test:basic": "jest tests/markdown/basic.test.js --verbose", + "test:variables": "jest tests/markdown/variables.test.js --verbose", "test:mustache-syntax": "jest '.*(mustache-syntax).*' --verbose --noStackTrace", "test:mustache-syntax:inline": "jest '.*(mustache-syntax).*' -t '^Inline:.*' --verbose --noStackTrace", "test:mustache-syntax:block": "jest '.*(mustache-syntax).*' -t '^Block:.*' --verbose --noStackTrace", @@ -79,53 +80,54 @@ ] }, "dependencies": { - "@babel/core": "^7.22.20", - "@babel/plugin-transform-runtime": "^7.22.15", - "@babel/preset-env": "^7.22.20", - "@babel/preset-react": "^7.22.15", - "@googleapis/drive": "^8.3.1", + "@babel/core": "^7.23.9", + "@babel/plugin-transform-runtime": "^7.23.9", + "@babel/preset-env": "^7.23.9", + "@babel/preset-react": "^7.23.3", + "@googleapis/drive": "^8.7.0", "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.3", + "expr-eval": "^2.0.2", "express": "^4.18.2", "express-async-handler": "^1.2.0", "express-static-gzip": "2.1.7", - "fs-extra": "11.1.1", + "fs-extra": "11.2.0", "js-yaml": "^4.1.0", "jwt-simple": "^0.5.6", "less": "^3.13.1", "lodash": "^4.17.21", - "marked": "5.1.1", - "marked-extended-tables": "^1.0.6", - "marked-gfm-heading-id": "^3.1.0", - "marked-smartypants-lite": "^1.0.0", + "marked": "11.2.0", + "marked-extended-tables": "^1.0.8", + "marked-gfm-heading-id": "^3.1.3", + "marked-smartypants-lite": "^1.0.2", "markedLegacy": "npm:marked@^0.3.19", - "moment": "^2.29.4", - "mongoose": "^7.5.2", + "moment": "^2.30.1", + "mongoose": "^8.2.0", "nanoid": "3.3.4", - "nconf": "^0.12.0", + "nconf": "^0.12.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-frame-component": "^4.1.3", - "react-router-dom": "6.16.0", + "react-router-dom": "6.22.1", "sanitize-filename": "1.6.3", "superagent": "^8.1.2", "vitreum": "git+https://git@github.com/calculuschild/vitreum.git" }, "devDependencies": { - "eslint": "^8.50.0", - "eslint-plugin-jest": "^27.4.0", + "eslint": "^8.56.0", + "eslint-plugin-jest": "^27.9.0", "eslint-plugin-react": "^7.33.2", "jest": "^29.7.0", "jest-expect-message": "^1.1.3", "postcss-less": "^6.0.0", - "stylelint": "^15.10.3", - "stylelint-config-recess-order": "^4.3.0", + "stylelint": "^15.11.0", + "stylelint-config-recess-order": "^4.6.0", "stylelint-config-recommended": "^13.0.0", "stylelint-stylistic": "^0.4.3", - "supertest": "^6.3.3" + "supertest": "^6.3.4" } } diff --git a/scripts/buildHomebrew.js b/scripts/buildHomebrew.js index e78759168..f072b0359 100644 --- a/scripts/buildHomebrew.js +++ b/scripts/buildHomebrew.js @@ -101,7 +101,10 @@ fs.emptyDirSync('./build'); //v==---------------------------MOVE CM EDITOR THEMES -----------------------------==v// - editorThemeFiles = fs.readdirSync('./node_modules/codemirror/theme'); + const editorThemesBuildDir = './build/homebrew/cm-themes'; + await fs.copy('./node_modules/codemirror/theme', editorThemesBuildDir); + await fs.copy('./themes/codeMirror/customThemes', editorThemesBuildDir); + editorThemeFiles = fs.readdirSync(editorThemesBuildDir); const editorThemeFile = './themes/codeMirror/editorThemes.json'; if(fs.existsSync(editorThemeFile)) fs.rmSync(editorThemeFile); @@ -114,7 +117,7 @@ fs.emptyDirSync('./build'); stream.write('\n]\n'); stream.end(); - await fs.copy('./node_modules/codemirror/theme', './build/homebrew/cm-themes'); + await fs.copy('./themes/codeMirror', './build/homebrew/codeMirror'); //v==----------------------------- BUNDLE PACKAGES --------------------------------==v// @@ -151,14 +154,14 @@ fs.emptyDirSync('./build'); // build(bundles); // -})().catch(console.error); + //In development, set up LiveReload (refreshes browser), and Nodemon (restarts server) + if(isDev){ + livereload('./build'); // Install the Chrome extension LiveReload to automatically refresh the browser + watchFile('./server.js', { // Restart server when change detected to this file or any nested directory from here + ignore : ['./build', './client', './themes'], // Ignore folders that are not running server code / avoids unneeded restarts + ext : 'js json' // Extensions to watch (only .js/.json by default) + //watch : ['./server', './themes'], // Watch additional folders if needed + }); + } -//In development, set up LiveReload (refreshes browser), and Nodemon (restarts server) -if(isDev){ - livereload('./build'); // Install the Chrome extension LiveReload to automatically refresh the browser - watchFile('./server.js', { // Restart server when change detected to this file or any nested directory from here - ignore : ['./build', './client', './themes'], // Ignore folders that are not running server code / avoids unneeded restarts - ext : 'js json' // Extensions to watch (only .js/.json by default) - //watch : ['./server', './themes'], // Watch additional folders if needed - }); -} +})().catch(console.error); \ No newline at end of file diff --git a/scripts/project.json b/scripts/project.json index 5a0289ad0..4c769660f 100644 --- a/scripts/project.json +++ b/scripts/project.json @@ -26,7 +26,6 @@ "codemirror/addon/edit/trailingspace.js", "codemirror/addon/selection/active-line.js", "moment", - "superagent", - "marked" + "superagent" ] } diff --git a/server/admin.api.js b/server/admin.api.js index b9b2afbd7..5363ecc08 100644 --- a/server/admin.api.js +++ b/server/admin.api.js @@ -26,85 +26,124 @@ const mw = { } }; - -/* Search for brews that are older than 3 days and that are shorter than a tweet */ -const junkBrewQuery = HomebrewModel.find({ - '$where' : 'this.text.length < 140', - createdAt : { - $lt : Moment().subtract(30, 'days').toDate() - } -}).limit(100).maxTime(60000); +const junkBrewPipeline = [ + { $match : { + updatedAt : { $lt: Moment().subtract(30, 'days').toDate() }, + lastViewed : { $lt: Moment().subtract(30, 'days').toDate() } + }}, + { $project: { textBinSize: { $binarySize: '$textBin' } } }, + { $match: { textBinSize: { $lt: 140 } } }, + { $limit: 100 } +]; /* Search for brews that aren't compressed (missing the compressed text field) */ const uncompressedBrewQuery = HomebrewModel.find({ 'text' : { '$exists': true } }).lean().limit(10000).select('_id'); +// Search for up to 100 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes router.get('/admin/cleanup', mw.adminOnly, (req, res)=>{ - junkBrewQuery.exec((err, objs)=>{ - if(err) return res.status(500).send(err); - return res.json({ count: objs.length }); - }); + HomebrewModel.aggregate(junkBrewPipeline).option({ maxTimeMS: 60000 }) + .then((objs)=>res.json({ count: objs.length })) + .catch((error)=>{ + console.error(error); + res.status(500).json({ error: 'Internal Server Error' }); + }); }); -/* Removes all empty brews that are older than 3 days and that are shorter than a tweet */ + +// Delete up to 100 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes router.post('/admin/cleanup', mw.adminOnly, (req, res)=>{ - junkBrewQuery.remove().exec((err, objs)=>{ - if(err) return res.status(500).send(err); - return res.json({ count: objs.length }); - }); + HomebrewModel.aggregate(junkBrewPipeline).option({ maxTimeMS: 60000 }) + .then((docs)=>{ + const ids = docs.map((doc)=>doc._id); + return HomebrewModel.deleteMany({ _id: { $in: ids } }); + }).then((result)=>{ + res.json({ count: result.deletedCount }); + }).catch((error)=>{ + console.error(error); + res.status(500).json({ error: 'Internal Server Error' }); + }); }); /* Searches for matching edit or share id, also attempts to partial match */ -router.get('/admin/lookup/:id', mw.adminOnly, (req, res, next)=>{ - HomebrewModel.findOne({ $or : [ - { editId: { '$regex': req.params.id, '$options': 'i' } }, - { shareId: { '$regex': req.params.id, '$options': 'i' } }, - ] }).exec((err, brew)=>{ - return res.json(brew); +router.get('/admin/lookup/:id', mw.adminOnly, async (req, res, next)=>{ + HomebrewModel.findOne({ + $or : [ + { editId: { $regex: req.params.id, $options: 'i' } }, + { shareId: { $regex: req.params.id, $options: 'i' } }, + ] + }).exec() + .then((brew)=>{ + if(!brew) // No document found + return res.status(404).json({ error: 'Document not found' }); + else + return res.json(brew); + }) + .catch((err)=>{ + console.error(err); + return res.status(500).json({ error: 'Internal Server Error' }); }); }); /* Find 50 brews that aren't compressed yet */ router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{ - uncompressedBrewQuery.exec((err, objs)=>{ - if(err) return res.status(500).send(err); - objs = objs.map((obj)=>{return obj._id;}); - return res.json({ count: objs.length, ids: objs }); - }); + const query = uncompressedBrewQuery.clone(); + + query.exec() + .then((objs)=>{ + const ids = objs.map((obj)=>obj._id); + res.json({ count: ids.length, ids }); + }) + .catch((err)=>{ + console.error(err); + res.status(500).send(err.message || 'Internal Server Error'); + }); }); + /* Compresses the "text" field of a brew to binary */ router.put('/admin/compress/:id', (req, res)=>{ - HomebrewModel.get({ _id: req.params.id }) + HomebrewModel.findOne({ _id: req.params.id }) .then((brew)=>{ - brew.textBin = zlib.deflateRawSync(brew.text); // Compress brew text to binary before saving - brew.text = undefined; // Delete the non-binary text field since it's not needed anymore + if(!brew) + return res.status(404).send('Brew not found'); - brew.save((err, obj)=>{ - if(err) throw err; - return res.status(200).send(obj); - }); + if(brew.text) { + brew.textBin = brew.textBin || zlib.deflateRawSync(brew.text); //Don't overwrite textBin if exists + brew.text = undefined; + } + + return brew.save(); }) + .then((obj)=>res.status(200).send(obj)) .catch((err)=>{ - console.log(err); - return res.status(500).send('Error while saving'); + console.error(err); + res.status(500).send('Error while saving'); }); }); -router.get('/admin/stats', mw.adminOnly, (req, res)=>{ - HomebrewModel.count({}, (err, count)=>{ + +router.get('/admin/stats', mw.adminOnly, async (req, res)=>{ + try { + const totalBrewsCount = await HomebrewModel.countDocuments({}); + const publishedBrewsCount = await HomebrewModel.countDocuments({ published: true }); + return res.json({ - totalBrews : count + totalBrews : totalBrewsCount, + totalPublishedBrews : publishedBrewsCount }); - }); + } catch (error) { + console.error(error); + return res.status(500).json({ error: 'Internal Server Error' }); + } }); router.get('/admin', mw.adminOnly, (req, res)=>{ templateFn('admin', { url : req.originalUrl }) - .then((page)=>res.send(page)) - .catch((err)=>res.sendStatus(500)); + .then((page)=>res.send(page)) + .catch((err)=>res.sendStatus(500)); }); module.exports = router; diff --git a/server/app.js b/server/app.js index 85ac459f5..e5b25b1af 100644 --- a/server/app.js +++ b/server/app.js @@ -316,7 +316,8 @@ app.get('/new/:id', asyncHandler(getBrew('share')), (req, res, next)=>{ text : req.brew.text, style : req.brew.style, renderer : req.brew.renderer, - theme : req.brew.theme + theme : req.brew.theme, + tags : req.brew.tags }; req.brew = _.defaults(brew, DEFAULT_BREW); @@ -339,14 +340,17 @@ app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, r type : 'article' }; - if(req.params.id.length > 12 && !brew._id) { - const googleId = brew.googleId; - const shareId = brew.shareId; - await GoogleActions.increaseView(googleId, shareId, 'share', brew) - .catch((err)=>{next(err);}); - } else { - await HomebrewModel.increaseView({ shareId: brew.shareId }); - } + // increase visitor view count, do not include visits by author(s) + if(!brew.authors.includes(req.account?.username)){ + if(req.params.id.length > 12 && !brew._id) { + const googleId = brew.googleId; + const shareId = brew.shareId; + await GoogleActions.increaseView(googleId, shareId, 'share', brew) + .catch((err)=>{next(err);}); + } else { + await HomebrewModel.increaseView({ shareId: brew.shareId }); + } + }; sanitizeBrew(req.brew, 'share'); splitTextStyleAndMetadata(req.brew); return next(); @@ -481,9 +485,18 @@ const getPureError = (error)=>{ }; app.use(async (err, req, res, next)=>{ - const status = err.status || err.code || 500; + err.originalUrl = req.originalUrl; console.error(err); + if(err.originalUrl?.startsWith('/api/')) { + // console.log('API error'); + res.status(err.status || err.response?.status || 500).send(err); + return; + } + + // console.log('non-API error'); + const status = err.status || err.code || 500; + req.ogMeta = { ...defaultMetaTags, title : 'Error Page', description : 'Something went wrong!' diff --git a/server/homebrew.api.js b/server/homebrew.api.js index b394b2ee7..20e13ec71 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -79,7 +79,7 @@ const api = { if(accessType === 'edit' && (authorsExist && !(isAuthor || isInvited))) { const accessError = { name: 'Access Error', status: 401 }; if(req.account){ - throw { ...accessError, message: 'User is not an Author', HBErrorCode: '03', authors: stub.authors, brewTitle: stub.title }; + throw { ...accessError, message: 'User is not an Author', HBErrorCode: '03', authors: stub.authors, brewTitle: stub.title, shareId: stub.shareId }; } throw { ...accessError, message: 'User is not logged in', HBErrorCode: '04', authors: stub.authors, brewTitle: stub.title }; } diff --git a/shared/naturalcrit/codeEditor/codeEditor.jsx b/shared/naturalcrit/codeEditor/codeEditor.jsx index e0a2220b4..0a99570db 100644 --- a/shared/naturalcrit/codeEditor/codeEditor.jsx +++ b/shared/naturalcrit/codeEditor/codeEditor.jsx @@ -7,7 +7,7 @@ const cx = require('classnames'); const closeTag = require('./close-tag'); let CodeMirror; -if(typeof navigator !== 'undefined'){ +if(typeof window !== 'undefined'){ CodeMirror = require('codemirror'); //Language Modes @@ -112,6 +112,10 @@ const CodeEditor = createClass({ 'Shift-Tab' : this.dedent, 'Ctrl-B' : this.makeBold, 'Cmd-B' : this.makeBold, + 'Shift-Ctrl-=' : this.makeSuper, + 'Shift-Cmd-=' : this.makeSuper, + 'Ctrl-=' : this.makeSub, + 'Cmd-=' : this.makeSub, 'Ctrl-I' : this.makeItalic, 'Cmd-I' : this.makeItalic, 'Ctrl-U' : this.makeUnderline, @@ -219,6 +223,25 @@ const CodeEditor = createClass({ } }, + makeSuper : function() { + const selection = this.codeMirror.getSelection(), t = selection.slice(0, 1) === '^' && selection.slice(-1) === '^'; + this.codeMirror.replaceSelection(t ? selection.slice(1, -1) : `^${selection}^`, 'around'); + if(selection.length === 0){ + const cursor = this.codeMirror.getCursor(); + this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 1 }); + } + }, + + makeSub : function() { + const selection = this.codeMirror.getSelection(), t = selection.slice(0, 2) === '^^' && selection.slice(-2) === '^^'; + this.codeMirror.replaceSelection(t ? selection.slice(2, -2) : `^^${selection}^^`, 'around'); + if(selection.length === 0){ + const cursor = this.codeMirror.getCursor(); + this.codeMirror.setCursor({ line: cursor.line, ch: cursor.ch - 2 }); + } + }, + + makeNbsp : function() { this.codeMirror.replaceSelection(' ', 'end'); }, diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index 114229887..09f810907 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -4,7 +4,40 @@ const Marked = require('marked'); const MarkedExtendedTables = require('marked-extended-tables'); const { markedSmartypantsLite: MarkedSmartypantsLite } = require('marked-smartypants-lite'); const { gfmHeadingId: MarkedGFMHeadingId } = require('marked-gfm-heading-id'); +const MathParser = require('expr-eval').Parser; const renderer = new Marked.Renderer(); +const tokenizer = new Marked.Tokenizer(); + +//Limit math features to simple items +const mathParser = new MathParser({ + operators : { + // These default to true, but are included to be explicit + add : true, + subtract : true, + multiply : true, + divide : true, + power : true, + round : true, + floor : true, + ceil : true, + + sin : false, cos : false, tan : false, asin : false, acos : false, + atan : false, sinh : false, cosh : false, tanh : false, asinh : false, + acosh : false, atanh : false, sqrt : false, cbrt : false, log : false, + log2 : false, ln : false, lg : false, log10 : false, expm1 : false, + log1p : false, abs : false, trunc : false, join : false, sum : false, + '-' : false, '+' : false, exp : false, not : false, length : false, + '!' : false, sign : false, random : false, fac : false, min : false, + max : false, hypot : false, pyt : false, pow : false, atan2 : false, + 'if' : false, gamma : false, roundTo : false, map : false, fold : false, + filter : false, indexOf : false, + + remainder : false, factorial : false, + comparison : false, concatenate : false, + logical : false, assignment : false, + array : false, fndef : false + } +}); //Processes the markdown within an HTML block if it's just a class-wrapper renderer.html = function (html) { @@ -28,13 +61,40 @@ renderer.paragraph = function(text){ return `

    ${text}

    \n`; }; +//Fix local links in the Preview iFrame to link inside the frame +renderer.link = function (href, title, text) { + let self = false; + if(href[0] == '#') { + self = true; + } + href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); + + if(href === null) { + return text; + } + let out = `${text}`; + return out; +}; + +// Disable default reflink behavior, as it steps on our variables extension +tokenizer.def = function () { + return undefined; +}; + const mustacheSpans = { name : 'mustacheSpans', level : 'inline', // Is this a block-level or inline-level tokenizer? start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token - const inlineRegex = /{{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *|}}/g; + const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; const match = completeSpan.exec(src); if(match) { //Find closing delimiter @@ -45,7 +105,7 @@ const mustacheSpans = { let delim; while (delim = inlineRegex.exec(match[0])) { if(!tags) { - tags = ` ${processStyleTags(delim[0].substring(2))}`; + tags = `${processStyleTags(delim[0].substring(2))}`; endTags = delim[0].length; } if(delim[0].startsWith('{{')) { @@ -84,7 +144,7 @@ const mustacheDivs = { start(src) { return src.match(/\n *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { const completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token - const blockRegex = /^ *{{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *$|^ *}}$/gm; + const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; const match = completeBlock.exec(src); if(match) { //Find closing delimiter @@ -95,8 +155,8 @@ const mustacheDivs = { let delim; while (delim = blockRegex.exec(match[0])?.[0].trim()) { if(!tags) { - tags = ` ${processStyleTags(delim.substring(2))}`; - endTags = delim.length; + tags = `${processStyleTags(delim.substring(2))}`; + endTags = delim.length + src.indexOf(delim); } if(delim.startsWith('{{')) { blockCount++; @@ -132,14 +192,14 @@ const mustacheInjectInline = { level : 'inline', start(src) { return src.match(/ *{[^{\n]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /^ *{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1}/g; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1]; if(!lastToken || lastToken.type == 'mustacheInjectInline') return false; - const tags = ` ${processStyleTags(match[1])}`; + const tags = `${processStyleTags(match[1])}`; lastToken.originalType = lastToken.type; lastToken.type = 'mustacheInjectInline'; lastToken.tags = tags; @@ -167,7 +227,7 @@ const mustacheInjectBlock = { level : 'block', start(src) { return src.match(/\n *{[^{\n]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /^ *{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1}/ym; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/ym; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1]; @@ -175,7 +235,7 @@ const mustacheInjectBlock = { return false; lastToken.originalType = 'mustacheInjectBlock'; - lastToken.tags = ` ${processStyleTags(match[1])}`; + lastToken.tags = `${processStyleTags(match[1])}`; return { type : 'mustacheInjectBlock', // Should match "name" above raw : match[0], // Text to consume from the source @@ -206,6 +266,34 @@ const mustacheInjectBlock = { } }; +const superSubScripts = { + name : 'superSubScript', + level : 'inline', + start(src) { return src.match(/\^/m)?.index; }, // Hint to Marked.js to stop and check for a match + tokenizer(src, tokens) { + const superRegex = /^\^(?!\s)(?=([^\n\^]*[^\s\^]))\1\^/m; + const subRegex = /^\^\^(?!\s)(?=([^\n\^]*[^\s\^]))\1\^\^/m; + let isSuper = false; + let match = subRegex.exec(src); + if(!match){ + match = superRegex.exec(src); + if(match) + isSuper = true; + } + if(match?.length) { + return { + type : 'superSubScript', // Should match "name" above + raw : match[0], // Text to consume from the source + tag : isSuper ? 'sup' : 'sub', + tokens : this.lexer.inlineTokens(match[1]) + }; + } + }, + renderer(token) { + return `<${token.tag}>${this.parser.parseInline(token.tokens)}`; + } +}; + const definitionLists = { name : 'definitionLists', level : 'block', @@ -238,33 +326,257 @@ const definitionLists = { } }; -Marked.use({ extensions: [mustacheSpans, mustacheDivs, mustacheInjectInline, definitionLists] }); -Marked.use(mustacheInjectBlock); -Marked.use({ renderer: renderer, mangle: false }); -Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId(), MarkedSmartypantsLite()); -//Fix local links in the Preview iFrame to link inside the frame -renderer.link = function (href, title, text) { - let self = false; - if(href[0] == '#') { - self = true; - } - href = cleanUrl(this.options.sanitize, this.options.baseUrl, href); +//v=====--------------------< Variable Handling >-------------------=====v// 242 lines +const replaceVar = function(input, hoist=false, allowUnresolved=false) { + const regex = /([!$]?)\[((?!\s*\])(?:\\.|[^\[\]\\])+)\]/g; + const match = regex.exec(input); - if(href === null) { - return text; + const prefix = match[1]; + const label = match[2]; + + //v=====--------------------< HANDLE MATH >-------------------=====v// + const mathRegex = /[a-z]+\(|[+\-*/^()]/g; + const matches = label.split(mathRegex); + const mathVars = matches.filter((match)=>isNaN(match))?.map((s)=>s.trim()); // Capture any variable names + + let replacedLabel = label; + + if(prefix[0] == '$' && mathVars?.[0] !== label.trim()) {// If there was mathy stuff not captured, let's do math! + mathVars?.forEach((variable)=>{ + const foundVar = lookupVar(variable, globalPageNumber, hoist); + if(foundVar && foundVar.resolved && foundVar.content && !isNaN(foundVar.content)) // Only subsitute math values if fully resolved, not empty strings, and numbers + replacedLabel = replacedLabel.replaceAll(variable, foundVar.content); + }); + + try { + return mathParser.evaluate(replacedLabel); + } catch (error) { + return undefined; // Return undefined if invalid math result + } } - let out = `${text}`; - return out; + //^=====--------------------< HANDLE MATH >-------------------=====^// + + const foundVar = lookupVar(label, globalPageNumber, hoist); + + if(!foundVar || (!foundVar.resolved && !allowUnresolved)) + return undefined; // Return undefined if not found, or parially-resolved vars are not allowed + + // url or "title" or 'title' or (title) + const linkRegex = /^([^<\s][^\s]*|<.*?>)(?: ("(?:\\"|[^"])*"|'(?:\\'|[^'])*'|\((?:\\\(|\\\)|[^()])*\)))?$/m; + const linkMatch = linkRegex.exec(foundVar.content); + + const href = linkMatch ? linkMatch[1] : null; //TODO: TRIM OFF < > IF PRESENT + const title = linkMatch ? linkMatch[2]?.slice(1, -1) : null; + + if(!prefix[0] && href) // Link + return `[${label}](${href}${title ? ` "${title}"` : ''})`; + + if(prefix[0] == '!' && href) // Image + return `![${label}](${href} ${title ? ` "${title}"` : ''})`; + + if(prefix[0] == '$') // Variable + return foundVar.content; }; +const lookupVar = function(label, index, hoist=false) { + while (index >= 0) { + if(globalVarsList[index]?.[label] !== undefined) + return globalVarsList[index][label]; + index--; + } + + if(hoist) { //If normal lookup failed, attempt hoisting + index = Object.keys(globalVarsList).length; // Move index to start from last page + while (index >= 0) { + if(globalVarsList[index]?.[label] !== undefined) + return globalVarsList[index][label]; + index--; + } + } + + return undefined; +}; + +const processVariableQueue = function() { + let resolvedOne = true; + let finalLoop = false; + while (resolvedOne || finalLoop) { // Loop through queue until no more variable calls can be resolved + resolvedOne = false; + for (const item of varsQueue) { + if(item.type == 'text') + continue; + + if(item.type == 'varDefBlock') { + const regex = /[!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\]/g; + let match; + let resolved = true; + let tempContent = item.content; + while (match = regex.exec(item.content)) { // regex to find variable calls + const value = replaceVar(match[0], true); + + if(value == undefined) + resolved = false; + else + tempContent = tempContent.replaceAll(match[0], value); + } + + if(resolved == true || item.content != tempContent) { + resolvedOne = true; + item.content = tempContent; + } + + globalVarsList[globalPageNumber][item.varName] = { + content : item.content, + resolved : resolved + }; + + if(resolved) + item.type = 'resolved'; + } + + if(item.type == 'varCallBlock' || item.type == 'varCallInline') { + const value = replaceVar(item.content, true, finalLoop); // final loop will just use the best value so far + + if(value == undefined) + continue; + + resolvedOne = true; + item.content = value; + item.type = 'text'; + } + } + varsQueue = varsQueue.filter((item)=>item.type !== 'resolved'); // Remove any fully-resolved variable definitions + + if(finalLoop) + break; + if(!resolvedOne) + finalLoop = true; + } + varsQueue = varsQueue.filter((item)=>item.type !== 'varDefBlock'); +}; + +function MarkedVariables() { + return { + hooks : { + preprocess(src) { + const codeBlockSkip = /^(?: {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+|^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})(?:[^\n]*)(?:\n|$)(?:|(?:[\s\S]*?)(?:\n|$))(?: {0,3}\2[~`]* *(?=\n|$))|`[^`]*?`/; + const blockDefRegex = /^[!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\]:(?!\() *((?:\n? *[^\s].*)+)(?=\n+|$)/; //Matches 3, [4]:5 + const blockCallRegex = /^[!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\](?=\n|$)/; //Matches 6, [7] + const inlineDefRegex = /([!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\])\(([^\n]+)\)/; //Matches 8, 9[10](11) + const inlineCallRegex = /[!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\](?!\()/; //Matches 12, [13] + + // Combine regexes and wrap in parens like so: (regex1)|(regex2)|(regex3)|(regex4) + const combinedRegex = new RegExp([codeBlockSkip, blockDefRegex, blockCallRegex, inlineDefRegex, inlineCallRegex].map((s)=>`(${s.source})`).join('|'), 'gm'); + + let lastIndex = 0; + let match; + while ((match = combinedRegex.exec(src)) !== null) { + // Format any matches into tokens and store + if(match.index > lastIndex) { // Any non-variable stuff + varsQueue.push( + { type : 'text', + varName : null, + content : src.slice(lastIndex, match.index) + }); + } + if(match[1]) { + varsQueue.push( + { type : 'text', + varName : null, + content : match[0] + }); + } + if(match[3]) { // Block Definition + const label = match[4] ? match[4].trim().replace(/\s+/g, ' ') : null; // Trim edge spaces and shorten blocks of whitespace to 1 space + const content = match[5] ? match[5].trim().replace(/[ \t]+/g, ' ') : null; // Trim edge spaces and shorten blocks of whitespace to 1 space + + varsQueue.push( + { type : 'varDefBlock', + varName : label, + content : content + }); + } + if(match[6]) { // Block Call + const label = match[7] ? match[7].trim().replace(/\s+/g, ' ') : null; // Trim edge spaces and shorten blocks of whitespace to 1 space + + varsQueue.push( + { type : 'varCallBlock', + varName : label, + content : match[0] + }); + } + if(match[8]) { // Inline Definition + const label = match[10] ? match[10].trim().replace(/\s+/g, ' ') : null; // Trim edge spaces and shorten blocks of whitespace to 1 space + let content = match[11] ? match[11].trim().replace(/\s+/g, ' ') : null; // Trim edge spaces and shorten blocks of whitespace to 1 space + + // In case of nested (), find the correct matching end ) + let level = 0; + let i; + for (i = 0; i < content.length; i++) { + if(content[i] === '\\') { + i++; + } else if(content[i] === '(') { + level++; + } else if(content[i] === ')') { + level--; + if(level < 0) + break; + } + } + if(i > -1) { + combinedRegex.lastIndex = combinedRegex.lastIndex - (content.length - i); + content = content.slice(0, i).trim().replace(/\s+/g, ' '); + } + + varsQueue.push( + { type : 'varDefBlock', + varName : label, + content : content + }); + varsQueue.push( + { type : 'varCallInline', + varName : label, + content : match[9] + }); + } + if(match[12]) { // Inline Call + const label = match[13] ? match[13].trim().replace(/\s+/g, ' ') : null; // Trim edge spaces and shorten blocks of whitespace to 1 space + + varsQueue.push( + { type : 'varCallInline', + varName : label, + content : match[0] + }); + } + lastIndex = combinedRegex.lastIndex; + } + + if(lastIndex < src.length) { + varsQueue.push( + { type : 'text', + varName : null, + content : src.slice(lastIndex) + }); + } + + processVariableQueue(); + + const output = varsQueue.map((item)=>item.content).join(''); + varsQueue = []; // Must clear varsQueue because custom HTML renderer uses Marked.parse which will preprocess again without clearing the array + return output; + } + } + }; +}; +//^=====--------------------< Variable Handling >-------------------=====^// + +Marked.use(MarkedVariables()); +Marked.use({ extensions: [mustacheSpans, mustacheDivs, mustacheInjectInline, definitionLists, superSubScripts] }); +Marked.use(mustacheInjectBlock); +Marked.use({ renderer: renderer, tokenizer: tokenizer, mangle: false }); +Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId(), MarkedSmartypantsLite()); + const nonWordAndColonTest = /[^\w:]/g; const cleanUrl = function (sanitize, base, href) { if(sanitize) { @@ -326,24 +638,43 @@ const voidTags = new Set([ ]); const processStyleTags = (string)=>{ - //split tags up. quotes can only occur right after colons. + //split tags up. quotes can only occur right after : or =. //TODO: can we simplify to just split on commas? - const tags = string.match(/(?:[^, ":]+|:(?:"[^"]*"|))+/g); + const tags = string.match(/(?:[^, ":=]+|[:=](?:"[^"]*"|))+/g); - if(!tags) return '"'; + const id = _.remove(tags, (tag)=>tag.startsWith('#')).map((tag)=>tag.slice(1))[0]; + const classes = _.remove(tags, (tag)=>(!tag.includes(':')) && (!tag.includes('='))); + const attributes = _.remove(tags, (tag)=>(tag.includes('='))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"')); + const styles = tags?.length ? tags.map((tag)=>tag.replace(/:"?([^"]*)"?/g, ':$1;').trim()) : []; - const id = _.remove(tags, (tag)=>tag.startsWith('#')).map((tag)=>tag.slice(1))[0]; - const classes = _.remove(tags, (tag)=>!tag.includes(':')); - const styles = tags.map((tag)=>tag.replace(/:"?([^"]*)"?/g, ':$1;')); - return `${classes.join(' ')}" ${id ? `id="${id}"` : ''} ${styles.length ? `style="${styles.join(' ')}"` : ''}`; + return `${classes?.length ? ` ${classes.join(' ')}` : ''}"` + + `${id ? ` id="${id}"` : ''}` + + `${styles?.length ? ` style="${styles.join(' ')}"` : ''}` + + `${attributes?.length ? ` ${attributes.join(' ')}` : ''}`; }; +const globalVarsList = {}; +let varsQueue = []; +let globalPageNumber = 0; + module.exports = { marked : Marked, - render : (rawBrewText)=>{ + render : (rawBrewText, pageNumber=1)=>{ + globalVarsList[pageNumber] = {}; //Reset global links for current page, to ensure values are parsed in order + varsQueue = []; //Could move into MarkedVariables() + globalPageNumber = pageNumber; + rawBrewText = rawBrewText.replace(/^\\column$/gm, `\n
    \n`) .replace(/^(:+)$/gm, (match)=>`${`
    `.repeat(match.length)}\n`); - return Marked.parse(rawBrewText); + const opts = Marked.defaults; + + rawBrewText = opts.hooks.preprocess(rawBrewText); + const tokens = Marked.lexer(rawBrewText, opts); + + Marked.walkTokens(tokens, opts.walkTokens); + + const html = Marked.parser(tokens, opts); + return opts.hooks.postprocess(html); }, validate : (rawBrewText)=>{ diff --git a/tests/markdown/mustache-syntax.test.js b/tests/markdown/mustache-syntax.test.js index d9e1ce6f9..835bcc575 100644 --- a/tests/markdown/mustache-syntax.test.js +++ b/tests/markdown/mustache-syntax.test.js @@ -13,137 +13,134 @@ String.prototype.trimReturns = function(){ // Remove the `.failing()` method once you have fixed the issue. describe('Inline: When using the Inline syntax {{ }}', ()=>{ - it.failing('Renders a mustache span with text only', function() { + it('Renders a mustache span with text only', function() { const source = '{{ text}}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); - it.failing('Renders a mustache span with text only, but with spaces', function() { + it('Renders a mustache span with text only, but with spaces', function() { const source = '{{ this is a text}}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('this is a text'); }); - it.failing('Renders an empty mustache span', function() { + it('Renders an empty mustache span', function() { const source = '{{}}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(''); }); - it.failing('Renders a mustache span with just a space', function() { + it('Renders a mustache span with just a space', function() { const source = '{{ }}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(''); }); - it.failing('Renders a mustache span with a few spaces only', function() { + it('Renders a mustache span with a few spaces only', function() { const source = '{{ }}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(''); }); - it.failing('Renders a mustache span with text and class', function() { + it('Renders a mustache span with text and class', function() { const source = '{{my-class text}}'; const rendered = Markdown.render(source); - // FIXME: adds two extra \s before closing `>` in opening tag. expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); - it.failing('Renders a mustache span with text and two classes', function() { + it('Renders a mustache span with text and two classes', function() { const source = '{{my-class,my-class2 text}}'; const rendered = Markdown.render(source); - // FIXME: adds two extra \s before closing `>` in opening tag. expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); - it.failing('Renders a mustache span with text with spaces and class', function() { + it('Renders a mustache span with text with spaces and class', function() { const source = '{{my-class this is a text}}'; const rendered = Markdown.render(source); - // FIXME: adds two extra \s before closing `>` in opening tag expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('this is a text'); }); - it.failing('Renders a mustache span with text and id', function() { + it('Renders a mustache span with text and id', function() { const source = '{{#my-span text}}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s before closing `>` in opening tag, and another after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); - it.failing('Renders a mustache span with text and two ids', function() { + it('Renders a mustache span with text and two ids', function() { const source = '{{#my-span,#my-favorite-span text}}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s before closing `>` in opening tag, and another after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); - it.failing('Renders a mustache span with text and css property', function() { + it('Renders a mustache span with text and css property', function() { const source = '{{color:red text}}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); - it.failing('Renders a mustache span with text and two css properties', function() { + it('Renders a mustache span with text and two css properties', function() { const source = '{{color:red,padding:5px text}}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); - it.failing('Renders a mustache span with text and css property which contains quotes', function() { + it('Renders a mustache span with text and css property which contains quotes', function() { const source = '{{font-family:"trebuchet ms" text}}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); - it.failing('Renders a mustache span with text and two css properties which contains quotes', function() { + it('Renders a mustache span with text and two css properties which contains quotes', function() { const source = '{{font-family:"trebuchet ms",padding:"5px 10px" text}}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); - it.failing('Renders a mustache span with text with quotes and css property which contains quotes', function() { + it('Renders a mustache span with text with quotes and css property which contains double quotes', function() { const source = '{{font-family:"trebuchet ms" text "with quotes"}}'; const rendered = Markdown.render(source); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text “with quotes”'); }); + + it('Renders a mustache span with text with quotes and css property which contains double and simple quotes', function() { + const source = `{{--stringVariable:"'string'" text "with quotes"}}`; + const rendered = Markdown.render(source); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`text “with quotes”`); + }); + + it('Renders a mustache span with text, id, class and a couple of css properties', function() { const source = '{{pen,#author,color:orange,font-family:"trebuchet ms" text}}'; const rendered = Markdown.render(source); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); + + it('Renders a span with added attributes', function() { + const source = 'Text and {{pen,#author,color:orange,font-family:"trebuchet ms",a="b and c",d=e, text}} and more text!'; + const rendered = Markdown.render(source); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    Text and text and more text!

    \n'); + }); }); // BLOCK SYNTAX describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ - it.failing('Renders a div with text only', function() { + it('Renders a div with text only', function() { const source = dedent`{{ text }}`; const rendered = Markdown.render(source).trimReturns(); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    text

    `); }); - it.failing('Renders an empty div', function() { + it('Renders an empty div', function() { const source = dedent`{{ }}`; const rendered = Markdown.render(source).trimReturns(); - // FIXME: adds extra \s after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
    `); }); @@ -151,52 +148,62 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ const source = dedent`{{ }}`; const rendered = Markdown.render(source).trimReturns(); - // this actually renders in HB as '{{ }}'... expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    {{}}

    `); }); - it.failing('Renders a div with a single class', function() { + it('Renders a div with a single class', function() { const source = dedent`{{cat }}`; const rendered = Markdown.render(source).trimReturns(); - // FIXME: adds two extra \s before closing `>` in opening tag expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`
    `); }); - it.failing('Renders a div with a single class and text', function() { + it('Renders a div with a single class and text', function() { const source = dedent`{{cat Sample text. }}`; const rendered = Markdown.render(source).trimReturns(); - // FIXME: adds two extra \s before closing `>` in opening tag expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); - it.failing('Renders a div with two classes and text', function() { + it('Renders a div with two classes and text', function() { const source = dedent`{{cat,dog Sample text. }}`; const rendered = Markdown.render(source).trimReturns(); - // FIXME: adds two extra \s before closing `>` in opening tag expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); - it.failing('Renders a div with a style and text', function() { + it('Renders a div with a style and text', function() { const source = dedent`{{color:red Sample text. }}`; const rendered = Markdown.render(source).trimReturns(); - // FIXME: adds two extra \s before closing `>` in opening tag expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); - it.failing('Renders a div with a class, style and text', function() { + it('Renders a div with a style that has a string variable, and text', function() { + const source = dedent`{{--stringVariable:"'string'" + Sample text. + }}`; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); + }); + + it('Renders a div with a style that has a string variable, and text', function() { + const source = dedent`{{--stringVariable:"'string'" + Sample text. + }}`; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); + }); + + it('Renders a div with a class, style and text', function() { const source = dedent`{{cat,color:red Sample text. }}`; const rendered = Markdown.render(source).trimReturns(); - // FIXME: adds extra \s after the class attribute expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); @@ -208,14 +215,27 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); - it.failing('Renders a div with a single ID', function() { + it('Renders a div with a single ID', function() { const source = dedent`{{#cat,#dog Sample text. }}`; const rendered = Markdown.render(source).trimReturns(); - // FIXME: adds extra \s before closing `>` in opening tag, and another after class names expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); }); + + it('Renders a div with an ID, class, style and text, and a variable assignment', function() { + const source = dedent`{{color:red,cat,#dog,a="b and c",d="e" + Sample text. + }}`; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    Sample text.

    `); + }); + + it('Renders a div with added attributes', function() { + const source = '{{pen,#author,color:orange,font-family:"trebuchet ms",a="b and c",d=e\nText and text and more text!\n}}\n'; + const rendered = Markdown.render(source); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    Text and text and more text!

    \n
    '); + }); }); // MUSTACHE INJECTION SYNTAX @@ -235,12 +255,24 @@ describe('Injection: When an injection tag follows an element', ()=>{ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); + it.failing('Renders a span "text" with injected attribute', function() { + const source = '{{ text}}{a="b and c"}'; + const rendered = Markdown.render(source); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); + }); + it.failing('Renders a span "text" with injected style', function() { const source = '{{ text}}{color:red}'; const rendered = Markdown.render(source); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); + it.failing('Renders a span "text" with injected style using a string variable', function() { + const source = `{{ text}}{--stringVariable:"'string'"}`; + const rendered = Markdown.render(source); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`text`); + }); + it.failing('Renders a span "text" with two injected styles', function() { const source = '{{ text}}{color:red,background:blue}'; const rendered = Markdown.render(source); @@ -270,6 +302,12 @@ describe('Injection: When an injection tag follows an element', ()=>{ const rendered = Markdown.render(source).trimReturns(); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text{background:blue}

    '); }); + + it('Renders an image with added attributes', function() { + const source = `![homebrew mug](https://i.imgur.com/hMna6G0.png) {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e}`; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    homebrew mug

    `); + }); }); describe('and that element is a block', ()=>{ @@ -297,7 +335,16 @@ describe('Injection: When an injection tag follows an element', ()=>{ }} {color:red,background:blue}`; const rendered = Markdown.render(source).trimReturns(); - expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    text

    '); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    text

    `); + }); + + it.failing('renders a div "text" with injected variable string', function() { + const source = dedent`{{ + text + }} + {--stringVariable:"'string'"}`; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    text

    `); }); it.failing('renders an h2 header "text" with injected class name', function() { diff --git a/tests/markdown/variables.test.js b/tests/markdown/variables.test.js new file mode 100644 index 000000000..c909dafec --- /dev/null +++ b/tests/markdown/variables.test.js @@ -0,0 +1,373 @@ +/* eslint-disable max-lines */ + +const dedent = require('dedent-tabs').default; +const Markdown = require('naturalcrit/markdown.js'); + +// Marked.js adds line returns after closing tags on some default tokens. +// This removes those line returns for comparison sake. +String.prototype.trimReturns = function(){ + return this.replace(/\r?\n|\r/g, '').trim(); +}; + +renderAllPages = function(pages){ + const outputs = []; + pages.forEach((page, index)=>{ + const output = Markdown.render(page, index); + outputs.push(output); + }); + + return outputs; +}; + +// Adding `.failing()` method to `describe` or `it` will make failing tests "pass" as long as they continue to fail. +// Remove the `.failing()` method once you have fixed the issue. + +describe('Block-level variables', ()=>{ + it('Handles variable assignment and recall with simple text', function() { + const source = dedent` + [var]: string + + $[var] + `; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    string

    '); + }); + + it('Handles variable assignment and recall with multiline string', function() { + const source = dedent` + [var]: string + across multiple + lines + + $[var]`; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    string across multiple lines

    '); + }); + + it('Handles variable assignment and recall with tables', function() { + const source = dedent` + [var]: + ##### Title + | H1 | H2 | + |:---|:--:| + | A | B | + | C | D | + + $[var]`; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent` +
    Title
    + + + + + + +
    H1H2
    AB
    CD
    `.trimReturns()); + }); + + it('Hoists undefined variables', function() { + const source = dedent` + $[var] + + [var]: string`; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    string

    '); + }); + + it('Hoists last instance of variable', function() { + const source = dedent` + $[var] + + [var]: string + + [var]: new string`; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    new string

    '); + }); + + it('Handles complex hoisting', function() { + const source = dedent` + $[titleAndName]: $[title] $[fullName] + + $[title]: Mr. + + $[fullName]: $[firstName] $[lastName] + + [firstName]: Bob + + Welcome, $[titleAndName]! + + [lastName]: Jacob + + [lastName]: $[lastName]son + `; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    Welcome, Mr. Bob Jacobson!

    '); + }); + + it('Handles variable reassignment', function() { + const source = dedent` + [var]: one + + $[var] + + [var]: two + + $[var] + `; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    one

    two

    '.trimReturns()); + }); + + it('Handles variable reassignment with hoisting', function() { + const source = dedent` + $[var] + + [var]: one + + $[var] + + [var]: two + + $[var] + `; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    two

    one

    two

    '.trimReturns()); + }); + + it('Ignores undefined variables that can\'t be hoisted', function() { + const source = dedent` + $[var](My name is $[first] $[last]) + + $[last]: Jones + `; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    My name is $[first] Jones

    `.trimReturns()); + }); +}); + +describe('Inline-level variables', ()=>{ + it('Handles variable assignment and recall with simple text', function() { + const source = dedent` + $[var](string) + + $[var] + `; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    string

    string

    '); + }); + + it('Hoists undefined variables when possible', function() { + const source = dedent` + $[var](My name is $[name] Jones) + + [name]: Bob`; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    My name is Bob Jones

    '); + }); + + it('Hoists last instance of variable', function() { + const source = dedent` + $[var](My name is $[name] Jones) + + $[name](Bob) + + [name]: Bill`; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`

    My name is Bill Jones

    Bob

    `.trimReturns()); + }); + + it('Only captures nested parens if balanced', function() { + const source = dedent` + $[var1](A variable (with nested parens) inside) + + $[var1] + + $[var2](A variable ) with unbalanced parens) + + $[var2]`; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent` +

    A variable (with nested parens) inside

    +

    A variable (with nested parens) inside

    +

    A variable with unbalanced parens)

    +

    A variable

    + `.trimReturns()); + }); +}); + +describe('Math', ()=>{ + it('Handles simple math using numbers only', function() { + const source = dedent` + $[1 + 3 * 5 - (1 / 4)] + `; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    15.75

    '); + }); + + it('Handles round function', function() { + const source = dedent` + $[round(1/4)]`; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    0

    '); + }); + + it('Handles floor function', function() { + const source = dedent` + $[floor(0.6)]`; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    0

    '); + }); + + it('Handles ceil function', function() { + const source = dedent` + $[ceil(0.2)]`; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    1

    '); + }); + + it('Handles nested functions', function() { + const source = dedent` + $[ceil(floor(round(0.6)))]`; + const rendered = Markdown.render(source).replace(/\s/g, ' ').trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    1

    '); + }); + + it('Handles simple math with variables', function() { + const source = dedent` + $[num1]: 5 + + $[num2]: 4 + + Answer is $[answer]($[1 + 3 * num1 - (1 / num2)]). + `; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    Answer is 15.75.

    '); + }); + + it('Handles variable incrementing', function() { + const source = dedent` + $[num1]: 5 + + Increment num1 to get $[num1]($[num1 + 1]) and again to $[num1]($[num1 + 1]). + `; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('

    Increment num1 to get 6 and again to 7.

    '); + }); +}); + +describe('Code blocks', ()=>{ + it('Ignores all variables in fenced code blocks', function() { + const source = dedent` + \`\`\` + [var]: string + + $[var] + + $[var](new string) + \`\`\` + `; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent` +
    
    +		 [var]: string
    +		 
    +		 $[var]
    +		 
    +		 $[var](new string)
    +		 
    `.trimReturns()); + }); + + it('Ignores all variables in indented code blocks', function() { + const source = dedent` + test + + [var]: string + + $[var] + + $[var](new string) + `; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent` +

    test

    + +
    
    +		 [var]: string
    +		 
    +		 $[var]
    +		 
    +		 $[var](new string)
    +		 
    `.trimReturns()); + }); + + it('Ignores all variables in inline code blocks', function() { + const source = '[var](Hello) `[link](url)`. This `[var] does not work`'; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent` +

    var [link](url). This [var] does not work

    `.trimReturns()); + }); +}); + +describe('Normal Links and Images', ()=>{ + it('Renders normal images', function() { + const source = `![alt text](url)`; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent` +

    alt text

    `.trimReturns()); + }); + + it('Renders normal images with a title', function() { + const source = 'An image ![alt text](url "and title")!'; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent` +

    An image alt text!

    `.trimReturns()); + }); + + it('Applies curly injectors to images', function() { + const source = `![alt text](url){width:100px}`; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent` +

    alt text

    `.trimReturns()); + }); + + it('Renders normal links', function() { + const source = 'A Link to my [website](url)!'; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent` +

    A Link to my website!

    `.trimReturns()); + }); + + it('Renders normal links with a title', function() { + const source = 'A Link to my [website](url "and title")!'; + const rendered = Markdown.render(source).trimReturns(); + expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent` +

    A Link to my website!

    `.trimReturns()); + }); +}); + +describe('Cross-page variables', ()=>{ + it('Handles variable assignment and recall across pages', function() { + const source0 = `[var]: string`; + const source1 = `$[var]`; + const rendered = renderAllPages([source0, source1]).join('\n\\page\n').trimReturns(); + expect(rendered, `Input:\n${[source0, source1].join('\n\\page\n')}`, { showPrefix: false }).toBe('\\page

    string

    '); + }); + + it('Handles hoisting across pages', function() { + const source0 = `$[var]`; + const source1 = `[var]: string`; + renderAllPages([source0, source1]).join('\n\\page\n').trimReturns(); //Requires one full render of document before hoisting is picked up + const rendered = renderAllPages([source0, source1]).join('\n\\page\n').trimReturns(); + expect(rendered, `Input:\n${[source0, source1].join('\n\\page\n')}`, { showPrefix: false }).toBe('

    string

    \\page'); + }); + + it('Handles reassignment and hoisting across pages', function() { + const source0 = `$[var]\n\n[var]: one\n\n$[var]`; + const source1 = `[var]: two\n\n$[var]`; + renderAllPages([source0, source1]).join('\n\\page\n').trimReturns(); //Requires one full render of document before hoisting is picked up + const rendered = renderAllPages([source0, source1]).join('\n\\page\n').trimReturns(); + expect(rendered, `Input:\n${[source0, source1].join('\n\\page\n')}`, { showPrefix: false }).toBe('

    two

    one

    \\page

    two

    '); + }); +}); \ No newline at end of file diff --git a/themes/Legacy/5ePHB/style.less b/themes/Legacy/5ePHB/style.less index fa7539f16..09eb2eec7 100644 --- a/themes/Legacy/5ePHB/style.less +++ b/themes/Legacy/5ePHB/style.less @@ -40,7 +40,7 @@ body { -webkit-column-gap : 1cm; -moz-column-gap : 1cm; } -.phb{ +.phb, .page{ .useColumns(); counter-increment : phb-page-numbers; position : relative; @@ -59,6 +59,9 @@ body { page-break-before : always; page-break-after : always; contain : size; +} + +.phb{ //***************************** // * BASE // *****************************/ diff --git a/themes/V3/5ePHB/snippets/classfeature.gen.js b/themes/V3/5ePHB/snippets/classfeature.gen.js index 2597c3ee8..e2e9148b5 100644 --- a/themes/V3/5ePHB/snippets/classfeature.gen.js +++ b/themes/V3/5ePHB/snippets/classfeature.gen.js @@ -42,8 +42,8 @@ module.exports = function(classname){ #### Equipment You start with the following equipment, in addition to the equipment granted by your background: - - *(a)* a martial weapon and a shield or *(b)* two martial weapons - - *(a)* five javelins or *(b)* any simple melee weapon + - (*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'])} `; }; diff --git a/themes/V3/5ePHB/style.less b/themes/V3/5ePHB/style.less index f37dfae2b..23c3992fd 100644 --- a/themes/V3/5ePHB/style.less +++ b/themes/V3/5ePHB/style.less @@ -1,5 +1,6 @@ @import (less) './themes/fonts/5e/fonts.less'; @import (less) './themes/assets/assets.less'; +@import (less) './themes/fonts/icon fonts/font-icons.less'; :root { //Colors @@ -14,16 +15,13 @@ --HB_Color_Footnotes : #C9AD6A; // Gold } -@page { margin : 0; } -body { counter-reset : phb-page-numbers; } -* { -webkit-print-color-adjust : exact; } .useSansSerif() { - font-family : "ScalySansRemake"; + font-family : 'ScalySansRemake'; font-size : 0.318cm; line-height : 1.2em; p,dl,ul,ol { line-height : 1.2em; } ul, ol { padding-left : 1em; } - em { font-style : italic; } + em { font-style : italic; } strong { font-weight : 800; letter-spacing : -0.02em; @@ -42,55 +40,31 @@ body { counter-reset : phb-page-numbers; } -webkit-column-gap : 0.9cm; -moz-column-gap : 0.9cm; } -.columnWrapper { - column-gap : inherit; - max-height : 100%; - column-span : all; - columns : inherit; -} .page { .useColumns(); - position : relative; - z-index : 15; - box-sizing : border-box; - width : 215.9mm; - height : 279.4mm; - padding : 1.4cm 1.9cm 1.7cm; - overflow : hidden; - font-family : "BookInsanityRemake"; - font-size : 0.34cm; - counter-increment : phb-page-numbers; - background-color : var(--HB_Color_Background); - background-image : @backgroundImage; - text-rendering : optimizeLegibility; - page-break-before : always; - page-break-after : always; + font-family : 'BookInsanityRemake'; + font-size : 0.34cm; + background-image : @backgroundImage; } -//***************************** +// ***************************** // * BASE - // *****************************/ +// *****************************/ .page { p { - display : block; - line-height : 1.25em; - overflow-wrap : break-word; //TODO: MAKE ALL MARGINS TOP-ONLY. USE * + * STYLE SELECTORS - & + * { margin-top : 0.325cm; } + line-height : 1.25em; + & + * { margin-top : 0.325cm; } //TODO: MAKE ALL MARGINS TOP-ONLY. USE * + * STYLE SELECTORS & + p { margin-top : 0; } } ul { - padding-left : 1.4em; - margin-bottom : 0.8em; - line-height : 1.25em; - list-style-position : outside; - list-style-type : disc; + padding-left : 1.4em; + margin-bottom : 0.8em; + line-height : 1.25em; } ol { - padding-left : 1.4em; - margin-bottom : 0.8em; - line-height : 1.25em; - list-style-position : outside; - list-style-type : decimal; + padding-left : 1.4em; + margin-bottom : 0.8em; + line-height : 1.25em; } //Indents after p or lists p + p, ul + p, ol + p { text-indent : 1em; } @@ -99,24 +73,12 @@ body { counter-reset : phb-page-numbers; } font-weight : bold; letter-spacing : -0.02em; } - em { font-style : italic; } - sup { - font-size : smaller; - line-height : 0; - vertical-align : super; - } - sub { - font-size : smaller; - line-height : 0; - vertical-align : sub; - } - //***************************** + // ***************************** // * HEADERS // *****************************/ h1,h2,h3,h4 { - font-family : "MrEavesRemake"; - font-weight : 800; - color : var(--HB_Color_HeaderText); + font-family : 'MrEavesRemake'; + color : var(--HB_Color_HeaderText); } h1 { margin-bottom : 0.18cm; //Margin-bottom only because this is WIDE @@ -132,7 +94,7 @@ body { counter-reset : phb-page-numbers; } margin-top : -0.3cm; margin-bottom : -20px; margin-left : -40px; - font-family : "SolberaImitationRemake"; + font-family : 'SolberaImitationRemake'; font-size : 3.5cm; line-height : 1em; color : rgba(0, 0, 0, 0); @@ -145,8 +107,8 @@ body { counter-reset : phb-page-numbers; } h2 { //margin-top : 0px; //Font is misaligned. Shift up slightly //margin-bottom : 0.05cm; - font-size : 0.75cm; - line-height : 0.988em; //Font is misaligned. Shift up slightly + font-size : 0.75cm; + line-height : 0.988em; //Font is misaligned. Shift up slightly } h3 { //margin-top : -0.1cm; //Font is misaligned. Shift up slightly @@ -162,8 +124,8 @@ body { counter-reset : phb-page-numbers; } h4 { //margin-top : -0.02cm; //Font is misaligned. Shift up slightly //margin-bottom : 0.02cm; - font-size : 0.458cm; - line-height : 0.971em; //Font is misaligned. Shift up slightly + font-size : 0.458cm; + line-height : 0.971em; //Font is misaligned. Shift up slightly & + * { margin-top : 0.09cm; } } * + h4 { @@ -172,19 +134,17 @@ body { counter-reset : phb-page-numbers; } h5 { //margin-top : -0.02cm; //Font is misaligned. Shift up slightly //margin-bottom : 0.02cm; - font-family : "ScalySansSmallCapsRemake"; - font-size : 0.423cm; - font-weight : 900; - line-height : 0.951em; //Font is misaligned. Shift up slightly + font-family : 'ScalySansSmallCapsRemake'; + font-size : 0.423cm; + line-height : 0.951em; //Font is misaligned. Shift up slightly & + * { margin-top : 0.2cm; } } - //***************************** + // ***************************** // * TABLE // *****************************/ table { .useSansSerif(); - width : 100%; - line-height : 16px; + line-height : 16px; & + * { margin-top : 0.325cm; } thead { display : table-row-group; @@ -200,15 +160,15 @@ body { counter-reset : phb-page-numbers; } tr { td { //padding : 0.14em 0.4em; - padding : 0px 1.5px; // Both of these are temporary, just to force + padding : 0px 1.5px; // Both of these are temporary, just to force //line-height : 16px; // PDF to render at same height until Chrome 108 } &:nth-child(odd) { background-color : var(--HB_Color_Accent); } } } } - //***************************** - // * QUOTE + // ***************************** + // * QUOTE // *****************************/ .quote { @@ -241,9 +201,7 @@ body { counter-reset : phb-page-numbers; } } - - - //***************************** + // ***************************** // * NOTE // *****************************/ .note { @@ -257,7 +215,7 @@ body { counter-reset : phb-page-numbers; } border-image-outset : 9px 0px; box-shadow : 1px 4px 14px #888888; .page :where(&) { - margin-top : 9px; //Prevent top border getting cut off on colbreak + margin-top : 9px; //Prevent top border getting cut off on colbreak } & + * { margin-top : 0.45cm; } h5 { font-size : 0.375cm; } @@ -267,7 +225,7 @@ body { counter-reset : phb-page-numbers; } } :last-child { margin-bottom : 0; } } - //************************************ + // ************************************ // * DESCRIPTIVE TEXT BOX // ************************************/ .descriptive { @@ -291,7 +249,7 @@ body { counter-reset : phb-page-numbers; } } :last-child { margin-bottom : 0; } } - //***************************** + // ***************************** // * Images Snippets // *****************************/ @@ -299,7 +257,7 @@ body { counter-reset : phb-page-numbers; } .artist { position : absolute; width : auto; - font-family : "WalterTurncoat"; + font-family : 'WalterTurncoat'; font-size : 0.27cm; color : var(--HB_Color_CaptionText); text-align : center; @@ -309,7 +267,7 @@ body { counter-reset : phb-page-numbers; } text-indent : unset; } h5 { - font-family : "WalterTurncoat"; + font-family : 'WalterTurncoat'; font-size : 1.3em; } a { @@ -320,42 +278,10 @@ body { counter-reset : phb-page-numbers; } } /* Watermark */ - .watermark { - position : absolute; - top : 0; - left : 0; - z-index : 500; - display : grid !important; - place-items : center; - justify-content : center; - width : 100%; - height : 100%; - font-size : 120px; - color : black; - text-transform : uppercase; - mix-blend-mode : overlay; - opacity : 30%; - transform : rotate(-45deg); - p { margin-bottom : none; } - } + .watermark { color : black; } /* Watercolor */ - [class*='watercolor'] { - position : absolute; - z-index : -2; - width : 2000px; /* dimensions need to be real big so the user can set */ - height : 2000px; /* height or width and the image will maintain aspect ratio */ - background-color : var(--HB_Color_WatercolorStain); /* default color */ - background-size : cover; - -webkit-mask-image : var(--wc); - -webkit-mask-size : contain; - -webkit-mask-repeat : no-repeat; - mask-image : var(--wc); - mask-size : contain; - mask-repeat : no-repeat; - --wc : @watercolor1; /* default image */ - } - + .watercolor1 { --wc : @watercolor1; } .watercolor2 { --wc : @watercolor2; } .watercolor3 { --wc : @watercolor3; } @@ -369,7 +295,7 @@ body { counter-reset : phb-page-numbers; } .watercolor11 { --wc : @watercolor11; } .watercolor12 { --wc : @watercolor12; } - //***************************** + // ***************************** // * MONSTER STAT BLOCK // *****************************/ .monster { @@ -381,7 +307,7 @@ body { counter-reset : phb-page-numbers; } margin-left : -0.16cm; background-color : var(--HB_Color_MonsterStatBackground); background-image : @monsterBlockBackground; - background-attachment : fixed; + background-attachment : unset; background-blend-mode : overlay; border-style : solid; border-width : 7px 6px; @@ -390,27 +316,24 @@ body { counter-reset : phb-page-numbers; } box-shadow : 1px 4px 14px #888888; } - position : relative; - padding : 0px; - margin-bottom : 0.325cm; + position : relative; + padding : 0px; + margin-bottom : 0.325cm; //Headers h2 { - margin : 0; - font-size : 0.62cm; - line-height : 1em; + margin : 0; + font-size : 0.62cm; + line-height : 1em; & + p { margin-bottom : 0; font-size : 0.304cm; //Monster size and type subtext } } h3 { - // margin-top : 0.05cm; //Font is misaligned. Shift up slightly - padding-bottom : 0.05cm; - font-family : "ScalySansRemake"; - font-weight : 800; - font-variant : small-caps; - border-bottom : 2px solid var(--HB_Color_HeaderText); + font-family : 'ScalySansSmallCapsRemake'; + font-size : 0.45cm; + border-bottom : 1.5px solid var(--HB_Color_HeaderText); } //Triangle dividers @@ -446,6 +369,8 @@ body { counter-reset : phb-page-numbers; } tr { background-color : transparent; } td,th { padding : 0px; } } + //indent fix after bulleted lists + :is(ul,ol) + p { text-indent : 0; } :last-child { margin-bottom : 0; } } @@ -455,10 +380,10 @@ body { counter-reset : phb-page-numbers; } .useColumns(0.96, @fillMode: balance); } - //***************************** + // ***************************** // * FOOTER // *****************************/ - &:after { + &::after { position : absolute; bottom : 0px; left : 0px; @@ -498,23 +423,18 @@ body { counter-reset : phb-page-numbers; } color : var(--HB_Color_Footnotes); text-align : right; } - //************************************ + // ************************************ // * CODE BLOCKS // ************************************/ code { padding : 0px 4px; - font-family : 'Courier New', "Courier", monospace; - font-size : 0.325; + font-size : 0.325cm; color : #58180D; - overflow-wrap : break-word; - white-space : pre-wrap; background-color : #FAF7EA; border-radius : 4px; } pre code { - display : inline-block; - width : 100%; padding : 0.15cm; margin-bottom : 2px; border-style : solid; @@ -528,26 +448,13 @@ body { counter-reset : phb-page-numbers; } } & + * { margin-top : 0.325cm; } } - //***************************** + // ***************************** // * EXTRAS // *****************************/ hr { margin : 0px; visibility : hidden; } - .columnSplit { - visibility : hidden; - -webkit-column-break-after : always; - break-after : always; - -moz-column-break-after : always; - } - //Avoid breaking up - blockquote,table { - z-index : 15; - -webkit-column-break-inside : avoid; - page-break-inside : avoid; - break-inside : avoid; - } //Text indent right after table table + p { text-indent : 1em; } // Nested lists @@ -555,18 +462,13 @@ body { counter-reset : phb-page-numbers; } margin-bottom : 0px; margin-left : 1.5em; } - li { - -webkit-column-break-inside : avoid; - page-break-inside : avoid; - break-inside : avoid; - } } -//***************************** +// ***************************** // * SPELL LIST // *****************************/ .page .spellList { .useSansSerif(); - column-count : 2; + column-count : 2; ul + h5 { margin-top : 15px; } p, ul { font-size : 0.352cm; @@ -584,7 +486,7 @@ body { counter-reset : phb-page-numbers; } &.wide { column-count : 4; } } -//***************************** +// ***************************** // * CLASS TABLE // *****************************/ .page .classTable { @@ -631,7 +533,7 @@ body { counter-reset : phb-page-numbers; } } h5 + table { margin-top : 0.2cm; } } -//***************************** +// ***************************** // * FRONT COVER PAGE // *****************************/ .page:has(.frontCover) { @@ -641,7 +543,7 @@ body { counter-reset : phb-page-numbers; } h1 { margin-top : 1.2cm; margin-bottom : 0; - font-family : "NodestoCapsCondensed"; + font-family : 'NodestoCapsCondensed'; font-size : 2.245cm; font-weight : normal; line-height : 0.85em; @@ -654,7 +556,7 @@ body { counter-reset : phb-page-numbers; } drop-shadow(0 0 0 black) drop-shadow(0 0 0 black); } h2 { - font-family : "NodestoCapsCondensed"; + font-family : 'NodestoCapsCondensed'; font-size : 0.85cm; font-weight : normal; color : white; @@ -687,7 +589,7 @@ body { counter-reset : phb-page-numbers; } height : 1.7cm; padding-top : 0.1cm; padding-left : 1cm; - font-family : "NodestoCapsCondensed"; + font-family : 'NodestoCapsCondensed'; font-size : 1cm; font-weight : normal; color : white; @@ -704,7 +606,7 @@ body { counter-reset : phb-page-numbers; } width : 70%; margin-right : auto; margin-left : auto; - font-family : "Overpass"; + font-family : 'Overpass'; font-size : 0.496cm; color : white; text-align : center; @@ -725,7 +627,7 @@ body { counter-reset : phb-page-numbers; } } } } -//***************************** +// ***************************** // * INSIDE COVER PAGE // *****************************/ .page:has(.insideCover) { @@ -735,14 +637,14 @@ body { counter-reset : phb-page-numbers; } h1 { margin-top : 1.2cm; margin-bottom : 0; - font-family : "NodestoCapsCondensed"; + font-family : 'NodestoCapsCondensed'; font-size : 2.1cm; font-weight : normal; line-height : 0.85em; text-transform : uppercase; } h2 { - font-family : "NodestoCapsCondensed"; + font-family : 'NodestoCapsCondensed'; font-size : 0.85cm; font-weight : normal; letter-spacing : 0.5cm; @@ -770,7 +672,7 @@ body { counter-reset : phb-page-numbers; } } } } -//***************************** +// ***************************** // * BACK COVER // *****************************/ .page:has(.backCover) { @@ -791,7 +693,7 @@ body { counter-reset : phb-page-numbers; } .blank { height : 1.4em; } h1 { margin-bottom : 0.3cm; - font-family : "NodestoCapsCondensed"; + font-family : 'NodestoCapsCondensed'; font-size : 1.35cm; line-height : 0.95em; color : #ED1C24; @@ -817,7 +719,7 @@ body { counter-reset : phb-page-numbers; } border : none; } p { - font-family : "Overpass"; + font-family : 'Overpass'; font-size : 0.332cm; line-height : 1.5em; } @@ -841,7 +743,7 @@ body { counter-reset : phb-page-numbers; } p { position : relative; width : 100%; - font-family : "NodestoCapsWide"; + font-family : 'NodestoCapsWide'; font-size : 0.4cm; line-height : 1em; color : #FFFFFF; @@ -852,10 +754,10 @@ body { counter-reset : phb-page-numbers; } } } -//***************************** +// ***************************** // * PART COVER - // *****************************/ - .page:has(.partCover) { +// *****************************/ +.page:has(.partCover) { padding-top : 0; text-align : center; columns : 1; @@ -874,7 +776,7 @@ body { counter-reset : phb-page-numbers; } h1 { position : relative; margin-top : 0.4cm; - font-family : "NodestoCapsCondensed"; + font-family : 'NodestoCapsCondensed'; font-size : 2.3cm; text-align : center; text-transform : uppercase; @@ -885,13 +787,13 @@ body { counter-reset : phb-page-numbers; } margin-top : -0.7em; margin-right : auto; margin-left : auto; - font-family : "Overpass"; + font-family : 'Overpass'; font-size : 0.45cm; line-height : 1.1em; } } -//***************************** +// ***************************** // * TABLE OF CONTENTS // *****************************/ .page { @@ -960,34 +862,25 @@ body { counter-reset : phb-page-numbers; } } } -//***************************** +// ***************************** // * DEFINITION LISTS // *****************************/ .page { dl { - padding-left : 1em; line-height : 1.25em; - white-space : pre-line; - & + * { margin-top : 0.28cm; } + & + * { margin-top : 0.17cm; } } - dl + * { margin-top : 0.17cm; } p + dl { margin-top : 0.17cm; } dt { - display : inline; margin-right : 5px; margin-left : -1em; } - dd { - display : inline; - margin-left : 0px; - text-indent : 0px; - } } -//***************************** +// ***************************** // * WIDE // *****************************/ -.page .wide { margin-bottom : 0.325cm; } +.page .wide { margin-bottom : 0.325cm; } .page h1 + * { margin-top : 0; } @@ -1009,7 +902,7 @@ body { counter-reset : phb-page-numbers; } outline : 1px solid #000000; } th { - font-family : "BookInsanityRemake"; + font-family : 'BookInsanityRemake'; font-size : 0.45cm; } td { font-size : 0.7cm; } @@ -1026,7 +919,7 @@ body { counter-reset : phb-page-numbers; } } } } -//***************************** +// ***************************** // * INDEX // *****************************/ .page { diff --git a/themes/V3/Blank/snippets.js b/themes/V3/Blank/snippets.js index 72372c297..122666055 100644 --- a/themes/V3/Blank/snippets.js +++ b/themes/V3/Blank/snippets.js @@ -111,6 +111,21 @@ module.exports = [ icon : 'fas fa-code', gen : '' }, + { + name : 'Homebrewery Credit', + icon : 'fas fa-dice-d20', + gen : function(){ + return dedent` + {{homebreweryCredits + Made With + + {{homebreweryIcon}} + + The Homebrewery + [Homebrewery.Naturalcrit.com](https://homebrewery.naturalcrit.com) + }}\n\n`; + }, + } ] }, { @@ -289,6 +304,99 @@ module.exports = [ } ] }, + /**************** FONTS *************/ + { + groupName : 'Fonts', + icon : 'fas fa-keyboard', + view : 'text', + snippets : [ + { + name : 'Open Sans', + icon : 'font OpenSans', + gen : dedent`{{font-family:OpenSans Dummy Text}}` + }, + { + name : 'Code Bold', + icon : 'font CodeBold', + gen : dedent`{{font-family:CodeBold Dummy Text}}` + }, + { + name : 'Code Light', + icon : 'font CodeLight', + gen : dedent`{{font-family:CodeLight Dummy Text}}` + }, + { + name : 'Scaly Sans Remake', + icon : 'font ScalySansRemake', + gen : dedent`{{font-family:ScalySansRemake Dummy Text}}` + }, + { + name : 'Book Insanity Remake', + icon : 'font BookInsanityRemake', + gen : dedent`{{font-family:BookInsanityRemake Dummy Text}}` + }, + { + name : 'Mr Eaves Remake', + icon : 'font MrEavesRemake', + gen : dedent`{{font-family:MrEavesRemake Dummy Text}}` + }, + { + name: 'Solbera Imitation Remake', + icon: 'font SolberaImitationRemake', + gen: dedent`{{font-family:SolberaImitationRemake Dummy Text}}` + }, + { + name: 'Scaly Sans Small Caps Remake', + icon: 'font ScalySansSmallCapsRemake', + gen: dedent`{{font-family:ScalySansSmallCapsRemake Dummy Text}}` + }, + { + name: 'Walter Turncoat', + icon: 'font WalterTurncoat', + gen: dedent`{{font-family:WalterTurncoat Dummy Text}}` + }, + { + name: 'Lato', + icon: 'font Lato', + gen: dedent`{{font-family:Lato Dummy Text}}` + }, + { + name: 'Courier', + icon: 'font Courier', + gen: dedent`{{font-family:Courier Dummy Text}}` + }, + { + name: 'Nodesto Caps Condensed', + icon: 'font NodestoCapsCondensed', + gen: dedent`{{font-family:NodestoCapsCondensed Dummy Text}}` + }, + { + name: 'Overpass', + icon: 'font Overpass', + gen: dedent`{{font-family:Overpass Dummy Text}}` + }, + { + name: 'Davek', + icon: 'font Davek', + gen: dedent`{{font-family:Davek Dummy Text}}` + }, + { + name: 'Iokharic', + icon: 'font Iokharic', + gen: dedent`{{font-family:Iokharic Dummy Text}}` + }, + { + name: 'Rellanic', + icon: 'font Rellanic', + gen: dedent`{{font-family:Rellanic Dummy Text}}` + }, + { + name: 'Times New Roman', + icon: 'font TimesNewRoman', + gen: dedent`{{font-family:"Times New Roman" Dummy Text}}` + } + ] + }, /**************** PAGE *************/ diff --git a/themes/V3/Blank/style.less b/themes/V3/Blank/style.less index f233a2347..d31919fab 100644 --- a/themes/V3/Blank/style.less +++ b/themes/V3/Blank/style.less @@ -7,13 +7,9 @@ --HB_Color_WatercolorStain : #000000; // Black } -@page { margin: 0; } -body { - counter-reset : phb-page-numbers; -} -*{ - -webkit-print-color-adjust : exact; -} +@page { margin : 0; } +body { counter-reset : phb-page-numbers; } +* { -webkit-print-color-adjust : exact; } //***************************** // * MUSTACHE DIVS/SPANS @@ -23,9 +19,7 @@ body { break-inside : avoid; display : inline-block; width : 100%; - img { - z-index : 0; - } + img { z-index : 0; } } .inline-block { display : inline-block; @@ -33,99 +27,81 @@ body { } } -.useColumns(@multiplier : 1, @fillMode: auto){ +.useColumns(@multiplier : 1, @fillMode: auto) { column-fill : @fillMode; column-count : 2; } -.columnWrapper{ +.columnWrapper { + column-gap : inherit; max-height : 100%; column-span : all; columns : inherit; - column-gap : inherit; column-fill : inherit; } -.page{ +.page { .useColumns(); - height : 279.4mm; - width : 215.9mm; - padding : 1.4cm 1.9cm 1.7cm; - counter-increment : phb-page-numbers; - background-color : var(--HB_Color_Background); position : relative; z-index : 15; box-sizing : border-box; + width : 215.9mm; + height : 279.4mm; + padding : 1.4cm 1.9cm 1.7cm; overflow : hidden; + counter-increment : phb-page-numbers; + background-color : var(--HB_Color_Background); text-rendering : optimizeLegibility; - page-break-before : always; - page-break-after : always; contain : size; } - //***************************** - // * BASE +//***************************** +// * BASE // *****************************/ -.page{ - p{ - overflow-wrap : break-word; +.page { + p { display : block; + overflow-wrap : break-word; } - strong{ - font-weight : bold; - } - em{ - font-style : italic; - } - sup{ + strong { font-weight : bold; } + em { font-style : italic; } + sup { + font-size : smaller; + line-height : 0; vertical-align : super; - font-size : smaller; - line-height : 0; } - sub{ - vertical-align : sub; + sub { font-size : smaller; line-height : 0; + vertical-align : sub; } ul { + padding-left : 1.4em; list-style-position : outside; //Needed for multiline list items list-style-type : disc; - padding-left : 1.4em; } ol { + padding-left : 1.4em; list-style-position : outside; list-style-type : decimal; - padding-left : 1.4em; - } - img{ - z-index : -1; } + img { z-index : -1; } //***************************** // * HEADERS // *****************************/ - h1,h2,h3,h4,h5,h6{ + h1,h2,h3,h4,h5,h6 { font-weight : bold; line-height : 1.2em; } - h1{ - font-size : 2em; - } - h2{ - font-size : 1.5em; - } - h3{ - font-size : 1.17em; - } - h4{ - font-size : 1em; - } - h5{ - font-size : 0.83em; - } + h1 { font-size : 2em; } + h2 { font-size : 1.5em; } + h3 { font-size : 1.17em; } + h4 { font-size : 1em; } + h5 { font-size : 0.83em; } //***************************** // * TABLE // *****************************/ - table{ + table { width : 100%; - thead{ + thead { display : table-row-group; font-weight : bold; } @@ -137,42 +113,40 @@ body { //************************************ // * CODE BLOCKS // ************************************/ - code{ - font-family : "Courier New", Courier, monospace; - white-space : pre-wrap; + code { + font-family : 'Courier New', "Courier", monospace; overflow-wrap : break-word; + white-space : pre-wrap; } - pre code{ - width : 100%; + pre code { display : inline-block; + width : 100%; } //***************************** // * EXTRAS // *****************************/ .columnSplit { + margin-top : 0; visibility : hidden; -webkit-column-break-after : always; break-after : always; -moz-column-break-after : always; - margin-top : 0; - & + * { - margin-top : 0; - } + & + * { margin-top : 0; } } //Avoid breaking up - blockquote,table{ + blockquote,table { z-index : 15; -webkit-column-break-inside : avoid; page-break-inside : avoid; break-inside : avoid; } // Nested lists - ul ul,ol ol,ul ol,ol ul{ + ul ul,ol ol,ul ol,ol ul { margin-bottom : 0px; margin-left : 1.5em; } - li{ + li { -webkit-column-break-inside : avoid; page-break-inside : avoid; break-inside : avoid; @@ -180,69 +154,66 @@ body { /* Watermark */ .watermark { - display : grid !important; - place-items : center; - justify-content : center; position : absolute; - margin : 0; top : 0; left : 0; + z-index : 500; + display : grid !important; + place-items : center; + justify-content : center; width : 100%; height : 100%; + margin : 0; font-size : 120px; - text-transform : uppercase; + text-transform : uppercase; mix-blend-mode : overlay; opacity : 30%; transform : rotate(-45deg); - z-index : 500; - p { - margin-bottom : none; - } + p { margin-bottom : none; } } /* Watercolor */ - [class*="watercolor"] { + [class*='watercolor'] { position : absolute; + z-index : -2; width : 2000px; /* dimensions need to be real big so the user can set */ height : 2000px; /* height or width and the image will maintain aspect ratio */ + background-color : var(--HB_Color_WatercolorStain); /* default color */ + background-size : cover; -webkit-mask-image : var(--wc); -webkit-mask-size : contain; -webkit-mask-repeat : no-repeat; mask-image : var(--wc); mask-size : contain; mask-repeat : no-repeat; - background-size : cover; - background-color : var(--HB_Color_WatercolorStain); /*default color*/ - --wc : @watercolor1; /*default image*/ - z-index : -2; + --wc : @watercolor1; /* default image */ } - .watercolor1 { --wc : @watercolor1; } - .watercolor2 { --wc : @watercolor2; } - .watercolor3 { --wc : @watercolor3; } - .watercolor4 { --wc : @watercolor4; } - .watercolor5 { --wc : @watercolor5; } - .watercolor6 { --wc : @watercolor6; } - .watercolor7 { --wc : @watercolor7; } - .watercolor8 { --wc : @watercolor8; } - .watercolor9 { --wc : @watercolor9; } + .watercolor1 { --wc : @watercolor1; } + .watercolor2 { --wc : @watercolor2; } + .watercolor3 { --wc : @watercolor3; } + .watercolor4 { --wc : @watercolor4; } + .watercolor5 { --wc : @watercolor5; } + .watercolor6 { --wc : @watercolor6; } + .watercolor7 { --wc : @watercolor7; } + .watercolor8 { --wc : @watercolor8; } + .watercolor9 { --wc : @watercolor9; } .watercolor10 { --wc : @watercolor10; } .watercolor11 { --wc : @watercolor11; } .watercolor12 { --wc : @watercolor12; } /* Image Masks */ - [class*="imageMask"] { + [class*='imageMask'] { position : absolute; - height : 200%; - width : 200%; - left : 50%; bottom : 50%; - --rotation : 0; - --revealer : none; - --checkerboard : none; - --scaleX : 1; - --scaleY : 1; + left : 50%; + z-index : -1; + width : 200%; + height : 200%; + background-image : var(--checkerboard); + background-size : 20px; + transform : translateY(50%) translateX(-50%) rotate(calc(1deg * var(--rotation))) scaleX(var(--scaleX)) scaleY(var(--scaleY)); -webkit-mask-image : var(--wc), var(--revealer); -webkit-mask-repeat : repeat-x; -webkit-mask-size : 50%; //Scale only X to fit page width, leave height at aspect ratio, designed to hang off the edge @@ -251,61 +222,63 @@ body { mask-repeat : repeat-x; mask-size : 50%; mask-position : 50% calc(50% - var(--offset)); - background-image : var(--checkerboard); - background-size : 20px; - z-index : -1; - transform : translateY(50%) translateX(-50%) rotate(calc(1deg * var(--rotation))) scaleX(var(--scaleX)) scaleY(var(--scaleY)); + --rotation : 0; + --revealer : none; + --checkerboard : none; + --scaleX : 1; + --scaleY : 1; & > p:has(img) { position : absolute; - width : 50%; - height : 50%; bottom : 50%; left : 50%; + width : 50%; + height : 50%; transform : translateX(-50%) translateY(50%) rotate(calc(-1deg * var(--rotation))) scaleX(calc(1 / var(--scaleX))) scaleY(calc(1 / var(--scaleY))); } & img { position : absolute; - display : block; bottom : 0; + display : block; } &.bottom { --rotation : 0; - & img {bottom: 0;} + & img {bottom : 0;} } &.top { --rotation : 180; - & img {top: 0;} + & img {top : 0;} } &.left { --rotation : 90; - & img {left: 0;} + & img {left : 0;} } &.right { --rotation : -90; - & img {right: 0;} + & img {right : 0;} } &.revealImage { - --revealer : linear-gradient(0deg, rgba(0,0,0,.2) 0%, rgba(0,0,0,0.2)); - --checkerboard : url(/assets/waterColorMasks/missingImage.png); //shows any masked regions not filled by image + --revealer : linear-gradient(0deg, rgba(0,0,0,0.2) 0%, rgba(0,0,0,0.2)); + --checkerboard : url("/assets/waterColorMasks/missingImage.png"); //shows any masked regions not filled by image } } .imageMaskEdge { - &1 { --wc : url(/assets/waterColorMasks/edge/0001.webp); } - &2 { --wc : url(/assets/waterColorMasks/edge/0002.webp); } - &3 { --wc : url(/assets/waterColorMasks/edge/0003.webp); } - &4 { --wc : url(/assets/waterColorMasks/edge/0004.webp); } - &5 { --wc : url(/assets/waterColorMasks/edge/0005.webp); } - &6 { --wc : url(/assets/waterColorMasks/edge/0006.webp); } - &7 { --wc : url(/assets/waterColorMasks/edge/0007.webp); } - &8 { --wc : url(/assets/waterColorMasks/edge/0008.webp); } + &1 { --wc : url("/assets/waterColorMasks/edge/0001.webp"); } + &2 { --wc : url("/assets/waterColorMasks/edge/0002.webp"); } + &3 { --wc : url("/assets/waterColorMasks/edge/0003.webp"); } + &4 { --wc : url("/assets/waterColorMasks/edge/0004.webp"); } + &5 { --wc : url("/assets/waterColorMasks/edge/0005.webp"); } + &6 { --wc : url("/assets/waterColorMasks/edge/0006.webp"); } + &7 { --wc : url("/assets/waterColorMasks/edge/0007.webp"); } + &8 { --wc : url("/assets/waterColorMasks/edge/0008.webp"); } } - [class*="imageMaskCenter"] { + [class*='imageMaskCenter'] { + bottom : calc(var(--offsetY)); + left : calc(var(--offsetX)); width : 100%; height : 100%; - left : calc(var(--offsetX)); - bottom : calc(var(--offsetY)); + transform : rotate(calc(1deg * var(--rotation))) scaleX(var(--scaleX)) scaleY(var(--scaleY)); -webkit-mask-image : var(--wc), var(--revealer); -webkit-mask-repeat : no-repeat; -webkit-mask-size : 100% 100%; //Scale both dimensions to fit page size @@ -314,48 +287,48 @@ body { mask-repeat : no-repeat; mask-size : 100% 100%; //Scale both dimensions to fit page size mask-position : 50% 50%; - transform : rotate(calc(1deg * var(--rotation))) scaleX(var(--scaleX)) scaleY(var(--scaleY)); & > p:has(img) { position : absolute; - width : 100%; - height : 100%; bottom : 0; left : 0; + width : 100%; + height : 100%; transform : unset; transform : scaleX(calc(1 / var(--scaleX))) scaleY(calc(1 / var(--scaleY))) - rotate(calc(-1deg * var(--rotation))) - translateX(calc(-1 * var(--offsetX))) - translateY(calc(1 * var(--offsetY))); + rotate(calc(-1deg * var(--rotation))) + translateX(calc(-1 * var(--offsetX))) + translateY(calc(1 * var(--offsetY))); } } .imageMaskCenter { - &1 { --wc : url(/assets/waterColorMasks/center/0001.webp); } - &2 { --wc : url(/assets/waterColorMasks/center/0002.webp); } - &3 { --wc : url(/assets/waterColorMasks/center/0003.webp); } - &4 { --wc : url(/assets/waterColorMasks/center/0004.webp); } - &5 { --wc : url(/assets/waterColorMasks/center/0005.webp); } - &6 { --wc : url(/assets/waterColorMasks/center/0006.webp); } - &7 { --wc : url(/assets/waterColorMasks/center/0007.webp); } - &8 { --wc : url(/assets/waterColorMasks/center/0008.webp); } - &9 { --wc : url(/assets/waterColorMasks/center/0009.webp); } - &10 { --wc : url(/assets/waterColorMasks/center/0010.webp); } - &11 { --wc : url(/assets/waterColorMasks/center/0011.webp); } - &12 { --wc : url(/assets/waterColorMasks/center/0012.webp); } - &13 { --wc : url(/assets/waterColorMasks/center/0013.webp); } - &14 { --wc : url(/assets/waterColorMasks/center/0014.webp); } - &15 { --wc : url(/assets/waterColorMasks/center/0015.webp); } - &16 { --wc : url(/assets/waterColorMasks/center/0016.webp); } - &special { --wc : url(/assets/waterColorMasks/center/special.webp); } + &1 { --wc : url("/assets/waterColorMasks/center/0001.webp"); } + &2 { --wc : url("/assets/waterColorMasks/center/0002.webp"); } + &3 { --wc : url("/assets/waterColorMasks/center/0003.webp"); } + &4 { --wc : url("/assets/waterColorMasks/center/0004.webp"); } + &5 { --wc : url("/assets/waterColorMasks/center/0005.webp"); } + &6 { --wc : url("/assets/waterColorMasks/center/0006.webp"); } + &7 { --wc : url("/assets/waterColorMasks/center/0007.webp"); } + &8 { --wc : url("/assets/waterColorMasks/center/0008.webp"); } + &9 { --wc : url("/assets/waterColorMasks/center/0009.webp"); } + &10 { --wc : url("/assets/waterColorMasks/center/0010.webp"); } + &11 { --wc : url("/assets/waterColorMasks/center/0011.webp"); } + &12 { --wc : url("/assets/waterColorMasks/center/0012.webp"); } + &13 { --wc : url("/assets/waterColorMasks/center/0013.webp"); } + &14 { --wc : url("/assets/waterColorMasks/center/0014.webp"); } + &15 { --wc : url("/assets/waterColorMasks/center/0015.webp"); } + &16 { --wc : url("/assets/waterColorMasks/center/0016.webp"); } + &special { --wc : url("/assets/waterColorMasks/center/special.webp"); } } - [class*="imageMaskCorner"] { - height : 200%; - width : 200%; - left : calc(-50% + var(--offsetX)); + [class*='imageMaskCorner'] { bottom : calc(-50% + var(--offsetY)); + left : calc(-50% + var(--offsetX)); + width : 200%; + height : 200%; + transform : rotate(calc(1deg * var(--rotation))) scaleX(var(--scaleX)) scaleY(var(--scaleY)); -webkit-mask-image : var(--wc), var(--revealer); -webkit-mask-repeat : no-repeat; -webkit-mask-size : 100% 100%; //Scale both dimensions to fit page size @@ -364,56 +337,55 @@ body { mask-repeat : no-repeat; mask-size : 100% 100%; //Scale both dimensions to fit page size mask-position : 50% 50%; - transform : rotate(calc(1deg * var(--rotation))) scaleX(var(--scaleX)) scaleY(var(--scaleY)); & > p:has(img) { + bottom : 25%; + left : 25%; width : 50%; height : 50%; //Complex transform below to handle mix of % and cm offsets - left : 25%; - bottom : 25%; transform : scaleX(calc(1 / var(--scaleX))) scaleY(calc(1 / var(--scaleY))) - rotate(calc(-1deg * var(--rotation))) - translateX(calc(-1 * var(--offsetX))) - translateY(calc(1 * var(--offsetY))); + rotate(calc(-1deg * var(--rotation))) + translateX(calc(-1 * var(--offsetX))) + translateY(calc(1 * var(--offsetY))); } } .imageMaskCorner { - &1 { --wc : url(/assets/waterColorMasks/corner/0001.webp); } - &2 { --wc : url(/assets/waterColorMasks/corner/0002.webp); } - &3 { --wc : url(/assets/waterColorMasks/corner/0003.webp); } - &4 { --wc : url(/assets/waterColorMasks/corner/0004.webp); } - &5 { --wc : url(/assets/waterColorMasks/corner/0005.webp); } - &6 { --wc : url(/assets/waterColorMasks/corner/0006.webp); } - &7 { --wc : url(/assets/waterColorMasks/corner/0007.webp); } - &8 { --wc : url(/assets/waterColorMasks/corner/0008.webp); } - &9 { --wc : url(/assets/waterColorMasks/corner/0009.webp); } - &10 { --wc : url(/assets/waterColorMasks/corner/0010.webp); } - &11 { --wc : url(/assets/waterColorMasks/corner/0011.webp); } - &12 { --wc : url(/assets/waterColorMasks/corner/0012.webp); } - &13 { --wc : url(/assets/waterColorMasks/corner/0013.webp); } - &14 { --wc : url(/assets/waterColorMasks/corner/0014.webp); } - &15 { --wc : url(/assets/waterColorMasks/corner/0015.webp); } - &16 { --wc : url(/assets/waterColorMasks/corner/0016.webp); } - &17 { --wc : url(/assets/waterColorMasks/corner/0017.webp); } - &18 { --wc : url(/assets/waterColorMasks/corner/0018.webp); } - &19 { --wc : url(/assets/waterColorMasks/corner/0019.webp); } - &20 { --wc : url(/assets/waterColorMasks/corner/0020.webp); } - &21 { --wc : url(/assets/waterColorMasks/corner/0021.webp); } - &22 { --wc : url(/assets/waterColorMasks/corner/0022.webp); } - &23 { --wc : url(/assets/waterColorMasks/corner/0023.webp); } - &24 { --wc : url(/assets/waterColorMasks/corner/0024.webp); } - &25 { --wc : url(/assets/waterColorMasks/corner/0025.webp); } - &26 { --wc : url(/assets/waterColorMasks/corner/0026.webp); } - &27 { --wc : url(/assets/waterColorMasks/corner/0027.webp); } - &28 { --wc : url(/assets/waterColorMasks/corner/0028.webp); } - &29 { --wc : url(/assets/waterColorMasks/corner/0029.webp); } - &30 { --wc : url(/assets/waterColorMasks/corner/0030.webp); } - &31 { --wc : url(/assets/waterColorMasks/corner/0031.webp); } - &32 { --wc : url(/assets/waterColorMasks/corner/0032.webp); } - &33 { --wc : url(/assets/waterColorMasks/corner/0033.webp); } - &34 { --wc : url(/assets/waterColorMasks/corner/0034.webp); } - &35 { --wc : url(/assets/waterColorMasks/corner/0035.webp); } - &36 { --wc : url(/assets/waterColorMasks/corner/0036.webp); } - &37 { --wc : url(/assets/waterColorMasks/corner/0037.webp); } + &1 { --wc : url("/assets/waterColorMasks/corner/0001.webp"); } + &2 { --wc : url("/assets/waterColorMasks/corner/0002.webp"); } + &3 { --wc : url("/assets/waterColorMasks/corner/0003.webp"); } + &4 { --wc : url("/assets/waterColorMasks/corner/0004.webp"); } + &5 { --wc : url("/assets/waterColorMasks/corner/0005.webp"); } + &6 { --wc : url("/assets/waterColorMasks/corner/0006.webp"); } + &7 { --wc : url("/assets/waterColorMasks/corner/0007.webp"); } + &8 { --wc : url("/assets/waterColorMasks/corner/0008.webp"); } + &9 { --wc : url("/assets/waterColorMasks/corner/0009.webp"); } + &10 { --wc : url("/assets/waterColorMasks/corner/0010.webp"); } + &11 { --wc : url("/assets/waterColorMasks/corner/0011.webp"); } + &12 { --wc : url("/assets/waterColorMasks/corner/0012.webp"); } + &13 { --wc : url("/assets/waterColorMasks/corner/0013.webp"); } + &14 { --wc : url("/assets/waterColorMasks/corner/0014.webp"); } + &15 { --wc : url("/assets/waterColorMasks/corner/0015.webp"); } + &16 { --wc : url("/assets/waterColorMasks/corner/0016.webp"); } + &17 { --wc : url("/assets/waterColorMasks/corner/0017.webp"); } + &18 { --wc : url("/assets/waterColorMasks/corner/0018.webp"); } + &19 { --wc : url("/assets/waterColorMasks/corner/0019.webp"); } + &20 { --wc : url("/assets/waterColorMasks/corner/0020.webp"); } + &21 { --wc : url("/assets/waterColorMasks/corner/0021.webp"); } + &22 { --wc : url("/assets/waterColorMasks/corner/0022.webp"); } + &23 { --wc : url("/assets/waterColorMasks/corner/0023.webp"); } + &24 { --wc : url("/assets/waterColorMasks/corner/0024.webp"); } + &25 { --wc : url("/assets/waterColorMasks/corner/0025.webp"); } + &26 { --wc : url("/assets/waterColorMasks/corner/0026.webp"); } + &27 { --wc : url("/assets/waterColorMasks/corner/0027.webp"); } + &28 { --wc : url("/assets/waterColorMasks/corner/0028.webp"); } + &29 { --wc : url("/assets/waterColorMasks/corner/0029.webp"); } + &30 { --wc : url("/assets/waterColorMasks/corner/0030.webp"); } + &31 { --wc : url("/assets/waterColorMasks/corner/0031.webp"); } + &32 { --wc : url("/assets/waterColorMasks/corner/0032.webp"); } + &33 { --wc : url("/assets/waterColorMasks/corner/0033.webp"); } + &34 { --wc : url("/assets/waterColorMasks/corner/0034.webp"); } + &35 { --wc : url("/assets/waterColorMasks/corner/0035.webp"); } + &36 { --wc : url("/assets/waterColorMasks/corner/0036.webp"); } + &37 { --wc : url("/assets/waterColorMasks/corner/0037.webp"); } } } @@ -425,16 +397,16 @@ body { padding-left : 1em; white-space : pre-line; } - dt { - display : inline; - margin-right : 0.5ch; + dt { + display : inline; + margin-right : 0.5ch; margin-left : -1em; - } - dd { + } + dd { display : inline; margin-left : 0; text-indent : 0; - } + } } //***************************** @@ -444,9 +416,7 @@ body { .blank { height : 1em; margin-top : 0; - & + * { - margin-top : 0; - } + & + * { margin-top : 0; } } } @@ -454,12 +424,39 @@ body { // * WIDE // *****************************/ .page { - .wide{ + .wide { column-span : all; display : block; margin-bottom : 1em; - &+* { - margin-top : 0; - } + & + * { margin-top : 0; } } } + +//***************************** +//* CREDITS +//*****************************/ +.page .homebreweryCredits { + p { + font-family : 'NodestoCapsWide'; + font-size : 0.4cm; + line-height : 1em; + text-align : center; + text-indent : 0; + letter-spacing : 0.08em; + } + a { + color : inherit; + text-decoration : none; + &:hover { text-decoration : underline; } + } + .homebreweryIcon { + display : block; + height : 1.5cm; + margin : 0 auto; + background-color : black; + -webkit-mask : url("/assets/naturalCritLogoWhite.svg") center / contain no-repeat; + mask : url("/assets/naturalCritLogoWhite.svg") center / contain no-repeat; + } + .homebreweryIcon.red { background-color : red; } + .homebreweryIcon.gold { background-image : linear-gradient(to top left, brown 22.5%, gold 40%, white 60%, gold 67.5%, brown 82.5%); } +} diff --git a/themes/codeMirror/customThemes/darkbrewery-v301.css b/themes/codeMirror/customThemes/darkbrewery-v301.css new file mode 100644 index 000000000..267c377f6 --- /dev/null +++ b/themes/codeMirror/customThemes/darkbrewery-v301.css @@ -0,0 +1,129 @@ +/* Main BG color and normal text color */ +.CodeMirror { + background: #293134; + color: #91A6AA; +} + +/* Brew BG */ +.brewRenderer { + background-color: #293134; +} +/* Blinking cursor */ +.CodeMirror-cursor { + border-left: 1px solid #e0e2e4; +} + +/* HB DARK NAV START*/ + +/* Bars at the top */ +.snippetBar { + background-color: #2F393C; + color: white; +} +nav { + background-color: #293134; +} +nav .navItem { + background-color: #293134; +} +/* Fix for Homebrewery custom Snippet icons */ +.snippetBar .fac { + filter: invert(1); +} +.snippetBar .snippetGroup .dropdown { + background-color: #2F393C; +} +/* HB DARK NAV END */ + +/* Line number stuff */ +.CodeMirror-gutter-elt { + color: #81969A; +} +.CodeMirror-linenumber { + background-color: #293134; +} +.CodeMirror-gutter { + background-color: #293134; +} +/* column splits */ +.editor .codeEditor .columnSplit { + font-style: italic; + color: inherit; + background-color:#1f5763; + border-bottom: #299 solid 1px; +} + +/* Colors for headings and such */ +/* ###Headings */ +.cm-s-default .cm-header { + color: #c51b1b; + -webkit-text-stroke-width: 0.1px; + -webkit-text-stroke-color: #000; +} +/* bold points */ +.cm-header, .cm-strong { + font-weight: bold; + color: #309dd2; +} +/* Link headings */ +.cm-s-default .cm-link { + color: #dd6300; +} +/* links */ +.cm-s-default .cm-string { + color: #aa8261; +} +/*@import*/ +.cm-s-default .cm-def { + color:#2986cc; +} +/* Bullets and such */ +.cm-s-default .cm-variable-2 { + color: #3cbf30; +} +/* blocks */ +.editor .codeEditor .block:not(.cm-comment) { + color: #e3e3e3; +} +/* inline blocks */ +.editor .codeEditor .inline-block { + color: #e3e3e3; +} +/* Tags (divs) */ +.cm-s-default .cm-tag { + color: #e3ff00; +} +.cm-s-default .cm-attribute { + color: #e3ff00; +} +.cm-s-default .cm-atom { + color:#000; +} +.cm-s-default .cm-qualifier{ + color:#ee1919; +} +.cm-s-default .cm-comment{ + color:#bbc700; +} +.cm-s-default .cm-keyword { + color:#c302df; + background-color:#b1b1b1; +} +.cm-s-default .cm-property.cm-error { + color:#c50202; +} + +.CodeMirror-foldmarker { + color:#f0ff00; +} + +/* New page */ +.editor .codeEditor .pageLine { + background: #000; + color:#000; + border-bottom: 1px solid #fff; +} + +.cm-s-default .cm-builtin { + color:#fff; +} \ No newline at end of file diff --git a/themes/codeMirror/editorThemes.json b/themes/codeMirror/editorThemes.json index a4dd74470..384ce4602 100644 --- a/themes/codeMirror/editorThemes.json +++ b/themes/codeMirror/editorThemes.json @@ -15,6 +15,7 @@ "cobalt", "colorforth", "darcula", +"darkbrewery-v301", "dracula", "duotone-dark", "duotone-light", diff --git a/themes/fonts/icon fonts/Elderberry-Inn-Icons.woff2 b/themes/fonts/icon fonts/Elderberry-Inn-Icons.woff2 new file mode 100644 index 000000000..030deb92a Binary files /dev/null and b/themes/fonts/icon fonts/Elderberry-Inn-Icons.woff2 differ diff --git a/themes/fonts/icon fonts/font-icons.less b/themes/fonts/icon fonts/font-icons.less new file mode 100644 index 000000000..f8eb19f11 --- /dev/null +++ b/themes/fonts/icon fonts/font-icons.less @@ -0,0 +1,224 @@ +/* Main Font, serif */ +@font-face { + font-family : 'Eldeberry-Inn'; + font-style : normal; + font-weight : normal; + src : url('../../../fonts/icon fonts/Elderberry-Inn-Icons.woff2'); +} + +.page { + span.ei { + display : inline-block; + margin-right : 3px; + font-family : 'Eldeberry-Inn'; + line-height : 1; + vertical-align : baseline; + -moz-osx-font-smoothing : grayscale; + -webkit-font-smoothing : antialiased; + text-rendering : auto; + + &.book::before { content : '\E900'; } + &.screen::before { content : '\E901'; } + + /* Spell levels */ + &.spell-0::before { content : '\E902'; } + &.spell-1::before { content : '\E903'; } + &.spell-2::before { content : '\E904'; } + &.spell-3::before { content : '\E905'; } + &.spell-4::before { content : '\E906'; } + &.spell-5::before { content : '\E907'; } + &.spell-6::before { content : '\E908'; } + &.spell-7::before { content : '\E909'; } + &.spell-8::before { content : '\E90A'; } + &.spell-9::before { content : '\E90B'; } + + /* Damage types */ + &.acid::before { content : '\E90C'; } + &.bludgeoning::before { content : '\E90D'; } + &.cold::before { content : '\E90E'; } + &.fire::before { content : '\E90F'; } + &.force::before { content : '\E910'; } + &.lightning::before { content : '\E911'; } + &.necrotic::before { content : '\E912'; } + &.piercing::before { content : '\E914'; } + &.poison::before { content : '\E913'; } + &.psychic::before { content : '\E915'; } + &.radiant::before { content : '\E916'; } + &.slashing::before { content : '\E917'; } + &.thunder::before { content : '\E918'; } + + /* DnD Conditions */ + &.blinded::before { content : '\E919'; } + &.charmed::before { content : '\E91A'; } + &.deafened::before { content : '\E91B'; } + &.exhaust-1::before { content : '\E91C'; } + &.exhaust-2::before { content : '\E91D'; } + &.exhaust-3::before { content : '\E91E'; } + &.exhaust-4::before { content : '\E91F'; } + &.exhaust-5::before { content : '\E920'; } + &.exhaust-6::before { content : '\E921'; } + &.frightened::before { content : '\E922'; } + &.grappled::before { content : '\E923'; } + &.incapacitated::before { content : '\E924'; } + &.invisible::before { content : '\E926'; } + &.paralyzed::before { content : '\E927'; } + &.petrified::before { content : '\E928'; } + &.poisoned::before { content : '\E929'; } + &.prone::before { content : '\E92A'; } + &.restrained::before { content : '\E92B'; } + &.stunned::before { content : '\E92C'; } + &.unconscious::before { content : '\E925'; } + + /* Character Classes and Features */ + &.barbarian-rage::before { content : '\E92D'; } + &.barbarian-reckless-attack::before { content : '\E92E'; } + &.bardic-inspiration::before { content : '\E92F'; } + &.cleric-channel-divinity::before { content : '\E930'; } + &.druid-wild-shape::before { content : '\E931'; } + &.fighter-action-surge::before { content : '\E932'; } + &.fighter-second-wind::before { content : '\E933'; } + &.monk-flurry-blows::before { content : '\E934'; } + &.monk-patient-defense::before { content : '\E935'; } + &.monk-step-of-the-wind::before { content : '\E936'; } + &.monk-step-of-the-wind-2::before { content : '\E937'; } + &.monk-step-of-the-wind-3::before { content : '\E938'; } + &.monk-stunning-strike::before { content : '\E939'; } + &.monk-stunning-strike-2::before { content : '\E939'; } + &.paladin-divine-smite::before { content : '\E93B'; } + &.paladin-lay-on-hands::before { content : '\E93C'; } + &.barbarian-abilities::before { content : '\E93D'; } + &.barbarian::before { content : '\E93E'; } + &.bard-abilities::before { content : '\E93F'; } + &.bard::before { content : '\E940'; } + &.cleric-abilities::before { content : '\E941'; } + &.cleric::before { content : '\E942'; } + &.druid-abilities::before { content : '\E943'; } + &.druid::before { content : '\E944'; } + &.fighter-abilities::before { content : '\E945'; } + &.fighter::before { content : '\E946'; } + &.monk-abilities::before { content : '\E947'; } + &.monk::before { content : '\E948'; } + &.paladin-abilities::before { content : '\E949'; } + &.paladin::before { content : '\E94A'; } + &.ranger-abilities::before { content : '\E94B'; } + &.ranger::before { content : '\E94C'; } + &.rogue-abilities::before { content : '\E94D'; } + &.rogue::before { content : '\E94E'; } + &.sorcerer-abilities::before { content : '\E94F'; } + &.sorcerer::before { content : '\E950'; } + &.warlock-abilities::before { content : '\E951'; } + &.warlock::before { content : '\E952'; } + &.wizard-abilities::before { content : '\E953'; } + &.wizard::before { content : '\E954'; } + + /* Types of actions */ + &.movement::before { content : '\E955'; } + &.action::before { content : '\E956'; } + &.bonus-action::before { content : '\E957'; } + &.reaction::before { content : '\E958'; } + + /* SRD Spells */ + &.acid-arrow::before { content : '\E959'; } + &.action-1::before { content : '\E95A'; } + &.alter-self::before { content : '\E95B'; } + &.alter-self-2::before { content : '\E95C'; } + &.animal-friendship::before { content : '\E95E'; } + &.animate-dead::before { content : '\E95F'; } + &.animate-objects::before { content : '\E960'; } + &.animate-objects-2::before { content : '\E961'; } + &.bane::before { content : '\E962'; } + &.bless::before { content : '\E963'; } + &.blur::before { content : '\E964'; } + &.bonus::before { content : '\E965'; } + &.branding-smite::before { content : '\E966'; } + &.burning-hands::before { content : '\E967'; } + &.charm-person::before { content : '\E968'; } + &.chill-touch::before { content : '\E969'; } + &.cloudkill::before { content : '\E96A'; } + &.comprehend-languages::before { content : '\E96B'; } + &.cone-of-cold::before { content : '\E96C'; } + &.conjure-elemental::before { content : '\E96D'; } + &.conjure-minor-elemental::before { content : '\E96E'; } + &.control-water::before { content : '\E96F'; } + &.counterspell::before { content : '\E970'; } + &.cure-wounds::before { content : '\E971'; } + &.dancing-lights::before { content : '\E972'; } + &.darkness::before { content : '\E973'; } + &.detect-magic::before { content : '\E974'; } + &.disguise-self::before { content : '\E975'; } + &.disintegrate::before { content : '\E976'; } + &.dispel-evil-and-good::before { content : '\E977'; } + &.dispel-magic::before { content : '\E978'; } + &.dominate-monster::before { content : '\E979'; } + &.dominate-person::before { content : '\E97A'; } + &.eldritch-blast::before { content : '\E97B'; } + &.enlarge-reduce::before { content : '\E97C'; } + &.entangle::before { content : '\E97D'; } + &.faerie-fire::before { content : '\E97E'; } + &.faerie-fire2::before { content : '\E97F'; } + &.feather-fall::before { content : '\E980'; } + &.find-familiar::before { content : '\E981'; } + &.finger-of-death::before { content : '\E982'; } + &.fireball::before { content : '\E983'; } + &.floating-disk::before { content : '\E984'; } + &.fly::before { content : '\E985'; } + &.fog-cloud::before { content : '\E986'; } + &.gaseous-form::before { content : '\E987'; } + &.gaseous-form2::before { content : '\E988'; } + &.gentle-repose::before { content : '\E989'; } + &.gentle-repose2::before { content : '\E98A'; } + &.globe-of-invulnerability::before { content : '\E98B'; } + &.guiding-bolt::before { content : '\E98C'; } + &.healing-word::before { content : '\E98D'; } + &.heat-metal::before { content : '\E98E'; } + &.hellish-rebuke::before { content : '\E98F'; } + &.heroes-feast::before { content : '\E990'; } + &.heroism::before { content : '\E991'; } + &.hideous-laughter::before { content : '\E992'; } + &.identify::before { content : '\E993'; } + &.illusory-script::before { content : '\E994'; } + &.inflict-wounds::before { content : '\E995'; } + &.light::before { content : '\E996'; } + &.longstrider::before { content : '\E997'; } + &.mage-armor::before { content : '\E998'; } + &.mage-hand::before { content : '\E999'; } + &.magic-missile::before { content : '\E99A'; } + &.mass-cure-wounds::before { content : '\E99B'; } + &.mass-healing-word::before { content : '\E99C'; } + &.Mending::before { content : '\E99D'; } + &.message::before { content : '\E99E'; } + &.Minor-illusion::before { content : '\E99F'; } + &.movement1::before { content : '\E9A0'; } + &.polymorph::before { content : '\E9A1'; } + &.power-word-kill::before { content : '\E9A2'; } + &.power-word-stun::before { content : '\E9A3'; } + &.prayer-of-healing::before { content : '\E9A4'; } + &.prestidigitation::before { content : '\E9A5'; } + &.protection-from-evil-and-good::before { content : '\E9A6'; } + &.raise-read::before { content : '\E9A7'; } + &.raise-read2::before { content : '\E9A8'; } + &.reaction1::before { content : '\E9A9'; } + &.resurrection::before { content : '\E9AA'; } + &.resurrection2::before { content : '\E9AB'; } + &.revivify::before { content : '\E9AC'; } + &.revivify2::before { content : '\E9AD'; } + &.sacred-flame::before { content : '\E9AE'; } + &.sanctuary::before { content : '\E9AF'; } + &.scorching-ray::before { content : '\E9B0'; } + &.sending::before { content : '\E9B1'; } + &.shatter::before { content : '\E9B2'; } + &.shield::before { content : '\E9B3'; } + &.silent-image::before { content : '\E9B4'; } + &.sleep::before { content : '\E9B5'; } + &.speak-with-animals::before { content : '\E9B6'; } + &.telekinesis::before { content : '\E9B7'; } + &.true-strike::before { content : '\E9B8'; } + &.vicious-mockery::before { content : '\E9B9'; } + &.wall-of-fire::before { content : '\E9BA'; } + &.wall-of-force::before { content : '\E9BB'; } + &.wall-of-ice::before { content : '\E9BC'; } + &.wall-of-stone::before { content : '\E9BD'; } + &.wall-of-thorns::before { content : '\E9BE'; } + &.wish::before { content : '\E9BF'; } + } +} \ No newline at end of file