diff --git a/docs/_markbind/variables.md b/docs/_markbind/variables.md index 2dfa5f3779..8e18f53a0c 100644 --- a/docs/_markbind/variables.md +++ b/docs/_markbind/variables.md @@ -1,9 +1,3 @@ - -{{ baseUrl }} - - -{{ baseUrl }} - #00B0F0 :fas-arrow-down: diff --git a/docs/userGuide/markBindSyntaxOverview.md b/docs/userGuide/markBindSyntaxOverview.md index 91049262b7..6f390a4f86 100644 --- a/docs/userGuide/markBindSyntaxOverview.md +++ b/docs/userGuide/markBindSyntaxOverview.md @@ -99,13 +99,15 @@ As MarkBind uses [VueStrap](https://bootstrap-vue.js.org/docs/components/alert/) [Nunjucks](https://mozilla.github.io/nunjucks/) is a JavaScript based templating tool. Here is a simple example: - -`` - +{% raw %} +```html { .no-line-numbers } + +``` +{% endraw %} {{ icon_arrow_down }} diff --git a/docs/userGuide/syntax/icons.mbdf b/docs/userGuide/syntax/icons.mbdf index a5f7345d1b..16f663cdbd 100644 --- a/docs/userGuide/syntax/icons.mbdf +++ b/docs/userGuide/syntax/icons.mbdf @@ -13,8 +13,9 @@ The advantage of font icons over emojis is font icons can be _styled_ to fit you -The syntax for icons has changed, and the earlier {{ prefix_name }} syntax has been deprecated.
-Please use the new :prefix-name: syntax instead. + +The syntax for icons has changed, and the earlier {%raw%}`{{ prefix_name }}`{%endraw%} syntax has been deprecated.
+Please use the new `:prefix-name:` syntax instead.
###### Using Font Awesome Icons diff --git a/docs/userGuide/syntax/includes.mbdf b/docs/userGuide/syntax/includes.mbdf index 57d83f366d..19eacaa690 100644 --- a/docs/userGuide/syntax/includes.mbdf +++ b/docs/userGuide/syntax/includes.mbdf @@ -130,10 +130,12 @@ In other words, **`` interprets the reused code relative to the origina In `article.md`: - -# {{ title }}
-Author: {{ author }} -
+{% raw %} +```html +# {{ title }}
+Author: {{ author }} +``` +{% endraw %} These variables work the same way as variables in `_markbind/variables.md`, except that they only apply to the included file. They allow the included file to be reused as a template, for different source files using different variable values. diff --git a/docs/userGuide/syntax/links.mbdf b/docs/userGuide/syntax/links.mbdf index 69eff564c0..fc4dfb7275 100644 --- a/docs/userGuide/syntax/links.mbdf +++ b/docs/userGuide/syntax/links.mbdf @@ -32,16 +32,19 @@ Links to files of the generated site (e.g., an HTML page or an image file) can b Absolute paths:
-Links should start with {{ showBaseUrlCode }} (which represents the root directory of the project). -{{ icon_example }} Here's how to specify a link to (1) a page, and (2) an image, using the {{ showBaseUrlCode }}: +Links should start with {% raw %}`{{ baseUrl }}`{% endraw %} (which represents the root directory of the project). -1. Click [here]({{ showBaseUrlCode }}/userGuide/reusingContents.html). -2. `![](`{{ showBaseUrlCode }}`/images/preview.png)` +{{ icon_example }} Here's how to specify a link to (1) a page, and (2) an image, using the {% raw %}`{{ baseUrl }}`: + +1. `Click [here]({{ baseUrl }}/userGuide/reusingContents.html).` +2. `![]({{ baseUrl }}/images/preview.png)` -To ensure that links in the _markbind/ folder work correctly across the entire site, they should be written as absolute paths, prepended with {{ baseUrl }}. + +To ensure that links in the _markbind/ folder work correctly across the entire site, they should be written as absolute paths, prepended with `{{ baseUrl }}`. +{% endraw %}
Relative paths: diff --git a/docs/userGuide/syntax/pageLayouts.mbdf b/docs/userGuide/syntax/pageLayouts.mbdf index f5fe9e24d5..7ff35b39fe 100644 --- a/docs/userGuide/syntax/pageLayouts.mbdf +++ b/docs/userGuide/syntax/pageLayouts.mbdf @@ -1,10 +1,3 @@ - - -{{ MAIN_CONTENT_BODY }} - - ## Page Layouts **A _layout_ is a set of page-tweaks that can be applied to a page (or group of pages) in one go.** @@ -110,7 +103,8 @@ afterSetup(() => { In the `page.md` file of your layouts, it should come with the following reserved variable: - {{ mainContentBody }} + + {%raw%}`{{ MAIN_CONTENT_BODY }}`{%endraw%} which injects the actual page content in every page. This allows you to build layouts in different ways. @@ -124,7 +118,7 @@ which injects the actual page content in every page. This allows you to build la ``` ```html {heading="page.md"} - {{ mainContentBody }} + {%raw%}{{ MAIN_CONTENT_BODY }}{%endraw%} diff --git a/docs/userGuide/tipsAndTricks.md b/docs/userGuide/tipsAndTricks.md index 96fe9f2e7a..a5f9b9d4b3 100644 --- a/docs/userGuide/tipsAndTricks.md +++ b/docs/userGuide/tipsAndTricks.md @@ -9,7 +9,7 @@ -##### Tip: Escaping Characters +##### :fas-lightbulb: Escaping Characters For Markdown syntax: To display a literal character that are normally used for Markdown formatting, add a backslash (`\`) in front of the character. @@ -26,7 +26,26 @@ For Markdown syntax: To display a literal character that are normally used for M -##### Problem: Unwanted starting space in links and triggers +{% raw %} + +##### :fas-lightbulb: Using {% raw %}{% endraw %} to display `{{ content }}` + + +To display the raw variable interpolation syntax using `{% raw %}{% endraw %}`, you would also need to add +the `v-pre` attribute using markdown-it-attrs or as a html attribute. + + + +This isn't necessary for `` elements, markdown code fences and inline code though, which markbind automatically +adds `v-pre` for. + +However, this does not change the need for `{% raw %}{% endraw %}`. Meaning, you can still use variables within your code! + + + +{% endraw %} + +##### :fas-info: Unwanted starting space in links and triggers When you use links or triggers, you may encounter a situation where an unwanted space is being generated by MarkBind: diff --git a/docs/userGuide/usingPlugins.md b/docs/userGuide/usingPlugins.md index a825b84c65..4745bcb2e3 100644 --- a/docs/userGuide/usingPlugins.md +++ b/docs/userGuide/usingPlugins.md @@ -200,7 +200,8 @@ removing such potential conflicts. - Should return an array of string tag names to be blacklisted, with each tag name being at least 2 characters long. -Note however, that variable interpolation syntax {{ variable_name }} will act as per normal. + +Note however, that variable interpolation syntax {% raw %}`{{ variable_name }}`{% endraw %} will act as per normal. Meaning, the user would still be able to use variables in your special tags! diff --git a/src/lib/markbind/src/lib/markdown-it/index.js b/src/lib/markbind/src/lib/markdown-it/index.js index 5ca37d86f7..5b98c7331e 100644 --- a/src/lib/markbind/src/lib/markdown-it/index.js +++ b/src/lib/markbind/src/lib/markdown-it/index.js @@ -14,7 +14,7 @@ markdownIt.use(require('markdown-it-mark')) .use(require('markdown-it-table-of-contents')) .use(require('markdown-it-task-lists'), {enabled: true}) .use(require('markdown-it-linkify-images'), {imgClass: 'img-fluid'}) - .use(require('markdown-it-attrs')) + .use(require('./patches/markdown-it-attrs-nunjucks')) .use(require('./markdown-it-dimmed')) .use(require('./markdown-it-radio-button')) .use(require('./markdown-it-block-embed')) diff --git a/src/lib/markbind/src/lib/markdown-it/patches/markdown-it-attrs-nunjucks.js b/src/lib/markbind/src/lib/markdown-it/patches/markdown-it-attrs-nunjucks.js new file mode 100644 index 0000000000..38dc633cfc --- /dev/null +++ b/src/lib/markbind/src/lib/markdown-it/patches/markdown-it-attrs-nunjucks.js @@ -0,0 +1,78 @@ +/* + Patch for markdown-it-attrs and nunjuck's usage of {% ... %} + */ + +const mdAttrsUtils = require('markdown-it-attrs/utils'); + +mdAttrsUtils.hasDelimiters = function (where, options) { + + if (!where) { + throw new Error('Parameter `where` not passed. Should be "start", "middle", "end" or "only".'); + } + + /** + * @param {string} str + * @return {boolean} + */ + return function (str) { + // we need minimum three chars, for example {b} + let minCurlyLength = options.leftDelimiter.length + 1 + options.rightDelimiter.length; + if (!str || typeof str !== 'string' || str.length < minCurlyLength) { + return false; + } + + function validCurlyLength (curly) { + let isClass = curly.charAt(options.leftDelimiter.length) === '.'; + let isId = curly.charAt(options.leftDelimiter.length) === '#'; + return (isClass || isId) + ? curly.length >= (minCurlyLength + 1) + : curly.length >= minCurlyLength; + } + + let start, end, slice, nextChar; + let rightDelimiterMinimumShift = minCurlyLength - options.rightDelimiter.length; + switch (where) { + case 'start': + // first char should be {, } found in char 2 or more + slice = str.slice(0, options.leftDelimiter.length); + start = slice === options.leftDelimiter ? 0 : -1; + end = start === -1 ? -1 : str.indexOf(options.rightDelimiter, rightDelimiterMinimumShift); + // check if next character is not one of the delimiters + nextChar = str.charAt(end + options.rightDelimiter.length); + if (nextChar && options.rightDelimiter.indexOf(nextChar) !== -1) { + end = -1; + } + break; + + case 'end': + // last char should be } + start = str.lastIndexOf(options.leftDelimiter); + end = start === -1 ? -1 : str.indexOf(options.rightDelimiter, start + rightDelimiterMinimumShift); + end = end === str.length - options.rightDelimiter.length ? end : -1; + break; + + case 'only': + // '{.a}' + slice = str.slice(0, options.leftDelimiter.length); + start = slice === options.leftDelimiter ? 0 : -1; + slice = str.slice(str.length - options.rightDelimiter.length); + end = slice === options.rightDelimiter ? str.length - options.rightDelimiter.length : -1; + break; + } + + /* + Simple patch here - abort if the delimiters wrap around % % + */ + const isCharAfterStartPercent = str.charAt(start + 1) === '%'; + const isCharBeforeEndPercent = str.charAt(end - 1) === '%'; + if (isCharAfterStartPercent && isCharBeforeEndPercent) { + return false; + } + + return start !== -1 + && end !== -1 + && validCurlyLength(str.substring(start, end + options.rightDelimiter.length)); + }; +}; + +module.exports = require('markdown-it-attrs'); diff --git a/src/lib/markbind/src/parsers/componentParser.js b/src/lib/markbind/src/parsers/componentParser.js index d7d58028cb..e4665b59f3 100644 --- a/src/lib/markbind/src/parsers/componentParser.js +++ b/src/lib/markbind/src/parsers/componentParser.js @@ -432,6 +432,9 @@ function _parseThumbnailAttributes(node) { function parseComponents(node) { try { switch (node.name) { + case 'code': + node.attribs['v-pre'] = ''; + break; case 'panel': _parsePanelAttributes(node); break; diff --git a/src/lib/markbind/src/utils/nunjuckUtils.js b/src/lib/markbind/src/utils/nunjuckUtils.js index 4373d13034..0f30a61b1b 100644 --- a/src/lib/markbind/src/utils/nunjuckUtils.js +++ b/src/lib/markbind/src/utils/nunjuckUtils.js @@ -6,10 +6,57 @@ const unescapedEnv = nunjucks.configure({ autoescape: false }).addFilter('date', const START_ESCAPE_STR = '{% raw %}'; const END_ESCAPE_STR = '{% endraw %}'; -const REGEX = new RegExp('{% *raw *%}(.*?){% *endraw *%}', 'gs'); +const RAW_TAG_REGEX = new RegExp('{% *(end)?raw *%}', 'g'); +/** + * Pads the outermost {% raw %} {% endraw %} pairs with {% raw %} {% endraw %} again. + * This allows variables and other nunjuck syntax inside {% raw %} {% endraw %} tags + * to be ignored by nunjucks until the final renderString call. + */ function preEscapeRawTags(pageData) { - return pageData.replace(REGEX, `${START_ESCAPE_STR}$&${END_ESCAPE_STR}`); + // TODO simplify using re.matchAll once node v10 reaches 'eol' + // https://github.com/nodejs/Release#nodejs-release-working-group + const tagMatches = []; + let tagMatch = RAW_TAG_REGEX.exec(pageData); + while (tagMatch !== null) { + tagMatches.push(tagMatch); + tagMatch = RAW_TAG_REGEX.exec(pageData); + } + + const tagInfos = Array.from(tagMatches, match => ({ + isStartTag: !match[0].includes('endraw'), + index: match.index, + content: match[0], + })); + + let numStartRawTags = 0; // nesting level of {% raw %} + let lastTokenEnd = 0; + const tokens = []; + + for (let i = 0; i < tagInfos.length; i += 1) { + const { index, isStartTag, content } = tagInfos[i]; + const currentTokenEnd = index + content.length; + tokens.push(pageData.slice(lastTokenEnd, currentTokenEnd)); + lastTokenEnd = currentTokenEnd; + + if (isStartTag) { + if (numStartRawTags === 0) { + // only pad outermost {% raw %} with an extra {% raw %} + tokens.push(START_ESCAPE_STR); + } + numStartRawTags += 1; + } else { + if (numStartRawTags === 1) { + // only pad outermost {% endraw %} with an extra {% endraw %} + tokens.push(END_ESCAPE_STR); + } + numStartRawTags -= 1; + } + } + // add the last token + tokens.push(pageData.slice(lastTokenEnd)); + + return tokens.join(''); } module.exports = { diff --git a/test/functional/test_site/expected/index.html b/test/functional/test_site/expected/index.html index 6002d95d8e..9a69db6da9 100644 --- a/test/functional/test_site/expected/index.html +++ b/test/functional/test_site/expected/index.html @@ -317,8 +317,8 @@

