Parse markdown inside a svelte component
Asked Answered
T

5

11

Please excuse me if this is a naive question. I would like to parse markdown inside a Svelte component, something like

<script>
  --- import some markdownLibrary ---
  export let text; // text is a markdown param
</script>

markdownLibrary.render({text})

I can't use markdown-it or marked as require isn't available.

I feel like I'm missing the bigger picture here. What is the 'svelte' way of doing this? Any pointer would help.

Tybalt answered 25/3, 2020 at 21:23 Comment(1)
To anyone new here: if you want to use markdown documents as Svelte components or put Svelte components into markdown, I recommend taking a look at mdsvex!Oneidaoneil
E
17

Using markdown is simple in Svelte, but you have to remember that a lot of markdown libraries expect to find node/requirejs etc, so you have to configure your bundler correctly to accomodate this.

To simply use markdown in Svelte, pick a library which supports modern JavaScript out of the box:

<script>
  import snarkdown from 'snarkdown'

  let md = `
    # Hello

    ## How are you?

    This text is _bold_
  `
</script>

<div>
{@html snarkdown(md)}
</div>
Edmondedmonda answered 26/3, 2020 at 8:48 Comment(2)
using @html is risky as per the documentation - Svelte does not sanitize expressions before injecting HTML. If the data comes from an untrusted source, you must sanitize it, or you are exposing your users to an XSS vulnerabilityEntwistle
You can use the DOMPurify package to further sanitize the html text content.Entwistle
O
8

The problem with the accepted answer is that it relies on @html which is not secure.

There is a svelte component that renders markdown without using @html

https://www.npmjs.com/package/svelte-markdown

yarn add svelte-markdown
<script>
  import SvelteMarkdown from 'svelte-markdown'
  const source = `
  # This is a header

This is a paragraph.

* This is a list
* With two items
  1. And a sublist
  2. That is ordered
    * With another
    * Sublist inside

| And this is | A table |
|-------------|---------|
| With two    | columns |`
</script>

<SvelteMarkdown {source} />
Oviduct answered 22/3, 2021 at 12:3 Comment(4)
Agreed that it is not secure, but we use markdown for our own copy so it doesn't need to be. I would suggest in all cases that you sanitize the input before rendering it. I'm assuming that this library does that.Edmondedmonda
This solution is beyond sanitisation. From the markdown the library builds the tree, so the labels are constrained. It would be analogous to having a query with trusted input because it's internal vs a prepared statement. Variables go on a different channel so injection is not possibleOviduct
If you want to use another library like marked or snarkdown, you can always run the results through a sanitizer like dompurify before rendering.Chaotic
svelte-markdown does use @html when the Markdown content contains HTML github.com/pablo-abc/svelte-markdown/issues/42Poussin
B
5

I use marked. I game the system by assigning a variable that svelte can see to marked.

<script>
  let _marked = marked

  let md = `
    # Hello

    ## How are you?

    This text is _bold_
  `
</script>

<div>
{@html _marked(md)}
</div>
Burrus answered 27/3, 2020 at 17:45 Comment(0)
H
1

Magidoc has a svelte library to render markdown into components as well.

Hireling answered 20/8, 2022 at 11:12 Comment(0)
A
0

I use marked as well.

I am fully understand that @html is NOT secure since it could be used in XSS attack but in my case, I also have full control of what should be use with @html so I accepted the risk and just let the ESlint warn me instead of throw an error.

<script lang="ts">
  import { marked } from 'marked';

  export let markdownContent: string;
</script>

{@html marked(markdownContent)}

And I override the Eslint rules like this:

// eslintrc.js
{
    ...,
    rules: {
        'svelte/no-at-html-tags': 'warn'
    }
}
Aesculapius answered 3/12, 2023 at 2:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.