diff --git a/packages/rehype-shikiji/src/index.ts b/packages/rehype-shikiji/src/index.ts index 8873ad7f9..4a348b2d6 100644 --- a/packages/rehype-shikiji/src/index.ts +++ b/packages/rehype-shikiji/src/index.ts @@ -21,6 +21,13 @@ export type RehypeShikijiOptions = CodeOptionsThemes & { */ highlightLines?: boolean | string + /** + * Add `language-*` class to code element + * + * @default false + */ + addLanguageClass?: boolean + /** * Extra meta data to pass to the highlighter */ @@ -40,6 +47,7 @@ export type RehypeShikijiOptions = CodeOptionsThemes & { const rehypeShikiji: Plugin<[RehypeShikijiOptions], Root> = function (options = {} as any) { const { highlightLines = true, + addLanguageClass = false, parseMetaString, ...rest } = options @@ -93,6 +101,17 @@ const rehypeShikiji: Plugin<[RehypeShikijiOptions], Root> = function (options = }, } + if (addLanguageClass) { + codeOptions.transformers ||= [] + codeOptions.transformers.push({ + name: 'rehype-shikiji:code-language-class', + code(node) { + addClassToHast(node, language) + return node + }, + }) + } + if (highlightLines && typeof attrs === 'string') { const lines = parseHighlightLines(attrs) if (lines) { diff --git a/packages/rehype-shikiji/test/fixtures/b.md b/packages/rehype-shikiji/test/fixtures/b.md new file mode 100644 index 000000000..b5103bf80 --- /dev/null +++ b/packages/rehype-shikiji/test/fixtures/b.md @@ -0,0 +1,8 @@ +# Hello + +…world! + +```js +const b = 2 +console.log(b) +``` diff --git a/packages/rehype-shikiji/test/fixtures/b.out.html b/packages/rehype-shikiji/test/fixtures/b.out.html new file mode 100644 index 000000000..926f8f368 --- /dev/null +++ b/packages/rehype-shikiji/test/fixtures/b.out.html @@ -0,0 +1,5 @@ +

Hello

+

…world!

+
const b = 2
+console.log(b)
+
\ No newline at end of file diff --git a/packages/rehype-shikiji/test/index.test.ts b/packages/rehype-shikiji/test/index.test.ts index 6fecfa89a..afe387f59 100644 --- a/packages/rehype-shikiji/test/index.test.ts +++ b/packages/rehype-shikiji/test/index.test.ts @@ -27,3 +27,17 @@ it('run', async () => { expect(file.toString()).toMatchFileSnapshot('./fixtures/a.out.html') }) + +it('code-add-language-class', async () => { + const file = await unified() + .use(remarkParse) + .use(remarkRehype) + .use(rehypeShikiji, { + theme: 'vitesse-light', + addLanguageClass: true, + }) + .use(rehypeStringify) + .process(await fs.readFile(new URL('./fixtures/b.md', import.meta.url))) + + expect(file.toString()).toMatchFileSnapshot('./fixtures/b.out.html') +})