pablo-abc / svelte-markdown

Markdown parser to svelte components
MIT License
360 stars 50 forks source link

HTML not rendering properly #57

Closed Prinzhorn closed 8 months ago

Prinzhorn commented 2 years ago
<script>
  import SvelteMarkdown from 'svelte-markdown'
  const source = `<a href="/foo">bar</a>`
</script>

<SvelteMarkdown {source} />

This will essentially cause the following renderer components to be rendered

<Html /><Text /><Html />

image

But that's not how HTML works. This works when concatenating HTML strings, but not with @html / innerHTML. You end up with this after the browser repaired it:

<a href="/foo"></a>bar

Quoting Svelte docs https://svelte.dev/docs#template-syntax-html

The expression should be valid standalone HTML — {@html "<div>"}content{@html "</div>"} will not work, because

is not valid HTML

Prinzhorn commented 2 years ago

Funny enough, wrapping everything in a div works, since it causes a single big HTML token. So this a matter of how marked tokenizes some HTML things. It breaks for <strong> as well.

These bits of inline HTML seem to have a special meaning in Markdown. Look at how these three render in GitHub:

<a href="/foo">foo</a>

<a href="/foo">**foo**</a>

<div><a href="/foo">**foo**</a></div>

foo

foo

**foo**

I honestly don't know if this can be solved on svelte-markdown's end. Sure, you could pass all tokens with inLink: true to a <slot> and essentially ignore the </a> closing tokens. But how would you go about actually rendering the link? You'd have to extract the attributes from the opening tag and then delegate to the link renderer. But that wasn't the authors intent with the given markdown.

A solution that would "work" would be to first render the opening/closing tag (with empty content) via the HTML renderer. And then mount a new renderer inside onMount/afterUpdate with bind:this via new SvelteMarkdown() to render the children. Sounds fun. Also not SSR compatible, but idc about that.

Can someone figure out how ReactMarkdown does it (if at all)? Edit: they're not using marked, so I assume they just have different tokens to work with. The example above renders correctly in their online demo.

Prinzhorn commented 8 months ago

YEP fixed by using raw html + morphdom