diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index 3a9de6288..1c44c57ca 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -754,7 +754,7 @@ 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-z]+="[^"]*)"/g) + 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("="); diff --git a/tests/markdown/mustache-syntax.test.js b/tests/markdown/mustache-syntax.test.js index c210167b6..8ca12519e 100644 --- a/tests/markdown/mustache-syntax.test.js +++ b/tests/markdown/mustache-syntax.test.js @@ -279,6 +279,36 @@ describe('Injection: When an injection tag follows an element', ()=>{ expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe('text'); }); + 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('text'); + }); + + 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('text'); + }); + + 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('text'); + }); + + 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('text'); + }); + + 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('text'); + }); + it('Renders an emphasis element with injected Class name', function() { const source = '*emphasis*{big}'; const rendered = Markdown.render(source).trimReturns(); @@ -340,13 +370,58 @@ describe('Injection: When an injection tag follows an element', ()=>{ 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(`

text

`); }); + 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('

text

'); + }); + + 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('

text

'); + }); + + 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('

text

'); + }); + + 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('

text

'); + }); + + 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('

text

'); + }); + it('renders an h2 header "text" with injected class name', function() { const source = dedent`## text {ClassName}`;