From 26a5cb9fab98cc3d1ec358209bc8f19bec623b8c Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 19 Apr 2025 22:47:33 -0500 Subject: [PATCH 01/95] Add a percentile on single die representation to dicefont. This is added as a new icon but inlined with the df icons for user conveniance. used dper instead of dpercent for ease of use. --- themes/fonts/iconFonts/diceFont.js | 103 ++++- themes/fonts/iconFonts/diceFont.less | 412 +++++++++++++++++++ themes/fonts/iconFonts/dpercent-Kremlin.woff | Bin 0 -> 84332 bytes 3 files changed, 514 insertions(+), 1 deletion(-) create mode 100644 themes/fonts/iconFonts/dpercent-Kremlin.woff diff --git a/themes/fonts/iconFonts/diceFont.js b/themes/fonts/iconFonts/diceFont.js index a349d7b0a..dd4e439b6 100644 --- a/themes/fonts/iconFonts/diceFont.js +++ b/themes/fonts/iconFonts/diceFont.js @@ -90,7 +90,108 @@ const diceFont = { 'df_solid_small_dot_d6_3' : 'df solid-small-dot-d6-3', 'df_solid_small_dot_d6_4' : 'df solid-small-dot-d6-4', 'df_solid_small_dot_d6_5' : 'df solid-small-dot-d6-5', - 'df_solid_small_dot_d6_6' : 'df solid-small-dot-d6-6' + 'df_solid_small_dot_d6_6' : 'df solid-small-dot-d6-6', + 'df_dper_00' : 'df dper-00', + 'df_dper_01' : 'df dper-01', + 'df_dper_02' : 'df dper-02', + 'df_dper_03' : 'df dper-03', + 'df_dper_04' : 'df dper-04', + 'df_dper_05' : 'df dper-05', + 'df_dper_06' : 'df dper-06', + 'df_dper_07' : 'df dper-07', + 'df_dper_08' : 'df dper-08', + 'df_dper_09' : 'df dper-09', + 'df_dper_10' : 'df dper-10', + 'df_dper_11' : 'df dper-11', + 'df_dper_12' : 'df dper-12', + 'df_dper_13' : 'df dper-13', + 'df_dper_14' : 'df dper-14', + 'df_dper_15' : 'df dper-15', + 'df_dper_16' : 'df dper-16', + 'df_dper_17' : 'df dper-17', + 'df_dper_18' : 'df dper-18', + 'df_dper_19' : 'df dper-19', + 'df_dper_20' : 'df dper-20', + 'df_dper_21' : 'df dper-21', + 'df_dper_22' : 'df dper-22', + 'df_dper_23' : 'df dper-23', + 'df_dper_24' : 'df dper-24', + 'df_dper_25' : 'df dper-25', + 'df_dper_26' : 'df dper-26', + 'df_dper_27' : 'df dper-27', + 'df_dper_28' : 'df dper-28', + 'df_dper_29' : 'df dper-29', + 'df_dper_30' : 'df dper-30', + 'df_dper_31' : 'df dper-31', + 'df_dper_32' : 'df dper-32', + 'df_dper_33' : 'df dper-33', + 'df_dper_34' : 'df dper-34', + 'df_dper_35' : 'df dper-35', + 'df_dper_36' : 'df dper-36', + 'df_dper_37' : 'df dper-37', + 'df_dper_38' : 'df dper-38', + 'df_dper_39' : 'df dper-39', + 'df_dper_40' : 'df dper-40', + 'df_dper_41' : 'df dper-41', + 'df_dper_42' : 'df dper-42', + 'df_dper_43' : 'df dper-43', + 'df_dper_44' : 'df dper-44', + 'df_dper_45' : 'df dper-45', + 'df_dper_46' : 'df dper-46', + 'df_dper_47' : 'df dper-47', + 'df_dper_48' : 'df dper-48', + 'df_dper_49' : 'df dper-49', + 'df_dper_50' : 'df dper-50', + 'df_dper_51' : 'df dper-51', + 'df_dper_52' : 'df dper-52', + 'df_dper_53' : 'df dper-53', + 'df_dper_54' : 'df dper-54', + 'df_dper_55' : 'df dper-55', + 'df_dper_56' : 'df dper-56', + 'df_dper_57' : 'df dper-57', + 'df_dper_58' : 'df dper-58', + 'df_dper_59' : 'df dper-59', + 'df_dper_60' : 'df dper-60', + 'df_dper_61' : 'df dper-61', + 'df_dper_62' : 'df dper-62', + 'df_dper_63' : 'df dper-63', + 'df_dper_64' : 'df dper-64', + 'df_dper_65' : 'df dper-65', + 'df_dper_66' : 'df dper-66', + 'df_dper_67' : 'df dper-67', + 'df_dper_68' : 'df dper-68', + 'df_dper_69' : 'df dper-69', + 'df_dper_70' : 'df dper-70', + 'df_dper_71' : 'df dper-71', + 'df_dper_72' : 'df dper-72', + 'df_dper_73' : 'df dper-73', + 'df_dper_74' : 'df dper-74', + 'df_dper_75' : 'df dper-75', + 'df_dper_76' : 'df dper-76', + 'df_dper_77' : 'df dper-77', + 'df_dper_78' : 'df dper-78', + 'df_dper_79' : 'df dper-79', + 'df_dper_80' : 'df dper-80', + 'df_dper_81' : 'df dper-81', + 'df_dper_82' : 'df dper-82', + 'df_dper_83' : 'df dper-83', + 'df_dper_84' : 'df dper-84', + 'df_dper_85' : 'df dper-85', + 'df_dper_86' : 'df dper-86', + 'df_dper_87' : 'df dper-87', + 'df_dper_88' : 'df dper-88', + 'df_dper_89' : 'df dper-89', + 'df_dper_90' : 'df dper-90', + 'df_dper_91' : 'df dper-91', + 'df_dper_92' : 'df dper-92', + 'df_dper_93' : 'df dper-93', + 'df_dper_94' : 'df dper-94', + 'df_dper_95' : 'df dper-95', + 'df_dper_96' : 'df dper-96', + 'df_dper_97' : 'df dper-97', + 'df_dper_98' : 'df dper-98', + 'df_dper_99' : 'df dper-99', + 'df_dper_100' : 'df dper-100' }; export default diceFont; \ No newline at end of file diff --git a/themes/fonts/iconFonts/diceFont.less b/themes/fonts/iconFonts/diceFont.less index 3b60093d0..e7e256814 100644 --- a/themes/fonts/iconFonts/diceFont.less +++ b/themes/fonts/iconFonts/diceFont.less @@ -6,6 +6,14 @@ src : url('../../../fonts/iconFonts/diceFont.woff2'); } +@font-face { + font-family : 'dpercent-Kremlin'; + src : url('../../../fonts/iconFonts/dpercent-Kremlin.woff') format('woff'); + font-weight : normal; + font-style : normal; + font-display : block; + } + .df { display : inline; font-family : 'DiceFont'; @@ -114,4 +122,408 @@ &.solid-small-dot-d6-4::before { content : '\f18c'; } &.solid-small-dot-d6-5::before { content : '\f18d'; } &.solid-small-dot-d6-6::before { content : '\f18e'; } + &.dper-00::before { + font-family : 'dpercent-Kremlin'; + content : '\e900'; + } + &.dper-01::before { + font-family : 'dpercent-Kremlin'; + content : '\e901'; + } + &.dper-02::before { + font-family : 'dpercent-Kremlin'; + content : '\e902'; + } + &.dper-03::before { + font-family : 'dpercent-Kremlin'; + content : '\e903'; + } + &.dper-04::before { + font-family : 'dpercent-Kremlin'; + content : '\e904'; + } + &.dper-05::before { + font-family : 'dpercent-Kremlin'; + content : '\e905'; + } + &.dper-06::before { + font-family : 'dpercent-Kremlin'; + content : '\e906'; + } + &.dper-07::before { + font-family : 'dpercent-Kremlin'; + content : '\e907'; + } + &.dper-08::before { + font-family : 'dpercent-Kremlin'; + content : '\e908'; + } + &.dper-09::before { + font-family : 'dpercent-Kremlin'; + content : '\e909'; + } + &.dper-10::before { + font-family : 'dpercent-Kremlin'; + content : '\e90a'; + } + &.dper-11::before { + font-family : 'dpercent-Kremlin'; + content : '\e90b'; + } + &.dper-12::before { + font-family : 'dpercent-Kremlin'; + content : '\e90c'; + } + &.dper-13::before { + font-family : 'dpercent-Kremlin'; + content : '\e90d'; + } + &.dper-14::before { + font-family : 'dpercent-Kremlin'; + content : '\e90e'; + } + &.dper-15::before { + font-family : 'dpercent-Kremlin'; + content : '\e90f'; + } + &.dper-16::before { + font-family : 'dpercent-Kremlin'; + content : '\e910'; + } + &.dper-17::before { + font-family : 'dpercent-Kremlin'; + content : '\e911'; + } + &.dper-18::before { + font-family : 'dpercent-Kremlin'; + content : '\e912'; + } + &.dper-19::before { + font-family : 'dpercent-Kremlin'; + content : '\e913'; + } + &.dper-20::before { + font-family : 'dpercent-Kremlin'; + content : '\e914'; + } + &.dper-21::before { + font-family : 'dpercent-Kremlin'; + content : '\e915'; + } + &.dper-22::before { + font-family : 'dpercent-Kremlin'; + content : '\e916'; + } + &.dper-23::before { + font-family : 'dpercent-Kremlin'; + content : '\e917'; + } + &.dper-24::before { + font-family : 'dpercent-Kremlin'; + content : '\e918'; + } + &.dper-25::before { + font-family : 'dpercent-Kremlin'; + content : '\e919'; + } + &.dper-26::before { + font-family : 'dpercent-Kremlin'; + content : '\e91a'; + } + &.dper-27::before { + font-family : 'dpercent-Kremlin'; + content : '\e91b'; + } + &.dper-28::before { + font-family : 'dpercent-Kremlin'; + content : '\e91c'; + } + &.dper-29::before { + font-family : 'dpercent-Kremlin'; + content : '\e91d'; + } + &.dper-30::before { + font-family : 'dpercent-Kremlin'; + content : '\e91e'; + } + &.dper-31::before { + font-family : 'dpercent-Kremlin'; + content : '\e91f'; + } + &.dper-32::before { + font-family : 'dpercent-Kremlin'; + content : '\e920'; + } + &.dper-33::before { + font-family : 'dpercent-Kremlin'; + content : '\e921'; + } + &.dper-34::before { + font-family : 'dpercent-Kremlin'; + content : '\e922'; + } + &.dper-35::before { + font-family : 'dpercent-Kremlin'; + content : '\e923'; + } + &.dper-36::before { + font-family : 'dpercent-Kremlin'; + content : '\e924'; + } + &.dper-37::before { + font-family : 'dpercent-Kremlin'; + content : '\e925'; + } + &.dper-38::before { + font-family : 'dpercent-Kremlin'; + content : '\e926'; + } + &.dper-39::before { + font-family : 'dpercent-Kremlin'; + content : '\e927'; + } + &.dper-40::before { + font-family : 'dpercent-Kremlin'; + content : '\e928'; + } + &.dper-41::before { + font-family : 'dpercent-Kremlin'; + content : '\e929'; + } + &.dper-42::before { + font-family : 'dpercent-Kremlin'; + content : '\e92a'; + } + &.dper-43::before { + font-family : 'dpercent-Kremlin'; + content : '\e92b'; + } + &.dper-44::before { + font-family : 'dpercent-Kremlin'; + content : '\e92c'; + } + &.dper-45::before { + font-family : 'dpercent-Kremlin'; + content : '\e92d'; + } + &.dper-46::before { + font-family : 'dpercent-Kremlin'; + content : '\e92e'; + } + &.dper-47::before { + font-family : 'dpercent-Kremlin'; + content : '\e92f'; + } + &.dper-48::before { + font-family : 'dpercent-Kremlin'; + content : '\e930'; + } + &.dper-49::before { + font-family : 'dpercent-Kremlin'; + content : '\e931'; + } + &.dper-50::before { + font-family : 'dpercent-Kremlin'; + content : '\e932'; + } + &.dper-51::before { + font-family : 'dpercent-Kremlin'; + content : '\e933'; + } + &.dper-52::before { + font-family : 'dpercent-Kremlin'; + content : '\e934'; + } + &.dper-53::before { + font-family : 'dpercent-Kremlin'; + content : '\e935'; + } + &.dper-54::before { + font-family : 'dpercent-Kremlin'; + content : '\e936'; + } + &.dper-55::before { + font-family : 'dpercent-Kremlin'; + content : '\e937'; + } + &.dper-56::before { + font-family : 'dpercent-Kremlin'; + content : '\e938'; + } + &.dper-57::before { + font-family : 'dpercent-Kremlin'; + content : '\e939'; + } + &.dper-58::before { + font-family : 'dpercent-Kremlin'; + content : '\e93a'; + } + &.dper-59::before { + font-family : 'dpercent-Kremlin'; + content : '\e93b'; + } + &.dper-60::before { + font-family : 'dpercent-Kremlin'; + content : '\e93c'; + } + &.dper-61::before { + font-family : 'dpercent-Kremlin'; + content : '\e93d'; + } + &.dper-62::before { + font-family : 'dpercent-Kremlin'; + content : '\e93e'; + } + &.dper-63::before { + font-family : 'dpercent-Kremlin'; + content : '\e93f'; + } + &.dper-64::before { + font-family : 'dpercent-Kremlin'; + content : '\e940'; + } + &.dper-65::before { + font-family : 'dpercent-Kremlin'; + content : '\e941'; + } + &.dper-66::before { + font-family : 'dpercent-Kremlin'; + content : '\e942'; + } + &.dper-67::before { + font-family : 'dpercent-Kremlin'; + content : '\e943'; + } + &.dper-68::before { + font-family : 'dpercent-Kremlin'; + content : '\e944'; + } + &.dper-69::before { + font-family : 'dpercent-Kremlin'; + content : '\e945'; + } + &.dper-70::before { + font-family : 'dpercent-Kremlin'; + content : '\e946'; + } + &.dper-71::before { + font-family : 'dpercent-Kremlin'; + content : '\e947'; + } + &.dper-72::before { + font-family : 'dpercent-Kremlin'; + content : '\e948'; + } + &.dper-73::before { + font-family : 'dpercent-Kremlin'; + content : '\e949'; + } + &.dper-74::before { + font-family : 'dpercent-Kremlin'; + content : '\e94a'; + } + &.dper-75::before { + font-family : 'dpercent-Kremlin'; + content : '\e94b'; + } + &.dper-76::before { + font-family : 'dpercent-Kremlin'; + content : '\e94c'; + } + &.dper-77::before { + font-family : 'dpercent-Kremlin'; + content : '\e94d'; + } + &.dper-78::before { + font-family : 'dpercent-Kremlin'; + content : '\e94e'; + } + &.dper-79::before { + font-family : 'dpercent-Kremlin'; + content : '\e94f'; + } + &.dper-80::before { + font-family : 'dpercent-Kremlin'; + content : '\e950'; + } + &.dper-81::before { + font-family : 'dpercent-Kremlin'; + content : '\e951'; + } + &.dper-82::before { + font-family : 'dpercent-Kremlin'; + content : '\e952'; + } + &.dper-83::before { + font-family : 'dpercent-Kremlin'; + content : '\e953'; + } + &.dper-84::before { + font-family : 'dpercent-Kremlin'; + content : '\e954'; + } + &.dper-85::before { + font-family : 'dpercent-Kremlin'; + content : '\e955'; + } + &.dper-86::before { + font-family : 'dpercent-Kremlin'; + content : '\e956'; + } + &.dper-87::before { + font-family : 'dpercent-Kremlin'; + content : '\e957'; + } + &.dper-88::before { + font-family : 'dpercent-Kremlin'; + content : '\e958'; + } + &.dper-89::before { + font-family : 'dpercent-Kremlin'; + content : '\e959'; + } + &.dper-90::before { + font-family : 'dpercent-Kremlin'; + content : '\e95a'; + } + &.dper-91::before { + font-family : 'dpercent-Kremlin'; + content : '\e95b'; + } + &.dper-92::before { + font-family : 'dpercent-Kremlin'; + content : '\e95c'; + } + &.dper-93::before { + font-family : 'dpercent-Kremlin'; + content : '\e95d'; + } + &.dper-94::before { + font-family : 'dpercent-Kremlin'; + content : '\e95e'; + } + &.dper-95::before { + font-family : 'dpercent-Kremlin'; + content : '\e95f'; + } + &.dper-96::before { + font-family : 'dpercent-Kremlin'; + content : '\e960'; + } + &.dper-97::before { + font-family : 'dpercent-Kremlin'; + content : '\e961'; + } + &.dper-98::before { + font-family : 'dpercent-Kremlin'; + content : '\e962'; + } + &.dper-99::before { + font-family : 'dpercent-Kremlin'; + content : '\e963'; + } + &.dper-100::before { + font-family : 'dpercent-Kremlin'; + content : '\e964'; + } } \ No newline at end of file diff --git a/themes/fonts/iconFonts/dpercent-Kremlin.woff b/themes/fonts/iconFonts/dpercent-Kremlin.woff new file mode 100644 index 0000000000000000000000000000000000000000..d425f7f51133ea81ef7cbfcc70ecf6d2f55b0e45 GIT binary patch literal 84332 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 Date: Sat, 10 May 2025 12:26:26 -0500 Subject: [PATCH 02/95] Add scripting for bus insurance. --- .../iconFonts/d100_Sources/buildFont.bash | 68 +++++++++++ .../iconFonts/d100_Sources/d10-MASTER.svg | 112 ++++++++++++++++++ themes/fonts/iconFonts/d100_Sources/readme.md | 28 +++++ 3 files changed, 208 insertions(+) create mode 100644 themes/fonts/iconFonts/d100_Sources/buildFont.bash create mode 100644 themes/fonts/iconFonts/d100_Sources/d10-MASTER.svg create mode 100644 themes/fonts/iconFonts/d100_Sources/readme.md diff --git a/themes/fonts/iconFonts/d100_Sources/buildFont.bash b/themes/fonts/iconFonts/d100_Sources/buildFont.bash new file mode 100644 index 000000000..c1afd7495 --- /dev/null +++ b/themes/fonts/iconFonts/d100_Sources/buildFont.bash @@ -0,0 +1,68 @@ +#!/bin/bash -x + +# If there is no argument, don't recreate the individual dice, only run the final conversion. +if [ "${1}" == "y" ] || [ "${1}" == "n" ]; then + if [ ! -d './rendered-files' ]; then + mkdir rendered-files + fi + rm ./rendered-files/*.svg + # Build 00-99 ( leading zeros ) + for tens in $(echo 0 1 2 3 4 5 6 7 8 9); do + for ones in $(echo 0 1 2 3 4 5 6 7 8 9); do + num=$(echo ${tens}${ones}); + cat d10-MASTER.svg | sed "s/AAAAA/${num}/" > ./rendered-files/10-MASTER-${num}.svg + printf "Rendering d100 - ${num}\r" + # Tweak the individual die + if [ "${1}" == "y" ]; then inkscape ./rendered-files/10-MASTER-${num}.svg; fi + done + done + # Build 0-9, non-leading zero + for ones in $(echo 0 1 2 3 4 5 6 7 8 9); do + num=$(echo ${ones}); + cat d10-MASTER.svg | sed "s/AAAAA/${num}/" > ./rendered-files/10-MASTER-${num}.svg + printf "Rendering d10 - ${num}\r" + # Tweak the individual die + if [ "${1}" == "y" ]; then inkscape ./rendered-files/10-MASTER-${num}.svg; fi + done + # Build the 100 ace + num=100 + cat d10-MASTER.svg | sed "s/AAAAA/${num}/" > ./rendered-files/10-MASTER-${num}.svg + printf "Rendering d100 - ${num}\r" + # Tweak the individual die + if [ "${1}" == "y" ]; then inkscape ./rendered-files/10-MASTER-${num}.svg; fi + printf "\r\n" +fi + +# Convert the Master files for better IcoMoon compatibility +# Mirror this literally +for tens in $(echo 0 1 2 3 4 5 6 7 8 9); do + for ones in $(echo 0 1 2 3 4 5 6 7 8 9); do + num=$(echo ${tens}${ones}) + inkscape --export-text-to-path -o ./rendered-files/dpercent-${num}.svg ./rendered-files/10-MASTER-${num}.svg 2> /dev/null + printf "Rewriting d100 - ${num}\r" + done +done + +# d100 +num=100 +inkscape --export-text-to-path -o ./rendered-files/dpercent-${num}.svg ./rendered-files/10-MASTER-${num}.svg 2> /dev/null +printf "Rewriting d100 - ${num}\r" + +for ones in $(echo 0 1 2 3 4 5 6 7 8 9); do + num=$(echo ${ones}) + inkscape --export-text-to-path -o ./rendered-files/d10-${num}.svg ./rendered-files/10-MASTER-${num}.svg 2> /dev/null + printf "Rewriting d10 - ${num}\r" +done + +# Duplicate the 10 for the d10 set +num=10 +inkscape --export-text-to-path -o ./rendered-files/d10-${num}.svg ./rendered-files/10-MASTER-${num}.svg 2> /dev/null +printf "Rewriting d10 - ${num}\r" + +# Run svgfixer +if [ ! -d './fixed-files' ]; then + mkdir fixed-files +fi + +rm ./fixed-files/*.svg +oslllo-svg-fixer -s ./rendered-files/ -d ./fixed-files diff --git a/themes/fonts/iconFonts/d100_Sources/d10-MASTER.svg b/themes/fonts/iconFonts/d100_Sources/d10-MASTER.svg new file mode 100644 index 000000000..c16ce5002 --- /dev/null +++ b/themes/fonts/iconFonts/d100_Sources/d10-MASTER.svg @@ -0,0 +1,112 @@ + + + + + + + + + + + + + d10-0 + + + + + + AAAAA + + + + + d10-0 + + + + diff --git a/themes/fonts/iconFonts/d100_Sources/readme.md b/themes/fonts/iconFonts/d100_Sources/readme.md new file mode 100644 index 000000000..fb06620bf --- /dev/null +++ b/themes/fonts/iconFonts/d100_Sources/readme.md @@ -0,0 +1,28 @@ +# Dicefont extensions + +This folder is setup for building/rebuilding the d10 and d100 (percent representation on a d10 shape) for use with Icomoon. This will, presumably, be a usable workflow with similar tools. + +## Overview + +This script uses the file 10-MASTER.svg as a base, loops through each of the die face numbers needed, creating an SVG per face in `./rendered-files`. Next, it post-processes the files from `./rendered-files/` to be more compatible with IcoMoon and places the results in `./fixed-files`. + +## Usage + +The script runs on three possible paths. + +1. Start from scratch ***and*** open inkscape for each glyph for tweaking. + `bash ./buildFont.bash y` + + On this path, the per-face SVG files are generated and Inkscape is opened on each file for any tweaking to be done. + +2. Start from scratch but ***do not*** tweak each glyph while running. + `bash ./buildFont.bash n` + +3. Process the rendered glyphs for loading into IcoMoon + `bash ./buildFont.bash` + +For most rebuilds, the expectation is that the script will be run once with `n` as the parameter, then some number of files will be manually touched, then the script re-run with no parameters before finally using the results with IcoMoon. + +## Requirements + +This script expects inkscape and [https://docs-oslllo-com.onrender.com/svg-fixer/master/#/getting-started/introduction](svgFixer) to be in the path. The numbering uses the Kremlin Minister Font Family. \ No newline at end of file From 1a52347e9be9cbe182bc2dfcfa527463f07636f6 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sun, 11 May 2025 18:31:45 -0500 Subject: [PATCH 03/95] Tweaked the Image source to use one for 2 digit numbers and one for centered numbers. These results are much better. Renamed the resulting face subbed in d10s generated from teh same souce so they would match. --- .../iconFonts/d100_Sources/buildFont.bash | 4 +- .../iconFonts/d100_Sources/d10-MASTER-AB.svg | 134 +++ .../iconFonts/d100_Sources/d10-MASTER.svg | 6 +- themes/fonts/iconFonts/diceFont.js | 203 ++-- themes/fonts/iconFonts/diceFont.less | 986 ++++++++++-------- themes/fonts/iconFonts/dicefont-D100.woff | Bin 0 -> 81608 bytes themes/fonts/iconFonts/dpercent-Kremlin.woff | Bin 84332 -> 0 bytes 7 files changed, 809 insertions(+), 524 deletions(-) create mode 100644 themes/fonts/iconFonts/d100_Sources/d10-MASTER-AB.svg create mode 100644 themes/fonts/iconFonts/dicefont-D100.woff delete mode 100644 themes/fonts/iconFonts/dpercent-Kremlin.woff diff --git a/themes/fonts/iconFonts/d100_Sources/buildFont.bash b/themes/fonts/iconFonts/d100_Sources/buildFont.bash index c1afd7495..286472e17 100644 --- a/themes/fonts/iconFonts/d100_Sources/buildFont.bash +++ b/themes/fonts/iconFonts/d100_Sources/buildFont.bash @@ -10,7 +10,7 @@ if [ "${1}" == "y" ] || [ "${1}" == "n" ]; then for tens in $(echo 0 1 2 3 4 5 6 7 8 9); do for ones in $(echo 0 1 2 3 4 5 6 7 8 9); do num=$(echo ${tens}${ones}); - cat d10-MASTER.svg | sed "s/AAAAA/${num}/" > ./rendered-files/10-MASTER-${num}.svg + cat d10-MASTER-AB.svg | sed "s/AAAAA/${tens}/" | sed "s/BBBBB/${ones}/" > ./rendered-files/10-MASTER-${num}.svg printf "Rendering d100 - ${num}\r" # Tweak the individual die if [ "${1}" == "y" ]; then inkscape ./rendered-files/10-MASTER-${num}.svg; fi @@ -24,7 +24,7 @@ if [ "${1}" == "y" ] || [ "${1}" == "n" ]; then # Tweak the individual die if [ "${1}" == "y" ]; then inkscape ./rendered-files/10-MASTER-${num}.svg; fi done - # Build the 100 ace + # Build the 100 face num=100 cat d10-MASTER.svg | sed "s/AAAAA/${num}/" > ./rendered-files/10-MASTER-${num}.svg printf "Rendering d100 - ${num}\r" diff --git a/themes/fonts/iconFonts/d100_Sources/d10-MASTER-AB.svg b/themes/fonts/iconFonts/d100_Sources/d10-MASTER-AB.svg new file mode 100644 index 000000000..b31778607 --- /dev/null +++ b/themes/fonts/iconFonts/d100_Sources/d10-MASTER-AB.svg @@ -0,0 +1,134 @@ + + + + + + + + + + + + + d10-0 + + + + + + AAAAA + + BBBBB + + + + + d10-0 + + + + diff --git a/themes/fonts/iconFonts/d100_Sources/d10-MASTER.svg b/themes/fonts/iconFonts/d100_Sources/d10-MASTER.svg index c16ce5002..baa327064 100644 --- a/themes/fonts/iconFonts/d100_Sources/d10-MASTER.svg +++ b/themes/fonts/iconFonts/d100_Sources/d10-MASTER.svg @@ -25,9 +25,9 @@ inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" - inkscape:zoom="4.1653009" - inkscape:cx="228.91503" - inkscape:cy="271.76908" + inkscape:zoom="2.8284271" + inkscape:cx="292.56543" + inkscape:cy="342.23968" inkscape:window-width="1920" inkscape:window-height="1043" inkscape:window-x="0" diff --git a/themes/fonts/iconFonts/diceFont.js b/themes/fonts/iconFonts/diceFont.js index dd4e439b6..3e7572c1d 100644 --- a/themes/fonts/iconFonts/diceFont.js +++ b/themes/fonts/iconFonts/diceFont.js @@ -14,6 +14,7 @@ const diceFont = { 'df_d10_7' : 'df d10-7', 'df_d10_8' : 'df d10-8', 'df_d10_9' : 'df d10-9', + 'df_d10_0' : 'df d10-0', 'df_d12' : 'df d12', 'df_d12_1' : 'df d12-1', 'df_d12_10' : 'df d12-10', @@ -91,107 +92,107 @@ const diceFont = { 'df_solid_small_dot_d6_4' : 'df solid-small-dot-d6-4', 'df_solid_small_dot_d6_5' : 'df solid-small-dot-d6-5', 'df_solid_small_dot_d6_6' : 'df solid-small-dot-d6-6', - 'df_dper_00' : 'df dper-00', - 'df_dper_01' : 'df dper-01', - 'df_dper_02' : 'df dper-02', - 'df_dper_03' : 'df dper-03', - 'df_dper_04' : 'df dper-04', - 'df_dper_05' : 'df dper-05', - 'df_dper_06' : 'df dper-06', - 'df_dper_07' : 'df dper-07', - 'df_dper_08' : 'df dper-08', - 'df_dper_09' : 'df dper-09', - 'df_dper_10' : 'df dper-10', - 'df_dper_11' : 'df dper-11', - 'df_dper_12' : 'df dper-12', - 'df_dper_13' : 'df dper-13', - 'df_dper_14' : 'df dper-14', - 'df_dper_15' : 'df dper-15', - 'df_dper_16' : 'df dper-16', - 'df_dper_17' : 'df dper-17', - 'df_dper_18' : 'df dper-18', - 'df_dper_19' : 'df dper-19', - 'df_dper_20' : 'df dper-20', - 'df_dper_21' : 'df dper-21', - 'df_dper_22' : 'df dper-22', - 'df_dper_23' : 'df dper-23', - 'df_dper_24' : 'df dper-24', - 'df_dper_25' : 'df dper-25', - 'df_dper_26' : 'df dper-26', - 'df_dper_27' : 'df dper-27', - 'df_dper_28' : 'df dper-28', - 'df_dper_29' : 'df dper-29', - 'df_dper_30' : 'df dper-30', - 'df_dper_31' : 'df dper-31', - 'df_dper_32' : 'df dper-32', - 'df_dper_33' : 'df dper-33', - 'df_dper_34' : 'df dper-34', - 'df_dper_35' : 'df dper-35', - 'df_dper_36' : 'df dper-36', - 'df_dper_37' : 'df dper-37', - 'df_dper_38' : 'df dper-38', - 'df_dper_39' : 'df dper-39', - 'df_dper_40' : 'df dper-40', - 'df_dper_41' : 'df dper-41', - 'df_dper_42' : 'df dper-42', - 'df_dper_43' : 'df dper-43', - 'df_dper_44' : 'df dper-44', - 'df_dper_45' : 'df dper-45', - 'df_dper_46' : 'df dper-46', - 'df_dper_47' : 'df dper-47', - 'df_dper_48' : 'df dper-48', - 'df_dper_49' : 'df dper-49', - 'df_dper_50' : 'df dper-50', - 'df_dper_51' : 'df dper-51', - 'df_dper_52' : 'df dper-52', - 'df_dper_53' : 'df dper-53', - 'df_dper_54' : 'df dper-54', - 'df_dper_55' : 'df dper-55', - 'df_dper_56' : 'df dper-56', - 'df_dper_57' : 'df dper-57', - 'df_dper_58' : 'df dper-58', - 'df_dper_59' : 'df dper-59', - 'df_dper_60' : 'df dper-60', - 'df_dper_61' : 'df dper-61', - 'df_dper_62' : 'df dper-62', - 'df_dper_63' : 'df dper-63', - 'df_dper_64' : 'df dper-64', - 'df_dper_65' : 'df dper-65', - 'df_dper_66' : 'df dper-66', - 'df_dper_67' : 'df dper-67', - 'df_dper_68' : 'df dper-68', - 'df_dper_69' : 'df dper-69', - 'df_dper_70' : 'df dper-70', - 'df_dper_71' : 'df dper-71', - 'df_dper_72' : 'df dper-72', - 'df_dper_73' : 'df dper-73', - 'df_dper_74' : 'df dper-74', - 'df_dper_75' : 'df dper-75', - 'df_dper_76' : 'df dper-76', - 'df_dper_77' : 'df dper-77', - 'df_dper_78' : 'df dper-78', - 'df_dper_79' : 'df dper-79', - 'df_dper_80' : 'df dper-80', - 'df_dper_81' : 'df dper-81', - 'df_dper_82' : 'df dper-82', - 'df_dper_83' : 'df dper-83', - 'df_dper_84' : 'df dper-84', - 'df_dper_85' : 'df dper-85', - 'df_dper_86' : 'df dper-86', - 'df_dper_87' : 'df dper-87', - 'df_dper_88' : 'df dper-88', - 'df_dper_89' : 'df dper-89', - 'df_dper_90' : 'df dper-90', - 'df_dper_91' : 'df dper-91', - 'df_dper_92' : 'df dper-92', - 'df_dper_93' : 'df dper-93', - 'df_dper_94' : 'df dper-94', - 'df_dper_95' : 'df dper-95', - 'df_dper_96' : 'df dper-96', - 'df_dper_97' : 'df dper-97', - 'df_dper_98' : 'df dper-98', - 'df_dper_99' : 'df dper-99', - 'df_dper_100' : 'df dper-100' + 'df_dper_00' : 'df dpercent-00', + 'df_dper_01' : 'df dpercent-01', + 'df_dper_02' : 'df dpercent-02', + 'df_dper_03' : 'df dpercent-03', + 'df_dper_04' : 'df dpercent-04', + 'df_dper_05' : 'df dpercent-05', + 'df_dper_06' : 'df dpercent-06', + 'df_dper_07' : 'df dpercent-07', + 'df_dper_08' : 'df dpercent-08', + 'df_dper_09' : 'df dpercent-09', + 'df_dper_10' : 'df dpercent-10', + 'df_dper_11' : 'df dpercent-11', + 'df_dper_12' : 'df dpercent-12', + 'df_dper_13' : 'df dpercent-13', + 'df_dper_14' : 'df dpercent-14', + 'df_dper_15' : 'df dpercent-15', + 'df_dper_16' : 'df dpercent-16', + 'df_dper_17' : 'df dpercent-17', + 'df_dper_18' : 'df dpercent-18', + 'df_dper_19' : 'df dpercent-19', + 'df_dper_20' : 'df dpercent-20', + 'df_dper_21' : 'df dpercent-21', + 'df_dper_22' : 'df dpercent-22', + 'df_dper_23' : 'df dpercent-23', + 'df_dper_24' : 'df dpercent-24', + 'df_dper_25' : 'df dpercent-25', + 'df_dper_26' : 'df dpercent-26', + 'df_dper_27' : 'df dpercent-27', + 'df_dper_28' : 'df dpercent-28', + 'df_dper_29' : 'df dpercent-29', + 'df_dper_30' : 'df dpercent-30', + 'df_dper_31' : 'df dpercent-31', + 'df_dper_32' : 'df dpercent-32', + 'df_dper_33' : 'df dpercent-33', + 'df_dper_34' : 'df dpercent-34', + 'df_dper_35' : 'df dpercent-35', + 'df_dper_36' : 'df dpercent-36', + 'df_dper_37' : 'df dpercent-37', + 'df_dper_38' : 'df dpercent-38', + 'df_dper_39' : 'df dpercent-39', + 'df_dper_40' : 'df dpercent-40', + 'df_dper_41' : 'df dpercent-41', + 'df_dper_42' : 'df dpercent-42', + 'df_dper_43' : 'df dpercent-43', + 'df_dper_44' : 'df dpercent-44', + 'df_dper_45' : 'df dpercent-45', + 'df_dper_46' : 'df dpercent-46', + 'df_dper_47' : 'df dpercent-47', + 'df_dper_48' : 'df dpercent-48', + 'df_dper_49' : 'df dpercent-49', + 'df_dper_50' : 'df dpercent-50', + 'df_dper_51' : 'df dpercent-51', + 'df_dper_52' : 'df dpercent-52', + 'df_dper_53' : 'df dpercent-53', + 'df_dper_54' : 'df dpercent-54', + 'df_dper_55' : 'df dpercent-55', + 'df_dper_56' : 'df dpercent-56', + 'df_dper_57' : 'df dpercent-57', + 'df_dper_58' : 'df dpercent-58', + 'df_dper_59' : 'df dpercent-59', + 'df_dper_60' : 'df dpercent-60', + 'df_dper_61' : 'df dpercent-61', + 'df_dper_62' : 'df dpercent-62', + 'df_dper_63' : 'df dpercent-63', + 'df_dper_64' : 'df dpercent-64', + 'df_dper_65' : 'df dpercent-65', + 'df_dper_66' : 'df dpercent-66', + 'df_dper_67' : 'df dpercent-67', + 'df_dper_68' : 'df dpercent-68', + 'df_dper_69' : 'df dpercent-69', + 'df_dper_70' : 'df dpercent-70', + 'df_dper_71' : 'df dpercent-71', + 'df_dper_72' : 'df dpercent-72', + 'df_dper_73' : 'df dpercent-73', + 'df_dper_74' : 'df dpercent-74', + 'df_dper_75' : 'df dpercent-75', + 'df_dper_76' : 'df dpercent-76', + 'df_dper_77' : 'df dpercent-77', + 'df_dper_78' : 'df dpercent-78', + 'df_dper_79' : 'df dpercent-79', + 'df_dper_80' : 'df dpercent-80', + 'df_dper_81' : 'df dpercent-81', + 'df_dper_82' : 'df dpercent-82', + 'df_dper_83' : 'df dpercent-83', + 'df_dper_84' : 'df dpercent-84', + 'df_dper_85' : 'df dpercent-85', + 'df_dper_86' : 'df dpercent-86', + 'df_dper_87' : 'df dpercent-87', + 'df_dper_88' : 'df dpercent-88', + 'df_dper_89' : 'df dpercent-89', + 'df_dper_90' : 'df dpercent-90', + 'df_dper_91' : 'df dpercent-91', + 'df_dper_92' : 'df dpercent-92', + 'df_dper_93' : 'df dpercent-93', + 'df_dper_94' : 'df dpercent-94', + 'df_dper_95' : 'df dpercent-95', + 'df_dper_96' : 'df dpercent-96', + 'df_dper_97' : 'df dpercent-97', + 'df_dper_98' : 'df dpercent-98', + 'df_dper_99' : 'df dpercent-99', + 'df_dper_100' : 'df dpercent-100' }; export default diceFont; \ No newline at end of file diff --git a/themes/fonts/iconFonts/diceFont.less b/themes/fonts/iconFonts/diceFont.less index e7e256814..9e10a0bd1 100644 --- a/themes/fonts/iconFonts/diceFont.less +++ b/themes/fonts/iconFonts/diceFont.less @@ -7,8 +7,8 @@ } @font-face { - font-family : 'dpercent-Kremlin'; - src : url('../../../fonts/iconFonts/dpercent-Kremlin.woff') format('woff'); + font-family : 'dicefont-percent'; + src : url('../../../fonts/iconFonts/dicefont-D100.woff') format('woff'); font-weight : normal; font-style : normal; font-display : block; @@ -33,18 +33,6 @@ &.F-minus::before { content : '\f191'; } &.F-plus::before { content : '\f192'; } &.F-zero::before { content : '\f193'; } - &.d10::before { content : '\f194'; } - &.d10-0::before { content : '\f100'; } - &.d10-1::before { content : '\f101'; } - &.d10-10::before { content : '\f102'; } - &.d10-2::before { content : '\f103'; } - &.d10-3::before { content : '\f104'; } - &.d10-4::before { content : '\f105'; } - &.d10-5::before { content : '\f106'; } - &.d10-6::before { content : '\f107'; } - &.d10-7::before { content : '\f108'; } - &.d10-8::before { content : '\f109'; } - &.d10-9::before { content : '\f10a'; } &.d12::before { content : '\f195'; } &.d12-1::before { content : '\f10b'; } &.d12-10::before { content : '\f10c'; } @@ -122,408 +110,570 @@ &.solid-small-dot-d6-4::before { content : '\f18c'; } &.solid-small-dot-d6-5::before { content : '\f18d'; } &.solid-small-dot-d6-6::before { content : '\f18e'; } - &.dper-00::before { - font-family : 'dpercent-Kremlin'; - content : '\e900'; - } - &.dper-01::before { - font-family : 'dpercent-Kremlin'; - content : '\e901'; - } - &.dper-02::before { - font-family : 'dpercent-Kremlin'; - content : '\e902'; - } - &.dper-03::before { - font-family : 'dpercent-Kremlin'; - content : '\e903'; - } - &.dper-04::before { - font-family : 'dpercent-Kremlin'; - content : '\e904'; - } - &.dper-05::before { - font-family : 'dpercent-Kremlin'; - content : '\e905'; - } - &.dper-06::before { - font-family : 'dpercent-Kremlin'; - content : '\e906'; - } - &.dper-07::before { - font-family : 'dpercent-Kremlin'; - content : '\e907'; - } - &.dper-08::before { - font-family : 'dpercent-Kremlin'; - content : '\e908'; - } - &.dper-09::before { - font-family : 'dpercent-Kremlin'; - content : '\e909'; - } - &.dper-10::before { - font-family : 'dpercent-Kremlin'; - content : '\e90a'; - } - &.dper-11::before { - font-family : 'dpercent-Kremlin'; - content : '\e90b'; - } - &.dper-12::before { - font-family : 'dpercent-Kremlin'; - content : '\e90c'; - } - &.dper-13::before { - font-family : 'dpercent-Kremlin'; - content : '\e90d'; - } - &.dper-14::before { - font-family : 'dpercent-Kremlin'; - content : '\e90e'; - } - &.dper-15::before { - font-family : 'dpercent-Kremlin'; - content : '\e90f'; - } - &.dper-16::before { - font-family : 'dpercent-Kremlin'; - content : '\e910'; - } - &.dper-17::before { - font-family : 'dpercent-Kremlin'; - content : '\e911'; - } - &.dper-18::before { - font-family : 'dpercent-Kremlin'; - content : '\e912'; - } - &.dper-19::before { - font-family : 'dpercent-Kremlin'; - content : '\e913'; - } - &.dper-20::before { - font-family : 'dpercent-Kremlin'; - content : '\e914'; - } - &.dper-21::before { - font-family : 'dpercent-Kremlin'; - content : '\e915'; - } - &.dper-22::before { - font-family : 'dpercent-Kremlin'; - content : '\e916'; - } - &.dper-23::before { - font-family : 'dpercent-Kremlin'; - content : '\e917'; - } - &.dper-24::before { - font-family : 'dpercent-Kremlin'; - content : '\e918'; - } - &.dper-25::before { - font-family : 'dpercent-Kremlin'; - content : '\e919'; - } - &.dper-26::before { - font-family : 'dpercent-Kremlin'; - content : '\e91a'; - } - &.dper-27::before { - font-family : 'dpercent-Kremlin'; - content : '\e91b'; - } - &.dper-28::before { - font-family : 'dpercent-Kremlin'; - content : '\e91c'; - } - &.dper-29::before { - font-family : 'dpercent-Kremlin'; - content : '\e91d'; - } - &.dper-30::before { - font-family : 'dpercent-Kremlin'; - content : '\e91e'; - } - &.dper-31::before { - font-family : 'dpercent-Kremlin'; - content : '\e91f'; - } - &.dper-32::before { - font-family : 'dpercent-Kremlin'; - content : '\e920'; - } - &.dper-33::before { - font-family : 'dpercent-Kremlin'; - content : '\e921'; - } - &.dper-34::before { - font-family : 'dpercent-Kremlin'; - content : '\e922'; - } - &.dper-35::before { - font-family : 'dpercent-Kremlin'; - content : '\e923'; - } - &.dper-36::before { - font-family : 'dpercent-Kremlin'; - content : '\e924'; - } - &.dper-37::before { - font-family : 'dpercent-Kremlin'; - content : '\e925'; - } - &.dper-38::before { - font-family : 'dpercent-Kremlin'; - content : '\e926'; - } - &.dper-39::before { - font-family : 'dpercent-Kremlin'; - content : '\e927'; - } - &.dper-40::before { - font-family : 'dpercent-Kremlin'; - content : '\e928'; - } - &.dper-41::before { - font-family : 'dpercent-Kremlin'; - content : '\e929'; - } - &.dper-42::before { - font-family : 'dpercent-Kremlin'; - content : '\e92a'; - } - &.dper-43::before { - font-family : 'dpercent-Kremlin'; - content : '\e92b'; - } - &.dper-44::before { - font-family : 'dpercent-Kremlin'; - content : '\e92c'; - } - &.dper-45::before { - font-family : 'dpercent-Kremlin'; - content : '\e92d'; - } - &.dper-46::before { - font-family : 'dpercent-Kremlin'; - content : '\e92e'; - } - &.dper-47::before { - font-family : 'dpercent-Kremlin'; - content : '\e92f'; - } - &.dper-48::before { - font-family : 'dpercent-Kremlin'; - content : '\e930'; - } - &.dper-49::before { - font-family : 'dpercent-Kremlin'; - content : '\e931'; - } - &.dper-50::before { - font-family : 'dpercent-Kremlin'; - content : '\e932'; - } - &.dper-51::before { - font-family : 'dpercent-Kremlin'; - content : '\e933'; - } - &.dper-52::before { - font-family : 'dpercent-Kremlin'; - content : '\e934'; - } - &.dper-53::before { - font-family : 'dpercent-Kremlin'; - content : '\e935'; - } - &.dper-54::before { - font-family : 'dpercent-Kremlin'; - content : '\e936'; - } - &.dper-55::before { - font-family : 'dpercent-Kremlin'; - content : '\e937'; - } - &.dper-56::before { - font-family : 'dpercent-Kremlin'; - content : '\e938'; - } - &.dper-57::before { - font-family : 'dpercent-Kremlin'; - content : '\e939'; - } - &.dper-58::before { - font-family : 'dpercent-Kremlin'; - content : '\e93a'; - } - &.dper-59::before { - font-family : 'dpercent-Kremlin'; - content : '\e93b'; - } - &.dper-60::before { - font-family : 'dpercent-Kremlin'; - content : '\e93c'; - } - &.dper-61::before { - font-family : 'dpercent-Kremlin'; - content : '\e93d'; - } - &.dper-62::before { - font-family : 'dpercent-Kremlin'; - content : '\e93e'; - } - &.dper-63::before { - font-family : 'dpercent-Kremlin'; - content : '\e93f'; - } - &.dper-64::before { - font-family : 'dpercent-Kremlin'; - content : '\e940'; - } - &.dper-65::before { - font-family : 'dpercent-Kremlin'; - content : '\e941'; - } - &.dper-66::before { - font-family : 'dpercent-Kremlin'; - content : '\e942'; - } - &.dper-67::before { - font-family : 'dpercent-Kremlin'; - content : '\e943'; - } - &.dper-68::before { - font-family : 'dpercent-Kremlin'; - content : '\e944'; - } - &.dper-69::before { - font-family : 'dpercent-Kremlin'; - content : '\e945'; - } - &.dper-70::before { - font-family : 'dpercent-Kremlin'; - content : '\e946'; - } - &.dper-71::before { - font-family : 'dpercent-Kremlin'; - content : '\e947'; - } - &.dper-72::before { - font-family : 'dpercent-Kremlin'; - content : '\e948'; - } - &.dper-73::before { - font-family : 'dpercent-Kremlin'; - content : '\e949'; - } - &.dper-74::before { - font-family : 'dpercent-Kremlin'; - content : '\e94a'; - } - &.dper-75::before { - font-family : 'dpercent-Kremlin'; - content : '\e94b'; - } - &.dper-76::before { - font-family : 'dpercent-Kremlin'; - content : '\e94c'; - } - &.dper-77::before { - font-family : 'dpercent-Kremlin'; - content : '\e94d'; - } - &.dper-78::before { - font-family : 'dpercent-Kremlin'; - content : '\e94e'; - } - &.dper-79::before { - font-family : 'dpercent-Kremlin'; - content : '\e94f'; - } - &.dper-80::before { - font-family : 'dpercent-Kremlin'; - content : '\e950'; - } - &.dper-81::before { - font-family : 'dpercent-Kremlin'; - content : '\e951'; - } - &.dper-82::before { - font-family : 'dpercent-Kremlin'; - content : '\e952'; - } - &.dper-83::before { - font-family : 'dpercent-Kremlin'; - content : '\e953'; - } - &.dper-84::before { - font-family : 'dpercent-Kremlin'; - content : '\e954'; - } - &.dper-85::before { - font-family : 'dpercent-Kremlin'; - content : '\e955'; - } - &.dper-86::before { - font-family : 'dpercent-Kremlin'; - content : '\e956'; - } - &.dper-87::before { - font-family : 'dpercent-Kremlin'; - content : '\e957'; - } - &.dper-88::before { - font-family : 'dpercent-Kremlin'; - content : '\e958'; - } - &.dper-89::before { - font-family : 'dpercent-Kremlin'; - content : '\e959'; - } - &.dper-90::before { - font-family : 'dpercent-Kremlin'; - content : '\e95a'; - } - &.dper-91::before { - font-family : 'dpercent-Kremlin'; - content : '\e95b'; - } - &.dper-92::before { - font-family : 'dpercent-Kremlin'; - content : '\e95c'; - } - &.dper-93::before { - font-family : 'dpercent-Kremlin'; - content : '\e95d'; - } - &.dper-94::before { - font-family : 'dpercent-Kremlin'; - content : '\e95e'; - } - &.dper-95::before { - font-family : 'dpercent-Kremlin'; - content : '\e95f'; - } - &.dper-96::before { - font-family : 'dpercent-Kremlin'; - content : '\e960'; - } - &.dper-97::before { - font-family : 'dpercent-Kremlin'; - content : '\e961'; - } - &.dper-98::before { - font-family : 'dpercent-Kremlin'; - content : '\e962'; - } - &.dper-99::before { - font-family : 'dpercent-Kremlin'; - content : '\e963'; - } - &.dper-100::before { - font-family : 'dpercent-Kremlin'; - content : '\e964'; - } + + // Replacement d10 + + &.d10-0::before { + font-family : 'dicefont-percent'; + content : '\e900'; + } + + &.d10-1::before { + font-family : 'dicefont-percent'; + content : '\e901'; + } + + &.d10-2::before { + font-family : 'dicefont-percent'; + content : '\e902'; + } + + &.d10-3::before { + font-family : 'dicefont-percent'; + content : '\e903'; + } + + &.d10-4::before { + font-family : 'dicefont-percent'; + content : '\e904'; + } + + &.d10-5::before { + font-family : 'dicefont-percent'; + content : '\e905'; + } + + &.d10-6::before { + font-family : 'dicefont-percent'; + content : '\e906'; + } + + &.d10-7::before { + font-family : 'dicefont-percent'; + content : '\e907'; + } + + &.d10-8::before { + font-family : 'dicefont-percent'; + content : '\e908'; + } + + &.d10-9::before { + font-family : 'dicefont-percent'; + content : '\e909'; + } + + &.d10-10::before { + font-family : 'dicefont-percent'; + content : '\e90a'; + } + + // d100 + + &.dpercent-00::before { + font-family : 'dicefont-percent'; + content : '\e90b'; + } + + &.dpercent-01::before { + font-family : 'dicefont-percent'; + content : '\e90c'; + } + + &.dpercent-02::before { + font-family : 'dicefont-percent'; + content : '\e90d'; + } + + &.dpercent-03::before { + font-family : 'dicefont-percent'; + content : '\e90e'; + } + + &.dpercent-04::before { + font-family : 'dicefont-percent'; + content : '\e90f'; + } + + &.dpercent-05::before { + font-family : 'dicefont-percent'; + content : '\e910'; + } + + &.dpercent-06::before { + font-family : 'dicefont-percent'; + content : '\e911'; + } + + &.dpercent-07::before { + font-family : 'dicefont-percent'; + content : '\e912'; + } + + &.dpercent-08::before { + font-family : 'dicefont-percent'; + content : '\e913'; + } + + &.dpercent-09::before { + font-family : 'dicefont-percent'; + content : '\e914'; + } + + &.dpercent-10::before { + font-family : 'dicefont-percent'; + content : '\e915'; + } + + &.dpercent-11::before { + font-family : 'dicefont-percent'; + content : '\e916'; + } + + &.dpercent-12::before { + font-family : 'dicefont-percent'; + content : '\e917'; + } + + &.dpercent-13::before { + font-family : 'dicefont-percent'; + content : '\e918'; + } + + &.dpercent-14::before { + font-family : 'dicefont-percent'; + content : '\e919'; + } + + &.dpercent-15::before { + font-family : 'dicefont-percent'; + content : '\e91a'; + } + + &.dpercent-16::before { + font-family : 'dicefont-percent'; + content : '\e91b'; + } + + &.dpercent-17::before { + font-family : 'dicefont-percent'; + content : '\e91c'; + } + + &.dpercent-18::before { + font-family : 'dicefont-percent'; + content : '\e91d'; + } + + &.dpercent-19::before { + font-family : 'dicefont-percent'; + content : '\e91e'; + } + + &.dpercent-20::before { + font-family : 'dicefont-percent'; + content : '\e91f'; + } + + &.dpercent-21::before { + font-family : 'dicefont-percent'; + content : '\e920'; + } + + &.dpercent-22::before { + font-family : 'dicefont-percent'; + content : '\e921'; + } + + &.dpercent-23::before { + font-family : 'dicefont-percent'; + content : '\e922'; + } + + &.dpercent-24::before { + font-family : 'dicefont-percent'; + content : '\e923'; + } + + &.dpercent-25::before { + font-family : 'dicefont-percent'; + content : '\e924'; + } + + &.dpercent-26::before { + font-family : 'dicefont-percent'; + content : '\e925'; + } + + &.dpercent-27::before { + font-family : 'dicefont-percent'; + content : '\e926'; + } + + &.dpercent-28::before { + font-family : 'dicefont-percent'; + content : '\e927'; + } + + &.dpercent-29::before { + font-family : 'dicefont-percent'; + content : '\e928'; + } + + &.dpercent-30::before { + font-family : 'dicefont-percent'; + content : '\e929'; + } + + &.dpercent-31::before { + font-family : 'dicefont-percent'; + content : '\e92a'; + } + + &.dpercent-32::before { + font-family : 'dicefont-percent'; + content : '\e92b'; + } + + &.dpercent-33::before { + font-family : 'dicefont-percent'; + content : '\e92c'; + } + + &.dpercent-34::before { + font-family : 'dicefont-percent'; + content : '\e92d'; + } + + &.dpercent-35::before { + font-family : 'dicefont-percent'; + content : '\e92e'; + } + + &.dpercent-36::before { + font-family : 'dicefont-percent'; + content : '\e92f'; + } + + &.dpercent-37::before { + font-family : 'dicefont-percent'; + content : '\e930'; + } + + &.dpercent-38::before { + font-family : 'dicefont-percent'; + content : '\e931'; + } + + &.dpercent-39::before { + font-family : 'dicefont-percent'; + content : '\e932'; + } + + &.dpercent-40::before { + font-family : 'dicefont-percent'; + content : '\e933'; + } + + &.dpercent-41::before { + font-family : 'dicefont-percent'; + content : '\e934'; + } + + &.dpercent-42::before { + font-family : 'dicefont-percent'; + content : '\e935'; + } + + &.dpercent-43::before { + font-family : 'dicefont-percent'; + content : '\e936'; + } + + &.dpercent-44::before { + font-family : 'dicefont-percent'; + content : '\e937'; + } + + &.dpercent-45::before { + font-family : 'dicefont-percent'; + content : '\e938'; + } + + &.dpercent-46::before { + font-family : 'dicefont-percent'; + content : '\e939'; + } + + &.dpercent-47::before { + font-family : 'dicefont-percent'; + content : '\e93a'; + } + + &.dpercent-48::before { + font-family : 'dicefont-percent'; + content : '\e93b'; + } + + &.dpercent-49::before { + font-family : 'dicefont-percent'; + content : '\e93c'; + } + + &.dpercent-50::before { + font-family : 'dicefont-percent'; + content : '\e93d'; + } + + &.dpercent-51::before { + font-family : 'dicefont-percent'; + content : '\e93e'; + } + + &.dpercent-52::before { + font-family : 'dicefont-percent'; + content : '\e93f'; + } + + &.dpercent-53::before { + font-family : 'dicefont-percent'; + content : '\e940'; + } + + &.dpercent-54::before { + font-family : 'dicefont-percent'; + content : '\e941'; + } + + &.dpercent-55::before { + font-family : 'dicefont-percent'; + content : '\e942'; + } + + &.dpercent-56::before { + font-family : 'dicefont-percent'; + content : '\e943'; + } + + &.dpercent-57::before { + font-family : 'dicefont-percent'; + content : '\e944'; + } + + &.dpercent-58::before { + font-family : 'dicefont-percent'; + content : '\e945'; + } + + &.dpercent-59::before { + font-family : 'dicefont-percent'; + content : '\e946'; + } + + &.dpercent-60::before { + font-family : 'dicefont-percent'; + content : '\e947'; + } + + &.dpercent-61::before { + font-family : 'dicefont-percent'; + content : '\e948'; + } + + &.dpercent-62::before { + font-family : 'dicefont-percent'; + content : '\e949'; + } + + &.dpercent-63::before { + font-family : 'dicefont-percent'; + content : '\e94a'; + } + + &.dpercent-64::before { + font-family : 'dicefont-percent'; + content : '\e94b'; + } + + &.dpercent-65::before { + font-family : 'dicefont-percent'; + content : '\e94c'; + } + + &.dpercent-66::before { + font-family : 'dicefont-percent'; + content : '\e94d'; + } + + &.dpercent-67::before { + font-family : 'dicefont-percent'; + content : '\e94e'; + } + + &.dpercent-68::before { + font-family : 'dicefont-percent'; + content : '\e94f'; + } + + &.dpercent-69::before { + font-family : 'dicefont-percent'; + content : '\e950'; + } + + &.dpercent-70::before { + font-family : 'dicefont-percent'; + content : '\e951'; + } + + &.dpercent-71::before { + font-family : 'dicefont-percent'; + content : '\e952'; + } + + &.dpercent-72::before { + font-family : 'dicefont-percent'; + content : '\e953'; + } + + &.dpercent-73::before { + font-family : 'dicefont-percent'; + content : '\e954'; + } + + &.dpercent-74::before { + font-family : 'dicefont-percent'; + content : '\e955'; + } + + &.dpercent-75::before { + font-family : 'dicefont-percent'; + content : '\e956'; + } + + &.dpercent-76::before { + font-family : 'dicefont-percent'; + content : '\e957'; + } + + &.dpercent-77::before { + font-family : 'dicefont-percent'; + content : '\e958'; + } + + &.dpercent-78::before { + font-family : 'dicefont-percent'; + content : '\e959'; + } + + &.dpercent-79::before { + font-family : 'dicefont-percent'; + content : '\e95a'; + } + + &.dpercent-80::before { + font-family : 'dicefont-percent'; + content : '\e95b'; + } + + &.dpercent-81::before { + font-family : 'dicefont-percent'; + content : '\e95c'; + } + + &.dpercent-82::before { + font-family : 'dicefont-percent'; + content : '\e95d'; + } + + &.dpercent-83::before { + font-family : 'dicefont-percent'; + content : '\e95e'; + } + + &.dpercent-84::before { + font-family : 'dicefont-percent'; + content : '\e95f'; + } + + &.dpercent-85::before { + font-family : 'dicefont-percent'; + content : '\e960'; + } + + &.dpercent-86::before { + font-family : 'dicefont-percent'; + content : '\e961'; + } + + &.dpercent-87::before { + font-family : 'dicefont-percent'; + content : '\e962'; + } + + &.dpercent-88::before { + font-family : 'dicefont-percent'; + content : '\e963'; + } + + &.dpercent-89::before { + font-family : 'dicefont-percent'; + content : '\e964'; + } + + &.dpercent-90::before { + font-family : 'dicefont-percent'; + content : '\e965'; + } + + &.dpercent-91::before { + font-family : 'dicefont-percent'; + content : '\e966'; + } + + &.dpercent-92::before { + font-family : 'dicefont-percent'; + content : '\e967'; + } + + &.dpercent-93::before { + font-family : 'dicefont-percent'; + content : '\e968'; + } + + &.dpercent-94::before { + font-family : 'dicefont-percent'; + content : '\e969'; + } + + &.dpercent-95::before { + font-family : 'dicefont-percent'; + content : '\e96a'; + } + + &.dpercent-96::before { + font-family : 'dicefont-percent'; + content : '\e96b'; + } + + &.dpercent-97::before { + font-family : 'dicefont-percent'; + content : '\e96c'; + } + + &.dpercent-98::before { + font-family : 'dicefont-percent'; + content : '\e96d'; + } + + &.dpercent-99::before { + font-family : 'dicefont-percent'; + content : '\e96e'; + } + + &.dpercent-100::before { + font-family : 'dicefont-percent'; + content : '\e96f'; + } + + } \ No newline at end of file diff --git a/themes/fonts/iconFonts/dicefont-D100.woff b/themes/fonts/iconFonts/dicefont-D100.woff new file mode 100644 index 0000000000000000000000000000000000000000..6f7404cb8d9d39252636fd73d468fed9d40792b6 GIT binary patch literal 81608 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 literal 0 HcmV?d00001 diff --git a/themes/fonts/iconFonts/dpercent-Kremlin.woff b/themes/fonts/iconFonts/dpercent-Kremlin.woff deleted file mode 100644 index d425f7f51133ea81ef7cbfcc70ecf6d2f55b0e45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84332 zcmeHw3z!^bnePAB<*$2nSKqs*@6*$rnF({h9zFczu=OOoe$@pLijzOp|@8i-@fL; zEt@tY{66};F?#FWxZ|}8;Ut{99_|(+e~ z4!=)tzrFwV_iWvC#SVmzUjg^C=IwI)!EKwiZh>=W!Smjvw^vbea>w>dcfsHL{^{#j zIAYm9;Lji)A?ANEPr?09TmRzM&@h(Ze&rYTSKgz?$0GE~X7<3*1L#;5Zg7Tvrc+;8 z^T2!;I7-4}^f(DW=~YR@na@z+lVac)!*4(E%I2eQA3bV5kKRM(J$&@=(dVOl`FZAp z<`0Z8T%55ehd$djgO75#paI*94r+}eHeZei7<6h2%ZEdN2f0v9*RVT^2;$g_F)5F zU~q`=Q3I~)XRMd#$MijTcvJH`9HQ?@-;Tc72z{469Ibe0y!;TncU}mA5yKDV=o)|(H4-Q^7IDpSwzh}>h z8}R_#8N>{WG0SYgidu>%lGo<+2*cff;zgLj>+a&1h@QJPnMf2>1#=R2(eaaiE$fo3 z@;v7^lyoqdR5c&RvLqdqx*kycV!+Sxa&I=4*AxXa#V#o+-Ym-uW;mfs=2;9+)%ks@ zDvCTIqRJ5tV~L)deB)hb!*7e3iDUn90{%jyTj4(ZE@ntG@Uas&9Xo;P*GJ#;1%->L z>?7Rj)z_|C#gNH+dG@#yl8JapRpDcR7f{VVNOmP`FG87$_J(UG-)68X296B(^&J-uF+^ZD zuDqHRMJep_<>KAr0hNAbqsCf)zE|SlW0a-9Xm>QHcNTCU=4 z#Y|#Zm%y@EC>FB?2|f!Vit%J`kH|8UZzZ}gd&)=$E|or9Dq&rU@VJ!d6=XPZPN~$F z>&xTrj`tBp6A)m)fseiDA@p7JYU`rIhr@uE2^=0aI^96QdVl#pO}avo%o}28buV|n zW6_`P?e#5aS(#tSG9oA4gAHNOv92eNG`NPpiGGNFgJJh?)g9i4qeGDlrkn8E@~%!d z=J4=nXTCT(U>bzAbfceT<8OmCeqSobG65k#G>paNqLAoL#s%144~&G#GEckPH@`#t5 ztW1AEi^49zB_kXUk;kf4D^58DpOo#xjOZVJw*oh`W=1u^_P=JhB;IFKl&S$K!!XL0=x| z#hB+DLLQu=ms-iIVbjt; zR?SCE67}sM!$s3sW-bd(MLlb7LOF@f51V!ymhfeZ38h0 z%{1-=CeRG)r=p;;SLRMBTAp3lbl<42W@V@?QWEY1gBhWDIKgwinG<05DgjAWSV0SL z3JcDePmW_&Q?x`dl+{9hB8l0cl#y<9Se(aMVy4zu&M)f*&xr|1XCRi+BuS=RTuM?| zJo$phLB}YP9MqDd22T+ONd+O2lvPR9gJXTEyb*}Qhu{PrrFDoXOA;>%7>5j5Co(Ty zDf@uug@m^Oxi;|HxU1@cp-bLjH~LcZ{WBjy9`N(k-IAs%7$=;U@lt-!h z&kLPFMOA|Wgf(lHb6<3)=Q}-0#(!GNNPH^AaT3_ek-}Nn5Q#enKiVkcZdMc7{IlKY zR`fM=sF~KpeI-{h?Ov%Wu`Sj8l~nrV?^}OQc3F(LnlPXIRy~_1RIfSK+kS`!e%*@e ztqxY)E1|7zJ>Fh3?ft4J*D7B#w>|lIJ!kOV*KE-!>Ga4GdqXjdtv77n0EpAhmFdD;A$gbmmL;qDP_1>sOdG z6D?N0aCMn%hn^P-6!7x=2K82d9b}`$7}dRNXSFIu?{WFf)Ik1m3Y3V!v{@ZkX0%TCR07M$@fphL^|^~ zdx3>~2K~Y#NPv{SDnFt9E4(Pk+6%1Mt&C9gRx_9R)T6w2y z7|mRyz4O-x#k56webe|h?a@?qDnBzRQLO4Vdxgo(nkkONkeq z6(3c8&HklAm(Bs7N{{CqWKiAucK4zOfI)3?h0LsW#fdDhbE~z1Bm#Eumt$o+E)7YOM$kn4H~(3hRJpExO>r)=tW?0Ih^tcj)tc? zr{?I&rI}UW7TTcYwl*X^u@q?E+K}{)62We{rH9dT=rxaE$;g744nx0R$RleP>;P=@ZO$*(w#fIlG3{I%9Nr-!+6_0)LcjT2*pIutgB!}Z z)zCFdy{LBLr)vY#z9mLm*9NdA5!tSKbBEA>fWkur_ctGLgXPv&s@@2w0{MpU06iEC zLGyTo3d~u8)qQvnlpQKyHzjjYq2ox}mGu6k(IK)j#w)2Boka9FFYuBqf~*aL2^WkC zJ~1E$cpgr$*e}a|&^_RxC!O^Pk-U!+84VuiRaO?VhMbhX(QfQ`)JNHIN#NuFH0k>U z2{gzUY^aJKJ}-g=rCR_|GByB&3l$H-IHwqK9%G*$`uXE4{Q~dr4(cE+M5VZ0CAAl! zo!5nzIfQhOrXZiO16&@!3Vl{RR<1gdDS?5+&k{cUo5|kkf{~gkA*?x5M)&p1>6?;?#hedSjsG z2mhMGmprFK-T)|l2~`TS{1&s#yvN89A7Mnc0$~5{ozC-xTSieJQBk&f)K|y*#jwK5 zpjtg0*WFTg+q$!c6o>IKc%A3b12`$$z}c0|O|NwJQVR#-mVoh76e*sC&I7Eg+U!#2 zb5&$;Y)%1HyQO3OK%KcO4${_^L7a8VEJ}I@mN*nb7>WI zG+-{>5~BaIG^#%q?!-FMr0-;rh|`Zf)G9ptBIiv#EH<#ni2S4nt4_+QWrx(IjU-IBU zgbo+-#OTKzt1n)a!}-3|&(&TI^G!pPa`?p7XDnWzonkoIaoZWE)n3qYN*uCV{XY4j zx+Jw+W-eTXZbVI1bF;7JDg_8nFW1*9%SyiPy#=|UTG`=~3tDteeV(g8ljJeDhsSz+;Ta)PjJf2x;vHJOa=f3+Ln1=9c4Ck9wb zI1u#rWF|JiXS4_n`p$gN-=S}#pP=726F*hFWodrYL?c50C^`eei8+rnX?(Gg;Cy>d zP_UgzIWK3HsX9?aJDOUbrQcmmg|c(3{7jF)Fw$6OD5DD$5z}aye4-w<-nqu_09|~H z6U|-YbxiXXmIMY4)=a4Wq@4kBP0iHnTvlU|u;c8BXK(@!HxoH!PibIm)O4aC!`W+k zPXi#HGz4A~JPw6f{kW6%^I1k=L0;Gdb;zhsW_n>2UGsF(kVnkQ!CJKQVU(63g_BXc zEt$tN3+Hr6V>yP=B|RH9I@DlLQe;jhJV{5ytmuIObmmc5{vqphF<}(SflE2C9m|7R^3h-PJmI#IQ`BQ-cc@?E(op zz7VI9d>LKQK%tHkl76uuv9!~9GrnG!y>*-=$*9vNwSIha?HmTegbL{blaS~FRX$ah z;#%7A@3xiy^y_Z3WPk_qx6-~1!01)_2m6Kp~`e~M3 zq0$a!x{Ug2vrlgqs5jRZ^8OEpa}qCbB<`=@9KpK7kagx`iW<;DDJ>%Fd{kgLtV$8k zc@Q`u;TLmK$w8`P&(Z1E@Y$H&9n@rhhfs$l6S`AGVE7J6iSdNPiXL8erW0^}QnVj@t~BobZ$wu`}|N+*MTvZe}K8YnPu);!)0 zdLl<)LS`pk(@fM+2e5{z0u5%sL3NNq&U7{bg4Q(IC}=jr+r#~S@C<48P=M>a(8u{$ zZG{If)c{9#JBA_2!BD=1<@~a4@SK>CbWc_*TvJPp!h#a%Q45nEZt%ljt>ff1P}YoEN$Bu zvLmua2Nlo_iC031Xkk{sr34(Z|}+UaM06=rEa-|Q|A%g-!BYYZZ;s$vb8OqVa$*47Hg znfi{BiB@Z(od-iXEQn$*5bW`b2FqSx&Knqy<{)a}Lt2dhyT_{gxX-h`XGh-Wk3$Yf z5h60Nsyt549V2kQI0Us-5u7VvE}#V=dIQ0k>paI_19KgP%-snsX9tI;?V!mf?I1Ukd-iGi=UchOs^)$1=)jV%6lyN}Uw6Pv6oT&-C|6E&j&2_U_ z%1520GY4&0KIF|(ni?qlTB>baLCv{V(|pk8v3567UE{1fy$*c|?E|IN*PDiH3Rk_{ zzfe^#!-qj2#8M0a`7<*kJK7nB`ZO9G+Nx!+H>%bw5fIS0=*?Ctc}yN14yOqh%QCAm z)1Q+c#s!y>m&rF;zs7}Xdjv+iqdC2^Ql=xF!U`#!Q;I};w=Gk8Q&E@NmC3j2C{}@d zsIxcp@6fHF27joTE4fOy!+ikFwO^yOw1Q&0?D+|09kqU-o#iCh~uBlqiMQ*}_i+>*ZiJ;6ueux!erqd8}5Z>-Mq0M#eA*@g+ z`HeXy4&)}^w7~=~caYK^6iS$9uzl7BlbD@XUUcn)-OZk)=<0ibb7DE|K0FK^q!Ta| zDeTq#eP1=}>j9wx`)1vc1cA$}_*>9@=nl#bBZ& zfRcdNmjPK`QSc20RRcuJX6dgV<77eCK>LJ1RPVw~ZU#YuKpY2+Kn`*l zM7l4c-?cJ&T-xbpK+~4+_+e%9{CzW^VA=}+wm$j6iiLmP!WOwRmvalm5I<;ve!h7u z!~$C4+Z+S?YHonPp=|+DbFceo>p>+Ned zC64-O=MN zM@3adqC|*JRHBNS!C|IHW1VM5@j;w%q<22-E>{Ppfe!$y~8y`1RtI_-e zxqfJ0qhm$f7XJB^er6Zuy1Ce&m(Z`8tV8P-+gEp@F07q=F08aiL=!LYuw^FvTEI6O zB|R6X&9PY(CbYDd;hD|^2nCoq5Xy<5AXwMX0h!Kekd@$~+Z|`G%`GtJ`6={&pceo4 z&L9?gg=AqnIRD@UavF*|V&7W(2?jH1YP`!K!9cg9!xy=@+!dqLS>EqRu z{TVaZX|pVyqbEC7frbU<>72SF`yo&FuQ2KMH(0{?mRjvo{+=li0)q@KkI%|AlqVF- z<<1RH*8)_+z{)gG87^;iTRWK@)6wG!_5lJN;ZPbzv-pW5$aHS9G)oF$|8(8JfoYTS zyyq$i99$3e@Dv!hW$&R@)X<6`k;IS!U$gmf)8z#f=n@vWm--g;1cKS@kl`cHuQ=XP zh;#aPwU#7QdU;lo(7kus%0GCvDq((t_3O1YO^j(L+czUAr;VWQ4WeD@=S`FWh4ShHOBn&k70k zVV63HJ2_1xL6(EWHO#V=ppxJM57a{d)_l1rB!f5!h75o>p1*_Uh+uG@p)CstypfWp z`n1Q^>ypGmF0m&|S&dS%9knXcXyS0{C>;Pt{W) z;f6mtci;ecroY0ZRq>2( zt-erMH*v2GNk&_tMjl#byjx2aM2@wUQ4Ce#xMETI=WTvs`-5;% zdhVADKrx92XRpxk&C{trzPJX`iCgM1K8bz|GvfTMY9H5v&}C(J|EwX}Oy!1|gK3|z zjLSsylCE_Kn6V@Qwqhu+QIF|x3BvBPsyOzvi3geJBpgSCl%IxQR$a#}xsH?`OWLEX zEwrE`-IxpM#K#^}YgNX1yt-BKF>Tkt^!R3q4QCP<(}0;4f|*@)V9CW{H_TPqQIlN3 z#Y@H4%q>{tAiTI{3^_SDsvZ71n#4g6d3j%}A{AgaGBzBFSP95E)Dpmc`6>#1tD?Md z)8Q;t&jEl^;EFjp?U*}(q$Cd%6%@D5GZ`S$MW9Z&GYvTwdxG+@c`8NjZ4;w8ovf5Q z6v!&dX<$Z}aP4MD+Hb&Tj30$>+w=xNN@f}W3? zy?p>`h<^y&Iy~0I8sa%Pgc*D5qUx~Z?B|u$wI!!76=UcqHHj~>jdRvHQtkimp?`<` zJ_D-a!!3`G8nyqcShnd36mVb5M$M`^X|s^dV%jPRfk)>P{rYlqI!WWsw%$6H2pF}@`Y2SQHOqH8I{|UIPy-20X_oOi;;L?0PEnFTk zsc~0mT1i&3+Ke*eV?)p-?rmDU60G}ct6BN1%^Dtb7Opsb&i&pjV400GuRw4uB`nn_ zW?YL{{?dtHwxME{%6M`!`WX5w`rpt~@EoXh9Ki|GiWi%5aFW+#SjBvGt)R0pa6!@?o)nAv+krcLerh) z#?WXaL|+`FI_RsLY8?RMs#Clv(lNo91UzV>cBOGA#E^OVyTCUfdk|)$zcY|crPrm> zA`e}jJm)vmWPk{(mYw_bs$QN|aW=Cdn}vW5x)_-aSW!#yMDp649$~oqPrL{mp>=n0 zOhnI>0#Vj4lI(D95GL|+7ac!&I9~_`m532Z>p?%1T8R0Wm=Ov@0t%iplzOW&ef!(@IV zABy0Xxcq-^_=s=K?~noluJHA_to+Z_pLy4X z6XzWJ&G(@9p8vjA*X57@r}aZ8?l|f74cDB~^MTKuw(9h^K6uHQ*|T0hd-I3VAAa*A zU)i+w+~05h>G@Y)c<#j~{P~Mp@7=!Vzmc75F1_`#;(yyL&$U>UFz5yX*$;#_Mmo@aFg5@}tl1z3nq!fQiE9 zio6(~PG>^F*VM{2@05S&=qu%QixIGH>EHE;liEhQg{>kP! Date: Sun, 11 May 2025 18:39:25 -0500 Subject: [PATCH 04/95] Move d100 Source files --- .../fonts/iconFonts/d100_Sources => d100_Sources}/buildFont.bash | 0 .../iconFonts/d100_Sources => d100_Sources}/d10-MASTER-AB.svg | 0 .../fonts/iconFonts/d100_Sources => d100_Sources}/d10-MASTER.svg | 0 {themes/fonts/iconFonts/d100_Sources => d100_Sources}/readme.md | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {themes/fonts/iconFonts/d100_Sources => d100_Sources}/buildFont.bash (100%) rename {themes/fonts/iconFonts/d100_Sources => d100_Sources}/d10-MASTER-AB.svg (100%) rename {themes/fonts/iconFonts/d100_Sources => d100_Sources}/d10-MASTER.svg (100%) rename {themes/fonts/iconFonts/d100_Sources => d100_Sources}/readme.md (100%) diff --git a/themes/fonts/iconFonts/d100_Sources/buildFont.bash b/d100_Sources/buildFont.bash similarity index 100% rename from themes/fonts/iconFonts/d100_Sources/buildFont.bash rename to d100_Sources/buildFont.bash diff --git a/themes/fonts/iconFonts/d100_Sources/d10-MASTER-AB.svg b/d100_Sources/d10-MASTER-AB.svg similarity index 100% rename from themes/fonts/iconFonts/d100_Sources/d10-MASTER-AB.svg rename to d100_Sources/d10-MASTER-AB.svg diff --git a/themes/fonts/iconFonts/d100_Sources/d10-MASTER.svg b/d100_Sources/d10-MASTER.svg similarity index 100% rename from themes/fonts/iconFonts/d100_Sources/d10-MASTER.svg rename to d100_Sources/d10-MASTER.svg diff --git a/themes/fonts/iconFonts/d100_Sources/readme.md b/d100_Sources/readme.md similarity index 100% rename from themes/fonts/iconFonts/d100_Sources/readme.md rename to d100_Sources/readme.md From 077aaeb815d78ee4bb4bb2c873a62d6b6389efc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 27 May 2025 10:54:07 +0200 Subject: [PATCH 05/95] log --- client/homebrew/brewRenderer/brewRenderer.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index c391d8c43..4b65a9425 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -290,6 +290,7 @@ const BrewRenderer = (props)=>{ const styleObject = {}; + console.log(global.config); if(global.config.deployment) { styleObject.backgroundImage = `url("data:image/svg+xml;utf8,${global.config.deployment}")`; } From ed05d8c754d6a76a65076f4cb6a1d78e0aca53f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 27 May 2025 11:25:01 +0200 Subject: [PATCH 06/95] move all to homebrew.jsx --- client/homebrew/brewRenderer/brewRenderer.jsx | 10 +------ .../homebrew/brewRenderer/brewRenderer.less | 1 - client/homebrew/homebrew.jsx | 27 +++++++++++++++++-- client/homebrew/homebrew.less | 4 ++- .../homebrew/pages/vaultPage/vaultPage.less | 7 ++--- 5 files changed, 33 insertions(+), 16 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 4b65a9425..82c1ebb19 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -288,13 +288,6 @@ const BrewRenderer = (props)=>{ rowGap : `${displayOptions.rowGap}px` }; - const styleObject = {}; - - console.log(global.config); - if(global.config.deployment) { - styleObject.backgroundImage = `url("data:image/svg+xml;utf8,${global.config.deployment}")`; - } - const renderedStyle = useMemo(()=>renderStyle(), [props.style, props.themeBundle]); renderedPages = useMemo(()=>renderPages(), [props.text, displayOptions]); @@ -323,10 +316,9 @@ const BrewRenderer = (props)=>{ contentDidMount={frameDidMount} onClick={()=>{emitClick();}} > -
{/* Apply CSS from Style tab and render pages from Markdown tab */} diff --git a/client/homebrew/brewRenderer/brewRenderer.less b/client/homebrew/brewRenderer/brewRenderer.less index b0a3e9779..bb4fe69c5 100644 --- a/client/homebrew/brewRenderer/brewRenderer.less +++ b/client/homebrew/brewRenderer/brewRenderer.less @@ -6,7 +6,6 @@ overflow-y : scroll; will-change : transform; &:has(.facing, .flow) { padding : 60px 30px; } - &.deployment { background-color : darkred; } :where(.pages) { &.facing { display : grid; diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index 415390498..6e7a95a31 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -63,13 +63,36 @@ const Homebrew = createClass({ global.enable_themes = this.props.enable_themes; global.config = this.props.config; - return {}; + return { isClient: false }; }, + componentDidMount : function() { + this.setState({ isClient: true }); + }, + + backgroundObject : function() { + if(!this.state.isClient) return null; + + if(this.props.config.deployment) { + return { + backgroundImage : `url("data:image/svg+xml;utf8,${this.props.config.deployment}")` + }; + } else if(this.props.config.local) { + return { + backgroundImage : `url("data:image/svg+xml;utf8,Local")` + }; + } + + return null; + }, + + render : function (){ return ( -
+
} /> } /> diff --git a/client/homebrew/homebrew.less b/client/homebrew/homebrew.less index e265c2941..6df5254ec 100644 --- a/client/homebrew/homebrew.less +++ b/client/homebrew/homebrew.less @@ -1,12 +1,14 @@ @import 'naturalcrit/styles/core.less'; .homebrew { height : 100%; + &.deployment { background-color : darkred; } + .sitePage { display : flex; flex-direction : column; height : 100%; overflow-y : hidden; - background-color : @steel; + //background-color : @steel; .content { position : relative; flex : auto; diff --git a/client/homebrew/pages/vaultPage/vaultPage.less b/client/homebrew/pages/vaultPage/vaultPage.less index 8a5f3a714..304fefc72 100644 --- a/client/homebrew/pages/vaultPage/vaultPage.less +++ b/client/homebrew/pages/vaultPage/vaultPage.less @@ -1,14 +1,16 @@ .vaultPage { height : 100%; overflow-y : hidden; - background-color : #2C3E50; *:not(input) { user-select : none; } + .form { + background:white; + } + :where(.content .dataGroup) { width : 100%; height : 100%; - background : white; &.form .brewLookup { position : relative; @@ -171,7 +173,6 @@ max-height : 100%; padding : 70px 50px; overflow-y : scroll; - background-color : #2C3E50; container-type : inline-size; h3 { font-size : 25px; } From 88b70d340e6fccb2e21176e254d9211bd9051a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Tue, 27 May 2025 11:27:04 +0200 Subject: [PATCH 07/95] final bit --- client/homebrew/homebrew.less | 1 + 1 file changed, 1 insertion(+) diff --git a/client/homebrew/homebrew.less b/client/homebrew/homebrew.less index 6df5254ec..5c7b63023 100644 --- a/client/homebrew/homebrew.less +++ b/client/homebrew/homebrew.less @@ -1,6 +1,7 @@ @import 'naturalcrit/styles/core.less'; .homebrew { height : 100%; + background-color:@steel; &.deployment { background-color : darkred; } .sitePage { From f04d6cdd1fd245569aa1ecc5db7598c42d8cfa2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 17 Jul 2025 23:32:18 +0200 Subject: [PATCH 08/95] fix to current --- client/homebrew/homebrew.jsx | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index a6b4b9175..a261e76ef 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -1,7 +1,7 @@ /* eslint-disable camelcase */ import 'core-js/es/string/to-well-formed.js'; //Polyfill for older browsers import './homebrew.less'; -import React from 'react'; +import { useState, useEffect } from 'react'; import { StaticRouter as Router, Route, Routes, useParams, useSearchParams } from 'react-router'; import HomePage from './pages/homePage/homePage.jsx'; @@ -17,7 +17,6 @@ const WithRoute = ({ el: Element, ...rest })=>{ const params = useParams(); const [searchParams] = useSearchParams(); const queryParams = Object.fromEntries(searchParams?.entries() || []); - return ; }; @@ -42,15 +41,35 @@ const Homebrew = (props)=>{ brews } = props; + const [isClient, setIsClient] = useState(false); + + useEffect(() => { + setIsClient(true); + }, []); + global.account = account; global.version = version; global.enable_v3 = enable_v3; global.enable_themes = enable_themes; global.config = config; + const backgroundObject = ()=>{ + if(!isClient) return null; + if(config.deployment) { + return { + backgroundImage : `url("data:image/svg+xml;utf8,${config.deployment}")` + }; + } else if(config.local) { + return { + backgroundImage : `url("data:image/svg+xml;utf8,Local")` + }; + } + return null; + }; + return ( -
+
} /> } /> @@ -72,4 +91,4 @@ const Homebrew = (props)=>{ ); }; -module.exports = Homebrew; \ No newline at end of file +module.exports = Homebrew; From d6a5a1f03c82025f10e0862a2cb261c0b25be8f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 18 Jul 2025 00:39:36 +0200 Subject: [PATCH 09/95] no idea what changed but now it works --- client/homebrew/homebrew.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index a261e76ef..095c679f1 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -1,7 +1,7 @@ /* eslint-disable camelcase */ import 'core-js/es/string/to-well-formed.js'; //Polyfill for older browsers import './homebrew.less'; -import { useState, useEffect } from 'react'; +import React, { useState, useEffect } from 'react'; import { StaticRouter as Router, Route, Routes, useParams, useSearchParams } from 'react-router'; import HomePage from './pages/homePage/homePage.jsx'; @@ -43,7 +43,7 @@ const Homebrew = (props)=>{ const [isClient, setIsClient] = useState(false); - useEffect(() => { + useEffect(()=>{ setIsClient(true); }, []); From 878ea1449db719d7abe413b3c3b062cd4b2bba51 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 20 Jul 2025 11:42:24 +1200 Subject: [PATCH 10/95] Add indexes to HomebrewSchema --- server/homebrew.model.js | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/server/homebrew.model.js b/server/homebrew.model.js index 2e74b1de2..ff371ee42 100644 --- a/server/homebrew.model.js +++ b/server/homebrew.model.js @@ -7,29 +7,29 @@ import zlib from 'zlib'; const HomebrewSchema = mongoose.Schema({ shareId : { type: String, default: ()=>{return nanoid(12);}, index: { unique: true } }, editId : { type: String, default: ()=>{return nanoid(12);}, index: { unique: true } }, - googleId : { type: String }, - title : { type: String, default: '' }, + googleId : { type: String, index: true }, + title : { type: String, default: '', index: true }, text : { type: String, default: '' }, textBin : { type: Buffer }, - pageCount : { type: Number, default: 1 }, + pageCount : { type: Number, default: 1, index: true }, description : { type: String, default: '' }, - tags : [String], + tags : { type: [String], index: true }, systems : [String], - lang : { type: String, default: 'en' }, - renderer : { type: String, default: '' }, - authors : [String], + lang : { type: String, default: 'en', index: true }, + renderer : { type: String, default: '', index: true }, + authors : { type: [String], index: true }, invitedAuthors : [String], - published : { type: Boolean, default: false }, - thumbnail : { type: String, default: '' }, + published : { type: Boolean, default: false, index: true }, + thumbnail : { type: String, default: '', index: true }, - createdAt : { type: Date, default: Date.now }, - updatedAt : { type: Date, default: Date.now }, - lastViewed : { type: Date, default: Date.now }, + createdAt : { type: Date, default: Date.now, index: true }, + updatedAt : { type: Date, default: Date.now, index: true }, + lastViewed : { type: Date, default: Date.now, index: true }, views : { type: Number, default: 0 }, - version : { type: Number, default: 1 }, + version : { type: Number, default: 1, index: true }, - lock : { type: Object } + lock : { type: Object, index: true } }, { versionKey: false }); HomebrewSchema.statics.increaseView = async function(query) { @@ -43,6 +43,8 @@ HomebrewSchema.statics.increaseView = async function(query) { return brew; }; +// STATIC FUNCTIONS + HomebrewSchema.statics.get = async function(query, fields=null){ const brew = await Homebrew.findOne(query, fields).orFail() .catch((error)=>{throw 'Can not find brew';}); @@ -63,6 +65,15 @@ HomebrewSchema.statics.getByUser = async function(username, allowAccess=false, f return brews; }; +// INDEXES + +HomebrewSchema.index({ updatedAt: -1, lastViewed: -1 }); +HomebrewSchema.index({ published: 1, title: 'text' }); + +HomebrewSchema.index({ lock: 1, sparse: true }); +HomebrewSchema.path('lock.reviewRequested').index({ sparse: true }); + + const Homebrew = mongoose.model('Homebrew', HomebrewSchema); export { From d9cd270f3b993e02cb4a76bfd867d70247991989 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 20 Jul 2025 11:43:14 +1200 Subject: [PATCH 11/95] Add autobuild to Mongoose connection (local/docker ONLY) --- server/db.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/db.js b/server/db.js index 97da56a08..f4e7fd851 100644 --- a/server/db.js +++ b/server/db.js @@ -27,7 +27,10 @@ const disconnect = async ()=>{ }; const connect = async (config)=>{ - return await Mongoose.connect(getMongoDBURL(config), { retryWrites: false }) + return await Mongoose.connect(getMongoDBURL(config), { + retryWrites : false, + autoIndex : (config.get('node_env') == 'local' || config.get('node_env') == 'docker') + }) .catch((error)=>handleConnectionError(error)); }; From 4856c803ed6102d93397be2ba544da0d30eb6694 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 20 Jul 2025 11:48:22 +1200 Subject: [PATCH 12/95] Use local_environments from config --- server/db.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/db.js b/server/db.js index f4e7fd851..196eba650 100644 --- a/server/db.js +++ b/server/db.js @@ -29,7 +29,7 @@ const disconnect = async ()=>{ const connect = async (config)=>{ return await Mongoose.connect(getMongoDBURL(config), { retryWrites : false, - autoIndex : (config.get('node_env') == 'local' || config.get('node_env') == 'docker') + autoIndex : (config.get('local_environments').includes(config.get('node_env'))) }) .catch((error)=>handleConnectionError(error)); }; From 7af22c9da743573df36a5e2c66ded138edb6ae42 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 26 Jul 2025 12:13:59 +1200 Subject: [PATCH 13/95] Return a basic error message when DB connection is lost --- server/app.js | 2 + server/middleware/dbCheck.js | 13 +++++++ server/middleware/dbCheck.spec.js | 63 +++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 server/middleware/dbCheck.js create mode 100644 server/middleware/dbCheck.spec.js diff --git a/server/app.js b/server/app.js index 869fe6555..113f4c37d 100644 --- a/server/app.js +++ b/server/app.js @@ -32,6 +32,7 @@ import { splitTextStyleAndMetadata } from '../shared/helpers.js'; //==== Middleware Imports ====// import contentNegotiation from './middleware/content-negotiation.js'; +import dbCheck from './middleware/dbCheck.js'; import bodyParser from 'body-parser'; import cookieParser from 'cookie-parser'; import forceSSL from './forcessl.mw.js'; @@ -49,6 +50,7 @@ const sanitizeBrew = (brew, accessType)=>{ app.set('trust proxy', 1 /* number of proxies between user and server */); app.use('/', serveCompressedStaticAssets(`build`)); +app.use(dbCheck); app.use(contentNegotiation); app.use(bodyParser.json({ limit: '25mb' })); app.use(cookieParser()); diff --git a/server/middleware/dbCheck.js b/server/middleware/dbCheck.js new file mode 100644 index 000000000..e90190517 --- /dev/null +++ b/server/middleware/dbCheck.js @@ -0,0 +1,13 @@ +import mongoose from 'mongoose'; +import config from '../config.js'; + +export default (req, res, next)=>{ + // Bypass DB checks during testing + if(config.get('node_env') == 'test') return next(); + + if(mongoose.connection.readyState == 1) return next(); + return res.status(503).send({ + message : 'Unable to connect to database', + state : mongoose.connection.readyState + }); +}; diff --git a/server/middleware/dbCheck.spec.js b/server/middleware/dbCheck.spec.js new file mode 100644 index 000000000..c4482a54a --- /dev/null +++ b/server/middleware/dbCheck.spec.js @@ -0,0 +1,63 @@ +import mongoose from 'mongoose'; +import dbCheck from './dbCheck.js'; +import config from '../config.js'; + +describe('database check middleware', ()=>{ + let request; + let response; + let next; + + beforeEach(()=>{ + request = { + get : function(key) { + return this[key]; + } + }; + response = { + status : jest.fn(()=>response), + send : jest.fn(()=>{}) + }; + next = jest.fn(); + + // Mock the Config module + jest.mock('../config.js'); + config.get = jest.fn((param)=>{ + // The requested key name will be reflected to the output + return param; + }); + }); + + afterEach(()=>{ + jest.clearAllMocks(); + }); + + it('should return 503 if readystate != 1', ()=>{ + const dbState = mongoose.connection.readyState; + + mongoose.connection.readyState = 99; + + dbCheck(request, response); + + mongoose.connection.readyState = dbState; + + expect(response.status).toHaveBeenLastCalledWith(503); + expect(response.send).toHaveBeenLastCalledWith( + expect.objectContaining({ + message : 'Unable to connect to database', + state : 99 + }) + ); + }); + + it('should call next if readystate == 1', ()=>{ + const dbState = mongoose.connection.readyState; + + mongoose.connection.readyState = 1; + + dbCheck(request, response, next); + + mongoose.connection.readyState = dbState; + + expect(next).toHaveBeenCalled(); + }); +}); From 005c05376cb93f1274fd1c080a3458abe1f8d316 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 26 Jul 2025 14:11:20 +1200 Subject: [PATCH 14/95] Add DB connection/disconnections events to log --- server/db.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server/db.js b/server/db.js index 97da56a08..8958fa6b2 100644 --- a/server/db.js +++ b/server/db.js @@ -22,12 +22,21 @@ const handleConnectionError = (error)=>{ } }; +const addListeners = (conn)=>{ + conn.connection.on('disconnecting', ()=>{console.log('Mongo disconnecting...');}); + conn.connection.on('disconnected', ()=>{console.log('Mongo disconnected!');}); + conn.connection.on('connecting', ()=>{console.log('Mongo connecting...');}); + conn.connection.on('connected', ()=>{console.log('Mongo connected!');}); + return conn; +}; + const disconnect = async ()=>{ return await Mongoose.disconnect(); }; const connect = async (config)=>{ return await Mongoose.connect(getMongoDBURL(config), { retryWrites: false }) + .then(addListeners(Mongoose)) .catch((error)=>handleConnectionError(error)); }; @@ -35,3 +44,4 @@ export default { connect, disconnect }; + From 4aadb0b23821989b211e6a3ca157c943f809b499 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Wed, 30 Jul 2025 12:28:06 -0500 Subject: [PATCH 15/95] Keep the cursor in the active view page after a divider width change. Solves #2963 --- client/components/splitPane/splitPane.jsx | 4 ++-- client/homebrew/editor/editor.jsx | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/client/components/splitPane/splitPane.jsx b/client/components/splitPane/splitPane.jsx index 4c77d81a5..4e100638f 100644 --- a/client/components/splitPane/splitPane.jsx +++ b/client/components/splitPane/splitPane.jsx @@ -86,7 +86,7 @@ const SplitPane = (props)=>{ return (
- + {props.children[0]} {renderDivider} @@ -102,7 +102,7 @@ const Pane = ({ width, children, isDragging, moveBrew, moveSource, liveScroll, s return (
- {React.cloneElement(children, { moveBrew, moveSource, liveScroll, setMoveArrows })} + {React.cloneElement(children, { moveBrew, moveSource, liveScroll, isDragging, setMoveArrows })}
); }; diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 8d331e46e..4a7b9be08 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -100,6 +100,16 @@ const Editor = createClass({ if(prevProps.moveSource !== this.props.moveSource) this.sourceJump(); + if((prevProps.isDragging !== this.props.isDragging) && (this.props.isDragging) && (this.lastCursor == undefined)) { + this.lastCursor = this.codeEditor.current.codeMirror.getCursor(); + } + + if((prevProps.isDragging !== this.props.isDragging) && (!this.props.isDragging)) { + this.codeEditor.current.codeMirror.scrollTo(null, this.codeEditor.current.codeMirror.heightAtLine(this.lastCursor.line, 'local', true)) + this.codeEditor.current.setCursorPosition(this.lastCursor.line, this.lastCursor.ch); + this.lastCursor = undefined; + } + if(this.props.liveScroll) { if(prevProps.currentBrewRendererPageNum !== this.props.currentBrewRendererPageNum) { this.sourceJump(this.props.currentBrewRendererPageNum, false); From 785af639c7c3e29787d268e9e3d1064d6d50bffb Mon Sep 17 00:00:00 2001 From: David Bolack Date: Wed, 30 Jul 2025 13:04:16 -0500 Subject: [PATCH 16/95] Keep the cursor as close to the same place on the screen as possible. --- client/homebrew/editor/editor.jsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 4a7b9be08..4894b881d 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -102,10 +102,15 @@ const Editor = createClass({ if((prevProps.isDragging !== this.props.isDragging) && (this.props.isDragging) && (this.lastCursor == undefined)) { this.lastCursor = this.codeEditor.current.codeMirror.getCursor(); + const lastXY = this.codeEditor.current.codeMirror.getScrollInfo(); + const lastRowPos = this.codeEditor.current.codeMirror.heightAtLine(this.lastCursor.line, 'local', true); + this.lastCursor.offset = Math.round(lastRowPos-lastXY.top); } if((prevProps.isDragging !== this.props.isDragging) && (!this.props.isDragging)) { - this.codeEditor.current.codeMirror.scrollTo(null, this.codeEditor.current.codeMirror.heightAtLine(this.lastCursor.line, 'local', true)) + const scroll = this.codeEditor.current.codeMirror.getScrollInfo(); + this.codeEditor.current.codeMirror.scrollTo(null, + this.codeEditor.current.codeMirror.heightAtLine(this.lastCursor.line, 'local', true) - this.lastCursor.offset); this.codeEditor.current.setCursorPosition(this.lastCursor.line, this.lastCursor.ch); this.lastCursor = undefined; } From a1ab27b57ff4c501a0934603336bc8c1778649c2 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Wed, 30 Jul 2025 19:47:59 -0500 Subject: [PATCH 17/95] Applies G-Ambatte's fix --- themes/V3/Blank/style.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/themes/V3/Blank/style.less b/themes/V3/Blank/style.less index 42a392454..dec547854 100644 --- a/themes/V3/Blank/style.less +++ b/themes/V3/Blank/style.less @@ -145,8 +145,8 @@ body { counter-reset : page-numbers 0; } blockquote,table { z-index : 15; -webkit-column-break-inside : avoid; - page-break-inside : avoid; - break-inside : avoid; + page-break-inside : auto; + break-inside : auto; } // Nested lists ul ul,ol ol,ul ol,ol ul { From fdd4b3c1d5bc54fbe7a5ca4830b2fbb0c18b7261 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 30 Aug 2025 18:07:11 -0500 Subject: [PATCH 18/95] Remove braces from consideration --- shared/naturalcrit/markdown.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index c07d879ec..a13ef980a 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -185,7 +185,7 @@ const mustacheSpans = { start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token - const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\=]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; + const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\-\_\+\=]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; const match = completeSpan.exec(src); if(match) { //Find closing delimiter @@ -241,8 +241,8 @@ const mustacheDivs = { level : 'block', start(src) { return src.match(/\n *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const completeBlock = /^ *{{[^\n]* *\n.*\n *}}/s; // Regex for the complete token - const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%. ]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; + const completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token + const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\-\_\+\= ]*"|[\w\-()#%. ]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; const match = completeBlock.exec(src); if(match) { //Find closing delimiter @@ -297,7 +297,7 @@ const mustacheInjectInline = { level : 'inline', start(src) { return src.match(/ *{[^{\n]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\-\_\+\= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1]; From 4fca207e0eae202269a245acd2e3508c7bcf337b Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Tue, 2 Sep 2025 20:58:08 +1200 Subject: [PATCH 19/95] Change error result to use Error Page --- client/homebrew/pages/errorPage/errors/errorIndex.js | 6 ++++++ server/middleware/dbCheck.js | 10 ++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/client/homebrew/pages/errorPage/errors/errorIndex.js b/client/homebrew/pages/errorPage/errors/errorIndex.js index c0220b648..89abd570f 100644 --- a/client/homebrew/pages/errorPage/errors/errorIndex.js +++ b/client/homebrew/pages/errorPage/errors/errorIndex.js @@ -196,6 +196,12 @@ const errorIndex = (props)=>{ **Brew ID:** ${props.brew.brewId}`, + // Database Connection Lost + '13' : dedent` + ## Database connection has been lost. + + The server could not communicate with the database.`, + //account page when account is not defined '50' : dedent` ## You are not signed in diff --git a/server/middleware/dbCheck.js b/server/middleware/dbCheck.js index e90190517..154ab4a9c 100644 --- a/server/middleware/dbCheck.js +++ b/server/middleware/dbCheck.js @@ -6,8 +6,10 @@ export default (req, res, next)=>{ if(config.get('node_env') == 'test') return next(); if(mongoose.connection.readyState == 1) return next(); - return res.status(503).send({ - message : 'Unable to connect to database', - state : mongoose.connection.readyState - }); + throw { + HBErrorCode : 13, + name : 'Database Connection Error', + message : 'Unable to connect to database', + status : mongoose.connection.readyState + }; }; From d6a7d0272af704552aa80f6852e013ba87e05174 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Tue, 2 Sep 2025 21:08:15 +1200 Subject: [PATCH 20/95] Update dbCheck test --- server/middleware/dbCheck.spec.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/server/middleware/dbCheck.spec.js b/server/middleware/dbCheck.spec.js index c4482a54a..dea218918 100644 --- a/server/middleware/dbCheck.spec.js +++ b/server/middleware/dbCheck.spec.js @@ -36,17 +36,9 @@ describe('database check middleware', ()=>{ mongoose.connection.readyState = 99; - dbCheck(request, response); + expect(()=>{dbCheck(request, response);}).toThrow(new Error('Unable to connect to database')); mongoose.connection.readyState = dbState; - - expect(response.status).toHaveBeenLastCalledWith(503); - expect(response.send).toHaveBeenLastCalledWith( - expect.objectContaining({ - message : 'Unable to connect to database', - state : 99 - }) - ); }); it('should call next if readystate == 1', ()=>{ From 1eb5b6d3a4948ecce5eb3b26129df25c872b1d7a Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Tue, 9 Sep 2025 22:04:40 +1200 Subject: [PATCH 21/95] Copy exisitng key data to new keys --- client/homebrew/homebrew.jsx | 4 ++++ .../localStorageKeyMap.json | 19 ++++++++++++++++ .../updateLocalStorageKeys.js | 22 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json create mode 100644 client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index a6b4b9175..1aff5067d 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -4,6 +4,8 @@ import './homebrew.less'; import React from 'react'; import { StaticRouter as Router, Route, Routes, useParams, useSearchParams } from 'react-router'; +import { updateLocalStorage } from './utils/updateLocalStorage/updateLocalStorageKeys.js'; + import HomePage from './pages/homePage/homePage.jsx'; import EditPage from './pages/editPage/editPage.jsx'; import UserPage from './pages/userPage/userPage.jsx'; @@ -48,6 +50,8 @@ const Homebrew = (props)=>{ global.enable_themes = enable_themes; global.config = config; + updateLocalStorage(); + return (
diff --git a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json new file mode 100644 index 000000000..d8b4d1268 --- /dev/null +++ b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json @@ -0,0 +1,19 @@ +{ + "AUTOSAVE_ON" : "HB_editor_autoSaveOn", + "HOMEBREWERY-EDITOR-THEME" : "HB_editor_theme", + "liveScroll" : "HB_editor_liveScroll", + "naturalcrit-pane-split" : "HB_editor_splitWidth", + "HOMEBREWERY-LISTPAGE-SORTDIR" : "HB_listPage_sortDir", + "HOMEBREWERY-LISTPAGE-SORTTYPE" : "HB_listPage_sortType", + "HOMEBREWERY-LISTPAGE-VISIBILITY" : "HB_listPage_visibility_group", + "dismiss_notif_drive" : "HB_dismissNotif_drive", + "dismiss_notif_faq" : "HB_dismissNotif_faq", + "dismiss_notif_update_v3.18" : "HB_dismissNotif_update_v3.18", + "dismiss_v134 update" : "HB_dismissNotif_update_v134", + "hbAdminTab" : "HB_adminPage_currentTab", + "homebrewery-new" : "HB_newPage_content", + "homebrewery-new-meta" : "HB_newPage_metadata", + "homebrewery-new-style" : "HB_newPage_style", + "homebrewery-recently-edited" : "HB_nav_recentlyEdited", + "homebrewery-recently-viewed" : "HB_nav_recentlyViewed" +} \ No newline at end of file diff --git a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js new file mode 100644 index 000000000..02471387d --- /dev/null +++ b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js @@ -0,0 +1,22 @@ +import localStorageKeyMap from './localStorageKeyMap.json' with { type: 'json' }; + +const updateLocalStorage = function(){ + // Return if no window and thus no local storage + if(typeof window === 'undefined') return; + + // Return if the local storage key map has no content + if(Object.keys(localStorageKeyMap).length == 0) return; + + const storage = window.localStorage; + + Object.keys(localStorageKeyMap).forEach((key)=>{ + if(storage[key]){ + const data = storage.getItem(key); + storage.setItem(localStorageKeyMap[key], data); + // storage.removeItem(key); + } + }); + +}; + +export { updateLocalStorage }; \ No newline at end of file From 08d228831d362b579742b0e5f3ade13aad5c3794 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 18:53:23 +1200 Subject: [PATCH 22/95] Add missing keys to JSON, tweak layout --- .../localStorageKeyMap.json | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json index d8b4d1268..b880bfa0c 100644 --- a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json +++ b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json @@ -1,19 +1,28 @@ { - "AUTOSAVE_ON" : "HB_editor_autoSaveOn", - "HOMEBREWERY-EDITOR-THEME" : "HB_editor_theme", - "liveScroll" : "HB_editor_liveScroll", - "naturalcrit-pane-split" : "HB_editor_splitWidth", - "HOMEBREWERY-LISTPAGE-SORTDIR" : "HB_listPage_sortDir", - "HOMEBREWERY-LISTPAGE-SORTTYPE" : "HB_listPage_sortType", - "HOMEBREWERY-LISTPAGE-VISIBILITY" : "HB_listPage_visibility_group", - "dismiss_notif_drive" : "HB_dismissNotif_drive", - "dismiss_notif_faq" : "HB_dismissNotif_faq", - "dismiss_notif_update_v3.18" : "HB_dismissNotif_update_v3.18", - "dismiss_v134 update" : "HB_dismissNotif_update_v134", - "hbAdminTab" : "HB_adminPage_currentTab", - "homebrewery-new" : "HB_newPage_content", - "homebrewery-new-meta" : "HB_newPage_metadata", - "homebrewery-new-style" : "HB_newPage_style", - "homebrewery-recently-edited" : "HB_nav_recentlyEdited", - "homebrewery-recently-viewed" : "HB_nav_recentlyViewed" + "AUTOSAVE_ON" : "HB_editor_autoSaveOn", + "HOMEBREWERY-EDITOR-THEME" : "HB_editor_theme", + "liveScroll" : "HB_editor_liveScroll", + "naturalcrit-pane-split" : "HB_editor_splitWidth", + + "HOMEBREWERY-LISTPAGE-SORTDIR" : "HB_listPage_sortDir", + "HOMEBREWERY-LISTPAGE-SORTTYPE" : "HB_listPage_sortType", + "HOMEBREWERY-LISTPAGE-VISIBILITY-published" : "HB_listPage_visibility_group_published", + "HOMEBREWERY-LISTPAGE-VISIBILITY-unpublished" : "HB_listPage_visibility_group_unpublished", + + "dismiss_notif_drive" : "HB_dismissNotif_drive", + "dismiss_notif_faq" : "HB_dismissNotif_faq", + "dismiss_notif_update_v3.18" : "HB_dismissNotif_update_v3.18", + "dismiss_v134 update" : "HB_dismissNotif_update_v134", + + "hbAdminTab" : "HB_adminPage_currentTab", + + "homebrewery-new" : "HB_newPage_content", + "homebrewery-new-meta" : "HB_newPage_metadata", + "homebrewery-new-style" : "HB_newPage_style", + + "homebrewery-recently-edited" : "HB_nav_recentlyEdited", + "homebrewery-recently-viewed" : "HB_nav_recentlyViewed", + + "hb_toolbarState" : "HB_renderer_toolbarState", + "hb_toolbarVisibility" : "HB_renderer_toolbarVisibility" } \ No newline at end of file From 7163b1a2873bab9e1ef7d1ed40890315d1333410 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 18:53:53 +1200 Subject: [PATCH 23/95] Add function to add dynamic keys to local storage map --- .../updateLocalStorage/updateLocalStorageKeys.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js index 02471387d..dae2580f4 100644 --- a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js +++ b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js @@ -1,5 +1,15 @@ import localStorageKeyMap from './localStorageKeyMap.json' with { type: 'json' }; +const addDynamicKeys = function(keyObject){ + + if(global?.account?.username){ + const username = global.account.username; + keyObject[`HOMEBREWERY-DEFAULT-SAVE-LOCATION-${username}`] = `HB_editor_defaultSave_${username}`; + } + + return keyObject; +}; + const updateLocalStorage = function(){ // Return if no window and thus no local storage if(typeof window === 'undefined') return; @@ -8,11 +18,12 @@ const updateLocalStorage = function(){ if(Object.keys(localStorageKeyMap).length == 0) return; const storage = window.localStorage; + const storageKeyMap = addDynamicKeys(localStorageKeyMap); - Object.keys(localStorageKeyMap).forEach((key)=>{ + Object.keys(storageKeyMap).forEach((key)=>{ if(storage[key]){ const data = storage.getItem(key); - storage.setItem(localStorageKeyMap[key], data); + storage.setItem(storageKeyMap[key], data); // storage.removeItem(key); } }); From c99f59d42b1e8c7ae6e02e99b206bc02bcd76837 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 19:08:47 +1200 Subject: [PATCH 24/95] Update newPage.jsx keys --- client/homebrew/pages/newPage/newPage.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index bb21441cf..67ff227ae 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -20,10 +20,10 @@ import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; -const BREWKEY = 'homebrewery-new'; -const STYLEKEY = 'homebrewery-new-style'; -const METAKEY = 'homebrewery-new-meta'; -const SAVEKEY = `HOMEBREWERY-DEFAULT-SAVE-LOCATION-${global.account?.username || ''}`; +const BREWKEY = 'HB_newPage_content'; +const STYLEKEY = 'HB_newPage_style'; +const METAKEY = 'HB_newPage_metadata'; +const SAVEKEY = `HB_editor_defaultSave_${global.account?.username || ''}`; const NewPage = (props) => { props = { From 088ca9971cd42bf34d49297da29b6ac4cf58800a Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 19:16:29 +1200 Subject: [PATCH 25/95] Update accountPage keys --- client/homebrew/pages/accountPage/accountPage.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/pages/accountPage/accountPage.jsx b/client/homebrew/pages/accountPage/accountPage.jsx index 598683504..b69eb6e3e 100644 --- a/client/homebrew/pages/accountPage/accountPage.jsx +++ b/client/homebrew/pages/accountPage/accountPage.jsx @@ -13,7 +13,7 @@ const AccountPage = (props)=>{ // initialize save location from local storage based on user id React.useEffect(()=>{ if(!saveLocation && accountDetails.username) { - SAVEKEY = `HOMEBREWERY-DEFAULT-SAVE-LOCATION-${accountDetails.username}`; + SAVEKEY = `HB_editor_defaultSave_${accountDetails.username}`; // if no SAVEKEY in local storage, default save location to Google Drive if user has Google account. let saveLocation = window.localStorage.getItem(SAVEKEY); saveLocation = saveLocation ?? (accountDetails.googleId ? 'GOOGLE-DRIVE' : 'HOMEBREWERY'); From 328e071268cb0e893a82fb85080a2d8124622cf1 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 19:22:54 +1200 Subject: [PATCH 26/95] Update BrewRenderer toolbar keys --- client/homebrew/brewRenderer/brewRenderer.jsx | 6 ++++-- client/homebrew/brewRenderer/toolBar/toolBar.jsx | 8 +++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/client/homebrew/brewRenderer/brewRenderer.jsx b/client/homebrew/brewRenderer/brewRenderer.jsx index 7a101e9f9..bda7143fc 100644 --- a/client/homebrew/brewRenderer/brewRenderer.jsx +++ b/client/homebrew/brewRenderer/brewRenderer.jsx @@ -24,6 +24,8 @@ const PAGEBREAK_REGEX_LEGACY = /\\page(?:break)?/m; const COLUMNBREAK_REGEX_LEGACY = /\\column(:?break)?/m; const PAGE_HEIGHT = 1056; +const TOOLBAR_STATE_KEY = 'HB_renderer_toolbarState'; + const INITIAL_CONTENT = dedent` @@ -122,7 +124,7 @@ const BrewRenderer = (props)=>{ //useEffect to store or gather toolbar state from storage useEffect(()=>{ - const toolbarState = JSON.parse(window.localStorage.getItem('hb_toolbarState')); + const toolbarState = JSON.parse(window.localStorage.getItem(TOOLBAR_STATE_KEY)); toolbarState && setDisplayOptions(toolbarState); }, []); @@ -284,7 +286,7 @@ const BrewRenderer = (props)=>{ const handleDisplayOptionsChange = (newDisplayOptions)=>{ setDisplayOptions(newDisplayOptions); - localStorage.setItem('hb_toolbarState', JSON.stringify(newDisplayOptions)); + localStorage.setItem(TOOLBAR_STATE_KEY, JSON.stringify(newDisplayOptions)); }; const pagesStyle = { diff --git a/client/homebrew/brewRenderer/toolBar/toolBar.jsx b/client/homebrew/brewRenderer/toolBar/toolBar.jsx index 6938eacb7..4aee3b6bd 100644 --- a/client/homebrew/brewRenderer/toolBar/toolBar.jsx +++ b/client/homebrew/brewRenderer/toolBar/toolBar.jsx @@ -9,6 +9,8 @@ import { Anchored, AnchoredBox, AnchoredTrigger } from '../../../components/Anch const MAX_ZOOM = 300; const MIN_ZOOM = 10; +const TOOLBAR_VISIBILITY = 'HB_renderer_toolbarVisibility'; + const ToolBar = ({ displayOptions, onDisplayOptionsChange, visiblePages, totalPages, headerState, setHeaderState })=>{ const [pageNum, setPageNum] = useState(1); @@ -21,8 +23,8 @@ const ToolBar = ({ displayOptions, onDisplayOptionsChange, visiblePages, totalPa }, [visiblePages]); useEffect(()=>{ - const Visibility = localStorage.getItem('hb_toolbarVisibility'); - if (Visibility) setToolsVisible(Visibility === 'true'); + const Visibility = localStorage.getItem(TOOLBAR_VISIBILITY); + if(Visibility) setToolsVisible(Visibility === 'true'); }, []); @@ -100,7 +102,7 @@ const ToolBar = ({ displayOptions, onDisplayOptionsChange, visiblePages, totalPa
From 52486495c82cf9d8cafe2df08655ec390360f7d8 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 19:35:14 +1200 Subject: [PATCH 27/95] Update adminPage storage keys --- client/admin/admin.jsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index 29973d221..15ca430e0 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -7,15 +7,17 @@ import LockTools from './lockTools/lockTools.jsx'; const tabGroups = ['brew', 'notifications', 'authors', 'locks']; +const ADMIN_TAB = 'hbAdminTab'; + const Admin = ()=>{ const [currentTab, setCurrentTab] = useState(''); useEffect(()=>{ - setCurrentTab(localStorage.getItem('hbAdminTab') || 'brew'); + setCurrentTab(localStorage.getItem(ADMIN_TAB) || 'brew'); }, []); useEffect(()=>{ - localStorage.setItem('hbAdminTab', currentTab); + localStorage.setItem(ADMIN_TAB, currentTab); }, [currentTab]); return ( From 885c0105f32988cf6af70ea5df2cae2164620ae6 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 19:36:39 +1200 Subject: [PATCH 28/95] Update adminPage key --- client/admin/admin.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/admin/admin.jsx b/client/admin/admin.jsx index 15ca430e0..787c2a3eb 100644 --- a/client/admin/admin.jsx +++ b/client/admin/admin.jsx @@ -7,7 +7,7 @@ import LockTools from './lockTools/lockTools.jsx'; const tabGroups = ['brew', 'notifications', 'authors', 'locks']; -const ADMIN_TAB = 'hbAdminTab'; +const ADMIN_TAB = 'HB_adminPage_currentTab'; const Admin = ()=>{ const [currentTab, setCurrentTab] = useState(''); From 58277585e1d770724585e662110c52720888d9b5 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 19:55:42 +1200 Subject: [PATCH 29/95] Update Recent Items keys --- client/homebrew/navbar/recent.navitem.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/navbar/recent.navitem.jsx b/client/homebrew/navbar/recent.navitem.jsx index a6cbbf406..4c4722515 100644 --- a/client/homebrew/navbar/recent.navitem.jsx +++ b/client/homebrew/navbar/recent.navitem.jsx @@ -5,8 +5,8 @@ const Moment = require('moment'); const Nav = require('naturalcrit/nav/nav.jsx'); -const EDIT_KEY = 'homebrewery-recently-edited'; -const VIEW_KEY = 'homebrewery-recently-viewed'; +const EDIT_KEY = 'HB_nav_recentlyEdited'; +const VIEW_KEY = 'HB_nav_recentlyViewed'; const RecentItems = createClass({ From fd370c777dc465d99c9281ec6f4d792ce2acc489 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 19:57:16 +1200 Subject: [PATCH 30/95] Update Editor theme key --- client/homebrew/editor/editor.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 8d331e46e..8c53cb333 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -10,7 +10,7 @@ const CodeEditor = require('naturalcrit/codeEditor/codeEditor.jsx'); const SnippetBar = require('./snippetbar/snippetbar.jsx'); const MetadataEditor = require('./metadataEditor/metadataEditor.jsx'); -const EDITOR_THEME_KEY = 'HOMEBREWERY-EDITOR-THEME'; +const EDITOR_THEME_KEY = 'HB_editor_theme'; const PAGEBREAK_REGEX_V3 = /^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/m; const SNIPPETBREAK_REGEX_V3 = /^\\snippet\ .*$/; @@ -143,7 +143,7 @@ const Editor = createClass({ handleViewChange : function(newView){ this.props.setMoveArrows(newView === 'text'); - + this.setState({ view : newView }, ()=>{ From 5504c1b96b74e465f14941f31451cfc3c7132224 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 20:00:53 +1200 Subject: [PATCH 31/95] Update Autosave key --- client/homebrew/pages/editPage/editPage.jsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 49512d66c..b4eca7e2d 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -38,6 +38,8 @@ const SAVE_TIMEOUT = 10000; const UNSAVED_WARNING_TIMEOUT = 900000; //Warn user afer 15 minutes of unsaved changes const UNSAVED_WARNING_POPUP_TIMEOUT = 4000; //Show the warning for 4 seconds +const AUTOSAVE_KEY = 'HB_editor_autoSaveOn'; + const EditPage = (props)=>{ props = { brew : DEFAULT_BREW_LOAD, @@ -70,7 +72,7 @@ const EditPage = (props)=>{ useEffect(()=>{ setUrl(window.location.href); - const autoSavePref = JSON.parse(localStorage.getItem('AUTOSAVE_ON') ?? true); + const autoSavePref = JSON.parse(localStorage.getItem(AUTOSAVE_KEY) ?? true); setAutoSaveEnabled(autoSavePref); setAutoSaveWarning(!autoSavePref); setHTMLErrors(Markdown.validate(currentBrew.text)); @@ -317,7 +319,7 @@ const EditPage = (props)=>{ const toggleAutoSave = ()=>{ if(warningTimer.current) clearTimeout(warningTimer.current); - localStorage.setItem('AUTOSAVE_ON', JSON.stringify(!autoSaveEnabled)); + localStorage.setItem(AUTOSAVE_KEY, JSON.stringify(!autoSaveEnabled)); setAutoSaveWarning(autoSaveWarning); setAutoSaveEnabled(!autoSaveEnabled); }; From dc1bc471aad9f63a34a5ea11fd262b60cc4f98e9 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 20:10:18 +1200 Subject: [PATCH 32/95] Update SplitPane keys --- client/components/splitPane/splitPane.jsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/client/components/splitPane/splitPane.jsx b/client/components/splitPane/splitPane.jsx index 4c77d81a5..78ba59ed3 100644 --- a/client/components/splitPane/splitPane.jsx +++ b/client/components/splitPane/splitPane.jsx @@ -2,7 +2,8 @@ require('./splitPane.less'); const React = require('react'); const { useState, useEffect } = React; -const storageKey = 'naturalcrit-pane-split'; +const PANE_WIDTH_KEY = 'HB_editor_splitWidth'; +const LIVE_SCROLL_KEY = 'HB_editor_liveScroll'; const SplitPane = (props)=>{ const { @@ -18,9 +19,9 @@ const SplitPane = (props)=>{ const [liveScroll, setLiveScroll] = useState(false); useEffect(()=>{ - const savedPos = window.localStorage.getItem(storageKey); + const savedPos = window.localStorage.getItem(PANE_WIDTH_KEY); setDividerPos(savedPos ? limitPosition(savedPos, 0.1 * (window.innerWidth - 13), 0.9 * (window.innerWidth - 13)) : window.innerWidth / 2); - setLiveScroll(window.localStorage.getItem('liveScroll') === 'true'); + setLiveScroll(window.localStorage.getItem(LIVE_SCROLL_KEY) === 'true'); window.addEventListener('resize', handleResize); return ()=>window.removeEventListener('resize', handleResize); @@ -29,13 +30,13 @@ const SplitPane = (props)=>{ const limitPosition = (x, min = 1, max = window.innerWidth - 13)=>Math.round(Math.min(max, Math.max(min, x))); //when resizing, the divider should grow smaller if less space is given, then grow back if the space is restored, to the original position - const handleResize = ()=>setDividerPos(limitPosition(window.localStorage.getItem(storageKey), 0.1 * (window.innerWidth - 13), 0.9 * (window.innerWidth - 13))); + const handleResize = ()=>setDividerPos(limitPosition(window.localStorage.getItem(PANE_WIDTH_KEY), 0.1 * (window.innerWidth - 13), 0.9 * (window.innerWidth - 13))); const handleUp =(e)=>{ e.preventDefault(); if(isDragging) { onDragFinish(dividerPos); - window.localStorage.setItem(storageKey, dividerPos); + window.localStorage.setItem(PANE_WIDTH_KEY, dividerPos); } setIsDragging(false); }; @@ -52,7 +53,7 @@ const SplitPane = (props)=>{ }; const liveScrollToggle = ()=>{ - window.localStorage.setItem('liveScroll', String(!liveScroll)); + window.localStorage.setItem(LIVE_SCROLL_KEY, String(!liveScroll)); setLiveScroll(!liveScroll); }; From b6818e963b7373e3af57c238f3fae08109f10a24 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 20:12:50 +1200 Subject: [PATCH 33/95] Remove unused dismiss keys --- .../utils/updateLocalStorage/localStorageKeyMap.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json index b880bfa0c..984ccba7e 100644 --- a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json +++ b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json @@ -9,11 +9,6 @@ "HOMEBREWERY-LISTPAGE-VISIBILITY-published" : "HB_listPage_visibility_group_published", "HOMEBREWERY-LISTPAGE-VISIBILITY-unpublished" : "HB_listPage_visibility_group_unpublished", - "dismiss_notif_drive" : "HB_dismissNotif_drive", - "dismiss_notif_faq" : "HB_dismissNotif_faq", - "dismiss_notif_update_v3.18" : "HB_dismissNotif_update_v3.18", - "dismiss_v134 update" : "HB_dismissNotif_update_v134", - "hbAdminTab" : "HB_adminPage_currentTab", "homebrewery-new" : "HB_newPage_content", From 8d4ea7cfd84a07fe3f3d9aa138f2c4b8d408c98d Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 20:20:42 +1200 Subject: [PATCH 34/95] Update listPage storage keys --- .../pages/basePages/listPage/listPage.jsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/client/homebrew/pages/basePages/listPage/listPage.jsx b/client/homebrew/pages/basePages/listPage/listPage.jsx index ec557ffb1..4afc14364 100644 --- a/client/homebrew/pages/basePages/listPage/listPage.jsx +++ b/client/homebrew/pages/basePages/listPage/listPage.jsx @@ -7,7 +7,9 @@ const moment = require('moment'); const BrewItem = require('./brewItem/brewItem.jsx'); -const USERPAGE_KEY_PREFIX = 'HOMEBREWERY-LISTPAGE'; +const USERPAGE_SORT_DIR = 'HB_listPage_sortDir'; +const USERPAGE_SORT_TYPE = 'HB_listPage_sortType'; +const USERPAGE_GROUP_VISIBILITY_PREFIX = 'HB_listPage_visibility_group'; const DEFAULT_SORT_TYPE = 'alpha'; const DEFAULT_SORT_DIR = 'asc'; @@ -50,12 +52,12 @@ const ListPage = createClass({ // LOAD FROM LOCAL STORAGE if(typeof window !== 'undefined') { - const newSortType = (this.state.sortType ?? (localStorage.getItem(`${USERPAGE_KEY_PREFIX}-SORTTYPE`) || DEFAULT_SORT_TYPE)); - const newSortDir = (this.state.sortDir ?? (localStorage.getItem(`${USERPAGE_KEY_PREFIX}-SORTDIR`) || DEFAULT_SORT_DIR)); + const newSortType = (this.state.sortType ?? (localStorage.getItem(USERPAGE_SORT_TYPE) || DEFAULT_SORT_TYPE)); + const newSortDir = (this.state.sortDir ?? (localStorage.getItem(USERPAGE_SORT_DIR) || DEFAULT_SORT_DIR)); this.updateUrl(this.state.filterString, newSortType, newSortDir); const brewCollection = this.props.brewCollection.map((brewGroup)=>{ - brewGroup.visible = (localStorage.getItem(`${USERPAGE_KEY_PREFIX}-VISIBILITY-${brewGroup.class}`) ?? 'true')=='true'; + brewGroup.visible = (localStorage.getItem(`${USERPAGE_GROUP_VISIBILITY_PREFIX}_${brewGroup.class}`) ?? 'true')=='true'; return brewGroup; }); @@ -73,10 +75,10 @@ const ListPage = createClass({ saveToLocalStorage : function() { this.state.brewCollection.map((brewGroup)=>{ - localStorage.setItem(`${USERPAGE_KEY_PREFIX}-VISIBILITY-${brewGroup.class}`, `${brewGroup.visible}`); + localStorage.setItem(`${USERPAGE_GROUP_VISIBILITY_PREFIX}_${brewGroup.class}`, `${brewGroup.visible}`); }); - localStorage.setItem(`${USERPAGE_KEY_PREFIX}-SORTTYPE`, this.state.sortType); - localStorage.setItem(`${USERPAGE_KEY_PREFIX}-SORTDIR`, this.state.sortDir); + localStorage.setItem(USERPAGE_SORT_TYPE, this.state.sortType); + localStorage.setItem(USERPAGE_SORT_DIR, this.state.sortDir); }, renderBrews : function(brews){ From 2663d86627bdee7b7bc52871be69c846efcbbde7 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Wed, 10 Sep 2025 20:31:50 +1200 Subject: [PATCH 35/95] Don't update storage values if key already exists --- .../homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js index dae2580f4..9f32a840b 100644 --- a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js +++ b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js @@ -23,7 +23,7 @@ const updateLocalStorage = function(){ Object.keys(storageKeyMap).forEach((key)=>{ if(storage[key]){ const data = storage.getItem(key); - storage.setItem(storageKeyMap[key], data); + if(!storage[storageKeyMap[key]]) storage.setItem(storageKeyMap[key], data); // storage.removeItem(key); } }); From a11fa72261a98e46a618934e2b3701d4a66666a4 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 11 Sep 2025 21:02:56 +1200 Subject: [PATCH 36/95] Change JSON file to JS getter function --- .../updateLocalStorage/localStorageKeyMap.js | 35 +++++++++++++++++++ .../localStorageKeyMap.json | 23 ------------ .../updateLocalStorageKeys.js | 18 +++------- 3 files changed, 39 insertions(+), 37 deletions(-) create mode 100644 client/homebrew/utils/updateLocalStorage/localStorageKeyMap.js delete mode 100644 client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json diff --git a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.js b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.js new file mode 100644 index 000000000..b4a05974f --- /dev/null +++ b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.js @@ -0,0 +1,35 @@ + +const getLocalStorageMap = function(){ + const localStorageMap = { + 'AUTOSAVE_ON' : 'HB_editor_autoSaveOn', + 'HOMEBREWERY-EDITOR-THEME' : 'HB_editor_theme', + 'liveScroll' : 'HB_editor_liveScroll', + 'naturalcrit-pane-split' : 'HB_editor_splitWidth', + + 'HOMEBREWERY-LISTPAGE-SORTDIR' : 'HB_listPage_sortDir', + 'HOMEBREWERY-LISTPAGE-SORTTYPE' : 'HB_listPage_sortType', + 'HOMEBREWERY-LISTPAGE-VISIBILITY-published' : 'HB_listPage_visibility_group_published', + 'HOMEBREWERY-LISTPAGE-VISIBILITY-unpublished' : 'HB_listPage_visibility_group_unpublished', + + 'hbAdminTab' : 'HB_adminPage_currentTab', + + 'homebrewery-new' : 'HB_newPage_content', + 'homebrewery-new-meta' : 'HB_newPage_metadata', + 'homebrewery-new-style' : 'HB_newPage_style', + + 'homebrewery-recently-edited' : 'HB_nav_recentlyEdited', + 'homebrewery-recently-viewed' : 'HB_nav_recentlyViewed', + + 'hb_toolbarState' : 'HB_renderer_toolbarState', + 'hb_toolbarVisibility' : 'HB_renderer_toolbarVisibility' + }; + + if(global?.account?.username){ + const username = global.account.username; + localStorageMap[`HOMEBREWERY-DEFAULT-SAVE-LOCATION-${username}`] = `HB_editor_defaultSave_${username}`; + } + + return localStorageMap; +}; + +export default getLocalStorageMap; \ No newline at end of file diff --git a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json deleted file mode 100644 index 984ccba7e..000000000 --- a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "AUTOSAVE_ON" : "HB_editor_autoSaveOn", - "HOMEBREWERY-EDITOR-THEME" : "HB_editor_theme", - "liveScroll" : "HB_editor_liveScroll", - "naturalcrit-pane-split" : "HB_editor_splitWidth", - - "HOMEBREWERY-LISTPAGE-SORTDIR" : "HB_listPage_sortDir", - "HOMEBREWERY-LISTPAGE-SORTTYPE" : "HB_listPage_sortType", - "HOMEBREWERY-LISTPAGE-VISIBILITY-published" : "HB_listPage_visibility_group_published", - "HOMEBREWERY-LISTPAGE-VISIBILITY-unpublished" : "HB_listPage_visibility_group_unpublished", - - "hbAdminTab" : "HB_adminPage_currentTab", - - "homebrewery-new" : "HB_newPage_content", - "homebrewery-new-meta" : "HB_newPage_metadata", - "homebrewery-new-style" : "HB_newPage_style", - - "homebrewery-recently-edited" : "HB_nav_recentlyEdited", - "homebrewery-recently-viewed" : "HB_nav_recentlyViewed", - - "hb_toolbarState" : "HB_renderer_toolbarState", - "hb_toolbarVisibility" : "HB_renderer_toolbarVisibility" -} \ No newline at end of file diff --git a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js index 9f32a840b..4fd7262a3 100644 --- a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js +++ b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js @@ -1,29 +1,19 @@ -import localStorageKeyMap from './localStorageKeyMap.json' with { type: 'json' }; - -const addDynamicKeys = function(keyObject){ - - if(global?.account?.username){ - const username = global.account.username; - keyObject[`HOMEBREWERY-DEFAULT-SAVE-LOCATION-${username}`] = `HB_editor_defaultSave_${username}`; - } - - return keyObject; -}; +import getLocalStorageMap from './localStorageKeyMap.js'; const updateLocalStorage = function(){ // Return if no window and thus no local storage if(typeof window === 'undefined') return; // Return if the local storage key map has no content + const localStorageKeyMap = getLocalStorageMap(); if(Object.keys(localStorageKeyMap).length == 0) return; const storage = window.localStorage; - const storageKeyMap = addDynamicKeys(localStorageKeyMap); - Object.keys(storageKeyMap).forEach((key)=>{ + Object.keys(localStorageKeyMap).forEach((key)=>{ if(storage[key]){ const data = storage.getItem(key); - if(!storage[storageKeyMap[key]]) storage.setItem(storageKeyMap[key], data); + if(!storage[localStorageKeyMap[key]]) storage.setItem(localStorageKeyMap[key], data); // storage.removeItem(key); } }); From 1459f6a32077e7778327a687bce912c343887708 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 11 Sep 2025 21:25:13 +1200 Subject: [PATCH 37/95] Tweak local storage update logic --- .../utils/updateLocalStorage/updateLocalStorageKeys.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js index 4fd7262a3..6ab4fbcd1 100644 --- a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js +++ b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js @@ -11,9 +11,9 @@ const updateLocalStorage = function(){ const storage = window.localStorage; Object.keys(localStorageKeyMap).forEach((key)=>{ - if(storage[key]){ + if(storage[key] && !storage[localStorageKeyMap[key]]){ const data = storage.getItem(key); - if(!storage[localStorageKeyMap[key]]) storage.setItem(localStorageKeyMap[key], data); + storage.setItem(localStorageKeyMap[key], data); // storage.removeItem(key); } }); From 87a36bb02df1cd1d38945193a6fd3e286301c2e8 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 11 Sep 2025 21:57:00 +1200 Subject: [PATCH 38/95] Add tests for localStorageKeyMap.js --- .../localStorageKeyMap.spec.js | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 client/homebrew/utils/updateLocalStorage/localStorageKeyMap.spec.js diff --git a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.spec.js b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.spec.js new file mode 100644 index 000000000..ac61d4add --- /dev/null +++ b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.spec.js @@ -0,0 +1,30 @@ +import getLocalStorageMap from './localStorageKeyMap.js'; + +describe('getLocalStorageMap', ()=>{ + it('no username', ()=>{ + const account = global.account; + + delete global.account; + + const map = getLocalStorageMap(); + + global.account = account; + + expect(map).toBeInstanceOf(Object); + expect(Object.entries(map)).toHaveLength(16); + }); + + it('no username', ()=>{ + const account = global.account; + + global.account = { username: 'test' }; + + const map = getLocalStorageMap(); + + global.account = account; + + expect(map).toBeInstanceOf(Object); + expect(Object.entries(map)).toHaveLength(17); + expect(map).toHaveProperty('HOMEBREWERY-DEFAULT-SAVE-LOCATION-test', 'HB_editor_defaultSave_test'); + }); +}); \ No newline at end of file From da8772daa7e3f417bb0dc4b8a4a673ccc3973e79 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Thu, 11 Sep 2025 16:14:45 -0400 Subject: [PATCH 39/95] Use setXXXPageNum instead of handleXXXPageNum No need for separate wrapper functions when we can just pass the setState functions directly. --- client/homebrew/pages/editPage/editPage.jsx | 18 +++--------------- client/homebrew/pages/homePage/homePage.jsx | 18 +++--------------- client/homebrew/pages/newPage/newPage.jsx | 17 +++-------------- 3 files changed, 9 insertions(+), 44 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 49512d66c..1467a2a89 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -111,18 +111,6 @@ const EditPage = (props)=>{ editorRef.current?.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; - const handleTextChange = (text)=>{ //If there are HTML errors, run the validator on every change to give quick feedback if(HTMLErrors.length) @@ -417,8 +405,8 @@ const EditPage = (props)=>{ userThemes={props.userThemes} themeBundle={themeBundle} updateBrew={updateBrew} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -431,7 +419,7 @@ const EditPage = (props)=>{ themeBundle={themeBundle} errors={HTMLErrors} lang={currentBrew.lang} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 84967b1ff..f9713e13a 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -60,18 +60,6 @@ const HomePage =(props)=>{ editorRef.current.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; - const handleTextChange = (text)=>{ setBrew((prevBrew) => ({ ...prevBrew, text })); }; @@ -110,8 +98,8 @@ const HomePage =(props)=>{ renderer={brew.renderer} showEditButtons={false} themeBundle={themeBundle} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -120,7 +108,7 @@ const HomePage =(props)=>{ text={brew.text} style={brew.style} renderer={brew.renderer} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index bb21441cf..5c8853ec7 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -96,17 +96,6 @@ const NewPage = (props) => { editorRef.current.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; const handleTextChange = (text)=>{ //If there are HTML errors, run the validator on every change to give quick feedback @@ -222,8 +211,8 @@ const NewPage = (props) => { renderer={currentBrew.renderer} userThemes={props.userThemes} themeBundle={themeBundle} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -236,7 +225,7 @@ const NewPage = (props) => { themeBundle={themeBundle} errors={HTMLErrors} lang={currentBrew.lang} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} From 788324fe31b9cc4cc61155e9cad10bc6fef5d69d Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Thu, 11 Sep 2025 22:03:25 -0400 Subject: [PATCH 40/95] Merge handText/Style/Snip/MetaChange into handleBrewChange --- client/homebrew/editor/editor.jsx | 13 ++--- client/homebrew/pages/editPage/editPage.jsx | 47 ++++++++--------- client/homebrew/pages/homePage/homePage.jsx | 47 ++++++++++++----- client/homebrew/pages/newPage/newPage.jsx | 56 ++++++++------------- 4 files changed, 83 insertions(+), 80 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 8d331e46e..6558bd330 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -40,10 +40,7 @@ const Editor = createClass({ style : '' }, - onTextChange : ()=>{}, - onStyleChange : ()=>{}, - onMetaChange : ()=>{}, - onSnipChange : ()=>{}, + onBrewChange : ()=>{}, reportError : ()=>{}, onCursorPageChange : ()=>{}, @@ -438,7 +435,7 @@ const Editor = createClass({ language='gfm' view={this.state.view} value={this.props.brew.text} - onChange={this.props.onTextChange} + onChange={this.props.onBrewChange('text')} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} /> @@ -451,7 +448,7 @@ const Editor = createClass({ language='css' view={this.state.view} value={this.props.brew.style ?? DEFAULT_STYLE_TEXT} - onChange={this.props.onStyleChange} + onChange={this.props.onBrewChange('style')} enableFolding={true} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} @@ -467,7 +464,7 @@ const Editor = createClass({ ; @@ -481,7 +478,7 @@ const Editor = createClass({ language='gfm' view={this.state.view} value={this.props.brew.snippets} - onChange={this.props.onSnipChange} + onChange={this.props.onBrewChange('snippets')} enableFolding={true} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 1467a2a89..715ae72f9 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -1,7 +1,7 @@ /* eslint-disable max-lines */ import './editPage.less'; -import React, { useState, useEffect, useRef, useCallback } from 'react'; +import React, { useState, useEffect, useRef, useCallback, use } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; @@ -38,6 +38,8 @@ const SAVE_TIMEOUT = 10000; const UNSAVED_WARNING_TIMEOUT = 900000; //Warn user afer 15 minutes of unsaved changes const UNSAVED_WARNING_POPUP_TIMEOUT = 4000; //Show the warning for 4 seconds +const useLocalStorage = false; + const EditPage = (props)=>{ props = { brew : DEFAULT_BREW_LOAD, @@ -111,29 +113,27 @@ const EditPage = (props)=>{ editorRef.current?.update(); }; - const handleTextChange = (text)=>{ + const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' + if (subfield == 'renderer' || subfield == 'theme') + fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); + //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - setHTMLErrors(Markdown.validate(text)); - setCurrentBrew((prevBrew)=>({ ...prevBrew, text })); - }; + if(HTMLErrors.length && (field == 'text' || field == 'snippets')) + setHTMLErrors(Markdown.validate(value)); - const handleStyleChange = (style)=>{ - setCurrentBrew((prevBrew)=>({ ...prevBrew, style })); - }; + if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); + else setCurrentBrew(prev => ({ ...prev, [field]: value })); - const handleSnipChange = (snippet)=>{ - //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - setHTMLErrors(Markdown.validate(snippet)); - setCurrentBrew((prevBrew)=>({ ...prevBrew, snippets: snippet })); - }; - - const handleMetaChange = (metadata, field = undefined)=>{ - if(field === 'theme' || field === 'renderer') - fetchThemeBundle(setError, setThemeBundle, metadata.renderer, metadata.theme); - - setCurrentBrew((prev)=>({ ...prev, ...metadata })); + if(useLocalStorage) { + if(field == 'text') localStorage.setItem(BREWKEY, value); + if(field == 'style') localStorage.setItem(STYLEKEY, value); + if(field == 'snippets') localStorage.setItem(SNIPKEY, value); + if(field == 'metadata') localStorage.setItem(METAKEY, JSON.stringify({ + renderer : value.renderer, + theme : value.theme, + lang : value.lang + })); + } }; const updateBrew = (newData)=>setCurrentBrew((prevBrew)=>({ @@ -396,10 +396,7 @@ const EditPage = (props)=>{ { props = { brew : DEFAULT_BREW, @@ -28,9 +31,10 @@ const HomePage =(props)=>{ ...props }; - const [brew , setBrew] = useState(props.brew); + const [currentBrew , setCurrentBrew] = useState(props.brew); const [welcomeText , setWelcomeText] = useState(props.brew.text); const [error , setError] = useState(undefined); + const [HTMLErrors , setHTMLErrors] = useState(Markdown.validate(props.brew.text)); const [currentEditorViewPageNum , setCurrentEditorViewPageNum] = useState(1); const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); @@ -40,12 +44,12 @@ const HomePage =(props)=>{ const editorRef = useRef(null); useEffect(()=>{ - fetchThemeBundle(setError, setThemeBundle, brew.renderer, brew.theme); + fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); }, []); const save = ()=>{ request.post('/api') - .send(brew) + .send(currentBrew) .end((err, res)=>{ if(err) { setError(err); @@ -60,8 +64,27 @@ const HomePage =(props)=>{ editorRef.current.update(); }; - const handleTextChange = (text)=>{ - setBrew((prevBrew) => ({ ...prevBrew, text })); + const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' + if (subfield == 'renderer' || subfield == 'theme') + fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); + + //If there are HTML errors, run the validator on every change to give quick feedback + if(HTMLErrors.length && (field == 'text' || field == 'snippets')) + setHTMLErrors(Markdown.validate(value)); + + if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); + else setCurrentBrew(prev => ({ ...prev, [field]: value })); + + if(useLocalStorage) { + if(field == 'text') localStorage.setItem(BREWKEY, value); + if(field == 'style') localStorage.setItem(STYLEKEY, value); + if(field == 'snippets') localStorage.setItem(SNIPKEY, value); + if(field == 'metadata') localStorage.setItem(METAKEY, JSON.stringify({ + renderer : value.renderer, + theme : value.theme, + lang : value.lang + })); + } }; const clearError = ()=>{ @@ -93,9 +116,9 @@ const HomePage =(props)=>{ { currentBrewRendererPageNum={currentBrewRendererPageNum} /> { />
-
+
Save current
diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 5c8853ec7..60b8b17f0 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -22,9 +22,12 @@ import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '. const BREWKEY = 'homebrewery-new'; const STYLEKEY = 'homebrewery-new-style'; +const SNIPKEY = 'homebrewery-new-snippets'; const METAKEY = 'homebrewery-new-meta'; const SAVEKEY = `HOMEBREWERY-DEFAULT-SAVE-LOCATION-${global.account?.username || ''}`; +const useLocalStorage = true; + const NewPage = (props) => { props = { brew: DEFAULT_BREW, @@ -96,41 +99,27 @@ const NewPage = (props) => { editorRef.current.update(); }; + const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' + if (subfield == 'renderer' || subfield == 'theme') + fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); - const handleTextChange = (text)=>{ //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - HTMLErrors = Markdown.validate(text); + if(HTMLErrors.length && (field == 'text' || field == 'snippets')) + setHTMLErrors(Markdown.validate(value)); - setHTMLErrors(HTMLErrors); - setCurrentBrew((prevBrew) => ({ ...prevBrew, text })); - localStorage.setItem(BREWKEY, text); - }; + if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); + else setCurrentBrew(prev => ({ ...prev, [field]: value })); - const handleStyleChange = (style) => { - setCurrentBrew(prevBrew => ({ ...prevBrew, style })); - localStorage.setItem(STYLEKEY, style); - }; - - const handleSnipChange = (snippet)=>{ - //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - HTMLErrors = Markdown.validate(snippet); - - setHTMLErrors(HTMLErrors); - setCurrentBrew((prevBrew) => ({ ...prevBrew, snippets: snippet })); - }; - - const handleMetaChange = (metadata, field = undefined) => { - if (field === 'theme' || field === 'renderer') - fetchThemeBundle(setError, setThemeBundle, metadata.renderer, metadata.theme); - - setCurrentBrew(prev => ({ ...prev, ...metadata })); - localStorage.setItem(METAKEY, JSON.stringify({ - renderer : metadata.renderer, - theme : metadata.theme, - lang : metadata.lang - })); + if(useLocalStorage) { + if(field == 'text') localStorage.setItem(BREWKEY, value); + if(field == 'style') localStorage.setItem(STYLEKEY, value); + if(field == 'snippets') localStorage.setItem(SNIPKEY, value); + if(field == 'metadata') localStorage.setItem(METAKEY, JSON.stringify({ + renderer : value.renderer, + theme : value.theme, + lang : value.lang + })); + } }; const save = async () => { @@ -204,10 +193,7 @@ const NewPage = (props) => { Date: Mon, 29 Sep 2025 12:48:25 -0400 Subject: [PATCH 41/95] Make Print/Vault/New common nav buttons to all pages --- client/homebrew/pages/editPage/editPage.jsx | 36 ++++++------- client/homebrew/pages/homePage/homePage.jsx | 57 ++++++++++++++------- client/homebrew/pages/newPage/newPage.jsx | 53 ++++++++++--------- 3 files changed, 87 insertions(+), 59 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index af39838cf..c42032534 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -1,38 +1,38 @@ /* eslint-disable max-lines */ import './editPage.less'; -import React, { useState, useEffect, useRef, useCallback, use } from 'react'; +// Common imports +import React, { useState, useEffect, useRef } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; -import _ from 'lodash';; -import { makePatches, stringifyPatches } from '@sanity/diff-match-patch'; -import { md5 } from 'hash-wasm'; -import { gzipSync, strToU8 } from 'fflate'; -import { Meta } from 'vitreum/headtags'; +import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js'; +import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; + +import SplitPane from 'client/components/splitPane/splitPane.jsx'; +import Editor from '../../editor/editor.jsx'; +import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; import Nav from 'naturalcrit/nav/nav.jsx'; import Navbar from '../../navbar/navbar.jsx'; import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; import AccountNavItem from '../../navbar/account.navitem.jsx'; -import ShareNavItem from '../../navbar/share.navitem.jsx'; import ErrorNavItem from '../../navbar/error-navitem.jsx'; import HelpNavItem from '../../navbar/help.navitem.jsx'; import VaultNavItem from '../../navbar/vault.navitem.jsx'; import PrintNavItem from '../../navbar/print.navitem.jsx'; import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; -import SplitPane from 'client/components/splitPane/splitPane.jsx'; -import Editor from '../../editor/editor.jsx'; -import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; +// Page specific imports +import { Meta } from 'vitreum/headtags'; +import _ from 'lodash'; +import { md5 } from 'hash-wasm'; +import { gzipSync, strToU8 } from 'fflate'; +import { makePatches, stringifyPatches } from '@sanity/diff-match-patch'; +import ShareNavItem from '../../navbar/share.navitem.jsx'; import LockNotification from './lockNotification/lockNotification.jsx'; - -import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js'; -import { printCurrentBrew, fetchThemeBundle } from '../../../../shared/helpers.js'; - import { updateHistory, versionHistoryGarbageCollection } from '../../utils/versionHistory.js'; - import googleDriveIcon from '../../googleDrive.svg'; const SAVE_TIMEOUT = 10000; @@ -344,11 +344,11 @@ const EditPage = (props)=>{ {renderSaveButton()} {renderAutoSaveButton()} } - - - + + + diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index c6625cade..b568e0ad0 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -1,26 +1,30 @@ +/* eslint-disable max-lines */ import './homePage.less'; -import React from 'react'; -import { useEffect, useState, useRef } from 'react'; -import request from '../../utils/request-middleware.js'; -import Markdown from 'naturalcrit/markdown.js'; -import { Meta } from 'vitreum/headtags'; +// Common imports +import React, { useState, useEffect, useRef } from 'react'; +import request from '../../utils/request-middleware.js'; +import Markdown from 'naturalcrit/markdown.js'; -import Nav from 'naturalcrit/nav/nav.jsx'; -import Navbar from '../../navbar/navbar.jsx'; -import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; -import HelpNavItem from '../../navbar/help.navitem.jsx'; -import VaultNavItem from '../../navbar/vault.navitem.jsx'; -import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; -import AccountNavItem from '../../navbar/account.navitem.jsx'; -import ErrorNavItem from '../../navbar/error-navitem.jsx'; -import { fetchThemeBundle } from '../../../../shared/helpers.js'; +import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; +import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; -import SplitPane from 'client/components/splitPane/splitPane.jsx'; -import Editor from '../../editor/editor.jsx'; -import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; +import SplitPane from 'client/components/splitPane/splitPane.jsx'; +import Editor from '../../editor/editor.jsx'; +import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; -import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; +import Nav from 'naturalcrit/nav/nav.jsx'; +import Navbar from '../../navbar/navbar.jsx'; +import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; +import AccountNavItem from '../../navbar/account.navitem.jsx'; +import ErrorNavItem from '../../navbar/error-navitem.jsx'; +import HelpNavItem from '../../navbar/help.navitem.jsx'; +import VaultNavItem from '../../navbar/vault.navitem.jsx'; +import PrintNavItem from '../../navbar/print.navitem.jsx'; +import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; + +// Page specific imports +import { Meta } from 'vitreum/headtags'; const useLocalStorage = false; @@ -45,6 +49,22 @@ const HomePage =(props)=>{ useEffect(()=>{ fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); + + const handleControlKeys = (e)=>{ + if(!(e.ctrlKey || e.metaKey)) return; + if(e.keyCode === 83) trySaveRef.current(true); + if(e.keyCode === 80) printCurrentBrew(); + if([83, 80].includes(e.keyCode)) { + e.stopPropagation(); + e.preventDefault(); + } + }; + + document.addEventListener('keydown', handleControlKeys); + + return () => { + document.removeEventListener('keydown', handleControlKeys); + }; }, []); const save = ()=>{ @@ -100,6 +120,7 @@ const HomePage =(props)=>{ null } + diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index 60b8b17f0..6dd19dec6 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -1,24 +1,30 @@ -/*eslint max-lines: ["warn", {"max": 300, "skipBlankLines": true, "skipComments": true}]*/ +/* eslint-disable max-lines */ import './newPage.less'; +// Common imports import React, { useState, useEffect, useRef } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; -import Nav from 'naturalcrit/nav/nav.jsx'; -import Navbar from '../../navbar/navbar.jsx'; -import AccountNavItem from '../../navbar/account.navitem.jsx'; -import ErrorNavItem from '../../navbar/error-navitem.jsx'; -import HelpNavItem from '../../navbar/help.navitem.jsx'; -import PrintNavItem from '../../navbar/print.navitem.jsx'; -import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; +import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; +import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; import SplitPane from 'client/components/splitPane/splitPane.jsx'; import Editor from '../../editor/editor.jsx'; import BrewRenderer from '../../brewRenderer/brewRenderer.jsx'; -import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; -import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; +import Nav from 'naturalcrit/nav/nav.jsx'; +import Navbar from '../../navbar/navbar.jsx'; +import NewBrewItem from '../../navbar/newbrew.navitem.jsx'; +import AccountNavItem from '../../navbar/account.navitem.jsx'; +import ErrorNavItem from '../../navbar/error-navitem.jsx'; +import HelpNavItem from '../../navbar/help.navitem.jsx'; +import VaultNavItem from '../../navbar/vault.navitem.jsx'; +import PrintNavItem from '../../navbar/print.navitem.jsx'; +import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; + +// Page specific imports +import { Meta } from 'vitreum/headtags'; const BREWKEY = 'homebrewery-new'; const STYLEKEY = 'homebrewery-new-style'; @@ -47,10 +53,21 @@ const NewPage = (props) => { const editorRef = useRef(null); useEffect(() => { - document.addEventListener('keydown', handleControlKeys); loadBrew(); fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); + const handleControlKeys = (e)=>{ + if(!(e.ctrlKey || e.metaKey)) return; + if(e.keyCode === 83) trySaveRef.current(true); + if(e.keyCode === 80) printCurrentBrew(); + if([83, 80].includes(e.keyCode)) { + e.stopPropagation(); + e.preventDefault(); + } + }; + + document.addEventListener('keydown', handleControlKeys); + return () => { document.removeEventListener('keydown', handleControlKeys); }; @@ -83,18 +100,6 @@ const NewPage = (props) => { window.history.replaceState({}, window.location.title, '/new/'); }; - const handleControlKeys = (e) => { - if (!(e.ctrlKey || e.metaKey)) return; - const S_KEY = 83; - const P_KEY = 80; - if (e.keyCode === S_KEY) save(); - if (e.keyCode === P_KEY) printCurrentBrew(); - if (e.keyCode === S_KEY || e.keyCode === P_KEY) { - e.preventDefault(); - e.stopPropagation(); - } - }; - const handleSplitMove = ()=>{ editorRef.current.update(); }; @@ -177,8 +182,10 @@ const NewPage = (props) => { {error ? : renderSaveButton()} + + From 4b753970c9edc8664944c3188650d7a7e26f4b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Mon, 29 Sep 2025 22:19:19 +0200 Subject: [PATCH 42/95] remove scrollbar --- shared/naturalcrit/codeEditor/codeEditor.less | 9 --------- 1 file changed, 9 deletions(-) diff --git a/shared/naturalcrit/codeEditor/codeEditor.less b/shared/naturalcrit/codeEditor/codeEditor.less index 84a5c63f1..2a57ae8e6 100644 --- a/shared/naturalcrit/codeEditor/codeEditor.less +++ b/shared/naturalcrit/codeEditor/codeEditor.less @@ -38,15 +38,6 @@ animation-duration : 0.4s; } - .CodeMirror-vscrollbar { - &::-webkit-scrollbar { width : 20px; } - &::-webkit-scrollbar-thumb { - width : 20px; - background : linear-gradient(90deg, #858585 15px, #808080 15px); - } - } - - //.cm-tab { // background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAQAAACOs/baAAAARUlEQVR4nGJgIAG8JkXxUAcCtDWemcGR1lY4MvgzCEKY7jSBjgxBDAG09UEQzAe0AMwMHrSOAwEGRtpaMIwAAAAA//8DAG4ID9EKs6YqAAAAAElFTkSuQmCC) no-repeat right; //} From e793db7b37756c5ec0bc690602520e3e2fc49ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 1 Oct 2025 22:55:32 +0200 Subject: [PATCH 43/95] separating the words to make it less ugly --- client/homebrew/homebrew.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index 095c679f1..c1b3f7a96 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -57,11 +57,11 @@ const Homebrew = (props)=>{ if(!isClient) return null; if(config.deployment) { return { - backgroundImage : `url("data:image/svg+xml;utf8,${config.deployment}")` + backgroundImage : `url("data:image/svg+xml;utf8,${config.deployment}")` }; } else if(config.local) { return { - backgroundImage : `url("data:image/svg+xml;utf8,Local")` + backgroundImage : `url("data:image/svg+xml;utf8,Local")` }; } return null; From f141c0bebd2b8bb8aec146b3764cabf926642bad Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 2 Oct 2025 19:28:10 +1300 Subject: [PATCH 44/95] Move dbCheck to only API calls that touch the database --- server/app.js | 2 -- server/homebrew.api.js | 13 +++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/server/app.js b/server/app.js index 162b34df3..afba0997b 100644 --- a/server/app.js +++ b/server/app.js @@ -32,7 +32,6 @@ import { splitTextStyleAndMetadata } from '../shared/helpers.js'; //==== Middleware Imports ====// import contentNegotiation from './middleware/content-negotiation.js'; -import dbCheck from './middleware/dbCheck.js'; import bodyParser from 'body-parser'; import cookieParser from 'cookie-parser'; import forceSSL from './forcessl.mw.js'; @@ -50,7 +49,6 @@ const sanitizeBrew = (brew, accessType)=>{ app.set('trust proxy', 1 /* number of proxies between user and server */); app.use('/', serveCompressedStaticAssets(`build`)); -app.use(dbCheck); app.use(contentNegotiation); app.use(bodyParser.json({ limit: '25mb' })); app.use(cookieParser()); diff --git a/server/homebrew.api.js b/server/homebrew.api.js index 3221638ab..5a3008cc9 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -13,6 +13,7 @@ import { md5 } from 'hash-wasm'; import { splitTextStyleAndMetadata, brewSnippetsToJSON, debugTextMismatch } from '../shared/helpers.js'; import checkClientVersion from './middleware/check-client-version.js'; +import dbCheck from './middleware/dbCheck.js'; const router = express.Router(); @@ -530,11 +531,11 @@ const api = { } }; -router.post('/api', checkClientVersion, asyncHandler(api.newBrew)); -router.put('/api/:id', checkClientVersion, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew)); -router.put('/api/update/:id', checkClientVersion, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew)); -router.delete('/api/:id', checkClientVersion, asyncHandler(api.deleteBrew)); -router.get('/api/remove/:id', checkClientVersion, asyncHandler(api.deleteBrew)); -router.get('/api/theme/:renderer/:id', asyncHandler(api.getThemeBundle)); +router.post('/api', checkClientVersion, dbCheck, asyncHandler(api.newBrew)); +router.put('/api/:id', checkClientVersion, dbCheck, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew)); +router.put('/api/update/:id', checkClientVersion, dbCheck, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew)); +router.delete('/api/:id', checkClientVersion, dbCheck, asyncHandler(api.deleteBrew)); +router.get('/api/remove/:id', checkClientVersion, dbCheck, asyncHandler(api.deleteBrew)); +router.get('/api/theme/:renderer/:id', dbCheck, asyncHandler(api.getThemeBundle)); export default api; From 900cf6aebb676aa7e9ea4a83ab8dcc1acfbbe122 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Thu, 2 Oct 2025 22:59:24 +1300 Subject: [PATCH 45/95] Change SAVEKEY definition to after username is populated --- client/homebrew/pages/newPage/newPage.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index bb21441cf..e7b1fdee6 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -23,7 +23,7 @@ import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '. const BREWKEY = 'homebrewery-new'; const STYLEKEY = 'homebrewery-new-style'; const METAKEY = 'homebrewery-new-meta'; -const SAVEKEY = `HOMEBREWERY-DEFAULT-SAVE-LOCATION-${global.account?.username || ''}`; +const SAVEKEYPREFIX = 'HOMEBREWERY-DEFAULT-SAVE-LOCATION-'; const NewPage = (props) => { props = { @@ -67,6 +67,7 @@ const NewPage = (props) => { brew.lang = metaStorage?.lang ?? brew.lang; } + const SAVEKEY = `${SAVEKEYPREFIX}${global.account?.username}`; const saveStorage = localStorage.getItem(SAVEKEY) || 'HOMEBREWERY'; setCurrentBrew(brew); From eefda9fe45687ab0006c2345bca1ba11e257b166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Thu, 2 Oct 2025 12:40:12 +0200 Subject: [PATCH 46/95] simplifying per suggestion --- client/homebrew/homebrew.jsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index c1b3f7a96..933971c04 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -55,14 +55,11 @@ const Homebrew = (props)=>{ const backgroundObject = ()=>{ if(!isClient) return null; - if(config.deployment) { - return { - backgroundImage : `url("data:image/svg+xml;utf8,${config.deployment}")` - }; - } else if(config.local) { - return { - backgroundImage : `url("data:image/svg+xml;utf8,Local")` - }; + if(config.deployment || config.local){ + const bgText = config.deployment || 'Local'; + return { + backgroundImage : `url("data:image/svg+xml;utf8,${bgText}")` + }; } return null; }; From bcca5fa97d0bffb79c1251f30e43642f4ec0419e Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Thu, 2 Oct 2025 19:27:45 -0400 Subject: [PATCH 47/95] In /homepage, rename brew state to currentBrew to match /new and /edit --- client/homebrew/pages/homePage/homePage.jsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 84967b1ff..657f313e1 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -28,7 +28,7 @@ const HomePage =(props)=>{ ...props }; - const [brew , setBrew] = useState(props.brew); + const [currentBrew , setCurrentBrew] = useState(props.brew); const [welcomeText , setWelcomeText] = useState(props.brew.text); const [error , setError] = useState(undefined); const [currentEditorViewPageNum , setCurrentEditorViewPageNum] = useState(1); @@ -40,12 +40,12 @@ const HomePage =(props)=>{ const editorRef = useRef(null); useEffect(()=>{ - fetchThemeBundle(setError, setThemeBundle, brew.renderer, brew.theme); + fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); }, []); const save = ()=>{ request.post('/api') - .send(brew) + .send(currentBrew) .end((err, res)=>{ if(err) { setError(err); @@ -105,9 +105,9 @@ const HomePage =(props)=>{ { currentBrewRendererPageNum={currentBrewRendererPageNum} /> { />
-
+
Save current
From 1c6a39363ca07dacbaa70cd3789f93ae21f0d962 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Thu, 2 Oct 2025 19:33:15 -0400 Subject: [PATCH 48/95] Combine handleText/Style/Snippet/Meta functions into common function Also adds any related imports and key names --- client/homebrew/editor/editor.jsx | 15 +++--- client/homebrew/pages/editPage/editPage.jsx | 50 +++++++++--------- client/homebrew/pages/homePage/homePage.jsx | 34 ++++++++++-- client/homebrew/pages/newPage/newPage.jsx | 57 ++++++++------------- 4 files changed, 85 insertions(+), 71 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 8d331e46e..9f9e23625 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -40,11 +40,8 @@ const Editor = createClass({ style : '' }, - onTextChange : ()=>{}, - onStyleChange : ()=>{}, - onMetaChange : ()=>{}, - onSnipChange : ()=>{}, - reportError : ()=>{}, + onBrewChange : ()=>{}, + reportError : ()=>{}, onCursorPageChange : ()=>{}, onViewPageChange : ()=>{}, @@ -438,7 +435,7 @@ const Editor = createClass({ language='gfm' view={this.state.view} value={this.props.brew.text} - onChange={this.props.onTextChange} + onChange={this.props.onBrewChange('text')} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} style={{ height: `calc(100% - ${this.state.snippetbarHeight}px)` }} /> @@ -451,7 +448,7 @@ const Editor = createClass({ language='css' view={this.state.view} value={this.props.brew.style ?? DEFAULT_STYLE_TEXT} - onChange={this.props.onStyleChange} + onChange={this.props.onBrewChange('style')} enableFolding={true} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} @@ -467,7 +464,7 @@ const Editor = createClass({ ; @@ -481,7 +478,7 @@ const Editor = createClass({ language='gfm' view={this.state.view} value={this.props.brew.snippets} - onChange={this.props.onSnipChange} + onChange={this.props.onBrewChange('snippets')} enableFolding={true} editorTheme={this.state.editorTheme} rerenderParent={this.rerenderParent} diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 6c2220ec1..aff5dd3ea 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -39,6 +39,11 @@ const SAVE_TIMEOUT = 10000; const UNSAVED_WARNING_TIMEOUT = 900000; //Warn user afer 15 minutes of unsaved changes const UNSAVED_WARNING_POPUP_TIMEOUT = 4000; //Show the warning for 4 seconds +const BREWKEY = 'homebrewery-new'; +const STYLEKEY = 'homebrewery-new-style'; +const SNIPKEY = 'homebrewery-new-snippets'; +const METAKEY = 'homebrewery-new-meta'; + const EditPage = (props)=>{ props = { brew : DEFAULT_BREW_LOAD, @@ -69,6 +74,8 @@ const EditPage = (props)=>{ const trySaveRef = useRef(trySave); // CTRL+S listener lives outside React and needs ref to use trySave with latest copy of brew const unsavedChangesRef = useRef(unsavedChanges); // Similarly, onBeforeUnload lives outside React and needs ref to unsavedChanges + const useLocalStorage = false; + useEffect(()=>{ const autoSavePref = JSON.parse(localStorage.getItem('AUTOSAVE_ON') ?? true); setAutoSaveEnabled(autoSavePref); @@ -125,29 +132,27 @@ const EditPage = (props)=>{ setCurrentBrewRendererPageNum(pageNumber); }; - const handleTextChange = (text)=>{ + const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' + if (subfield == 'renderer' || subfield == 'theme') + fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); + //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - setHTMLErrors(Markdown.validate(text)); - setCurrentBrew((prevBrew)=>({ ...prevBrew, text })); - }; + if(HTMLErrors.length && (field == 'text' || field == 'snippets')) + setHTMLErrors(Markdown.validate(value)); - const handleStyleChange = (style)=>{ - setCurrentBrew((prevBrew)=>({ ...prevBrew, style })); - }; + if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); + else setCurrentBrew(prev => ({ ...prev, [field]: value })); - const handleSnipChange = (snippet)=>{ - //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - setHTMLErrors(Markdown.validate(snippet)); - setCurrentBrew((prevBrew)=>({ ...prevBrew, snippets: snippet })); - }; - - const handleMetaChange = (metadata, field = undefined)=>{ - if(field === 'theme' || field === 'renderer') - fetchThemeBundle(setError, setThemeBundle, metadata.renderer, metadata.theme); - - setCurrentBrew((prev)=>({ ...prev, ...metadata })); + if(useLocalStorage) { + if(field == 'text') localStorage.setItem(BREWKEY, value); + if(field == 'style') localStorage.setItem(STYLEKEY, value); + if(field == 'snippets') localStorage.setItem(SNIPKEY, value); + if(field == 'metadata') localStorage.setItem(METAKEY, JSON.stringify({ + renderer : value.renderer, + theme : value.theme, + lang : value.lang + })); + } }; const updateBrew = (newData)=>setCurrentBrew((prevBrew)=>({ @@ -380,10 +385,7 @@ const EditPage = (props)=>{ { props = { brew : DEFAULT_BREW, @@ -31,6 +37,7 @@ const HomePage =(props)=>{ const [currentBrew , setCurrentBrew] = useState(props.brew); const [welcomeText , setWelcomeText] = useState(props.brew.text); const [error , setError] = useState(undefined); + const [HTMLErrors , setHTMLErrors ] = useState(Markdown.validate(props.brew.text)); const [currentEditorViewPageNum , setCurrentEditorViewPageNum] = useState(1); const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); @@ -39,6 +46,8 @@ const HomePage =(props)=>{ const editorRef = useRef(null); + const useLocalStorage = false; + useEffect(()=>{ fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); }, []); @@ -72,8 +81,27 @@ const HomePage =(props)=>{ setCurrentBrewRendererPageNum(pageNumber); }; - const handleTextChange = (text)=>{ - setBrew((prevBrew) => ({ ...prevBrew, text })); + const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' + if (subfield == 'renderer' || subfield == 'theme') + fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); + + //If there are HTML errors, run the validator on every change to give quick feedback + if(HTMLErrors.length && (field == 'text' || field == 'snippets')) + setHTMLErrors(Markdown.validate(value)); + + if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); + else setCurrentBrew(prev => ({ ...prev, [field]: value })); + + if(useLocalStorage) { + if(field == 'text') localStorage.setItem(BREWKEY, value); + if(field == 'style') localStorage.setItem(STYLEKEY, value); + if(field == 'snippets') localStorage.setItem(SNIPKEY, value); + if(field == 'metadata') localStorage.setItem(METAKEY, JSON.stringify({ + renderer : value.renderer, + theme : value.theme, + lang : value.lang + })); + } }; const clearError = ()=>{ @@ -105,8 +133,8 @@ const HomePage =(props)=>{ { const editorRef = useRef(null); + const useLocalStorage = true; + useEffect(() => { document.addEventListener('keydown', handleControlKeys); loadBrew(); @@ -109,40 +112,27 @@ const NewPage = (props) => { setCurrentBrewRendererPageNum(pageNumber); }; - const handleTextChange = (text)=>{ + const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' + if (subfield == 'renderer' || subfield == 'theme') + fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); + //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - HTMLErrors = Markdown.validate(text); + if(HTMLErrors.length && (field == 'text' || field == 'snippets')) + setHTMLErrors(Markdown.validate(value)); - setHTMLErrors(HTMLErrors); - setCurrentBrew((prevBrew) => ({ ...prevBrew, text })); - localStorage.setItem(BREWKEY, text); - }; + if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); + else setCurrentBrew(prev => ({ ...prev, [field]: value })); - const handleStyleChange = (style) => { - setCurrentBrew(prevBrew => ({ ...prevBrew, style })); - localStorage.setItem(STYLEKEY, style); - }; - - const handleSnipChange = (snippet)=>{ - //If there are HTML errors, run the validator on every change to give quick feedback - if(HTMLErrors.length) - HTMLErrors = Markdown.validate(snippet); - - setHTMLErrors(HTMLErrors); - setCurrentBrew((prevBrew) => ({ ...prevBrew, snippets: snippet })); - }; - - const handleMetaChange = (metadata, field = undefined) => { - if (field === 'theme' || field === 'renderer') - fetchThemeBundle(setError, setThemeBundle, metadata.renderer, metadata.theme); - - setCurrentBrew(prev => ({ ...prev, ...metadata })); - localStorage.setItem(METAKEY, JSON.stringify({ - renderer : metadata.renderer, - theme : metadata.theme, - lang : metadata.lang - })); + if(useLocalStorage) { + if(field == 'text') localStorage.setItem(BREWKEY, value); + if(field == 'style') localStorage.setItem(STYLEKEY, value); + if(field == 'snippets') localStorage.setItem(SNIPKEY, value); + if(field == 'metadata') localStorage.setItem(METAKEY, JSON.stringify({ + renderer : value.renderer, + theme : value.theme, + lang : value.lang + })); + } }; const save = async () => { @@ -216,10 +206,7 @@ const NewPage = (props) => { Date: Fri, 3 Oct 2025 13:41:53 +1300 Subject: [PATCH 49/95] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5206f4cbf..a33f2f073 100644 --- a/README.md +++ b/README.md @@ -75,8 +75,9 @@ it using the two commands: 1. `npm install` 1. `npm start` -You should now be able to go to [http://localhost:8000](http://localhost:8000) -in your browser and use The Homebrewery offline. +When the Homebrewery server is started for the first time, it will modify the database to create the indexes required for better Homebrewery performance. This may take a few moments to complete for each index, dependent on how much content is in your local database - a brand new, empty database should be done in seconds. + +On completion, you should be able to go to [http://localhost:8000](http://localhost:8000) in your browser and use The Homebrewery offline. If you had any issue at all, here are some links that may be useful: - [Course](https://learn.mongodb.com/courses/m103-basic-cluster-administration) on cluster administration, useful for beginners @@ -145,3 +146,4 @@ your contribution to the project, please join our [gitter chat][gitter-url]. [github-pr-docs-url]: https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request [gitter-url]: https://gitter.im/naturalcrit/Lobby + From c2e51b0baa1257378b1e7fc22cca68ee7bc55c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 3 Oct 2025 21:32:52 +0200 Subject: [PATCH 50/95] removing isclient check to see what's what --- client/homebrew/homebrew.jsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index 933971c04..c85351289 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -41,12 +41,6 @@ const Homebrew = (props)=>{ brews } = props; - const [isClient, setIsClient] = useState(false); - - useEffect(()=>{ - setIsClient(true); - }, []); - global.account = account; global.version = version; global.enable_v3 = enable_v3; @@ -54,7 +48,6 @@ const Homebrew = (props)=>{ global.config = config; const backgroundObject = ()=>{ - if(!isClient) return null; if(config.deployment || config.local){ const bgText = config.deployment || 'Local'; return { @@ -66,7 +59,7 @@ const Homebrew = (props)=>{ return ( -
+
} /> } /> From e0379a0baa75c45b9479620164d53b47ce629e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 3 Oct 2025 21:38:10 +0200 Subject: [PATCH 51/95] last cleanup --- client/homebrew/homebrew.jsx | 2 +- client/homebrew/homebrew.less | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index c85351289..efdf70b49 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -1,7 +1,7 @@ /* eslint-disable camelcase */ import 'core-js/es/string/to-well-formed.js'; //Polyfill for older browsers import './homebrew.less'; -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { StaticRouter as Router, Route, Routes, useParams, useSearchParams } from 'react-router'; import HomePage from './pages/homePage/homePage.jsx'; diff --git a/client/homebrew/homebrew.less b/client/homebrew/homebrew.less index 5c7b63023..2cbc35857 100644 --- a/client/homebrew/homebrew.less +++ b/client/homebrew/homebrew.less @@ -9,7 +9,6 @@ flex-direction : column; height : 100%; overflow-y : hidden; - //background-color : @steel; .content { position : relative; flex : auto; From aff9a8576976cd5714ce02d811dff80605de8c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Fri, 3 Oct 2025 21:38:43 +0200 Subject: [PATCH 52/95] end of file character shit --- client/homebrew/homebrew.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index efdf70b49..cfc691407 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -81,4 +81,4 @@ const Homebrew = (props)=>{ ); }; -module.exports = Homebrew; +module.exports = Homebrew; \ No newline at end of file From 2b138e56db72c1770a98d462e5aa3f54b2297f43 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 4 Oct 2025 12:29:06 +1300 Subject: [PATCH 53/95] Add dbCheck middleware to app.js routes that use DB --- server/app.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/app.js b/server/app.js index afba0997b..673d70c68 100644 --- a/server/app.js +++ b/server/app.js @@ -35,6 +35,7 @@ import contentNegotiation from './middleware/content-negotiation.js'; import bodyParser from 'body-parser'; import cookieParser from 'cookie-parser'; import forceSSL from './forcessl.mw.js'; +import dbCheck from './middleware/dbCheck.js'; const sanitizeBrew = (brew, accessType)=>{ @@ -274,7 +275,7 @@ app.get('/metadata/:id', asyncHandler(getBrew('share')), (req, res)=>{ app.get('/css/:id', asyncHandler(getBrew('share')), (req, res)=>{getCSS(req, res);}); //User Page -app.get('/user/:username', async (req, res, next)=>{ +app.get('/user/:username', dbCheck, async (req, res, next)=>{ const ownAccount = req.account && (req.account.username == req.params.username); req.ogMeta = { ...defaultMetaTags, @@ -346,7 +347,7 @@ app.get('/user/:username', async (req, res, next)=>{ }); //Change author name on brews -app.put('/api/user/rename', async (req, res)=>{ +app.put('/api/user/rename', dbCheck, async (req, res)=>{ const { username, newUsername } = req.body; const ownAccount = req.account && (req.account.username == newUsername); @@ -432,7 +433,7 @@ app.get('/new', asyncHandler(async(req, res, next)=>{ })); //Share Page -app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, res, next)=>{ +app.get('/share/:id', dbCheck, asyncHandler(getBrew('share')), asyncHandler(async (req, res, next)=>{ const { brew } = req; req.ogMeta = { ...defaultMetaTags, title : `${req.brew.title || 'Untitled Brew'} - ${req.brew.authors[0] || 'No author.'}`, @@ -459,7 +460,7 @@ app.get('/share/:id', asyncHandler(getBrew('share')), asyncHandler(async (req, r })); //Account Page -app.get('/account', asyncHandler(async (req, res, next)=>{ +app.get('/account', dbCheck, asyncHandler(async (req, res, next)=>{ const data = {}; data.title = 'Account Information Page'; From e82921f81a7a2250ab0cade4124e028b0c5df156 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 4 Oct 2025 14:54:57 +1300 Subject: [PATCH 54/95] Add key to activate deletion for testing --- .../utils/updateLocalStorage/updateLocalStorageKeys.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js index 6ab4fbcd1..05b57dfa2 100644 --- a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js +++ b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js @@ -10,11 +10,14 @@ const updateLocalStorage = function(){ const storage = window.localStorage; + const deleteKeys = storage?.getItem('HB_deleteKeys') != null; + console.log('DELETE KEYS:', deleteKeys); + Object.keys(localStorageKeyMap).forEach((key)=>{ if(storage[key] && !storage[localStorageKeyMap[key]]){ const data = storage.getItem(key); storage.setItem(localStorageKeyMap[key], data); - // storage.removeItem(key); + if(deleteKeys) storage.removeItem(key); } }); From 400fa250eec2b71df2bd4ca124b4f3121e000956 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 4 Oct 2025 15:19:31 +1300 Subject: [PATCH 55/95] Move key deletion out of key update check --- .../utils/updateLocalStorage/updateLocalStorageKeys.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js index 05b57dfa2..6d0bf0c8c 100644 --- a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js +++ b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js @@ -11,12 +11,13 @@ const updateLocalStorage = function(){ const storage = window.localStorage; const deleteKeys = storage?.getItem('HB_deleteKeys') != null; - console.log('DELETE KEYS:', deleteKeys); Object.keys(localStorageKeyMap).forEach((key)=>{ - if(storage[key] && !storage[localStorageKeyMap[key]]){ - const data = storage.getItem(key); - storage.setItem(localStorageKeyMap[key], data); + if(storage[key]){ + if(!storage[localStorageKeyMap[key]]){ + const data = storage.getItem(key); + storage.setItem(localStorageKeyMap[key], data); + }; if(deleteKeys) storage.removeItem(key); } }); From 962dcbdbf6edbd8d1dadfa84f38b8fe38cdfe6dd Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 4 Oct 2025 15:36:14 +1300 Subject: [PATCH 56/95] Update Docker instructions --- README.DOCKER.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.DOCKER.md b/README.DOCKER.md index 4dfbef045..c3b38224d 100644 --- a/README.DOCKER.md +++ b/README.DOCKER.md @@ -49,7 +49,7 @@ Make an changes you need to `config/docker.json` then build the image. If it doe "web_port" : 8000, "enable_v3" : true, "mongodb_uri": "mongodb://172.17.0.2/homebrewery", -"enable_themes" : true, +"enable_themes" : true } ``` @@ -90,6 +90,13 @@ docker run --name homebrewery-mongodb -d --restart unless-stopped -v mongodata:/ docker run --name homebrewery-app -d --restart unless-stopped -e NODE_ENV=docker -v $(pwd)/config/docker.json:/usr/src/app/config/docker.json -p 8000:8000 docker.io/library/homebrewery:latest ``` +**NOTE:** If you are running from the Windows command line, this will not work as `$(pwd)` is not valid syntax. Use this command instead: +```shell +# Make sure you run this in the homebrewery directory +docker run --name homebrewery-app -d --restart unless-stopped -e NODE_ENV=docker -v %cd%/config/docker.json:/usr/src/app/config/docker.json -p 8000:8000 docker.io/library/homebrewery:latest +``` + + ## Updating the Image When Homebrewery code updates, your docker container will not automatically follow the changes. To do so you will need to rebuild your homebrewery image. @@ -117,3 +124,9 @@ docker-compose build homebrewery docker run --name homebrewery-app -d --restart unless-stopped -e NODE_ENV=docker -v $(pwd)/config/docker.json:/usr/src/app/config/docker.json -p 8000:8000 docker.io/library/homebrewery:latest ``` +**NOTE:** If you are running from the Windows command line, this will not work as `$(pwd)` is not valid syntax. Use this command instead: +```shell +# Make sure you run this in the homebrewery directory +docker run --name homebrewery-app -d --restart unless-stopped -e NODE_ENV=docker -v %cd%/config/docker.json:/usr/src/app/config/docker.json -p 8000:8000 docker.io/library/homebrewery:latest +``` + From ae51213c8c428a27242c5e5b8acb0af4b4564528 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 5 Oct 2025 12:25:51 +1300 Subject: [PATCH 57/95] Permanently enable old local storage key deletion --- .../utils/updateLocalStorage/updateLocalStorageKeys.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js index 6d0bf0c8c..1a8231f73 100644 --- a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js +++ b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js @@ -10,15 +10,13 @@ const updateLocalStorage = function(){ const storage = window.localStorage; - const deleteKeys = storage?.getItem('HB_deleteKeys') != null; - Object.keys(localStorageKeyMap).forEach((key)=>{ if(storage[key]){ if(!storage[localStorageKeyMap[key]]){ const data = storage.getItem(key); storage.setItem(localStorageKeyMap[key], data); }; - if(deleteKeys) storage.removeItem(key); + storage.removeItem(key); } }); From 20e12ebcb5f759a28d279c65355492fa8793b2fd Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 4 Oct 2025 21:39:24 -0400 Subject: [PATCH 58/95] Remove handler function for cursor/renderer page. Use setState directly --- client/homebrew/pages/editPage/editPage.jsx | 18 +++--------------- client/homebrew/pages/homePage/homePage.jsx | 18 +++--------------- client/homebrew/pages/newPage/newPage.jsx | 18 +++--------------- 3 files changed, 9 insertions(+), 45 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 200a754c2..499cbb454 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -123,18 +123,6 @@ const EditPage = (props)=>{ editorRef.current?.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; - const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' if (subfield == 'renderer' || subfield == 'theme') fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); @@ -394,8 +382,8 @@ const EditPage = (props)=>{ userThemes={props.userThemes} themeBundle={themeBundle} updateBrew={updateBrew} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -408,7 +396,7 @@ const EditPage = (props)=>{ themeBundle={themeBundle} errors={HTMLErrors} lang={currentBrew.lang} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index 16811576e..0a4920b81 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -69,18 +69,6 @@ const HomePage =(props)=>{ editorRef.current.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; - const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' if (subfield == 'renderer' || subfield == 'theme') fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); @@ -138,8 +126,8 @@ const HomePage =(props)=>{ renderer={currentBrew.renderer} showEditButtons={false} themeBundle={themeBundle} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -148,7 +136,7 @@ const HomePage =(props)=>{ text={currentBrew.text} style={currentBrew.style} renderer={currentBrew.renderer} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index b8c4e8100..580a7a764 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -102,18 +102,6 @@ const NewPage = (props) => { editorRef.current.update(); }; - const handleEditorViewPageChange = (pageNumber)=>{ - setCurrentEditorViewPageNum(pageNumber); - }; - - const handleEditorCursorPageChange = (pageNumber)=>{ - setCurrentEditorCursorPageNum(pageNumber); - }; - - const handleBrewRendererPageChange = (pageNumber)=>{ - setCurrentBrewRendererPageNum(pageNumber); - }; - const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' if (subfield == 'renderer' || subfield == 'theme') fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); @@ -212,8 +200,8 @@ const NewPage = (props) => { renderer={currentBrew.renderer} userThemes={props.userThemes} themeBundle={themeBundle} - onCursorPageChange={handleEditorCursorPageChange} - onViewPageChange={handleEditorViewPageChange} + onCursorPageChange={setCurrentEditorCursorPageNum} + onViewPageChange={setCurrentEditorViewPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} @@ -226,7 +214,7 @@ const NewPage = (props) => { themeBundle={themeBundle} errors={HTMLErrors} lang={currentBrew.lang} - onPageChange={handleBrewRendererPageChange} + onPageChange={setCurrentBrewRendererPageNum} currentEditorViewPageNum={currentEditorViewPageNum} currentEditorCursorPageNum={currentEditorCursorPageNum} currentBrewRendererPageNum={currentBrewRendererPageNum} From 2c4c4b8f924c9e8626935751bfabd057cac4206b Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sat, 4 Oct 2025 22:17:24 -0400 Subject: [PATCH 59/95] Make `unsavedChanges` state common /editPage.jsx uses `unsavedChanges` state to detect when autosave should fire, or unsaved changes warning should display. /homePage.jsx uses a similar check (different variables) to detect when to show the popup "save now"! button /newPage.jsx doesn't do any of this, but probably should pop up a warning when saving hasn't happened for a long time This commit just gives all of the pages the same common `unsavedChanges` state, calculated in the same way, and updates any sections that depend on that updated state. This is precursor work to adding "unsaved changes" warnings to all three pages. --- client/homebrew/pages/editPage/editPage.jsx | 2 +- client/homebrew/pages/homePage/homePage.jsx | 16 +++++++++++++--- client/homebrew/pages/newPage/newPage.jsx | 14 ++++++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index e3d449a55..3bd74b786 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -5,6 +5,7 @@ import './editPage.less'; import React, { useState, useEffect, useRef } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; +import _ from 'lodash'; import { DEFAULT_BREW_LOAD } from '../../../../server/brewDefaults.js'; import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; @@ -25,7 +26,6 @@ import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; // Page specific imports import { Meta } from 'vitreum/headtags'; -import _ from 'lodash'; import { md5 } from 'hash-wasm'; import { gzipSync, strToU8 } from 'fflate'; import { makePatches, stringifyPatches } from '@sanity/diff-match-patch'; diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index fdc439ab5..cfa6eb59d 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -5,6 +5,7 @@ import './homePage.less'; import React, { useState, useEffect, useRef } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; +import _ from 'lodash'; import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; @@ -41,16 +42,18 @@ const HomePage =(props)=>{ }; const [currentBrew , setCurrentBrew] = useState(props.brew); - const [welcomeText , setWelcomeText] = useState(props.brew.text); const [error , setError] = useState(undefined); const [HTMLErrors , setHTMLErrors] = useState(Markdown.validate(props.brew.text)); const [currentEditorViewPageNum , setCurrentEditorViewPageNum] = useState(1); const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); const [themeBundle , setThemeBundle] = useState({}); + const [unsavedChanges , setUnsavedChanges] = useState(false); const [isSaving , setIsSaving] = useState(false); + const [autoSaveEnabled , setAutoSaveEnable] = useState(false); - const editorRef = useRef(null); + const editorRef = useRef(null); + const lastSavedBrew = useRef(_.cloneDeep(props.brew)); useEffect(()=>{ fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); @@ -85,6 +88,13 @@ const HomePage =(props)=>{ }); }; + useEffect(()=>{ + const hasChange = !_.isEqual(currentBrew, lastSavedBrew.current); + setUnsavedChanges(hasChange); + + if(autoSaveEnabled) trySave(false, hasChange); + }, [currentBrew]); + const handleSplitMove = ()=>{ editorRef.current.update(); }; @@ -165,7 +175,7 @@ const HomePage =(props)=>{ />
-
+
Save current
diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index d1d1fa75c..b9b628a2c 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -5,6 +5,7 @@ import './newPage.less'; import React, { useState, useEffect, useRef } from 'react'; import request from '../../utils/request-middleware.js'; import Markdown from 'naturalcrit/markdown.js'; +import _ from 'lodash'; import { DEFAULT_BREW } from '../../../../server/brewDefaults.js'; import { printCurrentBrew, fetchThemeBundle, splitTextStyleAndMetadata } from '../../../../shared/helpers.js'; @@ -26,7 +27,6 @@ import { both as RecentNavItem } from '../../navbar/recent.navitem.jsx'; // Page specific imports import { Meta } from 'vitreum/headtags'; - const BREWKEY = 'HB_newPage_content'; const STYLEKEY = 'HB_newPage_style'; const METAKEY = 'HB_newPage_metadata'; @@ -51,8 +51,11 @@ const NewPage = (props) => { const [currentEditorCursorPageNum, setCurrentEditorCursorPageNum] = useState(1); const [currentBrewRendererPageNum, setCurrentBrewRendererPageNum] = useState(1); const [themeBundle , setThemeBundle ] = useState({}); + const [unsavedChanges , setUnsavedChanges ] = useState(false); + const [autoSaveEnabled , setAutoSaveEnabled ] = useState(false); - const editorRef = useRef(null); + const editorRef = useRef(null); + const lastSavedBrew = useRef(_.cloneDeep(props.brew)); useEffect(() => { loadBrew(); @@ -103,6 +106,13 @@ const NewPage = (props) => { window.history.replaceState({}, window.location.title, '/new/'); }; + useEffect(()=>{ + const hasChange = !_.isEqual(currentBrew, lastSavedBrew.current); + setUnsavedChanges(hasChange); + + if(autoSaveEnabled) trySave(false, hasChange); + }, [currentBrew]); + const handleSplitMove = ()=>{ editorRef.current.update(); }; From bb0a840113e2c246d11cd41ca5a07b95b48d8c36 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 5 Oct 2025 15:30:47 +1300 Subject: [PATCH 60/95] Fix HBErrorCode to string, not number --- server/middleware/dbCheck.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/middleware/dbCheck.js b/server/middleware/dbCheck.js index 154ab4a9c..f486eab52 100644 --- a/server/middleware/dbCheck.js +++ b/server/middleware/dbCheck.js @@ -7,7 +7,7 @@ export default (req, res, next)=>{ if(mongoose.connection.readyState == 1) return next(); throw { - HBErrorCode : 13, + HBErrorCode : '13', name : 'Database Connection Error', message : 'Unable to connect to database', status : mongoose.connection.readyState From a14ea8956237628d954bb0f5c8c03b59ad8f8559 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 5 Oct 2025 15:31:04 +1300 Subject: [PATCH 61/95] Post-merge cleanup --- server/db.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/db.js b/server/db.js index d7baa922d..4930e4cd6 100644 --- a/server/db.js +++ b/server/db.js @@ -39,8 +39,8 @@ const connect = async (config)=>{ retryWrites : false, autoIndex : (config.get('local_environments').includes(config.get('node_env'))) }) - .then(addListeners(Mongoose)) - .catch((error)=>handleConnectionError(error)); + .then(addListeners(Mongoose)) + .catch((error)=>handleConnectionError(error)); }; export default { From 88bc9b79c9f1ed54182dfa5ddaf73d18ea4d4744 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 5 Oct 2025 15:31:53 +1300 Subject: [PATCH 62/95] Add new error message to nav bar error container --- client/homebrew/navbar/error-navitem.jsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/client/homebrew/navbar/error-navitem.jsx b/client/homebrew/navbar/error-navitem.jsx index 6d9bec444..030378cb6 100644 --- a/client/homebrew/navbar/error-navitem.jsx +++ b/client/homebrew/navbar/error-navitem.jsx @@ -2,9 +2,9 @@ require('./error-navitem.less'); const React = require('react'); const Nav = require('naturalcrit/nav/nav.jsx'); -const ErrorNavItem = ({error = '', clearError})=>{ +const ErrorNavItem = ({ error = '', clearError })=>{ const response = error.response; - const errorCode = error.code + const errorCode = error.code; const status = response?.status; const HBErrorCode = response?.body?.HBErrorCode; const message = response?.body?.message; @@ -112,6 +112,15 @@ const ErrorNavItem = ({error = '', clearError})=>{ ; } + if(HBErrorCode === '13') { + return + Oops! +
+ Server has lost connection to the database. +
+
; + } + if(errorCode === 'ECONNABORTED') { return Oops! From c17a5e72b92ea2f35d9dd971a7f4b5d37732e21f Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sun, 5 Oct 2025 15:40:40 +1300 Subject: [PATCH 63/95] Switch to Calc's simplified test spec --- server/middleware/dbCheck.spec.js | 67 +++++++++---------------------- 1 file changed, 20 insertions(+), 47 deletions(-) diff --git a/server/middleware/dbCheck.spec.js b/server/middleware/dbCheck.spec.js index dea218918..0c37d40ab 100644 --- a/server/middleware/dbCheck.spec.js +++ b/server/middleware/dbCheck.spec.js @@ -2,54 +2,27 @@ import mongoose from 'mongoose'; import dbCheck from './dbCheck.js'; import config from '../config.js'; -describe('database check middleware', ()=>{ - let request; - let response; - let next; +describe('dbCheck middleware', ()=>{ + const next = jest.fn(); - beforeEach(()=>{ - request = { - get : function(key) { - return this[key]; - } - }; - response = { - status : jest.fn(()=>response), - send : jest.fn(()=>{}) - }; - next = jest.fn(); - - // Mock the Config module - jest.mock('../config.js'); - config.get = jest.fn((param)=>{ - // The requested key name will be reflected to the output - return param; - }); - }); - - afterEach(()=>{ - jest.clearAllMocks(); - }); - - it('should return 503 if readystate != 1', ()=>{ - const dbState = mongoose.connection.readyState; - - mongoose.connection.readyState = 99; - - expect(()=>{dbCheck(request, response);}).toThrow(new Error('Unable to connect to database')); - - mongoose.connection.readyState = dbState; - }); - - it('should call next if readystate == 1', ()=>{ - const dbState = mongoose.connection.readyState; - - mongoose.connection.readyState = 1; - - dbCheck(request, response, next); - - mongoose.connection.readyState = dbState; + afterEach(()=>jest.clearAllMocks()); + it('should skip check in test mode', ()=>{ + config.get = jest.fn(()=>'test'); + expect(()=>dbCheck({}, {}, next)).not.toThrow(); expect(next).toHaveBeenCalled(); }); -}); + + it('should call next if readyState == 1', ()=>{ + config.get = jest.fn(()=>'production'); + mongoose.connection.readyState = 1; + dbCheck({}, {}, next); + expect(next).toHaveBeenCalled(); + }); + + it('should throw if readyState != 1', ()=>{ + config.get = jest.fn(()=>'production'); + mongoose.connection.readyState = 99; + expect(()=>dbCheck({}, {}, next)).toThrow(/Unable to connect/); + }); +}); \ No newline at end of file From 460b12e3569476b959022411cf0b508228e0f1b9 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sun, 5 Oct 2025 11:26:43 -0500 Subject: [PATCH 64/95] Proposed fix per calc. This also works but has different currsor behavior. Original fix left in place, commented pending decisions. --- client/homebrew/editor/editor.jsx | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index 4a4dff0f3..dd810f33a 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -97,20 +97,20 @@ const Editor = createClass({ if(prevProps.moveSource !== this.props.moveSource) this.sourceJump(); - if((prevProps.isDragging !== this.props.isDragging) && (this.props.isDragging) && (this.lastCursor == undefined)) { - this.lastCursor = this.codeEditor.current.codeMirror.getCursor(); - const lastXY = this.codeEditor.current.codeMirror.getScrollInfo(); - const lastRowPos = this.codeEditor.current.codeMirror.heightAtLine(this.lastCursor.line, 'local', true); - this.lastCursor.offset = Math.round(lastRowPos-lastXY.top); - } + // if((prevProps.isDragging !== this.props.isDragging) && (this.props.isDragging) && (this.lastCursor == undefined)) { + // this.lastCursor = this.codeEditor.current.codeMirror.getCursor(); + // const lastXY = this.codeEditor.current.codeMirror.getScrollInfo(); + // const lastRowPos = this.codeEditor.current.codeMirror.heightAtLine(this.lastCursor.line, 'local', true); + // this.lastCursor.offset = Math.round(lastRowPos-lastXY.top); + // } - if((prevProps.isDragging !== this.props.isDragging) && (!this.props.isDragging)) { - const scroll = this.codeEditor.current.codeMirror.getScrollInfo(); - this.codeEditor.current.codeMirror.scrollTo(null, - this.codeEditor.current.codeMirror.heightAtLine(this.lastCursor.line, 'local', true) - this.lastCursor.offset); - this.codeEditor.current.setCursorPosition(this.lastCursor.line, this.lastCursor.ch); - this.lastCursor = undefined; - } + // if((prevProps.isDragging !== this.props.isDragging) && (!this.props.isDragging)) { + // const scroll = this.codeEditor.current.codeMirror.getScrollInfo(); + // this.codeEditor.current.codeMirror.scrollTo(null, + // this.codeEditor.current.codeMirror.heightAtLine(this.lastCursor.line, 'local', true) - this.lastCursor.offset); + // this.codeEditor.current.setCursorPosition(this.lastCursor.line, this.lastCursor.ch); + // this.lastCursor = undefined; + // } if(this.props.liveScroll) { if(prevProps.currentBrewRendererPageNum !== this.props.currentBrewRendererPageNum) { @@ -424,7 +424,6 @@ const Editor = createClass({ //Called when there are changes to the editor's dimensions update : function(){ - this.codeEditor.current?.updateSize(); const snipHeight = document.querySelector('.editor > .snippetBar').offsetHeight; if(snipHeight !== this.state.snippetbarHeight) this.setState({ snippetbarHeight: snipHeight }); From 7393aef806e8cda3c2b0e3d84ce5924db8d3d6aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 5 Oct 2025 19:42:01 +0200 Subject: [PATCH 65/95] set up development config variavle --- client/homebrew/homebrew.jsx | 1 + config/default.json | 1 + 2 files changed, 2 insertions(+) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index cfc691407..f670df8ab 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -48,6 +48,7 @@ const Homebrew = (props)=>{ global.config = config; const backgroundObject = ()=>{ + if(!config.development) return null; if(config.deployment || config.local){ const bgText = config.deployment || 'Local'; return { diff --git a/config/default.json b/config/default.json index bea3b2663..0a2d7281e 100644 --- a/config/default.json +++ b/config/default.json @@ -1,4 +1,5 @@ { + "development": true, "host" : "homebrewery.local.naturalcrit.com:8000", "naturalcrit_url" : "local.naturalcrit.com:8010", "secret" : "secret", From c90a8c53a50218c0b605419ba6fba5ddbabb4c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 5 Oct 2025 19:56:50 +0200 Subject: [PATCH 66/95] lets test this --- client/homebrew/homebrew.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index bf51babc8..d62bc6699 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -51,8 +51,8 @@ const Homebrew = (props)=>{ const backgroundObject = ()=>{ if(!config.development) return null; - if(config.deployment || config.local){ - const bgText = config.deployment || 'Local'; + if(global.config.deployment || config.local){ + const bgText = global.config.deployment || 'Local'; return { backgroundImage : `url("data:image/svg+xml;utf8,${bgText}")` }; From 1f51abaf10998210e1ea3a251f3cf2e49dcdfe6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 5 Oct 2025 19:57:49 +0200 Subject: [PATCH 67/95] this makes more sense --- client/homebrew/homebrew.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index d62bc6699..e7e006808 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -50,8 +50,7 @@ const Homebrew = (props)=>{ global.config = config; const backgroundObject = ()=>{ - if(!config.development) return null; - if(global.config.deployment || config.local){ + if(global.config.deployment || (config.local && config.development)){ const bgText = global.config.deployment || 'Local'; return { backgroundImage : `url("data:image/svg+xml;utf8,${bgText}")` From 4a5bb1efb10e4974f3fb1c3f5dd13b029e8432f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Sun, 5 Oct 2025 22:14:13 +0200 Subject: [PATCH 68/95] initial commit --- README.DOCKER.md | 2 -- client/homebrew/editor/metadataEditor/metadataEditor.jsx | 4 ---- client/homebrew/homebrew.jsx | 4 ---- config/default.json | 2 -- server/app.js | 2 -- 5 files changed, 14 deletions(-) diff --git a/README.DOCKER.md b/README.DOCKER.md index c3b38224d..dba2e2257 100644 --- a/README.DOCKER.md +++ b/README.DOCKER.md @@ -47,9 +47,7 @@ Make an changes you need to `config/docker.json` then build the image. If it doe "naturalcrit_url" : "local.naturalcrit.com:8010", "secret" : "secret", "web_port" : 8000, -"enable_v3" : true, "mongodb_uri": "mongodb://172.17.0.2/homebrewery", -"enable_themes" : true } ``` diff --git a/client/homebrew/editor/metadataEditor/metadataEditor.jsx b/client/homebrew/editor/metadataEditor/metadataEditor.jsx index 8f256922f..338ad9360 100644 --- a/client/homebrew/editor/metadataEditor/metadataEditor.jsx +++ b/client/homebrew/editor/metadataEditor/metadataEditor.jsx @@ -207,8 +207,6 @@ const MetadataEditor = createClass({ }, renderThemeDropdown : function(){ - if(!global.enable_themes) return; - const mergedThemes = _.merge(Themes, this.props.userThemes); const listThemes = (renderer)=>{ @@ -307,8 +305,6 @@ const MetadataEditor = createClass({ }, renderRenderOptions : function(){ - if(!global.enable_v3) return; - return
diff --git a/client/homebrew/homebrew.jsx b/client/homebrew/homebrew.jsx index 1aff5067d..d53d3770e 100644 --- a/client/homebrew/homebrew.jsx +++ b/client/homebrew/homebrew.jsx @@ -28,8 +28,6 @@ const Homebrew = (props)=>{ url = '', version = '0.0.0', account = null, - enable_v3 = false, - enable_themes, config, brew = { title : '', @@ -46,8 +44,6 @@ const Homebrew = (props)=>{ global.account = account; global.version = version; - global.enable_v3 = enable_v3; - global.enable_themes = enable_themes; global.config = config; updateLocalStorage(); diff --git a/config/default.json b/config/default.json index bea3b2663..e18e90a20 100644 --- a/config/default.json +++ b/config/default.json @@ -3,8 +3,6 @@ "naturalcrit_url" : "local.naturalcrit.com:8010", "secret" : "secret", "web_port" : 8000, - "enable_v3" : true, - "enable_themes" : true, "local_environments" : ["docker", "local"], "publicUrl" : "https://homebrewery.naturalcrit.com", "hb_images" : null, diff --git a/server/app.js b/server/app.js index afba0997b..735ba0665 100644 --- a/server/app.js +++ b/server/app.js @@ -562,8 +562,6 @@ const renderPage = async (req, res)=>{ brews : req.brews, googleBrews : req.googleBrews, account : req.account, - enable_v3 : config.get('enable_v3'), - enable_themes : config.get('enable_themes'), config : configuration, ogMeta : req.ogMeta, userThemes : req.userThemes From 8f715a6615fe536e0a34581761ce4557d2e00718 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sun, 5 Oct 2025 18:36:14 -0500 Subject: [PATCH 69/95] Isolate change to Firefox --- themes/V3/Blank/style.less | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/themes/V3/Blank/style.less b/themes/V3/Blank/style.less index dec547854..c251e323b 100644 --- a/themes/V3/Blank/style.less +++ b/themes/V3/Blank/style.less @@ -145,8 +145,8 @@ body { counter-reset : page-numbers 0; } blockquote,table { z-index : 15; -webkit-column-break-inside : avoid; - page-break-inside : auto; - break-inside : auto; + page-break-inside : avoid; + break-inside : avoid; } // Nested lists ul ul,ol ol,ul ol,ol ul { @@ -611,3 +611,17 @@ h6, } .toc.wide li { break-inside : auto; } } + + +/********************************** +Firefox endruns +**********************************/ + +@supports (-moz-user-select: none) { // This section will only apply to Firefox; it's the only browser that supports `-mos-xyz...` + .page { + .blockquote, .table { + page-break-inside: auto; + break-inside: auto; + } + } +} \ No newline at end of file From 41aebf084bcee6053993b490604e10da5c3b5541 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 5 Oct 2025 21:57:19 -0400 Subject: [PATCH 70/95] Make the renderSaveButton() function common between edit/new/home Each of the edit/home/new pages renders its save button differently. This makes it a common function with all the same possible render states (does the document have unsaved changes? Is it already saved? Was it auto-saved?). - Common save button - Adds the "save" button to /home page which wasn't there before - Animates the "save" button in /home and /new when the user makes their first change to signal that yes, you do have to actually click the save button if you want to keep this. - "reminder... you haven't saved for X minutes" still not functional on /new and /home since that involves more moving pieces. --- client/homebrew/pages/editPage/editPage.jsx | 12 ++++-- client/homebrew/pages/homePage/homePage.jsx | 43 +++++++++++++++++-- client/homebrew/pages/homePage/homePage.less | 6 +++ client/homebrew/pages/newPage/newPage.jsx | 44 +++++++++++++++----- client/homebrew/pages/newPage/newPage.less | 6 +++ 5 files changed, 93 insertions(+), 18 deletions(-) diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index 3bd74b786..d4e0061b1 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -46,8 +46,8 @@ const STYLEKEY = 'HB_newPage_style'; const SNIPKEY = 'HB_newPage_snippets'; const METAKEY = 'HB_newPage_meta'; - const useLocalStorage = false; +const neverSaved = false; const EditPage = (props)=>{ props = { @@ -309,14 +309,18 @@ const EditPage = (props)=>{ // #3 - Unsaved changes exist, click to save, show SAVE NOW if(unsavedChanges) - return trySave(true)} color='blue' icon='fas fa-save'>Save Now; + return trySave(true)} color='blue' icon='fas fa-save'>save now; // #4 - No unsaved changes, autosave is ON, show AUTO-SAVED if(autoSaveEnabled) - return auto-saved.; + return auto-saved; + + // #5 - No unsaved changes, and has never been saved, hide the button + if(neverSaved) + return save now; // DEFAULT - No unsaved changes, show SAVED - return saved.; + return saved; }; const toggleAutoSave = ()=>{ diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index cfa6eb59d..fe57a9913 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -33,6 +33,7 @@ const SNIPKEY = 'homebrewery-new-snippets'; const METAKEY = 'homebrewery-new-meta'; const useLocalStorage = false; +const neverSaved = true; const HomePage =(props)=>{ props = { @@ -122,6 +123,41 @@ const HomePage =(props)=>{ } }; + const renderSaveButton = ()=>{ + // #1 - Currently saving, show SAVING + if(isSaving) + return saving...; + + // #2 - Unsaved changes exist, autosave is OFF and warning timer has expired, show AUTOSAVE WARNING + // if(unsavedChanges && warnUnsavedChanges) { + // resetWarnUnsavedTimer(); + // const elapsedTime = Math.round((new Date() - lastSavedTime) / 1000 / 60); + // const text = elapsedTime === 0 + // ? 'Autosave is OFF.' + // : `Autosave is OFF, and you haven't saved for ${elapsedTime} minutes.`; + + // return + // Reminder... + //
{text}
+ //
; + // } + + // #3 - Unsaved changes exist, click to save, show SAVE NOW + if(unsavedChanges) + return save now; + + // #4 - No unsaved changes, autosave is ON, show AUTO-SAVED + if(autoSaveEnabled) + return auto-saved; + + // #5 - No unsaved changes, and has never been saved, hide the button + if(neverSaved) + return save now; + + // DEFAULT - No unsaved changes, show SAVED + return saved; + }; + const clearError = ()=>{ setError(null); setIsSaving(false); @@ -130,10 +166,9 @@ const HomePage =(props)=>{ const renderNavbar = ()=>{ return - {error ? - : - null - } + {error + ? + : renderSaveButton()} diff --git a/client/homebrew/pages/homePage/homePage.less b/client/homebrew/pages/homePage/homePage.less index 4cf9ff4fe..c3ec1815c 100644 --- a/client/homebrew/pages/homePage/homePage.less +++ b/client/homebrew/pages/homePage/homePage.less @@ -34,7 +34,13 @@ } .navItem.save { + .fadeInRight(); + .transition(opacity); background-color : @orange; &:hover { background-color : @green; } + &.neverSaved { + .fadeOutRight(); + opacity: 0; + } } } diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index b9b628a2c..bc2b39c44 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -33,8 +33,8 @@ const METAKEY = 'HB_newPage_metadata'; const SNIPKEY = 'HB_newPage_snippets'; const SAVEKEYPREFIX = 'HB_editor_defaultSave_'; - const useLocalStorage = true; +const neverSaved = true; const NewPage = (props) => { props = { @@ -96,6 +96,7 @@ const NewPage = (props) => { const saveStorage = localStorage.getItem(SAVEKEY) || 'HOMEBREWERY'; setCurrentBrew(brew); + lastSavedBrew.current = brew; setSaveGoogle(saveStorage == 'GOOGLE-DRIVE' && saveGoogle); localStorage.setItem(BREWKEY, brew.text); @@ -169,15 +170,38 @@ const NewPage = (props) => { }; const renderSaveButton = ()=>{ - if(isSaving){ - return - save... - ; - } else { - return - save - ; - } + // #1 - Currently saving, show SAVING + if(isSaving) + return saving...; + + // #2 - Unsaved changes exist, autosave is OFF and warning timer has expired, show AUTOSAVE WARNING + // if(unsavedChanges && warnUnsavedChanges) { + // resetWarnUnsavedTimer(); + // const elapsedTime = Math.round((new Date() - lastSavedTime) / 1000 / 60); + // const text = elapsedTime === 0 + // ? 'Autosave is OFF.' + // : `Autosave is OFF, and you haven't saved for ${elapsedTime} minutes.`; + + // return + // Reminder... + //
{text}
+ //
; + // } + + // #3 - Unsaved changes exist, click to save, show SAVE NOW + if(unsavedChanges) + return save now; + + // #4 - No unsaved changes, autosave is ON, show AUTO-SAVED + if(autoSaveEnabled) + return auto-saved; + + // #5 - No unsaved changes, and has never been saved, hide the button + if(neverSaved) + return save now; + + // DEFAULT - No unsaved changes, show SAVED + return saved; }; const clearError = ()=>{ diff --git a/client/homebrew/pages/newPage/newPage.less b/client/homebrew/pages/newPage/newPage.less index ebc44d543..083e1ee09 100644 --- a/client/homebrew/pages/newPage/newPage.less +++ b/client/homebrew/pages/newPage/newPage.less @@ -1,6 +1,12 @@ .newPage { .navItem.save { + .fadeInRight(); + .transition(opacity); background-color : @orange; &:hover { background-color : @green; } + &.neverSaved { + .fadeOutRight(); + opacity: 0; + } } } From 1e71e9e18af53c0db5810baf5cba6e2e36c3e815 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 5 Oct 2025 22:19:43 -0400 Subject: [PATCH 71/95] Use blockquote and table elements, not .classes --- themes/V3/Blank/style.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/V3/Blank/style.less b/themes/V3/Blank/style.less index c251e323b..9d41181e9 100644 --- a/themes/V3/Blank/style.less +++ b/themes/V3/Blank/style.less @@ -619,7 +619,7 @@ Firefox endruns @supports (-moz-user-select: none) { // This section will only apply to Firefox; it's the only browser that supports `-mos-xyz...` .page { - .blockquote, .table { + blockquote, table { page-break-inside: auto; break-inside: auto; } From 5395412ac50ce1587a05f94ea1bf0dabee7fbf0f Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 5 Oct 2025 23:24:35 -0400 Subject: [PATCH 72/95] Remove tests for `getLocalStorageMap()` The function is a simple getter with trivial logic; test is effectively just asserting the size of the map, which coverage adds no meaningful value and adds cruft to the codebase. --- .../localStorageKeyMap.spec.js | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 client/homebrew/utils/updateLocalStorage/localStorageKeyMap.spec.js diff --git a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.spec.js b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.spec.js deleted file mode 100644 index ac61d4add..000000000 --- a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.spec.js +++ /dev/null @@ -1,30 +0,0 @@ -import getLocalStorageMap from './localStorageKeyMap.js'; - -describe('getLocalStorageMap', ()=>{ - it('no username', ()=>{ - const account = global.account; - - delete global.account; - - const map = getLocalStorageMap(); - - global.account = account; - - expect(map).toBeInstanceOf(Object); - expect(Object.entries(map)).toHaveLength(16); - }); - - it('no username', ()=>{ - const account = global.account; - - global.account = { username: 'test' }; - - const map = getLocalStorageMap(); - - global.account = account; - - expect(map).toBeInstanceOf(Object); - expect(Object.entries(map)).toHaveLength(17); - expect(map).toHaveProperty('HOMEBREWERY-DEFAULT-SAVE-LOCATION-test', 'HB_editor_defaultSave_test'); - }); -}); \ No newline at end of file From 643e0ac6505765bae2de9117e48a23ad981bda00 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Sun, 5 Oct 2025 23:24:50 -0400 Subject: [PATCH 73/95] small cleanups of localstorage keys code --- client/homebrew/utils/updateLocalStorage/localStorageKeyMap.js | 2 +- .../utils/updateLocalStorage/updateLocalStorageKeys.js | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.js b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.js index b4a05974f..f6e01c54f 100644 --- a/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.js +++ b/client/homebrew/utils/updateLocalStorage/localStorageKeyMap.js @@ -26,7 +26,7 @@ const getLocalStorageMap = function(){ if(global?.account?.username){ const username = global.account.username; - localStorageMap[`HOMEBREWERY-DEFAULT-SAVE-LOCATION-${username}`] = `HB_editor_defaultSave_${username}`; + localStorageMap[`HOMEBREWERY-DEFAULT-SAVE-LOCATION-${username}`] = `HB_editor_defaultSave_${username}`; } return localStorageMap; diff --git a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js index 1a8231f73..912c4297b 100644 --- a/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js +++ b/client/homebrew/utils/updateLocalStorage/updateLocalStorageKeys.js @@ -4,10 +4,7 @@ const updateLocalStorage = function(){ // Return if no window and thus no local storage if(typeof window === 'undefined') return; - // Return if the local storage key map has no content const localStorageKeyMap = getLocalStorageMap(); - if(Object.keys(localStorageKeyMap).length == 0) return; - const storage = window.localStorage; Object.keys(localStorageKeyMap).forEach((key)=>{ From 63bebe1efd9b21d441d57f01618f1bc9525ca91f Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 6 Oct 2025 00:02:24 -0400 Subject: [PATCH 74/95] Lint everything Catching up on a bunch of linting so random changes stop showing up on PRs when the linter is run. --- .../editor/metadataEditor/validations.js | 2 +- client/homebrew/navbar/error-navitem.jsx | 6 ++-- client/homebrew/navbar/newbrew.navitem.jsx | 4 +-- client/homebrew/navbar/share.navitem.jsx | 20 ++++++------- client/homebrew/pages/editPage/editPage.jsx | 8 ++--- client/homebrew/pages/homePage/homePage.jsx | 16 +++++----- client/homebrew/pages/newPage/newPage.jsx | 30 +++++++++---------- server/homebrew.api.js | 10 +++---- shared/helpers.js | 20 ++++++------- shared/naturalcrit/markdown.js | 4 +-- shared/naturalcrit/markdownLegacy.js | 4 +-- 11 files changed, 62 insertions(+), 62 deletions(-) diff --git a/client/homebrew/editor/metadataEditor/validations.js b/client/homebrew/editor/metadataEditor/validations.js index 858fca6c4..d0e052b07 100644 --- a/client/homebrew/editor/metadataEditor/validations.js +++ b/client/homebrew/editor/metadataEditor/validations.js @@ -18,7 +18,7 @@ module.exports = { try { Boolean(new URL(value)); return null; - } catch (e) { + } catch { return 'Must be a valid URL'; } } diff --git a/client/homebrew/navbar/error-navitem.jsx b/client/homebrew/navbar/error-navitem.jsx index 6d9bec444..0271224b7 100644 --- a/client/homebrew/navbar/error-navitem.jsx +++ b/client/homebrew/navbar/error-navitem.jsx @@ -2,9 +2,9 @@ require('./error-navitem.less'); const React = require('react'); const Nav = require('naturalcrit/nav/nav.jsx'); -const ErrorNavItem = ({error = '', clearError})=>{ +const ErrorNavItem = ({ error = '', clearError })=>{ const response = error.response; - const errorCode = error.code + const errorCode = error.code; const status = response?.status; const HBErrorCode = response?.body?.HBErrorCode; const message = response?.body?.message; @@ -15,7 +15,7 @@ const ErrorNavItem = ({error = '', clearError})=>{ errMsg += `\`\`\`\n${error.stack}\n`; errMsg += `${JSON.stringify(response?.error, null, ' ')}\n\`\`\``; console.log(errMsg); - } catch (e){} + } catch {} if(status === 409) { return diff --git a/client/homebrew/navbar/newbrew.navitem.jsx b/client/homebrew/navbar/newbrew.navitem.jsx index ccade4e8b..d19b7595f 100644 --- a/client/homebrew/navbar/newbrew.navitem.jsx +++ b/client/homebrew/navbar/newbrew.navitem.jsx @@ -34,8 +34,8 @@ const NewBrew = ()=>{ } const type = file.name.split('.').pop().toLowerCase(); - - alert(`This file is invalid: ${!type ? "Missing file extension" :`.${type} files are not supported`}. Only .txt files exported from the Homebrewery are allowed.`); + + alert(`This file is invalid: ${!type ? 'Missing file extension' :`.${type} files are not supported`}. Only .txt files exported from the Homebrewery are allowed.`); console.log(file); diff --git a/client/homebrew/navbar/share.navitem.jsx b/client/homebrew/navbar/share.navitem.jsx index a08ac6878..0cd1a52b7 100644 --- a/client/homebrew/navbar/share.navitem.jsx +++ b/client/homebrew/navbar/share.navitem.jsx @@ -2,22 +2,22 @@ import React from 'react'; import dedent from 'dedent-tabs'; import Nav from 'naturalcrit/nav/nav.jsx'; - const getShareId = (brew)=>( - brew.googleId && !brew.stubbed - ? brew.googleId + brew.shareId - : brew.shareId - ); +const getShareId = (brew)=>( + brew.googleId && !brew.stubbed + ? brew.googleId + brew.shareId + : brew.shareId +); - const getRedditLink = (brew)=>{ - const text = dedent` +const getRedditLink = (brew)=>{ + const text = dedent` Hey guys! I've been working on this homebrew. I'd love your feedback. Check it out. **[Homebrewery Link](${global.config.baseUrl}/share/${getShareId(brew)})**`; - return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(brew.title.toWellFormed())}&text=${encodeURIComponent(text)}`; - }; + return `https://www.reddit.com/r/UnearthedArcana/submit?title=${encodeURIComponent(brew.title.toWellFormed())}&text=${encodeURIComponent(text)}`; +}; -export default ({brew}) => ( +export default ({ brew })=>( share diff --git a/client/homebrew/pages/editPage/editPage.jsx b/client/homebrew/pages/editPage/editPage.jsx index d4e0061b1..524f31ac9 100644 --- a/client/homebrew/pages/editPage/editPage.jsx +++ b/client/homebrew/pages/editPage/editPage.jsx @@ -123,16 +123,16 @@ const EditPage = (props)=>{ editorRef.current?.update(); }; - const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' - if (subfield == 'renderer' || subfield == 'theme') + const handleBrewChange = (field)=>(value, subfield)=>{ //'text', 'style', 'snippets', 'metadata' + if(subfield == 'renderer' || subfield == 'theme') fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); //If there are HTML errors, run the validator on every change to give quick feedback if(HTMLErrors.length && (field == 'text' || field == 'snippets')) setHTMLErrors(Markdown.validate(value)); - if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); - else setCurrentBrew(prev => ({ ...prev, [field]: value })); + if(field == 'metadata') setCurrentBrew((prev)=>({ ...prev, ...value })); + else setCurrentBrew((prev)=>({ ...prev, [field]: value })); if(useLocalStorage) { if(field == 'text') localStorage.setItem(BREWKEY, value); diff --git a/client/homebrew/pages/homePage/homePage.jsx b/client/homebrew/pages/homePage/homePage.jsx index fe57a9913..82c5b7084 100644 --- a/client/homebrew/pages/homePage/homePage.jsx +++ b/client/homebrew/pages/homePage/homePage.jsx @@ -39,8 +39,8 @@ const HomePage =(props)=>{ props = { brew : DEFAULT_BREW, ver : '0.0.0', - ...props - }; + ...props + }; const [currentBrew , setCurrentBrew] = useState(props.brew); const [error , setError] = useState(undefined); @@ -71,7 +71,7 @@ const HomePage =(props)=>{ document.addEventListener('keydown', handleControlKeys); - return () => { + return ()=>{ document.removeEventListener('keydown', handleControlKeys); }; }, []); @@ -100,16 +100,16 @@ const HomePage =(props)=>{ editorRef.current.update(); }; - const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' - if (subfield == 'renderer' || subfield == 'theme') + const handleBrewChange = (field)=>(value, subfield)=>{ //'text', 'style', 'snippets', 'metadata' + if(subfield == 'renderer' || subfield == 'theme') fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); //If there are HTML errors, run the validator on every change to give quick feedback if(HTMLErrors.length && (field == 'text' || field == 'snippets')) setHTMLErrors(Markdown.validate(value)); - if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); - else setCurrentBrew(prev => ({ ...prev, [field]: value })); + if(field == 'metadata') setCurrentBrew((prev)=>({ ...prev, ...value })); + else setCurrentBrew((prev)=>({ ...prev, [field]: value })); if(useLocalStorage) { if(field == 'text') localStorage.setItem(BREWKEY, value); @@ -218,7 +218,7 @@ const HomePage =(props)=>{ Create your own
- ) + ); }; module.exports = HomePage; diff --git a/client/homebrew/pages/newPage/newPage.jsx b/client/homebrew/pages/newPage/newPage.jsx index bc2b39c44..dccf7deb7 100644 --- a/client/homebrew/pages/newPage/newPage.jsx +++ b/client/homebrew/pages/newPage/newPage.jsx @@ -36,9 +36,9 @@ const SAVEKEYPREFIX = 'HB_editor_defaultSave_'; const useLocalStorage = true; const neverSaved = true; -const NewPage = (props) => { +const NewPage = (props)=>{ props = { - brew: DEFAULT_BREW, + brew : DEFAULT_BREW, ...props }; @@ -57,7 +57,7 @@ const NewPage = (props) => { const editorRef = useRef(null); const lastSavedBrew = useRef(_.cloneDeep(props.brew)); - useEffect(() => { + useEffect(()=>{ loadBrew(); fetchThemeBundle(setError, setThemeBundle, currentBrew.renderer, currentBrew.theme); @@ -73,7 +73,7 @@ const NewPage = (props) => { document.addEventListener('keydown', handleControlKeys); - return () => { + return ()=>{ document.removeEventListener('keydown', handleControlKeys); }; }, []); @@ -118,16 +118,16 @@ const NewPage = (props) => { editorRef.current.update(); }; - const handleBrewChange = (field) => (value, subfield) => { //'text', 'style', 'snippets', 'metadata' - if (subfield == 'renderer' || subfield == 'theme') + const handleBrewChange = (field)=>(value, subfield)=>{ //'text', 'style', 'snippets', 'metadata' + if(subfield == 'renderer' || subfield == 'theme') fetchThemeBundle(setError, setThemeBundle, value.renderer, value.theme); //If there are HTML errors, run the validator on every change to give quick feedback if(HTMLErrors.length && (field == 'text' || field == 'snippets')) setHTMLErrors(Markdown.validate(value)); - if(field == 'metadata') setCurrentBrew(prev => ({ ...prev, ...value })); - else setCurrentBrew(prev => ({ ...prev, [field]: value })); + if(field == 'metadata') setCurrentBrew((prev)=>({ ...prev, ...value })); + else setCurrentBrew((prev)=>({ ...prev, [field]: value })); if(useLocalStorage) { if(field == 'text') localStorage.setItem(BREWKEY, value); @@ -141,10 +141,10 @@ const NewPage = (props) => { } }; - const save = async () => { + const save = async ()=>{ setIsSaving(true); - let updatedBrew = { ...currentBrew }; + const updatedBrew = { ...currentBrew }; splitTextStyleAndMetadata(updatedBrew); const pageRegex = updatedBrew.renderer === 'legacy' ? /\\page/g : /^\\page$/gm; @@ -153,13 +153,13 @@ const NewPage = (props) => { const res = await request .post(`/api${saveGoogle ? '?saveToGoogle=true' : ''}`) .send(updatedBrew) - .catch((err) => { + .catch((err)=>{ setIsSaving(false); setError(err); }); - setIsSaving(false) - if (!res) return; + setIsSaving(false); + if(!res) return; const savedBrew = res.body; @@ -209,7 +209,7 @@ const NewPage = (props) => { setIsSaving(false); }; - const renderNavbar = () => ( + const renderNavbar = ()=>( {currentBrew.title} @@ -230,7 +230,7 @@ const NewPage = (props) => { ); return ( -
+
{renderNavbar()}
diff --git a/server/homebrew.api.js b/server/homebrew.api.js index 3221638ab..049dac1ce 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -8,9 +8,9 @@ import Markdown from '../shared/naturalcrit/markdown.js'; import yaml from 'js-yaml'; import asyncHandler from 'express-async-handler'; import { nanoid } from 'nanoid'; -import {makePatches, applyPatches, stringifyPatches, parsePatch} from '@sanity/diff-match-patch'; +import { makePatches, applyPatches, stringifyPatches, parsePatch } from '@sanity/diff-match-patch'; import { md5 } from 'hash-wasm'; -import { splitTextStyleAndMetadata, +import { splitTextStyleAndMetadata, brewSnippetsToJSON, debugTextMismatch } from '../shared/helpers.js'; import checkClientVersion from './middleware/check-client-version.js'; @@ -377,14 +377,14 @@ const api = { // Patch to a throwaway variable while parallelizing - we're more concerned with error/no error. const patchedResult = decodeURI(applyPatches(patches, encodeURI(brewFromServer.text))[0]); if(patchedResult != brewFromClient.text) - throw("Patches did not apply cleanly, text mismatch detected"); + throw ('Patches did not apply cleanly, text mismatch detected'); // brew.text = applyPatches(patches, brewFromServer.text)[0]; } catch (err) { //debugTextMismatch(brewFromClient.text, brewFromServer.text, `edit/${brewFromClient.editId}`); console.error('Failed to apply patches:', { //patches : brewFromClient.patches, - brewId : brewFromClient.editId || 'unknown', - error : err + brewId : brewFromClient.editId || 'unknown', + error : err }); // While running in parallel, don't throw the error upstream. // throw err; // rethrow to preserve the 500 behavior diff --git a/shared/helpers.js b/shared/helpers.js index 3f91583d6..adf5b889a 100644 --- a/shared/helpers.js +++ b/shared/helpers.js @@ -8,7 +8,7 @@ const brewSnippetsToJSON = (menuTitle, userBrewSnippets, themeBundleSnippets=nul const mpAsSnippets = []; // Snippets from Themes first. if(themeBundleSnippets) { - for (let themes of themeBundleSnippets) { + for (const themes of themeBundleSnippets) { if(typeof themes !== 'string') { const userSnippets = []; const snipSplit = themes.snippets.trim().split(textSplit).slice(1); @@ -76,9 +76,9 @@ const yamlSnippetsToText = (yamlObj)=>{ if(typeof yamlObj == 'string') return yamlObj; let snippetsText = ''; - - for (let snippet of yamlObj) { - for (let subSnippet of snippet.subsnippets) { + + for (const snippet of yamlObj) { + for (const subSnippet of snippet.subsnippets) { snippetsText = `${snippetsText}\\snippet ${subSnippet.name}\n${subSnippet.gen || ''}\n`; } } @@ -121,7 +121,7 @@ const fetchThemeBundle = async (setError, setThemeBundle, renderer, theme)=>{ const res = await request .get(`/api/theme/${renderer}/${theme}`) .catch((err)=>{ - setError(err) + setError(err); }); if(!res) { setThemeBundle({}); @@ -133,14 +133,14 @@ const fetchThemeBundle = async (setError, setThemeBundle, renderer, theme)=>{ setError(null); }; -const debugTextMismatch = (clientTextRaw, serverTextRaw, label) => { +const debugTextMismatch = (clientTextRaw, serverTextRaw, label)=>{ const clientText = clientTextRaw?.normalize('NFC') || ''; const serverText = serverTextRaw?.normalize('NFC') || ''; const clientBuffer = Buffer.from(clientText, 'utf8'); const serverBuffer = Buffer.from(serverText, 'utf8'); - if (clientBuffer.equals(serverBuffer)) { + if(clientBuffer.equals(serverBuffer)) { console.log(`✅ ${label} text matches byte-for-byte.`); return; } @@ -151,7 +151,7 @@ const debugTextMismatch = (clientTextRaw, serverTextRaw, label) => { // Byte-level diff for (let i = 0; i < Math.min(clientBuffer.length, serverBuffer.length); i++) { - if (clientBuffer[i] !== serverBuffer[i]) { + if(clientBuffer[i] !== serverBuffer[i]) { console.log(`Byte mismatch at offset ${i}: client=0x${clientBuffer[i].toString(16)} server=0x${serverBuffer[i].toString(16)}`); break; } @@ -159,14 +159,14 @@ const debugTextMismatch = (clientTextRaw, serverTextRaw, label) => { // Char-level diff for (let i = 0; i < Math.min(clientText.length, serverText.length); i++) { - if (clientText[i] !== serverText[i]) { + if(clientText[i] !== serverText[i]) { console.log(`Char mismatch at index ${i}:`); console.log(` Client: '${clientText[i]}' (U+${clientText.charCodeAt(i).toString(16).toUpperCase()})`); console.log(` Server: '${serverText[i]}' (U+${serverText.charCodeAt(i).toString(16).toUpperCase()})`); break; } } -} +}; export { splitTextStyleAndMetadata, diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index 78107dcf4..b0b44a079 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -435,7 +435,7 @@ const replaceVar = function(input, hoist=false, allowUnresolved=false) { try { return mathParser.evaluate(replacedLabel); - } catch (error) { + } catch { return undefined; // Return undefined if invalid math result } } @@ -680,7 +680,7 @@ const tableTerminators = [ Marked.use(MarkedVariables()); Marked.use(MarkedDefinitionLists()); -Marked.use({ extensions : [forcedParagraphBreaks, mustacheSpans, mustacheDivs, mustacheInjectInline] }); +Marked.use({ extensions: [forcedParagraphBreaks, mustacheSpans, mustacheDivs, mustacheInjectInline] }); Marked.use(mustacheInjectBlock); Marked.use(MarkedAlignedParagraphs()); Marked.use(MarkedSubSuperText()); diff --git a/shared/naturalcrit/markdownLegacy.js b/shared/naturalcrit/markdownLegacy.js index a6a37d639..5a8108297 100644 --- a/shared/naturalcrit/markdownLegacy.js +++ b/shared/naturalcrit/markdownLegacy.js @@ -49,7 +49,7 @@ const cleanUrl = function (sanitize, base, href) { prot = decodeURIComponent(unescape(href)) .replace(nonWordAndColonTest, '') .toLowerCase(); - } catch (e) { + } catch { return null; } if(prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) { @@ -58,7 +58,7 @@ const cleanUrl = function (sanitize, base, href) { } try { href = encodeURI(href).replace(/%25/g, '%'); - } catch (e) { + } catch { return null; } return href; From 811f27496813cdc75064b8e1f6e308c3118b866c Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 6 Oct 2025 00:06:34 -0400 Subject: [PATCH 75/95] Move badly-placed scrollingTimeout that was doing nothing When a user clicks brewJump or sourceJump, we disallow new jumps until the current scroll operation has finished for 150 ms. Unfortunately the timer being checked was always undefined, so you could keep clicking the jump button and get the brewRenderer or editor to keep bouncing around without finishing the jump action. This just moves the scrollingTimeout up outside of the listener function so it isn't being reset to undefined every loop. --- client/homebrew/editor/editor.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index a067ac4af..8b7f6ccf5 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -325,10 +325,10 @@ const Editor = createClass({ const brewRenderer = window.frames['BrewRenderer'].contentDocument.getElementsByClassName('brewRenderer')[0]; const currentPos = brewRenderer.scrollTop; const targetPos = window.frames['BrewRenderer'].contentDocument.getElementById(`p${targetPage}`).getBoundingClientRect().top; - - const checkIfScrollComplete = ()=>{ - let scrollingTimeout; - clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs + + let scrollingTimeout; + const checkIfScrollComplete = ()=>{ // Prevent interrupting a scroll in progress if user clicks multiple times + clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs scrollingTimeout = setTimeout(()=>{ isJumping = false; brewRenderer.removeEventListener('scroll', checkIfScrollComplete); @@ -369,8 +369,8 @@ const Editor = createClass({ let currentY = this.codeEditor.current.codeMirror.getScrollInfo().top; let targetY = this.codeEditor.current.codeMirror.heightAtLine(targetLine, 'local', true); - const checkIfScrollComplete = ()=>{ - let scrollingTimeout; + let scrollingTimeout; + const checkIfScrollComplete = ()=>{ // Prevent interrupting a scroll in progress if user clicks multiple times clearTimeout(scrollingTimeout); // Reset the timer every time a scroll event occurs scrollingTimeout = setTimeout(()=>{ isJumping = false; From 0d38b8607e1e4735bf426402c7f6525b521ad5b2 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Mon, 6 Oct 2025 18:51:05 +1300 Subject: [PATCH 76/95] Shift to router.use(dbCheck) instead of defining on every route --- server/homebrew.api.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/server/homebrew.api.js b/server/homebrew.api.js index fc1a4c70e..c931cb657 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -531,11 +531,13 @@ const api = { } }; -router.post('/api', checkClientVersion, dbCheck, asyncHandler(api.newBrew)); -router.put('/api/:id', checkClientVersion, dbCheck, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew)); -router.put('/api/update/:id', checkClientVersion, dbCheck, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew)); -router.delete('/api/:id', checkClientVersion, dbCheck, asyncHandler(api.deleteBrew)); -router.get('/api/remove/:id', checkClientVersion, dbCheck, asyncHandler(api.deleteBrew)); -router.get('/api/theme/:renderer/:id', dbCheck, asyncHandler(api.getThemeBundle)); +router.use(dbCheck); + +router.post('/api', checkClientVersion, asyncHandler(api.newBrew)); +router.put('/api/:id', checkClientVersion, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew)); +router.put('/api/update/:id', checkClientVersion, asyncHandler(api.getBrew('edit', false)), asyncHandler(api.updateBrew)); +router.delete('/api/:id', checkClientVersion, asyncHandler(api.deleteBrew)); +router.get('/api/remove/:id', checkClientVersion, asyncHandler(api.deleteBrew)); +router.get('/api/theme/:renderer/:id', asyncHandler(api.getThemeBundle)); export default api; From 4ccec08f21988312e6d4fcd58acea0f43c56366c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 03:01:39 +0000 Subject: [PATCH 77/95] Bump the dev-dependencies group across 1 directory with 4 updates Bumps the dev-dependencies group with 4 updates in the / directory: [eslint](https://github.com/eslint/eslint), [globals](https://github.com/sindresorhus/globals), [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest) and [stylelint](https://github.com/stylelint/stylelint). Updates `eslint` from 9.35.0 to 9.37.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v9.35.0...v9.37.0) Updates `globals` from 16.3.0 to 16.4.0 - [Release notes](https://github.com/sindresorhus/globals/releases) - [Commits](https://github.com/sindresorhus/globals/compare/v16.3.0...v16.4.0) Updates `jest` from 30.1.3 to 30.2.0 - [Release notes](https://github.com/jestjs/jest/releases) - [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/jestjs/jest/commits/v30.2.0/packages/jest) Updates `stylelint` from 16.24.0 to 16.25.0 - [Release notes](https://github.com/stylelint/stylelint/releases) - [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md) - [Commits](https://github.com/stylelint/stylelint/compare/16.24.0...16.25.0) --- updated-dependencies: - dependency-name: eslint dependency-version: 9.37.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: globals dependency-version: 16.4.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: jest dependency-version: 30.2.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies - dependency-name: stylelint dependency-version: 16.25.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] --- package-lock.json | 722 +++++++++++++++++++++++----------------------- package.json | 8 +- 2 files changed, 368 insertions(+), 362 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb815cdc6..ee762f8f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,15 +65,15 @@ "devDependencies": { "@stylistic/stylelint-plugin": "^4.0.0", "babel-plugin-transform-import-meta": "^2.3.3", - "eslint": "^9.35.0", + "eslint": "^9.37.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-react": "^7.37.5", - "globals": "^16.3.0", - "jest": "^30.1.3", + "globals": "^16.4.0", + "jest": "^30.2.0", "jest-expect-message": "^1.1.3", "jsdom-global": "^3.0.2", "postcss-less": "^6.0.0", - "stylelint": "^16.24.0", + "stylelint": "^16.25.0", "stylelint-config-recess-order": "^7.3.0", "stylelint-config-recommended": "^17.0.0", "supertest": "^7.1.4" @@ -1915,14 +1915,14 @@ "license": "Apache-2.0" }, "node_modules/@dual-bundle/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.2.1.tgz", + "integrity": "sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==", "dev": true, "license": "MIT", "funding": { "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/JounQin" } }, "node_modules/@emnapi/core": { @@ -2026,19 +2026,22 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz", + "integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/core": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2086,9 +2089,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz", - "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz", + "integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==", "dev": true, "license": "MIT", "engines": { @@ -2108,13 +2111,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.2", + "@eslint/core": "^0.16.0", "levn": "^0.4.1" }, "engines": { @@ -2214,9 +2217,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", - "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { @@ -2227,9 +2230,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", "engines": { @@ -2265,9 +2268,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { @@ -2416,17 +2419,17 @@ } }, "node_modules/@jest/console": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.1.2.tgz", - "integrity": "sha512-BGMAxj8VRmoD0MoA/jo9alMXSRoqW8KPeqOfEo1ncxnRLatTBCpRoOwlwlEMdudp68Q6WSGwYrrLtTGOh8fLzw==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", + "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.5", + "@jest/types": "30.2.0", "@types/node": "*", "chalk": "^4.1.2", - "jest-message-util": "30.1.0", - "jest-util": "30.0.5", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", "slash": "^3.0.0" }, "engines": { @@ -2434,39 +2437,39 @@ } }, "node_modules/@jest/core": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.1.3.tgz", - "integrity": "sha512-LIQz7NEDDO1+eyOA2ZmkiAyYvZuo6s1UxD/e2IHldR6D7UYogVq3arTmli07MkENLq6/3JEQjp0mA8rrHHJ8KQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", + "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.1.2", + "@jest/console": "30.2.0", "@jest/pattern": "30.0.1", - "@jest/reporters": "30.1.3", - "@jest/test-result": "30.1.3", - "@jest/transform": "30.1.2", - "@jest/types": "30.0.5", + "@jest/reporters": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "ci-info": "^4.2.0", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", - "jest-changed-files": "30.0.5", - "jest-config": "30.1.3", - "jest-haste-map": "30.1.0", - "jest-message-util": "30.1.0", + "jest-changed-files": "30.2.0", + "jest-config": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.1.3", - "jest-resolve-dependencies": "30.1.3", - "jest-runner": "30.1.3", - "jest-runtime": "30.1.3", - "jest-snapshot": "30.1.2", - "jest-util": "30.0.5", - "jest-validate": "30.1.0", - "jest-watcher": "30.1.3", + "jest-resolve": "30.2.0", + "jest-resolve-dependencies": "30.2.0", + "jest-runner": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "jest-watcher": "30.2.0", "micromatch": "^4.0.8", - "pretty-format": "30.0.5", + "pretty-format": "30.2.0", "slash": "^3.0.0" }, "engines": { @@ -2492,39 +2495,39 @@ } }, "node_modules/@jest/environment": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.1.2.tgz", - "integrity": "sha512-N8t1Ytw4/mr9uN28OnVf0SYE2dGhaIxOVYcwsf9IInBKjvofAjbFRvedvBBlyTYk2knbJTiEjEJ2PyyDIBnd9w==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", + "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.1.2", - "@jest/types": "30.0.5", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", "@types/node": "*", - "jest-mock": "30.0.5" + "jest-mock": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.1.2.tgz", - "integrity": "sha512-tyaIExOwQRCxPCGNC05lIjWJztDwk2gPDNSDGg1zitXJJ8dC3++G/CRjE5mb2wQsf89+lsgAgqxxNpDLiCViTA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", "dev": true, "license": "MIT", "dependencies": { - "expect": "30.1.2", - "jest-snapshot": "30.1.2" + "expect": "30.2.0", + "jest-snapshot": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.1.2.tgz", - "integrity": "sha512-HXy1qT/bfdjCv7iC336ExbqqYtZvljrV8odNdso7dWK9bSeHtLlvwWWC3YSybSPL03Gg5rug6WLCZAZFH72m0A==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", "dev": true, "license": "MIT", "dependencies": { @@ -2535,18 +2538,18 @@ } }, "node_modules/@jest/fake-timers": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.1.2.tgz", - "integrity": "sha512-Beljfv9AYkr9K+ETX9tvV61rJTY706BhBUtiaepQHeEGfe0DbpvUA5Z3fomwc5Xkhns6NWrcFDZn+72fLieUnA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", + "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.5", + "@jest/types": "30.2.0", "@sinonjs/fake-timers": "^13.0.0", "@types/node": "*", - "jest-message-util": "30.1.0", - "jest-mock": "30.0.5", - "jest-util": "30.0.5" + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -2563,16 +2566,16 @@ } }, "node_modules/@jest/globals": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.1.2.tgz", - "integrity": "sha512-teNTPZ8yZe3ahbYnvnVRDeOjr+3pu2uiAtNtrEsiMjVPPj+cXd5E/fr8BL7v/T7F31vYdEHrI5cC/2OoO/vM9A==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", + "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.1.2", - "@jest/expect": "30.1.2", - "@jest/types": "30.0.5", - "jest-mock": "30.0.5" + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/types": "30.2.0", + "jest-mock": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -2593,17 +2596,17 @@ } }, "node_modules/@jest/reporters": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.1.3.tgz", - "integrity": "sha512-VWEQmJWfXMOrzdFEOyGjUEOuVXllgZsoPtEHZzfdNz18RmzJ5nlR6kp8hDdY8dDS1yGOXAY7DHT+AOHIPSBV0w==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", + "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", "dev": true, "license": "MIT", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "30.1.2", - "@jest/test-result": "30.1.3", - "@jest/transform": "30.1.2", - "@jest/types": "30.0.5", + "@jest/console": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", "@jridgewell/trace-mapping": "^0.3.25", "@types/node": "*", "chalk": "^4.1.2", @@ -2616,9 +2619,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^5.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "30.1.0", - "jest-util": "30.0.5", - "jest-worker": "30.1.0", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", "slash": "^3.0.0", "string-length": "^4.0.2", "v8-to-istanbul": "^9.0.1" @@ -2696,13 +2699,13 @@ } }, "node_modules/@jest/snapshot-utils": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.1.2.tgz", - "integrity": "sha512-vHoMTpimcPSR7OxS2S0V1Cpg8eKDRxucHjoWl5u4RQcnxqQrV3avETiFpl8etn4dqxEGarBeHbIBety/f8mLXw==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", + "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.5", + "@jest/types": "30.2.0", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "natural-compare": "^1.4.0" @@ -2727,14 +2730,14 @@ } }, "node_modules/@jest/test-result": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.1.3.tgz", - "integrity": "sha512-P9IV8T24D43cNRANPPokn7tZh0FAFnYS2HIfi5vK18CjRkTDR9Y3e1BoEcAJnl4ghZZF4Ecda4M/k41QkvurEQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", + "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.1.2", - "@jest/types": "30.0.5", + "@jest/console": "30.2.0", + "@jest/types": "30.2.0", "@types/istanbul-lib-coverage": "^2.0.6", "collect-v8-coverage": "^1.0.2" }, @@ -2743,15 +2746,15 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.1.3.tgz", - "integrity": "sha512-82J+hzC0qeQIiiZDThh+YUadvshdBswi5nuyXlEmXzrhw5ZQSRHeQ5LpVMD/xc8B3wPePvs6VMzHnntxL+4E3w==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", + "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.1.3", + "@jest/test-result": "30.2.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.1.0", + "jest-haste-map": "30.2.0", "slash": "^3.0.0" }, "engines": { @@ -2759,23 +2762,23 @@ } }, "node_modules/@jest/transform": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.1.2.tgz", - "integrity": "sha512-UYYFGifSgfjujf1Cbd3iU/IQoSd6uwsj8XHj5DSDf5ERDcWMdJOPTkHWXj4U+Z/uMagyOQZ6Vne8C4nRIrCxqA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", + "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", - "@jest/types": "30.0.5", + "@jest/types": "30.2.0", "@jridgewell/trace-mapping": "^0.3.25", - "babel-plugin-istanbul": "^7.0.0", + "babel-plugin-istanbul": "^7.0.1", "chalk": "^4.1.2", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.1.0", + "jest-haste-map": "30.2.0", "jest-regex-util": "30.0.1", - "jest-util": "30.0.5", + "jest-util": "30.2.0", "micromatch": "^4.0.8", "pirates": "^4.0.7", "slash": "^3.0.0", @@ -2786,9 +2789,9 @@ } }, "node_modules/@jest/types": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.5.tgz", - "integrity": "sha512-aREYa3aku9SSnea4aX6bhKn4bgv3AXkgijoQgbYV3yvbiGt6z+MQ85+6mIhx9DsKW2BuB/cLR/A+tcMThx+KLQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", "dev": true, "license": "MIT", "dependencies": { @@ -3007,9 +3010,9 @@ } }, "node_modules/@tybys/wasm-util": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", - "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", "dev": true, "license": "MIT", "optional": true, @@ -3111,13 +3114,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", - "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", + "version": "24.7.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.7.0.tgz", + "integrity": "sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.10.0" + "undici-types": "~7.14.0" } }, "node_modules/@types/stack-utils": { @@ -4045,16 +4048,16 @@ } }, "node_modules/babel-jest": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.1.2.tgz", - "integrity": "sha512-IQCus1rt9kaSh7PQxLYRY5NmkNrNlU2TpabzwV7T2jljnpdHOcmnYYv8QmE04Li4S3a2Lj8/yXyET5pBarPr6g==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz", + "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/transform": "30.1.2", + "@jest/transform": "30.2.0", "@types/babel__core": "^7.20.5", - "babel-plugin-istanbul": "^7.0.0", - "babel-preset-jest": "30.0.1", + "babel-plugin-istanbul": "^7.0.1", + "babel-preset-jest": "30.2.0", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "slash": "^3.0.0" @@ -4063,15 +4066,18 @@ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, "peerDependencies": { - "@babel/core": "^7.11.0" + "@babel/core": "^7.11.0 || ^8.0.0-0" } }, "node_modules/babel-plugin-istanbul": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", - "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", "dev": true, "license": "BSD-3-Clause", + "workspaces": [ + "test/babel-8" + ], "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -4084,14 +4090,12 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.1.tgz", - "integrity": "sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz", + "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3", "@types/babel__core": "^7.20.5" }, "engines": { @@ -4182,20 +4186,20 @@ } }, "node_modules/babel-preset-jest": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.0.1.tgz", - "integrity": "sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz", + "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", "dev": true, "license": "MIT", "dependencies": { - "babel-plugin-jest-hoist": "30.0.1", - "babel-preset-current-node-syntax": "^1.1.0" + "babel-plugin-jest-hoist": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, "peerDependencies": { - "@babel/core": "^7.11.0" + "@babel/core": "^7.11.0 || ^8.0.0-beta.1" } }, "node_modules/balanced-match": { @@ -4851,9 +4855,9 @@ } }, "node_modules/ci-info": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", - "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", "dev": true, "funding": [ { @@ -5477,9 +5481,10 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -5510,9 +5515,9 @@ } }, "node_modules/dedent": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", - "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -6065,20 +6070,20 @@ } }, "node_modules/eslint": { - "version": "9.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz", - "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==", + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz", + "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.1", - "@eslint/core": "^0.15.2", + "@eslint/config-helpers": "^0.4.0", + "@eslint/core": "^0.16.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.35.0", - "@eslint/plugin-kit": "^0.3.5", + "@eslint/js": "9.37.0", + "@eslint/plugin-kit": "^0.4.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -6451,18 +6456,18 @@ "license": "MIT" }, "node_modules/expect": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.1.2.tgz", - "integrity": "sha512-xvHszRavo28ejws8FpemjhwswGj4w/BetHIL8cU49u4sGyXDw2+p3YbeDbj6xzlxi6kWTjIRSTJ+9sNXPnF0Zg==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.1.2", + "@jest/expect-utils": "30.2.0", "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.1.2", - "jest-message-util": "30.1.0", - "jest-mock": "30.0.5", - "jest-util": "30.0.5" + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -7293,10 +7298,11 @@ } }, "node_modules/globals": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", - "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -8611,16 +8617,16 @@ } }, "node_modules/jest": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-30.1.3.tgz", - "integrity": "sha512-Ry+p2+NLk6u8Agh5yVqELfUJvRfV51hhVBRIB5yZPY7mU0DGBmOuFG5GebZbMbm86cdQNK0fhJuDX8/1YorISQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", + "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.1.3", - "@jest/types": "30.0.5", + "@jest/core": "30.2.0", + "@jest/types": "30.2.0", "import-local": "^3.2.0", - "jest-cli": "30.1.3" + "jest-cli": "30.2.0" }, "bin": { "jest": "bin/jest.js" @@ -8638,14 +8644,14 @@ } }, "node_modules/jest-changed-files": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.0.5.tgz", - "integrity": "sha512-bGl2Ntdx0eAwXuGpdLdVYVr5YQHnSZlQ0y9HVDu565lCUAe9sj6JOtBbMmBBikGIegne9piDDIOeiLVoqTkz4A==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", + "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", "dev": true, "license": "MIT", "dependencies": { "execa": "^5.1.1", - "jest-util": "30.0.5", + "jest-util": "30.2.0", "p-limit": "^3.1.0" }, "engines": { @@ -8653,29 +8659,29 @@ } }, "node_modules/jest-circus": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.1.3.tgz", - "integrity": "sha512-Yf3dnhRON2GJT4RYzM89t/EXIWNxKTpWTL9BfF3+geFetWP4XSvJjiU1vrWplOiUkmq8cHLiwuhz+XuUp9DscA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", + "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.1.2", - "@jest/expect": "30.1.2", - "@jest/test-result": "30.1.3", - "@jest/types": "30.0.5", + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", "@types/node": "*", "chalk": "^4.1.2", "co": "^4.6.0", "dedent": "^1.6.0", "is-generator-fn": "^2.1.0", - "jest-each": "30.1.0", - "jest-matcher-utils": "30.1.2", - "jest-message-util": "30.1.0", - "jest-runtime": "30.1.3", - "jest-snapshot": "30.1.2", - "jest-util": "30.0.5", + "jest-each": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", "p-limit": "^3.1.0", - "pretty-format": "30.0.5", + "pretty-format": "30.2.0", "pure-rand": "^7.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" @@ -8685,21 +8691,21 @@ } }, "node_modules/jest-cli": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.1.3.tgz", - "integrity": "sha512-G8E2Ol3OKch1DEeIBl41NP7OiC6LBhfg25Btv+idcusmoUSpqUkbrneMqbW9lVpI/rCKb/uETidb7DNteheuAQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", + "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.1.3", - "@jest/test-result": "30.1.3", - "@jest/types": "30.0.5", + "@jest/core": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", "chalk": "^4.1.2", "exit-x": "^0.2.2", "import-local": "^3.2.0", - "jest-config": "30.1.3", - "jest-util": "30.0.5", - "jest-validate": "30.1.0", + "jest-config": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", "yargs": "^17.7.2" }, "bin": { @@ -8718,34 +8724,34 @@ } }, "node_modules/jest-config": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.1.3.tgz", - "integrity": "sha512-M/f7gqdQEPgZNA181Myz+GXCe8jXcJsGjCMXUzRj22FIXsZOyHNte84e0exntOvdPaeh9tA0w+B8qlP2fAezfw==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", + "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.27.4", "@jest/get-type": "30.1.0", "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.1.3", - "@jest/types": "30.0.5", - "babel-jest": "30.1.2", + "@jest/test-sequencer": "30.2.0", + "@jest/types": "30.2.0", + "babel-jest": "30.2.0", "chalk": "^4.1.2", "ci-info": "^4.2.0", "deepmerge": "^4.3.1", "glob": "^10.3.10", "graceful-fs": "^4.2.11", - "jest-circus": "30.1.3", - "jest-docblock": "30.0.1", - "jest-environment-node": "30.1.2", + "jest-circus": "30.2.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.1.3", - "jest-runner": "30.1.3", - "jest-util": "30.0.5", - "jest-validate": "30.1.0", + "jest-resolve": "30.2.0", + "jest-runner": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", "micromatch": "^4.0.8", "parse-json": "^5.2.0", - "pretty-format": "30.0.5", + "pretty-format": "30.2.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -8817,25 +8823,25 @@ } }, "node_modules/jest-diff": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.1.2.tgz", - "integrity": "sha512-4+prq+9J61mOVXCa4Qp8ZjavdxzrWQXrI80GNxP8f4tkI2syPuPrJgdRPZRrfUTRvIoUwcmNLbqEJy9W800+NQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", "dev": true, "license": "MIT", "dependencies": { "@jest/diff-sequences": "30.0.1", "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "pretty-format": "30.0.5" + "pretty-format": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-docblock": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.0.1.tgz", - "integrity": "sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", + "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", "dev": true, "license": "MIT", "dependencies": { @@ -8846,36 +8852,36 @@ } }, "node_modules/jest-each": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.1.0.tgz", - "integrity": "sha512-A+9FKzxPluqogNahpCv04UJvcZ9B3HamqpDNWNKDjtxVRYB8xbZLFuCr8JAJFpNp83CA0anGQFlpQna9Me+/tQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", + "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "@jest/types": "30.0.5", + "@jest/types": "30.2.0", "chalk": "^4.1.2", - "jest-util": "30.0.5", - "pretty-format": "30.0.5" + "jest-util": "30.2.0", + "pretty-format": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-environment-node": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.1.2.tgz", - "integrity": "sha512-w8qBiXtqGWJ9xpJIA98M0EIoq079GOQRQUyse5qg1plShUCQ0Ek1VTTcczqKrn3f24TFAgFtT+4q3aOXvjbsuA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", + "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.1.2", - "@jest/fake-timers": "30.1.2", - "@jest/types": "30.0.5", + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", "@types/node": "*", - "jest-mock": "30.0.5", - "jest-util": "30.0.5", - "jest-validate": "30.1.0" + "jest-mock": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -8889,20 +8895,20 @@ "license": "MIT" }, "node_modules/jest-haste-map": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.1.0.tgz", - "integrity": "sha512-JLeM84kNjpRkggcGpQLsV7B8W4LNUWz7oDNVnY1Vjj22b5/fAb3kk3htiD+4Na8bmJmjJR7rBtS2Rmq/NEcADg==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", + "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.5", + "@jest/types": "30.2.0", "@types/node": "*", "anymatch": "^3.1.3", "fb-watchman": "^2.0.2", "graceful-fs": "^4.2.11", "jest-regex-util": "30.0.1", - "jest-util": "30.0.5", - "jest-worker": "30.1.0", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", "micromatch": "^4.0.8", "walker": "^1.0.8" }, @@ -8914,49 +8920,49 @@ } }, "node_modules/jest-leak-detector": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.1.0.tgz", - "integrity": "sha512-AoFvJzwxK+4KohH60vRuHaqXfWmeBATFZpzpmzNmYTtmRMiyGPVhkXpBqxUQunw+dQB48bDf4NpUs6ivVbRv1g==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", + "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "pretty-format": "30.0.5" + "pretty-format": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.1.2.tgz", - "integrity": "sha512-7ai16hy4rSbDjvPTuUhuV8nyPBd6EX34HkBsBcBX2lENCuAQ0qKCPb/+lt8OSWUa9WWmGYLy41PrEzkwRwoGZQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", - "jest-diff": "30.1.2", - "pretty-format": "30.0.5" + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-message-util": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.1.0.tgz", - "integrity": "sha512-HizKDGG98cYkWmaLUHChq4iN+oCENohQLb7Z5guBPumYs+/etonmNFlg1Ps6yN9LTPyZn+M+b/9BbnHx3WTMDg==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@jest/types": "30.0.5", + "@jest/types": "30.2.0", "@types/stack-utils": "^2.0.3", "chalk": "^4.1.2", "graceful-fs": "^4.2.11", "micromatch": "^4.0.8", - "pretty-format": "30.0.5", + "pretty-format": "30.2.0", "slash": "^3.0.0", "stack-utils": "^2.0.6" }, @@ -8965,15 +8971,15 @@ } }, "node_modules/jest-mock": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.5.tgz", - "integrity": "sha512-Od7TyasAAQX/6S+QCbN6vZoWOMwlTtzzGuxJku1GhGanAjz9y+QsQkpScDmETvdc9aSXyJ/Op4rhpMYBWW91wQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.5", + "@jest/types": "30.2.0", "@types/node": "*", - "jest-util": "30.0.5" + "jest-util": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -9008,18 +9014,18 @@ } }, "node_modules/jest-resolve": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.1.3.tgz", - "integrity": "sha512-DI4PtTqzw9GwELFS41sdMK32Ajp3XZQ8iygeDMWkxlRhm7uUTOFSZFVZABFuxr0jvspn8MAYy54NxZCsuCTSOw==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", + "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.2", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.1.0", + "jest-haste-map": "30.2.0", "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.0.5", - "jest-validate": "30.1.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", "slash": "^3.0.0", "unrs-resolver": "^1.7.11" }, @@ -9028,46 +9034,46 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.1.3.tgz", - "integrity": "sha512-DNfq3WGmuRyHRHfEet+Zm3QOmVFtIarUOQHHryKPc0YL9ROfgWZxl4+aZq/VAzok2SS3gZdniP+dO4zgo59hBg==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", + "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", "dev": true, "license": "MIT", "dependencies": { "jest-regex-util": "30.0.1", - "jest-snapshot": "30.1.2" + "jest-snapshot": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, "node_modules/jest-runner": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.1.3.tgz", - "integrity": "sha512-dd1ORcxQraW44Uz029TtXj85W11yvLpDuIzNOlofrC8GN+SgDlgY4BvyxJiVeuabA1t6idjNbX59jLd2oplOGQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", + "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.1.2", - "@jest/environment": "30.1.2", - "@jest/test-result": "30.1.3", - "@jest/transform": "30.1.2", - "@jest/types": "30.0.5", + "@jest/console": "30.2.0", + "@jest/environment": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", "@types/node": "*", "chalk": "^4.1.2", "emittery": "^0.13.1", "exit-x": "^0.2.2", "graceful-fs": "^4.2.11", - "jest-docblock": "30.0.1", - "jest-environment-node": "30.1.2", - "jest-haste-map": "30.1.0", - "jest-leak-detector": "30.1.0", - "jest-message-util": "30.1.0", - "jest-resolve": "30.1.3", - "jest-runtime": "30.1.3", - "jest-util": "30.0.5", - "jest-watcher": "30.1.3", - "jest-worker": "30.1.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-leak-detector": "30.2.0", + "jest-message-util": "30.2.0", + "jest-resolve": "30.2.0", + "jest-runtime": "30.2.0", + "jest-util": "30.2.0", + "jest-watcher": "30.2.0", + "jest-worker": "30.2.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -9076,32 +9082,32 @@ } }, "node_modules/jest-runtime": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.1.3.tgz", - "integrity": "sha512-WS8xgjuNSphdIGnleQcJ3AKE4tBKOVP+tKhCD0u+Tb2sBmsU8DxfbBpZX7//+XOz81zVs4eFpJQwBNji2Y07DA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", + "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.1.2", - "@jest/fake-timers": "30.1.2", - "@jest/globals": "30.1.2", + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/globals": "30.2.0", "@jest/source-map": "30.0.1", - "@jest/test-result": "30.1.3", - "@jest/transform": "30.1.2", - "@jest/types": "30.0.5", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", "@types/node": "*", "chalk": "^4.1.2", "cjs-module-lexer": "^2.1.0", "collect-v8-coverage": "^1.0.2", "glob": "^10.3.10", "graceful-fs": "^4.2.11", - "jest-haste-map": "30.1.0", - "jest-message-util": "30.1.0", - "jest-mock": "30.0.5", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", "jest-regex-util": "30.0.1", - "jest-resolve": "30.1.3", - "jest-snapshot": "30.1.2", - "jest-util": "30.0.5", + "jest-resolve": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -9157,9 +9163,9 @@ } }, "node_modules/jest-snapshot": { - "version": "30.1.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.1.2.tgz", - "integrity": "sha512-4q4+6+1c8B6Cy5pGgFvjDy/Pa6VYRiGu0yQafKkJ9u6wQx4G5PqI2QR6nxTl43yy7IWsINwz6oT4o6tD12a8Dg==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", + "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", "dev": true, "license": "MIT", "dependencies": { @@ -9168,20 +9174,20 @@ "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.1.2", + "@jest/expect-utils": "30.2.0", "@jest/get-type": "30.1.0", - "@jest/snapshot-utils": "30.1.2", - "@jest/transform": "30.1.2", - "@jest/types": "30.0.5", - "babel-preset-current-node-syntax": "^1.1.0", + "@jest/snapshot-utils": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0", "chalk": "^4.1.2", - "expect": "30.1.2", + "expect": "30.2.0", "graceful-fs": "^4.2.11", - "jest-diff": "30.1.2", - "jest-matcher-utils": "30.1.2", - "jest-message-util": "30.1.0", - "jest-util": "30.0.5", - "pretty-format": "30.0.5", + "jest-diff": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "pretty-format": "30.2.0", "semver": "^7.7.2", "synckit": "^0.11.8" }, @@ -9203,13 +9209,13 @@ } }, "node_modules/jest-util": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.5.tgz", - "integrity": "sha512-pvyPWssDZR0FlfMxCBoc0tvM8iUEskaRFALUtGQYzVEAqisAztmy+R8LnU14KT4XA0H/a5HMVTXat1jLne010g==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.0.5", + "@jest/types": "30.2.0", "@types/node": "*", "chalk": "^4.1.2", "ci-info": "^4.2.0", @@ -9234,18 +9240,18 @@ } }, "node_modules/jest-validate": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.1.0.tgz", - "integrity": "sha512-7P3ZlCFW/vhfQ8pE7zW6Oi4EzvuB4sgR72Q1INfW9m0FGo0GADYlPwIkf4CyPq7wq85g+kPMtPOHNAdWHeBOaA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", + "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", "dev": true, "license": "MIT", "dependencies": { "@jest/get-type": "30.1.0", - "@jest/types": "30.0.5", + "@jest/types": "30.2.0", "camelcase": "^6.3.0", "chalk": "^4.1.2", "leven": "^3.1.0", - "pretty-format": "30.0.5" + "pretty-format": "30.2.0" }, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" @@ -9265,19 +9271,19 @@ } }, "node_modules/jest-watcher": { - "version": "30.1.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.1.3.tgz", - "integrity": "sha512-6jQUZCP1BTL2gvG9E4YF06Ytq4yMb4If6YoQGRR6PpjtqOXSP3sKe2kqwB6SQ+H9DezOfZaSLnmka1NtGm3fCQ==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", + "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.1.3", - "@jest/types": "30.0.5", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", "@types/node": "*", "ansi-escapes": "^4.3.2", "chalk": "^4.1.2", "emittery": "^0.13.1", - "jest-util": "30.0.5", + "jest-util": "30.2.0", "string-length": "^4.0.2" }, "engines": { @@ -9285,15 +9291,15 @@ } }, "node_modules/jest-worker": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.1.0.tgz", - "integrity": "sha512-uvWcSjlwAAgIu133Tt77A05H7RIk3Ho8tZL50bQM2AkvLdluw9NG48lRCl3Dt+MOH719n/0nnb5YxUwcuJiKRA==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", + "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.0.5", + "jest-util": "30.2.0", "merge-stream": "^2.0.0", "supports-color": "^8.1.1" }, @@ -10608,9 +10614,9 @@ } }, "node_modules/napi-postinstall": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.3.tgz", - "integrity": "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", "dev": true, "license": "MIT", "bin": { @@ -11605,9 +11611,9 @@ } }, "node_modules/pretty-format": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", - "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", "dependencies": { @@ -13287,9 +13293,9 @@ "license": "ISC" }, "node_modules/stylelint": { - "version": "16.24.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.24.0.tgz", - "integrity": "sha512-7ksgz3zJaSbTUGr/ujMXvLVKdDhLbGl3R/3arNudH7z88+XZZGNLMTepsY28WlnvEFcuOmUe7fg40Q3lfhOfSQ==", + "version": "16.25.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.25.0.tgz", + "integrity": "sha512-Li0avYWV4nfv1zPbdnxLYBGq4z8DVZxbRgx4Kn6V+Uftz1rMoF1qiEI3oL4kgWqyYgCgs7gT5maHNZ82Gk03vQ==", "dev": true, "funding": [ { @@ -13307,13 +13313,13 @@ "@csstools/css-tokenizer": "^3.0.4", "@csstools/media-query-list-parser": "^4.0.3", "@csstools/selector-specificity": "^5.0.0", - "@dual-bundle/import-meta-resolve": "^4.1.0", + "@dual-bundle/import-meta-resolve": "^4.2.1", "balanced-match": "^2.0.0", "colord": "^2.9.3", "cosmiconfig": "^9.0.0", "css-functions-list": "^3.2.3", "css-tree": "^3.1.0", - "debug": "^4.4.1", + "debug": "^4.4.3", "fast-glob": "^3.3.3", "fastest-levenshtein": "^1.0.16", "file-entry-cache": "^10.1.4", @@ -14162,9 +14168,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.14.0.tgz", + "integrity": "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index b36b9959a..c897d842d 100644 --- a/package.json +++ b/package.json @@ -138,15 +138,15 @@ "devDependencies": { "@stylistic/stylelint-plugin": "^4.0.0", "babel-plugin-transform-import-meta": "^2.3.3", - "eslint": "^9.35.0", + "eslint": "^9.37.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-react": "^7.37.5", - "globals": "^16.3.0", - "jest": "^30.1.3", + "globals": "^16.4.0", + "jest": "^30.2.0", "jest-expect-message": "^1.1.3", "jsdom-global": "^3.0.2", "postcss-less": "^6.0.0", - "stylelint": "^16.24.0", + "stylelint": "^16.25.0", "stylelint-config-recess-order": "^7.3.0", "stylelint-config-recommended": "^17.0.0", "supertest": "^7.1.4" From 1eff2dbeddfa4909a7bb0c67bc826d3427d559ca Mon Sep 17 00:00:00 2001 From: David Bolack Date: Thu, 9 Oct 2025 19:25:40 -0500 Subject: [PATCH 78/95] Change dpercent to d10 --- d100_Sources/buildFont.bash | 68 --------- d100_Sources/d10-MASTER-AB.svg | 134 ------------------ d100_Sources/d10-MASTER.svg | 112 --------------- d100_Sources/readme.md | 28 ---- themes/fonts/iconFonts/diceFont.js | 202 +++++++++++++-------------- themes/fonts/iconFonts/diceFont.less | 202 +++++++++++++-------------- 6 files changed, 202 insertions(+), 544 deletions(-) delete mode 100644 d100_Sources/buildFont.bash delete mode 100644 d100_Sources/d10-MASTER-AB.svg delete mode 100644 d100_Sources/d10-MASTER.svg delete mode 100644 d100_Sources/readme.md diff --git a/d100_Sources/buildFont.bash b/d100_Sources/buildFont.bash deleted file mode 100644 index 286472e17..000000000 --- a/d100_Sources/buildFont.bash +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash -x - -# If there is no argument, don't recreate the individual dice, only run the final conversion. -if [ "${1}" == "y" ] || [ "${1}" == "n" ]; then - if [ ! -d './rendered-files' ]; then - mkdir rendered-files - fi - rm ./rendered-files/*.svg - # Build 00-99 ( leading zeros ) - for tens in $(echo 0 1 2 3 4 5 6 7 8 9); do - for ones in $(echo 0 1 2 3 4 5 6 7 8 9); do - num=$(echo ${tens}${ones}); - cat d10-MASTER-AB.svg | sed "s/AAAAA/${tens}/" | sed "s/BBBBB/${ones}/" > ./rendered-files/10-MASTER-${num}.svg - printf "Rendering d100 - ${num}\r" - # Tweak the individual die - if [ "${1}" == "y" ]; then inkscape ./rendered-files/10-MASTER-${num}.svg; fi - done - done - # Build 0-9, non-leading zero - for ones in $(echo 0 1 2 3 4 5 6 7 8 9); do - num=$(echo ${ones}); - cat d10-MASTER.svg | sed "s/AAAAA/${num}/" > ./rendered-files/10-MASTER-${num}.svg - printf "Rendering d10 - ${num}\r" - # Tweak the individual die - if [ "${1}" == "y" ]; then inkscape ./rendered-files/10-MASTER-${num}.svg; fi - done - # Build the 100 face - num=100 - cat d10-MASTER.svg | sed "s/AAAAA/${num}/" > ./rendered-files/10-MASTER-${num}.svg - printf "Rendering d100 - ${num}\r" - # Tweak the individual die - if [ "${1}" == "y" ]; then inkscape ./rendered-files/10-MASTER-${num}.svg; fi - printf "\r\n" -fi - -# Convert the Master files for better IcoMoon compatibility -# Mirror this literally -for tens in $(echo 0 1 2 3 4 5 6 7 8 9); do - for ones in $(echo 0 1 2 3 4 5 6 7 8 9); do - num=$(echo ${tens}${ones}) - inkscape --export-text-to-path -o ./rendered-files/dpercent-${num}.svg ./rendered-files/10-MASTER-${num}.svg 2> /dev/null - printf "Rewriting d100 - ${num}\r" - done -done - -# d100 -num=100 -inkscape --export-text-to-path -o ./rendered-files/dpercent-${num}.svg ./rendered-files/10-MASTER-${num}.svg 2> /dev/null -printf "Rewriting d100 - ${num}\r" - -for ones in $(echo 0 1 2 3 4 5 6 7 8 9); do - num=$(echo ${ones}) - inkscape --export-text-to-path -o ./rendered-files/d10-${num}.svg ./rendered-files/10-MASTER-${num}.svg 2> /dev/null - printf "Rewriting d10 - ${num}\r" -done - -# Duplicate the 10 for the d10 set -num=10 -inkscape --export-text-to-path -o ./rendered-files/d10-${num}.svg ./rendered-files/10-MASTER-${num}.svg 2> /dev/null -printf "Rewriting d10 - ${num}\r" - -# Run svgfixer -if [ ! -d './fixed-files' ]; then - mkdir fixed-files -fi - -rm ./fixed-files/*.svg -oslllo-svg-fixer -s ./rendered-files/ -d ./fixed-files diff --git a/d100_Sources/d10-MASTER-AB.svg b/d100_Sources/d10-MASTER-AB.svg deleted file mode 100644 index b31778607..000000000 --- a/d100_Sources/d10-MASTER-AB.svg +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - - - - - - - d10-0 - - - - - - AAAAA - - BBBBB - - - - - d10-0 - - - - diff --git a/d100_Sources/d10-MASTER.svg b/d100_Sources/d10-MASTER.svg deleted file mode 100644 index baa327064..000000000 --- a/d100_Sources/d10-MASTER.svg +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - - - - - - d10-0 - - - - - - AAAAA - - - - - d10-0 - - - - diff --git a/d100_Sources/readme.md b/d100_Sources/readme.md deleted file mode 100644 index fb06620bf..000000000 --- a/d100_Sources/readme.md +++ /dev/null @@ -1,28 +0,0 @@ -# Dicefont extensions - -This folder is setup for building/rebuilding the d10 and d100 (percent representation on a d10 shape) for use with Icomoon. This will, presumably, be a usable workflow with similar tools. - -## Overview - -This script uses the file 10-MASTER.svg as a base, loops through each of the die face numbers needed, creating an SVG per face in `./rendered-files`. Next, it post-processes the files from `./rendered-files/` to be more compatible with IcoMoon and places the results in `./fixed-files`. - -## Usage - -The script runs on three possible paths. - -1. Start from scratch ***and*** open inkscape for each glyph for tweaking. - `bash ./buildFont.bash y` - - On this path, the per-face SVG files are generated and Inkscape is opened on each file for any tweaking to be done. - -2. Start from scratch but ***do not*** tweak each glyph while running. - `bash ./buildFont.bash n` - -3. Process the rendered glyphs for loading into IcoMoon - `bash ./buildFont.bash` - -For most rebuilds, the expectation is that the script will be run once with `n` as the parameter, then some number of files will be manually touched, then the script re-run with no parameters before finally using the results with IcoMoon. - -## Requirements - -This script expects inkscape and [https://docs-oslllo-com.onrender.com/svg-fixer/master/#/getting-started/introduction](svgFixer) to be in the path. The numbering uses the Kremlin Minister Font Family. \ No newline at end of file diff --git a/themes/fonts/iconFonts/diceFont.js b/themes/fonts/iconFonts/diceFont.js index 3e7572c1d..d6f5a3291 100644 --- a/themes/fonts/iconFonts/diceFont.js +++ b/themes/fonts/iconFonts/diceFont.js @@ -92,107 +92,107 @@ const diceFont = { 'df_solid_small_dot_d6_4' : 'df solid-small-dot-d6-4', 'df_solid_small_dot_d6_5' : 'df solid-small-dot-d6-5', 'df_solid_small_dot_d6_6' : 'df solid-small-dot-d6-6', - 'df_dper_00' : 'df dpercent-00', - 'df_dper_01' : 'df dpercent-01', - 'df_dper_02' : 'df dpercent-02', - 'df_dper_03' : 'df dpercent-03', - 'df_dper_04' : 'df dpercent-04', - 'df_dper_05' : 'df dpercent-05', - 'df_dper_06' : 'df dpercent-06', - 'df_dper_07' : 'df dpercent-07', - 'df_dper_08' : 'df dpercent-08', - 'df_dper_09' : 'df dpercent-09', - 'df_dper_10' : 'df dpercent-10', - 'df_dper_11' : 'df dpercent-11', - 'df_dper_12' : 'df dpercent-12', - 'df_dper_13' : 'df dpercent-13', - 'df_dper_14' : 'df dpercent-14', - 'df_dper_15' : 'df dpercent-15', - 'df_dper_16' : 'df dpercent-16', - 'df_dper_17' : 'df dpercent-17', - 'df_dper_18' : 'df dpercent-18', - 'df_dper_19' : 'df dpercent-19', - 'df_dper_20' : 'df dpercent-20', - 'df_dper_21' : 'df dpercent-21', - 'df_dper_22' : 'df dpercent-22', - 'df_dper_23' : 'df dpercent-23', - 'df_dper_24' : 'df dpercent-24', - 'df_dper_25' : 'df dpercent-25', - 'df_dper_26' : 'df dpercent-26', - 'df_dper_27' : 'df dpercent-27', - 'df_dper_28' : 'df dpercent-28', - 'df_dper_29' : 'df dpercent-29', - 'df_dper_30' : 'df dpercent-30', - 'df_dper_31' : 'df dpercent-31', - 'df_dper_32' : 'df dpercent-32', - 'df_dper_33' : 'df dpercent-33', - 'df_dper_34' : 'df dpercent-34', - 'df_dper_35' : 'df dpercent-35', - 'df_dper_36' : 'df dpercent-36', - 'df_dper_37' : 'df dpercent-37', - 'df_dper_38' : 'df dpercent-38', - 'df_dper_39' : 'df dpercent-39', - 'df_dper_40' : 'df dpercent-40', - 'df_dper_41' : 'df dpercent-41', - 'df_dper_42' : 'df dpercent-42', - 'df_dper_43' : 'df dpercent-43', - 'df_dper_44' : 'df dpercent-44', - 'df_dper_45' : 'df dpercent-45', - 'df_dper_46' : 'df dpercent-46', - 'df_dper_47' : 'df dpercent-47', - 'df_dper_48' : 'df dpercent-48', - 'df_dper_49' : 'df dpercent-49', - 'df_dper_50' : 'df dpercent-50', - 'df_dper_51' : 'df dpercent-51', - 'df_dper_52' : 'df dpercent-52', - 'df_dper_53' : 'df dpercent-53', - 'df_dper_54' : 'df dpercent-54', - 'df_dper_55' : 'df dpercent-55', - 'df_dper_56' : 'df dpercent-56', - 'df_dper_57' : 'df dpercent-57', - 'df_dper_58' : 'df dpercent-58', - 'df_dper_59' : 'df dpercent-59', - 'df_dper_60' : 'df dpercent-60', - 'df_dper_61' : 'df dpercent-61', - 'df_dper_62' : 'df dpercent-62', - 'df_dper_63' : 'df dpercent-63', - 'df_dper_64' : 'df dpercent-64', - 'df_dper_65' : 'df dpercent-65', - 'df_dper_66' : 'df dpercent-66', - 'df_dper_67' : 'df dpercent-67', - 'df_dper_68' : 'df dpercent-68', - 'df_dper_69' : 'df dpercent-69', - 'df_dper_70' : 'df dpercent-70', - 'df_dper_71' : 'df dpercent-71', - 'df_dper_72' : 'df dpercent-72', - 'df_dper_73' : 'df dpercent-73', - 'df_dper_74' : 'df dpercent-74', - 'df_dper_75' : 'df dpercent-75', - 'df_dper_76' : 'df dpercent-76', - 'df_dper_77' : 'df dpercent-77', - 'df_dper_78' : 'df dpercent-78', - 'df_dper_79' : 'df dpercent-79', - 'df_dper_80' : 'df dpercent-80', - 'df_dper_81' : 'df dpercent-81', - 'df_dper_82' : 'df dpercent-82', - 'df_dper_83' : 'df dpercent-83', - 'df_dper_84' : 'df dpercent-84', - 'df_dper_85' : 'df dpercent-85', - 'df_dper_86' : 'df dpercent-86', - 'df_dper_87' : 'df dpercent-87', - 'df_dper_88' : 'df dpercent-88', - 'df_dper_89' : 'df dpercent-89', - 'df_dper_90' : 'df dpercent-90', - 'df_dper_91' : 'df dpercent-91', - 'df_dper_92' : 'df dpercent-92', - 'df_dper_93' : 'df dpercent-93', - 'df_dper_94' : 'df dpercent-94', - 'df_dper_95' : 'df dpercent-95', - 'df_dper_96' : 'df dpercent-96', - 'df_dper_97' : 'df dpercent-97', - 'df_dper_98' : 'df dpercent-98', - 'df_dper_99' : 'df dpercent-99', - 'df_dper_100' : 'df dpercent-100' + 'df_dper_00' : 'df d10-00', + 'df_dper_01' : 'df d10-01', + 'df_dper_02' : 'df d10-02', + 'df_dper_03' : 'df d10-03', + 'df_dper_04' : 'df d10-04', + 'df_dper_05' : 'df d10-05', + 'df_dper_06' : 'df d10-06', + 'df_dper_07' : 'df d10-07', + 'df_dper_08' : 'df d10-08', + 'df_dper_09' : 'df d10-09', + 'df_dper_10' : 'df d10-10', + 'df_dper_11' : 'df d10-11', + 'df_dper_12' : 'df d10-12', + 'df_dper_13' : 'df d10-13', + 'df_dper_14' : 'df d10-14', + 'df_dper_15' : 'df d10-15', + 'df_dper_16' : 'df d10-16', + 'df_dper_17' : 'df d10-17', + 'df_dper_18' : 'df d10-18', + 'df_dper_19' : 'df d10-19', + 'df_dper_20' : 'df d10-20', + 'df_dper_21' : 'df d10-21', + 'df_dper_22' : 'df d10-22', + 'df_dper_23' : 'df d10-23', + 'df_dper_24' : 'df d10-24', + 'df_dper_25' : 'df d10-25', + 'df_dper_26' : 'df d10-26', + 'df_dper_27' : 'df d10-27', + 'df_dper_28' : 'df d10-28', + 'df_dper_29' : 'df d10-29', + 'df_dper_30' : 'df d10-30', + 'df_dper_31' : 'df d10-31', + 'df_dper_32' : 'df d10-32', + 'df_dper_33' : 'df d10-33', + 'df_dper_34' : 'df d10-34', + 'df_dper_35' : 'df d10-35', + 'df_dper_36' : 'df d10-36', + 'df_dper_37' : 'df d10-37', + 'df_dper_38' : 'df d10-38', + 'df_dper_39' : 'df d10-39', + 'df_dper_40' : 'df d10-40', + 'df_dper_41' : 'df d10-41', + 'df_dper_42' : 'df d10-42', + 'df_dper_43' : 'df d10-43', + 'df_dper_44' : 'df d10-44', + 'df_dper_45' : 'df d10-45', + 'df_dper_46' : 'df d10-46', + 'df_dper_47' : 'df d10-47', + 'df_dper_48' : 'df d10-48', + 'df_dper_49' : 'df d10-49', + 'df_dper_50' : 'df d10-50', + 'df_dper_51' : 'df d10-51', + 'df_dper_52' : 'df d10-52', + 'df_dper_53' : 'df d10-53', + 'df_dper_54' : 'df d10-54', + 'df_dper_55' : 'df d10-55', + 'df_dper_56' : 'df d10-56', + 'df_dper_57' : 'df d10-57', + 'df_dper_58' : 'df d10-58', + 'df_dper_59' : 'df d10-59', + 'df_dper_60' : 'df d10-60', + 'df_dper_61' : 'df d10-61', + 'df_dper_62' : 'df d10-62', + 'df_dper_63' : 'df d10-63', + 'df_dper_64' : 'df d10-64', + 'df_dper_65' : 'df d10-65', + 'df_dper_66' : 'df d10-66', + 'df_dper_67' : 'df d10-67', + 'df_dper_68' : 'df d10-68', + 'df_dper_69' : 'df d10-69', + 'df_dper_70' : 'df d10-70', + 'df_dper_71' : 'df d10-71', + 'df_dper_72' : 'df d10-72', + 'df_dper_73' : 'df d10-73', + 'df_dper_74' : 'df d10-74', + 'df_dper_75' : 'df d10-75', + 'df_dper_76' : 'df d10-76', + 'df_dper_77' : 'df d10-77', + 'df_dper_78' : 'df d10-78', + 'df_dper_79' : 'df d10-79', + 'df_dper_80' : 'df d10-80', + 'df_dper_81' : 'df d10-81', + 'df_dper_82' : 'df d10-82', + 'df_dper_83' : 'df d10-83', + 'df_dper_84' : 'df d10-84', + 'df_dper_85' : 'df d10-85', + 'df_dper_86' : 'df d10-86', + 'df_dper_87' : 'df d10-87', + 'df_dper_88' : 'df d10-88', + 'df_dper_89' : 'df d10-89', + 'df_dper_90' : 'df d10-90', + 'df_dper_91' : 'df d10-91', + 'df_dper_92' : 'df d10-92', + 'df_dper_93' : 'df d10-93', + 'df_dper_94' : 'df d10-94', + 'df_dper_95' : 'df d10-95', + 'df_dper_96' : 'df d10-96', + 'df_dper_97' : 'df d10-97', + 'df_dper_98' : 'df d10-98', + 'df_dper_99' : 'df d10-99', + 'df_dper_100' : 'df d10-100' }; export default diceFont; \ No newline at end of file diff --git a/themes/fonts/iconFonts/diceFont.less b/themes/fonts/iconFonts/diceFont.less index 9e10a0bd1..389ea3156 100644 --- a/themes/fonts/iconFonts/diceFont.less +++ b/themes/fonts/iconFonts/diceFont.less @@ -170,507 +170,507 @@ // d100 - &.dpercent-00::before { + &.d10-00::before { font-family : 'dicefont-percent'; content : '\e90b'; } - &.dpercent-01::before { + &.d10-01::before { font-family : 'dicefont-percent'; content : '\e90c'; } - &.dpercent-02::before { + &.d10-02::before { font-family : 'dicefont-percent'; content : '\e90d'; } - &.dpercent-03::before { + &.d10-03::before { font-family : 'dicefont-percent'; content : '\e90e'; } - &.dpercent-04::before { + &.d10-04::before { font-family : 'dicefont-percent'; content : '\e90f'; } - &.dpercent-05::before { + &.d10-05::before { font-family : 'dicefont-percent'; content : '\e910'; } - &.dpercent-06::before { + &.d10-06::before { font-family : 'dicefont-percent'; content : '\e911'; } - &.dpercent-07::before { + &.d10-07::before { font-family : 'dicefont-percent'; content : '\e912'; } - &.dpercent-08::before { + &.d10-08::before { font-family : 'dicefont-percent'; content : '\e913'; } - &.dpercent-09::before { + &.d10-09::before { font-family : 'dicefont-percent'; content : '\e914'; } - &.dpercent-10::before { + &.d10-10::before { font-family : 'dicefont-percent'; content : '\e915'; } - &.dpercent-11::before { + &.d10-11::before { font-family : 'dicefont-percent'; content : '\e916'; } - &.dpercent-12::before { + &.d10-12::before { font-family : 'dicefont-percent'; content : '\e917'; } - &.dpercent-13::before { + &.d10-13::before { font-family : 'dicefont-percent'; content : '\e918'; } - &.dpercent-14::before { + &.d10-14::before { font-family : 'dicefont-percent'; content : '\e919'; } - &.dpercent-15::before { + &.d10-15::before { font-family : 'dicefont-percent'; content : '\e91a'; } - &.dpercent-16::before { + &.d10-16::before { font-family : 'dicefont-percent'; content : '\e91b'; } - &.dpercent-17::before { + &.d10-17::before { font-family : 'dicefont-percent'; content : '\e91c'; } - &.dpercent-18::before { + &.d10-18::before { font-family : 'dicefont-percent'; content : '\e91d'; } - &.dpercent-19::before { + &.d10-19::before { font-family : 'dicefont-percent'; content : '\e91e'; } - &.dpercent-20::before { + &.d10-20::before { font-family : 'dicefont-percent'; content : '\e91f'; } - &.dpercent-21::before { + &.d10-21::before { font-family : 'dicefont-percent'; content : '\e920'; } - &.dpercent-22::before { + &.d10-22::before { font-family : 'dicefont-percent'; content : '\e921'; } - &.dpercent-23::before { + &.d10-23::before { font-family : 'dicefont-percent'; content : '\e922'; } - &.dpercent-24::before { + &.d10-24::before { font-family : 'dicefont-percent'; content : '\e923'; } - &.dpercent-25::before { + &.d10-25::before { font-family : 'dicefont-percent'; content : '\e924'; } - &.dpercent-26::before { + &.d10-26::before { font-family : 'dicefont-percent'; content : '\e925'; } - &.dpercent-27::before { + &.d10-27::before { font-family : 'dicefont-percent'; content : '\e926'; } - &.dpercent-28::before { + &.d10-28::before { font-family : 'dicefont-percent'; content : '\e927'; } - &.dpercent-29::before { + &.d10-29::before { font-family : 'dicefont-percent'; content : '\e928'; } - &.dpercent-30::before { + &.d10-30::before { font-family : 'dicefont-percent'; content : '\e929'; } - &.dpercent-31::before { + &.d10-31::before { font-family : 'dicefont-percent'; content : '\e92a'; } - &.dpercent-32::before { + &.d10-32::before { font-family : 'dicefont-percent'; content : '\e92b'; } - &.dpercent-33::before { + &.d10-33::before { font-family : 'dicefont-percent'; content : '\e92c'; } - &.dpercent-34::before { + &.d10-34::before { font-family : 'dicefont-percent'; content : '\e92d'; } - &.dpercent-35::before { + &.d10-35::before { font-family : 'dicefont-percent'; content : '\e92e'; } - &.dpercent-36::before { + &.d10-36::before { font-family : 'dicefont-percent'; content : '\e92f'; } - &.dpercent-37::before { + &.d10-37::before { font-family : 'dicefont-percent'; content : '\e930'; } - &.dpercent-38::before { + &.d10-38::before { font-family : 'dicefont-percent'; content : '\e931'; } - &.dpercent-39::before { + &.d10-39::before { font-family : 'dicefont-percent'; content : '\e932'; } - &.dpercent-40::before { + &.d10-40::before { font-family : 'dicefont-percent'; content : '\e933'; } - &.dpercent-41::before { + &.d10-41::before { font-family : 'dicefont-percent'; content : '\e934'; } - &.dpercent-42::before { + &.d10-42::before { font-family : 'dicefont-percent'; content : '\e935'; } - &.dpercent-43::before { + &.d10-43::before { font-family : 'dicefont-percent'; content : '\e936'; } - &.dpercent-44::before { + &.d10-44::before { font-family : 'dicefont-percent'; content : '\e937'; } - &.dpercent-45::before { + &.d10-45::before { font-family : 'dicefont-percent'; content : '\e938'; } - &.dpercent-46::before { + &.d10-46::before { font-family : 'dicefont-percent'; content : '\e939'; } - &.dpercent-47::before { + &.d10-47::before { font-family : 'dicefont-percent'; content : '\e93a'; } - &.dpercent-48::before { + &.d10-48::before { font-family : 'dicefont-percent'; content : '\e93b'; } - &.dpercent-49::before { + &.d10-49::before { font-family : 'dicefont-percent'; content : '\e93c'; } - &.dpercent-50::before { + &.d10-50::before { font-family : 'dicefont-percent'; content : '\e93d'; } - &.dpercent-51::before { + &.d10-51::before { font-family : 'dicefont-percent'; content : '\e93e'; } - &.dpercent-52::before { + &.d10-52::before { font-family : 'dicefont-percent'; content : '\e93f'; } - &.dpercent-53::before { + &.d10-53::before { font-family : 'dicefont-percent'; content : '\e940'; } - &.dpercent-54::before { + &.d10-54::before { font-family : 'dicefont-percent'; content : '\e941'; } - &.dpercent-55::before { + &.d10-55::before { font-family : 'dicefont-percent'; content : '\e942'; } - &.dpercent-56::before { + &.d10-56::before { font-family : 'dicefont-percent'; content : '\e943'; } - &.dpercent-57::before { + &.d10-57::before { font-family : 'dicefont-percent'; content : '\e944'; } - &.dpercent-58::before { + &.d10-58::before { font-family : 'dicefont-percent'; content : '\e945'; } - &.dpercent-59::before { + &.d10-59::before { font-family : 'dicefont-percent'; content : '\e946'; } - &.dpercent-60::before { + &.d10-60::before { font-family : 'dicefont-percent'; content : '\e947'; } - &.dpercent-61::before { + &.d10-61::before { font-family : 'dicefont-percent'; content : '\e948'; } - &.dpercent-62::before { + &.d10-62::before { font-family : 'dicefont-percent'; content : '\e949'; } - &.dpercent-63::before { + &.d10-63::before { font-family : 'dicefont-percent'; content : '\e94a'; } - &.dpercent-64::before { + &.d10-64::before { font-family : 'dicefont-percent'; content : '\e94b'; } - &.dpercent-65::before { + &.d10-65::before { font-family : 'dicefont-percent'; content : '\e94c'; } - &.dpercent-66::before { + &.d10-66::before { font-family : 'dicefont-percent'; content : '\e94d'; } - &.dpercent-67::before { + &.d10-67::before { font-family : 'dicefont-percent'; content : '\e94e'; } - &.dpercent-68::before { + &.d10-68::before { font-family : 'dicefont-percent'; content : '\e94f'; } - &.dpercent-69::before { + &.d10-69::before { font-family : 'dicefont-percent'; content : '\e950'; } - &.dpercent-70::before { + &.d10-70::before { font-family : 'dicefont-percent'; content : '\e951'; } - &.dpercent-71::before { + &.d10-71::before { font-family : 'dicefont-percent'; content : '\e952'; } - &.dpercent-72::before { + &.d10-72::before { font-family : 'dicefont-percent'; content : '\e953'; } - &.dpercent-73::before { + &.d10-73::before { font-family : 'dicefont-percent'; content : '\e954'; } - &.dpercent-74::before { + &.d10-74::before { font-family : 'dicefont-percent'; content : '\e955'; } - &.dpercent-75::before { + &.d10-75::before { font-family : 'dicefont-percent'; content : '\e956'; } - &.dpercent-76::before { + &.d10-76::before { font-family : 'dicefont-percent'; content : '\e957'; } - &.dpercent-77::before { + &.d10-77::before { font-family : 'dicefont-percent'; content : '\e958'; } - &.dpercent-78::before { + &.d10-78::before { font-family : 'dicefont-percent'; content : '\e959'; } - &.dpercent-79::before { + &.d10-79::before { font-family : 'dicefont-percent'; content : '\e95a'; } - &.dpercent-80::before { + &.d10-80::before { font-family : 'dicefont-percent'; content : '\e95b'; } - &.dpercent-81::before { + &.d10-81::before { font-family : 'dicefont-percent'; content : '\e95c'; } - &.dpercent-82::before { + &.d10-82::before { font-family : 'dicefont-percent'; content : '\e95d'; } - &.dpercent-83::before { + &.d10-83::before { font-family : 'dicefont-percent'; content : '\e95e'; } - &.dpercent-84::before { + &.d10-84::before { font-family : 'dicefont-percent'; content : '\e95f'; } - &.dpercent-85::before { + &.d10-85::before { font-family : 'dicefont-percent'; content : '\e960'; } - &.dpercent-86::before { + &.d10-86::before { font-family : 'dicefont-percent'; content : '\e961'; } - &.dpercent-87::before { + &.d10-87::before { font-family : 'dicefont-percent'; content : '\e962'; } - &.dpercent-88::before { + &.d10-88::before { font-family : 'dicefont-percent'; content : '\e963'; } - &.dpercent-89::before { + &.d10-89::before { font-family : 'dicefont-percent'; content : '\e964'; } - &.dpercent-90::before { + &.d10-90::before { font-family : 'dicefont-percent'; content : '\e965'; } - &.dpercent-91::before { + &.d10-91::before { font-family : 'dicefont-percent'; content : '\e966'; } - &.dpercent-92::before { + &.d10-92::before { font-family : 'dicefont-percent'; content : '\e967'; } - &.dpercent-93::before { + &.d10-93::before { font-family : 'dicefont-percent'; content : '\e968'; } - &.dpercent-94::before { + &.d10-94::before { font-family : 'dicefont-percent'; content : '\e969'; } - &.dpercent-95::before { + &.d10-95::before { font-family : 'dicefont-percent'; content : '\e96a'; } - &.dpercent-96::before { + &.d10-96::before { font-family : 'dicefont-percent'; content : '\e96b'; } - &.dpercent-97::before { + &.d10-97::before { font-family : 'dicefont-percent'; content : '\e96c'; } - &.dpercent-98::before { + &.d10-98::before { font-family : 'dicefont-percent'; content : '\e96d'; } - &.dpercent-99::before { + &.d10-99::before { font-family : 'dicefont-percent'; content : '\e96e'; } - &.dpercent-100::before { + &.d10-100::before { font-family : 'dicefont-percent'; content : '\e96f'; } From 2de151d3481c6fd90ddf625fa9d5f55cf5da4e61 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Thu, 9 Oct 2025 19:31:30 -0500 Subject: [PATCH 79/95] Rename font --- .../{dicefont-D100.woff => dicefont-D100.woff2} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename themes/fonts/iconFonts/{dicefont-D100.woff => dicefont-D100.woff2} (100%) diff --git a/themes/fonts/iconFonts/dicefont-D100.woff b/themes/fonts/iconFonts/dicefont-D100.woff2 similarity index 100% rename from themes/fonts/iconFonts/dicefont-D100.woff rename to themes/fonts/iconFonts/dicefont-D100.woff2 From 8fcadd87d47cce556c96e6e31000f4cbae1a5915 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Thu, 9 Oct 2025 20:24:01 -0500 Subject: [PATCH 80/95] Remove comments --- client/homebrew/editor/editor.jsx | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index dd810f33a..033b04557 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -97,21 +97,6 @@ const Editor = createClass({ if(prevProps.moveSource !== this.props.moveSource) this.sourceJump(); - // if((prevProps.isDragging !== this.props.isDragging) && (this.props.isDragging) && (this.lastCursor == undefined)) { - // this.lastCursor = this.codeEditor.current.codeMirror.getCursor(); - // const lastXY = this.codeEditor.current.codeMirror.getScrollInfo(); - // const lastRowPos = this.codeEditor.current.codeMirror.heightAtLine(this.lastCursor.line, 'local', true); - // this.lastCursor.offset = Math.round(lastRowPos-lastXY.top); - // } - - // if((prevProps.isDragging !== this.props.isDragging) && (!this.props.isDragging)) { - // const scroll = this.codeEditor.current.codeMirror.getScrollInfo(); - // this.codeEditor.current.codeMirror.scrollTo(null, - // this.codeEditor.current.codeMirror.heightAtLine(this.lastCursor.line, 'local', true) - this.lastCursor.offset); - // this.codeEditor.current.setCursorPosition(this.lastCursor.line, this.lastCursor.ch); - // this.lastCursor = undefined; - // } - if(this.props.liveScroll) { if(prevProps.currentBrewRendererPageNum !== this.props.currentBrewRendererPageNum) { this.sourceJump(this.props.currentBrewRendererPageNum, false); @@ -155,7 +140,7 @@ const Editor = createClass({ handleViewChange : function(newView){ this.props.setMoveArrows(newView === 'text'); - + this.setState({ view : newView }, ()=>{ From fbf0d425e2c5f3a7824f7154cd0daf1afed40bf7 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 11 Oct 2025 09:07:23 -0500 Subject: [PATCH 81/95] Don't pass isDragging to splitpane children. --- client/components/splitPane/splitPane.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/components/splitPane/splitPane.jsx b/client/components/splitPane/splitPane.jsx index 4e100638f..4c77d81a5 100644 --- a/client/components/splitPane/splitPane.jsx +++ b/client/components/splitPane/splitPane.jsx @@ -86,7 +86,7 @@ const SplitPane = (props)=>{ return (
- + {props.children[0]} {renderDivider} @@ -102,7 +102,7 @@ const Pane = ({ width, children, isDragging, moveBrew, moveSource, liveScroll, s return (
- {React.cloneElement(children, { moveBrew, moveSource, liveScroll, isDragging, setMoveArrows })} + {React.cloneElement(children, { moveBrew, moveSource, liveScroll, setMoveArrows })}
); }; From 333614f8664f8484ce64586a71597b7b17365af4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 21:45:46 +0000 Subject: [PATCH 82/95] Bump the prod-dependencies group across 1 directory with 10 updates Bumps the prod-dependencies group with 10 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) | `7.28.0` | `7.28.4` | | [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) | `7.28.0` | `7.28.3` | | [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) | `7.28.0` | `7.28.3` | | [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) | `7.27.6` | `7.28.4` | | [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) | `3.44.0` | `3.46.0` | | [fs-extra](https://github.com/jprichardson/node-fs-extra) | `11.3.0` | `11.3.2` | | [marked-subsuper-text](https://github.com/naturalcrit/marked-subsuper-text) | `1.0.3` | `1.0.4` | | [mongoose](https://github.com/Automattic/mongoose) | `8.16.3` | `8.19.1` | | [nanoid](https://github.com/ai/nanoid) | `5.1.5` | `5.1.6` | | [react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router) | `7.6.3` | `7.9.4` | Updates `@babel/core` from 7.28.0 to 7.28.4 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.28.4/packages/babel-core) Updates `@babel/plugin-transform-runtime` from 7.28.0 to 7.28.3 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.28.3/packages/babel-plugin-transform-runtime) Updates `@babel/preset-env` from 7.28.0 to 7.28.3 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.28.3/packages/babel-preset-env) Updates `@babel/runtime` from 7.27.6 to 7.28.4 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.28.4/packages/babel-runtime) Updates `core-js` from 3.44.0 to 3.46.0 - [Release notes](https://github.com/zloirock/core-js/releases) - [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md) - [Commits](https://github.com/zloirock/core-js/commits/v3.46.0/packages/core-js) Updates `fs-extra` from 11.3.0 to 11.3.2 - [Changelog](https://github.com/jprichardson/node-fs-extra/blob/master/CHANGELOG.md) - [Commits](https://github.com/jprichardson/node-fs-extra/compare/11.3.0...11.3.2) Updates `marked-subsuper-text` from 1.0.3 to 1.0.4 - [Changelog](https://github.com/naturalcrit/marked-subsuper-text/blob/main/release.config.cjs) - [Commits](https://github.com/naturalcrit/marked-subsuper-text/commits) Updates `mongoose` from 8.16.3 to 8.19.1 - [Release notes](https://github.com/Automattic/mongoose/releases) - [Changelog](https://github.com/Automattic/mongoose/blob/master/CHANGELOG.md) - [Commits](https://github.com/Automattic/mongoose/compare/8.16.3...8.19.1) Updates `nanoid` from 5.1.5 to 5.1.6 - [Release notes](https://github.com/ai/nanoid/releases) - [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md) - [Commits](https://github.com/ai/nanoid/compare/5.1.5...5.1.6) Updates `react-router` from 7.6.3 to 7.9.4 - [Release notes](https://github.com/remix-run/react-router/releases) - [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md) - [Commits](https://github.com/remix-run/react-router/commits/react-router@7.9.4/packages/react-router) --- updated-dependencies: - dependency-name: "@babel/core" dependency-version: 7.28.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-dependencies - dependency-name: "@babel/plugin-transform-runtime" dependency-version: 7.28.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-dependencies - dependency-name: "@babel/preset-env" dependency-version: 7.28.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-dependencies - dependency-name: "@babel/runtime" dependency-version: 7.28.4 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-dependencies - dependency-name: core-js dependency-version: 3.46.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-dependencies - dependency-name: fs-extra dependency-version: 11.3.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-dependencies - dependency-name: marked-subsuper-text dependency-version: 1.0.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-dependencies - dependency-name: mongoose dependency-version: 8.19.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-dependencies - dependency-name: nanoid dependency-version: 5.1.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: prod-dependencies - dependency-name: react-router dependency-version: 7.9.4 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: prod-dependencies ... Signed-off-by: dependabot[bot] --- package-lock.json | 270 +++++++++++++++++++++++++--------------------- package.json | 20 ++-- 2 files changed, 157 insertions(+), 133 deletions(-) diff --git a/package-lock.json b/package-lock.json index ee762f8f7..1e8e72488 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,11 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.27.1", - "@babel/plugin-transform-runtime": "^7.28.0", - "@babel/preset-env": "^7.28.0", + "@babel/core": "^7.28.4", + "@babel/plugin-transform-runtime": "^7.28.3", + "@babel/preset-env": "^7.28.3", "@babel/preset-react": "^7.27.1", - "@babel/runtime": "^7.27.6", + "@babel/runtime": "^7.28.4", "@dmsnell/diff-match-patch": "^1.1.0", "@googleapis/drive": "^13.0.1", "@sanity/diff-match-patch": "^3.2.0", @@ -22,7 +22,7 @@ "classnames": "^2.5.1", "codemirror": "^5.65.6", "cookie-parser": "^1.4.7", - "core-js": "^3.44.0", + "core-js": "^3.46.0", "cors": "^2.8.5", "create-react-class": "^15.7.0", "dedent-tabs": "^0.10.3", @@ -31,7 +31,7 @@ "express-async-handler": "^1.2.0", "express-static-gzip": "3.0.0", "fflate": "^0.8.2", - "fs-extra": "11.3.0", + "fs-extra": "11.3.2", "hash-wasm": "^4.12.0", "idb-keyval": "^6.2.2", "js-yaml": "^4.1.0", @@ -46,16 +46,16 @@ "marked-gfm-heading-id": "^4.1.2", "marked-nonbreaking-spaces": "^1.0.1", "marked-smartypants-lite": "^1.0.3", - "marked-subsuper-text": "^1.0.3", + "marked-subsuper-text": "^1.0.4", "markedLegacy": "npm:marked@^0.3.19", "moment": "^2.30.1", - "mongoose": "^8.16.3", - "nanoid": "5.1.5", + "mongoose": "^8.19.1", + "nanoid": "5.1.6", "nconf": "^0.13.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-frame-component": "^4.1.3", - "react-router": "^7.6.3", + "react-router": "^7.9.4", "romans": "^3.1.0", "sanitize-filename": "1.6.3", "superagent": "^10.2.1", @@ -83,19 +83,6 @@ "npm": "^10.8.x" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -119,20 +106,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", - "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", + "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.28.0", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -148,12 +136,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", - "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.0", - "@babel/types": "^7.28.0", + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -190,17 +179,17 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", - "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", + "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.27.1", + "@babel/traverse": "^7.28.3", "semver": "^6.3.1" }, "engines": { @@ -277,13 +266,14 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -402,23 +392,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", - "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", - "@babel/types": "^7.27.6" + "@babel/types": "^7.28.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", - "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.28.0" + "@babel/types": "^7.28.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -491,13 +483,13 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz", - "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", + "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -880,12 +872,12 @@ } }, "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz", - "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", + "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", "license": "MIT", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.28.3", "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { @@ -896,16 +888,17 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.0.tgz", - "integrity": "sha512-IjM1IoJNw72AZFlj33Cu8X0q2XK/6AaVC3jQu+cgQ5lThWD5ajnuUAml80dqRmOhmPkTH8uAwnpMu9Rvj0LTRA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", + "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", + "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.28.0" + "@babel/traverse": "^7.28.4" }, "engines": { "node": ">=6.9.0" @@ -1465,9 +1458,10 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.0.tgz", - "integrity": "sha512-LOAozRVbqxEVjSKfhGnuLoE4Kz4Oc5UJzuvFUhSsQzdCdaAQu06mG8zDv2GFSerM62nImUZ7K92vxnQcLSDlCQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", + "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1510,9 +1504,10 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.0.tgz", - "integrity": "sha512-dGopk9nZrtCs2+nfIem25UuHyt5moSJamArzIoh9/vezUQPmYDOzjaHDCkAzuGJibCIkPup8rMT2+wYB6S73cA==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.3.tgz", + "integrity": "sha512-Y6ab1kGqZ0u42Zv/4a7l0l72n9DKP/MKoKWaUSBylrhNZO2prYuqFOLbn5aW5SIFXwSH93yfjbgllL8lxuGKLg==", + "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", @@ -1668,9 +1663,10 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.0.tgz", - "integrity": "sha512-VmaxeGOwuDqzLl5JUkIRM1X2Qu2uKGxHEQWh+cvvbl7JuJRgKGJSfsEF/bUaxFhJl/XAyxBe7q7qSuTbKFuCyg==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.3.tgz", + "integrity": "sha512-ROiDcM+GbYVPYBOeCR6uBXKkQpBExLl8k9HO1ygXEyds39j+vCCsjmj7S8GOniZQlEs81QlkdJZe76IpLSiqpg==", + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", @@ -1680,7 +1676,7 @@ "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-import-assertions": "^7.27.1", "@babel/plugin-syntax-import-attributes": "^7.27.1", @@ -1691,8 +1687,8 @@ "@babel/plugin-transform-block-scoped-functions": "^7.27.1", "@babel/plugin-transform-block-scoping": "^7.28.0", "@babel/plugin-transform-class-properties": "^7.27.1", - "@babel/plugin-transform-class-static-block": "^7.27.1", - "@babel/plugin-transform-classes": "^7.28.0", + "@babel/plugin-transform-class-static-block": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.3", "@babel/plugin-transform-computed-properties": "^7.27.1", "@babel/plugin-transform-destructuring": "^7.28.0", "@babel/plugin-transform-dotall-regex": "^7.27.1", @@ -1724,7 +1720,7 @@ "@babel/plugin-transform-private-methods": "^7.27.1", "@babel/plugin-transform-private-property-in-object": "^7.27.1", "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.0", + "@babel/plugin-transform-regenerator": "^7.28.3", "@babel/plugin-transform-regexp-modifiers": "^7.27.1", "@babel/plugin-transform-reserved-words": "^7.27.1", "@babel/plugin-transform-shorthand-properties": "^7.27.1", @@ -1785,9 +1781,10 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1807,16 +1804,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", - "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", + "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.0", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/types": "^7.28.0", + "@babel/types": "^7.28.4", "debug": "^4.3.1" }, "engines": { @@ -1824,9 +1822,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -2816,6 +2814,16 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -2848,9 +2856,10 @@ "license": "MIT" }, "node_modules/@mongodb-js/saslprep": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz", - "integrity": "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.1.tgz", + "integrity": "sha512-6nZrq5kfAz0POWyhljnbWQQJQ5uT8oE2ddX303q1uY0tWsivWKgBDXBBvuFPwOqRRalXJuVO9EjOdVtuhLX0zg==", + "license": "MIT", "dependencies": { "sparse-bitfield": "^3.0.3" } @@ -3133,12 +3142,14 @@ "node_modules/@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", - "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" }, "node_modules/@types/whatwg-url": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "license": "MIT", "dependencies": { "@types/webidl-conversions": "*" } @@ -4592,6 +4603,7 @@ "version": "6.10.4", "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", + "license": "Apache-2.0", "engines": { "node": ">=16.20.1" } @@ -5149,9 +5161,9 @@ } }, "node_modules/core-js": { - "version": "3.44.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.44.0.tgz", - "integrity": "sha512-aFCtd4l6GvAXwVEh3XbbVqJGHDJt0OZRa+5ePGx3LLwi12WfexqQxcsohb2wgsa/92xtl19Hd66G/L+TaAxDMw==", + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.46.0.tgz", + "integrity": "sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -6982,9 +6994,9 @@ } }, "node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -9979,12 +9991,12 @@ } }, "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==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/marked-subsuper-text/-/marked-subsuper-text-1.0.4.tgz", + "integrity": "sha512-sSNZpQZUNyV6j6i40Sip207ywbvMwoTY8md94t+snBGMahhOz9QiAke738dJCz+um3d4QkpGBI21ke17c56fUQ==", "license": "MIT", "peerDependencies": { - "marked": ">=3 <16" + "marked": ">=3 <17" } }, "node_modules/markedLegacy": { @@ -10050,7 +10062,8 @@ "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT" }, "node_modules/meow": { "version": "13.2.0", @@ -10317,6 +10330,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "license": "Apache-2.0", "dependencies": { "@types/whatwg-url": "^11.0.2", "whatwg-url": "^14.1.0 || ^13.0.0" @@ -10326,6 +10340,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "license": "MIT", "dependencies": { "punycode": "^2.3.1" }, @@ -10337,6 +10352,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" } @@ -10345,6 +10361,7 @@ "version": "14.2.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "license": "MIT", "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" @@ -10354,14 +10371,14 @@ } }, "node_modules/mongoose": { - "version": "8.16.3", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.16.3.tgz", - "integrity": "sha512-p2JOsRQG7j0vXhLpsWw5Slm2VnDeJK8sRyqSyegk5jQujuP9BTOZ1Di9VX/0lYfBhZ2DpAExi51QTd4pIqSgig==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.19.1.tgz", + "integrity": "sha512-oB7hGQJn4f8aebqE7mhE54EReb5cxVgpCxQCQj0K/cK3q4J3Tg08nFP6sM52nJ4Hlm8jsDnhVYpqIITZUAhckQ==", "license": "MIT", "dependencies": { "bson": "^6.10.4", "kareem": "2.6.3", - "mongodb": "~6.17.0", + "mongodb": "~6.20.0", "mpath": "0.9.0", "mquery": "5.0.0", "ms": "2.1.3", @@ -10379,6 +10396,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", "optional": true, "peer": true, "dependencies": { @@ -10392,6 +10410,7 @@ "version": "5.1.3", "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", + "license": "Apache-2.0", "optional": true, "peer": true, "dependencies": { @@ -10408,6 +10427,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", + "license": "Apache-2.0", "optional": true, "peer": true, "dependencies": { @@ -10422,6 +10442,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", "optional": true, "peer": true, "dependencies": { @@ -10433,13 +10454,14 @@ } }, "node_modules/mongoose/node_modules/mongodb": { - "version": "6.17.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.17.0.tgz", - "integrity": "sha512-neerUzg/8U26cgruLysKEjJvoNSXhyID3RvzvdcpsIi2COYM3FS3o9nlH7fxFtefTb942dX3W9i37oPfCVj4wA==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.20.0.tgz", + "integrity": "sha512-Tl6MEIU3K4Rq3TSHd+sZQqRBoGlFsOgNrH5ltAcFBV62Re3Fd+FcaVf8uSEQFOJ51SDowDVttBTONMfoYWrWlQ==", + "license": "Apache-2.0", "dependencies": { - "@mongodb-js/saslprep": "^1.1.9", + "@mongodb-js/saslprep": "^1.3.0", "bson": "^6.10.4", - "mongodb-connection-string-url": "^3.0.0" + "mongodb-connection-string-url": "^3.0.2" }, "engines": { "node": ">=16.20.1" @@ -10450,7 +10472,7 @@ "gcp-metadata": "^5.2.0", "kerberos": "^2.0.1", "mongodb-client-encryption": ">=6.0.0 <7", - "snappy": "^7.2.2", + "snappy": "^7.3.2", "socks": "^2.7.1" }, "peerDependenciesMeta": { @@ -10511,9 +10533,9 @@ "optional": true }, "node_modules/nanoid": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", - "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz", + "integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==", "funding": [ { "type": "github", @@ -11873,9 +11895,10 @@ "license": "MIT" }, "node_modules/react-router": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.3.tgz", - "integrity": "sha512-zf45LZp5skDC6I3jDLXQUu0u26jtuP4lEGbc7BbdyxenBN1vJSTA18czM2D+h5qyMBuMrD+9uB+mU37HIoKGRA==", + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.4.tgz", + "integrity": "sha512-SD3G8HKviFHg9xj7dNODUKDFgpG4xqD5nhyd0mYoB5iISepuZAvzSr8ywxgxKJ52yRzf/HWtVHc9AWwoTbljvA==", + "license": "MIT", "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" @@ -12924,6 +12947,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", "dependencies": { "memory-pager": "^1.0.2" } diff --git a/package.json b/package.json index c897d842d..9b31a50f9 100644 --- a/package.json +++ b/package.json @@ -83,11 +83,11 @@ ] }, "dependencies": { - "@babel/core": "^7.27.1", - "@babel/plugin-transform-runtime": "^7.28.0", - "@babel/preset-env": "^7.28.0", + "@babel/core": "^7.28.4", + "@babel/plugin-transform-runtime": "^7.28.3", + "@babel/preset-env": "^7.28.3", "@babel/preset-react": "^7.27.1", - "@babel/runtime": "^7.27.6", + "@babel/runtime": "^7.28.4", "@dmsnell/diff-match-patch": "^1.1.0", "@googleapis/drive": "^13.0.1", "@sanity/diff-match-patch": "^3.2.0", @@ -95,7 +95,7 @@ "classnames": "^2.5.1", "codemirror": "^5.65.6", "cookie-parser": "^1.4.7", - "core-js": "^3.44.0", + "core-js": "^3.46.0", "cors": "^2.8.5", "create-react-class": "^15.7.0", "dedent-tabs": "^0.10.3", @@ -104,7 +104,7 @@ "express-async-handler": "^1.2.0", "express-static-gzip": "3.0.0", "fflate": "^0.8.2", - "fs-extra": "11.3.0", + "fs-extra": "11.3.2", "hash-wasm": "^4.12.0", "idb-keyval": "^6.2.2", "js-yaml": "^4.1.0", @@ -119,16 +119,16 @@ "marked-gfm-heading-id": "^4.1.2", "marked-nonbreaking-spaces": "^1.0.1", "marked-smartypants-lite": "^1.0.3", - "marked-subsuper-text": "^1.0.3", + "marked-subsuper-text": "^1.0.4", "markedLegacy": "npm:marked@^0.3.19", "moment": "^2.30.1", - "mongoose": "^8.16.3", - "nanoid": "5.1.5", + "mongoose": "^8.19.1", + "nanoid": "5.1.6", "nconf": "^0.13.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-frame-component": "^4.1.3", - "react-router": "^7.6.3", + "react-router": "^7.9.4", "romans": "^3.1.0", "sanitize-filename": "1.6.3", "superagent": "^10.2.1", From b864e9b677b92a04d7697788567d3c2e2e25b2df Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 13 Oct 2025 20:05:09 -0400 Subject: [PATCH 83/95] Update diceFont.js to use d10 instead of dper --- themes/fonts/iconFonts/diceFont.js | 202 ++++++++++++++--------------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/themes/fonts/iconFonts/diceFont.js b/themes/fonts/iconFonts/diceFont.js index d6f5a3291..65b56a62a 100644 --- a/themes/fonts/iconFonts/diceFont.js +++ b/themes/fonts/iconFonts/diceFont.js @@ -92,107 +92,107 @@ const diceFont = { 'df_solid_small_dot_d6_4' : 'df solid-small-dot-d6-4', 'df_solid_small_dot_d6_5' : 'df solid-small-dot-d6-5', 'df_solid_small_dot_d6_6' : 'df solid-small-dot-d6-6', - 'df_dper_00' : 'df d10-00', - 'df_dper_01' : 'df d10-01', - 'df_dper_02' : 'df d10-02', - 'df_dper_03' : 'df d10-03', - 'df_dper_04' : 'df d10-04', - 'df_dper_05' : 'df d10-05', - 'df_dper_06' : 'df d10-06', - 'df_dper_07' : 'df d10-07', - 'df_dper_08' : 'df d10-08', - 'df_dper_09' : 'df d10-09', - 'df_dper_10' : 'df d10-10', - 'df_dper_11' : 'df d10-11', - 'df_dper_12' : 'df d10-12', - 'df_dper_13' : 'df d10-13', - 'df_dper_14' : 'df d10-14', - 'df_dper_15' : 'df d10-15', - 'df_dper_16' : 'df d10-16', - 'df_dper_17' : 'df d10-17', - 'df_dper_18' : 'df d10-18', - 'df_dper_19' : 'df d10-19', - 'df_dper_20' : 'df d10-20', - 'df_dper_21' : 'df d10-21', - 'df_dper_22' : 'df d10-22', - 'df_dper_23' : 'df d10-23', - 'df_dper_24' : 'df d10-24', - 'df_dper_25' : 'df d10-25', - 'df_dper_26' : 'df d10-26', - 'df_dper_27' : 'df d10-27', - 'df_dper_28' : 'df d10-28', - 'df_dper_29' : 'df d10-29', - 'df_dper_30' : 'df d10-30', - 'df_dper_31' : 'df d10-31', - 'df_dper_32' : 'df d10-32', - 'df_dper_33' : 'df d10-33', - 'df_dper_34' : 'df d10-34', - 'df_dper_35' : 'df d10-35', - 'df_dper_36' : 'df d10-36', - 'df_dper_37' : 'df d10-37', - 'df_dper_38' : 'df d10-38', - 'df_dper_39' : 'df d10-39', - 'df_dper_40' : 'df d10-40', - 'df_dper_41' : 'df d10-41', - 'df_dper_42' : 'df d10-42', - 'df_dper_43' : 'df d10-43', - 'df_dper_44' : 'df d10-44', - 'df_dper_45' : 'df d10-45', - 'df_dper_46' : 'df d10-46', - 'df_dper_47' : 'df d10-47', - 'df_dper_48' : 'df d10-48', - 'df_dper_49' : 'df d10-49', - 'df_dper_50' : 'df d10-50', - 'df_dper_51' : 'df d10-51', - 'df_dper_52' : 'df d10-52', - 'df_dper_53' : 'df d10-53', - 'df_dper_54' : 'df d10-54', - 'df_dper_55' : 'df d10-55', - 'df_dper_56' : 'df d10-56', - 'df_dper_57' : 'df d10-57', - 'df_dper_58' : 'df d10-58', - 'df_dper_59' : 'df d10-59', - 'df_dper_60' : 'df d10-60', - 'df_dper_61' : 'df d10-61', - 'df_dper_62' : 'df d10-62', - 'df_dper_63' : 'df d10-63', - 'df_dper_64' : 'df d10-64', - 'df_dper_65' : 'df d10-65', - 'df_dper_66' : 'df d10-66', - 'df_dper_67' : 'df d10-67', - 'df_dper_68' : 'df d10-68', - 'df_dper_69' : 'df d10-69', - 'df_dper_70' : 'df d10-70', - 'df_dper_71' : 'df d10-71', - 'df_dper_72' : 'df d10-72', - 'df_dper_73' : 'df d10-73', - 'df_dper_74' : 'df d10-74', - 'df_dper_75' : 'df d10-75', - 'df_dper_76' : 'df d10-76', - 'df_dper_77' : 'df d10-77', - 'df_dper_78' : 'df d10-78', - 'df_dper_79' : 'df d10-79', - 'df_dper_80' : 'df d10-80', - 'df_dper_81' : 'df d10-81', - 'df_dper_82' : 'df d10-82', - 'df_dper_83' : 'df d10-83', - 'df_dper_84' : 'df d10-84', - 'df_dper_85' : 'df d10-85', - 'df_dper_86' : 'df d10-86', - 'df_dper_87' : 'df d10-87', - 'df_dper_88' : 'df d10-88', - 'df_dper_89' : 'df d10-89', - 'df_dper_90' : 'df d10-90', - 'df_dper_91' : 'df d10-91', - 'df_dper_92' : 'df d10-92', - 'df_dper_93' : 'df d10-93', - 'df_dper_94' : 'df d10-94', - 'df_dper_95' : 'df d10-95', - 'df_dper_96' : 'df d10-96', - 'df_dper_97' : 'df d10-97', - 'df_dper_98' : 'df d10-98', - 'df_dper_99' : 'df d10-99', - 'df_dper_100' : 'df d10-100' + 'df_d10_00' : 'df d10-00', + 'df_d10_01' : 'df d10-01', + 'df_d10_02' : 'df d10-02', + 'df_d10_03' : 'df d10-03', + 'df_d10_04' : 'df d10-04', + 'df_d10_05' : 'df d10-05', + 'df_d10_06' : 'df d10-06', + 'df_d10_07' : 'df d10-07', + 'df_d10_08' : 'df d10-08', + 'df_d10_09' : 'df d10-09', + 'df_d10_10' : 'df d10-10', + 'df_d10_11' : 'df d10-11', + 'df_d10_12' : 'df d10-12', + 'df_d10_13' : 'df d10-13', + 'df_d10_14' : 'df d10-14', + 'df_d10_15' : 'df d10-15', + 'df_d10_16' : 'df d10-16', + 'df_d10_17' : 'df d10-17', + 'df_d10_18' : 'df d10-18', + 'df_d10_19' : 'df d10-19', + 'df_d10_20' : 'df d10-20', + 'df_d10_21' : 'df d10-21', + 'df_d10_22' : 'df d10-22', + 'df_d10_23' : 'df d10-23', + 'df_d10_24' : 'df d10-24', + 'df_d10_25' : 'df d10-25', + 'df_d10_26' : 'df d10-26', + 'df_d10_27' : 'df d10-27', + 'df_d10_28' : 'df d10-28', + 'df_d10_29' : 'df d10-29', + 'df_d10_30' : 'df d10-30', + 'df_d10_31' : 'df d10-31', + 'df_d10_32' : 'df d10-32', + 'df_d10_33' : 'df d10-33', + 'df_d10_34' : 'df d10-34', + 'df_d10_35' : 'df d10-35', + 'df_d10_36' : 'df d10-36', + 'df_d10_37' : 'df d10-37', + 'df_d10_38' : 'df d10-38', + 'df_d10_39' : 'df d10-39', + 'df_d10_40' : 'df d10-40', + 'df_d10_41' : 'df d10-41', + 'df_d10_42' : 'df d10-42', + 'df_d10_43' : 'df d10-43', + 'df_d10_44' : 'df d10-44', + 'df_d10_45' : 'df d10-45', + 'df_d10_46' : 'df d10-46', + 'df_d10_47' : 'df d10-47', + 'df_d10_48' : 'df d10-48', + 'df_d10_49' : 'df d10-49', + 'df_d10_50' : 'df d10-50', + 'df_d10_51' : 'df d10-51', + 'df_d10_52' : 'df d10-52', + 'df_d10_53' : 'df d10-53', + 'df_d10_54' : 'df d10-54', + 'df_d10_55' : 'df d10-55', + 'df_d10_56' : 'df d10-56', + 'df_d10_57' : 'df d10-57', + 'df_d10_58' : 'df d10-58', + 'df_d10_59' : 'df d10-59', + 'df_d10_60' : 'df d10-60', + 'df_d10_61' : 'df d10-61', + 'df_d10_62' : 'df d10-62', + 'df_d10_63' : 'df d10-63', + 'df_d10_64' : 'df d10-64', + 'df_d10_65' : 'df d10-65', + 'df_d10_66' : 'df d10-66', + 'df_d10_67' : 'df d10-67', + 'df_d10_68' : 'df d10-68', + 'df_d10_69' : 'df d10-69', + 'df_d10_70' : 'df d10-70', + 'df_d10_71' : 'df d10-71', + 'df_d10_72' : 'df d10-72', + 'df_d10_73' : 'df d10-73', + 'df_d10_74' : 'df d10-74', + 'df_d10_75' : 'df d10-75', + 'df_d10_76' : 'df d10-76', + 'df_d10_77' : 'df d10-77', + 'df_d10_78' : 'df d10-78', + 'df_d10_79' : 'df d10-79', + 'df_d10_80' : 'df d10-80', + 'df_d10_81' : 'df d10-81', + 'df_d10_82' : 'df d10-82', + 'df_d10_83' : 'df d10-83', + 'df_d10_84' : 'df d10-84', + 'df_d10_85' : 'df d10-85', + 'df_d10_86' : 'df d10-86', + 'df_d10_87' : 'df d10-87', + 'df_d10_88' : 'df d10-88', + 'df_d10_89' : 'df d10-89', + 'df_d10_90' : 'df d10-90', + 'df_d10_91' : 'df d10-91', + 'df_d10_92' : 'df d10-92', + 'df_d10_93' : 'df d10-93', + 'df_d10_94' : 'df d10-94', + 'df_d10_95' : 'df d10-95', + 'df_d10_96' : 'df d10-96', + 'df_d10_97' : 'df d10-97', + 'df_d10_98' : 'df d10-98', + 'df_d10_99' : 'df d10-99', + 'df_d10_100' : 'df d10-100' }; export default diceFont; \ No newline at end of file From 43e465ceb83abcadb576199c049649ddb61f9312 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 13 Oct 2025 20:05:42 -0400 Subject: [PATCH 84/95] Rename font to match format of existing diceFont font file. --- .../{dicefont-D100.woff2 => diceFontD100.woff2} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename themes/fonts/iconFonts/{dicefont-D100.woff2 => diceFontD100.woff2} (100%) diff --git a/themes/fonts/iconFonts/dicefont-D100.woff2 b/themes/fonts/iconFonts/diceFontD100.woff2 similarity index 100% rename from themes/fonts/iconFonts/dicefont-D100.woff2 rename to themes/fonts/iconFonts/diceFontD100.woff2 From d1f5c9da0d362de630b6c26ccde7e45f543a98cd Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 13 Oct 2025 20:06:13 -0400 Subject: [PATCH 85/95] Update diceFont.less to use DiceFont100 instead of dicefont-percent --- themes/fonts/iconFonts/diceFont.less | 230 +++++++++++++-------------- 1 file changed, 114 insertions(+), 116 deletions(-) diff --git a/themes/fonts/iconFonts/diceFont.less b/themes/fonts/iconFonts/diceFont.less index 389ea3156..8b20e0ab8 100644 --- a/themes/fonts/iconFonts/diceFont.less +++ b/themes/fonts/iconFonts/diceFont.less @@ -7,8 +7,8 @@ } @font-face { - font-family : 'dicefont-percent'; - src : url('../../../fonts/iconFonts/dicefont-D100.woff') format('woff'); + font-family : 'DiceFontD100'; + src : url('../../../fonts/iconFonts/diceFontD100.woff2') format('woff2'); font-weight : normal; font-style : normal; font-display : block; @@ -114,566 +114,564 @@ // Replacement d10 &.d10-0::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e900'; } &.d10-1::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e901'; } &.d10-2::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e902'; } &.d10-3::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e903'; } &.d10-4::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e904'; } &.d10-5::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e905'; } &.d10-6::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e906'; } &.d10-7::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e907'; } &.d10-8::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e908'; } &.d10-9::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e909'; } &.d10-10::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e90a'; } // d100 &.d10-00::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e90b'; } &.d10-01::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e90c'; } &.d10-02::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e90d'; } &.d10-03::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e90e'; } &.d10-04::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e90f'; } &.d10-05::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e910'; } &.d10-06::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e911'; } &.d10-07::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e912'; } &.d10-08::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e913'; } &.d10-09::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e914'; } &.d10-10::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e915'; } &.d10-11::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e916'; } &.d10-12::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e917'; } &.d10-13::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e918'; } &.d10-14::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e919'; } &.d10-15::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e91a'; } &.d10-16::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e91b'; } &.d10-17::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e91c'; } &.d10-18::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e91d'; } &.d10-19::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e91e'; } &.d10-20::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e91f'; } &.d10-21::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e920'; } &.d10-22::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e921'; } &.d10-23::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e922'; } &.d10-24::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e923'; } &.d10-25::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e924'; } &.d10-26::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e925'; } &.d10-27::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e926'; } &.d10-28::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e927'; } &.d10-29::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e928'; } &.d10-30::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e929'; } &.d10-31::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e92a'; } &.d10-32::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e92b'; } &.d10-33::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e92c'; } &.d10-34::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e92d'; } &.d10-35::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e92e'; } &.d10-36::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e92f'; } &.d10-37::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e930'; } &.d10-38::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e931'; } &.d10-39::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e932'; } &.d10-40::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e933'; } &.d10-41::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e934'; } &.d10-42::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e935'; } &.d10-43::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e936'; } &.d10-44::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e937'; } &.d10-45::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e938'; } &.d10-46::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e939'; } &.d10-47::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e93a'; } &.d10-48::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e93b'; } &.d10-49::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e93c'; } &.d10-50::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e93d'; } &.d10-51::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e93e'; } &.d10-52::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e93f'; } &.d10-53::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e940'; } &.d10-54::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e941'; } &.d10-55::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e942'; } &.d10-56::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e943'; } &.d10-57::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e944'; } &.d10-58::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e945'; } &.d10-59::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e946'; } &.d10-60::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e947'; } &.d10-61::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e948'; } &.d10-62::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e949'; } &.d10-63::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e94a'; } &.d10-64::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e94b'; } &.d10-65::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e94c'; } &.d10-66::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e94d'; } &.d10-67::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e94e'; } &.d10-68::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e94f'; } &.d10-69::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e950'; } &.d10-70::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e951'; } &.d10-71::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e952'; } &.d10-72::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e953'; } &.d10-73::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e954'; } &.d10-74::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e955'; } &.d10-75::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e956'; } &.d10-76::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e957'; } &.d10-77::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e958'; } &.d10-78::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e959'; } &.d10-79::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e95a'; } &.d10-80::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e95b'; } &.d10-81::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e95c'; } &.d10-82::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e95d'; } &.d10-83::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e95e'; } &.d10-84::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e95f'; } &.d10-85::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e960'; } &.d10-86::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e961'; } &.d10-87::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e962'; } &.d10-88::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e963'; } &.d10-89::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e964'; } &.d10-90::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e965'; } &.d10-91::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e966'; } &.d10-92::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e967'; } &.d10-93::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e968'; } &.d10-94::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e969'; } &.d10-95::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e96a'; } &.d10-96::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e96b'; } &.d10-97::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e96c'; } &.d10-98::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e96d'; } &.d10-99::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e96e'; } &.d10-100::before { - font-family : 'dicefont-percent'; + font-family : 'DiceFontD100'; content : '\e96f'; } - - } \ No newline at end of file From 6c8265688f33d518556f8ead2d23e2021df19467 Mon Sep 17 00:00:00 2001 From: Trevor Buckner Date: Mon, 13 Oct 2025 20:10:31 -0400 Subject: [PATCH 86/95] Restore missing empty d10 --- themes/fonts/iconFonts/diceFont.less | 1 + 1 file changed, 1 insertion(+) diff --git a/themes/fonts/iconFonts/diceFont.less b/themes/fonts/iconFonts/diceFont.less index 8b20e0ab8..a49be2da3 100644 --- a/themes/fonts/iconFonts/diceFont.less +++ b/themes/fonts/iconFonts/diceFont.less @@ -33,6 +33,7 @@ &.F-minus::before { content : '\f191'; } &.F-plus::before { content : '\f192'; } &.F-zero::before { content : '\f193'; } + &.d10::before { content : '\f194'; } &.d12::before { content : '\f195'; } &.d12-1::before { content : '\f10b'; } &.d12-10::before { content : '\f10c'; } From 9f48755f800e89820b18c16e802a27aa0c0f021d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 03:03:35 +0000 Subject: [PATCH 87/95] Bump @googleapis/drive from 13.0.1 to 18.0.0 Bumps [@googleapis/drive](https://github.com/googleapis/google-api-nodejs-client) from 13.0.1 to 18.0.0. - [Release notes](https://github.com/googleapis/google-api-nodejs-client/releases) - [Changelog](https://github.com/googleapis/google-api-nodejs-client/blob/main/.release-please-manifest.json) - [Commits](https://github.com/googleapis/google-api-nodejs-client/compare/iam-v13.0.1...run-v18.0.0) --- updated-dependencies: - dependency-name: "@googleapis/drive" dependency-version: 18.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- package-lock.json | 52 +++++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1e8e72488..4181aefa4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "@babel/preset-react": "^7.27.1", "@babel/runtime": "^7.28.4", "@dmsnell/diff-match-patch": "^1.1.0", - "@googleapis/drive": "^13.0.1", + "@googleapis/drive": "^18.0.0", "@sanity/diff-match-patch": "^3.2.0", "body-parser": "^2.2.0", "classnames": "^2.5.1", @@ -2123,11 +2123,12 @@ } }, "node_modules/@googleapis/drive": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-13.0.1.tgz", - "integrity": "sha512-n6smJQyKTllRbXI8Xe/9IsCI+tuY20bhs9lircO+t2+a4k2t08NCZuujsBgIBTiE29v2kDzrrKdsuPxg5lUmXw==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-18.0.0.tgz", + "integrity": "sha512-nk4TirsHttwZSOjBEBjltCPDKUqwFso59G3WitNE+EGNVSVseSEq981f8Dmjq2ah0/fk3i206wuCU4PUCwcoTQ==", + "license": "Apache-2.0", "dependencies": { - "googleapis-common": "^8.0.2-rc.0" + "googleapis-common": "^8.0.0" }, "engines": { "node": ">=12.0.0" @@ -4621,7 +4622,8 @@ "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" }, "node_modules/buffer-from": { "version": "1.1.2", @@ -5379,6 +5381,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", "engines": { "node": ">= 12" } @@ -5784,6 +5787,7 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" } @@ -6771,6 +6775,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -6939,6 +6944,7 @@ "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", "dependencies": { "fetch-blob": "^3.1.2" }, @@ -7068,9 +7074,10 @@ } }, "node_modules/gaxios": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.1.tgz", - "integrity": "sha512-Odju3uBUJyVCkW64nLD4wKLhbh93bh6vIg/ZIXkWiLPBrdgtc65+tls/qml+un3pr6JqYVFDZbbmLDQT68rTOQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.2.tgz", + "integrity": "sha512-/Szrn8nr+2TsQT1Gp8iIe/BEytJmbyfrbFh419DfGQSkEgNEhbPi7JRJuughjkTzPWgU9gBQf5AVu3DbHt0OXA==", + "license": "Apache-2.0", "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", @@ -7084,6 +7091,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -7101,6 +7109,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-7.0.1.tgz", "integrity": "sha512-UcO3kefx6dCcZkgcTGgVOTFb7b1LlQ02hY1omMjjrrBzkajRMCFgYOjs7J71WqnuG1k2b+9ppGL7FsOfhZMQKQ==", + "license": "Apache-2.0", "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", @@ -7368,9 +7377,10 @@ "license": "MIT" }, "node_modules/google-auth-library": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.1.0.tgz", - "integrity": "sha512-GspVjZj1RbyRWpQ9FbAXMKjFGzZwDKnUHi66JJ+tcjcu5/xYAP1pdlWotCuIkMwjfVsxxDvsGZXGLzRt72D0sQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.4.0.tgz", + "integrity": "sha512-CmIrSy1bqMQUsPmA9+hcSbAXL80cFhu40cGMUjCaLpNKVzzvi+0uAHq8GNZxkoGYIsTX4ZQ7e4aInAqWxgn4fg==", + "license": "Apache-2.0", "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", @@ -7388,18 +7398,20 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.1.tgz", "integrity": "sha512-rcX58I7nqpu4mbKztFeOAObbomBbHU2oIb/d3tJfF3dizGSApqtSwYJigGCooHdnMyQBIw8BrWyK96w3YXgr6A==", + "license": "Apache-2.0", "engines": { "node": ">=14" } }, "node_modules/googleapis-common": { - "version": "8.0.2-rc.0", - "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-8.0.2-rc.0.tgz", - "integrity": "sha512-JTcxRvmFa9Ec1uyfMEimEMeeKq1sHNZX3vn2qmoUMtnvixXXvcqTcbDZvEZXkEWpGlPlOf4joyep6/qs0BrLyg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-8.0.0.tgz", + "integrity": "sha512-66if47It7y+Sab3HMkwEXx1kCq9qUC9px8ZXoj1CMrmLmUw81GpbnsNlXnlyZyGbGPGcj+tDD9XsZ23m7GLaJQ==", + "license": "Apache-2.0", "dependencies": { "extend": "^3.0.2", "gaxios": "^7.0.0-rc.4", - "google-auth-library": "^10.0.0-rc.1", + "google-auth-library": "^10.1.0", "qs": "^6.7.0", "url-template": "^2.0.8" }, @@ -7429,6 +7441,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-8.0.0.tgz", "integrity": "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw==", + "license": "MIT", "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" @@ -9613,6 +9626,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", @@ -9623,6 +9637,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "license": "MIT", "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" @@ -10742,6 +10757,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "engines": { "node": ">=10.5.0" } @@ -14433,7 +14449,8 @@ "node_modules/url-template": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", - "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==" + "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==", + "license": "BSD" }, "node_modules/url/node_modules/punycode": { "version": "1.4.1", @@ -14891,6 +14908,7 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", "engines": { "node": ">= 8" } diff --git a/package.json b/package.json index 9b31a50f9..666832db8 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "@babel/preset-react": "^7.27.1", "@babel/runtime": "^7.28.4", "@dmsnell/diff-match-patch": "^1.1.0", - "@googleapis/drive": "^13.0.1", + "@googleapis/drive": "^18.0.0", "@sanity/diff-match-patch": "^3.2.0", "body-parser": "^2.2.0", "classnames": "^2.5.1", From f604d0a41f3b8342ea08f86df46033cc6dffe995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 15 Oct 2025 20:52:34 +0200 Subject: [PATCH 88/95] handle getid uncatched error --- server/homebrew.api.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/homebrew.api.js b/server/homebrew.api.js index c931cb657..921b25d96 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -481,6 +481,7 @@ const api = { await HomebrewModel.deleteOne({ editId: id }); return next(); } + return next(); } let brew = req.brew; From 3f29eb227a9ca7e4167c4d6ad1a9d738372db6f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 15 Oct 2025 21:22:45 +0200 Subject: [PATCH 89/95] next for throw --- server/homebrew.api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/homebrew.api.js b/server/homebrew.api.js index 921b25d96..2cedb5972 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -481,7 +481,7 @@ const api = { await HomebrewModel.deleteOne({ editId: id }); return next(); } - return next(); + throw(err); } let brew = req.brew; From 27861ba79659bcf90c9af54dfccb252df78ee7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 15 Oct 2025 21:50:01 +0200 Subject: [PATCH 90/95] add uppercase style to footnotes --- themes/V3/5ePHB/style.less | 1 + 1 file changed, 1 insertion(+) diff --git a/themes/V3/5ePHB/style.less b/themes/V3/5ePHB/style.less index 555866ba4..74856cdac 100644 --- a/themes/V3/5ePHB/style.less +++ b/themes/V3/5ePHB/style.less @@ -418,6 +418,7 @@ color : var(--HB_Color_Footnotes); } .footnote { + text-transform: uppercase; position : absolute; right : 80px; bottom : 32px; From d728126480211ef3b1f8c0c59e0fcae385d333ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 15 Oct 2025 22:01:13 +0200 Subject: [PATCH 91/95] initial commit --- shared/naturalcrit/codeEditor/codeEditor.less | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/shared/naturalcrit/codeEditor/codeEditor.less b/shared/naturalcrit/codeEditor/codeEditor.less index 2a57ae8e6..c8e60974b 100644 --- a/shared/naturalcrit/codeEditor/codeEditor.less +++ b/shared/naturalcrit/codeEditor/codeEditor.less @@ -38,6 +38,11 @@ animation-duration : 0.4s; } + .CodeMirror-search-field { + width:25em !important; + outline:1px inset #00000055 !important; + } + //.cm-tab { // background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAQAAACOs/baAAAARUlEQVR4nGJgIAG8JkXxUAcCtDWemcGR1lY4MvgzCEKY7jSBjgxBDAG09UEQzAe0AMwMHrSOAwEGRtpaMIwAAAAA//8DAG4ID9EKs6YqAAAAAElFTkSuQmCC) no-repeat right; //} From 3c3ca7981b2f94c855e0fd92ea644697015d5b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 15 Oct 2025 22:24:07 +0200 Subject: [PATCH 92/95] initial commit --- client/homebrew/navbar/navbar.less | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/homebrew/navbar/navbar.less b/client/homebrew/navbar/navbar.less index aa233d631..803e6d592 100644 --- a/client/homebrew/navbar/navbar.less +++ b/client/homebrew/navbar/navbar.less @@ -37,7 +37,10 @@ &:has(.brewTitle) { flex-grow : 1; - min-width : 300px; + min-width : 300px; + } + >.brewTitle { + cursor:auto; } } // "NaturalCrit" logo @@ -111,9 +114,9 @@ font-weight : 800; color : white; text-align : center; - text-transform : initial; + text-transform : initial; white-space : nowrap; - background-color : transparent; + background-color : transparent; } // "The Homebrewery" logo From 47c84428c72738556c2d145da0b5de9760c8d2b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 15 Oct 2025 22:24:45 +0200 Subject: [PATCH 93/95] initial commit --- client/homebrew/navbar/navbar.less | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/homebrew/navbar/navbar.less b/client/homebrew/navbar/navbar.less index aa233d631..7b0217bf8 100644 --- a/client/homebrew/navbar/navbar.less +++ b/client/homebrew/navbar/navbar.less @@ -37,7 +37,10 @@ &:has(.brewTitle) { flex-grow : 1; - min-width : 300px; + min-width : 300px; + } + >.brewTitle { + cursor:auto; } } // "NaturalCrit" logo From 11d3cddff0c15421810ba6436edd98dab395e759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Losada=20Hern=C3=A1ndez?= Date: Wed, 15 Oct 2025 22:25:36 +0200 Subject: [PATCH 94/95] Revert "initial commit" This reverts commit 3c3ca7981b2f94c855e0fd92ea644697015d5b52. --- client/homebrew/navbar/navbar.less | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/client/homebrew/navbar/navbar.less b/client/homebrew/navbar/navbar.less index 803e6d592..aa233d631 100644 --- a/client/homebrew/navbar/navbar.less +++ b/client/homebrew/navbar/navbar.less @@ -37,10 +37,7 @@ &:has(.brewTitle) { flex-grow : 1; - min-width : 300px; - } - >.brewTitle { - cursor:auto; + min-width : 300px; } } // "NaturalCrit" logo @@ -114,9 +111,9 @@ font-weight : 800; color : white; text-align : center; - text-transform : initial; + text-transform : initial; white-space : nowrap; - background-color : transparent; + background-color : transparent; } // "The Homebrewery" logo From 7e4facb47852b5f6145287d16fe382a2e0127719 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Thu, 16 Oct 2025 10:45:00 -0500 Subject: [PATCH 95/95] Remove greater than and less than from evaluation. Use calc's more concise regex Remove errant space. --- shared/naturalcrit/markdown.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index 39722f4ee..5331a5f6e 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -185,7 +185,7 @@ const mustacheSpans = { start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token - const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\-\_\+\=]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; + const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-+*/()#%=?.&:!@$^;:\[\]_= ]*"|[\w\-+*/()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; const match = completeSpan.exec(src); if(match) { //Find closing delimiter @@ -242,7 +242,7 @@ const mustacheDivs = { start(src) { return src.match(/\n *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { const completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token - const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\-\_\+\= ]*"|[\w\-()#%. ]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; + const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-+*/()#%=?.&:!@$^;:\[\]_= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; const match = completeBlock.exec(src); if(match) { //Find closing delimiter @@ -297,7 +297,7 @@ const mustacheInjectInline = { level : 'inline', start(src) { return src.match(/ *{[^{\n]/)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\-\_\+\= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-+*/()#%=?.&:!@$^;:\[\]_= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1]; @@ -343,7 +343,7 @@ const mustacheInjectBlock = { level : 'block', start(src) { return src.match(/\n *{[^{\n]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-+*/()#%=?. ]*"|[\w\-+*/()#%.]*)|[^"=':{}\s]*)*))\1}/ym; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-+*/()#%=?.&:!@$^;:\[\]_= ]*"|[\w\-+*/()#%.]*)|[^"=':{}\s]*)*))\1}/ym; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1];