pablo-abc / svelte-markdown

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

Overriding default renderers array #41

Open khromov opened 2 years ago

khromov commented 2 years ago

It's quite common to only want to support a subset of Markdown. (I'd argue the most common use case)

Since the current implementation merges renderers with the default render config this is needlessly verbose. In addition to having to know all the keys for existing renderers to configure, if a new one gets added in a future version of svelte-markdown we'd automatically opt into it. ☹️

For example to only support bold and cursive we'd have to do this:

// EmptyComponent.svelte
<slot></slot>

// Main.svelte
<script>
    import EmptyComponent from './EmptyComponent.svelte';
</script>

<SvelteMarkdown
    source={source}
    renderers={{
        text: EmptyComponent,
        paragraph: EmptyComponent,
        // em: EmptyComponent, <= We want to support this
        // strong: EmptyComponent, <= We want to support this
        hr: EmptyComponent,
        blockquote: EmptyComponent,
        del: EmptyComponent,
        link: EmptyComponent,
        image: EmptyComponent,
        table: EmptyComponent,
        tablehead: EmptyComponent,
        tablebody: EmptyComponent,
        tablerow: EmptyComponent,
        tablecell: EmptyComponent,
        list: EmptyComponent,
        listitem: EmptyComponent,
        heading: EmptyComponent,
        codespan: EmptyComponent,
        code: EmptyComponent,
        html: EmptyComponent
    }}
/>

I think the ergonomics would be improved if we could add a defaultRenderers prop that would override the default configuration instead of merging with it. The above example would be rewritten as:

// EmptyComponent.svelte
<slot></slot>

// Main.svelte
<script>
    import Em from 'svelte-markdown/src/renderers/Em.svelte';
    import Strong from 'svelte-markdown/src/renderers/Strong.svelte';
</script>

<SvelteMarkdown
    source={source}
    defaultRenderers={{
        em: Em ,
        strong: Strong ,
                // No other renderers are supported
    }}
/>

There could be even less verbose solution with a allowedRenderers prop, but it's a bit more opinionated. Eg:

<SvelteMarkdown
    source={source}
    allowedRenderers={['em', 'strong']}
/>

Let me know what you think!

pablo-abc commented 2 years ago

This is something that can be implemented. What would the expected behaviour for non-accepted tokens be? Would they be displayed as plain text? Raw (with markdown syntax untouched)? Would they be omitted completely?

I've toyed around with making default renderer's completely optional, so they'd only get included in the bundle only if you use them. Although this would make it more complex for basic scenarios.

khromov commented 2 years ago

@pablo-abc I would expect that unsupported tokens would be left as-is, so if we don't support Strong, then Hello **world** would render without any modifications, with the stars intact.

Attempting to convert to plaintext feels like it's not something that is generally desired. Markdown is about enhancing with markup after all, not to sanitize it. It could also already be implemented by passing EmptyComponent to all renderers as in my first example.