mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-05 10:12:41 +00:00
Merge branch 'master' into addEditorThemes-#362
This commit is contained in:
@@ -63,7 +63,7 @@ jobs:
|
|||||||
command: npm run test:basic
|
command: npm run test:basic
|
||||||
- run:
|
- run:
|
||||||
name: Test - Mustache Spans
|
name: Test - Mustache Spans
|
||||||
command: npm run test:mustache-span
|
command: npm run test:mustache-syntax
|
||||||
- run:
|
- run:
|
||||||
name: Test - Routes
|
name: Test - Routes
|
||||||
command: npm run test:route
|
command: npm run test:route
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ module.exports = {
|
|||||||
'react/jsx-no-bind' : ['error', { allowArrowFunctions: true }],
|
'react/jsx-no-bind' : ['error', { allowArrowFunctions: true }],
|
||||||
'react/jsx-uses-react' : 'error',
|
'react/jsx-uses-react' : 'error',
|
||||||
'react/prefer-es6-class' : ['error', 'never'],
|
'react/prefer-es6-class' : ['error', 'never'],
|
||||||
|
'jest/valid-expect' : ['error', { maxArgs: 2 }],
|
||||||
|
|
||||||
/** Warnings **/
|
/** Warnings **/
|
||||||
'max-lines' : ['warn', {
|
'max-lines' : ['warn', {
|
||||||
|
|||||||
@@ -82,6 +82,13 @@ For a full record of development, visit our [Github Page](https://github.com/nat
|
|||||||
|
|
||||||
### XXXXday DD/MM/2023 - v3.8.0
|
### XXXXday DD/MM/2023 - v3.8.0
|
||||||
{{taskList
|
{{taskList
|
||||||
|
|
||||||
|
##### Jeddai
|
||||||
|
|
||||||
|
* [X] Add content negotiation to exclude image requests from our API calls
|
||||||
|
|
||||||
|
Fixes issue [#2595](https://github.com/naturalcrit/homebrewery/issues/2595)
|
||||||
|
|
||||||
##### G-Ambatte
|
##### G-Ambatte
|
||||||
|
|
||||||
* [x] Update server build scripts to fix Admin page
|
* [x] Update server build scripts to fix Admin page
|
||||||
|
|||||||
@@ -82,4 +82,4 @@ const ErrorNavItem = createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = ErrorNavItem;
|
module.exports = ErrorNavItem;
|
||||||
|
|||||||
@@ -1,77 +1,75 @@
|
|||||||
.navItem {
|
.navItem.error {
|
||||||
&.error {
|
position : relative;
|
||||||
position : relative;
|
background-color : @red;
|
||||||
background-color : @red;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.errorContainer{
|
.errorContainer{
|
||||||
animation-name: glideDown;
|
animation-name: glideDown;
|
||||||
animation-duration: 0.4s;
|
animation-duration: 0.4s;
|
||||||
position : absolute;
|
position : absolute;
|
||||||
top : 100%;
|
top : 100%;
|
||||||
left : 50%;
|
left : 50%;
|
||||||
z-index : 1000;
|
z-index : 1000;
|
||||||
width : 140px;
|
width : 140px;
|
||||||
padding : 3px;
|
padding : 3px;
|
||||||
color : white;
|
color : white;
|
||||||
|
background-color : #333;
|
||||||
|
border : 3px solid #444;
|
||||||
|
border-radius : 5px;
|
||||||
|
transform : translate(-50% + 3px, 10px);
|
||||||
|
text-align : center;
|
||||||
|
font-size : 10px;
|
||||||
|
font-weight : 800;
|
||||||
|
text-transform : uppercase;
|
||||||
|
a{
|
||||||
|
color : @teal;
|
||||||
|
}
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
position: absolute;
|
||||||
|
border-left: 10px solid transparent;
|
||||||
|
border-right: 10px solid transparent;
|
||||||
|
border-top: 10px solid transparent;
|
||||||
|
border-bottom: 10px solid #444;
|
||||||
|
left: 53px;
|
||||||
|
top: -23px;
|
||||||
|
}
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
position: absolute;
|
||||||
|
border-left: 10px solid transparent;
|
||||||
|
border-right: 10px solid transparent;
|
||||||
|
border-top: 10px solid transparent;
|
||||||
|
border-bottom: 10px solid #333;
|
||||||
|
left: 53px;
|
||||||
|
top: -19px;
|
||||||
|
}
|
||||||
|
.deny {
|
||||||
|
width : 48%;
|
||||||
|
margin : 1px;
|
||||||
|
padding : 5px;
|
||||||
background-color : #333;
|
background-color : #333;
|
||||||
border : 3px solid #444;
|
display : inline-block;
|
||||||
border-radius : 5px;
|
border-left : 1px solid #666;
|
||||||
transform : translate(-50% + 3px, 10px);
|
.animate(background-color);
|
||||||
text-align : center;
|
&:hover{
|
||||||
font-size : 10px;
|
background-color : red;
|
||||||
font-weight : 800;
|
|
||||||
text-transform : uppercase;
|
|
||||||
a{
|
|
||||||
color : @teal;
|
|
||||||
}
|
|
||||||
&:before {
|
|
||||||
content: "";
|
|
||||||
width: 0px;
|
|
||||||
height: 0px;
|
|
||||||
position: absolute;
|
|
||||||
border-left: 10px solid transparent;
|
|
||||||
border-right: 10px solid transparent;
|
|
||||||
border-top: 10px solid transparent;
|
|
||||||
border-bottom: 10px solid #444;
|
|
||||||
left: 53px;
|
|
||||||
top: -23px;
|
|
||||||
}
|
|
||||||
&:after {
|
|
||||||
content: "";
|
|
||||||
width: 0px;
|
|
||||||
height: 0px;
|
|
||||||
position: absolute;
|
|
||||||
border-left: 10px solid transparent;
|
|
||||||
border-right: 10px solid transparent;
|
|
||||||
border-top: 10px solid transparent;
|
|
||||||
border-bottom: 10px solid #333;
|
|
||||||
left: 53px;
|
|
||||||
top: -19px;
|
|
||||||
}
|
|
||||||
.deny {
|
|
||||||
width : 48%;
|
|
||||||
margin : 1px;
|
|
||||||
padding : 5px;
|
|
||||||
background-color : #333;
|
|
||||||
display : inline-block;
|
|
||||||
border-left : 1px solid #666;
|
|
||||||
.animate(background-color);
|
|
||||||
&:hover{
|
|
||||||
background-color : red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.confirm {
|
|
||||||
width : 48%;
|
|
||||||
margin : 1px;
|
|
||||||
padding : 5px;
|
|
||||||
background-color : #333;
|
|
||||||
display : inline-block;
|
|
||||||
color : white;
|
|
||||||
.animate(background-color);
|
|
||||||
&:hover{
|
|
||||||
background-color : teal;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
.confirm {
|
||||||
|
width : 48%;
|
||||||
|
margin : 1px;
|
||||||
|
padding : 5px;
|
||||||
|
background-color : #333;
|
||||||
|
display : inline-block;
|
||||||
|
color : white;
|
||||||
|
.animate(background-color);
|
||||||
|
&:hover{
|
||||||
|
background-color : teal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -254,6 +254,15 @@ const EditPage = createClass({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{this.state.alertTrashedGoogleBrew &&
|
||||||
|
<div className='errorContainer' onClick={this.closeAlerts}>
|
||||||
|
This brew is currently in your Trash folder on Google Drive!<br />If you want to keep it, make sure to move it before it is deleted permanently!<br />
|
||||||
|
<div className='confirm'>
|
||||||
|
OK
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</Nav.item>;
|
</Nav.item>;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -335,16 +344,6 @@ const EditPage = createClass({
|
|||||||
const shareLink = this.processShareId();
|
const shareLink = this.processShareId();
|
||||||
|
|
||||||
return <Navbar>
|
return <Navbar>
|
||||||
|
|
||||||
{this.state.alertTrashedGoogleBrew &&
|
|
||||||
<div className='errorContainer' onClick={this.closeAlerts}>
|
|
||||||
This brew is currently in your Trash folder on Google Drive!<br />If you want to keep it, make sure to move it before it is deleted permanently!<br />
|
|
||||||
<div className='confirm'>
|
|
||||||
OK
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<Nav.section>
|
<Nav.section>
|
||||||
<Nav.item className='brewTitle'>{this.state.brew.title}</Nav.item>
|
<Nav.item className='brewTitle'>{this.state.brew.title}</Nav.item>
|
||||||
</Nav.section>
|
</Nav.section>
|
||||||
|
|||||||
77
package-lock.json
generated
77
package-lock.json
generated
@@ -36,7 +36,7 @@
|
|||||||
"mongoose": "^7.0.3",
|
"mongoose": "^7.0.3",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"nconf": "^0.12.0",
|
"nconf": "^0.12.0",
|
||||||
"npm": "^9.6.3",
|
"npm": "^9.6.4",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-frame-component": "5.2.6",
|
"react-frame-component": "5.2.6",
|
||||||
@@ -46,9 +46,10 @@
|
|||||||
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.37.0",
|
"eslint": "^8.38.0",
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"jest": "^29.5.0",
|
"jest": "^29.5.0",
|
||||||
|
"jest-expect-message": "^1.1.3",
|
||||||
"supertest": "^6.3.3"
|
"supertest": "^6.3.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -1791,9 +1792,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "8.37.0",
|
"version": "8.38.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz",
|
||||||
"integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==",
|
"integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
@@ -4852,15 +4853,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "8.37.0",
|
"version": "8.38.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz",
|
||||||
"integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==",
|
"integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.2.0",
|
"@eslint-community/eslint-utils": "^4.2.0",
|
||||||
"@eslint-community/regexpp": "^4.4.0",
|
"@eslint-community/regexpp": "^4.4.0",
|
||||||
"@eslint/eslintrc": "^2.0.2",
|
"@eslint/eslintrc": "^2.0.2",
|
||||||
"@eslint/js": "8.37.0",
|
"@eslint/js": "8.38.0",
|
||||||
"@humanwhocodes/config-array": "^0.11.8",
|
"@humanwhocodes/config-array": "^0.11.8",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@nodelib/fs.walk": "^1.2.8",
|
"@nodelib/fs.walk": "^1.2.8",
|
||||||
@@ -7489,6 +7490,12 @@
|
|||||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jest-expect-message": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/jest-expect-message/-/jest-expect-message-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-bTK77T4P+zto+XepAX3low8XVQxDgaEqh3jSTQOG8qvPpD69LsIdyJTa+RmnJh3HNSzJng62/44RPPc7OIlFxg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/jest-get-type": {
|
"node_modules/jest-get-type": {
|
||||||
"version": "29.4.3",
|
"version": "29.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
|
||||||
@@ -9576,9 +9583,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/npm": {
|
"node_modules/npm": {
|
||||||
"version": "9.6.3",
|
"version": "9.6.4",
|
||||||
"resolved": "https://registry.npmjs.org/npm/-/npm-9.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/npm/-/npm-9.6.4.tgz",
|
||||||
"integrity": "sha512-KMAw6cJF5JGPJz/NtsU8H1sMqb34qPGnSMaSWrVO8bzxOdAXJNAtDXATvLl0lflrImIze1FZCqocM8wdIu3Sfg==",
|
"integrity": "sha512-8/Mct0X/w77PmgIpSlXfNIOlrZBfT+8966zLCxOhwi1qZ2Ueyy99uWPSDW6bt2OKw1NzrvHJBSgkzAvn1iWuhw==",
|
||||||
"bundleDependencies": [
|
"bundleDependencies": [
|
||||||
"@isaacs/string-locale-compare",
|
"@isaacs/string-locale-compare",
|
||||||
"@npmcli/arborist",
|
"@npmcli/arborist",
|
||||||
@@ -9649,7 +9656,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@isaacs/string-locale-compare": "^1.1.0",
|
"@isaacs/string-locale-compare": "^1.1.0",
|
||||||
"@npmcli/arborist": "^6.2.6",
|
"@npmcli/arborist": "^6.2.7",
|
||||||
"@npmcli/config": "^6.1.5",
|
"@npmcli/config": "^6.1.5",
|
||||||
"@npmcli/map-workspaces": "^3.0.3",
|
"@npmcli/map-workspaces": "^3.0.3",
|
||||||
"@npmcli/package-json": "^3.0.0",
|
"@npmcli/package-json": "^3.0.0",
|
||||||
@@ -9664,7 +9671,7 @@
|
|||||||
"columnify": "^1.6.0",
|
"columnify": "^1.6.0",
|
||||||
"fastest-levenshtein": "^1.0.16",
|
"fastest-levenshtein": "^1.0.16",
|
||||||
"fs-minipass": "^3.0.1",
|
"fs-minipass": "^3.0.1",
|
||||||
"glob": "^9.3.1",
|
"glob": "^9.3.2",
|
||||||
"graceful-fs": "^4.2.11",
|
"graceful-fs": "^4.2.11",
|
||||||
"hosted-git-info": "^6.1.1",
|
"hosted-git-info": "^6.1.1",
|
||||||
"ini": "^3.0.1",
|
"ini": "^3.0.1",
|
||||||
@@ -9672,12 +9679,12 @@
|
|||||||
"is-cidr": "^4.0.2",
|
"is-cidr": "^4.0.2",
|
||||||
"json-parse-even-better-errors": "^3.0.0",
|
"json-parse-even-better-errors": "^3.0.0",
|
||||||
"libnpmaccess": "^7.0.2",
|
"libnpmaccess": "^7.0.2",
|
||||||
"libnpmdiff": "^5.0.14",
|
"libnpmdiff": "^5.0.15",
|
||||||
"libnpmexec": "^5.0.14",
|
"libnpmexec": "^5.0.15",
|
||||||
"libnpmfund": "^4.0.14",
|
"libnpmfund": "^4.0.15",
|
||||||
"libnpmhook": "^9.0.3",
|
"libnpmhook": "^9.0.3",
|
||||||
"libnpmorg": "^5.0.3",
|
"libnpmorg": "^5.0.3",
|
||||||
"libnpmpack": "^5.0.14",
|
"libnpmpack": "^5.0.15",
|
||||||
"libnpmpublish": "^7.1.3",
|
"libnpmpublish": "^7.1.3",
|
||||||
"libnpmsearch": "^6.0.2",
|
"libnpmsearch": "^6.0.2",
|
||||||
"libnpmteam": "^5.0.3",
|
"libnpmteam": "^5.0.3",
|
||||||
@@ -9706,7 +9713,7 @@
|
|||||||
"read-package-json": "^6.0.1",
|
"read-package-json": "^6.0.1",
|
||||||
"read-package-json-fast": "^3.0.2",
|
"read-package-json-fast": "^3.0.2",
|
||||||
"semver": "^7.3.8",
|
"semver": "^7.3.8",
|
||||||
"ssri": "^10.0.1",
|
"ssri": "^10.0.2",
|
||||||
"tar": "^6.1.13",
|
"tar": "^6.1.13",
|
||||||
"text-table": "~0.2.0",
|
"text-table": "~0.2.0",
|
||||||
"tiny-relative-date": "^1.3.0",
|
"tiny-relative-date": "^1.3.0",
|
||||||
@@ -9755,7 +9762,7 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/npm/node_modules/@npmcli/arborist": {
|
"node_modules/npm/node_modules/@npmcli/arborist": {
|
||||||
"version": "6.2.6",
|
"version": "6.2.7",
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -9786,7 +9793,7 @@
|
|||||||
"parse-conflict-json": "^3.0.0",
|
"parse-conflict-json": "^3.0.0",
|
||||||
"proc-log": "^3.0.0",
|
"proc-log": "^3.0.0",
|
||||||
"promise-all-reject-late": "^1.0.0",
|
"promise-all-reject-late": "^1.0.0",
|
||||||
"promise-call-limit": "^1.0.1",
|
"promise-call-limit": "^1.0.2",
|
||||||
"read-package-json-fast": "^3.0.2",
|
"read-package-json-fast": "^3.0.2",
|
||||||
"semver": "^7.3.7",
|
"semver": "^7.3.7",
|
||||||
"ssri": "^10.0.1",
|
"ssri": "^10.0.1",
|
||||||
@@ -10514,7 +10521,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/npm/node_modules/glob": {
|
"node_modules/npm/node_modules/glob": {
|
||||||
"version": "9.3.1",
|
"version": "9.3.2",
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -10788,7 +10795,7 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/npm/node_modules/just-diff": {
|
"node_modules/npm/node_modules/just-diff": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.2",
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -10810,11 +10817,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/npm/node_modules/libnpmdiff": {
|
"node_modules/npm/node_modules/libnpmdiff": {
|
||||||
"version": "5.0.14",
|
"version": "5.0.15",
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@npmcli/arborist": "^6.2.6",
|
"@npmcli/arborist": "^6.2.7",
|
||||||
"@npmcli/disparity-colors": "^3.0.0",
|
"@npmcli/disparity-colors": "^3.0.0",
|
||||||
"@npmcli/installed-package-contents": "^2.0.2",
|
"@npmcli/installed-package-contents": "^2.0.2",
|
||||||
"binary-extensions": "^2.2.0",
|
"binary-extensions": "^2.2.0",
|
||||||
@@ -10829,11 +10836,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/npm/node_modules/libnpmexec": {
|
"node_modules/npm/node_modules/libnpmexec": {
|
||||||
"version": "5.0.14",
|
"version": "5.0.15",
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@npmcli/arborist": "^6.2.6",
|
"@npmcli/arborist": "^6.2.7",
|
||||||
"@npmcli/run-script": "^6.0.0",
|
"@npmcli/run-script": "^6.0.0",
|
||||||
"chalk": "^4.1.0",
|
"chalk": "^4.1.0",
|
||||||
"ci-info": "^3.7.1",
|
"ci-info": "^3.7.1",
|
||||||
@@ -10851,11 +10858,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/npm/node_modules/libnpmfund": {
|
"node_modules/npm/node_modules/libnpmfund": {
|
||||||
"version": "4.0.14",
|
"version": "4.0.15",
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@npmcli/arborist": "^6.2.6"
|
"@npmcli/arborist": "^6.2.7"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||||
@@ -10886,11 +10893,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/npm/node_modules/libnpmpack": {
|
"node_modules/npm/node_modules/libnpmpack": {
|
||||||
"version": "5.0.14",
|
"version": "5.0.15",
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@npmcli/arborist": "^6.2.6",
|
"@npmcli/arborist": "^6.2.7",
|
||||||
"@npmcli/run-script": "^6.0.0",
|
"@npmcli/run-script": "^6.0.0",
|
||||||
"npm-package-arg": "^10.1.0",
|
"npm-package-arg": "^10.1.0",
|
||||||
"pacote": "^15.0.8"
|
"pacote": "^15.0.8"
|
||||||
@@ -11749,7 +11756,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/npm/node_modules/path-scurry": {
|
"node_modules/npm/node_modules/path-scurry": {
|
||||||
"version": "1.6.1",
|
"version": "1.6.3",
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "BlueOak-1.0.0",
|
"license": "BlueOak-1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -11757,7 +11764,7 @@
|
|||||||
"minipass": "^4.0.2"
|
"minipass": "^4.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=16 || 14 >=14.17"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
@@ -11800,7 +11807,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/npm/node_modules/promise-call-limit": {
|
"node_modules/npm/node_modules/promise-call-limit": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"funding": {
|
"funding": {
|
||||||
@@ -12088,7 +12095,7 @@
|
|||||||
"license": "CC0-1.0"
|
"license": "CC0-1.0"
|
||||||
},
|
},
|
||||||
"node_modules/npm/node_modules/ssri": {
|
"node_modules/npm/node_modules/ssri": {
|
||||||
"version": "10.0.1",
|
"version": "10.0.2",
|
||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
35
package.json
35
package.json
@@ -23,7 +23,10 @@
|
|||||||
"test:coverage": "jest --coverage --silent --runInBand",
|
"test:coverage": "jest --coverage --silent --runInBand",
|
||||||
"test:dev": "jest --verbose --watch",
|
"test:dev": "jest --verbose --watch",
|
||||||
"test:basic": "jest tests/markdown/basic.test.js --verbose",
|
"test:basic": "jest tests/markdown/basic.test.js --verbose",
|
||||||
"test:mustache-span": "jest tests/markdown/mustache-span.test.js --verbose",
|
"test:mustache-syntax": "jest '.*(mustache-syntax).*' --verbose --noStackTrace",
|
||||||
|
"test:mustache-syntax:inline": "jest '.*(mustache-syntax).*' -t '^Inline:.*' --verbose --noStackTrace",
|
||||||
|
"test:mustache-syntax:block": "jest '.*(mustache-syntax).*' -t '^Block:.*' --verbose --noStackTrace",
|
||||||
|
"test:mustache-syntax:injection": "jest '.*(mustache-syntax).*' -t '^Injection:.*' --verbose --noStackTrace",
|
||||||
"test:route": "jest tests/routes/static-pages.test.js --verbose",
|
"test:route": "jest tests/routes/static-pages.test.js --verbose",
|
||||||
"phb": "node scripts/phb.js",
|
"phb": "node scripts/phb.js",
|
||||||
"prod": "set NODE_ENV=production && npm run build",
|
"prod": "set NODE_ENV=production && npm run build",
|
||||||
@@ -45,20 +48,21 @@
|
|||||||
"coveragePathIgnorePatterns": [
|
"coveragePathIgnorePatterns": [
|
||||||
"build/*"
|
"build/*"
|
||||||
],
|
],
|
||||||
"coverageThreshold" : {
|
"coverageThreshold": {
|
||||||
"global" : {
|
"global": {
|
||||||
"statements" : 25,
|
"statements": 25,
|
||||||
"branches" : 10,
|
"branches": 10,
|
||||||
"functions" : 22,
|
"functions": 22,
|
||||||
"lines" : 25
|
"lines": 25
|
||||||
},
|
},
|
||||||
"server/homebrew.api.js" : {
|
"server/homebrew.api.js": {
|
||||||
"statements" : 65,
|
"statements": 65,
|
||||||
"branches" : 50,
|
"branches": 50,
|
||||||
"functions" : 60,
|
"functions": 60,
|
||||||
"lines" : 70
|
"lines": 70
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"setupFilesAfterEnv": ["jest-expect-message"]
|
||||||
},
|
},
|
||||||
"babel": {
|
"babel": {
|
||||||
"presets": [
|
"presets": [
|
||||||
@@ -96,7 +100,7 @@
|
|||||||
"mongoose": "^7.0.3",
|
"mongoose": "^7.0.3",
|
||||||
"nanoid": "3.3.4",
|
"nanoid": "3.3.4",
|
||||||
"nconf": "^0.12.0",
|
"nconf": "^0.12.0",
|
||||||
"npm": "^9.6.3",
|
"npm": "^9.6.4",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-frame-component": "5.2.6",
|
"react-frame-component": "5.2.6",
|
||||||
@@ -106,9 +110,10 @@
|
|||||||
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
"vitreum": "git+https://git@github.com/calculuschild/vitreum.git"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^8.37.0",
|
"eslint": "^8.38.0",
|
||||||
"eslint-plugin-react": "^7.32.2",
|
"eslint-plugin-react": "^7.32.2",
|
||||||
"jest": "^29.5.0",
|
"jest": "^29.5.0",
|
||||||
|
"jest-expect-message": "^1.1.3",
|
||||||
"supertest": "^6.3.3"
|
"supertest": "^6.3.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,8 +45,7 @@ const sanitizeBrew = (brew, accessType)=>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
app.use('/', serveCompressedStaticAssets(`build`));
|
app.use('/', serveCompressedStaticAssets(`build`));
|
||||||
|
app.use(require('./middleware/content-negotiation.js'));
|
||||||
//app.use(express.static(`${__dirname}/build`));
|
|
||||||
app.use(require('body-parser').json({ limit: '25mb' }));
|
app.use(require('body-parser').json({ limit: '25mb' }));
|
||||||
app.use(require('cookie-parser')());
|
app.use(require('cookie-parser')());
|
||||||
app.use(require('./forcessl.mw.js'));
|
app.use(require('./forcessl.mw.js'));
|
||||||
|
|||||||
12
server/middleware/content-negotiation.js
Normal file
12
server/middleware/content-negotiation.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
module.exports = (req, res, next)=>{
|
||||||
|
const isImageRequest = req.get('Accept')?.split(',')
|
||||||
|
?.filter((h)=>!h.includes('q='))
|
||||||
|
?.every((h)=>/image\/.*/.test(h));
|
||||||
|
if(isImageRequest) {
|
||||||
|
return res.status(406).send({
|
||||||
|
message : 'Request for image at this URL is not supported'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
41
server/middleware/content-negotiation.spec.js
Normal file
41
server/middleware/content-negotiation.spec.js
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
const contentNegotiationMiddleware = require('./content-negotiation.js');
|
||||||
|
|
||||||
|
describe('content-negotiation-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();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return 406 on image request', ()=>{
|
||||||
|
contentNegotiationMiddleware({
|
||||||
|
Accept : 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8',
|
||||||
|
...request
|
||||||
|
}, response);
|
||||||
|
|
||||||
|
expect(response.status).toHaveBeenLastCalledWith(406);
|
||||||
|
expect(response.send).toHaveBeenCalledWith({
|
||||||
|
message : 'Request for image at this URL is not supported'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call next on non-image request', ()=>{
|
||||||
|
contentNegotiationMiddleware({
|
||||||
|
Accept : 'text,image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8',
|
||||||
|
...request
|
||||||
|
}, response, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
/* eslint-disable max-lines */
|
|
||||||
|
|
||||||
const Markdown = require('naturalcrit/markdown.js');
|
|
||||||
|
|
||||||
test('Renders a mustache span with text only', function() {
|
|
||||||
const source = '{{ text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
expect(rendered).toBe('<span class="inline-block ">text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text only, but with spaces', function() {
|
|
||||||
const source = '{{ this is a text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
expect(rendered).toBe('<span class="inline-block ">this is a text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders an empty mustache span', function() {
|
|
||||||
const source = '{{}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
expect(rendered).toBe('<span class="inline-block "></span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with just a space', function() {
|
|
||||||
const source = '{{ }}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
expect(rendered).toBe('<span class="inline-block "></span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with a few spaces only', function() {
|
|
||||||
const source = '{{ }}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
expect(rendered).toBe('<span class="inline-block "></span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text and class', function() {
|
|
||||||
const source = '{{my-class text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
// FIXME: why do we have those two extra spaces after closing "?
|
|
||||||
expect(rendered).toBe('<span class="inline-block my-class" >text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text and two classes', function() {
|
|
||||||
const source = '{{my-class,my-class2 text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
// FIXME: why do we have those two extra spaces after closing "?
|
|
||||||
expect(rendered).toBe('<span class="inline-block my-class my-class2" >text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text with spaces and class', function() {
|
|
||||||
const source = '{{my-class this is a text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
// FIXME: why do we have those two extra spaces after closing "?
|
|
||||||
expect(rendered).toBe('<span class="inline-block my-class" >this is a text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text and id', function() {
|
|
||||||
const source = '{{#my-span text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
// FIXME: why do we have that one extra space after closing "?
|
|
||||||
expect(rendered).toBe('<span class="inline-block " id="my-span" >text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text and two ids', function() {
|
|
||||||
const source = '{{#my-span,#my-favorite-span text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
// FIXME: do we need to report an error here somehow?
|
|
||||||
expect(rendered).toBe('<span class="inline-block " id="my-span" >text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text and css property', function() {
|
|
||||||
const source = '{{color:red text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
expect(rendered).toBe('<span class="inline-block " style="color:red;">text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text and two css properties', function() {
|
|
||||||
const source = '{{color:red,padding:5px text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
expect(rendered).toBe('<span class="inline-block " style="color:red; padding:5px;">text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text and css property which contains quotes', function() {
|
|
||||||
const source = '{{font:"trebuchet ms" text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
// FIXME: is it correct to remove quotes surrounding css property value?
|
|
||||||
expect(rendered).toBe('<span class="inline-block " style="font:trebuchet ms;">text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text and two css properties which contains quotes', function() {
|
|
||||||
const source = '{{font:"trebuchet ms",padding:"5px 10px" text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
expect(rendered).toBe('<span class="inline-block " style="font:trebuchet ms; padding:5px 10px;">text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
test('Renders a mustache span with text with quotes and css property which contains quotes', function() {
|
|
||||||
const source = '{{font:"trebuchet ms" text "with quotes"}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
expect(rendered).toBe('<span class="inline-block " style="font:trebuchet ms;">text “with quotes”</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Renders a mustache span with text, id, class and a couple of css properties', function() {
|
|
||||||
const source = '{{pen,#author,color:orange,font-family:"trebuchet ms" text}}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
expect(rendered).toBe('<span class="inline-block pen" id="author" style="color:orange; font-family:trebuchet ms;">text</span>');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Two consecutive injections into Inline', function() {
|
|
||||||
const source = '{{dog Sample Text}}{cat}{toad}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
// FIXME: Drops original attributes in favor of injection, rather than adding.
|
|
||||||
// FIXME: Doesn't keep the raw text of second injection.
|
|
||||||
// FIXME: Renders the extra class attribute (which is dropped by the browser).
|
|
||||||
expect(rendered).toBe('<p><span class=" cat" class="inline-block cat" >Sample Text</span></p>\n');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Two consecutive injections into Block', function() {
|
|
||||||
const source = '{{dog\nSample Text\n}}\n{cat}\n{toad}';
|
|
||||||
const rendered = Markdown.render(source);
|
|
||||||
// FIXME: Renders the extra class attribute (which is dropped by the browser).
|
|
||||||
expect(rendered).toBe('<div class=" cat" class="block cat" ><p>Sample Text</p>\n</div><p>{toad}</p>\n');
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: add tests for ID with accordance to CSS spec:
|
|
||||||
//
|
|
||||||
// From https://drafts.csswg.org/selectors/#id-selectors:
|
|
||||||
//
|
|
||||||
// > An ID selector consists of a “number sign” (U+0023, #) immediately followed by the ID value, which must be a CSS identifier.
|
|
||||||
//
|
|
||||||
// From: https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier:
|
|
||||||
//
|
|
||||||
// > In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9]
|
|
||||||
// > and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_);
|
|
||||||
// > they cannot start with a digit, two hyphens, or a hyphen followed by a digit.
|
|
||||||
// > Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code (see next item).
|
|
||||||
// > For instance, the identifier "B&W?" may be written as "B\&W\?" or "B\26 W\3F".
|
|
||||||
// > Note that Unicode is code-by-code equivalent to ISO 10646 (see [UNICODE] and [ISO10646]).
|
|
||||||
|
|
||||||
// TODO: add tests for class with accordance to CSS spec:
|
|
||||||
//
|
|
||||||
// From: https://drafts.csswg.org/selectors/#class-html:
|
|
||||||
//
|
|
||||||
// > The class selector is given as a full stop (. U+002E) immediately followed by an identifier.
|
|
||||||
|
|
||||||
376
tests/markdown/mustache-syntax.test.js
Normal file
376
tests/markdown/mustache-syntax.test.js
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
/* eslint-disable max-lines */
|
||||||
|
|
||||||
|
const dedent = require('dedent-tabs').default;
|
||||||
|
const Markdown = require('naturalcrit/markdown.js');
|
||||||
|
|
||||||
|
// Marked.js adds line returns after closing tags on some default tokens.
|
||||||
|
// This removes those line returns for comparison sake.
|
||||||
|
String.prototype.trimReturns = function(){
|
||||||
|
return this.replace(/\r?\n|\r/g, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Adding `.failing()` method to `describe` or `it` will make failing tests "pass" as long as they continue to fail.
|
||||||
|
// Remove the `.failing()` method once you have fixed the issue.
|
||||||
|
|
||||||
|
describe('Inline: When using the Inline syntax {{ }}', ()=>{
|
||||||
|
it.failing('Renders a mustache span with text only', function() {
|
||||||
|
const source = '{{ text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text only, but with spaces', function() {
|
||||||
|
const source = '{{ this is a text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block">this is a text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders an empty mustache span', function() {
|
||||||
|
const source = '{{}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block"></span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with just a space', function() {
|
||||||
|
const source = '{{ }}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block"></span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with a few spaces only', function() {
|
||||||
|
const source = '{{ }}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block"></span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text and class', function() {
|
||||||
|
const source = '{{my-class text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds two extra \s before closing `>` in opening tag.
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block my-class">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text and two classes', function() {
|
||||||
|
const source = '{{my-class,my-class2 text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds two extra \s before closing `>` in opening tag.
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block my-class my-class2">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text with spaces and class', function() {
|
||||||
|
const source = '{{my-class this is a text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds two extra \s before closing `>` in opening tag
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block my-class">this is a text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text and id', function() {
|
||||||
|
const source = '{{#my-span text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s before closing `>` in opening tag, and another after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" id="my-span">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text and two ids', function() {
|
||||||
|
const source = '{{#my-span,#my-favorite-span text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s before closing `>` in opening tag, and another after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" id="my-span">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text and css property', function() {
|
||||||
|
const source = '{{color:red text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="color:red;">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text and two css properties', function() {
|
||||||
|
const source = '{{color:red,padding:5px text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="color:red; padding:5px;">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text and css property which contains quotes', function() {
|
||||||
|
const source = '{{font-family:"trebuchet ms" text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="font-family:trebuchet ms;">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text and two css properties which contains quotes', function() {
|
||||||
|
const source = '{{font-family:"trebuchet ms",padding:"5px 10px" text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="font-family:trebuchet ms; padding:5px 10px;">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it.failing('Renders a mustache span with text with quotes and css property which contains quotes', function() {
|
||||||
|
const source = '{{font-family:"trebuchet ms" text "with quotes"}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="font-family:trebuchet ms;">text “with quotes”</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders a mustache span with text, id, class and a couple of css properties', function() {
|
||||||
|
const source = '{{pen,#author,color:orange,font-family:"trebuchet ms" text}}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block pen" id="author" style="color:orange; font-family:trebuchet ms;">text</span>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// BLOCK SYNTAX
|
||||||
|
|
||||||
|
describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
|
||||||
|
it.failing('Renders a div with text only', function() {
|
||||||
|
const source = dedent`{{
|
||||||
|
text
|
||||||
|
}}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block"><p>text</p></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders an empty div', function() {
|
||||||
|
const source = dedent`{{
|
||||||
|
|
||||||
|
}}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
// FIXME: adds extra \s after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block"></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders a single paragraph with opening and closing brackets', function() {
|
||||||
|
const source = dedent`{{
|
||||||
|
}}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
// this actually renders in HB as '{{ }}'...
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }, `Input:\n${source}`, { showPrefix: false }).toBe(`<p>{{}}</p>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a div with a single class', function() {
|
||||||
|
const source = dedent`{{cat
|
||||||
|
|
||||||
|
}}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
// FIXME: adds two extra \s before closing `>` in opening tag
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat"></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a div with a single class and text', function() {
|
||||||
|
const source = dedent`{{cat
|
||||||
|
Sample text.
|
||||||
|
}}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
// FIXME: adds two extra \s before closing `>` in opening tag
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat"><p>Sample text.</p></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a div with two classes and text', function() {
|
||||||
|
const source = dedent`{{cat,dog
|
||||||
|
Sample text.
|
||||||
|
}}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
// FIXME: adds two extra \s before closing `>` in opening tag
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat dog"><p>Sample text.</p></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a div with a style and text', function() {
|
||||||
|
const source = dedent`{{color:red
|
||||||
|
Sample text.
|
||||||
|
}}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
// FIXME: adds two extra \s before closing `>` in opening tag
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="color:red;"><p>Sample text.</p></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a div with a class, style and text', function() {
|
||||||
|
const source = dedent`{{cat,color:red
|
||||||
|
Sample text.
|
||||||
|
}}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
// FIXME: adds extra \s after the class attribute
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat" style="color:red;"><p>Sample text.</p></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders a div with an ID, class, style and text (different order)', function() {
|
||||||
|
const source = dedent`{{color:red,cat,#dog
|
||||||
|
Sample text.
|
||||||
|
}}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat" id="dog" style="color:red;"><p>Sample text.</p></div>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a div with a single ID', function() {
|
||||||
|
const source = dedent`{{#cat,#dog
|
||||||
|
Sample text.
|
||||||
|
}}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
// FIXME: adds extra \s before closing `>` in opening tag, and another after class names
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" id="cat"><p>Sample text.</p></div>`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// MUSTACHE INJECTION SYNTAX
|
||||||
|
|
||||||
|
describe('Injection: When an injection tag follows an element', ()=>{
|
||||||
|
// FIXME: Most of these fail because injections currently replace attributes, rather than append to. Or just minor extra whitespace issues.
|
||||||
|
describe('and that element is an inline-block', ()=>{
|
||||||
|
it.failing('Renders a span "text" with no injection', function() {
|
||||||
|
const source = '{{ text}}{}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a span "text" with injected Class name', function() {
|
||||||
|
const source = '{{ text}}{ClassName}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block ClassName">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a span "text" with injected style', function() {
|
||||||
|
const source = '{{ text}}{color:red}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="color:red;">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a span "text" with two injected styles', function() {
|
||||||
|
const source = '{{ text}}{color:red,background:blue}';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="color:red; background:blue;">text</span>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders an emphasis element with injected Class name', function() {
|
||||||
|
const source = '*emphasis*{big}';
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><em class="big">emphasis</em></p>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders a code element with injected style', function() {
|
||||||
|
const source = '`code`{background:gray}';
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><code style="background:gray;">code</code></p>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders an image element with injected style', function() {
|
||||||
|
const source = '{position:absolute}';
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><img src="http://i.imgur.com/hMna6G0.png" alt="homebrew mug" style="position:absolute;"></p>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('Renders an element modified by only the first of two consecutive injections', function() {
|
||||||
|
const source = '{{ text}}{color:red}{background:blue}';
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><span class="inline-block" style="color:red;">text</span>{background:blue}</p>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and that element is a block', ()=>{
|
||||||
|
it.failing('renders a div "text" with no injection', function() {
|
||||||
|
const source = '{{\ntext\n}}\n{}';
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block"><p>text</p></div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('renders a div "text" with injected Class name', function() {
|
||||||
|
const source = '{{\ntext\n}}\n{ClassName}';
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block ClassName"><p>text</p></div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('renders a div "text" with injected style', function() {
|
||||||
|
const source = '{{\ntext\n}}\n{color:red}';
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" style="color:red;"><p>text</p></div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('renders a div "text" with two injected styles', function() {
|
||||||
|
const source = dedent`{{
|
||||||
|
text
|
||||||
|
}}
|
||||||
|
{color:red,background:blue}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" style="color:red; background:blue;"><p>text</p></div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('renders an h2 header "text" with injected class name', function() {
|
||||||
|
const source = dedent`## text
|
||||||
|
{ClassName}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<h2 class="ClassName">text</h2>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('renders a table with injected class name', function() {
|
||||||
|
const source = dedent`| Experience Points | Level |
|
||||||
|
|:------------------|:-----:|
|
||||||
|
| 0 | 1 |
|
||||||
|
| 300 | 2 |
|
||||||
|
|
||||||
|
{ClassName}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<table class="ClassName"><thead><tr><th align=left>Experience Points</th><th align=center>Level</th></tr></thead><tbody><tr><td align=left>0</td><td align=center>1</td></tr><tr><td align=left>300</td><td align=center>2</td></tr></tbody></table>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// it('renders a list with with a style injected into the <ul> tag', function() {
|
||||||
|
// const source = dedent`- Cursed Ritual of Bad Hair
|
||||||
|
// - Eliminate Vindictiveness in Gym Teacher
|
||||||
|
// - Ultimate Rite of the Confetti Angel
|
||||||
|
// - Dark Chant of the Dentists
|
||||||
|
// - Divine Spell of Crossdressing
|
||||||
|
// {color:red}`;
|
||||||
|
// const rendered = Markdown.render(source).trimReturns();
|
||||||
|
// expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`...`); // FIXME: expect this to be injected into <ul>? Currently injects into last <li>
|
||||||
|
// });
|
||||||
|
|
||||||
|
it.failing('renders an h2 header "text" with injected class name, and "secondInjection" as regular text on the next line.', function() {
|
||||||
|
const source = dedent`## text
|
||||||
|
{ClassName}
|
||||||
|
{secondInjection}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<h2 class="ClassName">text</h2><p>{secondInjection}</p>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it.failing('renders a div nested into another div, the inner with class=innerDiv and the other class=outerDiv', function() {
|
||||||
|
const source = dedent`{{
|
||||||
|
outer text
|
||||||
|
{{
|
||||||
|
inner text
|
||||||
|
}}
|
||||||
|
{innerDiv}
|
||||||
|
}}
|
||||||
|
{outerDiv}`;
|
||||||
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block outerDiv"><p>outer text</p><div class="block innerDiv"><p>inner text</p></div></div>');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: add tests for ID with accordance to CSS spec:
|
||||||
|
//
|
||||||
|
// From https://drafts.csswg.org/selectors/#id-selectors:
|
||||||
|
//
|
||||||
|
// > An ID selector consists of a “number sign” (U+0023, #) immediately followed by the ID value, which must be a CSS identifier.
|
||||||
|
//
|
||||||
|
// From: https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier:
|
||||||
|
//
|
||||||
|
// > In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9]
|
||||||
|
// > and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_);
|
||||||
|
// > they cannot start with a digit, two hyphens, or a hyphen followed by a digit.
|
||||||
|
// > Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code (see next item).
|
||||||
|
// > For instance, the identifier "B&W?" may be written as "B\&W\?" or "B\26 W\3F".
|
||||||
|
// > Note that Unicode is code-by-code equivalent to ISO 10646 (see [UNICODE] and [ISO10646]).
|
||||||
|
|
||||||
|
// TODO: add tests for class with accordance to CSS spec:
|
||||||
|
//
|
||||||
|
// From: https://drafts.csswg.org/selectors/#class-html:
|
||||||
|
//
|
||||||
|
// > The class selector is given as a full stop (. U+002E) immediately followed by an identifier.
|
||||||
|
|
||||||
Reference in New Issue
Block a user