mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2025-12-27 20:12:40 +00:00
Merge branch 'master' into issue_3206
This commit is contained in:
@@ -1,48 +1,48 @@
|
||||
{
|
||||
"extends": [
|
||||
"stylelint-config-recess-order",
|
||||
"stylelint-config-recommended"],
|
||||
"plugins": [
|
||||
"@stylistic/stylelint-plugin",
|
||||
"./stylelint_plugins/declaration-colon-align.js",
|
||||
"./stylelint_plugins/declaration-colon-min-space-before",
|
||||
"./stylelint_plugins/declaration-block-multi-line-min-declarations"
|
||||
],
|
||||
"customSyntax": "postcss-less",
|
||||
"rules": {
|
||||
"no-descending-specificity" : null,
|
||||
"at-rule-no-unknown" : null,
|
||||
"function-no-unknown" : null,
|
||||
"font-family-no-missing-generic-family-keyword" : null,
|
||||
"font-weight-notation" : "named-where-possible",
|
||||
"font-family-name-quotes" : "always-unless-keyword",
|
||||
"@stylistic/indentation" : "tab",
|
||||
"no-duplicate-selectors" : true,
|
||||
"@stylistic/color-hex-case" : "upper",
|
||||
"color-hex-length" : "long",
|
||||
"@stylistic/selector-combinator-space-after" : "always",
|
||||
"@stylistic/selector-combinator-space-before" : "always",
|
||||
"@stylistic/selector-attribute-operator-space-before" : "never",
|
||||
"@stylistic/selector-attribute-operator-space-after" : "never",
|
||||
"@stylistic/selector-attribute-brackets-space-inside" : "never",
|
||||
"selector-attribute-quotes" : "always",
|
||||
"selector-pseudo-element-colon-notation" : "double",
|
||||
"@stylistic/selector-pseudo-class-parentheses-space-inside" : "never",
|
||||
"@stylistic/block-opening-brace-space-before" : "always",
|
||||
"naturalcrit/declaration-colon-min-space-before" : 1,
|
||||
"@stylistic/declaration-block-trailing-semicolon" : "always",
|
||||
"@stylistic/declaration-colon-space-after" : "always",
|
||||
"@stylistic/number-leading-zero" : "always",
|
||||
"function-url-quotes" : ["always", { "except": ["empty"] }],
|
||||
"function-url-scheme-disallowed-list" : ["data","http"],
|
||||
"comment-whitespace-inside" : "always",
|
||||
"@stylistic/string-quotes" : "single",
|
||||
"@stylistic/media-feature-range-operator-space-before" : "always",
|
||||
"@stylistic/media-feature-range-operator-space-after" : "always",
|
||||
"@stylistic/media-feature-parentheses-space-inside" : "never",
|
||||
"@stylistic/media-feature-colon-space-before" : "always",
|
||||
"@stylistic/media-feature-colon-space-after" : "always",
|
||||
"naturalcrit/declaration-colon-align" : true,
|
||||
"naturalcrit/declaration-block-multi-line-min-declarations": 1
|
||||
}
|
||||
"extends": [
|
||||
"stylelint-config-recess-order",
|
||||
"stylelint-config-recommended"],
|
||||
"plugins": [
|
||||
"@stylistic/stylelint-plugin",
|
||||
"./stylelint_plugins/declaration-colon-align.js",
|
||||
"./stylelint_plugins/declaration-colon-min-space-before",
|
||||
"./stylelint_plugins/declaration-block-multi-line-min-declarations"
|
||||
],
|
||||
"customSyntax": "postcss-less",
|
||||
"rules": {
|
||||
"no-descending-specificity" : null,
|
||||
"at-rule-no-unknown" : null,
|
||||
"function-no-unknown" : null,
|
||||
"font-family-no-missing-generic-family-keyword" : null,
|
||||
"font-weight-notation" : "named-where-possible",
|
||||
"font-family-name-quotes" : "always-unless-keyword",
|
||||
"@stylistic/indentation" : "tab",
|
||||
"no-duplicate-selectors" : true,
|
||||
"@stylistic/color-hex-case" : "upper",
|
||||
"color-hex-length" : "long",
|
||||
"@stylistic/selector-combinator-space-after" : "always",
|
||||
"@stylistic/selector-combinator-space-before" : "always",
|
||||
"@stylistic/selector-attribute-operator-space-before" : "never",
|
||||
"@stylistic/selector-attribute-operator-space-after" : "never",
|
||||
"@stylistic/selector-attribute-brackets-space-inside" : "never",
|
||||
"selector-attribute-quotes" : "always",
|
||||
"selector-pseudo-element-colon-notation" : "double",
|
||||
"@stylistic/selector-pseudo-class-parentheses-space-inside" : "never",
|
||||
"@stylistic/block-opening-brace-space-before" : "always",
|
||||
"naturalcrit/declaration-colon-min-space-before" : 1,
|
||||
"@stylistic/declaration-block-trailing-semicolon" : "always",
|
||||
"@stylistic/declaration-colon-space-after" : "always",
|
||||
"@stylistic/number-leading-zero" : "always",
|
||||
"function-url-quotes" : ["always", { "except": ["empty"] }],
|
||||
"function-url-scheme-disallowed-list" : ["data","http"],
|
||||
"comment-whitespace-inside" : "always",
|
||||
"@stylistic/string-quotes" : "single",
|
||||
"@stylistic/media-feature-range-operator-space-before" : "always",
|
||||
"@stylistic/media-feature-range-operator-space-after" : "always",
|
||||
"@stylistic/media-feature-parentheses-space-inside" : "never",
|
||||
"@stylistic/media-feature-colon-space-before" : "always",
|
||||
"@stylistic/media-feature-colon-space-after" : "always",
|
||||
"naturalcrit/declaration-colon-align" : true,
|
||||
"naturalcrit/declaration-block-multi-line-min-declarations" : 1
|
||||
}
|
||||
}
|
||||
|
||||
94
changelog.md
94
changelog.md
@@ -77,14 +77,100 @@ pre {
|
||||
}
|
||||
|
||||
.varSyntaxTable th:first-of-type {
|
||||
width:6cm;
|
||||
width:6cm;
|
||||
}
|
||||
|
||||
.page .exampleTable td,th {
|
||||
border:1px dashed #00000030;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## changelog
|
||||
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
|
||||
|
||||
{{taskList
|
||||
@@ -131,6 +217,8 @@ Fixes issue [#3744](https://github.com/naturalcrit/homebrewery/issues/3744)
|
||||
* [x] Multiple code refactors, cleanups, and security fixes
|
||||
}}
|
||||
|
||||
\page
|
||||
|
||||
### Saturday 10/12/2024 - v3.16.0
|
||||
|
||||
{{taskList
|
||||
@@ -2053,4 +2141,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
|
||||
@@ -17,10 +17,9 @@ const dedent = require('dedent-tabs').default;
|
||||
const { printCurrentBrew } = require('../../../shared/helpers.js');
|
||||
|
||||
import HeaderNav from './headerNav/headerNav.jsx';
|
||||
|
||||
import { safeHTML } from './safeHTML.js';
|
||||
|
||||
|
||||
const PAGEBREAK_REGEX_V3 = /^(?=\\page(?: *{[^\n{}]*})?$)/m;
|
||||
const PAGE_HEIGHT = 1056;
|
||||
|
||||
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>;
|
||||
};
|
||||
@@ -126,7 +125,7 @@ const BrewRenderer = (props)=>{
|
||||
if(props.renderer == 'legacy') {
|
||||
rawPages = props.text.split('\\page');
|
||||
} else {
|
||||
rawPages = props.text.split(/^\\page$/gm);
|
||||
rawPages = props.text.split(PAGEBREAK_REGEX_V3);
|
||||
}
|
||||
|
||||
const handlePageVisibilityChange = (pageNum, isVisible, isCenter)=>{
|
||||
@@ -173,20 +172,34 @@ const BrewRenderer = (props)=>{
|
||||
|
||||
const renderPage = (pageText, index)=>{
|
||||
|
||||
const styles = {
|
||||
let styles = {
|
||||
...(!displayOptions.pageShadows ? { boxShadow: 'none' } : {})
|
||||
// Add more conditions as needed
|
||||
};
|
||||
let classes = 'page';
|
||||
let attributes = {};
|
||||
|
||||
if(props.renderer == 'legacy') {
|
||||
const html = MarkdownLegacy.render(pageText);
|
||||
|
||||
return <BrewPage className='page phb' index={index} key={index} contents={html} style={styles} onVisibilityChange={handlePageVisibilityChange} />;
|
||||
} 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 \n\\column\n `; //Artificial column break at page end to emulate column-fill:auto (until `wide` is used, when column-fill:balance will reappear)
|
||||
const html = Markdown.render(pageText, index);
|
||||
|
||||
return <BrewPage className='page' index={index} key={index} contents={html} style={styles} onVisibilityChange={handlePageVisibilityChange} />;
|
||||
return <BrewPage className={classes} index={index} key={index} contents={html} style={styles} attributes={attributes} onVisibilityChange={handlePageVisibilityChange} />;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
require('./notificationPopup.less');
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import request from '../../utils/request-middleware.js';
|
||||
import Markdown from 'naturalcrit/markdown.js';
|
||||
|
||||
import Dialog from '../../../components/dialog.jsx';
|
||||
|
||||
@@ -40,11 +41,10 @@ const NotificationPopup = ()=>{
|
||||
|
||||
const renderNotificationsList = ()=>{
|
||||
if(error) return <div className='error'>{error}</div>;
|
||||
|
||||
return notifications.map((notification)=>(
|
||||
<li key={notification.dismissKey} >
|
||||
<em>{notification.title}</em><br />
|
||||
<p dangerouslySetInnerHTML={{ __html: notification.text }}></p>
|
||||
<p dangerouslySetInnerHTML={{ __html: Markdown.render(notification.text) }}></p>
|
||||
</li>
|
||||
));
|
||||
};
|
||||
|
||||
@@ -48,17 +48,46 @@
|
||||
}
|
||||
ul {
|
||||
margin-top : 15px;
|
||||
font-size : 0.8em;
|
||||
font-size : 0.9em;
|
||||
list-style-position : outside;
|
||||
list-style-type : disc;
|
||||
li {
|
||||
margin-top : 1.4em;
|
||||
font-size : 0.8em;
|
||||
line-height : 1.4em;
|
||||
em {
|
||||
text-transform:capitalize;
|
||||
font-weight : 800;
|
||||
padding-left : 1em;
|
||||
margin-top : 1.5em;
|
||||
font-size : 0.9em;
|
||||
line-height : 1.5em;
|
||||
em {
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@ const MetadataEditor = require('./metadataEditor/metadataEditor.jsx');
|
||||
|
||||
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`
|
||||
/*=======--- Example CSS styling ---=======*/
|
||||
/* Any CSS here will apply to your document! */
|
||||
@@ -126,15 +127,15 @@ const Editor = createClass({
|
||||
},
|
||||
|
||||
updateCurrentCursorPage : function(cursor) {
|
||||
const lines = this.props.brew.text.split('\n').slice(0, cursor.line + 1);
|
||||
const pageRegex = this.props.brew.renderer == 'V3' ? /^\\page$/ : /\\page/;
|
||||
const lines = this.props.brew.text.split('\n').slice(1, cursor.line + 1);
|
||||
const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
|
||||
const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1);
|
||||
this.props.onCursorPageChange(currentPage);
|
||||
},
|
||||
|
||||
updateCurrentViewPage : function(topScrollLine) {
|
||||
const lines = this.props.brew.text.split('\n').slice(0, topScrollLine + 1);
|
||||
const pageRegex = this.props.brew.renderer == 'V3' ? /^\\page$/ : /\\page/;
|
||||
const lines = this.props.brew.text.split('\n').slice(1, topScrollLine + 1);
|
||||
const pageRegex = this.props.brew.renderer == 'V3' ? PAGEBREAK_REGEX_V3 : /\\page/;
|
||||
const currentPage = lines.reduce((count, line)=>count + (pageRegex.test(line) ? 1 : 0), 1);
|
||||
this.props.onViewPageChange(currentPage);
|
||||
},
|
||||
@@ -174,7 +175,7 @@ const Editor = createClass({
|
||||
|
||||
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)=>{
|
||||
|
||||
@@ -190,7 +191,10 @@ const Editor = createClass({
|
||||
|
||||
// Styling for \page breaks
|
||||
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'
|
||||
codeMirror.addLineClass(lineNumber, 'background', 'pageLine');
|
||||
@@ -199,8 +203,6 @@ const Editor = createClass({
|
||||
textContent : editorPageCount
|
||||
});
|
||||
codeMirror.setBookmark({ line: lineNumber, ch: line.length }, pageCountElement);
|
||||
|
||||
editorPageCount += 1;
|
||||
};
|
||||
|
||||
// New Codemirror styling for V3 renderer
|
||||
@@ -358,7 +360,7 @@ const Editor = createClass({
|
||||
if(!this.isText() || isJumping)
|
||||
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 targetLine = textString.match('\n') ? textString.split('\n').length - 1 : -1;
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ const dedent = require('dedent-tabs').default;
|
||||
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('');
|
||||
const escape = (text = '')=>{
|
||||
return text.split('').map((char)=>`&#${char.charCodeAt(0)};`).join('');
|
||||
};
|
||||
|
||||
//001-050 : Brew errors
|
||||
|
||||
116
package-lock.json
generated
116
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "homebrewery",
|
||||
"version": "3.16.1",
|
||||
"version": "3.17.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "homebrewery",
|
||||
"version": "3.16.1",
|
||||
"version": "3.17.0",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -23,7 +23,7 @@
|
||||
"cors": "^2.8.5",
|
||||
"create-react-class": "^15.7.0",
|
||||
"dedent-tabs": "^0.10.3",
|
||||
"dompurify": "^3.2.3",
|
||||
"dompurify": "^3.2.4",
|
||||
"expr-eval": "^2.0.2",
|
||||
"express": "^4.21.2",
|
||||
"express-async-handler": "^1.2.0",
|
||||
@@ -34,20 +34,20 @@
|
||||
"jwt-simple": "^0.5.6",
|
||||
"less": "^3.13.1",
|
||||
"lodash": "^4.17.21",
|
||||
"marked": "11.2.0",
|
||||
"marked": "13.0.3",
|
||||
"marked-emoji": "^1.4.3",
|
||||
"marked-extended-tables": "^1.1.0",
|
||||
"marked-gfm-heading-id": "^3.2.0",
|
||||
"marked-smartypants-lite": "^1.0.2",
|
||||
"marked-gfm-heading-id": "^4.0.1",
|
||||
"marked-smartypants-lite": "^1.0.3",
|
||||
"markedLegacy": "npm:marked@^0.3.19",
|
||||
"moment": "^2.30.1",
|
||||
"mongoose": "^8.9.5",
|
||||
"mongoose": "^8.9.6",
|
||||
"nanoid": "5.0.9",
|
||||
"nconf": "^0.12.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-frame-component": "^4.1.3",
|
||||
"react-router": "^7.1.3",
|
||||
"react-router": "^7.1.5",
|
||||
"sanitize-filename": "1.6.3",
|
||||
"superagent": "^10.1.1",
|
||||
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
||||
@@ -3837,16 +3837,6 @@
|
||||
"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": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
|
||||
@@ -5323,9 +5313,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.3.tgz",
|
||||
"integrity": "sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA==",
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz",
|
||||
"integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==",
|
||||
"license": "(MPL-2.0 OR Apache-2.0)",
|
||||
"optionalDependencies": {
|
||||
"@types/trusted-types": "^2.0.7"
|
||||
}
|
||||
@@ -6337,13 +6328,6 @@
|
||||
"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": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
@@ -6517,20 +6501,6 @@
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"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": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
@@ -9819,9 +9789,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "11.2.0",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz",
|
||||
"integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==",
|
||||
"version": "13.0.3",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz",
|
||||
"integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
@@ -9847,24 +9817,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/marked-gfm-heading-id": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-3.2.0.tgz",
|
||||
"integrity": "sha512-Xfxpr5lXLDLY10XqzSCA9l2dDaiabQUgtYM9hw8yunyVsB/xYBRpiic6BOiY/EAJw1ik1eWr1ET1HKOAPZBhXg==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-4.1.1.tgz",
|
||||
"integrity": "sha512-EeQZieAQmsI6c2tWLx0ETd0VjPwLV8qi+HT0dIsfVMERm0rCIuXfRvZXJbo1SgUi++lmuR1LVY+QzgNiLNvVpw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"github-slugger": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"marked": ">=4 <13"
|
||||
"marked": ">=13 <16"
|
||||
}
|
||||
},
|
||||
"node_modules/marked-smartypants-lite": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/marked-smartypants-lite/-/marked-smartypants-lite-1.0.2.tgz",
|
||||
"integrity": "sha512-cEANts+s3+gnTzXPvPT2z4V8NfbMEL9QooKUviug0DkaKkXQWrUwDAmFnQAkLSJCw2BQcD8YPDyxu0HJ3mg36w==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/marked-smartypants-lite/-/marked-smartypants-lite-1.0.3.tgz",
|
||||
"integrity": "sha512-OOL8cjFog8KtgUFpkihRu6G42Dz2QPOU4k2xfKmMJ0CdoX+BHBDmdesHUdoQKM0mlwTsRSU3shpMeM/LWuUokg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"marked": ">=4 <12"
|
||||
"marked": ">=4 <16"
|
||||
}
|
||||
},
|
||||
"node_modules/markedLegacy": {
|
||||
@@ -10217,9 +10187,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/mongoose": {
|
||||
"version": "8.9.5",
|
||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.9.5.tgz",
|
||||
"integrity": "sha512-SPhOrgBm0nKV3b+IIHGqpUTOmgVL5Z3OO9AwkFEmvOZznXTvplbomstCnPOGAyungtRXE5pJTgKpKcZTdjeESg==",
|
||||
"version": "8.9.6",
|
||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.9.6.tgz",
|
||||
"integrity": "sha512-ipLvXwNPVuuuq5H3lnSD0lpaRH3DlCoC6emnMVJvweTwxU29uxDJWxMsNpERDQt8JMvYF1HGVuTK+Id2BlQLCA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bson": "^6.10.1",
|
||||
"kareem": "2.6.3",
|
||||
@@ -10365,13 +10336,6 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"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": {
|
||||
"version": "5.0.9",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz",
|
||||
@@ -11646,9 +11610,10 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.3.tgz",
|
||||
"integrity": "sha512-EezYymLY6Guk/zLQ2vRA8WvdUhWFEj5fcE3RfWihhxXBW7+cd1LsIiA3lmx+KCmneAGQuyBv820o44L2+TtkSA==",
|
||||
"version": "7.1.5",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.5.tgz",
|
||||
"integrity": "sha512-8BUF+hZEU4/z/JD201yK6S+UYhsf58bzYIDq2NS1iGpwxSXDu7F+DeGSkIXMFBuHZB21FSiCzEcUb18cQNdRkA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/cookie": "^0.6.0",
|
||||
"cookie": "^1.0.1",
|
||||
@@ -14429,25 +14394,6 @@
|
||||
"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": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
|
||||
|
||||
14
package.json
14
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "homebrewery",
|
||||
"description": "Create authentic looking D&D homebrews using only markdown",
|
||||
"version": "3.16.1",
|
||||
"version": "3.17.0",
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"npm": "^10.2.x",
|
||||
@@ -98,7 +98,7 @@
|
||||
"cors": "^2.8.5",
|
||||
"create-react-class": "^15.7.0",
|
||||
"dedent-tabs": "^0.10.3",
|
||||
"dompurify": "^3.2.3",
|
||||
"dompurify": "^3.2.4",
|
||||
"expr-eval": "^2.0.2",
|
||||
"express": "^4.21.2",
|
||||
"express-async-handler": "^1.2.0",
|
||||
@@ -109,20 +109,20 @@
|
||||
"jwt-simple": "^0.5.6",
|
||||
"less": "^3.13.1",
|
||||
"lodash": "^4.17.21",
|
||||
"marked": "11.2.0",
|
||||
"marked": "13.0.3",
|
||||
"marked-emoji": "^1.4.3",
|
||||
"marked-extended-tables": "^1.1.0",
|
||||
"marked-gfm-heading-id": "^3.2.0",
|
||||
"marked-smartypants-lite": "^1.0.2",
|
||||
"marked-gfm-heading-id": "^4.0.1",
|
||||
"marked-smartypants-lite": "^1.0.3",
|
||||
"markedLegacy": "npm:marked@^0.3.19",
|
||||
"moment": "^2.30.1",
|
||||
"mongoose": "^8.9.5",
|
||||
"mongoose": "^8.9.6",
|
||||
"nanoid": "5.0.9",
|
||||
"nconf": "^0.12.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-frame-component": "^4.1.3",
|
||||
"react-router": "^7.1.3",
|
||||
"react-router": "^7.1.5",
|
||||
"sanitize-filename": "1.6.3",
|
||||
"superagent": "^10.1.1",
|
||||
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const stylelint = require('stylelint');
|
||||
const { isNumber } = require('stylelint/lib/utils/validateTypes.cjs');
|
||||
import stylelint from 'stylelint';
|
||||
import { isNumber } from 'stylelint/lib/utils/validateTypes.mjs';
|
||||
|
||||
const { report, ruleMessages, validateOptions } = stylelint.utils;
|
||||
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`,
|
||||
});
|
||||
|
||||
|
||||
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) {
|
||||
return function lint(postcssRoot, postcssResult) {
|
||||
const ruleFunction = (primaryOption, secondaryOptionObject, context)=>{
|
||||
return (postcssRoot, postcssResult)=>{
|
||||
|
||||
const validOptions = validateOptions(
|
||||
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;
|
||||
}
|
||||
|
||||
const isAutoFixing = Boolean(context.fix);
|
||||
|
||||
postcssRoot.walkRules((rule)=>{ //Iterate CSS 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;
|
||||
}
|
||||
|
||||
//Ignore if already one line
|
||||
if(!rule.nodes.some((node)=>node.raws.before.includes('\n')) && !rule.raws.after.includes('\n'))
|
||||
return;
|
||||
|
||||
if(isAutoFixing) { //We are in “fix” mode
|
||||
rule.each((decl)=>{
|
||||
decl.raws.before = ' ';
|
||||
});
|
||||
rule.each((decl)=>decl.raws.before = ' ');
|
||||
rule.raws.after = ' ';
|
||||
} else {
|
||||
report({
|
||||
@@ -52,7 +48,9 @@ module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOpti
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.ruleName = ruleName;
|
||||
module.exports.messages = messages;
|
||||
ruleFunction.ruleName = ruleName;
|
||||
ruleFunction.messages = messages;
|
||||
|
||||
export default stylelint.createPlugin(ruleName, ruleFunction);
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
const stylelint = require('stylelint');
|
||||
|
||||
import stylelint from 'stylelint';
|
||||
const { report, ruleMessages, validateOptions } = stylelint.utils;
|
||||
|
||||
const ruleName = 'naturalcrit/declaration-colon-align';
|
||||
const messages = ruleMessages(ruleName, {
|
||||
expected : (rule)=>`Expected colons aligned within rule "${rule}"`,
|
||||
});
|
||||
|
||||
|
||||
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) {
|
||||
return function lint(postcssRoot, postcssResult) {
|
||||
const ruleFunction = (primaryOption, secondaryOptionObject, context)=>{
|
||||
return (postcssRoot, postcssResult)=>{
|
||||
|
||||
const validOptions = validateOptions(
|
||||
postcssResult,
|
||||
ruleName,
|
||||
{
|
||||
actual : primaryOption,
|
||||
possible : [
|
||||
true,
|
||||
false
|
||||
]
|
||||
possible : [true, false]
|
||||
}
|
||||
);
|
||||
|
||||
if(!validOptions) { //If the options are invalid, don't lint
|
||||
if(!validOptions) // If the options are invalid, don't lint
|
||||
return;
|
||||
}
|
||||
|
||||
const isAutoFixing = Boolean(context.fix);
|
||||
postcssRoot.walkRules((rule)=>{ //Iterate CSS rules
|
||||
|
||||
postcssRoot.walkRules((rule)=>{ // Iterate CSS rules
|
||||
|
||||
let maxColonPos = 0;
|
||||
let misaligned = false;
|
||||
@@ -36,33 +33,37 @@ module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOpti
|
||||
return;
|
||||
|
||||
const colonPos = declaration.prop.length + declaration.raws.between.indexOf(':');
|
||||
if(maxColonPos > 0 && colonPos != maxColonPos) {
|
||||
|
||||
if(maxColonPos > 0 && colonPos != maxColonPos)
|
||||
misaligned = true;
|
||||
}
|
||||
|
||||
maxColonPos = Math.max(maxColonPos, colonPos);
|
||||
});
|
||||
|
||||
if(misaligned) {
|
||||
if(isAutoFixing) { //We are in “fix” mode
|
||||
rule.each((declaration)=>{
|
||||
if(declaration.type != 'decl')
|
||||
return;
|
||||
if(!misaligned)
|
||||
return;
|
||||
|
||||
declaration.raws.between = `${' '.repeat(maxColonPos - declaration.prop.length)}:${declaration.raws.between.split(':')[1]}`;
|
||||
});
|
||||
} else { //We are in “report only” mode
|
||||
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
|
||||
});
|
||||
}
|
||||
if(isAutoFixing) { // We are in “fix” mode
|
||||
rule.each((declaration)=>{
|
||||
if(declaration.type != 'decl')
|
||||
return;
|
||||
|
||||
declaration.raws.between = `${' '.repeat(maxColonPos - declaration.prop.length)}:${declaration.raws.between.split(':')[1]}`;
|
||||
});
|
||||
} else { // We are in “report only” mode
|
||||
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;
|
||||
module.exports.messages = messages;
|
||||
ruleFunction.ruleName = ruleName;
|
||||
ruleFunction.messages = messages;
|
||||
|
||||
export default stylelint.createPlugin(ruleName, ruleFunction);
|
||||
@@ -1,5 +1,5 @@
|
||||
const stylelint = require('stylelint');
|
||||
const { isNumber } = require('stylelint/lib/utils/validateTypes.cjs');
|
||||
import stylelint from 'stylelint';
|
||||
import { isNumber } from 'stylelint/lib/utils/validateTypes.mjs';
|
||||
|
||||
const { report, ruleMessages, validateOptions } = stylelint.utils;
|
||||
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 ":"`
|
||||
});
|
||||
|
||||
|
||||
module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOption, secondaryOptionObject, context) {
|
||||
return function lint(postcssRoot, postcssResult) {
|
||||
const ruleFunction = (primaryOption, secondaryOptionObject, context)=>{
|
||||
return (postcssRoot, postcssResult)=>{
|
||||
|
||||
const validOptions = validateOptions(
|
||||
postcssResult,
|
||||
@@ -30,9 +29,9 @@ module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOpti
|
||||
const between = decl.raws.between;
|
||||
const colonIndex = between.indexOf(':');
|
||||
|
||||
if(between.slice(0, colonIndex).length >= primaryOption) {
|
||||
if(between.slice(0, colonIndex).length >= primaryOption)
|
||||
return;
|
||||
}
|
||||
|
||||
if(isAutoFixing) { //We are in “fix” mode
|
||||
decl.raws.between = between.slice(0, colonIndex).replace(/\s*$/, ' '.repeat(primaryOption)) + between.slice(colonIndex);
|
||||
} else {
|
||||
@@ -46,7 +45,9 @@ module.exports = stylelint.createPlugin(ruleName, function getPlugin(primaryOpti
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.ruleName = ruleName;
|
||||
module.exports.messages = messages;
|
||||
ruleFunction.ruleName = ruleName;
|
||||
ruleFunction.messages = messages;
|
||||
|
||||
export default stylelint.createPlugin(ruleName, ruleFunction);
|
||||
Reference in New Issue
Block a user