markedjs/marked-highlight

Issue with rendering in `sveltekit`

baseplate-admin opened this issue ยท 15 comments

Hi so here's my svelte code :

<script lang="ts">
    import { emojis } from "$data/emojis";
    import hljs from "highlight.js";
    import "highlight.js/scss/dark.scss";
    import { marked } from "marked";
    import { markedEmoji } from "marked-emoji";
    import { markedHighlight } from "marked-highlight";

    export { klass as class };

    let klass = "";

    const emoji_options = {
        emojis,
        unicode: false
    };

    // Override function
    const renderer: marked.RendererObject = {
        del(text: string) {
            /** Dont convert s (tag) -> del (tag)
             * Reason 1: Skeleton.dev is formatting `del` tag | Source : https://www.skeleton.dev/elements/typography
             * Reason 2: Marked.js is not allowing us to add unstyled class to rendered text.
             */

            return `<s>${text}</s>`;
        }
    };

    marked.use(
        // Highlight.js
        markedHighlight({
            langPrefix: "hljs language-",
            highlight: (code, lang) => {
                const language = hljs.getLanguage(lang) ? lang : "plaintext";
                return hljs.highlight(code, { language }).value;
            }
        }),

        // Emoji plugin
        markedEmoji(emoji_options),
        {
            renderer,
            // Disable it as marked-mangle doesn't support typescript
            mangle: false,
            // We dont need github like header prefix
            headerIds: false
        }
    );
</script>

<markdown class={klass}>
    {@html marked.parse(`
\`\`\`javascript
const highlight = "code";
\`\`\`
    `)}
</markdown>

The first render looks correct :

<pre>
	<code class="hljs language-javascript">
		<span class="hljs-keyword">const</span> highlight = 
		<span class="hljs-string">"code"</span>;

	</code>
</pre>

The next render looks like this ( incorrect | looks like some of the html from first render got into here? ) :

<pre>
	<code class="hljs language-javascript">&lt;span 
		<span class="hljs-keyword">class</span>=
		<span class="hljs-string">"hljs-keyword"</span>&gt;
		<span class="hljs-keyword">const</span>&lt;
		<span class="hljs-regexp">/span&gt; highlight = &lt;span class="hljs-string"&gt;&amp;quot;code&amp;quot;&lt;/</span>span&gt;;

	</code>
</pre>

The next render even is more incorrect :

<pre>
	<code class="hljs language-javascript">&amp;lt;span &lt;span 
		<span class="hljs-keyword">class</span>=
		<span class="hljs-string">"hljs-keyword"</span>&gt;
		<span class="hljs-keyword">class</span>&lt;
		<span class="hljs-regexp">/span&gt;=&lt;span class="hljs-string"&gt;&amp;quot;hljs-keyword&amp;quot;&lt;/</span>span&gt;&amp;gt;
		<span class="language-xml">
			<span class="hljs-tag">&lt;
				<span class="hljs-name">span</span>
				<span class="hljs-attr">class</span>=
				<span class="hljs-string">"hljs-keyword"</span>&gt;
			</span>const
			<span class="hljs-tag">&lt;/
				<span class="hljs-name">span</span>&gt;
			</span>
		</span>&amp;lt;
		<span class="language-xml">
			<span class="hljs-tag">&lt;
				<span class="hljs-name">span</span>
				<span class="hljs-attr">class</span>=
				<span class="hljs-string">"hljs-regexp"</span>&gt;
			</span>/span
			<span class="hljs-symbol">&amp;gt;</span> highlight = 
			<span class="hljs-symbol">&amp;lt;</span>span class=
			<span class="hljs-symbol">&amp;quot;</span>hljs-string
			<span class="hljs-symbol">&amp;quot;</span>
			<span class="hljs-symbol">&amp;gt;</span>
			<span class="hljs-symbol">&amp;amp;</span>quot;code
			<span class="hljs-symbol">&amp;amp;</span>quot;
			<span class="hljs-symbol">&amp;lt;</span>/
			<span class="hljs-tag">&lt;/
				<span class="hljs-name">span</span>&gt;
			</span>
		</span>span&amp;gt;;

	</code>
</pre>

This is how it looks ( screenshot ):
image


I think this is an issue in marked-highlight side instead of svelte side :)

Looks like a duplicate of #26

Yep, it seems like #26 highlights the issue.

So in my opinion there should there be a section in the readme.md regarding this issue?

PRs are always appreciated ๐Ÿ˜๐Ÿ‘

talwat commented

Yeah i'm experiencing this too, it sucks, took me ages to figure it out that this library was the problem.

talwat commented

And it hasn't been fixed for me, so for now, I'll use the deprecated method until something changes.

There is still this problem now.

๐ŸŽ‰ This issue has been resolved in version 2.0.2 ๐ŸŽ‰

The release is available on:

Your semantic-release bot ๐Ÿ“ฆ๐Ÿš€

talwat commented

How does the linked PR fix anything? This is really strange.

How does the linked PR fix anything? This is really strange.

The linked PR demonstrates a way to use the Marked constructor to render markdown. Which fixes the issue with sveltekit.

If you want a in project example :
https://github.com/tokitou-san/CoreProject-V3-UI/blob/bff57fe0fd7cb3b62611028ff0e6fe335bf5e8c2/src/lib/components/shared/markdown.svelte#L22-L70

talwat commented

But has the underlying issue been fixed yet? And what if you use the old API, does it work now?

what if you use the old API

Old API modifies global state. So no. Old API can't be fixed. That's why there's a new way to do things

talwat commented

But why does modifying global state lead to this mess specifically with svelte? Shouldn't that be fixed?

why does modifying global state lead to this mess specifically with svelte?

This is not local to svelte. react, vue have this exact issue. Basically marked is not playing nice with anything SPA based.


Shouldn't that be fixed?

Thats the limit of my knowledge about marked. @UziTech can explain it in depth

You can still use the old API you just have to reset the state by adding marked.setOptions(marked.getDefaults()); before adding marked extensions.

If you want svelte to fix the issue of it getting messed up due to global state you will have to talk to svelte.