0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2025-12-26 20:22:42 +00:00

Merge branch 'master' into headerNaxExtension

This commit is contained in:
Víctor Losada Hernández
2025-02-02 16:44:30 +01:00
committed by GitHub
17 changed files with 526 additions and 389 deletions

View File

@@ -1,48 +1,48 @@
{ {
"extends": [ "extends": [
"stylelint-config-recess-order", "stylelint-config-recess-order",
"stylelint-config-recommended"], "stylelint-config-recommended"],
"plugins": [ "plugins": [
"@stylistic/stylelint-plugin", "@stylistic/stylelint-plugin",
"./stylelint_plugins/declaration-colon-align.js", "./stylelint_plugins/declaration-colon-align.js",
"./stylelint_plugins/declaration-colon-min-space-before", "./stylelint_plugins/declaration-colon-min-space-before",
"./stylelint_plugins/declaration-block-multi-line-min-declarations" "./stylelint_plugins/declaration-block-multi-line-min-declarations"
], ],
"customSyntax": "postcss-less", "customSyntax": "postcss-less",
"rules": { "rules": {
"no-descending-specificity" : null, "no-descending-specificity" : null,
"at-rule-no-unknown" : null, "at-rule-no-unknown" : null,
"function-no-unknown" : null, "function-no-unknown" : null,
"font-family-no-missing-generic-family-keyword" : null, "font-family-no-missing-generic-family-keyword" : null,
"font-weight-notation" : "named-where-possible", "font-weight-notation" : "named-where-possible",
"font-family-name-quotes" : "always-unless-keyword", "font-family-name-quotes" : "always-unless-keyword",
"@stylistic/indentation" : "tab", "@stylistic/indentation" : "tab",
"no-duplicate-selectors" : true, "no-duplicate-selectors" : true,
"@stylistic/color-hex-case" : "upper", "@stylistic/color-hex-case" : "upper",
"color-hex-length" : "long", "color-hex-length" : "long",
"@stylistic/selector-combinator-space-after" : "always", "@stylistic/selector-combinator-space-after" : "always",
"@stylistic/selector-combinator-space-before" : "always", "@stylistic/selector-combinator-space-before" : "always",
"@stylistic/selector-attribute-operator-space-before" : "never", "@stylistic/selector-attribute-operator-space-before" : "never",
"@stylistic/selector-attribute-operator-space-after" : "never", "@stylistic/selector-attribute-operator-space-after" : "never",
"@stylistic/selector-attribute-brackets-space-inside" : "never", "@stylistic/selector-attribute-brackets-space-inside" : "never",
"selector-attribute-quotes" : "always", "selector-attribute-quotes" : "always",
"selector-pseudo-element-colon-notation" : "double", "selector-pseudo-element-colon-notation" : "double",
"@stylistic/selector-pseudo-class-parentheses-space-inside" : "never", "@stylistic/selector-pseudo-class-parentheses-space-inside" : "never",
"@stylistic/block-opening-brace-space-before" : "always", "@stylistic/block-opening-brace-space-before" : "always",
"naturalcrit/declaration-colon-min-space-before" : 1, "naturalcrit/declaration-colon-min-space-before" : 1,
"@stylistic/declaration-block-trailing-semicolon" : "always", "@stylistic/declaration-block-trailing-semicolon" : "always",
"@stylistic/declaration-colon-space-after" : "always", "@stylistic/declaration-colon-space-after" : "always",
"@stylistic/number-leading-zero" : "always", "@stylistic/number-leading-zero" : "always",
"function-url-quotes" : ["always", { "except": ["empty"] }], "function-url-quotes" : ["always", { "except": ["empty"] }],
"function-url-scheme-disallowed-list" : ["data","http"], "function-url-scheme-disallowed-list" : ["data","http"],
"comment-whitespace-inside" : "always", "comment-whitespace-inside" : "always",
"@stylistic/string-quotes" : "single", "@stylistic/string-quotes" : "single",
"@stylistic/media-feature-range-operator-space-before" : "always", "@stylistic/media-feature-range-operator-space-before" : "always",
"@stylistic/media-feature-range-operator-space-after" : "always", "@stylistic/media-feature-range-operator-space-after" : "always",
"@stylistic/media-feature-parentheses-space-inside" : "never", "@stylistic/media-feature-parentheses-space-inside" : "never",
"@stylistic/media-feature-colon-space-before" : "always", "@stylistic/media-feature-colon-space-before" : "always",
"@stylistic/media-feature-colon-space-after" : "always", "@stylistic/media-feature-colon-space-after" : "always",
"naturalcrit/declaration-colon-align" : true, "naturalcrit/declaration-colon-align" : true,
"naturalcrit/declaration-block-multi-line-min-declarations": 1 "naturalcrit/declaration-block-multi-line-min-declarations" : 1
} }
} }

View File

