mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-06 16:32:40 +00:00
Merge branch 'master' into pr/3066
This commit is contained in:
@@ -180,7 +180,7 @@ const Editor = createClass({
|
|||||||
|
|
||||||
// Highlight injectors {style}
|
// Highlight injectors {style}
|
||||||
if(line.includes('{') && line.includes('}')){
|
if(line.includes('{') && line.includes('}')){
|
||||||
const regex = /(?:^|[^{\n])({(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\2})/gm;
|
const regex = /(?:^|[^{\n])({(?=((?:[:=](?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':={}\s]*)*))\2})/gm;
|
||||||
let match;
|
let match;
|
||||||
while ((match = regex.exec(line)) != null) {
|
while ((match = regex.exec(line)) != null) {
|
||||||
codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length }, { className: 'injection' });
|
codeMirror.markText({ line: lineNumber, ch: line.indexOf(match[1]) }, { line: lineNumber, ch: line.indexOf(match[1]) + match[1].length }, { className: 'injection' });
|
||||||
@@ -188,7 +188,7 @@ const Editor = createClass({
|
|||||||
}
|
}
|
||||||
// Highlight inline spans {{content}}
|
// Highlight inline spans {{content}}
|
||||||
if(line.includes('{{') && line.includes('}}')){
|
if(line.includes('{{') && line.includes('}}')){
|
||||||
const regex = /{{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *|}}/g;
|
const regex = /{{(?=((?:[:=](?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':={}\s]*)*))\1 *|}}/g;
|
||||||
let match;
|
let match;
|
||||||
let blockCount = 0;
|
let blockCount = 0;
|
||||||
while ((match = regex.exec(line)) != null) {
|
while ((match = regex.exec(line)) != null) {
|
||||||
@@ -207,7 +207,7 @@ const Editor = createClass({
|
|||||||
// Highlight block divs {{\n Content \n}}
|
// Highlight block divs {{\n Content \n}}
|
||||||
let endCh = line.length+1;
|
let endCh = line.length+1;
|
||||||
|
|
||||||
const match = line.match(/^ *{{(?=((?::(?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *$|^ *}}$/);
|
const match = line.match(/^ *{{(?=((?:[:=](?:"[\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':={}\s]*)*))\1 *$|^ *}}$/);
|
||||||
if(match)
|
if(match)
|
||||||
endCh = match.index+match[0].length;
|
endCh = match.index+match[0].length;
|
||||||
codeMirror.markText({ line: lineNumber, ch: 0 }, { line: lineNumber, ch: endCh }, { className: 'block' });
|
codeMirror.markText({ line: lineNumber, ch: 0 }, { line: lineNumber, ch: endCh }, { className: 'block' });
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const mustacheSpans = {
|
|||||||
start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match
|
start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match
|
||||||
tokenizer(src, tokens) {
|
tokenizer(src, tokens) {
|
||||||
const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token
|
const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token
|
||||||
const inlineRegex = /{{(?=((?::(?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *|}}/g;
|
const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g;
|
||||||
const match = completeSpan.exec(src);
|
const match = completeSpan.exec(src);
|
||||||
if(match) {
|
if(match) {
|
||||||
//Find closing delimiter
|
//Find closing delimiter
|
||||||
@@ -84,7 +84,7 @@ const mustacheDivs = {
|
|||||||
start(src) { return src.match(/\n *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match
|
start(src) { return src.match(/\n *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match
|
||||||
tokenizer(src, tokens) {
|
tokenizer(src, tokens) {
|
||||||
const completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token
|
const completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token
|
||||||
const blockRegex = /^ *{{(?=((?::(?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1 *$|^ *}}$/gm;
|
const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm;
|
||||||
const match = completeBlock.exec(src);
|
const match = completeBlock.exec(src);
|
||||||
if(match) {
|
if(match) {
|
||||||
//Find closing delimiter
|
//Find closing delimiter
|
||||||
@@ -132,7 +132,7 @@ const mustacheInjectInline = {
|
|||||||
level : 'inline',
|
level : 'inline',
|
||||||
start(src) { return src.match(/ *{[^{\n]/)?.index; }, // Hint to Marked.js to stop and check for a match
|
start(src) { return src.match(/ *{[^{\n]/)?.index; }, // Hint to Marked.js to stop and check for a match
|
||||||
tokenizer(src, tokens) {
|
tokenizer(src, tokens) {
|
||||||
const inlineRegex = /^ *{(?=((?::(?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1}/g;
|
const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g;
|
||||||
const match = inlineRegex.exec(src);
|
const match = inlineRegex.exec(src);
|
||||||
if(match) {
|
if(match) {
|
||||||
const lastToken = tokens[tokens.length - 1];
|
const lastToken = tokens[tokens.length - 1];
|
||||||
@@ -167,7 +167,7 @@ const mustacheInjectBlock = {
|
|||||||
level : 'block',
|
level : 'block',
|
||||||
start(src) { return src.match(/\n *{[^{\n]/m)?.index; }, // Hint to Marked.js to stop and check for a match
|
start(src) { return src.match(/\n *{[^{\n]/m)?.index; }, // Hint to Marked.js to stop and check for a match
|
||||||
tokenizer(src, tokens) {
|
tokenizer(src, tokens) {
|
||||||
const inlineRegex = /^ *{(?=((?::(?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"':{}\s]*)*))\1}/ym;
|
const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/ym;
|
||||||
const match = inlineRegex.exec(src);
|
const match = inlineRegex.exec(src);
|
||||||
if(match) {
|
if(match) {
|
||||||
const lastToken = tokens[tokens.length - 1];
|
const lastToken = tokens[tokens.length - 1];
|
||||||
@@ -354,16 +354,19 @@ const voidTags = new Set([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const processStyleTags = (string)=>{
|
const processStyleTags = (string)=>{
|
||||||
//split tags up. quotes can only occur right after colons.
|
//split tags up. quotes can only occur right after : or =.
|
||||||
//TODO: can we simplify to just split on commas?
|
//TODO: can we simplify to just split on commas?
|
||||||
const tags = string.match(/(?:[^, ":]+|:(?:"[^"]*"|))+/g);
|
const tags = string.match(/(?:[^, ":=]+|[:=](?:"[^"]*"|))+/g);
|
||||||
|
|
||||||
if(!tags) return '"';
|
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];
|
return `${classes?.length ? ` ${classes.join(' ')}` : ''}"` +
|
||||||
const classes = _.remove(tags, (tag)=>!tag.includes(':'));
|
`${id ? ` id="${id}"` : ''}` +
|
||||||
const styles = tags.map((tag)=>tag.replace(/:"?([^"]*)"?/g, ':$1;'));
|
`${styles?.length ? ` style="${styles.join(' ')}"` : ''}` +
|
||||||
return `${classes.length ? ` ${classes.join(' ')}` : ''}"${id ? ` id="${id}"` : ''}${styles.length ? ` style="${styles.join(' ')}"` : ''}`;
|
`${attributes?.length ? ` ${attributes.join(' ')}` : ''}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
@@ -117,6 +117,12 @@ describe('Inline: When using the Inline syntax {{ }}', ()=>{
|
|||||||
const rendered = Markdown.render(source);
|
const rendered = Markdown.render(source);
|
||||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block pen" id="author" style="color:orange; font-family:trebuchet ms;">text</span>');
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block pen" id="author" style="color:orange; font-family:trebuchet ms;">text</span>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Renders a span with added attributes', function() {
|
||||||
|
const source = 'Text and {{pen,#author,color:orange,font-family:"trebuchet ms",a="b and c",d=e, text}} and more text!';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p>Text and <span class="inline-block pen" id="author" style="color:orange; font-family:trebuchet ms;" a="b and c" d="e">text</span> and more text!</p>\n');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// BLOCK SYNTAX
|
// BLOCK SYNTAX
|
||||||
@@ -216,6 +222,20 @@ describe(`Block: When using the Block syntax {{tags\\ntext\\n}}`, ()=>{
|
|||||||
const rendered = Markdown.render(source).trimReturns();
|
const rendered = Markdown.render(source).trimReturns();
|
||||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<div class="block" id="cat"><p>Sample text.</p></div>`);
|
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.
|
||||||
|
}}`;
|
||||||
|
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>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders a div with added attributes', function() {
|
||||||
|
const source = '{{pen,#author,color:orange,font-family:"trebuchet ms",a="b and c",d=e\nText and text and more text!\n}}\n';
|
||||||
|
const rendered = Markdown.render(source);
|
||||||
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<div class="block pen" id="author" style="color:orange; font-family:trebuchet ms;" a="b and c" d="e"><p>Text and text and more text!</p>\n</div>');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// MUSTACHE INJECTION SYNTAX
|
// MUSTACHE INJECTION SYNTAX
|
||||||
@@ -235,6 +255,12 @@ describe('Injection: When an injection tag follows an element', ()=>{
|
|||||||
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<span class="inline-block ClassName">text</span>');
|
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() {
|
||||||
|
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>');
|
||||||
|
});
|
||||||
|
|
||||||
it.failing('Renders a span "text" with injected style', function() {
|
it.failing('Renders a span "text" with injected style', function() {
|
||||||
const source = '{{ text}}{color:red}';
|
const source = '{{ text}}{color:red}';
|
||||||
const rendered = Markdown.render(source);
|
const rendered = Markdown.render(source);
|
||||||
@@ -276,6 +302,12 @@ describe('Injection: When an injection tag follows an element', ()=>{
|
|||||||
const rendered = Markdown.render(source).trimReturns();
|
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>');
|
expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('<p><span class="inline-block" style="color:red;">text</span>{background:blue}</p>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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>`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('and that element is a block', ()=>{
|
describe('and that element is a block', ()=>{
|
||||||
|
|||||||
Reference in New Issue
Block a user