mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2025-12-24 20:42:43 +00:00
Merge branch 'master' into dependabot/npm_and_yarn/superagent-9.0.2
This commit is contained in:
18
package-lock.json
generated
18
package-lock.json
generated
@@ -14,7 +14,7 @@
|
||||
"@babel/plugin-transform-runtime": "^7.24.3",
|
||||
"@babel/preset-env": "^7.24.5",
|
||||
"@babel/preset-react": "^7.24.1",
|
||||
"@googleapis/drive": "^8.7.0",
|
||||
"@googleapis/drive": "^8.8.0",
|
||||
"body-parser": "^1.20.2",
|
||||
"classnames": "^2.5.1",
|
||||
"codemirror": "^5.65.6",
|
||||
@@ -49,7 +49,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-jest": "^28.2.0",
|
||||
"eslint-plugin-jest": "^28.5.0",
|
||||
"eslint-plugin-react": "^7.34.1",
|
||||
"jest": "^29.7.0",
|
||||
"jest-expect-message": "^1.1.3",
|
||||
@@ -1983,9 +1983,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@googleapis/drive": {
|
||||
"version": "8.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.7.0.tgz",
|
||||
"integrity": "sha512-XAi6kfySIU4H3ivX2DpzTDce5UhNke5NxEWCL6tySEdcVqx+cmXJmkMqwfOAHJalEB5s9PPfdLBU29Xd5XlLSQ==",
|
||||
"version": "8.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@googleapis/drive/-/drive-8.8.0.tgz",
|
||||
"integrity": "sha512-EOZ9GZCOUdej9PJVnkai7qu5RPyFLYse8FlpgijzfnZPOACXWFf4XOFuAuMcMw4Zue8xPhAPHu1qYcy8u362Xw==",
|
||||
"dependencies": {
|
||||
"googleapis-common": "^7.0.0"
|
||||
},
|
||||
@@ -5748,12 +5748,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jest": {
|
||||
"version": "28.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.2.0.tgz",
|
||||
"integrity": "sha512-yRDti/a+f+SMSmNTiT9/M/MzXGkitl8CfzUxnpoQcTyfq8gUrXMriVcWU36W1X6BZSUoyUCJrDAWWUA2N4hE5g==",
|
||||
"version": "28.5.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.5.0.tgz",
|
||||
"integrity": "sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/utils": "^6.0.0"
|
||||
"@typescript-eslint/utils": "^6.0.0 || ^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.10.0 || ^18.12.0 || >=20.0.0"
|
||||
|
||||
12
package.json
12
package.json
@@ -27,10 +27,10 @@
|
||||
"test:dev": "jest --verbose --watch",
|
||||
"test:basic": "jest tests/markdown/basic.test.js --verbose",
|
||||
"test:variables": "jest tests/markdown/variables.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: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:definition-lists": "jest tests/markdown/definition-lists.test.js --verbose --noStackTrace",
|
||||
"test:route": "jest tests/routes/static-pages.test.js --verbose",
|
||||
"phb": "node scripts/phb.js",
|
||||
@@ -85,7 +85,7 @@
|
||||
"@babel/plugin-transform-runtime": "^7.24.3",
|
||||
"@babel/preset-env": "^7.24.5",
|
||||
"@babel/preset-react": "^7.24.1",
|
||||
"@googleapis/drive": "^8.7.0",
|
||||
"@googleapis/drive": "^8.8.0",
|
||||
"body-parser": "^1.20.2",
|
||||
"classnames": "^2.5.1",
|
||||
"codemirror": "^5.65.6",
|
||||
@@ -120,7 +120,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-jest": "^28.2.0",
|
||||
"eslint-plugin-jest": "^28.5.0",
|
||||
"eslint-plugin-react": "^7.34.1",
|
||||
"jest": "^29.7.0",
|
||||
"jest-expect-message": "^1.1.3",
|
||||
|
||||
@@ -50,7 +50,7 @@ renderer.html = function (html) {
|
||||
return html;
|
||||
};
|
||||
|
||||
// Don't wrap {{ Divs or {{ empty Spans in <p> tags
|
||||
// Don't wrap {{ Spans alone on a line, or {{ Divs in <p> tags
|
||||
renderer.paragraph = function(text){
|
||||
let match;
|
||||
if(text.startsWith('<div') || text.startsWith('</div'))
|
||||
@@ -99,13 +99,13 @@ const mustacheSpans = {
|
||||
if(match) {
|
||||
//Find closing delimiter
|
||||
let blockCount = 0;
|
||||
let tags = '';
|
||||
let tags = {};
|
||||
let endTags = 0;
|
||||
let endToken = 0;
|
||||
let delim;
|
||||
while (delim = inlineRegex.exec(match[0])) {
|
||||
if(!tags) {
|
||||
tags = `${processStyleTags(delim[0].substring(2))}`;
|
||||
if(_.isEmpty(tags)) {
|
||||
tags = processStyleTags(delim[0].substring(2));
|
||||
endTags = delim[0].length;
|
||||
}
|
||||
if(delim[0].startsWith('{{')) {
|
||||
@@ -134,7 +134,14 @@ const mustacheSpans = {
|
||||
}
|
||||
},
|
||||
renderer(token) {
|
||||
return `<span class="inline-block${token.tags}>${this.parser.parseInline(token.tokens)}</span>`; // parseInline to turn child tokens into HTML
|
||||
const tags = token.tags;
|
||||
tags.classes = ['inline-block', tags.classes].join(' ').trim();
|
||||
return `<span` +
|
||||
`${tags.classes ? ` class="${tags.classes}"` : ''}` +
|
||||
`${tags.id ? ` id="${tags.id}"` : ''}` +
|
||||
`${tags.styles ? ` style="${tags.styles}"` : ''}` +
|
||||
`${tags.attributes ? ` ${Object.entries(tags.attributes).map(([key, value]) => `${key}="${value}"`).join(' ')}` : ''}` +
|
||||
`>${this.parser.parseInline(token.tokens)}</span>`; // parseInline to turn child tokens into HTML
|
||||
}
|
||||
};
|
||||
|
||||
@@ -149,13 +156,13 @@ const mustacheDivs = {
|
||||
if(match) {
|
||||
//Find closing delimiter
|
||||
let blockCount = 0;
|
||||
let tags = '';
|
||||
let tags = {};
|
||||
let endTags = 0;
|
||||
let endToken = 0;
|
||||
let delim;
|
||||
while (delim = blockRegex.exec(match[0])?.[0].trim()) {
|
||||
if(!tags) {
|
||||
tags = `${processStyleTags(delim.substring(2))}`;
|
||||
if(_.isEmpty(tags)) {
|
||||
tags = processStyleTags(delim.substring(2));
|
||||
endTags = delim.length + src.indexOf(delim);
|
||||
}
|
||||
if(delim.startsWith('{{')) {
|
||||
@@ -183,7 +190,14 @@ const mustacheDivs = {
|
||||
}
|
||||
},
|
||||
renderer(token) {
|
||||
return `<div class="block${token.tags}>${this.parser.parse(token.tokens)}</div>`; // parseInline to turn child tokens into HTML
|
||||
const tags = token.tags;
|
||||
tags.classes = ['block', tags.classes].join(' ').trim();
|
||||
return `<div` +
|
||||
`${tags.classes ? ` class="${tags.classes}"` : ''}` +
|
||||
`${tags.id ? ` id="${tags.id}"` : ''}` +
|
||||
`${tags.styles ? ` style="${tags.styles}"` : ''}` +
|
||||
`${tags.attributes ? ` ${Object.entries(tags.attributes).map(([key, value]) => `${key}="${value}"`).join(' ')}` : ''}` +
|
||||
`>${this.parser.parse(token.tokens)}</div>`; // parse to turn child tokens into HTML
|
||||
}
|
||||
};
|
||||
|
||||
@@ -199,23 +213,39 @@ const mustacheInjectInline = {
|
||||
if(!lastToken || lastToken.type == 'mustacheInjectInline')
|
||||
return false;
|
||||
|
||||
const tags = `${processStyleTags(match[1])}`;
|
||||
const tags = processStyleTags(match[1]);
|
||||
lastToken.originalType = lastToken.type;
|
||||
lastToken.type = 'mustacheInjectInline';
|
||||
lastToken.tags = tags;
|
||||
lastToken.injectedTags = tags;
|
||||
return {
|
||||
type : 'text', // Should match "name" above
|
||||
type : 'mustacheInjectInline', // Should match "name" above
|
||||
raw : match[0], // Text to consume from the source
|
||||
text : ''
|
||||
};
|
||||
}
|
||||
},
|
||||
renderer(token) {
|
||||
if(!token.originalType){
|
||||
return;
|
||||
}
|
||||
token.type = token.originalType;
|
||||
const text = this.parser.parseInline([token]);
|
||||
const openingTag = /(<[^\s<>]+)([^\n<>]*>.*)/s.exec(text);
|
||||
const originalTags = extractHTMLStyleTags(text);
|
||||
const injectedTags = token.injectedTags;
|
||||
const tags = {
|
||||
id : injectedTags.id || originalTags.id || null,
|
||||
classes : [originalTags.classes, injectedTags.classes].join(' ').trim() || null,
|
||||
styles : [originalTags.styles, injectedTags.styles].join(' ').trim() || null,
|
||||
attributes : Object.assign(originalTags.attributes ?? {}, injectedTags.attributes ?? {})
|
||||
};
|
||||
const openingTag = /(<[^\s<>]+)[^\n<>]*(>.*)/s.exec(text);
|
||||
if(openingTag) {
|
||||
return `${openingTag[1]} class="${token.tags}${openingTag[2]}`;
|
||||
return `${openingTag[1]}` +
|
||||
`${tags.classes ? ` class="${tags.classes}"` : ''}` +
|
||||
`${tags.id ? ` id="${tags.id}"` : ''}` +
|
||||
`${tags.styles ? ` style="${tags.styles}"` : ''}` +
|
||||
`${!_.isEmpty(tags.attributes) ? ` ${Object.entries(tags.attributes).map(([key, value]) => `${key}="${value}"`).join(' ')}` : ''}` +
|
||||
`${openingTag[2]}`; // parse to turn child tokens into HTML
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@@ -235,7 +265,7 @@ const mustacheInjectBlock = {
|
||||
return false;
|
||||
|
||||
lastToken.originalType = 'mustacheInjectBlock';
|
||||
lastToken.tags = `${processStyleTags(match[1])}`;
|
||||
lastToken.injectedTags = processStyleTags(match[1]);
|
||||
return {
|
||||
type : 'mustacheInjectBlock', // Should match "name" above
|
||||
raw : match[0], // Text to consume from the source
|
||||
@@ -249,9 +279,22 @@ const mustacheInjectBlock = {
|
||||
}
|
||||
token.type = token.originalType;
|
||||
const text = this.parser.parse([token]);
|
||||
const openingTag = /(<[^\s<>]+)([^\n<>]*>.*)/s.exec(text);
|
||||
const originalTags = extractHTMLStyleTags(text);
|
||||
const injectedTags = token.injectedTags;
|
||||
const tags = {
|
||||
id : injectedTags.id || originalTags.id || null,
|
||||
classes : [originalTags.classes, injectedTags.classes].join(' ').trim() || null,
|
||||
styles : [originalTags.styles, injectedTags.styles].join(' ').trim() || null,
|
||||
attributes : Object.assign(originalTags.attributes ?? {}, injectedTags.attributes ?? {})
|
||||
};
|
||||
const openingTag = /(<[^\s<>]+)[^\n<>]*(>.*)/s.exec(text);
|
||||
if(openingTag) {
|
||||
return `${openingTag[1]} class="${token.tags}${openingTag[2]}`;
|
||||
return `${openingTag[1]}` +
|
||||
`${tags.classes ? ` class="${tags.classes}"` : ''}` +
|
||||
`${tags.id ? ` id="${tags.id}"` : ''}` +
|
||||
`${tags.styles ? ` style="${tags.styles}"` : ''}` +
|
||||
`${!_.isEmpty(tags.attributes) ? ` ${Object.entries(tags.attributes).map(([key, value]) => `${key}="${value}"`).join(' ')}` : ''}` +
|
||||
`${openingTag[2]}`; // parse to turn child tokens into HTML
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@@ -687,15 +730,45 @@ const processStyleTags = (string)=>{
|
||||
//TODO: can we simplify to just split on commas?
|
||||
const tags = string.match(/(?:[^, ":=]+|[:=](?:"[^"]*"|))+/g);
|
||||
|
||||
const id = _.remove(tags, (tag)=>tag.startsWith('#')).map((tag)=>tag.slice(1))[0];
|
||||
const classes = _.remove(tags, (tag)=>(!tag.includes(':')) && (!tag.includes('=')));
|
||||
const attributes = _.remove(tags, (tag)=>(tag.includes('='))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"'));
|
||||
const styles = tags?.length ? tags.map((tag)=>tag.replace(/:"?([^"]*)"?/g, ':$1;').trim()) : [];
|
||||
const id = _.remove(tags, (tag)=>tag.startsWith('#')).map((tag)=>tag.slice(1))[0] || null;
|
||||
const classes = _.remove(tags, (tag)=>(!tag.includes(':')) && (!tag.includes('='))).join(' ') || null;
|
||||
const attributes = _.remove(tags, (tag)=>(tag.includes('='))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"'))
|
||||
?.filter(attr => !attr.startsWith('class="') && !attr.startsWith('style="') && !attr.startsWith('id="'))
|
||||
.reduce((obj, attr) => {
|
||||
let [key, value] = attr.split("=");
|
||||
value = value.replace(/"/g, '');
|
||||
obj[key] = value;
|
||||
return obj;
|
||||
}, {}) || null;
|
||||
const styles = tags?.length ? tags.map((tag)=>tag.replace(/:"?([^"]*)"?/g, ':$1;').trim()).join(' ') : null;
|
||||
|
||||
return `${classes?.length ? ` ${classes.join(' ')}` : ''}"` +
|
||||
`${id ? ` id="${id}"` : ''}` +
|
||||
`${styles?.length ? ` style="${styles.join(' ')}"` : ''}` +
|
||||
`${attributes?.length ? ` ${attributes.join(' ')}` : ''}`;
|
||||
return {
|
||||
id : id,
|
||||
classes : classes,
|
||||
styles : styles,
|
||||
attributes : _.isEmpty(attributes) ? null : attributes
|
||||
};
|
||||
};
|
||||
|
||||
const extractHTMLStyleTags = (htmlString)=> {
|
||||
const id = htmlString.match(/id="([^"]*)"/)?.[1] || null;
|
||||
const classes = htmlString.match(/class="([^"]*)"/)?.[1] || null;
|
||||
const styles = htmlString.match(/style="([^"]*)"/)?.[1] || null;
|
||||
const attributes = htmlString.match(/[a-zA-Z]+="[^"]*"/g)
|
||||
?.filter(attr => !attr.startsWith('class="') && !attr.startsWith('style="') && !attr.startsWith('id="'))
|
||||
.reduce((obj, attr) => {
|
||||
let [key, value] = attr.split("=");
|
||||
value = value.replace(/"/g, '');
|
||||
obj[key] = value;
|
||||
return obj;
|
||||
}, {}) || null;
|
||||
|
||||
return {
|
||||
id : id,
|
||||
classes : classes,
|
||||
styles : styles,
|
||||
attributes : _.isEmpty(attributes) ? null : attributes
|
||||
};
|
||||
};
|
||||
|
||||
const globalVarsList = {};
|
||||
|
||||
@@ -130,8 +130,8 @@ describe('Inline: When using the Inline syntax {{ }}', ()=>{
|
||||
describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
|
||||
it('Renders a div with text only', function() {
|
||||
const source = dedent`{{
|
||||
text
|
||||
}}`;
|
||||
text
|
||||
}}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block"><p>text</p></div>`);
|
||||
});
|
||||
@@ -139,14 +139,14 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
|
||||
it('Renders an empty div', function() {
|
||||
const source = dedent`{{
|
||||
|
||||
}}`;
|
||||
}}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `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();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p>{{}}</p>`);
|
||||
});
|
||||
@@ -154,79 +154,79 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
|
||||
it('Renders a div with a single class', function() {
|
||||
const source = dedent`{{cat
|
||||
|
||||
}}`;
|
||||
}}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat"></div>`);
|
||||
});
|
||||
|
||||
it('Renders a div with a single class and text', function() {
|
||||
const source = dedent`{{cat
|
||||
Sample text.
|
||||
}}`;
|
||||
Sample text.
|
||||
}}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat"><p>Sample text.</p></div>`);
|
||||
});
|
||||
|
||||
it('Renders a div with two classes and text', function() {
|
||||
const source = dedent`{{cat,dog
|
||||
Sample text.
|
||||
}}`;
|
||||
Sample text.
|
||||
}}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block cat dog"><p>Sample text.</p></div>`);
|
||||
});
|
||||
|
||||
it('Renders a div with a style and text', function() {
|
||||
const source = dedent`{{color:red
|
||||
Sample text.
|
||||
}}`;
|
||||
Sample text.
|
||||
}}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="color:red;"><p>Sample text.</p></div>`);
|
||||
});
|
||||
|
||||
it('Renders a div with a style that has a string variable, and text', function() {
|
||||
const source = dedent`{{--stringVariable:"'string'"
|
||||
Sample text.
|
||||
}}`;
|
||||
Sample text.
|
||||
}}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="--stringVariable:'string';"><p>Sample text.</p></div>`);
|
||||
});
|
||||
|
||||
it('Renders a div with a style that has a string variable, and text', function() {
|
||||
const source = dedent`{{--stringVariable:"'string'"
|
||||
Sample text.
|
||||
}}`;
|
||||
Sample text.
|
||||
}}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="--stringVariable:'string';"><p>Sample text.</p></div>`);
|
||||
});
|
||||
|
||||
it('Renders a div with a class, style and text', function() {
|
||||
const source = dedent`{{cat,color:red
|
||||
Sample text.
|
||||
}}`;
|
||||
Sample text.
|
||||
}}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
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.
|
||||
}}`;
|
||||
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('Renders a div with a single ID', function() {
|
||||
const source = dedent`{{#cat,#dog
|
||||
Sample text.
|
||||
}}`;
|
||||
Sample text.
|
||||
}}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" id="cat"><p>Sample text.</p></div>`);
|
||||
});
|
||||
|
||||
it('Renders a div with an ID, class, style and text, and a variable assignment', function() {
|
||||
const source = dedent`{{color:red,cat,#dog,a="b and c",d="e"
|
||||
Sample text.
|
||||
}}`;
|
||||
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;\" a=\"b and c\" d=\"e\"><p>Sample text.</p></div>`);
|
||||
});
|
||||
@@ -243,61 +243,91 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
|
||||
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() {
|
||||
it('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() {
|
||||
it('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 attribute', function() {
|
||||
it('Renders a span "text" with injected attribute', function() {
|
||||
const source = '{{ text}}{a="b and c"}';
|
||||
const rendered = Markdown.render(source);
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span a="b and c" class="inline-block ">text</span>');
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" a="b and c">text</span>');
|
||||
});
|
||||
|
||||
it.failing('Renders a span "text" with injected style', function() {
|
||||
it('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 injected style using a string variable', function() {
|
||||
it('Renders a span "text" with injected style using a string variable', function() {
|
||||
const source = `{{ text}}{--stringVariable:"'string'"}`;
|
||||
const rendered = Markdown.render(source);
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<span class="inline-block" style="--stringVariable:'string';">text</span>`);
|
||||
});
|
||||
|
||||
it.failing('Renders a span "text" with two injected styles', function() {
|
||||
it('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() {
|
||||
it('Renders a span "text" with its own ID, overwritten with an injected ID', function() {
|
||||
const source = '{{#oldId text}}{#newId}';
|
||||
const rendered = Markdown.render(source);
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" id="newId">text</span>');
|
||||
});
|
||||
|
||||
it('Renders a span "text" with its own attributes, overwritten with an injected attribute, plus a new one', function() {
|
||||
const source = '{{attrA="old",attrB="old" text}}{attrA="new",attrC="new"}';
|
||||
const rendered = Markdown.render(source);
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" attrA="new" attrB="old" attrC="new">text</span>');
|
||||
});
|
||||
|
||||
it('Renders a span "text" with its own attributes, overwritten with an injected attribute, ignoring "class", "style", and "id"', function() {
|
||||
const source = '{{attrA="old",attrB="old" text}}{attrA="new",attrC="new",class="new",style="new",id="new"}';
|
||||
const rendered = Markdown.render(source);
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" attrA="new" attrB="old" attrC="new">text</span>');
|
||||
});
|
||||
|
||||
it('Renders a span "text" with its own styles, appended with injected styles', function() {
|
||||
const source = '{{color:blue,height:10px text}}{width:10px,color:red}';
|
||||
const rendered = Markdown.render(source);
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block" style="color:blue; height:10px; width:10px; color:red;">text</span>');
|
||||
});
|
||||
|
||||
it('Renders a span "text" with its own classes, appended with injected classes', function() {
|
||||
const source = '{{classA,classB text}}{classA,classC}';
|
||||
const rendered = Markdown.render(source);
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block classA classB classA classC">text</span>');
|
||||
});
|
||||
|
||||
it('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() {
|
||||
it('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() {
|
||||
it('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>');
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><img style="position:absolute;" src="http://i.imgur.com/hMna6G0.png" alt="alt text"></p>');
|
||||
});
|
||||
|
||||
it.failing('Renders an element modified by only the first of two consecutive injections', function() {
|
||||
it('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>');
|
||||
@@ -306,61 +336,106 @@ describe('Injection: When an injection tag follows an element', ()=>{
|
||||
it('Renders an image with added attributes', function() {
|
||||
const source = ` {position:absolute,bottom:20px,left:130px,width:220px,a="b and c",d=e}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><img class="" style="position:absolute; bottom:20px; left:130px; width:220px;" a="b and c" d="e" src="https://i.imgur.com/hMna6G0.png" alt="homebrew mug"></p>`);
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p><img style="position:absolute; bottom:20px; left:130px; width:220px;" src="https://i.imgur.com/hMna6G0.png" alt="homebrew mug" a="b and c" d="e"></p>`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and that element is a block', ()=>{
|
||||
it.failing('renders a div "text" with no injection', function() {
|
||||
it('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() {
|
||||
it('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() {
|
||||
it('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() {
|
||||
it('renders a div "text" with two injected styles', function() {
|
||||
const source = dedent`{{
|
||||
text
|
||||
}}
|
||||
{color:red,background:blue}`;
|
||||
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>`);
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="color:red; background:blue;"><p>text</p></div>`);
|
||||
});
|
||||
|
||||
it.failing('renders a div "text" with injected variable string', function() {
|
||||
it('renders a div "text" with injected variable string', function() {
|
||||
const source = dedent`{{
|
||||
text
|
||||
}}
|
||||
{--stringVariable:"'string'"}`;
|
||||
text
|
||||
}}
|
||||
{--stringVariable:"'string'"}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="--stringVariable:'string'"><p>text</p></div>`);
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" style="--stringVariable:'string';"><p>text</p></div>`);
|
||||
});
|
||||
|
||||
it.failing('renders an h2 header "text" with injected class name', function() {
|
||||
it('Renders a span "text" with its own ID, overwritten with an injected ID', function() {
|
||||
const source = dedent`{{#oldId
|
||||
text
|
||||
}}
|
||||
{#newId}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" id="newId"><p>text</p></div>');
|
||||
});
|
||||
|
||||
it('Renders a span "text" with its own attributes, overwritten with an injected attribute, plus a new one', function() {
|
||||
const source = dedent`{{attrA="old",attrB="old"
|
||||
text
|
||||
}}
|
||||
{attrA="new",attrC="new"}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" attrA="new" attrB="old" attrC="new"><p>text</p></div>');
|
||||
});
|
||||
|
||||
it('Renders a span "text" with its own attributes, overwritten with an injected attribute, ignoring "class", "style", and "id"', function() {
|
||||
const source = dedent`{{attrA="old",attrB="old"
|
||||
text
|
||||
}}
|
||||
{attrA="new",attrC="new",class="new",style="new",id="new"}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" attrA="new" attrB="old" attrC="new"><p>text</p></div>');
|
||||
});
|
||||
|
||||
it('Renders a span "text" with its own styles, appended with injected styles', function() {
|
||||
const source = dedent`{{color:blue,height:10px
|
||||
text
|
||||
}}
|
||||
{width:10px,color:red}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block" style="color:blue; height:10px; width:10px; color:red;"><p>text</p></div>');
|
||||
});
|
||||
|
||||
it('Renders a span "text" with its own classes, appended with injected classes', function() {
|
||||
const source = dedent`{{classA,classB
|
||||
text
|
||||
}}
|
||||
{classA,classC}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block classA classB classA classC"><p>text</p></div>');
|
||||
});
|
||||
|
||||
it('renders an h2 header "text" with injected class name', function() {
|
||||
const source = dedent`## text
|
||||
{ClassName}`;
|
||||
{ClassName}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<h2 class="ClassName">text</h2>');
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<h2 class="ClassName" id="text">text</h2>');
|
||||
});
|
||||
|
||||
it.failing('renders a table with injected class name', function() {
|
||||
it('renders a table with injected class name', function() {
|
||||
const source = dedent`| Experience Points | Level |
|
||||
|:------------------|:-----:|
|
||||
| 0 | 1 |
|
||||
| 300 | 2 |
|
||||
|:------------------|:-----:|
|
||||
| 0 | 1 |
|
||||
| 300 | 2 |
|
||||
|
||||
{ClassName}`;
|
||||
{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>`);
|
||||
});
|
||||
@@ -376,23 +451,23 @@ describe('Injection: When an injection tag follows an element', ()=>{
|
||||
// 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() {
|
||||
it('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>');
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<h2 class="ClassName" id="text">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() {
|
||||
it('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}`;
|
||||
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>');
|
||||
});
|
||||
|
||||
@@ -329,7 +329,7 @@ describe('Normal Links and Images', ()=>{
|
||||
const source = `{width:100px}`;
|
||||
const rendered = Markdown.render(source).trimReturns();
|
||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(dedent`
|
||||
<p><img class="" style="width:100px;" src="url" alt="alt text"></p>`.trimReturns());
|
||||
<p><img style="width:100px;" src="url" alt="alt text"></p>`.trimReturns());
|
||||
});
|
||||
|
||||
it('Renders normal links', function() {
|
||||
|
||||
@@ -543,10 +543,8 @@
|
||||
color : white;
|
||||
text-shadow : unset;
|
||||
text-transform : uppercase;
|
||||
filter : drop-shadow(0 0 1.5px black) drop-shadow(0 0 0 black)
|
||||
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
|
||||
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
|
||||
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black);
|
||||
-webkit-text-stroke: 0.2cm black;
|
||||
paint-order:stroke;
|
||||
}
|
||||
h2 {
|
||||
font-family : 'NodestoCapsCondensed';
|
||||
@@ -554,10 +552,8 @@
|
||||
font-weight : normal;
|
||||
color : white;
|
||||
letter-spacing : 0.1cm;
|
||||
filter : drop-shadow(0 0 1px black) drop-shadow(0 0 0 black)
|
||||
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
|
||||
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
|
||||
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black);
|
||||
-webkit-text-stroke: 0.14cm black;
|
||||
paint-order:stroke;
|
||||
}
|
||||
hr {
|
||||
position : relative;
|
||||
@@ -603,10 +599,8 @@
|
||||
font-size : 0.496cm;
|
||||
color : white;
|
||||
text-align : center;
|
||||
filter : drop-shadow(0 0 0.7px black) drop-shadow(0 0 0 black)
|
||||
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
|
||||
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black)
|
||||
drop-shadow(0 0 0 black) drop-shadow(0 0 0 black);
|
||||
-webkit-text-stroke: 0.1cm black;
|
||||
paint-order:stroke;
|
||||
}
|
||||
.logo {
|
||||
position : absolute;
|
||||
|
||||
Reference in New Issue
Block a user