@@ -77,14 +77,100 @@ pre {
} }
.varSyntaxTable th:first-of-type { .varSyntaxTable th:first-of-type {
width:6cm; width:6cm;
}
.page .exampleTable td,th {
border:1px dashed #00000030;
} }
``` ```
## changelog ## changelog
For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery). For a full record of development, visit our [Github Page](https://github.com/naturalcrit/homebrewery).
### Thursday 01/30/2024 - v3.17.0
{{taskList
##### 5e-Cleric
* [x] Update FAQ
* [x] Fix styling for Vault buttons and checkboxes
* [x] Improve navigation bar styling
* [x] Add feature to change username at https://www.naturalcrit.com/account
* [x] Fix Reddit link crash when title has non-latin chars
##### dbolack
* [x] Fix page shadows toolbar option
Fixes issue [#3919](https://github.com/naturalcrit/homebrewery/issues/3919)
* [x] Add `:>>>` syntax for horizontal :>>>>> spaces
* [x] Update Docker install instructions
Fixes issue [#1930](https://github.com/naturalcrit/homebrewery/issues/1930)
* [x] Allow styling pages via `\page{myStyles}` (with calculuschild)
Fixes issue [#3901](https://github.com/naturalcrit/homebrewery/issues/3901)
* [x] Update Ubuntu install instructions
Fixes issue [#1952](https://github.com/naturalcrit/homebrewery/issues/1952)
* [x] Add `:-:` `:-` `-:` syntax for paragraph alignment, similar to table column alignment; for example:
-: -: Right-aligned
:-: :-: Centered
* [x] Add `:-- 50% --:` syntax to allow setting table column widths by percentage; for example:
```
| Narrow | Wide |
|:- 10% -:|:-90%--:|
| Cell | Cell |
```
| Narrow | Wide |
|:- 10% -:|:-90%--:|
|Cell | Cell |
{exampleTable}
##### G-Ambatte
* [x] Fix crash when opening brew Properties tab
Fixes issue [#3927](https://github.com/naturalcrit/homebrewery/issues/3927)
* [x] Update error pages with steps to refresh credentials
Fixes issue [#3955](https://github.com/naturalcrit/homebrewery/issues/3955)
* [x] Add {{openSans :fas_rectangle_list: **NAVIGATION**}} menu to the viewer toolbar
##### calculuschild
* [x] Reduce display lag on large brews
##### Gazook89
* [x] Smarter detection of current page number
Fixes issue [#3824](https://github.com/naturalcrit/homebrewery/issues/3824)
##### All
* [x] Update dependencies and scripts
* [x] Refactor components and fix various errors
}}
\column
### Wednesday 11/27/2024 - v3.16.1 ### Wednesday 11/27/2024 - v3.16.1
{{taskList {{taskList
@@ -131,6 +217,8 @@ Fixes issue [#3744](https://github.com/naturalcrit/homebrewery/issues/3744)
* [x] Multiple code refactors, cleanups, and security fixes * [x] Multiple code refactors, cleanups, and security fixes
}} }}
\page
### Saturday 10/12/2024 - v3.16.0 ### Saturday 10/12/2024 - v3.16.0
{{taskList {{taskList
@@ -2053,4 +2141,4 @@ Massive changelog incoming:
* Added `phb.standalone.css` plus a build system for creating it * Added `phb.standalone.css` plus a build system for creating it
* Added page numbers and footer text * Added page numbers and footer text
* Page accent now flips each page * Page accent now flips each page

View File

@@ -17,10 +17,9 @@ const dedent = require('dedent-tabs').default;
const { printCurrentBrew } = require('../../../shared/helpers.js'); const { printCurrentBrew } = require('../../../shared/helpers.js');
import HeaderNav from './headerNav/headerNav.jsx'; import HeaderNav from './headerNav/headerNav.jsx';
import { safeHTML } from './safeHTML.js'; import { safeHTML } from './safeHTML.js';
const PAGEBREAK_REGEX_V3 = /^(?=\\page(?: *{[^\n{}]*})?$)/m;
const PAGE_HEIGHT = 1056; const PAGE_HEIGHT = 1056;
const INITIAL_CONTENT = dedent` const INITIAL_CONTENT = dedent`
@@ -78,7 +77,7 @@ const BrewPage = (props)=>{
}; };
}, []); }, []);
return <div className={props.className} id={`p${props.index + 1}`} data-index={props.index} ref={pageRef} style={props.style}> return <div className={props.className} id={`p${props.index + 1}`} data-index={props.index} ref={pageRef} style={props.style} {...props.attributes}>
<div className='columnWrapper' dangerouslySetInnerHTML={{ __html: cleanText }} /> <div className='columnWrapper' dangerouslySetInnerHTML={{ __html: cleanText }} />
</div>; </div>;
}; };
@@ -126,7 +125,7 @@ const BrewRenderer = (props)=>{
if(props.renderer == 'legacy') { if(props.renderer == 'legacy') {
rawPages = props.text.split('\\page'); rawPages = props.text.split('\\page');
} else { } else {
rawPages = props.text.split(/^\\page$/gm); rawPages = props.text.split(PAGEBREAK_REGEX_V3);
} }
const handlePageVisibilityChange = (pageNum, isVisible, isCenter)=>{ const handlePageVisibilityChange = (pageNum, isVisible, isCenter)=>{
@@ -173,20 +172,34 @@ const BrewRenderer = (props)=>{
const renderPage = (pageText, index)=>{ const renderPage = (pageText, index)=>{
const styles = { let styles = {
...(!displayOptions.pageShadows ? { boxShadow: 'none' } : {}) ...(!displayOptions.pageShadows ? { boxShadow: 'none' } : {})
// Add more conditions as needed // Add more conditions as needed
}; };
let classes = 'page';
let attributes = {};
if(props.renderer == 'legacy') { if(props.renderer == 'legacy') {
const html = MarkdownLegacy.render(pageText); const html = MarkdownLegacy.render(pageText);
return <BrewPage className='page phb' index={index} key={index} contents={html} style={styles} onVisibilityChange={handlePageVisibilityChange} />; return <BrewPage className='page phb' index={index} key={index} contents={html} style={styles} onVisibilityChange={handlePageVisibilityChange} />;
} else { } else {
if(pageText.startsWith('\\page')) {
const firstLineTokens = Markdown.marked.lexer(pageText.split('\n', 1)[0])[0].tokens;
const injectedTags = firstLineTokens.find((obj)=>obj.injectedTags !== undefined)?.injectedTags;
if(injectedTags) {
styles = { ...styles, ...injectedTags.styles };
styles = _.mapKeys(styles, (v, k) => k.startsWith('--') ? k : _.camelCase(k)); // Convert CSS to camelCase for React
classes = [classes, injectedTags.classes].join(' ').trim();
attributes = injectedTags.attributes;
}
pageText = pageText.includes('\n') ? pageText.substring(pageText.indexOf('\n') + 1) : ''; // Remove the \page line
}
pageText += `\n\n&nbsp;\n\\column\n&nbsp;`; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear) pageText += `\n\n&nbsp;\n\\column\n&nbsp;`; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear)
const html = Markdown.render(pageText, index); const html = Markdown.render(pageText, index);
return <BrewPage className='page' index={index} key={index} contents={html} style={styles} onVisibilityChange={handlePageVisibilityChange} />; return <BrewPage className={classes} index={index} key={index} contents={html} style={styles} attributes={attributes} onVisibilityChange={handlePageVisibilityChange} />;
} }
}; };

View File

@@ -1,6 +1,7 @@
require('./notificationPopup.less'); require('./notificationPopup.less');
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import request from '../../utils/request-middleware.js'; import request from '../../utils/request-middleware.js';
import Markdown from 'naturalcrit/markdown.js';
import Dialog from '../../../components/dialog.jsx'; import Dialog from '../../../components/dialog.jsx';
@@ -40,11 +41,10 @@ const NotificationPopup = ()=>{
const renderNotificationsList = ()=>{ const renderNotificationsList = ()=>{
if(error) return <div className='error'>{error}</div>; if(error) return <div className='error'>{error}</div>;
return notifications.map((notification)=>( return notifications.map((notification)=>(
<li key={notification.dismissKey} > <li key={notification.dismissKey} >
<em>{notification.title}</em><br /> <em>{notification.title}</em><br />
<p dangerouslySetInnerHTML={{ __html: notification.text }}></p> <p dangerouslySetInnerHTML={{ __html: Markdown.render(notification.text) }}></p>
</li> </li>
)); ));
}; };

View File

@@ -48,17 +48,46 @@
} }
ul { ul {
margin-top : 15px; margin-top : 15px;
font-size : 0.8em; font-size : 0.9em;
list-style-position : outside; list-style-position : outside;
list-style-type : disc; list-style-type : disc;
li { li {
margin-top : 1.4em; padding-left : 1em;
font-size : 0.8em; margin-top : 1.5em;
line-height : 1.4em; font-size : 0.9em;
em { line-height : 1.5em;
text-transform:capitalize; em {
font-weight : 800; font-weight : 800;
text-transform : capitalize;
}
li {
margin-top : 0;
line-height : 1.2em;
list-style-type : square;
} }
} }
ul ul,ol ol,ul ol,ol ul {
margin-bottom : 0px;
margin-left : 1.5em;
}
} }
}
/* Markdown styling */
code {
padding : 0.1em 0.5em;
font-family : 'Courier New', 'Courier', monospace;
overflow-wrap : break-word;
white-space : pre-wrap;
background : #08115A;
border-radius : 2px;
}
pre code {
display : inline-block;
width : 100%;
}
.blank {
height : 1em;
margin-top : 0;
& + * { margin-top : 0; }
}
}

View File

@@ -12,7 +12,8 @@ const MetadataEditor = require('./metadataEditor/metadataEditor.jsx');
const EDITOR_THEME_KEY = 'HOMEBREWERY-EDITOR-THEME'; const EDITOR_THEME_KEY = 'HOMEBREWERY-EDITOR-THEME';
const SNIPPETBAR_HEIGHT = 25; const PAGEBREAK_REGEX_V3 = /^(?=\\page(?: *{[^\n{}]*})?$)/m;
const SNIPPETBAR_HEIGHT = 25;
const DEFAULT_STYLE_TEXT = dedent` const DEFAULT_STYLE_TEXT = dedent`
/*=======--- Example CSS styling ---=======*/ /*=======--- Example CSS styling ---=======*/
/* Any CSS here will apply to your document! */ /* Any CSS here will apply to your document! */
@@ -126,15 +127,15 @@ const Editor = createClass({
}, },
updateCurrentCursorPage : function(cursor) { updateCurrentCursorPage : function(cursor) {
const lines = this.props.brew.text.split('\n').slice(0, cursor.line + 1); const lines = this.props.brew.text.split('\n').slice(1, cursor.line + 1);
const pageRegex = this.props.brew.renderer == 'V3' ? /^\\page$/ : /\\page/; const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1); const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1);
this.props.onCursorPageChange(currentPage); this.props.onCursorPageChange(currentPage);
}, },
updateCurrentViewPage : function(topScrollLine) { updateCurrentViewPage : function(topScrollLine) {
const lines = this.props.brew.text.split('\n').slice(0, topScrollLine + 1); const lines = this.props.brew.text.split('\n').slice(1, topScrollLine + 1);
const pageRegex = this.props.brew.renderer == 'V3' ? /^\\page$/ : /\\page/; const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1); const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1);
this.props.onViewPageChange(currentPage); this.props.onViewPageChange(currentPage);
}, },
@@ -174,7 +175,7 @@ const Editor = createClass({
for (let i=customHighlights.length - 1;i>=0;i--) customHighlights[i].clear(); for (let i=customHighlights.length - 1;i>=0;i--) customHighlights[i].clear();
let editorPageCount = 2; // start page count from page 2 let editorPageCount = 1; // start page count from page 1
_.forEach(this.props.brew.text.split('\n'), (line, lineNumber)=>{ _.forEach(this.props.brew.text.split('\n'), (line, lineNumber)=>{
@@ -190,7 +191,10 @@ const Editor = createClass({
// Styling for \page breaks // Styling for \page breaks
if((this.props.renderer == 'legacy' && line.includes('\\page')) || if((this.props.renderer == 'legacy' && line.includes('\\page')) ||
(this.props.renderer == 'V3' && line.match(/^\\page$/))) { (this.props.renderer == 'V3' && line.match(PAGEBREAK_REGEX_V3))) {
if(lineNumber > 0) // Since \page is optional on first line of document,
editorPageCount += 1; // don't use it to increment page count; stay at 1
// add back the original class 'background' but also add the new class '.pageline' // add back the original class 'background' but also add the new class '.pageline'
codeMirror.addLineClass(lineNumber, 'background', 'pageLine'); codeMirror.addLineClass(lineNumber, 'background', 'pageLine');
@@ -199,8 +203,6 @@ const Editor = createClass({
textContent : editorPageCount textContent : editorPageCount
}); });
codeMirror.setBookmark({ line: lineNumber, ch: line.length }, pageCountElement); codeMirror.setBookmark({ line: lineNumber, ch: line.length }, pageCountElement);
editorPageCount += 1;
}; };
// New Codemirror styling for V3 renderer // New Codemirror styling for V3 renderer
@@ -358,7 +360,7 @@ const Editor = createClass({
if(!this.isText() || isJumping) if(!this.isText() || isJumping)
return; return;
const textSplit = this.props.renderer == 'V3' ? /^\\page$/gm : /\\page/; const textSplit = this.props.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit); const textString = this.props.brew.text.split(textSplit).slice(0, targetPage-1).join(textSplit);
const targetLine = textString.match('\n') ? textString.split('\n').length - 1 : -1; const targetLine = textString.match('\n') ? textString.split('\n').length - 1 : -1;

View File

@@ -2,6 +2,11 @@ const dedent = require('dedent-tabs').default;
const loginUrl = 'https://www.naturalcrit.com/login'; const loginUrl = 'https://www.naturalcrit.com/login';
// Prevent parsing text (e.g. document titles) as markdown
const escape = (text) => {
return text.split('').map(char => `&#${char.charCodeAt(0)};`).join('');
};
//001-050 : Brew errors //001-050 : Brew errors
//050-100 : Other pages errors //050-100 : Other pages errors
@@ -89,7 +94,7 @@ const errorIndex = (props)=>{
: :
**Brew Title:** ${props.brew.brewTitle || 'Unable to show title'} **Brew Title:** ${escape(props.brew.brewTitle) || 'Unable to show title'}
**Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'} **Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'}
@@ -104,7 +109,7 @@ const errorIndex = (props)=>{
: :
**Brew Title:** ${props.brew.brewTitle || 'Unable to show title'} **Brew Title:** ${escape(props.brew.brewTitle) || 'Unable to show title'}
**Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'} **Current Authors:** ${props.brew.authors?.map((author)=>{return `[${author}](/user/${author})`;}).join(', ') || 'Unable to list authors'}
@@ -181,7 +186,7 @@ const errorIndex = (props)=>{
**Brew ID:** ${props.brew.brewId} **Brew ID:** ${props.brew.brewId}
**Brew Title:** ${props.brew.brewTitle}`, **Brew Title:** ${escape(props.brew.brewTitle)}`,
// ####### Admin page error ####### // ####### Admin page error #######
'52' : dedent` '52' : dedent`

View File

@@ -24,12 +24,16 @@ These instructions assume that you are installing to a completely new, fresh Ubu
These installation instructions have been tested on the following Ubuntu releases: These installation instructions have been tested on the following Ubuntu releases:
- *ubuntu-20.04.3-desktop-amd64* - *ubuntu-24.04.1-desktop-amd64*
- *ubuntu-22.04.5-desktop-amd64*
- *ubuntu-20.04.6-desktop-amd64*
## Final Notes ## Final Notes
While this installation process works successfully at the time of writing (December 19, 2021), it relies on all of the Node.JS packages used in the HomeBrewery project retaining their cross-platform capabilities to continue to function. This is one of the inherent advantages of Node.JS, but it is by no means guaranteed and as such, functionality or even installation may fail without warning at some point in the future. While this installation process works successfully at the time of writing (December 19, 2021), it relies on all of the Node.JS packages used in the HomeBrewery project retaining their cross-platform capabilities to continue to function. This is one of the inherent advantages of Node.JS, but it is by no means guaranteed and as such, functionality or even installation may fail without warning at some point in the future.
Earlier versions of Ubuntu may requier an alternate Mongo setup, see https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/ for assistance.
Regards, Regards,
G G
December 19, 2021 December 19, 2021

View File

@@ -3,7 +3,8 @@ Description=Homebrewery Web Server
[Service] [Service]
User=root User=root
After=mongodb BindsTo=mongod.service
After=mongod.service
Environment=NODE_ENV=local Environment=NODE_ENV=local
WorkingDirectory=/usr/local/homebrewery WorkingDirectory=/usr/local/homebrewery
ExecStart=node server.js ExecStart=node server.js

View File

@@ -1,14 +1,60 @@
#!/bin/sh #!/bin/sh
# Detect Ubuntu Version
export DISTRO=$(grep "^NAME=" /etc/os-release | awk -F '=' '{print $2}' | sed 's/"//g')
export DISTRO_VER=$(grep "VERSION_ID=" /etc/os-release | awk -F '=' '{print $2}' | sed 's/"//g')
export MATCHED="Yes"
if [ "${DISTRO}" != "Ubuntu" ];
then
echo :: Ubuntu not detected. Are you using an alternate spin or derivative?
echo :: Detected - ${DISTRO}
read -p [y/N] YESNO
if [ "${YESNO}" != "Y" ] && [ ]"${YESNO}" != "y" ]; then
exit
fi
MATCHED="No"
fi
# Install CURL and add required NodeJS source to package repo # Install CURL and add required NodeJS source to package repo
echo ::Install CURL echo ::Install CURL
apt install -y curl apt install -y curl
echo ::Add NodeJS source to package repo echo ::Add NodeJS source to package repo
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
# Add Mongo CE Source
if [ ${DISTRO} = "Ubuntu" ];
then
echo ::Add Mongo CE source to package repo
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg \
--dearmor
if [ "${DISTRO_VER}" == "24.04" ]; then
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
elif [ "${DISTRO_VER}" == "22.04" ]; then
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/8.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
elif [ "${DISTRO_VER}" == "20.04" ]; then
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/8.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
else
MATCHED="No"
fi
sudo apt-get update
fi
if [ ${MATCHED} == "No" ]; then
echo :: WARNING
echo :: Unable to determine Ubuntu version for Mongo installation purposes.
echo :: Please check your spin/distro documentation to install Mongo CE and enable it on startup.
fi
# Install required packages # Install required packages
echo ::Install Homebrewery requirements echo ::Install Homebrewery requirements
apt satisfy -y git nodejs npm mongodb apt satisfy -y git nodejs npm mongodb-org
# Enable and start Mongo
systemctl enable mongod
systemctl start mongod
# Clone Homebrewery repo # Clone Homebrewery repo
echo ::Get Homebrewery files echo ::Get Homebrewery files

361
package-lock.json generated
View File

@@ -1,18 +1,18 @@
{ {
"name": "homebrewery", "name": "homebrewery",
"version": "3.16.1", "version": "3.17.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "homebrewery", "name": "homebrewery",
"version": "3.16.1", "version": "3.17.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/core": "^7.26.0", "@babel/core": "^7.26.7",
"@babel/plugin-transform-runtime": "^7.25.9", "@babel/plugin-transform-runtime": "^7.25.9",
"@babel/preset-env": "^7.26.0", "@babel/preset-env": "^7.26.7",
"@babel/preset-react": "^7.26.3", "@babel/preset-react": "^7.26.3",
"@googleapis/drive": "^8.14.0", "@googleapis/drive": "^8.14.0",
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
@@ -23,7 +23,7 @@
"cors": "^2.8.5", "cors": "^2.8.5",
"create-react-class": "^15.7.0", "create-react-class": "^15.7.0",
"dedent-tabs": "^0.10.3", "dedent-tabs": "^0.10.3",
"dompurify": "^3.2.3", "dompurify": "^3.2.4",
"expr-eval": "^2.0.2", "expr-eval": "^2.0.2",
"express": "^4.21.2", "express": "^4.21.2",
"express-async-handler": "^1.2.0", "express-async-handler": "^1.2.0",
@@ -34,11 +34,11 @@
"jwt-simple": "^0.5.6", "jwt-simple": "^0.5.6",
"less": "^3.13.1", "less": "^3.13.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"marked": "11.2.0", "marked": "13.0.3",
"marked-emoji": "^1.4.3", "marked-emoji": "^1.4.3",
"marked-extended-tables": "^1.1.0", "marked-extended-tables": "^1.1.0",
"marked-gfm-heading-id": "^3.2.0", "marked-gfm-heading-id": "^4.0.1",
"marked-smartypants-lite": "^1.0.2", "marked-smartypants-lite": "^1.0.3",
"markedLegacy": "npm:marked@^0.3.19", "markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.30.1", "moment": "^2.30.1",
"mongoose": "^8.9.5", "mongoose": "^8.9.5",
@@ -46,8 +46,8 @@
"nconf": "^0.12.1", "nconf": "^0.12.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-frame-component": "^5.2.7", "react-frame-component": "^4.1.3",
"react-router": "^7.1.2", "react-router": "^7.1.4",
"sanitize-filename": "1.6.3", "sanitize-filename": "1.6.3",
"superagent": "^10.1.1", "superagent": "^10.1.1",
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git" "vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
@@ -55,7 +55,7 @@
"devDependencies": { "devDependencies": {
"@stylistic/stylelint-plugin": "^3.1.1", "@stylistic/stylelint-plugin": "^3.1.1",
"babel-plugin-transform-import-meta": "^2.3.2", "babel-plugin-transform-import-meta": "^2.3.2",
"eslint": "^9.18.0", "eslint": "^9.19.0",
"eslint-plugin-jest": "^28.11.0", "eslint-plugin-jest": "^28.11.0",
"eslint-plugin-react": "^7.37.4", "eslint-plugin-react": "^7.37.4",
"globals": "^15.14.0", "globals": "^15.14.0",
@@ -63,7 +63,7 @@
"jest-expect-message": "^1.1.3", "jest-expect-message": "^1.1.3",
"jsdom-global": "^3.0.2", "jsdom-global": "^3.0.2",
"postcss-less": "^6.0.0", "postcss-less": "^6.0.0",
"stylelint": "^16.13.2", "stylelint": "^16.14.1",
"stylelint-config-recess-order": "^6.0.0", "stylelint-config-recess-order": "^6.0.0",
"stylelint-config-recommended": "^15.0.0", "stylelint-config-recommended": "^15.0.0",
"supertest": "^7.0.0" "supertest": "^7.0.0"
@@ -87,9 +87,10 @@
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
"version": "7.26.0", "version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.0.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
"integrity": "sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==", "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-validator-identifier": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9",
"js-tokens": "^4.0.0", "js-tokens": "^4.0.0",
@@ -100,28 +101,30 @@
} }
}, },
"node_modules/@babel/compat-data": { "node_modules/@babel/compat-data": {
"version": "7.26.0", "version": "7.26.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz",
"integrity": "sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==", "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==",
"license": "MIT",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/core": { "node_modules/@babel/core": {
"version": "7.26.0", "version": "7.26.7",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz",
"integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@ampproject/remapping": "^2.2.0", "@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.26.0", "@babel/code-frame": "^7.26.2",
"@babel/generator": "^7.26.0", "@babel/generator": "^7.26.5",
"@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-compilation-targets": "^7.26.5",
"@babel/helper-module-transforms": "^7.26.0", "@babel/helper-module-transforms": "^7.26.0",
"@babel/helpers": "^7.26.0", "@babel/helpers": "^7.26.7",
"@babel/parser": "^7.26.0", "@babel/parser": "^7.26.7",
"@babel/template": "^7.25.9", "@babel/template": "^7.25.9",
"@babel/traverse": "^7.25.9", "@babel/traverse": "^7.26.7",
"@babel/types": "^7.26.0", "@babel/types": "^7.26.7",
"convert-source-map": "^2.0.0", "convert-source-map": "^2.0.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"gensync": "^1.0.0-beta.2", "gensync": "^1.0.0-beta.2",
@@ -137,12 +140,13 @@
} }
}, },
"node_modules/@babel/generator": { "node_modules/@babel/generator": {
"version": "7.26.0", "version": "7.26.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.0.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz",
"integrity": "sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==", "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.26.0", "@babel/parser": "^7.26.5",
"@babel/types": "^7.26.0", "@babel/types": "^7.26.5",
"@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25", "@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2" "jsesc": "^3.0.2"
@@ -162,24 +166,13 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz",
"integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==",
"dependencies": {
"@babel/traverse": "^7.25.9",
"@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-compilation-targets": { "node_modules/@babel/helper-compilation-targets": {
"version": "7.25.9", "version": "7.26.5",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz",
"integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/compat-data": "^7.25.9", "@babel/compat-data": "^7.26.5",
"@babel/helper-validator-option": "^7.25.9", "@babel/helper-validator-option": "^7.25.9",
"browserslist": "^4.24.0", "browserslist": "^4.24.0",
"lru-cache": "^5.1.1", "lru-cache": "^5.1.1",
@@ -293,9 +286,10 @@
} }
}, },
"node_modules/@babel/helper-plugin-utils": { "node_modules/@babel/helper-plugin-utils": {
"version": "7.25.9", "version": "7.26.5",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz",
"integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==",
"license": "MIT",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
@@ -332,18 +326,6 @@
"@babel/core": "^7.0.0" "@babel/core": "^7.0.0"
} }
}, },
"node_modules/@babel/helper-simple-access": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz",
"integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==",
"dependencies": {
"@babel/traverse": "^7.25.9",
"@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-skip-transparent-expression-wrappers": { "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
"version": "7.25.9", "version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
@@ -394,23 +376,25 @@
} }
}, },
"node_modules/@babel/helpers": { "node_modules/@babel/helpers": {
"version": "7.26.0", "version": "7.26.7",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz",
"integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/template": "^7.25.9", "@babel/template": "^7.25.9",
"@babel/types": "^7.26.0" "@babel/types": "^7.26.7"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.26.1", "version": "7.26.7",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz",
"integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==", "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.26.0" "@babel/types": "^7.26.7"
}, },
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@@ -786,11 +770,12 @@
} }
}, },
"node_modules/@babel/plugin-transform-block-scoped-functions": { "node_modules/@babel/plugin-transform-block-scoped-functions": {
"version": "7.25.9", "version": "7.26.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz",
"integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-plugin-utils": "^7.25.9" "@babel/helper-plugin-utils": "^7.26.5"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -958,11 +943,11 @@
} }
}, },
"node_modules/@babel/plugin-transform-exponentiation-operator": { "node_modules/@babel/plugin-transform-exponentiation-operator": {
"version": "7.25.9", "version": "7.26.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz",
"integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9",
"@babel/helper-plugin-utils": "^7.25.9" "@babel/helper-plugin-utils": "^7.25.9"
}, },
"engines": { "engines": {
@@ -1089,13 +1074,13 @@
} }
}, },
"node_modules/@babel/plugin-transform-modules-commonjs": { "node_modules/@babel/plugin-transform-modules-commonjs": {
"version": "7.25.9", "version": "7.26.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz",
"integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-module-transforms": "^7.25.9", "@babel/helper-module-transforms": "^7.26.0",
"@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9"
"@babel/helper-simple-access": "^7.25.9"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -1166,11 +1151,12 @@
} }
}, },
"node_modules/@babel/plugin-transform-nullish-coalescing-operator": { "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
"version": "7.25.9", "version": "7.26.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz",
"integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-plugin-utils": "^7.25.9" "@babel/helper-plugin-utils": "^7.26.5"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -1494,11 +1480,12 @@
} }
}, },
"node_modules/@babel/plugin-transform-typeof-symbol": { "node_modules/@babel/plugin-transform-typeof-symbol": {
"version": "7.25.9", "version": "7.26.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz",
"integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", "integrity": "sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-plugin-utils": "^7.25.9" "@babel/helper-plugin-utils": "^7.26.5"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -1567,13 +1554,14 @@
} }
}, },
"node_modules/@babel/preset-env": { "node_modules/@babel/preset-env": {
"version": "7.26.0", "version": "7.26.7",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.7.tgz",
"integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", "integrity": "sha512-Ycg2tnXwixaXOVb29rana8HNPgLVBof8qqtNQ9LE22IoyZboQbGSxI6ZySMdW3K5nAe6gu35IaJefUJflhUFTQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/compat-data": "^7.26.0", "@babel/compat-data": "^7.26.5",
"@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-compilation-targets": "^7.26.5",
"@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-plugin-utils": "^7.26.5",
"@babel/helper-validator-option": "^7.25.9", "@babel/helper-validator-option": "^7.25.9",
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9",
"@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9",
@@ -1587,7 +1575,7 @@
"@babel/plugin-transform-arrow-functions": "^7.25.9", "@babel/plugin-transform-arrow-functions": "^7.25.9",
"@babel/plugin-transform-async-generator-functions": "^7.25.9", "@babel/plugin-transform-async-generator-functions": "^7.25.9",
"@babel/plugin-transform-async-to-generator": "^7.25.9", "@babel/plugin-transform-async-to-generator": "^7.25.9",
"@babel/plugin-transform-block-scoped-functions": "^7.25.9", "@babel/plugin-transform-block-scoped-functions": "^7.26.5",
"@babel/plugin-transform-block-scoping": "^7.25.9", "@babel/plugin-transform-block-scoping": "^7.25.9",
"@babel/plugin-transform-class-properties": "^7.25.9", "@babel/plugin-transform-class-properties": "^7.25.9",
"@babel/plugin-transform-class-static-block": "^7.26.0", "@babel/plugin-transform-class-static-block": "^7.26.0",
@@ -1598,7 +1586,7 @@
"@babel/plugin-transform-duplicate-keys": "^7.25.9", "@babel/plugin-transform-duplicate-keys": "^7.25.9",
"@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9",
"@babel/plugin-transform-dynamic-import": "^7.25.9", "@babel/plugin-transform-dynamic-import": "^7.25.9",
"@babel/plugin-transform-exponentiation-operator": "^7.25.9", "@babel/plugin-transform-exponentiation-operator": "^7.26.3",
"@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-export-namespace-from": "^7.25.9",
"@babel/plugin-transform-for-of": "^7.25.9", "@babel/plugin-transform-for-of": "^7.25.9",
"@babel/plugin-transform-function-name": "^7.25.9", "@babel/plugin-transform-function-name": "^7.25.9",
@@ -1607,12 +1595,12 @@
"@babel/plugin-transform-logical-assignment-operators": "^7.25.9", "@babel/plugin-transform-logical-assignment-operators": "^7.25.9",
"@babel/plugin-transform-member-expression-literals": "^7.25.9", "@babel/plugin-transform-member-expression-literals": "^7.25.9",
"@babel/plugin-transform-modules-amd": "^7.25.9", "@babel/plugin-transform-modules-amd": "^7.25.9",
"@babel/plugin-transform-modules-commonjs": "^7.25.9", "@babel/plugin-transform-modules-commonjs": "^7.26.3",
"@babel/plugin-transform-modules-systemjs": "^7.25.9", "@babel/plugin-transform-modules-systemjs": "^7.25.9",
"@babel/plugin-transform-modules-umd": "^7.25.9", "@babel/plugin-transform-modules-umd": "^7.25.9",
"@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9",
"@babel/plugin-transform-new-target": "^7.25.9", "@babel/plugin-transform-new-target": "^7.25.9",
"@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6",
"@babel/plugin-transform-numeric-separator": "^7.25.9", "@babel/plugin-transform-numeric-separator": "^7.25.9",
"@babel/plugin-transform-object-rest-spread": "^7.25.9", "@babel/plugin-transform-object-rest-spread": "^7.25.9",
"@babel/plugin-transform-object-super": "^7.25.9", "@babel/plugin-transform-object-super": "^7.25.9",
@@ -1629,7 +1617,7 @@
"@babel/plugin-transform-spread": "^7.25.9", "@babel/plugin-transform-spread": "^7.25.9",
"@babel/plugin-transform-sticky-regex": "^7.25.9", "@babel/plugin-transform-sticky-regex": "^7.25.9",
"@babel/plugin-transform-template-literals": "^7.25.9", "@babel/plugin-transform-template-literals": "^7.25.9",
"@babel/plugin-transform-typeof-symbol": "^7.25.9", "@babel/plugin-transform-typeof-symbol": "^7.26.7",
"@babel/plugin-transform-unicode-escapes": "^7.25.9", "@babel/plugin-transform-unicode-escapes": "^7.25.9",
"@babel/plugin-transform-unicode-property-regex": "^7.25.9", "@babel/plugin-transform-unicode-property-regex": "^7.25.9",
"@babel/plugin-transform-unicode-regex": "^7.25.9", "@babel/plugin-transform-unicode-regex": "^7.25.9",
@@ -1707,15 +1695,16 @@
} }
}, },
"node_modules/@babel/traverse": { "node_modules/@babel/traverse": {
"version": "7.25.9", "version": "7.26.7",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz",
"integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.25.9", "@babel/code-frame": "^7.26.2",
"@babel/generator": "^7.25.9", "@babel/generator": "^7.26.5",
"@babel/parser": "^7.25.9", "@babel/parser": "^7.26.7",
"@babel/template": "^7.25.9", "@babel/template": "^7.25.9",
"@babel/types": "^7.25.9", "@babel/types": "^7.26.7",
"debug": "^4.3.1", "debug": "^4.3.1",
"globals": "^11.1.0" "globals": "^11.1.0"
}, },
@@ -1733,9 +1722,10 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.26.0", "version": "7.26.7",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz",
"integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.25.9", "@babel/helper-string-parser": "^7.25.9",
"@babel/helper-validator-identifier": "^7.25.9" "@babel/helper-validator-identifier": "^7.25.9"
@@ -1915,10 +1905,11 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.18.0", "version": "9.19.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz",
"integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==", "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==",
"dev": true, "dev": true,
"license": "MIT",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
@@ -3846,16 +3837,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"license": "MIT",
"optional": true,
"dependencies": {
"file-uri-to-path": "1.0.0"
}
},
"node_modules/bn.js": { "node_modules/bn.js": {
"version": "5.2.1", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
@@ -5332,9 +5313,10 @@
} }
}, },
"node_modules/dompurify": { "node_modules/dompurify": {
"version": "3.2.3", "version": "3.2.4",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.3.tgz", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz",
"integrity": "sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA==", "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optionalDependencies": { "optionalDependencies": {
"@types/trusted-types": "^2.0.7" "@types/trusted-types": "^2.0.7"
} }
@@ -5650,17 +5632,18 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.18.0", "version": "9.19.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz",
"integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==", "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.19.0", "@eslint/config-array": "^0.19.0",
"@eslint/core": "^0.10.0", "@eslint/core": "^0.10.0",
"@eslint/eslintrc": "^3.2.0", "@eslint/eslintrc": "^3.2.0",
"@eslint/js": "9.18.0", "@eslint/js": "9.19.0",
"@eslint/plugin-kit": "^0.2.5", "@eslint/plugin-kit": "^0.2.5",
"@humanfs/node": "^0.16.6", "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
@@ -6345,13 +6328,6 @@
"node": ">=16.0.0" "node": ">=16.0.0"
} }
}, },
"node_modules/file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"license": "MIT",
"optional": true
},
"node_modules/fill-range": { "node_modules/fill-range": {
"version": "7.1.1", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -6525,20 +6501,6 @@
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -9827,9 +9789,9 @@
} }
}, },
"node_modules/marked": { "node_modules/marked": {
"version": "11.2.0", "version": "13.0.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz", "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz",
"integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==", "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==",
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"marked": "bin/marked.js" "marked": "bin/marked.js"
@@ -9855,24 +9817,24 @@
} }
}, },
"node_modules/marked-gfm-heading-id": { "node_modules/marked-gfm-heading-id": {
"version": "3.2.0", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-3.2.0.tgz", "resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-4.1.1.tgz",
"integrity": "sha512-Xfxpr5lXLDLY10XqzSCA9l2dDaiabQUgtYM9hw8yunyVsB/xYBRpiic6BOiY/EAJw1ik1eWr1ET1HKOAPZBhXg==", "integrity": "sha512-EeQZieAQmsI6c2tWLx0ETd0VjPwLV8qi+HT0dIsfVMERm0rCIuXfRvZXJbo1SgUi++lmuR1LVY+QzgNiLNvVpw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"github-slugger": "^2.0.0" "github-slugger": "^2.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"marked": ">=4 <13" "marked": ">=13 <16"
} }
}, },
"node_modules/marked-smartypants-lite": { "node_modules/marked-smartypants-lite": {
"version": "1.0.2", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/marked-smartypants-lite/-/marked-smartypants-lite-1.0.2.tgz", "resolved": "https://registry.npmjs.org/marked-smartypants-lite/-/marked-smartypants-lite-1.0.3.tgz",
"integrity": "sha512-cEANts+s3+gnTzXPvPT2z4V8NfbMEL9QooKUviug0DkaKkXQWrUwDAmFnQAkLSJCw2BQcD8YPDyxu0HJ3mg36w==", "integrity": "sha512-OOL8cjFog8KtgUFpkihRu6G42Dz2QPOU4k2xfKmMJ0CdoX+BHBDmdesHUdoQKM0mlwTsRSU3shpMeM/LWuUokg==",
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
"marked": ">=4 <12" "marked": ">=4 <16"
} }
}, },
"node_modules/markedLegacy": { "node_modules/markedLegacy": {
@@ -10373,13 +10335,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}, },
"node_modules/nan": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz",
"integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==",
"license": "MIT",
"optional": true
},
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "5.0.9", "version": "5.0.9",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz",
@@ -11246,9 +11201,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.49", "version": "8.5.1",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -11266,7 +11221,7 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"nanoid": "^3.3.7", "nanoid": "^3.3.8",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
"source-map-js": "^1.2.1" "source-map-js": "^1.2.1"
}, },
@@ -11350,9 +11305,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/postcss/node_modules/nanoid": { "node_modules/postcss/node_modules/nanoid": {
"version": "3.3.7", "version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -11636,9 +11591,10 @@
} }
}, },
"node_modules/react-frame-component": { "node_modules/react-frame-component": {
"version": "5.2.7", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/react-frame-component/-/react-frame-component-5.2.7.tgz", "resolved": "https://registry.npmjs.org/react-frame-component/-/react-frame-component-4.1.3.tgz",
"integrity": "sha512-ROjHtSLoSVYUBfTieazj/nL8jIX9rZFmHC0yXEU+dx6Y82OcBEGgU9o7VyHMrBFUN9FuQ849MtIPNNLsb4krbg==", "integrity": "sha512-4PurhctiqnmC1F5prPZ+LdsalH7pZ3SFA5xoc0HBe8mSHctdLLt4Cr2WXfXOoajHBYq/yiipp9zOgx+vy8GiEA==",
"license": "MIT",
"peerDependencies": { "peerDependencies": {
"prop-types": "^15.5.9", "prop-types": "^15.5.9",
"react": ">= 16.3", "react": ">= 16.3",
@@ -11653,9 +11609,10 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/react-router": { "node_modules/react-router": {
"version": "7.1.2", "version": "7.1.4",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.2.tgz", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.4.tgz",
"integrity": "sha512-KeallSO30KLpIe/ZZqfk6pCJ1c+5JhMxl3SCS3Zx1LgaGuQbgLDmjuNi6KZ5LnAV9sWjbmBWGRw8Um/Pw6BExg==", "integrity": "sha512-aJWVrKoLI0nIK1lfbTU3d5al1ZEUiwtSus/xjYL8K5sv2hyPesiOIojHM7QnaNLVtroOB1McZsWk37fMQVoc6A==",
"license": "MIT",
"dependencies": { "dependencies": {
"@types/cookie": "^0.6.0", "@types/cookie": "^0.6.0",
"cookie": "^1.0.1", "cookie": "^1.0.1",
@@ -13037,9 +12994,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/stylelint": { "node_modules/stylelint": {
"version": "16.13.2", "version": "16.14.1",
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.13.2.tgz", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.14.1.tgz",
"integrity": "sha512-wDlgh0mRO9RtSa3TdidqHd0nOG8MmUyVKl+dxA6C1j8aZRzpNeEgdhFmU5y4sZx4Fc6r46p0fI7p1vR5O2DZqA==", "integrity": "sha512-oqCL7AC3786oTax35T/nuLL8p2C3k/8rHKAooezrPGRvUX0wX+qqs5kMWh5YYT4PHQgVDobHT4tw55WgpYG6Sw==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -13051,6 +13008,7 @@
"url": "https://github.com/sponsors/stylelint" "url": "https://github.com/sponsors/stylelint"
} }
], ],
"license": "MIT",
"dependencies": { "dependencies": {
"@csstools/css-parser-algorithms": "^3.0.4", "@csstools/css-parser-algorithms": "^3.0.4",
"@csstools/css-tokenizer": "^3.0.3", "@csstools/css-tokenizer": "^3.0.3",
@@ -13070,7 +13028,7 @@
"globby": "^11.1.0", "globby": "^11.1.0",
"globjoin": "^0.1.4", "globjoin": "^0.1.4",
"html-tags": "^3.3.1", "html-tags": "^3.3.1",
"ignore": "^7.0.1", "ignore": "^7.0.3",
"imurmurhash": "^0.1.4", "imurmurhash": "^0.1.4",
"is-plain-object": "^5.0.0", "is-plain-object": "^5.0.0",
"known-css-properties": "^0.35.0", "known-css-properties": "^0.35.0",
@@ -13079,7 +13037,7 @@
"micromatch": "^4.0.8", "micromatch": "^4.0.8",
"normalize-path": "^3.0.0", "normalize-path": "^3.0.0",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
"postcss": "^8.4.49", "postcss": "^8.5.1",
"postcss-resolve-nested-selector": "^0.1.6", "postcss-resolve-nested-selector": "^0.1.6",
"postcss-safe-parser": "^7.0.1", "postcss-safe-parser": "^7.0.1",
"postcss-selector-parser": "^7.0.0", "postcss-selector-parser": "^7.0.0",
@@ -14435,25 +14393,6 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/watchify/node_modules/fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"dependencies": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
},
"engines": {
"node": ">= 4.0"
}
},
"node_modules/watchify/node_modules/glob-parent": { "node_modules/watchify/node_modules/glob-parent": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",

View File

@@ -1,7 +1,7 @@
{ {
"name": "homebrewery", "name": "homebrewery",
"description": "Create authentic looking D&D homebrews using only markdown", "description": "Create authentic looking D&D homebrews using only markdown",
"version": "3.16.1", "version": "3.17.0",
"type": "module", "type": "module",
"engines": { "engines": {
"npm": "^10.2.x", "npm": "^10.2.x",
@@ -85,9 +85,9 @@
] ]
}, },
"dependencies": { "dependencies": {
"@babel/core": "^7.26.0", "@babel/core": "^7.26.7",
"@babel/plugin-transform-runtime": "^7.25.9", "@babel/plugin-transform-runtime": "^7.25.9",
"@babel/preset-env": "^7.26.0", "@babel/preset-env": "^7.26.7",
"@babel/preset-react": "^7.26.3", "@babel/preset-react": "^7.26.3",
"@googleapis/drive": "^8.14.0", "@googleapis/drive": "^8.14.0",
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
@@ -98,7 +98,7 @@
"cors": "^2.8.5", "cors": "^2.8.5",
"create-react-class": "^15.7.0", "create-react-class": "^15.7.0",
"dedent-tabs": "^0.10.3", "dedent-tabs": "^0.10.3",
"dompurify": "^3.2.3", "dompurify": "^3.2.4",
"expr-eval": "^2.0.2", "expr-eval": "^2.0.2",
"express": "^4.21.2", "express": "^4.21.2",
"express-async-handler": "^1.2.0", "express-async-handler": "^1.2.0",
@@ -109,11 +109,11 @@
"jwt-simple": "^0.5.6", "jwt-simple": "^0.5.6",
"less": "^3.13.1", "less": "^3.13.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"marked": "11.2.0", "marked": "13.0.3",
"marked-emoji": "^1.4.3", "marked-emoji": "^1.4.3",
"marked-extended-tables": "^1.1.0", "marked-extended-tables": "^1.1.0",
"marked-gfm-heading-id": "^3.2.0", "marked-gfm-heading-id": "^4.0.1",
"marked-smartypants-lite": "^1.0.2", "marked-smartypants-lite": "^1.0.3",
"markedLegacy": "npm:marked@^0.3.19", "markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.30.1", "moment": "^2.30.1",
"mongoose": "^8.9.5", "mongoose": "^8.9.5",
@@ -121,8 +121,8 @@
"nconf": "^0.12.1", "nconf": "^0.12.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-frame-component": "^5.2.7", "react-frame-component": "^4.1.3",
"react-router": "^7.1.2", "react-router": "^7.1.4",
"sanitize-filename": "1.6.3", "sanitize-filename": "1.6.3",
"superagent": "^10.1.1", "superagent": "^10.1.1",
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git" "vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
@@ -130,7 +130,7 @@
"devDependencies": { "devDependencies": {
"@stylistic/stylelint-plugin": "^3.1.1", "@stylistic/stylelint-plugin": "^3.1.1",
"babel-plugin-transform-import-meta": "^2.3.2", "babel-plugin-transform-import-meta": "^2.3.2",
"eslint": "^9.18.0", "eslint": "^9.19.0",
"eslint-plugin-jest": "^28.11.0", "eslint-plugin-jest": "^28.11.0",
"eslint-plugin-react": "^7.37.4", "eslint-plugin-react": "^7.37.4",
"globals": "^15.14.0", "globals": "^15.14.0",
@@ -138,7 +138,7 @@
"jest-expect-message": "^1.1.3", "jest-expect-message": "^1.1.3",
"jsdom-global": "^3.0.2", "jsdom-global": "^3.0.2",
"postcss-less": "^6.0.0", "postcss-less": "^6.0.0",
"stylelint": "^16.13.2", "stylelint": "^16.14.1",
"stylelint-config-recess-order": "^6.0.0", "stylelint-config-recess-order": "^6.0.0",
"stylelint-config-recommended": "^15.0.0", "stylelint-config-recommended": "^15.0.0",
"supertest": "^7.0.0" "supertest": "^7.0.0"

View File

@@ -2,7 +2,7 @@
/* eslint-disable max-lines */ /* eslint-disable max-lines */
import _ from 'lodash'; import _ from 'lodash';
import { Parser as MathParser } from 'expr-eval'; import { Parser as MathParser } from 'expr-eval';
import { marked as Marked } from 'marked'; import { marked as Marked } from 'marked';
import MarkedExtendedTables from 'marked-extended-tables'; import MarkedExtendedTables from 'marked-extended-tables';
import { markedSmartypantsLite as MarkedSmartypantsLite } from 'marked-smartypants-lite'; import { markedSmartypantsLite as MarkedSmartypantsLite } from 'marked-smartypants-lite';
import { gfmHeadingId as MarkedGFMHeadingId, resetHeadings as MarkedGFMResetHeadingIDs } from 'marked-gfm-heading-id'; import { gfmHeadingId as MarkedGFMHeadingId, resetHeadings as MarkedGFMResetHeadingIDs } from 'marked-gfm-heading-id';
@@ -173,8 +173,8 @@ const mustacheSpans = {
return `<span` + return `<span` +
`${tags.classes ? ` class="${tags.classes}"` : ''}` + `${tags.classes ? ` class="${tags.classes}"` : ''}` +
`${tags.id ? ` id="${tags.id}"` : ''}` + `${tags.id ? ` id="${tags.id}"` : ''}` +
`${tags.styles ? ` style="${tags.styles}"` : ''}` + `${tags.styles ? ` style="${Object.entries(tags.styles).map(([key, value])=>`${key}:${value};`).join(' ')}"` : ''}` +
`${tags.attributes ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` + `${tags.attributes ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` +
`>${this.parser.parseInline(token.tokens)}</span>`; // parseInline to turn child tokens into HTML `>${this.parser.parseInline(token.tokens)}</span>`; // parseInline to turn child tokens into HTML
} }
}; };
@@ -229,7 +229,7 @@ const mustacheDivs = {
return `<div` + return `<div` +
`${tags.classes ? ` class="${tags.classes}"` : ''}` + `${tags.classes ? ` class="${tags.classes}"` : ''}` +
`${tags.id ? ` id="${tags.id}"` : ''}` + `${tags.id ? ` id="${tags.id}"` : ''}` +
`${tags.styles ? ` style="${tags.styles}"` : ''}` + `${tags.styles ? ` style="${Object.entries(tags.styles).map(([key, value])=>`${key}:${value};`).join(' ')}"` : ''}` +
`${tags.attributes ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` + `${tags.attributes ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` +
`>${this.parser.parse(token.tokens)}</div>`; // parse to turn child tokens into HTML `>${this.parser.parse(token.tokens)}</div>`; // parse to turn child tokens into HTML
} }
@@ -266,18 +266,13 @@ const mustacheInjectInline = {
const text = this.parser.parseInline([token]); const text = this.parser.parseInline([token]);
const originalTags = extractHTMLStyleTags(text); const originalTags = extractHTMLStyleTags(text);
const injectedTags = token.injectedTags; const injectedTags = token.injectedTags;
const tags = { const tags = mergeHTMLTags(originalTags, injectedTags);
id : injectedTags.id || originalTags.id || null,
classes : [originalTags.classes, injectedTags.classes].join(' ').trim() || null,
styles : [originalTags.styles, injectedTags.styles].join(' ').trim() || null,
attributes : Object.assign(originalTags.attributes ?? {}, injectedTags.attributes ?? {})
};
const openingTag = /(<[^\s<>]+)[^\n<>]*(>.*)/s.exec(text); const openingTag = /(<[^\s<>]+)[^\n<>]*(>.*)/s.exec(text);
if(openingTag) { if(openingTag) {
return `${openingTag[1]}` + return `${openingTag[1]}` +
`${tags.classes ? ` class="${tags.classes}"` : ''}` + `${tags.classes ? ` class="${tags.classes}"` : ''}` +
`${tags.id ? ` id="${tags.id}"` : ''}` + `${tags.id ? ` id="${tags.id}"` : ''}` +
`${tags.styles ? ` style="${tags.styles}"` : ''}` + `${!_.isEmpty(tags.styles) ? ` style="${Object.entries(tags.styles).map(([key, value])=>`${key}:${value};`).join(' ')}"` : ''}` +
`${!_.isEmpty(tags.attributes) ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` + `${!_.isEmpty(tags.attributes) ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` +
`${openingTag[2]}`; // parse to turn child tokens into HTML `${openingTag[2]}`; // parse to turn child tokens into HTML
} }
@@ -315,18 +310,13 @@ const mustacheInjectBlock = {
const text = this.parser.parse([token]); const text = this.parser.parse([token]);
const originalTags = extractHTMLStyleTags(text); const originalTags = extractHTMLStyleTags(text);
const injectedTags = token.injectedTags; const injectedTags = token.injectedTags;
const tags = { const tags = mergeHTMLTags(originalTags, injectedTags);
id : injectedTags.id || originalTags.id || null,
classes : [originalTags.classes, injectedTags.classes].join(' ').trim() || null,
styles : [originalTags.styles, injectedTags.styles].join(' ').trim() || null,
attributes : Object.assign(originalTags.attributes ?? {}, injectedTags.attributes ?? {})
};
const openingTag = /(<[^\s<>]+)[^\n<>]*(>.*)/s.exec(text); const openingTag = /(<[^\s<>]+)[^\n<>]*(>.*)/s.exec(text);
if(openingTag) { if(openingTag) {
return `${openingTag[1]}` + return `${openingTag[1]}` +
`${tags.classes ? ` class="${tags.classes}"` : ''}` + `${tags.classes ? ` class="${tags.classes}"` : ''}` +
`${tags.id ? ` id="${tags.id}"` : ''}` + `${tags.id ? ` id="${tags.id}"` : ''}` +
`${tags.styles ? ` style="${tags.styles}"` : ''}` + `${!_.isEmpty(tags.styles) ? ` style="${Object.entries(tags.styles).map(([key, value])=>`${key}:${value};`).join(' ')}"` : ''}` +
`${!_.isEmpty(tags.attributes) ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` + `${!_.isEmpty(tags.attributes) ? ` ${Object.entries(tags.attributes).map(([key, value])=>`${key}="${value}"`).join(' ')}` : ''}` +
`${openingTag[2]}`; // parse to turn child tokens into HTML `${openingTag[2]}`; // parse to turn child tokens into HTML
} }
@@ -871,15 +861,20 @@ const processStyleTags = (string)=>{
const index = attr.indexOf('='); const index = attr.indexOf('=');
let [key, value] = [attr.substring(0, index), attr.substring(index + 1)]; let [key, value] = [attr.substring(0, index), attr.substring(index + 1)];
value = value.replace(/"/g, ''); value = value.replace(/"/g, '');
obj[key] = value; obj[key.trim()] = value.trim();
return obj; return obj;
}, {}) || null; }, {}) || null;
const styles = tags?.length ? tags.map((tag)=>tag.replace(/:"?([^"]*)"?/g, ':$1;').trim()).join(' ') : null; const styles = tags?.length ? tags.reduce((styleObj, style) => {
const index = style.indexOf(':');
const [key, value] = [style.substring(0, index), style.substring(index + 1)];
styleObj[key.trim()] = value.replace(/"?([^"]*)"?/g, '$1').trim();
return styleObj;
}, {}) : null;
return { return {
id : id, id : id,
classes : classes, classes : classes,
styles : styles, styles : _.isEmpty(styles) ? null : styles,
attributes : _.isEmpty(attributes) ? null : attributes attributes : _.isEmpty(attributes) ? null : attributes
}; };
}; };
@@ -889,25 +884,40 @@ const extractHTMLStyleTags = (htmlString)=>{
const firstElementOnly = htmlString.split('>')[0]; const firstElementOnly = htmlString.split('>')[0];
const id = firstElementOnly.match(/id="([^"]*)"/)?.[1] || null; const id = firstElementOnly.match(/id="([^"]*)"/)?.[1] || null;
const classes = firstElementOnly.match(/class="([^"]*)"/)?.[1] || null; const classes = firstElementOnly.match(/class="([^"]*)"/)?.[1] || null;
const styles = firstElementOnly.match(/style="([^"]*)"/)?.[1] || null; const styles = firstElementOnly.match(/style="([^"]*)"/)?.[1]
?.split(';').reduce((styleObj, style) => {
if (style.trim() === '') return styleObj;
const index = style.indexOf(':');
const [key, value] = [style.substring(0, index), style.substring(index + 1)];
styleObj[key.trim()] = value.trim();
return styleObj;
}, {}) || null;
const attributes = firstElementOnly.match(/[a-zA-Z]+="[^"]*"/g) const attributes = firstElementOnly.match(/[a-zA-Z]+="[^"]*"/g)
?.filter((attr)=>!attr.startsWith('class="') && !attr.startsWith('style="') && !attr.startsWith('id="')) ?.filter((attr)=>!attr.startsWith('class="') && !attr.startsWith('style="') && !attr.startsWith('id="'))
.reduce((obj, attr)=>{ .reduce((obj, attr)=>{
const index = attr.indexOf('='); const index = attr.indexOf('=');
let [key, value] = [attr.substring(0, index), attr.substring(index + 1)]; let [key, value] = [attr.substring(0, index), attr.substring(index + 1)];
value = value.replace(/"/g, ''); obj[key.trim()] = value.replace(/"/g, '');
obj[key] = value;
return obj; return obj;
}, {}) || null; }, {}) || null;
return { return {
id : id, id : id,
classes : classes, classes : classes,
styles : styles, styles : _.isEmpty(styles) ? null : styles,
attributes : _.isEmpty(attributes) ? null : attributes attributes : _.isEmpty(attributes) ? null : attributes
}; };
}; };
const mergeHTMLTags = (originalTags, newTags) => {
return {
id : newTags.id || originalTags.id || null,
classes : [originalTags.classes, newTags.classes].join(' ').trim() || null,
styles : Object.assign(originalTags.styles ?? {}, newTags.styles ?? {}),
attributes : Object.assign(originalTags.attributes ?? {}, newTags.attributes ?? {})
};
};
const globalVarsList = {}; const globalVarsList = {};
let varsQueue = []; let varsQueue = [];
let globalPageNumber = 0; let globalPageNumber = 0;

