twoslash icon indicating copy to clipboard operation
twoslash copied to clipboard

Doesn't highlight code?

Open SiddharthShyniben opened this issue 2 years ago • 3 comments

I'm using remark-shiki-twoslash:

const rendered = await unified()
	.use(remarkParse)
	.use(remarkTwoslash, ({theme: 'dark-plus'}))
	.use(remarkGfm)
	.use(remarkRehype)

	.use(rehypeStringify)
	.process(`
\`\`\`ts
const msg = "this";
//    ^?
\`\`\`
`);

console.log(String(rendered));

For some reason, this only wraps the code in a pre>code block:

<pre><code class="language-ts">const msg = "this";
//    ^?
</code></pre>

Is this a bug or am I doing something completely wrong?

SiddharthShyniben avatar Apr 25 '22 09:04 SiddharthShyniben

Hard to say, I don't know that API very well, but perhaps the order of your plugins is wrong - shiki twoslash will highlight code outside of ```ts twoslash codeblocks.

orta avatar Apr 25 '22 09:04 orta

I think I have outlined the problem ~~with a ton of console.logs~~. Since shiki uses async, remark finishes parsing before shiki gets to finish the async load call. The node is parsed to html, but too late.

SiddharthShyniben avatar Apr 25 '22 10:04 SiddharthShyniben

Fixed it! 🎉

const highlighter = await createShikiHighlighter({theme: 'dark-plus'});

const rendered = await unified()
	.use(remarkParse)
	.use(remarkGfm)
	.use(remarkTwoslash)
	.use(() => tree => {
		visit(tree, 'code', node => {
			const code = `
const msg = 'Hello, world!';
//    ^?
`;
			const twoslash = runTwoSlash(code, 'ts', {})
			const html = renderCodeToHTML(twoslash.code, 'ts', {twoslash: true}, {}, highlighter, twoslash);

			node.value = html;
			node.type = 'html';
			node.children = [];
		})
	})
	.use(remarkRehype, {allowDangerousHtml: true})
	.use(rehypeStringify, {allowDangerousHtml: true})
	.process(`
\`\`\`ts
const msg = "this";
//    ^?
\`\`\`
`);

console.log(String(rendered));

It's a hardcoded example, yes

SiddharthShyniben avatar Apr 25 '22 10:04 SiddharthShyniben