11ty / eleventy-plugin-template-languages

Official template syntax plugins for Eleventy
MIT License
2 stars 2 forks source link

Parse error on some handlebars code snippets in markdown #9

Open mehulkar opened 2 years ago

mehulkar commented 2 years ago

Describe the bug Exception in markdown template parsing:

 ```hbs
<h1>{{or @foo "default"}}</h1>
\```

I've included a backslash in the snippet below for Github's markdown parsing, it is not in my actual markdown file

To Reproduce

  1. With "@11ty/eleventy": "1.0.0"
  2. Create .md file with syntax above
  3. npm run start or npm run build
  4. See error

    [11ty] > Having trouble rendering liquid template ./source/my-file.md
    
    `TemplateContentRenderError` was thrown
    [11ty] > unexpected token at "@foo \"default\"", file:./source/my-file.md, line:237, col:5
    
    `ParseError` was thrown
    [11ty] > unexpected token at "@foo \"default\""
    
    `AssertionError` was thrown:
    [11ty]     AssertionError: unexpected token at "@foo \"default\""
            at new AssertionError (/dev/project/node_modules/liquidjs/dist/liquid.node.cjs.js:664:28)
            at assert (/dev/project/node_modules/liquidjs/dist/liquid.node.cjs.js:822:15)
            at Tokenizer.readFilter (/dev/project/node_modules/liquidjs/dist/liquid.node.cjs.js:1944:9)
            at Tokenizer.readFilters (/dev/project/node_modules/liquidjs/dist/liquid.node.cjs.js:1933:31)
            at new Value (/dev/project/node_modules/liquidjs/dist/liquid.node.cjs.js:2418:34)
            at new Output (/dev/project/node_modules/liquidjs/dist/liquid.node.cjs.js:2501:23)
            at Parser.parseToken (/dev/project/node_modules/liquidjs/dist/liquid.node.cjs.js:2562:24)
            at Parser.parseTokens (/dev/project/node_modules/liquidjs/dist/liquid.node.cjs.js:2552:33)
            at Parser.parse (/dev/project/node_modules/liquidjs/dist/liquid.node.cjs.js:2546:21)
            at Liquid.parse (/dev/project/node_modules/liquidjs/dist/liquid.node.cjs.js:4280:28)
    [11ty] Wrote 0 files in 0.33 seconds (v1.0.0)

Environment:

Additional context

Build worked fine with v0.12.1!

pdehaan commented 2 years ago

Ah yes... I think part of the issue might be it didn't work exactly fine in 0.12.x, but failed silently.

If I have this in my src/index.md file and compile w/ Eleventy@0.12.1…

    <h1>{{or @foo "default"}}</h1>

then I get the following generated output:

<pre><code class="language-hbs">&lt;h1&gt;&lt;/h1&gt;
</code></pre>

So liquidjs (the default parser for *.md files) doesn't know how to interpret {{or @foo "default"}} and just ignores it silently, and was probably stripping the unexpected hbs code.

But now in Eleventy v1 (which uses liquidjs@9 vs liquidjs@6 in Eleventy v0.12.x), it will throw a parsing error on the invalid {{or @foo "default"}} syntax, because that isn't liquidjs at all and it panics, giving me the following output:

[11ty] Problem writing Eleventy templates: (more in DEBUG output) [11ty] > Having trouble rendering liquid template ./src/index.md

TemplateContentRenderError was thrown [11ty] > unexpected token at "@foo \"default\"", file:./src/index.md, line:3, col:5

ParseError was thrown [11ty] > unexpected token at "@foo \"default\""

AssertionError was thrown: [11ty] AssertionError: unexpected token at "@foo \"default\""

[11ty] Wrote 0 files in 0.03 seconds (v1.0.0)

One workaround might be to wrap your ``hbs</code> blocks with{% raw %}...{% endraw %}` tags and see if that solves it for you.

{% raw %}
```hbs
<h1>{{or @foo "default"}}</h1>
```
{% endraw %}

This should give you the following output in Eleventy 1.0:

<pre><code class="language-hbs">&lt;h1&gt;{{or @foo &quot;default&quot;}}&lt;/h1&gt;
</code></pre>
mehulkar commented 2 years ago

So liquidjs (the default parser for *.md files) doesn't know how to interpret

oh interesting. I see in the docs as well that liquidjs is the default parser. Since all my files are markdown, would changing the template engine be the right way forward for me? Or to debug why liquidJS doesn't like this syntax? It seems to be ok with fenced code blocks in general, so maybe it's a bug that it fails on this specifically? (even in 0.12 when it was a silent failure)

pdehaan commented 2 years ago

Or to debug why liquidJS doesn't like this syntax?

I think the problem is that liquidjs is trying to parse handlebars snippets.

If you don't want liquid to parse blocks of code, you'd have to either

  1. wrap the blocks in {% raw %}...{% endraw %} so LiquidJS ignores any Handlebars template code, or
  2. set templateEngineOverride: md (or templateEngineOverride: false?) front matter data in specific templates which tells Eleventy to not preprocess the file w/ a different template engine; like liquidjs or nunjucks)
  3. turn off template preprocessing globally for Markdown files by setting markdownTemplateEngine: false in your .eleventy.js config file:
    module.exports = (eleventyConfig) => {
      return {
        dir: {
          input: "src",
          output: "www",
        },
    +   markdownTemplateEngine: false,
      };
    };

But yeah fenced code blocks are fine, but liquidjs is trying to parse the templates for custom tags or shortcodes or variables and then throwing errors when it encounters unexpected Handlebars syntax.