View File

@@ -1,5 +1,5 @@
const stylelint = require('stylelint'); import stylelint from 'stylelint';
const { isNumber } = require('stylelint/lib/utils/validateTypes.cjs'); import { isNumber } from 'stylelint/lib/utils/validateTypes.mjs';
const { report, ruleMessages, validateOptions } = stylelint.utils; const { report, ruleMessages, validateOptions } = stylelint.utils;
const ruleName = 'naturalcrit/declaration-block-multi-line-min-declarations'; const ruleName = 'naturalcrit/declaration-block-multi-line-min-declarations';
@@ -7,9 +7,8 @@ const messages = ruleMessages(ruleName, {
expected : (decls)=>`Rule with ${decls} declaration${decls == 1 ? '' : 's'} should be single line`, expected : (decls)=>`Rule with ${decls} declaration${decls == 1 ? '' : 's'} should be single line`,
}); });
const ruleFunction = (primaryOption, secondaryOptionObject, context)=>{
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) { return (postcssRoot, postcssResult)=>{
return function lint(postcssRoot, postcssResult) {
const validOptions = validateOptions( const validOptions = validateOptions(
postcssResult, postcssResult,
@@ -20,26 +19,23 @@ module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOpti
} }
); );
if(!validOptions) { //If the options are invalid, don't lint if(!validOptions) //If the options are invalid, don't lint
return; return;
}
const isAutoFixing = Boolean(context.fix); const isAutoFixing = Boolean(context.fix);
postcssRoot.walkRules((rule)=>{ //Iterate CSS rules postcssRoot.walkRules((rule)=>{ //Iterate CSS rules
//Apply rule only if all children are decls (no further nested rules) //Apply rule only if all children are decls (no further nested rules)
if(rule.nodes.length > primaryOption || !rule.nodes.every((node)=>node.type === 'decl')) { if(rule.nodes.length > primaryOption || !rule.nodes.every((node)=>node.type === 'decl'))
return; return;
}
//Ignore if already one line //Ignore if already one line
if(!rule.nodes.some((node)=>node.raws.before.includes('\n')) && !rule.raws.after.includes('\n')) if(!rule.nodes.some((node)=>node.raws.before.includes('\n')) && !rule.raws.after.includes('\n'))
return; return;
if(isAutoFixing) { //We are in “fix” mode if(isAutoFixing) { //We are in “fix” mode
rule.each((decl)=>{ rule.each((decl)=>decl.raws.before = ' ');
decl.raws.before = ' ';
});
rule.raws.after = ' '; rule.raws.after = ' ';
} else { } else {
report({ report({
@@ -52,7 +48,9 @@ module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOpti
} }
}); });
}; };
}); };
module.exports.ruleName = ruleName; ruleFunction.ruleName = ruleName;
module.exports.messages = messages; ruleFunction.messages = messages;
export default stylelint.createPlugin(ruleName, ruleFunction);

