11ty / eleventy-plugin-webc

Adds support for WebC *.webc files to Eleventy
https://www.11ty.dev/docs/languages/webc/
120 stars 10 forks source link

Parsing markdown templates as webc breaks blockquotes #34

Open oliverjam opened 1 year ago

oliverjam commented 1 year ago

I know you said it was risky to do this, but using WebC as a Markdown template engine works great, except it breaks all blockquotes.

## A title

A paragraph

> a blockquote

Output:

<h2>A title</h2>
<p>A paragraph</p>
<p>&gt; a blockquote</p>

I assume this is because the HTML parser escapes any angle brackets before it gets to the Markdown parser.

Is there an obvious way to work around this or should I give up on my custom-elements-in-markdown dream?

zachleat commented 1 year ago

Yeah, hmm. You can wrap it in a webc:raw element and it should work (though it isn’t ideal)

## A title

A paragraph

<template webc:raw webc:nokeep>
> a blockquote
</template>

or even the whole thing, I suppose?

<template webc:raw webc:nokeep>
## A title

A paragraph

> a blockquote
</template>
zachleat commented 1 year ago

Well, wait there is something else going on here, when I paste your example into AST Explorer for parse5:

image

Given that AST I would expect it to work

zachleat commented 1 year ago

Rather, this is more accurate to what WebC does behind the scenes to avoid quirks mode (but the point still stands):

image

oliverjam commented 1 year ago

Interesting—I chucked some logs into my node_modules and found that while the AST is correct the > definitely gets converted to an HTML entity during serialization:

// node_modules/@11ty/eleventy-plugin-webc/src/eleventyWebcTemplate.js
// this is inside the plugin's `compile` method:

let setup = await page.setup(setupObject);
incremental.addSetup(inputPath, setup);
console.log(setup.serializer);

let { ast, serializer } = setup;
let { html, css, js, buckets } = await serializer.compile(ast);
console.log(html)
AstSerializer {
    mode: 'component',
    bundlerMode: true,
    reprocessingMode: true,
    _filePath: './index.md',
    transforms: {...},
    helpers: {...},
    aliases: {},
    componentMap: {},
    components: {},
    hashOverrides: {},
    globalData: {...},
    streams: Streams {...},
    fileCache: FileSystemCache {...},
+    content: '<!doctype html>\n# Home\n\nSome text\n\n> a quote\n'
  }
}
# Home

Some text

&gt; a quote

I'm reading the source for the serializer and it looks like #text nodes get escaped here:

https://github.com/11ty/webc/blob/553fb87a60a4e10929126ddd3e0164103dc0420a/src/ast.js#L1236-L1242

oliverjam commented 1 year ago

Thank you for the workaround suggestion. Using <template webc:raw> does preserve markdown, but it prevents the WebC parser from compiling components, which was the main reason to use it as the templating engine (i.e. using WebC components as shortcodes).

Is there any way to tell WebC you want to opt out of HTML-escaping?

solution-loisir commented 1 year ago

I have the same setup, and find it very beneficial except for blockquotes breaking. I went for a component workaround:

<blockquote :cite="cite || null">
  <slot></slot>
</blockquote>