Focus groups

Path within the boilerplate folder is separately specified

Like static include, pages within the site should be able to use files located in folders within boilerplate.

-

Also, the boilerplate file name (e.g. inside.md) and the file that it is supposed to act as (notInside.md) can be different.

-

This file should behaves as if it is in the requirements folder:

+

Also, the boilerplate file name (e.g. inside.md) and the file that it is supposed to act as (notInside.md) can be different.

+

This file should behaves as if it is in the requirements folder:

@@ -347,7 +347,7 @@

Path within

MarkBind supports .mbd files.

-

MarkBind supports .mbdf files.

+

MarkBind supports .mbdf files.

Include from another Markbind site

@@ -630,6 +630,12 @@

Markbind Plugin Pre-renderLevel 2 header (inside headingSearchIndex) with no-index attribute should not be indexed

Level 6 header (outside headingSearchIndex) with always-index attribute should be indexed
+

Test nunjucks raw tags

+

+
{{ variable interpolation syntax can be used with v-pre }}
+
{{ nonExistentVariable }}
+ {{ code elements should automatically be assigned v-pre }} +


    diff --git a/test/functional/test_site/expected/requirements/UserStories._include_.html b/test/functional/test_site/expected/requirements/UserStories._include_.html index 1ce1ca22b5..be63ca4d34 100644 --- a/test/functional/test_site/expected/requirements/UserStories._include_.html +++ b/test/functional/test_site/expected/requirements/UserStories._include_.html @@ -1,10 +1,10 @@

    User stories are brief (typically, 1-3 sentences) descriptions of what the system can do for the users, written in the customers’ language. Often, user stories are written by the customers themselves.

    A commonly used format for writing user stories is:
    - As a <use type/role> I can <function> so that <benefit>

    + As a <use type/role> I can <function> so that <benefit>

    Here are some examples of user stories for the IVLE system:

    -
    * As a student, I can download files uploaded by lecturers, so that I can get my own copy of the files.
    * As a lecturer, I can create discussion forums, so that students can discuss things online.
    * As a tutor, I can print attendance sheets, so that I can take attendance during the class.
    -

    The <benefit> can be omitted if it is obvious. E.g. As a tutor, I can print attendance sheets. +

    * As a student, I can download files uploaded by lecturers, so that I can get my own copy of the files.
    * As a lecturer, I can create discussion forums, so that students can discuss things online.
    * As a tutor, I can print attendance sheets, so that I can take attendance during the class.
    +

    The <benefit> can be omitted if it is obvious. E.g. As a tutor, I can print attendance sheets. User stories are mainly used for early estimation and scheduling purposes.

    According to this, the biggest difference between user stories and traditional requirements specifications is in the level of detail. User stories should only provide enough detail to make a reasonably low risk diff --git a/test/functional/test_site/expected/testCodeBlocks.html b/test/functional/test_site/expected/testCodeBlocks.html index a6bf1326da..ab7d3f1c49 100644 --- a/test/functional/test_site/expected/testCodeBlocks.html +++ b/test/functional/test_site/expected/testCodeBlocks.html @@ -28,39 +28,39 @@

    Test: Code blocks

    Normal fenced code should render correctly

    -
    Content in a fenced code block
    +
    Content in a fenced code block

    With syntax coloring should render correctly

    -
    <foo>
    <bar type="name">goo</bar>
    </foo>
    -

    no-line-numbers attr should hide corresponding line numbers

    -
    <foo>
    <bar type="name">goo</bar>
    </foo>
    -

    start-from attr should set inline css in <code> tag, enabling lines to start from a specific line number

    -
    *****
    -----
    -

    highlight-lines attr causes corresponding lines to have 'highlighted' class

    -
    1  highlighted
    2
    3 highlighted
    4
    5 highlighted
    6 highlighted
    7 highlighted
    8 highlighted
    9
    10
    -

    highlight-lines attr with start-from attr should cause corresponding lines to have 'highlighted' class based on start-from

    -
    11  highlighted
    12
    13 highlighted
    14
    15 highlighted
    16 highlighted
    17 highlighted
    18 highlighted
    19
    20
    +
    <foo>
    <bar type="name">goo</bar>
    </foo>
    +

    no-line-numbers attr should hide corresponding line numbers

    +
    <foo>
    <bar type="name">goo</bar>
    </foo>
    +

    start-from attr should set inline css in <code> tag, enabling lines to start from a specific line number

    +
    *****
    -----
    +

    highlight-lines attr causes corresponding lines to have 'highlighted' class

    +
    1  highlighted
    2
    3 highlighted
    4
    5 highlighted
    6 highlighted
    7 highlighted
    8 highlighted
    9
    10
    +

    highlight-lines attr with start-from attr should cause corresponding lines to have 'highlighted' class based on start-from

    +
    11  highlighted
    12
    13 highlighted
    14
    15 highlighted
    16 highlighted
    17 highlighted
    18 highlighted
    19
    20

    Should render correctly with heading

    A heading
    -
    <foo>
    <bar>
    </foo>
    +
    <foo>
    <bar>
    </foo>

    Inline markdown contained in heading should also be rendered correctly

    Bold, Italic, Bold and Italic, Strike through, Super Bold, Underline, Highlight, 👍 ❗️ ❌ 🚧
    We support page breaks
    -
    <foo>
    <bar>
    </foo>
    +
    <foo>
    <bar>
    </foo>

    Code block with multiple linebreaks should not have the empty lines collapsed

    -

    Four empty lines below, one above




    Four empty lines above, one below

    +

    Four empty lines below, one above




    Four empty lines above, one below

    Code block without line numbers and multiple linebreaks should not have the empty lines collapsed

    -

    Four empty lines below, one above




    Four empty lines above, one below

    +

    Four empty lines below, one above




    Four empty lines above, one below

    Code block with syntax highlighting and multiple linebreaks should not have the empty lines collapsed

    -

    function fourEmptyLinesBelowOneAbove() {




    } // four empty lines above, one below

    -

    span with hljs class should span multiple lines (Link for context)

    -
    *****
    -----
    +

    function fourEmptyLinesBelowOneAbove() {




    } // four empty lines above, one below

    +

    span with hljs class should span multiple lines (Link for context)

    +
    *****
    -----
    diff --git a/test/functional/test_site/expected/testThumbnails.html b/test/functional/test_site/expected/testThumbnails.html index 4d2290340e..bfee4817a8 100644 --- a/test/functional/test_site/expected/testThumbnails.html +++ b/test/functional/test_site/expected/testThumbnails.html @@ -74,14 +74,14 @@ - border='3px solid red' + border='3px solid red' 3 pixel thick solid red line - 4px dotted blue + 4px dotted blue 4 pixel thick dotted blue line diff --git a/test/functional/test_site/expected/testTooltipSpacing.html b/test/functional/test_site/expected/testTooltipSpacing.html index ba0a6961cb..75220e49e3 100644 --- a/test/functional/test_site/expected/testTooltipSpacing.html +++ b/test/functional/test_site/expected/testTooltipSpacing.html @@ -27,7 +27,7 @@

    569: Stray space after tooltip

    -
    <tooltip>tooltip</tooltip>, test

    <trigger>trigger</trigger>, test
    +
    <tooltip>tooltip</tooltip>, test

    <trigger>trigger</trigger>, test

    tooltip, test

    trigger, test

    diff --git a/test/functional/test_site/index.md b/test/functional/test_site/index.md index 4e3f0e583f..d07daac64c 100644 --- a/test/functional/test_site/index.md +++ b/test/functional/test_site/index.md @@ -321,3 +321,13 @@ tags: ["tag-frontmatter-shown", "tag-included-file", "+tag-exp*", "-tag-exp-hidd ## Level 2 header (inside headingSearchIndex) with no-index attribute should not be indexed {.no-index} ###### Level 6 header (outside headingSearchIndex) with always-index attribute should be indexed {.always-index} + +**Test nunjucks raw tags** + +{% raw %} + +
    {{ variable interpolation syntax can be used with v-pre }}
    +
    {{ nonExistentVariable }}
    +{{ code elements should automatically be assigned v-pre }} + +{% endraw %} diff --git a/test/functional/test_site_algolia_plugin/expected/index.html b/test/functional/test_site_algolia_plugin/expected/index.html index 65e66db8ef..5d2bb6b508 100644 --- a/test/functional/test_site_algolia_plugin/expected/index.html +++ b/test/functional/test_site_algolia_plugin/expected/index.html @@ -60,7 +60,7 @@
    Content should have `algolia-no-index` class
    - TitleContent as attribute does not require algolia-no-index class + TitleContent as attribute does not require algolia-no-index class

    Question hint and answer should have algolia-no-index class

    diff --git a/test/functional/test_site_special_tags/expected/index.html b/test/functional/test_site_special_tags/expected/index.html index 2e3791dcad..9d871f89f3 100644 --- a/test/functional/test_site_special_tags/expected/index.html +++ b/test/functional/test_site_special_tags/expected/index.html @@ -25,7 +25,7 @@

    Functional test for htmlparser2 and markdown-it patches for special tags

    So far as to comply with the commonmark spec

    -

    There should be no text between this and the next <hr> tag in the browser, since it is a <script> tag.
    +

    There should be no text between this and the next <hr> tag in the browser, since it is a <script> tag.
    There should be an alert with the value of 2 as well.


    -

    There should be no text between this and the next <hr> tag in the browser, since it is a <style> tag.

    +

    There should be no text between this and the next <hr> tag in the browser, since it is a <style> tag.


    -

    There should be text between this and the next <hr> tag, since it is a special tag. +

    There should be text between this and the next <hr> tag, since it is a special tag. All text should appear in the browser window as a single line, save for the comment which the browser still interprets. (but will be in the expected output)

    @@ -69,8 +69,8 @@

    So far as to comply with t success!

    This has the same content has the previous test, but it is not a special tag. - The html comment <!-- --> should disappear in the expected output. - The line some text should appear as per normal, and not wrapped by a paragraph since + The html comment <!-- --> should disappear in the expected output. + The line some text should appear as per normal, and not wrapped by a paragraph since a html tag precedes it without a blank line. The other lines should be parsed as markdown paragraphs, as per commonmark spec.

    @@ -86,7 +86,7 @@

    So far as to comply with t

    There are two self closing special tags below, which should display nothing, but are present in the output. - There is then one special tag with both and opening and closing tag with some text in it (lorem ipsum...). + There is then one special tag with both and opening and closing tag with some text in it (lorem ipsum...). Note that script and style tags are still not allowed to be self-closing, as per the html5 spec.

    @@ -96,7 +96,7 @@

    So far as to comply with t

    This should pass the htmlparser2 patch but not the markdown-it patch as it violates commonmark.
    - All lines after the first !success wrapping text will be wrapped in a <p>...</p> tag as it is + All lines after the first !success wrapping text will be wrapped in a <p>...</p> tag as it is parsed as a markdown paragraph.

    !success diff --git a/test/functional/test_site_templates/test_default/expected/index.html b/test/functional/test_site_templates/test_default/expected/index.html index 0de6a3410b..464a69fc7f 100644 --- a/test/functional/test_site_templates/test_default/expected/index.html +++ b/test/functional/test_site_templates/test_default/expected/index.html @@ -86,8 +86,8 @@

    Heading 1<foo>
    <bar type="name">goo</bar>
    </foo>
    +

    A code example:

    +
    <foo>
    <bar type="name">goo</bar>
    </foo>

    Sub Heading 1.1

    A ❗️ some important explanationtooltip, a modal, a link, a badge, another badge.

    diff --git a/test/unit/nunjuckUtils.test.js b/test/unit/nunjuckUtils.test.js index 3fd753ab46..e506a44673 100644 --- a/test/unit/nunjuckUtils.test.js +++ b/test/unit/nunjuckUtils.test.js @@ -1,21 +1,28 @@ const njUtil = require('../../src/lib/markbind/src/utils/nunjuckUtils'); test('Escaping nunjucks raw tags', () => { - const escapedString = 'This is a content with escaped data {%raw%} CONTENT {%endraw%}'; + const escapedString = 'This is a content with escaped data {% raw %} CONTENT {% endraw %}'; const escapedContent = njUtil.renderRaw(escapedString); expect(escapedContent).toBe(escapedString); }); test('Escaping nunjucks with new lines', () => { - const escapedString = 'This is a content with escaped data\n {%raw%} \nCONTENT\n {%endraw%}'; + const escapedString = 'This is a content with escaped data\n {% raw %} \nCONTENT\n {% endraw %}'; const escapedContent = njUtil.renderRaw(escapedString); expect(escapedContent).toBe(escapedString); }); test('Escaping multiple nunjucks raw tags', () => { - const escapedString = 'Multiple escapes: {%raw%} first {%endraw%} {%raw%} second {%endraw%}'; + const escapedString = 'Multiple escapes: {% raw %} first {% endraw %} {% raw %} second {% endraw %}'; + const escapedContent = njUtil.renderRaw(escapedString); + + expect(escapedContent).toBe(escapedString); +}); + +test('Escaping nested nunjucks raw tags', () => { + const escapedString = 'Multiple escapes: {% raw %} first {% raw %} inside {% endraw %} second {% endraw %}'; const escapedContent = njUtil.renderRaw(escapedString); expect(escapedContent).toBe(escapedString);