View File

@@ -1,32 +1,29 @@
const stylelint = require('stylelint'); import stylelint from 'stylelint';
const { report, ruleMessages, validateOptions } = stylelint.utils; const { report, ruleMessages, validateOptions } = stylelint.utils;
const ruleName = 'naturalcrit/declaration-colon-align'; const ruleName = 'naturalcrit/declaration-colon-align';
const messages = ruleMessages(ruleName, { const messages = ruleMessages(ruleName, {
expected : (rule)=>`Expected colons aligned within rule "${rule}"`, expected : (rule)=>`Expected colons aligned within rule "${rule}"`,
}); });
const ruleFunction = (primaryOption, secondaryOptionObject, context)=>{
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) { return (postcssRoot, postcssResult)=>{
return function lint(postcssRoot, postcssResult) {
const validOptions = validateOptions( const validOptions = validateOptions(
postcssResult, postcssResult,
ruleName, ruleName,
{ {
actual : primaryOption, actual : primaryOption,
possible : [ possible : [true, false]
true,
false
]
} }
); );
if(!validOptions) { //If the options are invalid, don't lint if(!validOptions) // If the options are invalid, don't lint
return; return;
}
const isAutoFixing = Boolean(context.fix); const isAutoFixing = Boolean(context.fix);
postcssRoot.walkRules((rule)=>{ //Iterate CSS rules
postcssRoot.walkRules((rule)=>{ // Iterate CSS rules
let maxColonPos = 0; let maxColonPos = 0;
let misaligned = false; let misaligned = false;
@@ -36,33 +33,37 @@ module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOpti
return; return;
const colonPos = declaration.prop.length + declaration.raws.between.indexOf(':'); const colonPos = declaration.prop.length + declaration.raws.between.indexOf(':');
if(maxColonPos > 0 && colonPos != maxColonPos) {
if(maxColonPos > 0 && colonPos != maxColonPos)
misaligned = true; misaligned = true;
}
maxColonPos = Math.max(maxColonPos, colonPos); maxColonPos = Math.max(maxColonPos, colonPos);
}); });
if(misaligned) { if(!misaligned)
if(isAutoFixing) { //We are in “fix” mode return;
rule.each((declaration)=>{
if(declaration.type != 'decl')
return;
declaration.raws.between = `${' '.repeat(maxColonPos - declaration.prop.length)}:${declaration.raws.between.split(':')[1]}`; if(isAutoFixing) { // We are in “fix” mode
}); rule.each((declaration)=>{
} else { //We are in “report only” mode if(declaration.type != 'decl')
report({ return;
ruleName,
result : postcssResult, declaration.raws.between = `${' '.repeat(maxColonPos - declaration.prop.length)}:${declaration.raws.between.split(':')[1]}`;
message : messages.expected(rule.selector), // Build the reported message });
node : rule, // Specify the reported node } else { // We are in “report only” mode
word : rule.selector, // Which exact word caused the error? This positions the error properly report({
}); ruleName,
} result : postcssResult,
message : messages.expected(rule.selector), // Build the reported message
node : rule, // Specify the reported node
word : rule.selector, // Which exact word caused the error? This positions the error properly
});
} }
}); });
}; };
}); };
module.exports.ruleName = ruleName; ruleFunction.ruleName = ruleName;
module.exports.messages = messages; ruleFunction.messages = messages;
export default stylelint.createPlugin(ruleName, ruleFunction);

