Stats
Total Brew Count
{this.state.stats.totalBrews}
+ Total Brews Published
+ {this.state.stats.totalPublishedBrews}
{this.state.fetching
diff --git a/client/admin/brewUtils/stats/stats.less b/client/admin/brewUtils/stats/stats.less
deleted file mode 100644
index b5a4612e1..000000000
--- a/client/admin/brewUtils/stats/stats.less
+++ /dev/null
@@ -1,13 +0,0 @@
-
-.Stats {
- position : relative;
-
- .pending {
- position : absolute;
- top : 0px;
- left : 0px;
- width : 100%;
- height : 100%;
- background-color : rgba(238,238,238, 0.5);
- }
-}
\ No newline at end of file
diff --git a/client/admin/notificationUtils/notificationAdd/notificationAdd.less b/client/admin/notificationUtils/notificationAdd/notificationAdd.less
index 878da24c2..14bdabd03 100644
--- a/client/admin/notificationUtils/notificationAdd/notificationAdd.less
+++ b/client/admin/notificationUtils/notificationAdd/notificationAdd.less
@@ -6,31 +6,32 @@
.field {
display : grid;
- grid-template-columns : 120px 150px;
+ grid-template-columns : 120px 200px;
align-items : center;
justify-items : stretch;
width : 100%;
margin-bottom : 20px;
-
-
+
input {
height : 33px;
padding : 0px 10px;
margin-bottom : unset;
font-family : monospace;
+
+ &[type='date'] { width : 14ch; }
}
textarea {
width : 50ch;
min-height : 7em;
max-height : 20em;
- resize : vertical;
padding : 10px;
+ resize : vertical;
}
}
button {
- width: 200px;
+ width : 200px;
i { margin-right : 10px; }
}
diff --git a/client/admin/notificationUtils/notificationLookup/notificationLookup.less b/client/admin/notificationUtils/notificationLookup/notificationLookup.less
index 3f9b78310..65903213c 100644
--- a/client/admin/notificationUtils/notificationLookup/notificationLookup.less
+++ b/client/admin/notificationUtils/notificationLookup/notificationLookup.less
@@ -1,8 +1,8 @@
-
.notificationLookup {
width : 450px;
- height : fit-content;
+ height : fit-content;
+ .noNotification { margin-block : 20px; }
.notificationList {
display : flex;
flex-direction : column;
@@ -30,11 +30,6 @@
font-size : 20px;
font-weight : 900;
}
-
- dl dt{
- font-weight: 900;
- }
}
}
- .noNotification { margin-block : 20px; }
}
\ No newline at end of file
diff --git a/client/components/Anchored.less b/client/components/Anchored.less
index 4f0e2fa8f..aeb9f1d5f 100644
--- a/client/components/Anchored.less
+++ b/client/components/Anchored.less
@@ -1,13 +1,11 @@
.anchored-box {
- position:absolute;
- @supports (inset-block-start: anchor(bottom)){
- inset-block-start: anchor(bottom);
- }
- justify-self: anchor-center;
- visibility: hidden;
- &.active {
- visibility: visible;
+ position : absolute;
+ visibility : hidden;
+ justify-self : anchor-center;
+ @supports (inset-block-start: anchor(bottom)) {
+ inset-block-start : anchor(bottom);
}
+ &.active { visibility : visible; }
}
\ No newline at end of file
diff --git a/client/components/combobox.jsx b/client/components/combobox.jsx
index 56633bbdd..ae9f1d7f8 100644
--- a/client/components/combobox.jsx
+++ b/client/components/combobox.jsx
@@ -45,6 +45,7 @@ const Combobox = createClass({
},
handleDropdown : function(show){
this.setState({
+ value : show ? '' : this.props.default,
showDropdown : show,
inputFocused : this.props.autoSuggest.clearAutoSuggestOnClick ? show : false
});
@@ -78,7 +79,7 @@ const Combobox = createClass({
if(!e.target.checkValidity()){
this.setState({
value : this.props.default
- }, ()=>this.props.onEntry(e));
+ });
}
}}
/>
diff --git a/client/components/combobox.less b/client/components/combobox.less
index d58019f6f..27f78356b 100644
--- a/client/components/combobox.less
+++ b/client/components/combobox.less
@@ -27,7 +27,7 @@
position : relative;
padding : 5px;
margin : 0 3px;
- font-family : "Open Sans";
+ font-family : 'Open Sans';
font-size : 11px;
cursor : default;
&:hover {
diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx
index a82ea8b34..21c0608bd 100644
--- a/client/homebrew/brewRenderer/brewRenderer.jsx
+++ b/client/homebrew/brewRenderer/brewRenderer.jsx
@@ -39,7 +39,7 @@ const BrewPage = (props)=>{
...props
};
const pageRef = useRef(null);
- const cleanText = safeHTML(props.contents);
+ const cleanText = safeHTML(`${props.contents}\n
\n`);
useEffect(()=>{
if(!pageRef.current) return;
@@ -189,14 +189,13 @@ const BrewRenderer = (props)=>{
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
+ 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
;
diff --git a/client/homebrew/brewRenderer/brewRenderer.less b/client/homebrew/brewRenderer/brewRenderer.less
index 68c688fb6..128c419be 100644
--- a/client/homebrew/brewRenderer/brewRenderer.less
+++ b/client/homebrew/brewRenderer/brewRenderer.less
@@ -1,43 +1,39 @@
@import (multiple, less) 'shared/naturalcrit/styles/reset.less';
.brewRenderer {
+ height : 100vh;
+ padding-top : 60px;
overflow-y : scroll;
will-change : transform;
- padding-top : 60px;
- height : 100vh;
- &:has(.facing, .flow) {
- padding : 60px 30px;
- }
- &.deployment {
- background-color: darkred;
- }
+ &:has(.facing, .flow) { padding : 60px 30px; }
+ &.deployment { background-color : darkred; }
:where(.pages) {
&.facing {
- display: grid;
- grid-template-columns: repeat(2, auto);
- grid-template-rows: repeat(3, auto);
- gap: 10px 10px;
- justify-content: safe center;
+ display : grid;
+ grid-template-rows : repeat(3, auto);
+ grid-template-columns : repeat(2, auto);
+ gap : 10px 10px;
+ justify-content : safe center;
&.recto .page:first-child {
// sets first page on 'right' ('recto') of the preview, as if for a Cover page.
// todo: add a checkbox to toggle this setting
- grid-column-start: 2;
+ grid-column-start : 2;
}
& :where(.page) {
- margin-left: unset !important;
- margin-right: unset !important;
+ margin-right : unset !important;
+ margin-left : unset !important;
}
}
&.flow {
- display: flex;
- flex-wrap: wrap;
- gap: 10px;
- justify-content: safe center;
+ display : flex;
+ flex-wrap : wrap;
+ gap : 10px;
+ justify-content : safe center;
& :where(.page) {
- flex: 0 0 auto;
- margin-left: unset !important;
- margin-right: unset !important;
+ flex : 0 0 auto;
+ margin-right : unset !important;
+ margin-left : unset !important;
}
}
@@ -50,9 +46,7 @@
margin-left : auto;
box-shadow : 1px 4px 14px #000000;
}
- *[id] {
- scroll-margin-top:100px;
- }
+ *[id] { scroll-margin-top : 100px; }
}
&::-webkit-scrollbar {
width : 20px;
@@ -79,11 +73,9 @@
overflow-y : unset;
.pages {
margin : 0px;
- zoom: 100% !important;
+ zoom : 100% !important;
& > .page { box-shadow : unset; }
}
}
- .headerNav {
- visibility: hidden;
- }
+ .headerNav { visibility : hidden; }
}
\ No newline at end of file
diff --git a/client/homebrew/brewRenderer/headerNav/headerNav.jsx b/client/homebrew/brewRenderer/headerNav/headerNav.jsx
index 68963129f..04ced2585 100644
--- a/client/homebrew/brewRenderer/headerNav/headerNav.jsx
+++ b/client/homebrew/brewRenderer/headerNav/headerNav.jsx
@@ -3,7 +3,6 @@ require('./headerNav.less');
import * as React from 'react';
import * as _ from 'lodash';
-
const MAX_TEXT_LENGTH = 40;
const HeaderNav = React.forwardRef(({}, pagesRef)=>{
@@ -11,11 +10,30 @@ const HeaderNav = React.forwardRef(({}, pagesRef)=>{
const renderHeaderLinks = ()=>{
if(!pagesRef.current) return;
+ // Top Level Pages
+ // Pages that contain an element with a specified class (e.g. cover pages, table of contents)
+ // will NOT have its content scanned for navigation headers, instead displaying a custom label
+ // ---
+ // The property name is class that will be used for detecting the page is a top level page
+ // The property value is a function that returns the text to be used
+
+ const topLevelPages = {
+ '.frontCover' : (el, pageType)=>{ const text = getHeaderContent(el); return text ? `Cover: ${text}` : 'Cover Page'; },
+ '.insideCover' : (el, pageType)=>{ const text = getHeaderContent(el); return text ? `Interior: ${text}` : 'Interior Cover Page'; },
+ '.partCover' : (el, pageType)=>{ const text = getHeaderContent(el); return text ? `Section: ${text}` : 'Section Cover Page'; },
+ '.backCover' : (el, pageType)=>{ const text = getHeaderContent(el); return text ? `Back: ${text}` : 'Rear Cover Page'; },
+ '.toc' : ()=>{ return 'Table of Contents'; },
+ };
+
+ const getHeaderContent = (el)=>el.querySelector('h1')?.textContent;
+
+ const topLevelPageSelector = Object.keys(topLevelPages).join(',');
+
const selector = [
- '.pages > .page', // All page elements, which by definition have IDs
- '.page:not(:has(.toc)) > [id]', // All direct children of non-ToC .page with an ID (Legacy)
- '.page:not(:has(.toc)) > .columnWrapper > [id]', // All direct children of non-ToC .page > .columnWrapper with an ID (V3)
- '.page:not(:has(.toc)) h2', // All non-ToC H2 titles, like Monster frame titles
+ '.pages > .page', // All page elements, which by definition have IDs
+ `.page:not(:has(${topLevelPageSelector})) > [id]`, // All direct children of non-excluded .pages with an ID (Legacy)
+ `.page:not(:has(${topLevelPageSelector})) > .columnWrapper > [id]`, // All direct children of non-excluded .page > .columnWrapper with an ID (V3)
+ `.page:not(:has(${topLevelPageSelector})) h2`, // All non-excluded H2 titles, like Monster frame titles
];
const elements = pagesRef.current.querySelectorAll(selector.join(','));
if(!elements) return;
@@ -23,45 +41,35 @@ const HeaderNav = React.forwardRef(({}, pagesRef)=>{
// navList is a list of objects which have the following structure:
// {
- // depth : how deeply indented the item should be
- // text : the text to display in the nav link
- // link : the hyperlink to navigate to when clicked
- // className : [optional] the class to apply to the nav link for styling
+ // depth : how deeply indented the item should be
+ // text : the text to display in the nav link
+ // link : the hyperlink to navigate to when clicked
+ // className : [optional] the class to apply to the nav link for styling
// }
elements.forEach((el)=>{
- if(el.className.match(/\bpage\b/)) {
- let text = `Page ${el.id.slice(1)}`; // The ID of a page *should* always be equal to `p` followed by the page number
- if(el.querySelector('.toc')){ // If the page contains a table of contents, add "- Contents" to the display text
- text += ' - Contents';
- };
- navList.push({
- depth : 0, // Pages are always at the least indented level
- text : text,
- link : el.id,
- className : 'pageLink'
- });
- return;
- }
- if(el.localName.match(/^h[1-6]/)){ // Header elements H1 through H6
- navList.push({
- depth : el.localName[1], // Depth is set by the header level
- text : el.textContent, // Use `textContent` because `innerText` is affected by rendering, e.g. 'content-visibility: auto'
- link : el.id
- });
- return;
- }
- navList.push({
- depth : 7, // All unmatched elements with IDs are set to the maximum depth (7)
- text : el.textContent, // Use `textContent` because `innerText` is affected by rendering, e.g. 'content-visibility: auto'
+ const navEntry = { // Default structure of a navList entry
+ depth : 7, // All unmatched elements with IDs are set to the maximum depth (7)
+ text : el.textContent, // Use `textContent` because `innerText` is affected by rendering, e.g. 'content-visibility: auto'
link : el.id
- });
- });
-
- return _.map(navList, (navItem, index)=>{
- return
;
+ };
+ if(el.classList.contains('page')) {
+ let text = `Page ${el.id.slice(1)}`; // Get the page # by trimming off the 'p' from the ID
+ const pageType = Object.keys(topLevelPages).find((pageType)=>el.querySelector(pageType));
+ if(pageType)
+ text += ` - ${topLevelPages[pageType](el, pageType)}`; // If a Top Level Page, add extra label
+
+ navEntry.depth = 0; // Pages are always at the least indented level
+ navEntry.text = text;
+ navEntry.className = 'pageLink';
+ } else if(el.localName.match(/^h[1-6]/)){ // Header elements H1 through H6
+ navEntry.depth = el.localName[1]; // Depth is set by the header level
+ }
+ navList.push(navEntry);
});
+ return _.map(navList, (navItem, index)=>
+ );
};
return
@@ -69,8 +77,7 @@ const HeaderNav = React.forwardRef(({}, pagesRef)=>{
{renderHeaderLinks()}
;
-}
-);
+});
const HeaderNavItem = ({ link, text, depth, className })=>{
diff --git a/client/homebrew/brewRenderer/headerNav/headerNav.less b/client/homebrew/brewRenderer/headerNav/headerNav.less
index 8b35041d9..a5fd11f5e 100644
--- a/client/homebrew/brewRenderer/headerNav/headerNav.less
+++ b/client/homebrew/brewRenderer/headerNav/headerNav.less
@@ -1,45 +1,37 @@
.headerNav {
- position: fixed;
- top: 32px;
- left: 0px;
- padding: 5px 10px;
- background-color: #ccc;
- border-radius: 5px;
- max-height: calc(100vh - 32px);
- max-width: 40vw;
- overflow-y: auto;
- &.active {
- padding-bottom: 10px;
- .navIcon {
- padding-bottom: 10px;
- }
- }
- .navIcon {
- cursor: pointer;
+ position : fixed;
+ top : 32px;
+ left : 0px;
+ max-width : 40vw;
+ max-height : calc(100vh - 32px);
+ padding : 5px 10px;
+ overflow-y : auto;
+ background-color : #CCCCCC;
+ border-radius : 5px;
+ &.active {
+ padding-bottom : 10px;
+ .navIcon { padding-bottom : 10px; }
}
+ .navIcon { cursor : pointer; }
li {
- list-style-type: none;
+ list-style-type : none;
a {
- display: inline-block;
- width: 100%;
- font-family: 'Open Sans';
- font-size: 12px;
- padding: 2px;
- color: inherit;
- text-decoration: none;
- cursor: pointer;
- &:hover {
- text-decoration: underline;
- }
- &.pageLink {
- font-weight: 900;
- }
+ display : inline-block;
+ width : 100%;
+ padding : 2px;
+ font-family : 'Open Sans';
+ font-size : 12px;
+ color : inherit;
+ text-decoration : none;
+ cursor : pointer;
+ &:hover { text-decoration : underline; }
+ &.pageLink { font-weight : 900; }
- @depths: 1,2,3,4,5,6,7;
+ @depths: 0,1,2,3,4,5,6,7;
each(@depths, {
&.depth-@{value} {
- padding-left: ((@value - 1) * 0.5em);
+ padding-left: ((@value) * 0.5em);
}
});
}
diff --git a/client/homebrew/brewRenderer/notificationPopup/notificationPopup.less b/client/homebrew/brewRenderer/notificationPopup/notificationPopup.less
index be642f0fe..85d4c8365 100644
--- a/client/homebrew/brewRenderer/notificationPopup/notificationPopup.less
+++ b/client/homebrew/brewRenderer/notificationPopup/notificationPopup.less
@@ -86,8 +86,8 @@
width : 100%;
}
.blank {
- height : 1em;
- margin-top : 0;
+ height : 1em;
+ margin-top : 0;
& + * { margin-top : 0; }
}
}
\ No newline at end of file
diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.less b/client/homebrew/brewRenderer/toolBar/toolBar.less
index a24731489..8f1464c8f 100644
--- a/client/homebrew/brewRenderer/toolBar/toolBar.less
+++ b/client/homebrew/brewRenderer/toolBar/toolBar.less
@@ -156,7 +156,7 @@
min-width : 46px;
height : 100%;
&:hover { background-color : #444444; }
- &:focus { border : 1px solid #D3D3D3;outline : none;}
+ &:focus {outline : none; border : 1px solid #D3D3D3;}
&:disabled {
color : #777777;
background-color : unset !important;
@@ -182,8 +182,8 @@
position : absolute;
left : 0;
z-index : 5;
+ display : flex;
width : 32px;
min-width : unset;
height : 100%;
- display : flex;
}
\ No newline at end of file
diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx
index 2d0a26268..9e6178f3e 100644
--- a/client/homebrew/editor/editor.jsx
+++ b/client/homebrew/editor/editor.jsx
@@ -456,6 +456,7 @@ const Editor = createClass({
rerenderParent={this.rerenderParent} />
diff --git a/client/homebrew/editor/editor.less b/client/homebrew/editor/editor.less
index b2e96683e..5511bee6e 100644
--- a/client/homebrew/editor/editor.less
+++ b/client/homebrew/editor/editor.less
@@ -1,8 +1,8 @@
@import 'themes/codeMirror/customEditorStyles.less';
.editor {
- position : relative;
- width : 100%;
- container: editor / inline-size;
+ position : relative;
+ width : 100%;
+ container : editor / inline-size;
.codeEditor {
height : 100%;
@@ -45,26 +45,26 @@
color : green;
}
.emoji:not(.cm-comment) {
- margin-left : 2px;
- color : #360034;
- background : #ffc8ff;
- border-radius : 6px;
- font-weight : bold;
padding-bottom : 1px;
+ margin-left : 2px;
+ font-weight : bold;
+ color : #360034;
+ outline : solid 2px #FF96FC;
outline-offset : -2px;
- outline : solid 2px #ff96fc;
+ background : #FFC8FF;
+ border-radius : 6px;
}
.superscript:not(.cm-comment) {
- font-weight : bold;
- color : goldenrod;
- vertical-align : super;
font-size : 0.9em;
+ font-weight : bold;
+ vertical-align : super;
+ color : goldenrod;
}
.subscript:not(.cm-comment) {
- font-weight : bold;
- color : rgb(123, 123, 15);
- vertical-align : sub;
font-size : 0.9em;
+ font-weight : bold;
+ vertical-align : sub;
+ color : rgb(123, 123, 15);
}
.dl-highlight {
&.dl-colon-highlight {
diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.jsx b/client/homebrew/editor/metadataEditor/metadataEditor.jsx
index 9d2ec7db6..8f256922f 100644
--- a/client/homebrew/editor/metadataEditor/metadataEditor.jsx
+++ b/client/homebrew/editor/metadataEditor/metadataEditor.jsx
@@ -4,7 +4,6 @@ const React = require('react');
const createClass = require('create-react-class');
const _ = require('lodash');
import request from '../../utils/request-middleware.js';
-const Nav = require('naturalcrit/nav/nav.jsx');
const Combobox = require('client/components/combobox.jsx');
const TagInput = require('../tagInput/tagInput.jsx');
@@ -40,6 +39,7 @@ const MetadataEditor = createClass({
theme : '5ePHB',
lang : 'en'
},
+
onChange : ()=>{},
reportError : ()=>{}
};
@@ -67,6 +67,11 @@ const MetadataEditor = createClass({
const inputRules = validations[name] ?? [];
const validationErr = inputRules.map((rule)=>rule(e.target.value)).filter(Boolean);
+ const debouncedReportValidity = _.debounce((target, errMessage)=>{
+ callIfExists(target, 'setCustomValidity', errMessage);
+ callIfExists(target, 'reportValidity');
+ }, 300); // 300ms debounce delay, adjust as needed
+
// if no validation rules, save to props
if(validationErr.length === 0){
callIfExists(e.target, 'setCustomValidity', '');
@@ -74,14 +79,16 @@ const MetadataEditor = createClass({
...this.props.metadata,
[name] : e.target.value
});
+ return true;
} else {
// if validation issues, display built-in browser error popup with each error.
const errMessage = validationErr.map((err)=>{
return `- ${err}`;
}).join('\n');
- callIfExists(e.target, 'setCustomValidity', errMessage);
- callIfExists(e.target, 'reportValidity');
+
+ debouncedReportValidity(e.target, errMessage);
+ return false;
}
},
@@ -102,6 +109,7 @@ const MetadataEditor = createClass({
}
this.props.onChange(this.props.metadata, 'renderer');
},
+
handlePublish : function(val){
this.props.onChange({
...this.props.metadata,
@@ -112,6 +120,14 @@ const MetadataEditor = createClass({
handleTheme : function(theme){
this.props.metadata.renderer = theme.renderer;
this.props.metadata.theme = theme.path;
+
+ this.props.onChange(this.props.metadata, 'theme');
+ },
+
+ handleThemeWritein : function(e) {
+ const shareId = e.target.value.split('/').pop(); //Extract just the ID if a URL was pasted in
+ this.props.metadata.theme = shareId;
+
this.props.onChange(this.props.metadata, 'theme');
},
@@ -200,7 +216,7 @@ const MetadataEditor = createClass({
if(theme.path == this.props.metadata.shareId) return;
const preview = theme.thumbnail || `/themes/${theme.renderer}/${theme.path}/dropdownPreview.png`;
const texture = theme.thumbnail || `/themes/${theme.renderer}/${theme.path}/dropdownTexture.png`;
- return this.handleTheme(theme)} title={''}>
+ return
{theme.author ?? renderer} : {theme.name}
@@ -210,26 +226,40 @@ const MetadataEditor = createClass({
;
- });
+ }).filter(Boolean);
};
const currentRenderer = this.props.metadata.renderer;
- const currentTheme = mergedThemes[`${_.upperFirst(this.props.metadata.renderer)}`][this.props.metadata.theme]
- ?? { name: `!!! THEME MISSING !!! ID=${this.props.metadata.theme}` };
+ const currentThemeDisplay = this.props.themeBundle?.name ? `${this.props.themeBundle.author ?? currentRenderer} : ${this.props.themeBundle.name}` : 'No Theme Selected';
let dropdown;
if(currentRenderer == 'legacy') {
dropdown =
-
- {`Themes are not supported in the Legacy Renderer`}
- ;
+
+
Themes are not supported in the Legacy Renderer
+
;
} else {
dropdown =
-
- {currentTheme.author ?? _.upperFirst(currentRenderer)} : {currentTheme.name}
-
- {listThemes(currentRenderer)}
- ;
+
+ this.handleTheme(value)}
+ onEntry={(e)=>{
+ e.target.setCustomValidity(''); //Clear the validation popup while typing
+ if(this.handleFieldChange('theme', e))
+ this.handleThemeWritein(e);
+ }}
+ options={listThemes(currentRenderer)}
+ autoSuggest={{
+ suggestMethod : 'includes',
+ clearAutoSuggestOnClick : true,
+ filterOn : ['value', 'title']
+ }}
+ />
+ Select from the list below (built-in themes and brews you have tagged "meta:theme"), or paste in the Share URL or Share ID of any brew.
+
;
}
return
@@ -251,8 +281,6 @@ const MetadataEditor = createClass({
});
};
- const debouncedHandleFieldChange = _.debounce(this.handleFieldChange, 500);
-
return
language
@@ -263,7 +291,7 @@ const MetadataEditor = createClass({
onSelect={(value)=>this.handleLanguage(value)}
onEntry={(e)=>{
e.target.setCustomValidity(''); //Clear the validation popup while typing
- debouncedHandleFieldChange('lang', e);
+ this.handleFieldChange('lang', e);
}}
options={listLanguages()}
autoSuggest={{
@@ -271,8 +299,7 @@ const MetadataEditor = createClass({
clearAutoSuggestOnClick : true,
filterOn : ['value', 'detail', 'title']
}}
- >
-
+ />
Sets the HTML Lang property for your brew. May affect hyphenation or spellcheck.
@@ -345,7 +372,7 @@ const MetadataEditor = createClass({
placeholder='add tag' unique={true}
values={this.props.metadata.tags}
onChange={(e)=>this.handleFieldChange('tags', e)}
- />
+ />
systems
@@ -370,7 +397,7 @@ const MetadataEditor = createClass({
values={this.props.metadata.invitedAuthors}
notes={['Invited author usernames are case sensitive.', 'After adding an invited author, send them the edit link. There, they can choose to accept or decline the invitation.']}
onChange={(e)=>this.handleFieldChange('invitedAuthors', e)}
- />
+ />
Privacy
diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.less b/client/homebrew/editor/metadataEditor/metadataEditor.less
index 2cff01cfe..fd04f07d9 100644
--- a/client/homebrew/editor/metadataEditor/metadataEditor.less
+++ b/client/homebrew/editor/metadataEditor/metadataEditor.less
@@ -1,28 +1,31 @@
@import 'naturalcrit/styles/colors.less';
+.userThemeName {
+ padding-right : 10px;
+ padding-left : 10px;
+}
.metadataEditor {
position : absolute;
- z-index : 5;
box-sizing : border-box;
width : 100%;
height : calc(100vh - 54px); // 54px is the height of the navbar + snippet bar. probably a better way to dynamic get this.
padding : 25px;
overflow-y : auto;
+ font-size : 13px;
background-color : #999999;
- font-size : 13px;
h1 {
- margin: 0 0 40px;
- font-weight: bold;
- text-transform: uppercase;
+ margin : 0 0 40px;
+ font-weight : bold;
+ text-transform : uppercase;
}
h2 {
- margin : 20px 0;
- font-weight : bold;
- border-bottom: 2px solid gray;
- color: #555;
+ margin : 20px 0;
+ font-weight : bold;
+ color : #555555;
+ border-bottom : 2px solid gray;
}
& > div { margin-bottom : 10px; }
@@ -51,10 +54,10 @@
min-width : 200px;
& > label {
width : 80px;
+ font-size : 0.9em;
font-weight : 800;
line-height : 1.8em;
text-transform : uppercase;
- font-size: .9em;
}
& > .value {
flex : 1 1 auto;
@@ -71,8 +74,7 @@
border : 1px solid gray;
&:focus { outline : 1px solid #444444; }
}
- &.thumbnail {
- height : 1.4em;
+ &.thumbnail, &.themes {
label { line-height : 2.0em; }
.value {
overflow : hidden;
@@ -88,6 +90,17 @@
}
}
+ &.themes {
+ .value {
+ overflow : visible;
+ text-overflow : auto;
+ }
+ button {
+ padding-right : 5px;
+ padding-left : 5px;
+ }
+ }
+
&.description {
flex : 1;
textarea.value {
@@ -123,8 +136,8 @@
margin-right : 15px;
font-size : 0.9em;
font-weight : 800;
- white-space : nowrap;
vertical-align : middle;
+ white-space : nowrap;
cursor : pointer;
user-select : none;
}
@@ -151,94 +164,74 @@
.colorButton(@red);
}
}
- .authors.field .value {
- line-height : 1.5em;
- }
+ .authors.field .value { line-height : 1.5em; }
.themes.field {
- .navDropdownContainer {
+ & .dropdown-container {
position : relative;
z-index : 100;
background-color : white;
- &.disabled {
- font-style : italic;
- color : dimgray;
- background-color : darkgray;
- }
- & > div:first-child {
- padding : 3px 3px;
- background-color : inherit;
- border : 1px solid gray;
- i { float : right; }
- &:hover {
- color : white;
- background-color : @blue;
+ }
+ & .dropdown-options { overflow-y : visible; }
+ .disabled {
+ font-style : italic;
+ color : dimgray;
+ background-color : darkgray;
+ }
+ .item {
+ position : relative;
+ padding : 3px 3px;
+ overflow : visible;
+ background-color : white;
+ border-top : 1px solid rgb(118, 118, 118);
+ .preview {
+ position : absolute;
+ top : 0;
+ right : 0;
+ z-index : 1;
+ display : flex;
+ flex-direction : column;
+ width : 200px;
+ overflow : hidden;
+ color : black;
+ background : #CCCCCC;
+ border-radius : 5px;
+ box-shadow : 0 0 5px black;
+ opacity : 0;
+ transition : opacity 250ms ease;
+ h6 {
+ padding-block : 0.5em;
+ padding-inline : 1em;
+ font-weight : 900;
+ border-bottom : 2px solid hsl(0,0%,40%);
}
}
- .navDropdown .item > p {
- width : 45%;
- height : 1.1em;
- overflow : hidden;
- text-overflow : ellipsis;
- white-space : nowrap;
- }
- .navDropdown {
- position : absolute;
- width : 100%;
- box-shadow : 0px 5px 10px rgba(0, 0, 0, 0.3);
- .item {
- position : relative;
- padding : 3px 3px;
- overflow : visible;
- background-color : white;
- border-top : 1px solid rgb(118, 118, 118);
- .preview {
- position : absolute;
- top : 0;
- right : 0;
- z-index : 1;
- display : flex;
- flex-direction : column;
- width : 200px;
- overflow : hidden;
- color : black;
- background : #CCCCCC;
- border-radius : 5px;
- box-shadow : 0 0 5px black;
- opacity : 0;
- transition : opacity 250ms ease;
- h6 {
- padding-block : 0.5em;
- padding-inline : 1em;
- font-weight : 900;
- border-bottom : 2px solid hsl(0,0%,40%);
- }
- }
- &:hover {
- color : white;
- background-color : @blue;
- }
- &:hover > .preview { opacity : 1; }
- .texture-container {
- position : absolute;
- top : 0;
- left : 0;
- width : 100%;
- height : 100%;
- min-height : 100%;
- overflow : hidden;
- > img {
- position : absolute;
- top : 0px;
- right : 0;
- width : 50%;
- min-height : 100%;
- -webkit-mask-image : linear-gradient(90deg, transparent, black 20%);
- mask-image : linear-gradient(90deg, transparent, black 20%);
- }
- }
+
+ .texture-container {
+ position : absolute;
+ top : 0;
+ left : 0;
+ width : 100%;
+ height : 100%;
+ min-height : 100%;
+ overflow : hidden;
+ > img {
+ position : absolute;
+ top : 0;
+ right : 0;
+ width : 50%;
+ min-height : 100%;
+ -webkit-mask-image : linear-gradient(90deg, transparent, black 20%);
+ mask-image : linear-gradient(90deg, transparent, black 20%);
}
}
+
+ &:hover {
+ color : white;
+ background-color : @blue;
+ filter : unset;
+ }
+ &:hover > .preview { opacity : 1; }
}
}
diff --git a/client/homebrew/editor/metadataEditor/validations.js b/client/homebrew/editor/metadataEditor/validations.js
index 32c8131f6..858fca6c4 100644
--- a/client/homebrew/editor/metadataEditor/validations.js
+++ b/client/homebrew/editor/metadataEditor/validations.js
@@ -27,6 +27,19 @@ module.exports = {
(value)=>{
return new RegExp(/^([a-zA-Z]{2,3})(-[a-zA-Z]{4})?(-(?:[0-9]{3}|[a-zA-Z]{2}))?$/).test(value) === false && (value.length > 0) ? 'Invalid language code.' : null;
}
+ ],
+ theme : [
+ (value)=>{
+ const URL = global.config.baseUrl.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); //Escape any regex characters
+ const shareIDPattern = '[a-zA-Z0-9-_]{12}';
+ const shareURLRegex = new RegExp(`^${URL}\\/share\\/${shareIDPattern}$`);
+ const shareIDRegex = new RegExp(`^${shareIDPattern}$`);
+ if(value?.length === 0) return null;
+ if(shareURLRegex.test(value)) return null;
+ if(shareIDRegex.test(value)) return null;
+
+ return 'Must be a valid Share URL or a 12-character ID.';
+ }
]
};
diff --git a/client/homebrew/editor/snippetbar/snippetbar.jsx b/client/homebrew/editor/snippetbar/snippetbar.jsx
index f7d9508f8..4d702bfdf 100644
--- a/client/homebrew/editor/snippetbar/snippetbar.jsx
+++ b/client/homebrew/editor/snippetbar/snippetbar.jsx
@@ -207,59 +207,59 @@ const Snippetbar = createClass({
renderEditorButtons : function(){
if(!this.props.showEditButtons) return;
-
+
return (
-
- {this.props.view !== 'meta' && <>
-
-
- { this.state.showHistory && this.renderHistoryItems() }
+
+ {this.props.view !== 'meta' && <>
+
+
+ { this.state.showHistory && this.renderHistoryItems() }
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {this.state.themeSelector && this.renderThemeSelector()}
-
-
>}
-
+
+
+
+
+
+
+
+
+
+ {this.state.themeSelector && this.renderThemeSelector()}
+
+
>}
-
-
this.props.onViewChange('text')}>
-
-
-
this.props.onViewChange('style')}>
-
-
-
this.props.onViewChange('meta')}>
-
-
-
-
- )
+
+
this.props.onViewChange('text')}>
+
+
+
this.props.onViewChange('style')}>
+
+
+
this.props.onViewChange('meta')}>
+
+
+
+
+
+ );
},
render : function(){
diff --git a/client/homebrew/editor/snippetbar/snippetbar.less b/client/homebrew/editor/snippetbar/snippetbar.less
index 7d56dc718..0860a44bf 100644
--- a/client/homebrew/editor/snippetbar/snippetbar.less
+++ b/client/homebrew/editor/snippetbar/snippetbar.less
@@ -22,7 +22,7 @@
justify-content : flex-end;
min-width : 225px;
- &:only-child { margin-left : auto;min-width:unset;}
+ &:only-child {min-width : unset; margin-left : auto;}
>div {
display : flex;
@@ -39,9 +39,7 @@
text-align : center;
cursor : pointer;
- &.editorTool:not(.active) {
- cursor:not-allowed;
- }
+ &.editorTool:not(.active) { cursor : not-allowed; }
&:hover,&.selected { background-color : #999999; }
&.text {
@@ -151,9 +149,9 @@
position : absolute;
top : 100%;
z-index : 1000;
+ visibility : hidden;
padding : 0px;
margin-left : -5px;
- visibility : hidden;
background-color : #DDDDDD;
.snippet {
position : relative;
diff --git a/client/homebrew/editor/tagInput/tagInput.jsx b/client/homebrew/editor/tagInput/tagInput.jsx
index 816541167..d60e23b1b 100644
--- a/client/homebrew/editor/tagInput/tagInput.jsx
+++ b/client/homebrew/editor/tagInput/tagInput.jsx
@@ -3,43 +3,43 @@ const React = require('react');
const { useState, useEffect } = React;
const _ = require('lodash');
-const TagInput = ({ unique = true, values = [], ...props }) => {
+const TagInput = ({ unique = true, values = [], ...props })=>{
const [tempInputText, setTempInputText] = useState('');
- const [tagList, setTagList] = useState(values.map((value) => ({ value, editing: false })));
+ const [tagList, setTagList] = useState(values.map((value)=>({ value, editing: false })));
useEffect(()=>{
- handleChange(tagList.map((context)=>context.value))
- }, [tagList])
+ handleChange(tagList.map((context)=>context.value));
+ }, [tagList]);
const handleChange = (value)=>{
props.onChange({
target : { value }
- })
+ });
};
- const handleInputKeyDown = ({ evt, value, index, options = {} }) => {
- if (_.includes(['Enter', ','], evt.key)) {
+ const handleInputKeyDown = ({ evt, value, index, options = {} })=>{
+ if(_.includes(['Enter', ','], evt.key)) {
evt.preventDefault();
submitTag(evt.target.value, value, index);
- if (options.clear) {
+ if(options.clear) {
setTempInputText('');
}
}
};
- const submitTag = (newValue, originalValue, index) => {
- setTagList((prevContext) => {
+ const submitTag = (newValue, originalValue, index)=>{
+ setTagList((prevContext)=>{
// remove existing tag
if(newValue === null){
return [...prevContext].filter((context, i)=>i !== index);
}
// add new tag
if(originalValue === null){
- return [...prevContext, { value: newValue, editing: false }]
+ return [...prevContext, { value: newValue, editing: false }];
}
// update existing tag
- return prevContext.map((context, i) => {
- if (i === index) {
+ return prevContext.map((context, i)=>{
+ if(i === index) {
return { ...context, value: newValue, editing: false };
}
return context;
@@ -47,10 +47,10 @@ const TagInput = ({ unique = true, values = [], ...props }) => {
});
};
- const editTag = (index) => {
- setTagList((prevContext) => {
- return prevContext.map((context, i) => {
- if (i === index) {
+ const editTag = (index)=>{
+ setTagList((prevContext)=>{
+ return prevContext.map((context, i)=>{
+ if(i === index) {
return { ...context, editing: true };
}
return { ...context, editing: false };
@@ -58,25 +58,25 @@ const TagInput = ({ unique = true, values = [], ...props }) => {
});
};
- const renderReadTag = (context, index) => {
+ const renderReadTag = (context, index)=>{
return (
editTag(index)}>
+ onClick={()=>editTag(index)}>
{context.value}
- {evt.stopPropagation(); submitTag(null, context.value, index)}}>
+ {evt.stopPropagation(); submitTag(null, context.value, index);}}>
);
};
- const renderWriteTag = (context, index) => {
+ const renderWriteTag = (context, index)=>{
return (
handleInputKeyDown({evt, value: context.value, index: index})}
- autoFocus
+ defaultValue={context.value}
+ onKeyDown={(evt)=>handleInputKeyDown({ evt, value: context.value, index: index })}
+ autoFocus
/>
);
};
@@ -86,7 +86,7 @@ const TagInput = ({ unique = true, values = [], ...props }) => {
{props.label}
- {tagList.map((context, index) => { return context.editing ? renderWriteTag(context, index) : renderReadTag(context, index); })}
+ {tagList.map((context, index)=>{ return context.editing ? renderWriteTag(context, index) : renderReadTag(context, index); })}
{
className='value'
placeholder={props.placeholder}
value={tempInputText}
- onChange={(e) => setTempInputText(e.target.value)}
- onKeyDown={(evt) => handleInputKeyDown({ evt, value: null, options: { clear: true } })}
+ onChange={(e)=>setTempInputText(e.target.value)}
+ onKeyDown={(evt)=>handleInputKeyDown({ evt, value: null, options: { clear: true } })}
/>
diff --git a/client/homebrew/homebrew.less b/client/homebrew/homebrew.less
index 828de796f..e265c2941 100644
--- a/client/homebrew/homebrew.less
+++ b/client/homebrew/homebrew.less
@@ -1,36 +1,32 @@
@import 'naturalcrit/styles/core.less';
-.homebrew{
+.homebrew {
height : 100%;
- .sitePage{
+ .sitePage {
display : flex;
- height : 100%;
- background-color : @steel;
flex-direction : column;
+ height : 100%;
overflow-y : hidden;
- .content{
+ background-color : @steel;
+ .content {
position : relative;
- height : calc(~"100% - 29px"); //Navbar height
flex : auto;
+ height : calc(~'100% - 29px'); //Navbar height
overflow-y : hidden;
}
&.listPage .content {
overflow-y : scroll;
&::-webkit-scrollbar {
- width: 20px;
- &:horizontal{
- height: 20px;
- width:auto;
+ width : 20px;
+ &:horizontal {
+ width : auto;
+ height : 20px;
}
&-thumb {
- background: linear-gradient(90deg, #d3c1af 15px, #00000000 15px);
- &:horizontal{
- background: linear-gradient(0deg, #d3c1af 15px, #00000000 15px);
- }
- }
- &-corner {
- visibility: hidden;
+ background : linear-gradient(90deg, #D3C1AF 15px, #00000000 15px);
+ &:horizontal { background : linear-gradient(0deg, #D3C1AF 15px, #00000000 15px); }
}
+ &-corner { visibility : hidden; }
}
}
}
diff --git a/client/homebrew/navbar/error-navitem.jsx b/client/homebrew/navbar/error-navitem.jsx
index f6788e6d5..3de26ca56 100644
--- a/client/homebrew/navbar/error-navitem.jsx
+++ b/client/homebrew/navbar/error-navitem.jsx
@@ -116,6 +116,19 @@ const ErrorNavItem = createClass({
;
}
+ if(HBErrorCode === '10') {
+ return
+ Oops!
+
+ Looks like the brew you have selected
+ as a theme is not tagged for use as a
+ theme. Verify that
+ brew
+ {response.body.brewId} has the
meta:theme tag!
+
+ ;
+ }
+
return
Oops!
diff --git a/client/homebrew/navbar/error-navitem.less b/client/homebrew/navbar/error-navitem.less
index be138dca4..637ddac95 100644
--- a/client/homebrew/navbar/error-navitem.less
+++ b/client/homebrew/navbar/error-navitem.less
@@ -1,78 +1,70 @@
.navItem.error {
- position : relative;
- background-color : @red;
+ position : relative;
+ background-color : @red;
}
-.errorContainer{
- animation-name: glideDown;
- animation-duration: 0.4s;
- position : absolute;
- top : 100%;
- left : 50%;
- z-index : 1000;
- width : 140px;
- padding : 3px;
- color : white;
- background-color : #333;
- border : 3px solid #444;
- border-radius : 5px;
- transform : translate(-50% + 3px, 10px);
- text-align : center;
- font-size : 10px;
- font-weight : 800;
- text-transform : uppercase;
- .lowercase {
- text-transform : none;
+.errorContainer {
+ position : absolute;
+ top : 100%;
+ left : 50%;
+ z-index : 1000;
+ width : 140px;
+ padding : 3px;
+ font-size : 10px;
+ font-weight : 800;
+ color : white;
+ text-align : center;
+ text-transform : uppercase;
+ background-color : #333333;
+ border : 3px solid #444444;
+ border-radius : 5px;
+ transform : translate(-50% + 3px, 10px);
+ animation-name : glideDown;
+ animation-duration : 0.4s;
+ .lowercase { text-transform : none; }
+ a { color : @teal; }
+ &::before {
+ position : absolute;
+ top : -23px;
+ left : 53px;
+ width : 0px;
+ height : 0px;
+ content : '';
+ border-top : 10px solid transparent;
+ border-right : 10px solid transparent;
+ border-bottom : 10px solid #444444;
+ border-left : 10px solid transparent;
+ }
+ &::after {
+ position : absolute;
+ top : -19px;
+ left : 53px;
+ width : 0px;
+ height : 0px;
+ content : '';
+ border-top : 10px solid transparent;
+ border-right : 10px solid transparent;
+ border-bottom : 10px solid #333333;
+ border-left : 10px solid transparent;
+ }
+ .deny {
+ display : inline-block;
+ width : 48%;
+ padding : 5px;
+ margin : 1px;
+ background-color : #333333;
+ border-left : 1px solid #666666;
+ .animate(background-color);
+ &:hover { background-color : red; }
+ }
+ .confirm {
+ display : inline-block;
+ width : 48%;
+ padding : 5px;
+ margin : 1px;
+ color : white;
+ background-color : #333333;
+ .animate(background-color);
+ &:hover { background-color : teal; }
}
- a{
- color : @teal;
- }
- &:before {
- content: "";
- width: 0px;
- height: 0px;
- position: absolute;
- border-left: 10px solid transparent;
- border-right: 10px solid transparent;
- border-top: 10px solid transparent;
- border-bottom: 10px solid #444;
- left: 53px;
- top: -23px;
- }
- &:after {
- content: "";
- width: 0px;
- height: 0px;
- position: absolute;
- border-left: 10px solid transparent;
- border-right: 10px solid transparent;
- border-top: 10px solid transparent;
- border-bottom: 10px solid #333;
- left: 53px;
- top: -19px;
- }
- .deny {
- width : 48%;
- margin : 1px;
- padding : 5px;
- background-color : #333;
- display : inline-block;
- border-left : 1px solid #666;
- .animate(background-color);
- &:hover{
- background-color : red;
- }
- }
- .confirm {
- width : 48%;
- margin : 1px;
- padding : 5px;
- background-color : #333;
- display : inline-block;
- color : white;
- .animate(background-color);
- &:hover{
- background-color : teal;
- }
- }
}
diff --git a/client/homebrew/navbar/navbar.less b/client/homebrew/navbar/navbar.less
index ae11c1e7e..aa233d631 100644
--- a/client/homebrew/navbar/navbar.less
+++ b/client/homebrew/navbar/navbar.less
@@ -24,11 +24,11 @@
}
.homebrew nav {
+ position : relative;
+ z-index : 2;
+ display : flex;
+ justify-content : space-between;
background-color : #333333;
- position : relative;
- z-index : 2;
- display : flex;
- justify-content : space-between;
.navSection {
display : flex;
@@ -82,8 +82,8 @@
font-weight : 800;
line-height : 13px;
color : white;
- text-decoration : none;
text-transform : uppercase;
+ text-decoration : none;
cursor : pointer;
background-color : #333333;
i {
@@ -106,11 +106,11 @@
display : block;
width : 100%;
overflow : hidden;
+ text-overflow : ellipsis;
font-size : 12px;
font-weight : 800;
color : white;
text-align : center;
- text-overflow : ellipsis;
text-transform : initial;
white-space : nowrap;
background-color : transparent;
@@ -170,16 +170,16 @@
h4 {
box-sizing : border-box;
display : block;
- flex-basis : 20%;
flex-grow : 1;
+ flex-basis : 20%;
min-width : 76px;
padding : 5px 0;
color : #BBBBBB;
text-align : center;
}
p {
- flex-basis : 80%;
flex-grow : 1;
+ flex-basis : 80%;
padding : 5px 0;
font-family : 'Open Sans', sans-serif;
font-size : 10px;
@@ -215,10 +215,10 @@
z-index : 10000;
box-sizing : border-box;
display : block;
+ visibility : hidden;
width : 100%;
padding : 13px 5px;
text-align : center;
- visibility : hidden;
background-color : #333333;
}
}
diff --git a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx
index ef98e8425..ef309a613 100644
--- a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx
+++ b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.jsx
@@ -30,11 +30,11 @@ const BrewItem = ({
}
request.delete(`/api/${brew.googleId ?? ''}${brew.editId}`).send().end((err, res)=>{
- if (err) reportError(err); else window.location.reload();
- });
+ if(err) reportError(err); else window.location.reload();
+ });
}, [brew, reportError]);
- const updateFilter = useCallback((type, term)=> updateListFilter(type, term), [updateListFilter]);
+ const updateFilter = useCallback((type, term)=>updateListFilter(type, term), [updateListFilter]);
const renderDeleteBrewLink = ()=>{
if(!brew.editId) return null;
diff --git a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less
index a3c17215e..0d45e8537 100644
--- a/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less
+++ b/client/homebrew/pages/basePages/listPage/brewItem/brewItem.less
@@ -1,148 +1,129 @@
-.brewItem{
+.brewItem {
position : relative;
+ box-sizing : border-box;
display : inline-block;
- vertical-align : top;
- box-sizing : border-box;
- box-sizing : border-box;
- overflow : hidden;
width : 48%;
min-height : 105px;
- margin-right : 15px;
- margin-bottom : 15px;
padding : 5px 15px 2px 6px;
padding-right : 15px;
- border : 1px solid #c9ad6a;
+ margin-right : 15px;
+ margin-bottom : 15px;
+ overflow : hidden;
+ vertical-align : top;
+ background-color : #CAB2802E;
+ border : 1px solid #C9AD6A;
border-radius : 5px;
+ box-shadow : 0px 4px 5px 0px #333333;
+ break-inside : avoid;
-webkit-column-break-inside : avoid;
page-break-inside : avoid;
- break-inside : avoid;
- box-shadow : 0px 4px 5px 0px #333;
- background-color : #cab2802e;
- .thumbnail {
- position: absolute;
- width: 150px;
- height: 100%;
- top: 0;
- right: 0;
- z-index: -1;
- background-size: contain;
- background-repeat: no-repeat;
- background-position: right top;
- mask-image: linear-gradient(80deg, #0000 20%, #050 40%);
- -webkit-mask-image: linear-gradient(80deg, #0000 20%, #050 40%);
- opacity: 50%;
+ .thumbnail {
+ position : absolute;
+ top : 0;
+ right : 0;
+ z-index : -1;
+ width : 150px;
+ height : 100%;
+ background-repeat : no-repeat;
+ background-position : right top;
+ background-size : contain;
+ opacity : 50%;
+ -webkit-mask-image : linear-gradient(80deg, #00000000 20%, #005500 40%);
+ mask-image : linear-gradient(80deg, #00000000 20%, #005500 40%);
}
.text {
min-height : 54px;
- h4{
+ h4 {
margin-bottom : 5px;
font-size : 2.2em;
}
}
- .info{
- position: initial;
- bottom: 2px;
- font-family : ScalySansRemake;
+ .info {
+ position : initial;
+ bottom : 2px;
+ font-family : "ScalySansRemake";
font-size : 1.2em;
- &>span{
+ & > span {
margin-right : 12px;
line-height : 1.5em;
- a {
- color:inherit;
- }
+ a { color : inherit; }
}
}
.brewTags span {
- background-color: #c8ac6e3b;
- margin: 2px;
- padding: 2px;
- border: 1px solid #c8ac6e;
- border-radius: 4px;
- white-space: nowrap;
- display: inline-block;
- font-weight: bold;
- border-color: currentColor;
- cursor : pointer;
- &:before {
- font-family: 'Font Awesome 5 Free';
- font-size: 12px;
- margin-right: 3px;
+ display : inline-block;
+ padding : 2px;
+ margin : 2px;
+ font-weight : bold;
+ white-space : nowrap;
+ cursor : pointer;
+ background-color : #C8AC6E3B;
+ border : 1px solid #C8AC6E;
+ border-color : currentColor;
+ border-radius : 4px;
+ &::before {
+ margin-right : 3px;
+ font-family : 'Font Awesome 5 Free';
+ font-size : 12px;
}
&.type {
- background-color: #0080003b;
- color: #008000;
- &:before{
- content: '\f0ad';
- }
+ color : #008000;
+ background-color : #0080003B;
+ &::before { content : '\f0ad'; }
}
&.group {
- background-color: #5050503b;
- color: #000000;
- &:before{
- content: '\f500';
- }
+ color : #000000;
+ background-color : #5050503B;
+ &::before { content : '\f500'; }
}
&.meta {
- background-color: #0000803b;
- color: #000080;
- &:before{
- content: '\f05a';
- }
+ color : #000080;
+ background-color : #0000803B;
+ &::before { content : '\f05a'; }
}
&.system {
- background-color: #8000003b;
- color: #800000;
- &:before{
- content: '\f518';
- }
+ color : #800000;
+ background-color : #8000003B;
+ &::before { content : '\f518'; }
}
}
- &:hover{
- .links{
- opacity : 1;
- }
+ &:hover {
+ .links { opacity : 1; }
}
- &:nth-child(2n + 1){
- margin-right : 0px;
- }
- .links{
+ &:nth-child(2n + 1) { margin-right : 0px; }
+ .links {
.animate(opacity);
position : absolute;
top : 0px;
right : 0px;
- height : 100%;
width : 2em;
- opacity : 0;
- background-color : fade(black, 60%);
+ height : 100%;
text-align : center;
- a{
+ background-color : fade(black, 60%);
+ opacity : 0;
+ a {
.animate(opacity);
display : block;
margin : 8px 0px;
- opacity : 0.6;
font-size : 1.3em;
color : white;
text-decoration : unset;
- &:hover{
- opacity : 1;
- }
- i{
- cursor : pointer;
- }
+ opacity : 0.6;
+ &:hover { opacity : 1; }
+ i { cursor : pointer; }
}
}
.googleDriveIcon {
- height : 18px;
+ height : 18px;
padding : 0px;
margin : -5px;
}
.homebreweryIcon {
- mix-blend-mode : darken;
- height : 24px;
position : relative;
top : 5px;
left : -5px;
+ height : 24px;
+ mix-blend-mode : darken;
}
}
diff --git a/client/homebrew/pages/basePages/listPage/listPage.less b/client/homebrew/pages/basePages/listPage/listPage.less
index 0aa4a278d..bf899bc71 100644
--- a/client/homebrew/pages/basePages/listPage/listPage.less
+++ b/client/homebrew/pages/basePages/listPage/listPage.less
@@ -1,5 +1,5 @@
-.noColumns(){
+.noColumns() {
column-count : auto;
column-fill : auto;
column-gap : normal;
@@ -13,177 +13,151 @@
height : auto;
min-height : 279.4mm;
margin : 20px auto;
- contain : unset;
+ contain : unset;
}
-.listPage{
- .content{
+.listPage {
+ .content {
z-index : 1;
- .page{
+ .page {
.noColumns() !important; //Needed to override PHB Theme since this is on a lower @layer
- &::after{
- display : none;
- }
- .noBrews{
+ &::after { display : none; }
+ .noBrews {
margin : 10px 0px;
font-size : 1.3em;
font-style : italic;
}
.brewCollection {
- h1:hover{
- cursor: pointer;
- }
+ h1:hover { cursor : pointer; }
.active::before, .inactive::before {
- font-family: 'Font Awesome 5 Free';
- font-weight: 900;
- font-size: 0.6cm;
- padding-right: 0.5em;
- }
- .active {
- color: var(--HB_Color_HeaderText);
- }
- .active::before {
- content: '\f107';
- }
- .inactive {
- color: #707070;
- }
- .inactive::before {
- content: '\f105';
+ padding-right : 0.5em;
+ font-family : 'Font Awesome 5 Free';
+ font-size : 0.6cm;
+ font-weight : 900;
}
+ .active { color : var(--HB_Color_HeaderText); }
+ .active::before { content : '\f107'; }
+ .inactive { color : #707070; }
+ .inactive::before { content : '\f105'; }
}
}
}
.sort-container {
- font-family : 'Open Sans', sans-serif;
- position : sticky;
- top : 0;
- left : 0;
- width : 100%;
- height : 30px;
- background-color : #555;
- border-top : 1px solid #666;
- border-bottom : 1px solid #666;
- color : white;
- text-align : center;
- z-index : 1;
- display : flex;
- justify-content : center;
- align-items : baseline;
- column-gap : 15px;
- row-gap : 5px;
- flex-wrap : wrap;
- h6{
- text-transform : uppercase;
+ position : sticky;
+ top : 0;
+ left : 0;
+ z-index : 1;
+ display : flex;
+ flex-wrap : wrap;
+ row-gap : 5px;
+ column-gap : 15px;
+ align-items : baseline;
+ justify-content : center;
+ width : 100%;
+ height : 30px;
+ font-family : 'Open Sans', sans-serif;
+ color : white;
+ text-align : center;
+ background-color : #555555;
+ border-top : 1px solid #666666;
+ border-bottom : 1px solid #666666;
+ h6 {
font-family : 'Open Sans', sans-serif;
font-size : 11px;
font-weight : bold;
+ text-transform : uppercase;
}
.sort-option {
- display: flex;
- align-items: center;
- padding: 0 8px;
- color: #ccc;
- height: 100%;
+ display : flex;
+ align-items : center;
+ height : 100%;
+ padding : 0 8px;
+ color : #CCCCCC;
- &:hover{
- background-color : #444;
- }
+ &:hover { background-color : #444444; }
&.active {
- font-weight: bold;
- color: #ddd;
- background-color: #333;
+ font-weight : bold;
+ color : #DDDDDD;
+ background-color : #333333;
- button {
- color: white;
- font-weight: 800;
- height: 100%;
- & + .sortDir {
- padding-left: 5px;
+ button {
+ height : 100%;
+ font-weight : 800;
+ color : white;
+ & + .sortDir { padding-left : 5px; }
}
}
- }
}
.filter-option {
- margin-left: 20px;
- background-color : transparent !important;
+ margin-left : 20px;
font-size : 11px;
- i{
- padding-right : 5px;
- }
+ background-color : transparent !important;
+ i { padding-right : 5px; }
+ }
+ button {
+ padding : 0;
+ font-family : 'Open Sans', sans-serif;
+ font-size : 11px;
+ font-weight : normal;
+ color : #CCCCCC;
+ text-transform : uppercase;
+ background-color : transparent;
}
- button{
- background-color : transparent;
- font-family : 'Open Sans', sans-serif;
- text-transform : uppercase;
- font-weight : normal;
- font-size : 11px;
- color : #ccc;
- padding : 0;
- }
}
.tags-container {
- height : 30px;
- background-color : #555;
- border-top : 1px solid #666;
- border-bottom : 1px solid #666;
- color : white;
display : flex;
- justify-content : center;
- align-items : center;
- column-gap : 15px;
- row-gap : 5px;
flex-wrap : wrap;
+ row-gap : 5px;
+ column-gap : 15px;
+ align-items : center;
+ justify-content : center;
+ height : 30px;
+ color : white;
+ background-color : #555555;
+ border-top : 1px solid #666666;
+ border-bottom : 1px solid #666666;
span {
+ padding : 3px;
font-family : 'Open Sans', sans-serif;
font-size : 11px;
font-weight : bold;
+ color : #DFDFDF;
+ cursor : pointer;
border : 1px solid;
border-radius : 3px;
- padding : 3px;
- cursor : pointer;
- color: #dfdfdf;
- &:before {
- font-family: 'Font Awesome 5 Free';
- font-size: 12px;
- margin-right: 3px;
+ &::before {
+ margin-right : 3px;
+ font-family : 'Font Awesome 5 Free';
+ font-size : 12px;
}
- &:after {
- content: '\f00d';
- font-family: 'Font Awesome 5 Free';
- font-size: 12px;
- margin-left: 3px;
+ &::after {
+ margin-left : 3px;
+ font-family : 'Font Awesome 5 Free';
+ font-size : 12px;
+ content : '\f00d';
}
&.type {
- background-color: #008000;
- border-color: #00a000;
- &:before{
- content: '\f0ad';
- }
+ background-color : #008000;
+ border-color : #00A000;
+ &::before { content : '\f0ad'; }
}
&.group {
- background-color: #505050;
- border-color: #000000;
- &:before{
- content: '\f500';
- }
+ background-color : #505050;
+ border-color : #000000;
+ &::before { content : '\f500'; }
}
&.meta {
- background-color: #000080;
- border-color: #0000a0;
- &:before{
- content: '\f05a';
- }
+ background-color : #000080;
+ border-color : #0000A0;
+ &::before { content : '\f05a'; }
}
&.system {
- background-color: #800000;
- border-color: #a00000;
- &:before{
- content: '\f518';
- }
+ background-color : #800000;
+ border-color : #A00000;
+ &::before { content : '\f518'; }
}
}
}
diff --git a/client/homebrew/pages/basePages/uiPage/uiPage.less b/client/homebrew/pages/basePages/uiPage/uiPage.less
index 913c74a2e..27f079e20 100644
--- a/client/homebrew/pages/basePages/uiPage/uiPage.less
+++ b/client/homebrew/pages/basePages/uiPage/uiPage.less
@@ -1,7 +1,7 @@
.homebrew {
.uiPage.sitePage {
.content {
- width : ~"min(90vw, 1000px)";
+ width : ~'min(90vw, 1000px)';
padding : 2% 4%;
margin-top : 25px;
margin-right : auto;
@@ -17,19 +17,19 @@
border : 2px solid black;
border-radius : 5px;
button {
+ width : 125px;
+ margin-right : 5px;
+ color : black;
background-color : transparent;
border : 1px solid black;
border-radius : 5px;
- width : 125px;
- color : black;
- margin-right : 5px;
&.active {
- background-color: #0007;
- color: white;
- &:before {
- content: '\f00c';
- font-family: 'FONT AWESOME 5 FREE';
- margin-right: 5px;
+ color : white;
+ background-color : #00000077;
+ &::before {
+ margin-right : 5px;
+ font-family : 'FONT AWESOME 5 FREE';
+ content : '\f00c';
}
}
}
diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx
index ffb6a6b40..dc2520373 100644
--- a/client/homebrew/pages/editPage/editPage.jsx
+++ b/client/homebrew/pages/editPage/editPage.jsx
@@ -102,6 +102,14 @@ const EditPage = createClass({
window.onbeforeunload = function(){};
document.removeEventListener('keydown', this.handleControlKeys);
},
+ componentDidUpdate : function(){
+ const hasChange = this.hasChanges();
+ if(this.state.isPending != hasChange){
+ this.setState({
+ isPending : hasChange
+ });
+ }
+ },
handleControlKeys : function(e){
if(!(e.ctrlKey || e.metaKey)) return;
@@ -138,15 +146,13 @@ const EditPage = createClass({
this.setState((prevState)=>({
brew : { ...prevState.brew, text: text },
- isPending : true,
htmlErrors : htmlErrors,
}), ()=>{if(this.state.autoSave) this.trySave();});
},
handleStyleChange : function(style){
this.setState((prevState)=>({
- brew : { ...prevState.brew, style: style },
- isPending : true
+ brew : { ...prevState.brew, style: style }
}), ()=>{if(this.state.autoSave) this.trySave();});
},
@@ -158,8 +164,7 @@ const EditPage = createClass({
brew : {
...prevState.brew,
...metadata
- },
- isPending : true,
+ }
}), ()=>{if(this.state.autoSave) this.trySave();});
},
@@ -247,16 +252,17 @@ const EditPage = createClass({
});
if(!res) return;
- this.savedBrew = res.body;
+ this.savedBrew = {
+ ...this.state.brew,
+ googleId : res.body.googleId ? res.body.googleId : null,
+ editId : res.body.editId,
+ shareId : res.body.shareId,
+ version : res.body.version
+ };
history.replaceState(null, null, `/edit/${this.savedBrew.editId}`);
- this.setState((prevState)=>({
- brew : { ...prevState.brew,
- googleId : this.savedBrew.googleId ? this.savedBrew.googleId : null,
- editId : this.savedBrew.editId,
- shareId : this.savedBrew.shareId,
- version : this.savedBrew.version
- },
+ this.setState(()=>({
+ brew : this.savedBrew,
isPending : false,
isSaving : false,
unsavedTime : new Date()
@@ -311,7 +317,14 @@ const EditPage = createClass({
},
renderSaveButton : function(){
- if(this.state.autoSaveWarning && this.hasChanges()){
+
+ // #1 - Currently saving, show SAVING
+ if(this.state.isSaving){
+ return
saving... ;
+ }
+
+ // #2 - Unsaved changes exist, autosave is OFF and warning timer has expired, show AUTOSAVE WARNING
+ if(this.state.isPending && this.state.autoSaveWarning){
this.setAutosaveWarning();
const elapsedTime = Math.round((new Date() - this.state.unsavedTime) / 1000 / 60);
const text = elapsedTime == 0 ? 'Autosave is OFF.' : `Autosave is OFF, and you haven't saved for ${elapsedTime} minutes.`;
@@ -324,18 +337,17 @@ const EditPage = createClass({
;
}
- if(this.state.isSaving){
- return
saving... ;
+ // #3 - Unsaved changes exist, click to save, show SAVE NOW
+ // Use trySave(true) instead of save() to use debounced save function
+ if(this.state.isPending){
+ return
this.trySave(true)} color='blue' icon='fas fa-save'>Save Now ;
}
- if(this.state.isPending && this.hasChanges()){
- return
Save Now ;
- }
- if(!this.state.isPending && !this.state.isSaving && this.state.autoSave){
+ // #4 - No unsaved changes, autosave is ON, show AUTO-SAVED
+ if(this.state.autoSave){
return
auto-saved. ;
}
- if(!this.state.isPending && !this.state.isSaving){
- return
saved. ;
- }
+ // DEFAULT - No unsaved changes, show SAVED
+ return
saved. ;
},
handleAutoSave : function(){
@@ -379,7 +391,7 @@ const EditPage = createClass({
const title = `${this.props.brew.title} ${systems}`;
const text = `Hey guys! I've been working on this homebrew. I'd love your feedback. Check it out.
-**[Homebrewery Link](${global.config.publicUrl}/share/${shareLink})**`;
+**[Homebrewery Link](${global.config.baseUrl}/share/${shareLink})**`;
return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(title.toWellFormed())}&text=${encodeURIComponent(text)}`;
},
@@ -410,7 +422,7 @@ const EditPage = createClass({
view
-
{navigator.clipboard.writeText(`${global.config.publicUrl}/share/${shareLink}`);}}>
+ {navigator.clipboard.writeText(`${global.config.baseUrl}/share/${shareLink}`);}}>
copy url
@@ -443,6 +455,7 @@ const EditPage = createClass({
reportError={this.errorReported}
renderer={this.state.brew.renderer}
userThemes={this.props.userThemes}
+ themeBundle={this.state.themeBundle}
snippetBundle={this.state.themeBundle.snippets}
updateBrew={this.updateBrew}
onCursorPageChange={this.handleEditorCursorPageChange}
diff --git a/client/homebrew/pages/editPage/editPage.less b/client/homebrew/pages/editPage/editPage.less
index f94b60c1b..184aaa1f7 100644
--- a/client/homebrew/pages/editPage/editPage.less
+++ b/client/homebrew/pages/editPage/editPage.less
@@ -1,29 +1,25 @@
@keyframes glideDown {
- 0% {transform : translate(-50% + 3px, 0px);
- opacity : 0;}
- 100% {transform : translate(-50% + 3px, 10px);
- opacity : 1;}
+ 0% {
+ opacity : 0;transform : translate(-50% + 3px, 0px);}
+ 100% {
+ opacity : 1;transform : translate(-50% + 3px, 10px);}
}
-.editPage{
- .navItem.save{
+.editPage {
+ .navItem.save {
+ position : relative;
width : 106px;
text-align : center;
- position : relative;
- &.saved{
+ &.saved {
+ color : #666666;
cursor : initial;
- color : #666;
}
}
- .googleDriveStorage {
- position : relative;
- }
- .googleDriveStorage img{
- height : 18px;
+ .googleDriveStorage { position : relative; }
+ .googleDriveStorage img {
+ height : 18px;
padding : 0px;
margin : -5px;
- &.inactive {
- filter: grayscale(1);
- }
+ &.inactive { filter : grayscale(1); }
}
}
diff --git a/client/homebrew/pages/errorPage/errors/errorIndex.js b/client/homebrew/pages/errorPage/errors/errorIndex.js
index 2c7be5d4b..9584a14b9 100644
--- a/client/homebrew/pages/errorPage/errors/errorIndex.js
+++ b/client/homebrew/pages/errorPage/errors/errorIndex.js
@@ -168,6 +168,14 @@ const errorIndex = (props)=>{
**Brew ID:** ${props.brew.brewId}`,
+ // Theme Not Valid
+ '10' : dedent`
+ ## The selected theme is not tagged as a theme.
+
+ The brew selected as a theme exists, but has not been marked for use as a theme with the \`theme:meta\` tag.
+
+ If the selected brew is your document, you may designate it as a theme by adding the \`theme:meta\` tag.`,
+
//account page when account is not defined
'50' : dedent`
## You are not signed in
diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx
index 00d0c801d..b9c1b7371 100644
--- a/client/homebrew/pages/homePage/homePage.jsx
+++ b/client/homebrew/pages/homePage/homePage.jsx
@@ -100,32 +100,32 @@ const HomePage = createClass({
return
{this.renderNavbar()}
-
-
-
-
-
+
+
+
+
+
Save current
diff --git a/client/homebrew/pages/homePage/homePage.less b/client/homebrew/pages/homePage/homePage.less
index a7523bd3c..4cf9ff4fe 100644
--- a/client/homebrew/pages/homePage/homePage.less
+++ b/client/homebrew/pages/homePage/homePage.less
@@ -1,50 +1,40 @@
-.homePage{
+.homePage {
position : relative;
- a.floatingNewButton{
+ a.floatingNewButton {
.animate(background-color);
position : absolute;
- display : block;
right : 70px;
bottom : 50px;
- z-index : 100;
z-index : 5001;
+ display : block;
padding : 1em;
- background-color : @orange;
font-size : 1.5em;
color : white;
text-decoration : none;
+ background-color : @orange;
box-shadow : 3px 3px 15px black;
- &:hover{
- background-color : darken(@orange, 20%);
- }
+ &:hover { background-color : darken(@orange, 20%); }
}
- .floatingSaveButton{
+ .floatingSaveButton {
.animateAll();
position : absolute;
- display : block;
right : 200px;
bottom : 70px;
- z-index : 100;
z-index : 5000;
+ display : block;
padding : 0.8em;
- cursor : pointer;
- background-color : @blue;
font-size : 0.8em;
color : white;
text-decoration : none;
+ cursor : pointer;
+ background-color : @blue;
box-shadow : 3px 3px 15px black;
- &:hover{
- background-color : darken(@blue, 20%);
- }
- &.show{
- right : 350px;
- }
+ &:hover { background-color : darken(@blue, 20%); }
+ &.show { right : 350px; }
}
- .navItem.save{
- background-color: @orange;
- &:hover{
- background-color: @green;
- }
+ .navItem.save {
+ background-color : @orange;
+ &:hover { background-color : @green; }
}
}
diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx
index ee2c67d5f..7aaeb3fd3 100644
--- a/client/homebrew/pages/newPage/newPage.jsx
+++ b/client/homebrew/pages/newPage/newPage.jsx
@@ -223,38 +223,39 @@ const NewPage = createClass({
render : function(){
return
{this.renderNavbar()}
-
;
}
diff --git a/client/homebrew/pages/newPage/newPage.less b/client/homebrew/pages/newPage/newPage.less
index f83827ffb..ebc44d543 100644
--- a/client/homebrew/pages/newPage/newPage.less
+++ b/client/homebrew/pages/newPage/newPage.less
@@ -1,8 +1,6 @@
-.newPage{
- .navItem.save{
- background-color: @orange;
- &:hover{
- background-color: @green;
- }
+.newPage {
+ .navItem.save {
+ background-color : @orange;
+ &:hover { background-color : @green; }
}
}
diff --git a/client/homebrew/pages/sharePage/sharePage.less b/client/homebrew/pages/sharePage/sharePage.less
index 754108506..b76dc50f9 100644
--- a/client/homebrew/pages/sharePage/sharePage.less
+++ b/client/homebrew/pages/sharePage/sharePage.less
@@ -1,9 +1,7 @@
-.sharePage{
+.sharePage {
nav .navSection.titleSection {
- flex-grow: 1;
- justify-content: center;
- }
- .content{
- overflow-y : hidden;
+ flex-grow : 1;
+ justify-content : center;
}
+ .content { overflow-y : hidden; }
}
diff --git a/client/homebrew/pages/vaultPage/vaultPage.jsx b/client/homebrew/pages/vaultPage/vaultPage.jsx
index 21a8e8363..f979aa4f7 100644
--- a/client/homebrew/pages/vaultPage/vaultPage.jsx
+++ b/client/homebrew/pages/vaultPage/vaultPage.jsx
@@ -99,14 +99,14 @@ const VaultPage = (props)=>{
setSearching(true);
setError(null);
- const title = titleRef.current.value || '';
- const author = authorRef.current.value || '';
- const count = countRef.current.value || 10;
- const v3 = v3Ref.current.checked != false;
- const legacy = legacyRef.current.checked != false;
+ const title = titleRef.current.value || '';
+ const author = authorRef.current.value || '';
+ const count = countRef.current.value || 10;
+ const v3 = v3Ref.current.checked != false;
+ const legacy = legacyRef.current.checked != false;
const sortOption = sort || 'title';
- const dirOption = dir || 'asc';
- const pageProp = page || 1;
+ const dirOption = dir || 'asc';
+ const pageProp = page || 1;
setSort(sortOption);
setdir(dirOption);
@@ -247,7 +247,7 @@ const VaultPage = (props)=>{
Some common words like "a", "after", "through", "itself", "here", etc.,
- are ignored in searches. The full list can be found
+ are ignored in searches. The full list can be found
here
@@ -286,9 +286,9 @@ const VaultPage = (props)=>{
};
const renderPaginationControls = ()=>{
- if(!totalBrews) return null;
+ if(!totalBrews || totalBrews < 10) return null;
- const countInt = parseInt(props.query.count || 20);
+ const countInt = parseInt(brewCollection.length || 20);
const totalPages = Math.ceil(totalBrews / countInt);
let startPage, endPage;
@@ -355,7 +355,7 @@ const VaultPage = (props)=>{
};
const renderFoundBrews = ()=>{
- if(searching) {
+ if(searching && !brewCollection) {
return (
Searching
@@ -395,6 +395,7 @@ const VaultPage = (props)=>{
{`Brews found: `}
{totalBrews}
+ {brewCollection.length > 10 && renderPaginationControls()}
{brewCollection.map((brew, index)=>{
return (
{
{renderNavItems()}
-
-
- {renderForm()}
-
- {renderSortBar()}
- {renderFoundBrews()}
-
-
+
+
+ {renderForm()}
+
+ {renderSortBar()}
+ {renderFoundBrews()}
+
+
);
diff --git a/client/homebrew/pages/vaultPage/vaultPage.less b/client/homebrew/pages/vaultPage/vaultPage.less
index a69bcb33b..8a5f3a714 100644
--- a/client/homebrew/pages/vaultPage/vaultPage.less
+++ b/client/homebrew/pages/vaultPage/vaultPage.less
@@ -5,7 +5,7 @@
*:not(input) { user-select : none; }
- .content .dataGroup {
+ :where(.content .dataGroup) {
width : 100%;
height : 100%;
background : white;
@@ -169,9 +169,10 @@
width : 100%;
height : 100%;
max-height : 100%;
- padding : 50px 50px 70px 50px;
+ padding : 70px 50px;
overflow-y : scroll;
background-color : #2C3E50;
+ container-type : inline-size;
h3 { font-size : 25px; }
@@ -236,6 +237,7 @@
margin-right : 40px;
color : black;
isolation : isolate;
+ transition : width 0.5s;
&::after {
position : absolute;
@@ -269,8 +271,8 @@
.links { z-index : 2; }
hr {
- margin : 0px;
visibility : hidden;
+ margin : 0px;
}
.thumbnail { z-index : -1; }
@@ -278,30 +280,37 @@
.paginationControls {
position : absolute;
+ top : 35px;
left : 50%;
display : grid;
grid-template-areas : 'previousPage currentPage nextPage';
grid-template-columns : 50px 1fr 50px;
+ gap : 20px;
place-items : center;
width : auto;
+ font-size : 15px;
translate : -50%;
+ &:last-child { top : unset; }
+
.pages {
display : flex;
grid-area : currentPage;
+ gap : 1em;
justify-content : space-evenly;
width : 100%;
height : 100%;
- padding : 5px 8px;
text-align : center;
.pageNumber {
- margin-inline : 1vw;
+ place-content : center;
+ width : fit-content;
+ min-width : 2em;
font-family : 'Open Sans';
font-weight : 900;
color : white;
- text-underline-position : under;
text-wrap : nowrap;
+ text-underline-position : under;
cursor : pointer;
&.currentPage {
@@ -329,7 +338,6 @@
}
}
}
-
}
@keyframes trailingDots {
@@ -344,8 +352,7 @@
100% { content : ' ...'; }
}
-// media query for when the page is smaller than 1079 px in width
-@media screen and (max-width : 1079px) {
+@container (width < 670px) {
.vaultPage {
.dataGroup.form .brewLookup { padding : 1px 20px 20px 10px; }
diff --git a/client/icons/customIcons.less b/client/icons/customIcons.less
index 1c8d1bd47..a2caffc57 100644
--- a/client/icons/customIcons.less
+++ b/client/icons/customIcons.less
@@ -1,84 +1,34 @@
.fac {
display : inline-block;
- background-color : currentColor;
- mask-size : contain;
- mask-repeat : no-repeat;
- mask-position : center;
width : 1em;
aspect-ratio : 1;
+ background-color : currentColor;
+ mask-repeat : no-repeat;
+ mask-position : center;
+ mask-size : contain;
}
-.position-top-left {
- mask-image: url('../icons/position-top-left.svg');
-}
-.position-top-right {
- mask-image: url('../icons/position-top-right.svg');
-}
-.position-bottom-left {
- mask-image: url('../icons/position-bottom-left.svg');
-}
-.position-bottom-right {
- mask-image: url('../icons/position-bottom-right.svg');
-}
-.position-top {
- mask-image: url('../icons/position-top.svg');
-}
-.position-right {
- mask-image: url('../icons/position-right.svg');
-}
-.position-bottom {
- mask-image: url('../icons/position-bottom.svg');
-}
-.position-left {
- mask-image: url('../icons/position-left.svg');
-}
-.mask-edge {
- mask-image: url('../icons/mask-edge.svg');
-}
-.mask-corner {
- mask-image: url('../icons/mask-corner.svg');
-}
-.mask-center {
- mask-image: url('../icons/mask-center.svg');
-}
-.book-front-cover {
- mask-image: url('../icons/book-front-cover.svg');
-}
-.book-back-cover {
- mask-image: url('../icons/book-back-cover.svg');
-}
-.book-inside-cover {
- mask-image: url('../icons/book-inside-cover.svg');
-}
-.book-part-cover {
- mask-image: url('../icons/book-part-cover.svg');
-}
-.image-wrap-left {
- mask-image: url('../icons/image-wrap-left.svg');
-}
-.image-wrap-right {
- mask-image: url('../icons/image-wrap-right.svg');
-}
-.davek {
- mask-image: url('../icons/Davek.svg');
-}
-.rellanic {
- mask-image: url('../icons/Rellanic.svg');
-}
-.iokharic {
- mask-image: url('../icons/Iokharic.svg');
-}
-.zoom-to-fit {
- mask-image: url('../icons/zoom-to-fit.svg');
-}
-.fit-width {
- mask-image: url('../icons/fit-width.svg');
-}
-.single-spread {
- mask-image: url('../icons/single-spread.svg');
-}
-.facing-spread {
- mask-image: url('../icons/facing-spread.svg');
-}
-.flow-spread {
- mask-image: url('../icons/flow-spread.svg');
-}
+.position-top-left { mask-image : url('../icons/position-top-left.svg'); }
+.position-top-right { mask-image : url('../icons/position-top-right.svg'); }
+.position-bottom-left { mask-image : url('../icons/position-bottom-left.svg'); }
+.position-bottom-right { mask-image : url('../icons/position-bottom-right.svg'); }
+.position-top { mask-image : url('../icons/position-top.svg'); }
+.position-right { mask-image : url('../icons/position-right.svg'); }
+.position-bottom { mask-image : url('../icons/position-bottom.svg'); }
+.position-left { mask-image : url('../icons/position-left.svg'); }
+.mask-edge { mask-image : url('../icons/mask-edge.svg'); }
+.mask-corner { mask-image : url('../icons/mask-corner.svg'); }
+.mask-center { mask-image : url('../icons/mask-center.svg'); }
+.book-front-cover { mask-image : url('../icons/book-front-cover.svg'); }
+.book-back-cover { mask-image : url('../icons/book-back-cover.svg'); }
+.book-inside-cover { mask-image : url('../icons/book-inside-cover.svg'); }
+.book-part-cover { mask-image : url('../icons/book-part-cover.svg'); }
+.image-wrap-left { mask-image : url('../icons/image-wrap-left.svg'); }
+.image-wrap-right { mask-image : url('../icons/image-wrap-right.svg'); }
+.davek { mask-image : url('../icons/Davek.svg'); }
+.rellanic { mask-image : url('../icons/Rellanic.svg'); }
+.iokharic { mask-image : url('../icons/Iokharic.svg'); }
+.zoom-to-fit { mask-image : url('../icons/zoom-to-fit.svg'); }
+.fit-width { mask-image : url('../icons/fit-width.svg'); }
+.single-spread { mask-image : url('../icons/single-spread.svg'); }
+.facing-spread { mask-image : url('../icons/facing-spread.svg'); }
+.flow-spread { mask-image : url('../icons/flow-spread.svg'); }
diff --git a/package-lock.json b/package-lock.json
index bd3f71491..69cc1cade 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,29 +1,28 @@
{
"name": "homebrewery",
- "version": "3.17.0",
+ "version": "3.18.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "homebrewery",
- "version": "3.17.0",
+ "version": "3.18.1",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
- "@babel/core": "^7.26.8",
- "@babel/plugin-transform-runtime": "^7.26.8",
- "@babel/preset-env": "^7.26.8",
+ "@babel/core": "^7.26.9",
+ "@babel/plugin-transform-runtime": "^7.26.9",
+ "@babel/preset-env": "^7.26.9",
"@babel/preset-react": "^7.26.3",
- "@googleapis/drive": "^8.14.0",
+ "@googleapis/drive": "^8.16.0",
"body-parser": "^1.20.2",
"classnames": "^2.5.1",
"codemirror": "^5.65.6",
"cookie-parser": "^1.4.7",
- "core-js": "^3.40.0",
+ "core-js": "^3.41.0",
"cors": "^2.8.5",
"create-react-class": "^15.7.0",
"dedent-tabs": "^0.10.3",
- "dompurify": "^3.2.4",
"expr-eval": "^2.0.2",
"express": "^4.21.2",
"express-async-handler": "^1.2.0",
@@ -34,20 +33,21 @@
"jwt-simple": "^0.5.6",
"less": "^3.13.1",
"lodash": "^4.17.21",
- "marked": "13.0.3",
- "marked-emoji": "^1.4.3",
- "marked-extended-tables": "^1.1.0",
+ "marked": "14.0.0",
+ "marked-emoji": "^2.0.0",
+ "marked-extended-tables": "^2.0.1",
"marked-gfm-heading-id": "^4.0.1",
"marked-smartypants-lite": "^1.0.3",
+ "marked-subsuper-text": "^1.0.3",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.30.1",
- "mongoose": "^8.10.0",
- "nanoid": "5.0.9",
+ "mongoose": "^8.12.1",
+ "nanoid": "5.1.3",
"nconf": "^0.12.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-frame-component": "^4.1.3",
- "react-router": "^7.1.5",
+ "react-router": "^7.3.0",
"sanitize-filename": "1.6.3",
"superagent": "^10.1.1",
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
@@ -55,15 +55,15 @@
"devDependencies": {
"@stylistic/stylelint-plugin": "^3.1.2",
"babel-plugin-transform-import-meta": "^2.3.2",
- "eslint": "^9.20.0",
+ "eslint": "^9.22.0",
"eslint-plugin-jest": "^28.11.0",
"eslint-plugin-react": "^7.37.4",
- "globals": "^15.14.0",
+ "globals": "^16.0.0",
"jest": "^29.7.0",
"jest-expect-message": "^1.1.3",
"jsdom-global": "^3.0.2",
"postcss-less": "^6.0.0",
- "stylelint": "^16.14.1",
+ "stylelint": "^16.16.0",
"stylelint-config-recess-order": "^6.0.0",
"stylelint-config-recommended": "^15.0.0",
"supertest": "^7.0.0"
@@ -110,22 +110,21 @@
}
},
"node_modules/@babel/core": {
- "version": "7.26.8",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.8.tgz",
- "integrity": "sha512-l+lkXCHS6tQEc5oUpK28xBOZ6+HwaH7YwoYQbLFiYb4nS2/l1tKnZEtEWkD0GuiYdvArf9qBS0XlQGXzPMsNqQ==",
+ "version": "7.26.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz",
+ "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==",
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.26.2",
- "@babel/generator": "^7.26.8",
+ "@babel/generator": "^7.26.9",
"@babel/helper-compilation-targets": "^7.26.5",
"@babel/helper-module-transforms": "^7.26.0",
- "@babel/helpers": "^7.26.7",
- "@babel/parser": "^7.26.8",
- "@babel/template": "^7.26.8",
- "@babel/traverse": "^7.26.8",
- "@babel/types": "^7.26.8",
- "@types/gensync": "^1.0.0",
+ "@babel/helpers": "^7.26.9",
+ "@babel/parser": "^7.26.9",
+ "@babel/template": "^7.26.9",
+ "@babel/traverse": "^7.26.9",
+ "@babel/types": "^7.26.9",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -141,13 +140,13 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.26.8",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.8.tgz",
- "integrity": "sha512-ef383X5++iZHWAXX0SXQR6ZyQhw/0KtTkrTz61WXRhFM6dhpHulO/RJz79L8S6ugZHJkOOkUrUdxgdF2YiPFnA==",
+ "version": "7.26.9",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz",
+ "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==",
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.26.8",
- "@babel/types": "^7.26.8",
+ "@babel/parser": "^7.26.9",
+ "@babel/types": "^7.26.9",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2"
@@ -377,25 +376,25 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.26.7",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz",
- "integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==",
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz",
+ "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==",
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.25.9",
- "@babel/types": "^7.26.7"
+ "@babel/template": "^7.26.9",
+ "@babel/types": "^7.26.10"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.26.8",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.8.tgz",
- "integrity": "sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw==",
+ "version": "7.26.9",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz",
+ "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.26.8"
+ "@babel/types": "^7.26.9"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -974,11 +973,12 @@
}
},
"node_modules/@babel/plugin-transform-for-of": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz",
- "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==",
+ "version": "7.26.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz",
+ "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.26.5",
"@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
},
"engines": {
@@ -1406,9 +1406,9 @@
}
},
"node_modules/@babel/plugin-transform-runtime": {
- "version": "7.26.8",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.8.tgz",
- "integrity": "sha512-H0jlQxFMI0Q8SyGPsj9pO3ygVQRxPkIGytsL3m1Zqca8KrCPpMlvh+e2dxknqdfS8LFwBw+PpiYPD9qy/FPQpA==",
+ "version": "7.26.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz",
+ "integrity": "sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ==",
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.25.9",
@@ -1558,9 +1558,9 @@
}
},
"node_modules/@babel/preset-env": {
- "version": "7.26.8",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.8.tgz",
- "integrity": "sha512-um7Sy+2THd697S4zJEfv/U5MHGJzkN2xhtsR3T/SWRbVSic62nbISh51VVfU9JiO/L/Z97QczHTaFVkOU8IzNg==",
+ "version": "7.26.9",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz",
+ "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==",
"license": "MIT",
"dependencies": {
"@babel/compat-data": "^7.26.8",
@@ -1592,7 +1592,7 @@
"@babel/plugin-transform-dynamic-import": "^7.25.9",
"@babel/plugin-transform-exponentiation-operator": "^7.26.3",
"@babel/plugin-transform-export-namespace-from": "^7.25.9",
- "@babel/plugin-transform-for-of": "^7.25.9",
+ "@babel/plugin-transform-for-of": "^7.26.9",
"@babel/plugin-transform-function-name": "^7.25.9",
"@babel/plugin-transform-json-strings": "^7.25.9",
"@babel/plugin-transform-literals": "^7.25.9",
@@ -1688,9 +1688,10 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.9.tgz",
- "integrity": "sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg==",
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz",
+ "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==",
+ "license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -1699,30 +1700,30 @@
}
},
"node_modules/@babel/template": {
- "version": "7.26.8",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.8.tgz",
- "integrity": "sha512-iNKaX3ZebKIsCvJ+0jd6embf+Aulaa3vNBqZ41kM7iTWjx5qzWKXGHiJUW3+nTpQ18SG11hdF8OAzKrpXkb96Q==",
+ "version": "7.26.9",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz",
+ "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.26.2",
- "@babel/parser": "^7.26.8",
- "@babel/types": "^7.26.8"
+ "@babel/parser": "^7.26.9",
+ "@babel/types": "^7.26.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.26.8",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.8.tgz",
- "integrity": "sha512-nic9tRkjYH0oB2dzr/JoGIm+4Q6SuYeLEiIiZDwBscRMYFJ+tMAz98fuel9ZnbXViA2I0HVSSRRK8DW5fjXStA==",
+ "version": "7.26.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz",
+ "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.26.2",
- "@babel/generator": "^7.26.8",
- "@babel/parser": "^7.26.8",
- "@babel/template": "^7.26.8",
- "@babel/types": "^7.26.8",
+ "@babel/generator": "^7.26.9",
+ "@babel/parser": "^7.26.9",
+ "@babel/template": "^7.26.9",
+ "@babel/types": "^7.26.9",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -1740,9 +1741,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.26.8",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.8.tgz",
- "integrity": "sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA==",
+ "version": "7.26.10",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz",
+ "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==",
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.25.9",
@@ -1862,12 +1863,13 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.19.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz",
- "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==",
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
+ "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@eslint/object-schema": "^2.1.4",
+ "@eslint/object-schema": "^2.1.6",
"debug": "^4.3.1",
"minimatch": "^3.1.2"
},
@@ -1875,11 +1877,22 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@eslint/core": {
- "version": "0.10.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz",
- "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==",
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz",
+ "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==",
"dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
+ "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==",
+ "dev": true,
+ "license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
@@ -1888,10 +1901,11 @@
}
},
"node_modules/@eslint/eslintrc": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz",
- "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz",
+ "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
@@ -1915,6 +1929,7 @@
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=18"
},
@@ -1923,9 +1938,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.20.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz",
- "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==",
+ "version": "9.22.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz",
+ "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1933,21 +1948,23 @@
}
},
"node_modules/@eslint/object-schema": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz",
- "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==",
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz",
- "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==",
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz",
+ "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^0.10.0",
+ "@eslint/core": "^0.12.0",
"levn": "^0.4.1"
},
"engines": {
@@ -1955,9 +1972,10 @@
}
},
"node_modules/@googleapis/drive": {
- "version": "8.14.0",
- "resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.14.0.tgz",
- "integrity": "sha512-AOokfpP6pCdcJXWA8khaCEgbGpWYavWTdAAhL4idbbf2VCQcJ2f7vPalAYNu6a4Sfj0Ly4Ehnd1xw9J9TixB1A==",
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.16.0.tgz",
+ "integrity": "sha512-Xi2mMrUTQ+gsfyouRGd0pfnL+jjg4n4sjKsJruM1y4DknuRfdSBTk5E//WrL0YJ/CqpcBgyd7L8DvaPRtxZD3Q==",
+ "license": "Apache-2.0",
"dependencies": {
"googleapis-common": "^7.0.0"
},
@@ -2015,10 +2033,11 @@
}
},
"node_modules/@humanwhocodes/retry": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz",
- "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==",
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz",
+ "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
"node": ">=18.18"
},
@@ -2685,10 +2704,11 @@
}
},
"node_modules/@keyv/serialize": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.2.tgz",
- "integrity": "sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.3.tgz",
+ "integrity": "sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"buffer": "^6.0.3"
}
@@ -2712,6 +2732,7 @@
"url": "https://feross.org/support"
}
],
+ "license": "MIT",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
@@ -2871,12 +2892,6 @@
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
"dev": true
},
- "node_modules/@types/gensync": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@types/gensync/-/gensync-1.0.4.tgz",
- "integrity": "sha512-C3YYeRQWp2fmq9OryX+FoDy8nXS6scQ7dPptD8LnFDAUNcKWJjXQKDNJD3HVm+kOUsXhTOkpi69vI4EuAr95bA==",
- "license": "MIT"
- },
"node_modules/@types/graceful-fs": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
@@ -2918,7 +2933,8 @@
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@types/node": {
"version": "22.1.0",
@@ -2937,12 +2953,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@types/trusted-types": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
- "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
- "optional": true
- },
"node_modules/@types/webidl-conversions": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
@@ -3134,6 +3144,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"dev": true,
+ "license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@@ -3146,6 +3157,7 @@
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true,
+ "license": "MIT",
"peerDependencies": {
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
@@ -3199,6 +3211,7 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -3865,6 +3878,16 @@
"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",
@@ -4171,9 +4194,9 @@
}
},
"node_modules/bson": {
- "version": "6.10.2",
- "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.2.tgz",
- "integrity": "sha512-5afhLTjqDSA3akH56E+/2J6kTDuSIlBxyXPdQslj9hcIgOUE378xdOfZvC/9q3LifJNI6KR/juZ+d0NRNYBwXg==",
+ "version": "6.10.3",
+ "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.3.tgz",
+ "integrity": "sha512-MTxGsqgYTwfshYWTRdmZRC+M7FnG1b4y7RO7p2k3X24Wq0yv1m77Wsj0BzlPzd/IowgESfsruQCUToa7vbOpPQ==",
"license": "Apache-2.0",
"engines": {
"node": ">=16.20.1"
@@ -4243,22 +4266,24 @@
}
},
"node_modules/cacheable": {
- "version": "1.8.7",
- "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.8.7.tgz",
- "integrity": "sha512-AbfG7dAuYNjYxFUtL1lAqmlWdxczCJ47w7cFjhGcnGnUdwSo6VgmSojfoW3tUI12HUkgTJ5kqj78yyq6TsFtlg==",
+ "version": "1.8.9",
+ "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.8.9.tgz",
+ "integrity": "sha512-FicwAUyWnrtnd4QqYAoRlNs44/a1jTL7XDKqm5gJ90wz1DQPlC7U2Rd1Tydpv+E7WAr4sQHuw8Q8M3nZMAyecQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "hookified": "^1.6.0",
- "keyv": "^5.2.3"
+ "hookified": "^1.7.1",
+ "keyv": "^5.3.1"
}
},
"node_modules/cacheable/node_modules/keyv": {
- "version": "5.2.3",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.2.3.tgz",
- "integrity": "sha512-AGKecUfzrowabUv0bH1RIR5Vf7w+l4S3xtQAypKaUpTdIR1EbrAcTxHCrpo9Q+IWeUlFE2palRtgIQcgm+PQJw==",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.3.1.tgz",
+ "integrity": "sha512-13hQT2q2VIwOoaJdJa7nY3J8UVbYtMTJFHnwm9LI+SaQRfUiM6Em9KZeOVTCKbMnGcRIL3NSUFpAdjZCq24nLQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@keyv/serialize": "^1.0.2"
+ "@keyv/serialize": "^1.0.3"
}
},
"node_modules/cached-path-relative": {
@@ -4385,6 +4410,20 @@
"fsevents": "~2.3.2"
}
},
+ "node_modules/chokidar/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/chokidar/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
@@ -4687,10 +4726,11 @@
}
},
"node_modules/core-js": {
- "version": "3.40.0",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz",
- "integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==",
+ "version": "3.41.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.41.0.tgz",
+ "integrity": "sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==",
"hasInstallScript": true,
+ "license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
@@ -5344,15 +5384,6 @@
"npm": ">=1.2"
}
},
- "node_modules/dompurify": {
- "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"
- }
- },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -5397,9 +5428,10 @@
"license": "ISC"
},
"node_modules/elliptic": {
- "version": "6.6.0",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz",
- "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==",
+ "version": "6.6.1",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz",
+ "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==",
+ "license": "MIT",
"dependencies": {
"bn.js": "^4.11.9",
"brorand": "^1.1.0",
@@ -5665,22 +5697,23 @@
"license": "MIT"
},
"node_modules/eslint": {
- "version": "9.20.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.0.tgz",
- "integrity": "sha512-aL4F8167Hg4IvsW89ejnpTwx+B/UQRzJPGgbIOl+4XqffWsahVVsLEWoZvnrVuwpWmnRd7XeXmQI1zlKcFDteA==",
+ "version": "9.22.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz",
+ "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.19.0",
- "@eslint/core": "^0.11.0",
- "@eslint/eslintrc": "^3.2.0",
- "@eslint/js": "9.20.0",
- "@eslint/plugin-kit": "^0.2.5",
+ "@eslint/config-array": "^0.19.2",
+ "@eslint/config-helpers": "^0.1.0",
+ "@eslint/core": "^0.12.0",
+ "@eslint/eslintrc": "^3.3.0",
+ "@eslint/js": "9.22.0",
+ "@eslint/plugin-kit": "^0.2.7",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.4.1",
+ "@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6",
"@types/json-schema": "^7.0.15",
"ajv": "^6.12.4",
@@ -5688,7 +5721,7 @@
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.2.0",
+ "eslint-scope": "^8.3.0",
"eslint-visitor-keys": "^4.2.0",
"espree": "^10.3.0",
"esquery": "^1.5.0",
@@ -5813,10 +5846,11 @@
}
},
"node_modules/eslint-scope": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
- "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
+ "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^5.2.0"
@@ -5841,19 +5875,6 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/eslint/node_modules/@eslint/core": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz",
- "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@types/json-schema": "^7.0.15"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- }
- },
"node_modules/eslint/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -5924,6 +5945,7 @@
"resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
"integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"acorn": "^8.14.0",
"acorn-jsx": "^5.3.2",
@@ -5941,6 +5963,7 @@
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
"integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
@@ -5980,6 +6003,7 @@
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"estraverse": "^5.2.0"
},
@@ -6374,6 +6398,13 @@
"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",
@@ -6448,10 +6479,11 @@
}
},
"node_modules/flatted": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
- "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
- "dev": true
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
},
"node_modules/for-each": {
"version": "0.3.3",
@@ -6547,6 +6579,25 @@
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"license": "ISC"
},
+ "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": "Upgrade to fsevents v2 to mitigate potential security issues",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "dependencies": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ },
+ "engines": {
+ "node": ">= 4.0"
+ }
+ },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -6813,10 +6864,11 @@
}
},
"node_modules/globals": {
- "version": "15.14.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
- "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==",
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.0.0.tgz",
+ "integrity": "sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=18"
},
@@ -7135,10 +7187,11 @@
}
},
"node_modules/hookified": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.6.0.tgz",
- "integrity": "sha512-se7cpwTA+iA/eY548Bu03JJqBiEZAqU2jnyKdj5B5qurtBg64CZGHTgqCv4Yh7NWu6FGI09W61MCq+NoPj9GXA==",
- "dev": true
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.7.1.tgz",
+ "integrity": "sha512-OXcdHsXeOiD7OJ5zvWj8Oy/6RCdLwntAX+wUrfemNcMGn6sux4xbEHi2QXwqePYhjQ/yvxxq2MvCRirdlHscBw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/html-encoding-sniffer": {
"version": "4.0.0",
@@ -8542,6 +8595,21 @@
"fsevents": "^2.3.2"
}
},
+ "node_modules/jest-haste-map/node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
"node_modules/jest-leak-detector": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
@@ -9425,7 +9493,8 @@
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/json-stable-stringify": {
"version": "0.0.1",
@@ -9835,9 +9904,9 @@
}
},
"node_modules/marked": {
- "version": "13.0.3",
- "resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz",
- "integrity": "sha512-rqRix3/TWzE9rIoFGIn8JmsVfhiuC8VIQ8IdX5TfzmeBucdY05/0UlzKaw0eVtpcN/OdVFpBk7CjKGo9iHJ/zA==",
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz",
+ "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==",
"license": "MIT",
"bin": {
"marked": "bin/marked.js"
@@ -9847,17 +9916,19 @@
}
},
"node_modules/marked-emoji": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/marked-emoji/-/marked-emoji-1.4.3.tgz",
- "integrity": "sha512-HDZx1VOmzu7XT2QNKWfrHGbNRMTWKj9XD78yrcH1madD30HpGLMODPOmKr/e7CA7NKKXkpXXNdndQn++ysXmHg==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/marked-emoji/-/marked-emoji-2.0.0.tgz",
+ "integrity": "sha512-oTZ8fqbdVDHFQnqCE1tg4ND7zEd7cUVNHliR9Ldu4eys0J86uz/5Uksjd2mt5xcX16OOScDEr3MmPjajI/ZDHA==",
+ "license": "MIT",
"peerDependencies": {
"marked": ">=4 <16"
}
},
"node_modules/marked-extended-tables": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/marked-extended-tables/-/marked-extended-tables-1.1.0.tgz",
- "integrity": "sha512-xPQlnmr/mpIJEjwg9/guSKzxoKu7hyCD/sM59mcZc+nMIh2JuVM2se+kCa1Jo1UH+BEHcNlZ221ziJ/cOxAgCA==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/marked-extended-tables/-/marked-extended-tables-2.0.1.tgz",
+ "integrity": "sha512-DV4Si978ZdaFbycIxzG4TdaNMtC0J8QfIKj1UOCejgJHwVjVJse8DNdJriWDeo/n74DWVYpRC6S56AdgWDPrPA==",
+ "license": "MIT",
"peerDependencies": {
"marked": ">=3 <16"
}
@@ -9883,6 +9954,15 @@
"marked": ">=4 <16"
}
},
+ "node_modules/marked-subsuper-text": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/marked-subsuper-text/-/marked-subsuper-text-1.0.3.tgz",
+ "integrity": "sha512-v5hVVJo6L7HQtplIT8OYNbRWMCGupXYuZ7U9qTsC4yLDtfw24oM5xmWVYfzqzX6hD7KneMfDssMPt6U7fslbxQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "marked": ">=3 <16"
+ }
+ },
"node_modules/markedLegacy": {
"name": "marked",
"version": "0.3.19",
@@ -10238,14 +10318,14 @@
}
},
"node_modules/mongoose": {
- "version": "8.10.0",
- "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.10.0.tgz",
- "integrity": "sha512-nLhk3Qrv6q/HpD2k1O7kbBqsq+/kmKpdv5KJ+LLhQlII3e1p/SSLoLP6jMuSiU6+iLK7zFw4T1niAk3mA3QVug==",
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.12.1.tgz",
+ "integrity": "sha512-UW22y8QFVYmrb36hm8cGncfn4ARc/XsYWQwRTaj0gxtQk1rDuhzDO1eBantS+hTTatfAIS96LlRCJrcNHvW5+Q==",
"license": "MIT",
"dependencies": {
- "bson": "^6.10.1",
+ "bson": "^6.10.3",
"kareem": "2.6.3",
- "mongodb": "~6.13.0",
+ "mongodb": "~6.14.0",
"mpath": "0.9.0",
"mquery": "5.0.0",
"ms": "2.1.3",
@@ -10321,13 +10401,13 @@
}
},
"node_modules/mongoose/node_modules/mongodb": {
- "version": "6.13.0",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.13.0.tgz",
- "integrity": "sha512-KeESYR5TEaFxOuwRqkOm3XOsMqCSkdeDMjaW5u2nuKfX7rqaofp7JQGoi7sVqQcNJTKuveNbzZtWMstb8ABP6Q==",
+ "version": "6.14.2",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.14.2.tgz",
+ "integrity": "sha512-kMEHNo0F3P6QKDq17zcDuPeaywK/YaJVCEQRzPF3TOM/Bl9MFg64YE5Tu7ifj37qZJMhwU1tl2Ioivws5gRG5Q==",
"license": "Apache-2.0",
"dependencies": {
"@mongodb-js/saslprep": "^1.1.9",
- "bson": "^6.10.1",
+ "bson": "^6.10.3",
"mongodb-connection-string-url": "^3.0.0"
},
"engines": {
@@ -10392,10 +10472,17 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
+ "node_modules/nan": {
+ "version": "2.22.2",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz",
+ "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/nanoid": {
- "version": "5.0.9",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz",
- "integrity": "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==",
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.3.tgz",
+ "integrity": "sha512-zAbEOEr7u2CbxwoMRlz/pNSpRP0FdAU4pRaYunCdEezWohXFs+a0Xw7RfkKaezMsmSM1vttcLthJtwRnVtOfHQ==",
"funding": [
{
"type": "github",
@@ -11258,9 +11345,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.1",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
- "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
+ "version": "8.5.3",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
+ "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
"dev": true,
"funding": [
{
@@ -11666,9 +11753,9 @@
"license": "MIT"
},
"node_modules/react-router": {
- "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==",
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.3.0.tgz",
+ "integrity": "sha512-466f2W7HIWaNXTKM5nHTqNxLrHTyXybm7R0eBlVSt0k/u55tTCDO194OIx/NrYD4TS5SXKTNekXfT37kMKUjgw==",
"license": "MIT",
"dependencies": {
"@types/cookie": "^0.6.0",
@@ -13052,9 +13139,9 @@
"license": "ISC"
},
"node_modules/stylelint": {
- "version": "16.14.1",
- "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.14.1.tgz",
- "integrity": "sha512-oqCL7AC3786oTax35T/nuLL8p2C3k/8rHKAooezrPGRvUX0wX+qqs5kMWh5YYT4PHQgVDobHT4tw55WgpYG6Sw==",
+ "version": "16.16.0",
+ "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.16.0.tgz",
+ "integrity": "sha512-40X5UOb/0CEFnZVEHyN260HlSSUxPES+arrUphOumGWgXERHfwCD0kNBVILgQSij8iliYVwlc0V7M5bcLP9vPg==",
"dev": true,
"funding": [
{
@@ -13081,7 +13168,7 @@
"debug": "^4.3.7",
"fast-glob": "^3.3.3",
"fastest-levenshtein": "^1.0.16",
- "file-entry-cache": "^10.0.5",
+ "file-entry-cache": "^10.0.7",
"global-modules": "^2.0.0",
"globby": "^11.1.0",
"globjoin": "^0.1.4",
@@ -13095,14 +13182,14 @@
"micromatch": "^4.0.8",
"normalize-path": "^3.0.0",
"picocolors": "^1.1.1",
- "postcss": "^8.5.1",
+ "postcss": "^8.5.3",
"postcss-resolve-nested-selector": "^0.1.6",
"postcss-safe-parser": "^7.0.1",
- "postcss-selector-parser": "^7.0.0",
+ "postcss-selector-parser": "^7.1.0",
"postcss-value-parser": "^4.2.0",
"resolve-from": "^5.0.0",
"string-width": "^4.2.3",
- "supports-hyperlinks": "^3.1.0",
+ "supports-hyperlinks": "^3.2.0",
"svg-tags": "^1.0.0",
"table": "^6.9.0",
"write-file-atomic": "^5.0.1"
@@ -13217,23 +13304,25 @@
"license": "MIT"
},
"node_modules/stylelint/node_modules/file-entry-cache": {
- "version": "10.0.5",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.0.5.tgz",
- "integrity": "sha512-umpQsJrBNsdMDgreSryMEXvJh66XeLtZUwA8Gj7rHGearGufUFv6rB/bcXRFsiGWw/VeSUgUofF4Rf2UKEOrTA==",
+ "version": "10.0.7",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.0.7.tgz",
+ "integrity": "sha512-txsf5fu3anp2ff3+gOJJzRImtrtm/oa9tYLN0iTuINZ++EyVR/nRrg2fKYwvG/pXDofcrvvb0scEbX3NyW/COw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "flat-cache": "^6.1.5"
+ "flat-cache": "^6.1.7"
}
},
"node_modules/stylelint/node_modules/flat-cache": {
- "version": "6.1.5",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.5.tgz",
- "integrity": "sha512-QR+2kN38f8nMfiIQ1LHYjuDEmZNZVjxuxY+HufbS3BW0EX01Q5OnH7iduOYRutmgiXb797HAKcXUeXrvRjjgSQ==",
+ "version": "6.1.7",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.7.tgz",
+ "integrity": "sha512-qwZ4xf1v1m7Rc9XiORly31YaChvKt6oNVHuqqZcoED/7O+ToyNVGobKsIAopY9ODcWpEDKEBAbrSOCBHtNQvew==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cacheable": "^1.8.7",
- "flatted": "^3.3.2",
- "hookified": "^1.6.0"
+ "cacheable": "^1.8.9",
+ "flatted": "^3.3.3",
+ "hookified": "^1.7.1"
}
},
"node_modules/stylelint/node_modules/ignore": {
@@ -13246,9 +13335,9 @@
}
},
"node_modules/stylelint/node_modules/postcss-selector-parser": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz",
- "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz",
+ "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -13395,10 +13484,11 @@
}
},
"node_modules/supports-hyperlinks": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz",
- "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz",
+ "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0",
"supports-color": "^7.0.0"
@@ -13407,7 +13497,7 @@
"node": ">=14.18"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1"
}
},
"node_modules/supports-hyperlinks/node_modules/has-flag": {
@@ -13415,6 +13505,7 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -13424,6 +13515,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -14135,6 +14227,7 @@
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"punycode": "^2.1.0"
}
diff --git a/package.json b/package.json
index 342af4d6e..96528b786 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "homebrewery",
"description": "Create authentic looking D&D homebrews using only markdown",
- "version": "3.17.0",
+ "version": "3.18.1",
"type": "module",
"engines": {
"npm": "^10.2.x",
@@ -39,7 +39,6 @@
"test:definition-lists": "jest tests/markdown/definition-lists.test.js --verbose --noStackTrace",
"test:hard-breaks": "jest tests/markdown/hard-breaks.test.js --verbose --noStackTrace",
"test:non-breaking-spaces": "jest tests/markdown/non-breaking-spaces.test.js --verbose --noStackTrace",
- "test:paragraph-justification": "jest tests/markdown/paragraph-justification.test.js --verbose --noStackTrace",
"test:emojis": "jest tests/markdown/emojis.test.js --verbose --noStackTrace",
"test:route": "jest tests/routes/static-pages.test.js --verbose",
"test:safehtml": "jest tests/html/safeHTML.test.js --verbose",
@@ -85,20 +84,19 @@
]
},
"dependencies": {
- "@babel/core": "^7.26.8",
- "@babel/plugin-transform-runtime": "^7.26.8",
- "@babel/preset-env": "^7.26.8",
+ "@babel/core": "^7.26.9",
+ "@babel/plugin-transform-runtime": "^7.26.9",
+ "@babel/preset-env": "^7.26.9",
"@babel/preset-react": "^7.26.3",
- "@googleapis/drive": "^8.14.0",
+ "@googleapis/drive": "^8.16.0",
"body-parser": "^1.20.2",
"classnames": "^2.5.1",
"codemirror": "^5.65.6",
"cookie-parser": "^1.4.7",
- "core-js": "^3.40.0",
+ "core-js": "^3.41.0",
"cors": "^2.8.5",
"create-react-class": "^15.7.0",
"dedent-tabs": "^0.10.3",
- "dompurify": "^3.2.4",
"expr-eval": "^2.0.2",
"express": "^4.21.2",
"express-async-handler": "^1.2.0",
@@ -109,20 +107,21 @@
"jwt-simple": "^0.5.6",
"less": "^3.13.1",
"lodash": "^4.17.21",
- "marked": "13.0.3",
- "marked-emoji": "^1.4.3",
- "marked-extended-tables": "^1.1.0",
+ "marked": "14.0.0",
+ "marked-emoji": "^2.0.0",
+ "marked-extended-tables": "^2.0.1",
"marked-gfm-heading-id": "^4.0.1",
"marked-smartypants-lite": "^1.0.3",
+ "marked-subsuper-text": "^1.0.3",
"markedLegacy": "npm:marked@^0.3.19",
"moment": "^2.30.1",
- "mongoose": "^8.10.0",
- "nanoid": "5.0.9",
+ "mongoose": "^8.12.1",
+ "nanoid": "5.1.3",
"nconf": "^0.12.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-frame-component": "^4.1.3",
- "react-router": "^7.1.5",
+ "react-router": "^7.3.0",
"sanitize-filename": "1.6.3",
"superagent": "^10.1.1",
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
@@ -130,15 +129,15 @@
"devDependencies": {
"@stylistic/stylelint-plugin": "^3.1.2",
"babel-plugin-transform-import-meta": "^2.3.2",
- "eslint": "^9.20.0",
+ "eslint": "^9.22.0",
"eslint-plugin-jest": "^28.11.0",
"eslint-plugin-react": "^7.37.4",
- "globals": "^15.14.0",
+ "globals": "^16.0.0",
"jest": "^29.7.0",
"jest-expect-message": "^1.1.3",
"jsdom-global": "^3.0.2",
"postcss-less": "^6.0.0",
- "stylelint": "^16.14.1",
+ "stylelint": "^16.16.0",
"stylelint-config-recess-order": "^6.0.0",
"stylelint-config-recommended": "^15.0.0",
"supertest": "^7.0.0"
diff --git a/scripts/buildHomebrew.js b/scripts/buildHomebrew.js
index 656714d87..4d55a4176 100644
--- a/scripts/buildHomebrew.js
+++ b/scripts/buildHomebrew.js
@@ -10,7 +10,7 @@ import babel from '@babel/core';
import babelConfig from '../babel.config.json' with { type : 'json' };
import less from 'less';
-const isDev = !!process.argv.find((arg) => arg === '--dev');
+const isDev = !!process.argv.find((arg)=>arg === '--dev');
const babelify = async (code)=>(await babel.transformAsync(code, babelConfig)).code;
@@ -53,7 +53,7 @@ fs.emptyDirSync('./build');
const themes = { Legacy: {}, V3: {} };
let themeFiles = fs.readdirSync('./themes/Legacy');
- for (let dir of themeFiles) {
+ for (const dir of themeFiles) {
const themeData = JSON.parse(fs.readFileSync(`./themes/Legacy/${dir}/settings.json`).toString());
themeData.path = dir;
themes.Legacy[dir] = (themeData);
@@ -70,7 +70,7 @@ fs.emptyDirSync('./build');
}
themeFiles = fs.readdirSync('./themes/V3');
- for (let dir of themeFiles) {
+ for (const dir of themeFiles) {
const themeData = JSON.parse(fs.readFileSync(`./themes/V3/${dir}/settings.json`).toString());
themeData.path = dir;
themes.V3[dir] = (themeData);
@@ -113,7 +113,7 @@ fs.emptyDirSync('./build');
const stream = fs.createWriteStream(editorThemeFile, { flags: 'a' });
stream.write('[\n"default"');
- for (let themeFile of editorThemeFiles) {
+ for (const themeFile of editorThemeFiles) {
stream.write(`,\n"${themeFile.slice(0, -4)}"`);
}
stream.write('\n]\n');
diff --git a/server/admin.api.js b/server/admin.api.js
index 1a39f020b..e70268afa 100644
--- a/server/admin.api.js
+++ b/server/admin.api.js
@@ -93,7 +93,7 @@ router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{
/* Cleans `