mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-10 00:32:45 +00:00
Merge pull request #3290 from naturalcrit/PreprocessVars
Simplify and clean Vars - Done in preprocessing step now
This commit is contained in:
@@ -4,6 +4,7 @@ const Nav = require('naturalcrit/nav/nav.jsx');
|
|||||||
module.exports = function(props){
|
module.exports = function(props){
|
||||||
return <Nav.item
|
return <Nav.item
|
||||||
href='/new'
|
href='/new'
|
||||||
|
newTab={true}
|
||||||
color='purple'
|
color='purple'
|
||||||
icon='fas fa-plus-square'>
|
icon='fas fa-plus-square'>
|
||||||
new
|
new
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ const BrewItem = createClass({
|
|||||||
<div className='info'>
|
<div className='info'>
|
||||||
|
|
||||||
{brew.tags?.length ? <>
|
{brew.tags?.length ? <>
|
||||||
<div className='brewTags' title={`Tags:\n${brew.tags.join('\n')}`}>
|
<div className='brewTags' title={`${brew.tags.length} tags:\n${brew.tags.join('\n')}`}>
|
||||||
<i className='fas fa-tags'/>
|
<i className='fas fa-tags'/>
|
||||||
{brew.tags.map((tag, idx)=>{
|
{brew.tags.map((tag, idx)=>{
|
||||||
const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/);
|
const matches = tag.match(/^(?:([^:]+):)?([^:]+)$/);
|
||||||
@@ -135,7 +135,7 @@ const BrewItem = createClass({
|
|||||||
</> : <></>
|
</> : <></>
|
||||||
}
|
}
|
||||||
<span title={`Authors:\n${brew.authors?.join('\n')}`}>
|
<span title={`Authors:\n${brew.authors?.join('\n')}`}>
|
||||||
<i className='fas fa-user'/> {brew.authors?.join(', ')}
|
<i className='fas fa-user'/> {brew.authors.map((item) => <a href={`/user/${item}`}>{item}</a>)}
|
||||||
</span>
|
</span>
|
||||||
<br />
|
<br />
|
||||||
<span title={`Last viewed: ${moment(brew.lastViewed).local().format(dateFormatString)}`}>
|
<span title={`Last viewed: ${moment(brew.lastViewed).local().format(dateFormatString)}`}>
|
||||||
|
|||||||
@@ -48,6 +48,10 @@
|
|||||||
&>span{
|
&>span{
|
||||||
margin-right : 12px;
|
margin-right : 12px;
|
||||||
line-height : 1.5em;
|
line-height : 1.5em;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color:inherit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.brewTags span {
|
.brewTags span {
|
||||||
|
|||||||
214
package-lock.json
generated
214
package-lock.json
generated
@@ -10,17 +10,18 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.23.7",
|
"@babel/core": "^7.23.9",
|
||||||
"@babel/plugin-transform-runtime": "^7.23.7",
|
"@babel/plugin-transform-runtime": "^7.23.9",
|
||||||
"@babel/preset-env": "^7.23.8",
|
"@babel/preset-env": "^7.23.9",
|
||||||
"@babel/preset-react": "^7.23.3",
|
"@babel/preset-react": "^7.23.3",
|
||||||
"@googleapis/drive": "^8.6.0",
|
"@googleapis/drive": "^8.7.0",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.2",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"codemirror": "^5.65.6",
|
"codemirror": "^5.65.6",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"create-react-class": "^15.7.0",
|
"create-react-class": "^15.7.0",
|
||||||
"dedent-tabs": "^0.10.3",
|
"dedent-tabs": "^0.10.3",
|
||||||
|
"expr-eval": "^2.0.2",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-async-handler": "^1.2.0",
|
"express-async-handler": "^1.2.0",
|
||||||
"express-static-gzip": "2.1.7",
|
"express-static-gzip": "2.1.7",
|
||||||
@@ -29,19 +30,19 @@
|
|||||||
"jwt-simple": "^0.5.6",
|
"jwt-simple": "^0.5.6",
|
||||||
"less": "^3.13.1",
|
"less": "^3.13.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"marked": "5.1.1",
|
"marked": "11.2.0",
|
||||||
"marked-extended-tables": "^1.0.8",
|
"marked-extended-tables": "^1.0.8",
|
||||||
"marked-gfm-heading-id": "^3.1.2",
|
"marked-gfm-heading-id": "^3.1.3",
|
||||||
"marked-smartypants-lite": "^1.0.2",
|
"marked-smartypants-lite": "^1.0.2",
|
||||||
"markedLegacy": "npm:marked@^0.3.19",
|
"markedLegacy": "npm:marked@^0.3.19",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"mongoose": "^8.1.0",
|
"mongoose": "^8.1.1",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"nconf": "^0.12.1",
|
"nconf": "^0.12.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-frame-component": "^4.1.3",
|
"react-frame-component": "^4.1.3",
|
||||||
"react-router-dom": "6.21.3",
|
"react-router-dom": "6.22.0",
|
||||||
"sanitize-filename": "1.6.3",
|
"sanitize-filename": "1.6.3",
|
||||||
"superagent": "^8.1.2",
|
"superagent": "^8.1.2",
|
||||||
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
||||||
@@ -54,7 +55,7 @@
|
|||||||
"jest-expect-message": "^1.1.3",
|
"jest-expect-message": "^1.1.3",
|
||||||
"postcss-less": "^6.0.0",
|
"postcss-less": "^6.0.0",
|
||||||
"stylelint": "^15.11.0",
|
"stylelint": "^15.11.0",
|
||||||
"stylelint-config-recess-order": "^4.4.0",
|
"stylelint-config-recess-order": "^4.6.0",
|
||||||
"stylelint-config-recommended": "^13.0.0",
|
"stylelint-config-recommended": "^13.0.0",
|
||||||
"stylelint-stylistic": "^0.4.3",
|
"stylelint-stylistic": "^0.4.3",
|
||||||
"supertest": "^6.3.4"
|
"supertest": "^6.3.4"
|
||||||
@@ -106,20 +107,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/core": {
|
"node_modules/@babel/core": {
|
||||||
"version": "7.23.7",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz",
|
||||||
"integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==",
|
"integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.2.0",
|
"@ampproject/remapping": "^2.2.0",
|
||||||
"@babel/code-frame": "^7.23.5",
|
"@babel/code-frame": "^7.23.5",
|
||||||
"@babel/generator": "^7.23.6",
|
"@babel/generator": "^7.23.6",
|
||||||
"@babel/helper-compilation-targets": "^7.23.6",
|
"@babel/helper-compilation-targets": "^7.23.6",
|
||||||
"@babel/helper-module-transforms": "^7.23.3",
|
"@babel/helper-module-transforms": "^7.23.3",
|
||||||
"@babel/helpers": "^7.23.7",
|
"@babel/helpers": "^7.23.9",
|
||||||
"@babel/parser": "^7.23.6",
|
"@babel/parser": "^7.23.9",
|
||||||
"@babel/template": "^7.22.15",
|
"@babel/template": "^7.23.9",
|
||||||
"@babel/traverse": "^7.23.7",
|
"@babel/traverse": "^7.23.9",
|
||||||
"@babel/types": "^7.23.6",
|
"@babel/types": "^7.23.9",
|
||||||
"convert-source-map": "^2.0.0",
|
"convert-source-map": "^2.0.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"gensync": "^1.0.0-beta.2",
|
"gensync": "^1.0.0-beta.2",
|
||||||
@@ -242,9 +243,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-define-polyfill-provider": {
|
"node_modules/@babel/helper-define-polyfill-provider": {
|
||||||
"version": "0.4.4",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz",
|
||||||
"integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==",
|
"integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-compilation-targets": "^7.22.6",
|
"@babel/helper-compilation-targets": "^7.22.6",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
@@ -449,13 +450,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helpers": {
|
"node_modules/@babel/helpers": {
|
||||||
"version": "7.23.7",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz",
|
||||||
"integrity": "sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ==",
|
"integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/template": "^7.22.15",
|
"@babel/template": "^7.23.9",
|
||||||
"@babel/traverse": "^7.23.7",
|
"@babel/traverse": "^7.23.9",
|
||||||
"@babel/types": "^7.23.6"
|
"@babel/types": "^7.23.9"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -475,9 +476,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.23.6",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz",
|
||||||
"integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==",
|
"integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
},
|
},
|
||||||
@@ -814,9 +815,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-async-generator-functions": {
|
"node_modules/@babel/plugin-transform-async-generator-functions": {
|
||||||
"version": "7.23.7",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz",
|
||||||
"integrity": "sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==",
|
"integrity": "sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-environment-visitor": "^7.22.20",
|
"@babel/helper-environment-visitor": "^7.22.20",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
@@ -1150,9 +1151,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-modules-systemjs": {
|
"node_modules/@babel/plugin-transform-modules-systemjs": {
|
||||||
"version": "7.23.3",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz",
|
||||||
"integrity": "sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==",
|
"integrity": "sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-hoist-variables": "^7.22.5",
|
"@babel/helper-hoist-variables": "^7.22.5",
|
||||||
"@babel/helper-module-transforms": "^7.23.3",
|
"@babel/helper-module-transforms": "^7.23.3",
|
||||||
@@ -1455,15 +1456,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-runtime": {
|
"node_modules/@babel/plugin-transform-runtime": {
|
||||||
"version": "7.23.7",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.9.tgz",
|
||||||
"integrity": "sha512-fa0hnfmiXc9fq/weK34MUV0drz2pOL/vfKWvN7Qw127hiUPabFCUMgAbYWcchRzMJit4o5ARsK/s+5h0249pLw==",
|
"integrity": "sha512-A7clW3a0aSjm3ONU9o2HAILSegJCYlEZmOhmBRReVtIpY/Z/p7yIZ+wR41Z+UipwdGuqwtID/V/dOdZXjwi9gQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-module-imports": "^7.22.15",
|
"@babel/helper-module-imports": "^7.22.15",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
"babel-plugin-polyfill-corejs2": "^0.4.7",
|
"babel-plugin-polyfill-corejs2": "^0.4.8",
|
||||||
"babel-plugin-polyfill-corejs3": "^0.8.7",
|
"babel-plugin-polyfill-corejs3": "^0.9.0",
|
||||||
"babel-plugin-polyfill-regenerator": "^0.5.4",
|
"babel-plugin-polyfill-regenerator": "^0.5.5",
|
||||||
"semver": "^6.3.1"
|
"semver": "^6.3.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1604,9 +1605,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/preset-env": {
|
"node_modules/@babel/preset-env": {
|
||||||
"version": "7.23.8",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.8.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.9.tgz",
|
||||||
"integrity": "sha512-lFlpmkApLkEP6woIKprO6DO60RImpatTQKtz4sUcDjVcK8M8mQ4sZsuxaTMNOZf0sqAq/ReYW1ZBHnOQwKpLWA==",
|
"integrity": "sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/compat-data": "^7.23.5",
|
"@babel/compat-data": "^7.23.5",
|
||||||
"@babel/helper-compilation-targets": "^7.23.6",
|
"@babel/helper-compilation-targets": "^7.23.6",
|
||||||
@@ -1635,7 +1636,7 @@
|
|||||||
"@babel/plugin-syntax-top-level-await": "^7.14.5",
|
"@babel/plugin-syntax-top-level-await": "^7.14.5",
|
||||||
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
|
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
|
||||||
"@babel/plugin-transform-arrow-functions": "^7.23.3",
|
"@babel/plugin-transform-arrow-functions": "^7.23.3",
|
||||||
"@babel/plugin-transform-async-generator-functions": "^7.23.7",
|
"@babel/plugin-transform-async-generator-functions": "^7.23.9",
|
||||||
"@babel/plugin-transform-async-to-generator": "^7.23.3",
|
"@babel/plugin-transform-async-to-generator": "^7.23.3",
|
||||||
"@babel/plugin-transform-block-scoped-functions": "^7.23.3",
|
"@babel/plugin-transform-block-scoped-functions": "^7.23.3",
|
||||||
"@babel/plugin-transform-block-scoping": "^7.23.4",
|
"@babel/plugin-transform-block-scoping": "^7.23.4",
|
||||||
@@ -1657,7 +1658,7 @@
|
|||||||
"@babel/plugin-transform-member-expression-literals": "^7.23.3",
|
"@babel/plugin-transform-member-expression-literals": "^7.23.3",
|
||||||
"@babel/plugin-transform-modules-amd": "^7.23.3",
|
"@babel/plugin-transform-modules-amd": "^7.23.3",
|
||||||
"@babel/plugin-transform-modules-commonjs": "^7.23.3",
|
"@babel/plugin-transform-modules-commonjs": "^7.23.3",
|
||||||
"@babel/plugin-transform-modules-systemjs": "^7.23.3",
|
"@babel/plugin-transform-modules-systemjs": "^7.23.9",
|
||||||
"@babel/plugin-transform-modules-umd": "^7.23.3",
|
"@babel/plugin-transform-modules-umd": "^7.23.3",
|
||||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
|
"@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
|
||||||
"@babel/plugin-transform-new-target": "^7.23.3",
|
"@babel/plugin-transform-new-target": "^7.23.3",
|
||||||
@@ -1683,9 +1684,9 @@
|
|||||||
"@babel/plugin-transform-unicode-regex": "^7.23.3",
|
"@babel/plugin-transform-unicode-regex": "^7.23.3",
|
||||||
"@babel/plugin-transform-unicode-sets-regex": "^7.23.3",
|
"@babel/plugin-transform-unicode-sets-regex": "^7.23.3",
|
||||||
"@babel/preset-modules": "0.1.6-no-external-plugins",
|
"@babel/preset-modules": "0.1.6-no-external-plugins",
|
||||||
"babel-plugin-polyfill-corejs2": "^0.4.7",
|
"babel-plugin-polyfill-corejs2": "^0.4.8",
|
||||||
"babel-plugin-polyfill-corejs3": "^0.8.7",
|
"babel-plugin-polyfill-corejs3": "^0.9.0",
|
||||||
"babel-plugin-polyfill-regenerator": "^0.5.4",
|
"babel-plugin-polyfill-regenerator": "^0.5.5",
|
||||||
"core-js-compat": "^3.31.0",
|
"core-js-compat": "^3.31.0",
|
||||||
"semver": "^6.3.1"
|
"semver": "^6.3.1"
|
||||||
},
|
},
|
||||||
@@ -1745,22 +1746,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/template": {
|
"node_modules/@babel/template": {
|
||||||
"version": "7.22.15",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz",
|
||||||
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
|
"integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.22.13",
|
"@babel/code-frame": "^7.23.5",
|
||||||
"@babel/parser": "^7.22.15",
|
"@babel/parser": "^7.23.9",
|
||||||
"@babel/types": "^7.22.15"
|
"@babel/types": "^7.23.9"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse": {
|
"node_modules/@babel/traverse": {
|
||||||
"version": "7.23.7",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz",
|
||||||
"integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==",
|
"integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.23.5",
|
"@babel/code-frame": "^7.23.5",
|
||||||
"@babel/generator": "^7.23.6",
|
"@babel/generator": "^7.23.6",
|
||||||
@@ -1768,8 +1769,8 @@
|
|||||||
"@babel/helper-function-name": "^7.23.0",
|
"@babel/helper-function-name": "^7.23.0",
|
||||||
"@babel/helper-hoist-variables": "^7.22.5",
|
"@babel/helper-hoist-variables": "^7.22.5",
|
||||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||||
"@babel/parser": "^7.23.6",
|
"@babel/parser": "^7.23.9",
|
||||||
"@babel/types": "^7.23.6",
|
"@babel/types": "^7.23.9",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"globals": "^11.1.0"
|
"globals": "^11.1.0"
|
||||||
},
|
},
|
||||||
@@ -1778,9 +1779,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.23.6",
|
"version": "7.23.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz",
|
||||||
"integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==",
|
"integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.23.4",
|
"@babel/helper-string-parser": "^7.23.4",
|
||||||
"@babel/helper-validator-identifier": "^7.22.20",
|
"@babel/helper-validator-identifier": "^7.22.20",
|
||||||
@@ -1966,9 +1967,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@googleapis/drive": {
|
"node_modules/@googleapis/drive": {
|
||||||
"version": "8.6.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.7.0.tgz",
|
||||||
"integrity": "sha512-Af3/5i6h7gbjHnwFuO9zMTpYOy2yhhfZlNciUEjb14L3ZdT1WNIDM038viIAb9ovFzkrIDqLSfUbFCgh1pywkw==",
|
"integrity": "sha512-XAi6kfySIU4H3ivX2DpzTDce5UhNke5NxEWCL6tySEdcVqx+cmXJmkMqwfOAHJalEB5s9PPfdLBU29Xd5XlLSQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"googleapis-common": "^7.0.0"
|
"googleapis-common": "^7.0.0"
|
||||||
},
|
},
|
||||||
@@ -2837,9 +2838,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@remix-run/router": {
|
"node_modules/@remix-run/router": {
|
||||||
"version": "1.14.2",
|
"version": "1.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.2.tgz",
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.0.tgz",
|
||||||
"integrity": "sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==",
|
"integrity": "sha512-HOil5aFtme37dVQTB6M34G95kPM3MMuqSmIRVCC52eKV+Y/tGSqw9P3rWhlAx6A+mz+MoX+XxsGsNJbaI5qCgQ==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
@@ -3734,12 +3735,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-plugin-polyfill-corejs2": {
|
"node_modules/babel-plugin-polyfill-corejs2": {
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.7.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz",
|
||||||
"integrity": "sha512-LidDk/tEGDfuHW2DWh/Hgo4rmnw3cduK6ZkOI1NPFceSK3n/yAGeOsNT7FLnSGHkXj3RHGSEVkN3FsCTY6w2CQ==",
|
"integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/compat-data": "^7.22.6",
|
"@babel/compat-data": "^7.22.6",
|
||||||
"@babel/helper-define-polyfill-provider": "^0.4.4",
|
"@babel/helper-define-polyfill-provider": "^0.5.0",
|
||||||
"semver": "^6.3.1"
|
"semver": "^6.3.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@@ -3747,23 +3748,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-plugin-polyfill-corejs3": {
|
"node_modules/babel-plugin-polyfill-corejs3": {
|
||||||
"version": "0.8.7",
|
"version": "0.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz",
|
||||||
"integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==",
|
"integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-define-polyfill-provider": "^0.4.4",
|
"@babel/helper-define-polyfill-provider": "^0.5.0",
|
||||||
"core-js-compat": "^3.33.1"
|
"core-js-compat": "^3.34.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-plugin-polyfill-regenerator": {
|
"node_modules/babel-plugin-polyfill-regenerator": {
|
||||||
"version": "0.5.4",
|
"version": "0.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz",
|
||||||
"integrity": "sha512-S/x2iOCvDaCASLYsOOgWOq4bCfKYVqvO/uxjkaYyZ3rVsVE3CeAI/c84NpyuBBymEgNvHgjEot3a9/Z/kXvqsg==",
|
"integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-define-polyfill-provider": "^0.4.4"
|
"@babel/helper-define-polyfill-provider": "^0.5.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||||
@@ -6036,6 +6037,11 @@
|
|||||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expr-eval": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/expr-eval/-/expr-eval-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg=="
|
||||||
|
},
|
||||||
"node_modules/express": {
|
"node_modules/express": {
|
||||||
"version": "4.18.2",
|
"version": "4.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
||||||
@@ -10041,9 +10047,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked": {
|
"node_modules/marked": {
|
||||||
"version": "5.1.1",
|
"version": "11.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/marked/-/marked-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz",
|
||||||
"integrity": "sha512-bTmmGdEINWmOMDjnPWDxGPQ4qkDLeYorpYbEtFOXzOruTwUE671q4Guiuchn4N8h/v6NGd7916kXsm3Iz4iUSg==",
|
"integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"marked": "bin/marked.js"
|
"marked": "bin/marked.js"
|
||||||
},
|
},
|
||||||
@@ -10060,14 +10066,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked-gfm-heading-id": {
|
"node_modules/marked-gfm-heading-id": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/marked-gfm-heading-id/-/marked-gfm-heading-id-3.1.3.tgz",
|
||||||
"integrity": "sha512-SdIZvhNxDgndFkDa2WRcFP4ahYm6k6hoHdTCN+fD7HRiI/R3Eimcw/Yl7ikQ+0KUuDpi75NnYQiThZnZsNr9Dg==",
|
"integrity": "sha512-A0cRU4PCueX/5m8VE4mT8uTQ36l3xMYRojz3Eqnk4BmUFZ0T+9Xhn2KvHcANP4qbhfOeuMrWJCTQbASIBR5xeg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"github-slugger": "^2.0.0"
|
"github-slugger": "^2.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"marked": ">=4 <12"
|
"marked": ">=4 <13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/marked-smartypants-lite": {
|
"node_modules/marked-smartypants-lite": {
|
||||||
@@ -10453,9 +10459,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mongoose": {
|
"node_modules/mongoose": {
|
||||||
"version": "8.1.0",
|
"version": "8.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.1.1.tgz",
|
||||||
"integrity": "sha512-kOA4Xnq2goqNpN9EmYElGNWfxA9H80fxcr7UdJKWi3UMflza0R7wpTihCpM67dE/0MNFljoa0sjQtlXVkkySAQ==",
|
"integrity": "sha512-DbLb0NsiEXmaqLOpEz+AtAsgwhRw6f25gwa1dF5R7jj6lS1D8X6uTdhBSC8GDVtOwe5Tfw2EL7nTn6hiJT3Bgg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bson": "^6.2.0",
|
"bson": "^6.2.0",
|
||||||
"kareem": "2.5.1",
|
"kareem": "2.5.1",
|
||||||
@@ -11873,11 +11879,11 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "6.21.3",
|
"version": "6.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.0.tgz",
|
||||||
"integrity": "sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==",
|
"integrity": "sha512-q2yemJeg6gw/YixRlRnVx6IRJWZD6fonnfZhN1JIOhV2iJCPeRNSH3V1ISwHf+JWcESzLC3BOLD1T07tmO5dmg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.14.2"
|
"@remix-run/router": "1.15.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
@@ -11887,12 +11893,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router-dom": {
|
"node_modules/react-router-dom": {
|
||||||
"version": "6.21.3",
|
"version": "6.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.0.tgz",
|
||||||
"integrity": "sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==",
|
"integrity": "sha512-z2w+M4tH5wlcLmH3BMMOMdrtrJ9T3oJJNsAlBJbwk+8Syxd5WFJ7J5dxMEW0/GEXD1BBis4uXRrNIz3mORr0ag==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@remix-run/router": "1.14.2",
|
"@remix-run/router": "1.15.0",
|
||||||
"react-router": "6.21.3"
|
"react-router": "6.22.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
@@ -13327,9 +13333,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/stylelint-config-recess-order": {
|
"node_modules/stylelint-config-recess-order": {
|
||||||
"version": "4.4.0",
|
"version": "4.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/stylelint-config-recess-order/-/stylelint-config-recess-order-4.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/stylelint-config-recess-order/-/stylelint-config-recess-order-4.6.0.tgz",
|
||||||
"integrity": "sha512-Q99kvZyIM/aoPEV4dRDkzD3fZLzH0LXi+pawCf1r700uUeF/PHQ5PZXjwFUuGrWhOzd1N+cuVm+OUGsY2fRN5A==",
|
"integrity": "sha512-V76fhv3YtcNXh/hyAuAdSzi5FmcrG54Mp2AThJ3D/PTMTSYzUPd7GIhP6z9mTqnRhmkk6YTfcu/JWB8h+Yrcaw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"stylelint-order": "6.x"
|
"stylelint-order": "6.x"
|
||||||
|
|||||||
21
package.json
21
package.json
@@ -3,7 +3,7 @@
|
|||||||
"description": "Create authentic looking D&D homebrews using only markdown",
|
"description": "Create authentic looking D&D homebrews using only markdown",
|
||||||
"version": "3.10.0",
|
"version": "3.10.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"npm": "^10.2.x",
|
"npm": "^10.2.x",
|
||||||
"node": "^20.8.x"
|
"node": "^20.8.x"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -79,17 +79,18 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.23.7",
|
"@babel/core": "^7.23.9",
|
||||||
"@babel/plugin-transform-runtime": "^7.23.7",
|
"@babel/plugin-transform-runtime": "^7.23.9",
|
||||||
"@babel/preset-env": "^7.23.8",
|
"@babel/preset-env": "^7.23.9",
|
||||||
"@babel/preset-react": "^7.23.3",
|
"@babel/preset-react": "^7.23.3",
|
||||||
"@googleapis/drive": "^8.6.0",
|
"@googleapis/drive": "^8.7.0",
|
||||||
"body-parser": "^1.20.2",
|
"body-parser": "^1.20.2",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"codemirror": "^5.65.6",
|
"codemirror": "^5.65.6",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"create-react-class": "^15.7.0",
|
"create-react-class": "^15.7.0",
|
||||||
"dedent-tabs": "^0.10.3",
|
"dedent-tabs": "^0.10.3",
|
||||||
|
"expr-eval": "^2.0.2",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-async-handler": "^1.2.0",
|
"express-async-handler": "^1.2.0",
|
||||||
"express-static-gzip": "2.1.7",
|
"express-static-gzip": "2.1.7",
|
||||||
@@ -98,19 +99,19 @@
|
|||||||
"jwt-simple": "^0.5.6",
|
"jwt-simple": "^0.5.6",
|
||||||
"less": "^3.13.1",
|
"less": "^3.13.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"marked": "5.1.1",
|
"marked": "11.2.0",
|
||||||
"marked-extended-tables": "^1.0.8",
|
"marked-extended-tables": "^1.0.8",
|
||||||
"marked-gfm-heading-id": "^3.1.2",
|
"marked-gfm-heading-id": "^3.1.3",
|
||||||
"marked-smartypants-lite": "^1.0.2",
|
"marked-smartypants-lite": "^1.0.2",
|
||||||
"markedLegacy": "npm:marked@^0.3.19",
|
"markedLegacy": "npm:marked@^0.3.19",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"mongoose": "^8.1.0",
|
"mongoose": "^8.1.1",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"nconf": "^0.12.1",
|
"nconf": "^0.12.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-frame-component": "^4.1.3",
|
"react-frame-component": "^4.1.3",
|
||||||
"react-router-dom": "6.21.3",
|
"react-router-dom": "6.22.0",
|
||||||
"sanitize-filename": "1.6.3",
|
"sanitize-filename": "1.6.3",
|
||||||
"superagent": "^8.1.2",
|
"superagent": "^8.1.2",
|
||||||
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
||||||
@@ -123,7 +124,7 @@
|
|||||||
"jest-expect-message": "^1.1.3",
|
"jest-expect-message": "^1.1.3",
|
||||||
"postcss-less": "^6.0.0",
|
"postcss-less": "^6.0.0",
|
||||||
"stylelint": "^15.11.0",
|
"stylelint": "^15.11.0",
|
||||||
"stylelint-config-recess-order": "^4.4.0",
|
"stylelint-config-recess-order": "^4.6.0",
|
||||||
"stylelint-config-recommended": "^13.0.0",
|
"stylelint-config-recommended": "^13.0.0",
|
||||||
"stylelint-stylistic": "^0.4.3",
|
"stylelint-stylistic": "^0.4.3",
|
||||||
"supertest": "^6.3.4"
|
"supertest": "^6.3.4"
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
"codemirror/addon/edit/trailingspace.js",
|
"codemirror/addon/edit/trailingspace.js",
|
||||||
"codemirror/addon/selection/active-line.js",
|
"codemirror/addon/selection/active-line.js",
|
||||||
"moment",
|
"moment",
|
||||||
"superagent",
|
"superagent"
|
||||||
"marked"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,85 +26,124 @@ const mw = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const junkBrewPipeline = [
|
||||||
/* Search for brews that are older than 3 days and that are shorter than a tweet */
|
{ $match : {
|
||||||
const junkBrewQuery = HomebrewModel.find({
|
updatedAt : { $lt: Moment().subtract(30, 'days').toDate() },
|
||||||
'$where' : 'this.text.length < 140',
|
lastViewed : { $lt: Moment().subtract(30, 'days').toDate() }
|
||||||
createdAt : {
|
}},
|
||||||
$lt : Moment().subtract(30, 'days').toDate()
|
{ $project: { textBinSize: { $binarySize: '$textBin' } } },
|
||||||
}
|
{ $match: { textBinSize: { $lt: 140 } } },
|
||||||
}).limit(100).maxTime(60000);
|
{ $limit: 100 }
|
||||||
|
];
|
||||||
|
|
||||||
/* Search for brews that aren't compressed (missing the compressed text field) */
|
/* Search for brews that aren't compressed (missing the compressed text field) */
|
||||||
const uncompressedBrewQuery = HomebrewModel.find({
|
const uncompressedBrewQuery = HomebrewModel.find({
|
||||||
'text' : { '$exists': true }
|
'text' : { '$exists': true }
|
||||||
}).lean().limit(10000).select('_id');
|
}).lean().limit(10000).select('_id');
|
||||||
|
|
||||||
|
// Search for up to 100 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes
|
||||||
router.get('/admin/cleanup', mw.adminOnly, (req, res)=>{
|
router.get('/admin/cleanup', mw.adminOnly, (req, res)=>{
|
||||||
junkBrewQuery.exec((err, objs)=>{
|
HomebrewModel.aggregate(junkBrewPipeline).option({ maxTimeMS: 60000 })
|
||||||
if(err) return res.status(500).send(err);
|
.then((objs)=>res.json({ count: objs.length }))
|
||||||
return res.json({ count: objs.length });
|
.catch((error)=>{
|
||||||
});
|
console.error(error);
|
||||||
|
res.status(500).json({ error: 'Internal Server Error' });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
/* Removes all empty brews that are older than 3 days and that are shorter than a tweet */
|
|
||||||
|
// Delete up to 100 brews that have not been viewed or updated in 30 days and are shorter than 140 bytes
|
||||||
router.post('/admin/cleanup', mw.adminOnly, (req, res)=>{
|
router.post('/admin/cleanup', mw.adminOnly, (req, res)=>{
|
||||||
junkBrewQuery.remove().exec((err, objs)=>{
|
HomebrewModel.aggregate(junkBrewPipeline).option({ maxTimeMS: 60000 })
|
||||||
if(err) return res.status(500).send(err);
|
.then((docs)=>{
|
||||||
return res.json({ count: objs.length });
|
const ids = docs.map((doc)=>doc._id);
|
||||||
});
|
return HomebrewModel.deleteMany({ _id: { $in: ids } });
|
||||||
|
}).then((result)=>{
|
||||||
|
res.json({ count: result.deletedCount });
|
||||||
|
}).catch((error)=>{
|
||||||
|
console.error(error);
|
||||||
|
res.status(500).json({ error: 'Internal Server Error' });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Searches for matching edit or share id, also attempts to partial match */
|
/* Searches for matching edit or share id, also attempts to partial match */
|
||||||
router.get('/admin/lookup/:id', mw.adminOnly, (req, res, next)=>{
|
router.get('/admin/lookup/:id', mw.adminOnly, async (req, res, next)=>{
|
||||||
HomebrewModel.findOne({ $or : [
|
HomebrewModel.findOne({
|
||||||
{ editId: { '$regex': req.params.id, '$options': 'i' } },
|
$or : [
|
||||||
{ shareId: { '$regex': req.params.id, '$options': 'i' } },
|
{ editId: { $regex: req.params.id, $options: 'i' } },
|
||||||
] }).exec((err, brew)=>{
|
{ shareId: { $regex: req.params.id, $options: 'i' } },
|
||||||
return res.json(brew);
|
]
|
||||||
|
}).exec()
|
||||||
|
.then((brew)=>{
|
||||||
|
if(!brew) // No document found
|
||||||
|
return res.status(404).json({ error: 'Document not found' });
|
||||||
|
else
|
||||||
|
return res.json(brew);
|
||||||
|
})
|
||||||
|
.catch((err)=>{
|
||||||
|
console.error(err);
|
||||||
|
return res.status(500).json({ error: 'Internal Server Error' });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Find 50 brews that aren't compressed yet */
|
/* Find 50 brews that aren't compressed yet */
|
||||||
router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{
|
router.get('/admin/finduncompressed', mw.adminOnly, (req, res)=>{
|
||||||
uncompressedBrewQuery.exec((err, objs)=>{
|
const query = uncompressedBrewQuery.clone();
|
||||||
if(err) return res.status(500).send(err);
|
|
||||||
objs = objs.map((obj)=>{return obj._id;});
|
query.exec()
|
||||||
return res.json({ count: objs.length, ids: objs });
|
.then((objs)=>{
|
||||||
});
|
const ids = objs.map((obj)=>obj._id);
|
||||||
|
res.json({ count: ids.length, ids });
|
||||||
|
})
|
||||||
|
.catch((err)=>{
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).send(err.message || 'Internal Server Error');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/* Compresses the "text" field of a brew to binary */
|
/* Compresses the "text" field of a brew to binary */
|
||||||
router.put('/admin/compress/:id', (req, res)=>{
|
router.put('/admin/compress/:id', (req, res)=>{
|
||||||
HomebrewModel.get({ _id: req.params.id })
|
HomebrewModel.findOne({ _id: req.params.id })
|
||||||
.then((brew)=>{
|
.then((brew)=>{
|
||||||
brew.textBin = zlib.deflateRawSync(brew.text); // Compress brew text to binary before saving
|
if(!brew)
|
||||||
brew.text = undefined; // Delete the non-binary text field since it's not needed anymore
|
return res.status(404).send('Brew not found');
|
||||||
|
|
||||||
brew.save((err, obj)=>{
|
if(brew.text) {
|
||||||
if(err) throw err;
|
brew.textBin = brew.textBin || zlib.deflateRawSync(brew.text); //Don't overwrite textBin if exists
|
||||||
return res.status(200).send(obj);
|
brew.text = undefined;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
return brew.save();
|
||||||
})
|
})
|
||||||
|
.then((obj)=>res.status(200).send(obj))
|
||||||
.catch((err)=>{
|
.catch((err)=>{
|
||||||
console.log(err);
|
console.error(err);
|
||||||
return res.status(500).send('Error while saving');
|
res.status(500).send('Error while saving');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/admin/stats', mw.adminOnly, (req, res)=>{
|
|
||||||
HomebrewModel.count({}, (err, count)=>{
|
router.get('/admin/stats', mw.adminOnly, async (req, res)=>{
|
||||||
|
try {
|
||||||
|
const totalBrewsCount = await HomebrewModel.countDocuments({});
|
||||||
|
const publishedBrewsCount = await HomebrewModel.countDocuments({ published: true });
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
totalBrews : count
|
totalBrews : totalBrewsCount,
|
||||||
|
totalPublishedBrews : publishedBrewsCount
|
||||||
});
|
});
|
||||||
});
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return res.status(500).json({ error: 'Internal Server Error' });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/admin', mw.adminOnly, (req, res)=>{
|
router.get('/admin', mw.adminOnly, (req, res)=>{
|
||||||
templateFn('admin', {
|
templateFn('admin', {
|
||||||
url : req.originalUrl
|
url : req.originalUrl
|
||||||
})
|
})
|
||||||
.then((page)=>res.send(page))
|
.then((page)=>res.send(page))
|
||||||
.catch((err)=>res.sendStatus(500));
|
.catch((err)=>res.sendStatus(500));
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@@ -304,7 +304,8 @@ app.get('/new/:id', asyncHandler(getBrew('share')), (req, res, next)=>{
|
|||||||
text : req.brew.text,
|
text : req.brew.text,
|
||||||
style : req.brew.style,
|
style : req.brew.style,
|
||||||
renderer : req.brew.renderer,
|
renderer : req.brew.renderer,
|
||||||
theme : req.brew.theme
|
theme : req.brew.theme,
|
||||||
|
tags : req.brew.tags
|
||||||
};
|
};
|
||||||
req.brew = _.defaults(brew, DEFAULT_BREW);
|
req.brew = _.defaults(brew, DEFAULT_BREW);
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,39 @@ const Marked = require('marked');
|
|||||||
const MarkedExtendedTables = require('marked-extended-tables');
|
const MarkedExtendedTables = require('marked-extended-tables');
|
||||||
const { markedSmartypantsLite: MarkedSmartypantsLite } = require('marked-smartypants-lite');
|
const { markedSmartypantsLite: MarkedSmartypantsLite } = require('marked-smartypants-lite');
|
||||||
const { gfmHeadingId: MarkedGFMHeadingId } = require('marked-gfm-heading-id');
|
const { gfmHeadingId: MarkedGFMHeadingId } = require('marked-gfm-heading-id');
|
||||||
|
const MathParser = require('expr-eval').Parser;
|
||||||
const renderer = new Marked.Renderer();
|
const renderer = new Marked.Renderer();
|
||||||
const tokenizer = new Marked.Tokenizer();
|
const tokenizer = new Marked.Tokenizer();
|
||||||
|
|
||||||
|
//Limit math features to simple items
|
||||||
|
const mathParser = new MathParser({
|
||||||
|
operators: {
|
||||||
|
// These default to true, but are included to be explicit
|
||||||
|
add : true,
|
||||||
|
subtract : true,
|
||||||
|
multiply : true,
|
||||||
|
divide : true,
|
||||||
|
power : true,
|
||||||
|
round : true,
|
||||||
|
|
||||||
|
sin : false, cos : false, tan : false, asin : false, acos : false,
|
||||||
|
atan : false, sinh : false, cosh : false, tanh : false, asinh : false,
|
||||||
|
acosh : false, atanh : false, sqrt : false, cbrt : false, log : false,
|
||||||
|
log2 : false, ln : false, lg : false, log10: false, expm1 : false,
|
||||||
|
log1p : false, abs : false, ceil : false, floor: false, trunc : false,
|
||||||
|
'-' : false, '+' : false, exp : false, not : false, length: false,
|
||||||
|
'!' : false, sign : false, random : false, fac : false, min : false,
|
||||||
|
max : false, hypot : false, pyt : false, pow : false, atan2 : false,
|
||||||
|
'if' : false, gamma : false, roundTo: false, map : false, fold : false,
|
||||||
|
filter: false, indexOf: false, join : false, sum : false,
|
||||||
|
|
||||||
|
remainder : false, factorial : false,
|
||||||
|
comparison : false, concatenate : false,
|
||||||
|
logical : false, assignment : false,
|
||||||
|
array : false, fndef : false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
//Processes the markdown within an HTML block if it's just a class-wrapper
|
//Processes the markdown within an HTML block if it's just a class-wrapper
|
||||||
renderer.html = function (html) {
|
renderer.html = function (html) {
|
||||||
if(_.startsWith(_.trim(html), '<div') && _.endsWith(_.trim(html), '</div>')){
|
if(_.startsWith(_.trim(html), '<div') && _.endsWith(_.trim(html), '</div>')){
|
||||||
@@ -29,9 +59,26 @@ renderer.paragraph = function(text){
|
|||||||
return `<p>${text}</p>\n`;
|
return `<p>${text}</p>\n`;
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: may not be needed
|
//Fix local links in the Preview iFrame to link inside the frame
|
||||||
// Disable default reflink definitions
|
renderer.link = function (href, title, text) {
|
||||||
tokenizer.def = function(){
|
let self = false;
|
||||||
|
if(href[0] == '#') {
|
||||||
|
self = true;
|
||||||
|
}
|
||||||
|
href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
||||||
|
|
||||||
|
if(href === null) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
let out = `<a href="${escape(href)}"`;
|
||||||
|
if(title) {
|
||||||
|
out += ` title="${title}"`;
|
||||||
|
}
|
||||||
|
if(self) {
|
||||||
|
out += ' target="_self"';
|
||||||
|
}
|
||||||
|
out += `>${text}</a>`;
|
||||||
|
return out;
|
||||||
};
|
};
|
||||||
|
|
||||||
const mustacheSpans = {
|
const mustacheSpans = {
|
||||||
@@ -273,7 +320,7 @@ const definitionLists = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//v=====--------------------< Variable Handling >-------------------=====v// 295 lines
|
//v=====--------------------< Variable Handling >-------------------=====v// 258 lines
|
||||||
const replaceVar = function(input, hoist=false) {
|
const replaceVar = function(input, hoist=false) {
|
||||||
const regex = /([!$]?)\[((?!\s*\])(?:\\.|[^\[\]\\])+)/g;
|
const regex = /([!$]?)\[((?!\s*\])(?:\\.|[^\[\]\\])+)/g;
|
||||||
const match = regex.exec(input);
|
const match = regex.exec(input);
|
||||||
@@ -284,36 +331,31 @@ const replaceVar = function(input, hoist=false) {
|
|||||||
let missingValues = [];
|
let missingValues = [];
|
||||||
|
|
||||||
//v=====--------------------< HANDLE MATH >-------------------=====v//
|
//v=====--------------------< HANDLE MATH >-------------------=====v//
|
||||||
const mathRegex = /[^+\-*\/]+|[+\-*\/]/g;
|
const variableRegex = /[a-zA-Z_][a-zA-Z0-9_]*(?=\s*(?:[+\-*\/()]|$))/g; // Capture only variables, ignore mathy stuff
|
||||||
let mathLabels = label.match(mathRegex).map((s)=>s.trim());
|
let mathVars = label.match(variableRegex)?.map((s)=>s.trim());
|
||||||
|
|
||||||
if(mathLabels.length > 2 && mathLabels.length % 2 == 1) {
|
let replacedLabel = label;
|
||||||
|
|
||||||
const valid = mathLabels.every((val, i)=>{ // Math must alternate between operators and values
|
if(mathVars?.[0] !== label.trim()) {// If there was mathy stuff not captured, let's do math!
|
||||||
const isOperator = '+-*/'.includes(val);
|
mathVars?.forEach((variable) => {
|
||||||
return (i % 2 === 0 ? !isOperator : isOperator);
|
const foundVar = lookupVar(variable, globalPageNumber, hoist);
|
||||||
});
|
if(foundVar && foundVar.resolved && foundVar.content && !isNaN(foundVar.content)) { // Only subsitute math values if fully resolved, not empty strings, and numbers
|
||||||
if(!valid)
|
replacedLabel = replacedLabel.replaceAll(variable, foundVar.content);
|
||||||
return { value: input, missingValues: missingValues };
|
}
|
||||||
|
else {
|
||||||
mathLabels = mathLabels.map((str)=>{
|
missingValues.push(foundVar);
|
||||||
if(!isNaN(str))
|
}
|
||||||
return Number(str);
|
|
||||||
|
|
||||||
if('+-*/'.includes(str))
|
|
||||||
return str;
|
|
||||||
|
|
||||||
const foundVar = lookupVar(str, globalPageNumber, hoist);
|
|
||||||
if(foundVar && foundVar.resolved && foundVar.content) // Only subsitute math values if fully resolved and not empty strings
|
|
||||||
return foundVar.content;
|
|
||||||
|
|
||||||
return str;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
missingValues = mathLabels.filter((x)=>isNaN(x) && !'+-*/'.includes(x));
|
let result;
|
||||||
|
try {
|
||||||
|
result = mathParser.evaluate(replacedLabel);
|
||||||
|
} catch (error) {
|
||||||
|
result = input;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
value : missingValues.length > 0 ? input : eval(mathLabels.join('')),
|
value : result,
|
||||||
missingValues : missingValues
|
missingValues : missingValues
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -345,10 +387,10 @@ const replaceVar = function(input, hoist=false) {
|
|||||||
let value;
|
let value;
|
||||||
|
|
||||||
if(!prefix[0] && href) // Link
|
if(!prefix[0] && href) // Link
|
||||||
value = `[${label}](${href} ${title ? title : ''})`;
|
value = `[${label}](${href}${title ? ` ${title}` : ''})`;
|
||||||
|
|
||||||
if(prefix[0] == '!' && href) // Image
|
if(prefix[0] == '!' && href) // Image
|
||||||
value = ``;
|
value = ``;
|
||||||
|
|
||||||
if(prefix[0] == '$') // Variable
|
if(prefix[0] == '$') // Variable
|
||||||
value = foundVar.content;
|
value = foundVar.content;
|
||||||
@@ -376,209 +418,169 @@ const lookupVar = function(label, index, hoist=false) {
|
|||||||
const processVariableQueue = function() {
|
const processVariableQueue = function() {
|
||||||
let resolvedOne = true;
|
let resolvedOne = true;
|
||||||
let finalLoop = false;
|
let finalLoop = false;
|
||||||
let newQueue = [];
|
|
||||||
while (resolvedOne || finalLoop) { // Loop through queue until no more variable calls can be resolved
|
while (resolvedOne || finalLoop) { // Loop through queue until no more variable calls can be resolved
|
||||||
newQueue = [];
|
|
||||||
resolvedOne = false;
|
resolvedOne = false;
|
||||||
|
|
||||||
for (const item of linksQueue) {
|
for (const item of linksQueue) {
|
||||||
const value = replaceVar(item.match, true);
|
if(item.type == 'text')
|
||||||
|
continue;
|
||||||
|
|
||||||
if(value.missingValues.length > 0 && !finalLoop) { // Variable not found; try again next loop.
|
if(item.type == 'varDefBlock' || item.type == 'varDefInline') {
|
||||||
newQueue.push(item); // If previous loops could not resolve any new vars,
|
const regex = /[!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\]/g;
|
||||||
continue; // final loop will just use the best value so far
|
let match;
|
||||||
} // (may be only partially resolved)
|
let resolved = true;
|
||||||
|
let tempContent = item.content;
|
||||||
|
while (match = regex.exec(item.content)) { // regex to find variable calls
|
||||||
|
const value = replaceVar(match[0], true);
|
||||||
|
|
||||||
resolvedOne = true;
|
if(value.missingValues.length > 0) {
|
||||||
|
resolved = false;
|
||||||
|
} else {
|
||||||
|
item.content = item.content.replaceAll(match[0], value.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
item.token.content = item.token.content.replace(item.match, value.value);
|
if(resolved == true || item.content != tempContent) {
|
||||||
|
resolvedOne = true;
|
||||||
|
}
|
||||||
|
|
||||||
if(item.token.type == 'varDefBlock' || item.token.type == 'varDefInline') {
|
globalLinks[globalPageNumber][item.varName] = {
|
||||||
globalLinks[globalPageNumber][item.token.label] = {
|
content : item.content,
|
||||||
content : item.token.content,
|
resolved : resolved
|
||||||
resolved : true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(item.type == 'varDefBlock' && resolved){
|
||||||
|
item.type = 'resolved';
|
||||||
|
}
|
||||||
|
if(item.type == 'varDefInline' && resolved){
|
||||||
|
item.type = 'text';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(item.type == 'varCallBlock' || item.type == 'varCallInline') {
|
||||||
|
const value = replaceVar(item.match, true);
|
||||||
|
|
||||||
|
if(value.missingValues.length > 0 && !finalLoop) { // Variable not found or not fully resolved; try again next loop.
|
||||||
|
continue; // final loop will just use the best value so far
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvedOne = true;
|
||||||
|
item.content = item.content.replace(item.match, value.value);
|
||||||
|
item.type = 'text';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
linksQueue = newQueue;
|
linksQueue = linksQueue.filter(item => item.type !== 'resolved'); // Remove any fully-resolved variables
|
||||||
|
|
||||||
if(finalLoop)
|
if(finalLoop)
|
||||||
break;
|
break;
|
||||||
if(!resolvedOne)
|
if(!resolvedOne)
|
||||||
finalLoop = true;
|
finalLoop = true;
|
||||||
}
|
}
|
||||||
|
linksQueue = linksQueue.filter(item => item.type !== 'varDefBlock');
|
||||||
};
|
};
|
||||||
|
|
||||||
const walkVariableTokens = {
|
function MarkedVariables() {
|
||||||
walkTokens(token) {
|
return {
|
||||||
if(token.type == 'varDefBlock' || token.type == 'varDefInline') {
|
hooks: {
|
||||||
|
preprocess(src) {
|
||||||
|
const blockDefRegex = /^[!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\]:(?!\() *((?:\n? *[^\s].*)+)(?=\n+|$)/; //Matches 1, [2]:3
|
||||||
|
const blockCallRegex = /^[!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\](?=\n|$)/; //Matches 4, [5]
|
||||||
|
const inlineDefRegex = /([!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\])\(([^\n]+?)\)/; //Matches 6, 7[8](9)
|
||||||
|
const inlineCallRegex = /[!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\](?!\()/; //Matches 10, [11]
|
||||||
|
|
||||||
const regex = /[!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\]/g;
|
// Combine regexes like so: (regex1)|(regex2)|(regex3)|(regex4)
|
||||||
let match;
|
let combinedRegex = new RegExp([blockDefRegex, blockCallRegex, inlineDefRegex, inlineCallRegex].map(s => `(${s.source})`).join('|'), 'gm');
|
||||||
let resolved = true;
|
|
||||||
while (match = regex.exec(token.content)) { // regex to find variable calls
|
|
||||||
const value = replaceVar(match[0]);
|
|
||||||
|
|
||||||
if(value.missingValues.length > 0) {
|
let lastIndex = 0;
|
||||||
for (let i = 0; i < value.missingValues.length; i++) {
|
let match;
|
||||||
linksQueue.push({ token: token, match: match[0], varName: value.missingValues[i] });
|
while ((match = combinedRegex.exec(src)) !== null) {
|
||||||
}
|
// Form any matches into tokens and store
|
||||||
resolved = false;
|
if (match.index > lastIndex) {
|
||||||
} else {
|
linksQueue.push(
|
||||||
token.content = token.content.replace(match[0], value.value);
|
{ type : 'text',
|
||||||
|
match : src.slice(lastIndex, match.index),
|
||||||
|
varName : null,
|
||||||
|
content : src.slice(lastIndex, match.index)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(match[1]) { // Block Definition
|
||||||
|
const label = match[2] ? match[2].trim().replace(/\s+/g, ' ').toLowerCase() : null; // Trim edge spaces and shorten blocks of whitespace to 1 space
|
||||||
|
const content = match[3] ? match[3].trim().replace(/\s+/g, ' ') : null; // Trim edge spaces and shorten blocks of whitespace to 1 space
|
||||||
|
|
||||||
|
linksQueue.push(
|
||||||
|
{ type : 'varDefBlock',
|
||||||
|
match : match[0],
|
||||||
|
varName : label,
|
||||||
|
content : content
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(match[4]) { // Block Call
|
||||||
|
const label = match[5] ? match[5].trim().replace(/\s+/g, ' ').toLowerCase() : null; // Trim edge spaces and shorten blocks of whitespace to 1 space
|
||||||
|
|
||||||
|
linksQueue.push(
|
||||||
|
{ type : 'varCallBlock',
|
||||||
|
match : match[0],
|
||||||
|
varName : label,
|
||||||
|
content : match[0]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(match[6]) { // Inline Definition
|
||||||
|
const label = match[8] ? match[8].trim().replace(/\s+/g, ' ').toLowerCase() : null; // Trim edge spaces and shorten blocks of whitespace to 1 space
|
||||||
|
const content = match[9] ? match[9].trim().replace(/\s+/g, ' ') : null; // Trim edge spaces and shorten blocks of whitespace to 1 space
|
||||||
|
|
||||||
|
linksQueue.push(
|
||||||
|
{ type : 'varDefBlock',
|
||||||
|
match : match[0],
|
||||||
|
varName : label,
|
||||||
|
content : content
|
||||||
|
});
|
||||||
|
linksQueue.push(
|
||||||
|
{ type : 'varCallInline',
|
||||||
|
match : match[7],
|
||||||
|
varName : label,
|
||||||
|
content : match[7]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if(match[10]) { // Inline Call
|
||||||
|
const label = match[11] ? match[11].trim().replace(/\s+/g, ' ').toLowerCase() : null; // Trim edge spaces and shorten blocks of whitespace to 1 space
|
||||||
|
|
||||||
|
linksQueue.push(
|
||||||
|
{ type : 'varCallInline',
|
||||||
|
match : match[0],
|
||||||
|
varName : label,
|
||||||
|
content : match[0]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
lastIndex = combinedRegex.lastIndex;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
globalLinks[globalPageNumber][token.label] = {
|
if (lastIndex < src.length) {
|
||||||
content : token.content,
|
linksQueue.push(
|
||||||
resolved : resolved
|
{ type : 'text',
|
||||||
};
|
match : src.slice(lastIndex),
|
||||||
if(token.type == 'varDefInline') //Inline definitions are also inline calls; after storing the value, change type so it can be displayed
|
varName : null,
|
||||||
token.type = 'varCallInline';
|
content : src.slice(lastIndex)
|
||||||
}
|
});
|
||||||
if(token.type == 'varCallBlock' || token.type == 'varCallInline' || token.originalType == 'varCallBlock' || token.originalType == 'varCallInline') {
|
|
||||||
const value = replaceVar(token.raw);
|
|
||||||
if(value.missingValues.length > 0) {
|
|
||||||
|
|
||||||
for (let i = 0; i < value.missingValues.length; i++) {
|
|
||||||
linksQueue.push({ token: token, match: token.raw, varName: value.missingValues[i] });
|
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
token.content = token.content.replace(token.content, value.value);
|
processVariableQueue();
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const varDefBlock = {
|
const output = linksQueue.map(item => item.content).join('');
|
||||||
name : 'varDefBlock',
|
linksQueue = []; // Must clear linksQueue because custom HTML renderer uses Marked.parse which will preprocess again without clearing the array
|
||||||
level : 'block',
|
return output;
|
||||||
start(src) {return src.match(/\n {0,3}[!$]?\[(?!\s*\])(?:\\.|[^\[\]\\])+\]:/m)?.index; },
|
}
|
||||||
tokenizer(src, tokens) {
|
}
|
||||||
// [ variable name (spaces allowed) ]: Any text, including into newlines (but no fully blank lines)
|
};
|
||||||
const regex = /^ {0,3}[!$]?\[((?!\s*\])(?:\\.|[^\[\]\\])+)\]:(?!\() *((?:\n? *[^\s].*)+)(?=\n+|$)/;
|
|
||||||
const match = regex.exec(src);
|
|
||||||
if(match) {
|
|
||||||
const label = match[1] ? match[1].trim().replace(/\s+/g, ' ').toLowerCase() : null; // Trim edge spaces and shorten blocks of whitespace to 1 space
|
|
||||||
const content = match[2] ? match[2].trim().replace(/[ \t]+/g, ' ') : null; // Trim edge spaces and shorten blocks of whitespace to 1 space
|
|
||||||
|
|
||||||
return {
|
|
||||||
type : 'varDefBlock',
|
|
||||||
raw : match[0],
|
|
||||||
label : label,
|
|
||||||
content : content
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
renderer(token){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const varDefInline = {
|
|
||||||
name : 'varDefInline',
|
|
||||||
level : 'inline',
|
|
||||||
start(src) {return src.match(/\n?[!$]?\[(?!\s*\])(?:\\.|[^\[\]\\])+\]:\(.*\)/m)?.index;},
|
|
||||||
tokenizer(src, tokens) {
|
|
||||||
if(!parseVars) //Don't re-parse variable defs inside of another variable call
|
|
||||||
return;
|
|
||||||
// [ variable name (spaces allowed) ]: Any text, including into newlines (but no fully blank lines)
|
|
||||||
const regex = /^\n?([!$]?)\[((?!\s*\])(?:\\.|[^\[\]\\])+)\]:\((.+?)\)/;
|
|
||||||
const match = regex.exec(src);
|
|
||||||
if(match) {
|
|
||||||
const label = match[2] ? match[2].trim().replace(/\s+/g, ' ').toLowerCase() : null; // Trim edge spaces and shorten blocks of whitespace to 1 space
|
|
||||||
const content = match[3] ? match[3].trim().replace(/\s+/g, ' ') : null; // Trim edge spaces and shorten blocks of whitespace to 1 space
|
|
||||||
|
|
||||||
return {
|
|
||||||
type : 'varDefInline',
|
|
||||||
raw : match[0],
|
|
||||||
label : label,
|
|
||||||
content : content
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
renderer(token) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const varCallBlock = {
|
|
||||||
name : 'varCallBlock',
|
|
||||||
level : 'block',
|
|
||||||
start(src) {return src.match(/\n[!$]?\[(?!\s*\])(?:\\.|[^\[\]\\])+\]/m)?.index;},
|
|
||||||
tokenizer(src, tokens) {
|
|
||||||
if(!parseVars) //Don't re-parse variable calls inside of another variable call
|
|
||||||
return;
|
|
||||||
|
|
||||||
// [ variable name (spaces allowed) ] no following text allowed
|
|
||||||
const regex = /^([!$]?)\[((?!\s*\])(?:\\.|[^\[\]\\])+)\](?=\n|$)/;
|
|
||||||
const match = regex.exec(src);
|
|
||||||
if(match) {
|
|
||||||
return {
|
|
||||||
type : 'varCallBlock',
|
|
||||||
raw : match[0],
|
|
||||||
content : match[0]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
renderer(token){
|
|
||||||
const tokens = new Marked.Lexer(Marked.defaults).lex(token.content);
|
|
||||||
return this.parser.parse(tokens);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const varCallInline = {
|
|
||||||
name : 'varCallInline',
|
|
||||||
level : 'inline',
|
|
||||||
start(src) {return src.match(/[!$]?\[(?!\s*\])(?:\\.|[^\[\]\\])+\]/m)?.index;},
|
|
||||||
tokenizer(src, tokens) {
|
|
||||||
if(!parseVars) //Don't re-parse variable calls inside of another variable call
|
|
||||||
return;
|
|
||||||
|
|
||||||
// [ variable name (spaces allowed) ]: Any text, including into newlines (but no fully blank lines)
|
|
||||||
const regex = /^([!$]?)\[((?!\s*\])(?:\\.|[^\[\]\\])+)\](?!\()/; // Do not allow `(` after, since that is needed for normal images/links
|
|
||||||
const match = regex.exec(src);
|
|
||||||
if(match) {
|
|
||||||
return {
|
|
||||||
type : 'varCallInline',
|
|
||||||
raw : match[0],
|
|
||||||
content : match[0]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
renderer(token){
|
|
||||||
const tokens = new Marked.Lexer(Marked.defaults).inlineTokens(token.content);
|
|
||||||
return this.parser.parseInline(tokens);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
//^=====--------------------< Variable Handling >-------------------=====^//
|
//^=====--------------------< Variable Handling >-------------------=====^//
|
||||||
|
|
||||||
Marked.use({ extensions: [mustacheSpans, mustacheDivs, mustacheInjectInline, definitionLists, superSubScripts, varCallInline, varDefInline, varCallBlock, varDefBlock] });
|
Marked.use(MarkedVariables())
|
||||||
Marked.use(mustacheInjectBlock, walkVariableTokens);
|
Marked.use({ extensions: [mustacheSpans, mustacheDivs, mustacheInjectInline, definitionLists, superSubScripts] });
|
||||||
|
Marked.use(mustacheInjectBlock);
|
||||||
Marked.use({ renderer: renderer, tokenizer: tokenizer, mangle: false });
|
Marked.use({ renderer: renderer, tokenizer: tokenizer, mangle: false });
|
||||||
Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId(), MarkedSmartypantsLite());
|
Marked.use(MarkedExtendedTables(), MarkedGFMHeadingId(), MarkedSmartypantsLite());
|
||||||
|
|
||||||
//Fix local links in the Preview iFrame to link inside the frame
|
|
||||||
renderer.link = function (href, title, text) {
|
|
||||||
let self = false;
|
|
||||||
if(href[0] == '#') {
|
|
||||||
self = true;
|
|
||||||
}
|
|
||||||
href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
|
|
||||||
|
|
||||||
if(href === null) {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
let out = `<a href="${escape(href)}"`;
|
|
||||||
if(title) {
|
|
||||||
out += ` title="${title}"`;
|
|
||||||
}
|
|
||||||
if(self) {
|
|
||||||
out += ' target="_self"';
|
|
||||||
}
|
|
||||||
out += `>${text}</a>`;
|
|
||||||
return out;
|
|
||||||
};
|
|
||||||
|
|
||||||
const nonWordAndColonTest = /[^\w:]/g;
|
const nonWordAndColonTest = /[^\w:]/g;
|
||||||
const cleanUrl = function (sanitize, base, href) {
|
const cleanUrl = function (sanitize, base, href) {
|
||||||
if(sanitize) {
|
if(sanitize) {
|
||||||
@@ -664,7 +666,7 @@ module.exports = {
|
|||||||
marked : Marked,
|
marked : Marked,
|
||||||
render : (rawBrewText, pageNumber=1)=>{
|
render : (rawBrewText, pageNumber=1)=>{
|
||||||
globalLinks[pageNumber] = {}; //Reset global links for current page, to ensure values are parsed in order
|
globalLinks[pageNumber] = {}; //Reset global links for current page, to ensure values are parsed in order
|
||||||
linksQueue = [];
|
linksQueue = []; //Could move into MarkedVariables()
|
||||||
globalPageNumber = pageNumber;
|
globalPageNumber = pageNumber;
|
||||||
|
|
||||||
parseVars = true;
|
parseVars = true;
|
||||||
@@ -677,9 +679,9 @@ module.exports = {
|
|||||||
const tokens = Marked.lexer(rawBrewText, opts);
|
const tokens = Marked.lexer(rawBrewText, opts);
|
||||||
|
|
||||||
Marked.walkTokens(tokens, opts.walkTokens);
|
Marked.walkTokens(tokens, opts.walkTokens);
|
||||||
processVariableQueue();
|
|
||||||
|
|
||||||
parseVars = false;
|
parseVars = false;
|
||||||
|
|
||||||
const html = Marked.parser(tokens, opts);
|
const html = Marked.parser(tokens, opts);
|
||||||
return opts.hooks.postprocess(html);
|
return opts.hooks.postprocess(html);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user