View File

@@ -1,5 +1,5 @@
const stylelint = require('stylelint'); import stylelint from 'stylelint';
const { isNumber } = require('stylelint/lib/utils/validateTypes.cjs'); import { isNumber } from 'stylelint/lib/utils/validateTypes.mjs';
const { report, ruleMessages, validateOptions } = stylelint.utils; const { report, ruleMessages, validateOptions } = stylelint.utils;
const ruleName = 'naturalcrit/declaration-colon-min-space-before'; const ruleName = 'naturalcrit/declaration-colon-min-space-before';
@@ -7,9 +7,8 @@ const messages = ruleMessages(ruleName, {
expected : (num)=>`Expected at least ${num} space${num == 1 ? '' : 's'} before ":"` expected : (num)=>`Expected at least ${num} space${num == 1 ? '' : 's'} before ":"`
}); });
const ruleFunction = (primaryOption, secondaryOptionObject, context)=>{
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) { return (postcssRoot, postcssResult)=>{
return function lint(postcssRoot, postcssResult) {
const validOptions = validateOptions( const validOptions = validateOptions(
postcssResult, postcssResult,
@@ -30,9 +29,9 @@ module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOpti
const between = decl.raws.between; const between = decl.raws.between;
const colonIndex = between.indexOf(':'); const colonIndex = between.indexOf(':');
if(between.slice(0, colonIndex).length >= primaryOption) { if(between.slice(0, colonIndex).length >= primaryOption)
return; return;
}
if(isAutoFixing) { //We are in “fix” mode if(isAutoFixing) { //We are in “fix” mode
decl.raws.between = between.slice(0, colonIndex).replace(/\s*$/, ' '.repeat(primaryOption)) + between.slice(colonIndex); decl.raws.between = between.slice(0, colonIndex).replace(/\s*$/, ' '.repeat(primaryOption)) + between.slice(colonIndex);
} else { } else {
@@ -46,7 +45,9 @@ module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOpti
} }
}); });
}; };
}); };
module.exports.ruleName = ruleName; ruleFunction.ruleName = ruleName;
module.exports.messages = messages; ruleFunction.messages = messages;
export default stylelint.createPlugin(ruleName, ruleFunction);

