mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-06 01:22:44 +00:00
Merge branch 'master' into pr/3484
This commit is contained in:
@@ -11,6 +11,7 @@ const ToolBar = ({ onZoomChange, currentPage, onPageChange, totalPages })=>{
|
|||||||
|
|
||||||
const [zoomLevel, setZoomLevel] = useState(100);
|
const [zoomLevel, setZoomLevel] = useState(100);
|
||||||
const [pageNum, setPageNum] = useState(currentPage);
|
const [pageNum, setPageNum] = useState(currentPage);
|
||||||
|
const [toolsVisible, setToolsVisible] = useState(true);
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
onZoomChange(zoomLevel);
|
onZoomChange(zoomLevel);
|
||||||
@@ -66,8 +67,9 @@ const ToolBar = ({ onZoomChange, currentPage, onPageChange, totalPages })=>{
|
|||||||
return deltaZoom;
|
return deltaZoom;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='toolBar'>
|
<div className={`toolBar ${toolsVisible ? 'visible' : 'hidden'}`}>
|
||||||
|
<button className='toggleButton' title={`${toolsVisible ? 'Hide' : 'Show'} Preview Toolbar`} onClick={()=>{setToolsVisible(!toolsVisible)}}><i className='fas fa-glasses' /></button>
|
||||||
{/*v=====----------------------< Zoom Controls >---------------------=====v*/}
|
{/*v=====----------------------< Zoom Controls >---------------------=====v*/}
|
||||||
<div className='group'>
|
<div className='group'>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -15,6 +15,10 @@
|
|||||||
font-family : 'Open Sans', sans-serif;
|
font-family : 'Open Sans', sans-serif;
|
||||||
color : #CCCCCC;
|
color : #CCCCCC;
|
||||||
background-color : #555555;
|
background-color : #555555;
|
||||||
|
& > *:not(.toggleButton) {
|
||||||
|
opacity: 1;
|
||||||
|
transition: all .2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
.group {
|
.group {
|
||||||
box-sizing : border-box;
|
box-sizing : border-box;
|
||||||
@@ -100,4 +104,25 @@
|
|||||||
font-size:1.2em;
|
font-size:1.2em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
width: 32px;
|
||||||
|
transition: all .3s ease;
|
||||||
|
flex-wrap:nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: unset;
|
||||||
|
opacity: .5;
|
||||||
|
& > *:not(.toggleButton) {
|
||||||
|
opacity: 0;
|
||||||
|
transition: all .2s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button.toggleButton {
|
||||||
|
z-index : 5;
|
||||||
|
position:absolute;
|
||||||
|
left: 0;
|
||||||
|
width: 32px;
|
||||||
|
min-width: unset;
|
||||||
}
|
}
|
||||||
30
package-lock.json
generated
30
package-lock.json
generated
@@ -51,7 +51,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@stylistic/stylelint-plugin": "^3.0.1",
|
"@stylistic/stylelint-plugin": "^3.0.1",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.10.0",
|
||||||
"eslint-plugin-jest": "^28.8.3",
|
"eslint-plugin-jest": "^28.8.3",
|
||||||
"eslint-plugin-react": "^7.35.2",
|
"eslint-plugin-react": "^7.35.2",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
@@ -2073,9 +2073,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.9.1",
|
"version": "9.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz",
|
||||||
"integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==",
|
"integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
@@ -2090,6 +2090,18 @@
|
|||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@eslint/plugin-kit": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"levn": "^0.4.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@googleapis/drive": {
|
"node_modules/@googleapis/drive": {
|
||||||
"version": "8.14.0",
|
"version": "8.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.14.0.tgz",
|
||||||
@@ -5819,16 +5831,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.9.1",
|
"version": "9.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz",
|
||||||
"integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==",
|
"integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.11.0",
|
"@eslint-community/regexpp": "^4.11.0",
|
||||||
"@eslint/config-array": "^0.18.0",
|
"@eslint/config-array": "^0.18.0",
|
||||||
"@eslint/eslintrc": "^3.1.0",
|
"@eslint/eslintrc": "^3.1.0",
|
||||||
"@eslint/js": "9.9.1",
|
"@eslint/js": "9.10.0",
|
||||||
|
"@eslint/plugin-kit": "^0.1.0",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@humanwhocodes/retry": "^0.3.0",
|
"@humanwhocodes/retry": "^0.3.0",
|
||||||
"@nodelib/fs.walk": "^1.2.8",
|
"@nodelib/fs.walk": "^1.2.8",
|
||||||
@@ -5851,7 +5864,6 @@
|
|||||||
"is-glob": "^4.0.0",
|
"is-glob": "^4.0.0",
|
||||||
"is-path-inside": "^3.0.3",
|
"is-path-inside": "^3.0.3",
|
||||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||||
"levn": "^0.4.1",
|
|
||||||
"lodash.merge": "^4.6.2",
|
"lodash.merge": "^4.6.2",
|
||||||
"minimatch": "^3.1.2",
|
"minimatch": "^3.1.2",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
|
|||||||
@@ -126,7 +126,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@stylistic/stylelint-plugin": "^3.0.1",
|
"@stylistic/stylelint-plugin": "^3.0.1",
|
||||||
"eslint": "^9.9.1",
|
"eslint": "^9.10.0",
|
||||||
"eslint-plugin-jest": "^28.8.3",
|
"eslint-plugin-jest": "^28.8.3",
|
||||||
"eslint-plugin-react": "^7.35.2",
|
"eslint-plugin-react": "^7.35.2",
|
||||||
"globals": "^15.9.0",
|
"globals": "^15.9.0",
|
||||||
|
|||||||
@@ -436,6 +436,10 @@ if(isLocalEnvironment){
|
|||||||
|
|
||||||
//Vault Page
|
//Vault Page
|
||||||
app.get('/vault', asyncHandler(async(req, res, next)=>{
|
app.get('/vault', asyncHandler(async(req, res, next)=>{
|
||||||
|
req.ogMeta = { ...defaultMetaTags,
|
||||||
|
title : 'The Vault',
|
||||||
|
description : 'Search for Brews'
|
||||||
|
};
|
||||||
return next();
|
return next();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ const SplitPane = createClass({
|
|||||||
|
|
||||||
renderDivider : function(){
|
renderDivider : function(){
|
||||||
return <>
|
return <>
|
||||||
{this.renderMoveArrows()}
|
{this.props.showDividerButtons && this.renderMoveArrows()}
|
||||||
<div className='divider' onPointerDown={this.handleDown} >
|
<div className='divider' onPointerDown={this.handleDown} >
|
||||||
<div className='dots'>
|
<div className='dots'>
|
||||||
<i className='fas fa-circle' />
|
<i className='fas fa-circle' />
|
||||||
|
|||||||
@@ -1,77 +1,78 @@
|
|||||||
const _ = require('lodash');
|
|
||||||
const dedent = require('dedent-tabs').default;
|
const dedent = require('dedent-tabs').default;
|
||||||
|
|
||||||
const getTOC = (pages)=>{
|
// Map each actual page to its footer label, accounting for skips or numbering resets
|
||||||
|
const mapPages = (pages)=>{
|
||||||
|
let actualPage = 0;
|
||||||
|
let mappedPage = 0; // Number displayed in footer
|
||||||
|
let pageMap = [];
|
||||||
|
|
||||||
const recursiveAdd = (title, page, targetDepth, child, curDepth=0)=>{
|
pages.forEach(page => {
|
||||||
if(curDepth > 5) return; // Something went wrong.
|
actualPage++;
|
||||||
if(curDepth == targetDepth) {
|
const doSkip = page.querySelector('.skipCounting');
|
||||||
child.push({
|
const doReset = page.querySelector('.resetCounting');
|
||||||
title : title,
|
|
||||||
page : page,
|
if(doReset)
|
||||||
children : []
|
mappedPage = 1;
|
||||||
});
|
if(!doSkip && !doReset)
|
||||||
} else {
|
mappedPage++;
|
||||||
if(child.length == 0) {
|
|
||||||
child.push({
|
pageMap[actualPage] = {
|
||||||
title : null,
|
mappedPage : mappedPage,
|
||||||
page : page,
|
showPage : !doSkip
|
||||||
children : []
|
};
|
||||||
});
|
});
|
||||||
|
return pageMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMarkdown = (headings, pageMap) => {
|
||||||
|
const levelPad = ['- ###', ' - ####', ' -', ' -', ' -', ' -'];
|
||||||
|
|
||||||
|
let allMarkdown = [];
|
||||||
|
let depthChain = [0];
|
||||||
|
|
||||||
|
headings.forEach(heading => {
|
||||||
|
const page = parseInt(heading.closest('.page').id?.replace(/^p/, ''));
|
||||||
|
const mappedPage = pageMap[page].mappedPage;
|
||||||
|
const showPage = pageMap[page].showPage;
|
||||||
|
const title = heading.textContent.trim();
|
||||||
|
const ToCExclude = getComputedStyle(heading).getPropertyValue('--TOC');
|
||||||
|
const depth = parseInt(heading.tagName.substring(1));
|
||||||
|
|
||||||
|
if(!title || !showPage || ToCExclude == 'exclude')
|
||||||
|
return;
|
||||||
|
|
||||||
|
//If different header depth than last, remove indents until nearest higher-level header, then indent once
|
||||||
|
if (depth !== depthChain[depthChain.length -1]) {
|
||||||
|
while (depth <= depthChain[depthChain.length - 1]) {
|
||||||
|
depthChain.pop();
|
||||||
}
|
}
|
||||||
recursiveAdd(title, page, targetDepth, _.last(child).children, curDepth+1,);
|
depthChain.push(depth);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const res = [];
|
let markdown = `${levelPad[depthChain.length - 2]} [{{ ${title}}}{{ ${mappedPage}}}](#p${page})`;
|
||||||
|
allMarkdown.push(markdown);
|
||||||
|
});
|
||||||
|
return allMarkdown.join('\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTOC = ()=>{
|
||||||
const iframe = document.getElementById('BrewRenderer');
|
const iframe = document.getElementById('BrewRenderer');
|
||||||
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
|
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
|
||||||
const headings = iframeDocument.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
const headings = iframeDocument.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
||||||
const headerDepth = ['H1', 'H2', 'H3', 'H4', 'H5', 'H6'];
|
const pages = iframeDocument.querySelectorAll('.page');
|
||||||
|
|
||||||
_.each(headings, (heading)=>{
|
const pageMap = mapPages(pages);
|
||||||
const onPage = parseInt(heading.closest('.page').id?.replace(/^p/, ''));
|
return getMarkdown(headings, pageMap);
|
||||||
const ToCExclude = getComputedStyle(heading).getPropertyValue('--TOC');
|
|
||||||
|
|
||||||
if(ToCExclude != 'exclude') {
|
|
||||||
recursiveAdd(heading.textContent.trim(), onPage, headerDepth.indexOf(heading.tagName), res);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const ToCIterate = (entries, curDepth=0)=>{
|
|
||||||
const levelPad = ['- ###', ' - ####', ' - ', ' - ', ' - ', ' - '];
|
|
||||||
const toc = [];
|
|
||||||
if(entries.title !== null){
|
|
||||||
toc.push(`${levelPad[curDepth]} [{{ ${entries.title}}}{{ ${entries.page}}}](#p${entries.page})`);
|
|
||||||
}
|
|
||||||
if(entries.children.length) {
|
|
||||||
_.each(entries.children, (entry, idx)=>{
|
|
||||||
const children = ToCIterate(entry, entry.title == null ? curDepth : curDepth+1);
|
|
||||||
if(children.length) {
|
|
||||||
toc.push(...children);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return toc;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = function(props){
|
module.exports = function(props){
|
||||||
const pages = props.brew.text.split('\\page');
|
const TOC = getTOC();
|
||||||
const TOC = getTOC(pages);
|
|
||||||
const markdown = _.reduce(TOC, (r, g1, idx1)=>{
|
|
||||||
r.push(ToCIterate(g1).join('\n'));
|
|
||||||
return r;
|
|
||||||
}, []).join('\n');
|
|
||||||
|
|
||||||
return dedent`
|
return dedent`
|
||||||
{{toc,wide
|
{{toc,wide
|
||||||
# Contents
|
# Contents
|
||||||
|
|
||||||
${markdown}
|
${TOC}
|
||||||
}}
|
}}
|
||||||
\n`;
|
\n`;
|
||||||
};
|
};
|
||||||
@@ -23,14 +23,30 @@ module.exports = [
|
|||||||
gen : '\n\\page\n'
|
gen : '\n\\page\n'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'Page Number',
|
name : 'Page Numbering',
|
||||||
icon : 'fas fa-bookmark',
|
icon : 'fas fa-bookmark',
|
||||||
gen : '{{pageNumber 1}}\n'
|
subsnippets : [
|
||||||
},
|
{
|
||||||
{
|
name : 'Page Number',
|
||||||
name : 'Auto-incrementing Page Number',
|
icon : 'fas fa-bookmark',
|
||||||
icon : 'fas fa-sort-numeric-down',
|
gen : '{{pageNumber 1}}\n'
|
||||||
gen : '{{pageNumber,auto}}\n'
|
},
|
||||||
|
{
|
||||||
|
name : 'Auto-incrementing Page Number',
|
||||||
|
icon : 'fas fa-sort-numeric-down',
|
||||||
|
gen : '{{pageNumber,auto}}\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'Skip Page Number Increment this Page',
|
||||||
|
icon : 'fas fa-xmark',
|
||||||
|
gen : '{{skipCounting}}\n'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name : 'Restart Numbering',
|
||||||
|
icon : 'fas fa-arrow-rotate-left',
|
||||||
|
gen : '{{resetCounting}}\n'
|
||||||
|
},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'Footer',
|
name : 'Footer',
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@page { margin : 0; }
|
@page { margin : 0; }
|
||||||
body { counter-reset : page-numbers; }
|
body { counter-reset : page-numbers 0; }
|
||||||
* { -webkit-print-color-adjust : exact; }
|
* { -webkit-print-color-adjust : exact; }
|
||||||
|
|
||||||
//*****************************
|
//*****************************
|
||||||
@@ -51,7 +51,6 @@ body { counter-reset : page-numbers; }
|
|||||||
height : 279.4mm;
|
height : 279.4mm;
|
||||||
padding : 1.4cm 1.9cm 1.7cm;
|
padding : 1.4cm 1.9cm 1.7cm;
|
||||||
overflow : hidden;
|
overflow : hidden;
|
||||||
counter-increment : page-numbers;
|
|
||||||
background-color : var(--HB_Color_Background);
|
background-color : var(--HB_Color_Background);
|
||||||
text-rendering : optimizeLegibility;
|
text-rendering : optimizeLegibility;
|
||||||
contain : size;
|
contain : size;
|
||||||
@@ -494,4 +493,13 @@ body { counter-reset : page-numbers; }
|
|||||||
&:nth-child(even) {
|
&:nth-child(even) {
|
||||||
.pageNumber { left : 30px; }
|
.pageNumber { left : 30px; }
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
.resetCounting {
|
||||||
|
counter-set : page-numbers 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:has(.skipCounting)) {
|
||||||
|
counter-increment : page-numbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user