View File

@@ -300,7 +300,7 @@ describe('Injection: When an injection tag follows an element', ()=>{
it('Renders a span "text" with its own styles, appended with injected styles', function() { it('Renders a span "text" with its own styles, appended with injected styles', function() {
const source = '{{color:blue,height:10px text}}{width:10px,color:red}'; const source = '{{color:blue,height:10px text}}{width:10px,color:red}';
const rendered = Markdown.render(source); const rendered = Markdown.render(source);
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="color:blue; height:10px; width:10px; color:red;">text</span>'); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="color:red; height:10px; width:10px;">text</span>');
}); });
it('Renders a span "text" with its own classes, appended with injected classes', function() { it('Renders a span "text" with its own classes, appended with injected classes', function() {
@@ -429,7 +429,7 @@ describe('Injection: When an injection tag follows an element', ()=>{
}} }}
{width:10px,color:red}`; {width:10px,color:red}`;
const rendered = Markdown.render(source).trimReturns(); const rendered = Markdown.render(source).trimReturns();
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" style="color:blue; height:10px; width:10px; color:red;"><p>text</p></div>'); expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" style="color:red; height:10px; width:10px;"><p>text</p></div>');
}); });
it('Renders a span "text" with its own classes, appended with injected classes', function() { it('Renders a span "text" with its own classes, appended with injected classes', function() {