Skip to content

Commit 3aae9d5

Browse files
AntzyMoantfu
andauthored
feat(rehype): custom parseMetaString (#17)
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
1 parent 8bb4f18 commit 3aae9d5

File tree

6 files changed

+46
-6
lines changed

6 files changed

+46
-6
lines changed

packages/rehype-shikiji/src/index.ts

+26-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { bundledLanguages, getHighlighter } from 'shikiji'
33
import { toString } from 'hast-util-to-string'
44
import { visit } from 'unist-util-visit'
55
import type { Plugin } from 'unified'
6-
import type { Root } from 'hast'
6+
import type { Element, Root } from 'hast'
77
import { parseHighlightLines } from '../../shared/line-highlight'
88

99
export type RehypeShikijiOptions = CodeOptionsThemes<BuiltinTheme> & {
@@ -20,11 +20,28 @@ export type RehypeShikijiOptions = CodeOptionsThemes<BuiltinTheme> & {
2020
* @default true
2121
*/
2222
highlightLines?: boolean | string
23+
24+
/**
25+
* Extra meta data to pass to the highlighter
26+
*/
27+
meta?: Record<string, any>
28+
29+
/**
30+
* Custom meta string parser
31+
* Return an object to merge with `meta`
32+
*/
33+
parseMetaString?: (
34+
metaString: string,
35+
node: Element,
36+
tree: Root
37+
) => Record<string, any> | undefined | null
2338
}
2439

2540
const rehypeShikiji: Plugin<[RehypeShikijiOptions], Root> = function (options = {} as any) {
2641
const {
2742
highlightLines = true,
43+
parseMetaString,
44+
...rest
2845
} = options
2946

3047
const prefix = 'language-'
@@ -64,12 +81,18 @@ const rehypeShikiji: Plugin<[RehypeShikijiOptions], Root> = function (options =
6481
return
6582

6683
const code = toString(head as any)
84+
const attrs = (head.data as any)?.meta
85+
const meta = parseMetaString?.(attrs, node, tree) || {}
86+
6787
const codeOptions: CodeToHastOptions = {
68-
...options,
88+
...rest,
6989
lang: language.slice(prefix.length),
90+
meta: {
91+
...rest.meta,
92+
...meta,
93+
},
7094
}
7195

72-
const attrs = (head.data as any)?.meta
7396
if (highlightLines && typeof attrs === 'string') {
7497
const lines = parseHighlightLines(attrs)
7598
if (lines) {

packages/rehype-shikiji/test/fixtures/a.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
…world!
44

5-
```js {3-4}
5+
```js {3-4} fileName=test
66
console.log('it works!')
77

88
const a = 1

packages/rehype-shikiji/test/fixtures/a.out.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<h1>Hello</h1>
22
<p>…world!</p>
3-
<pre class="shiki vitesse-light" style="background-color:#ffffff;color:#393a34" tabindex="0" lang="js"><code><span class="line"><span style="color:#B07D48">console</span><span style="color:#999999">.</span><span style="color:#59873A">log</span><span style="color:#999999">(</span><span style="color:#B5695999">'</span><span style="color:#B56959">it works!</span><span style="color:#B5695999">'</span><span style="color:#999999">)</span></span>
3+
<pre class="shiki vitesse-light" style="background-color:#ffffff;color:#393a34" tabindex="0" lang="js" fileName="test"><code><span class="line"><span style="color:#B07D48">console</span><span style="color:#999999">.</span><span style="color:#59873A">log</span><span style="color:#999999">(</span><span style="color:#B5695999">'</span><span style="color:#B56959">it works!</span><span style="color:#B5695999">'</span><span style="color:#999999">)</span></span>
44
<span class="line"></span>
55
<span class="line highlighted"><span style="color:#AB5959">const</span><span style="color:#B07D48"> a</span><span style="color:#999999"> =</span><span style="color:#2F798A"> 1</span></span>
66
<span class="line highlighted"><span style="color:#B07D48">console</span><span style="color:#999999">.</span><span style="color:#59873A">log</span><span style="color:#999999">(</span><span style="color:#B07D48">a</span><span style="color:#999999">)</span></span>

packages/rehype-shikiji/test/index.test.ts

+9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ it('run', async () => {
1212
.use(remarkRehype)
1313
.use(rehypeShikiji, {
1414
theme: 'vitesse-light',
15+
parseMetaString: (str) => {
16+
return Object.fromEntries(str.split(' ').reduce((prev: [string, boolean | string][], curr: string) => {
17+
const [key, value] = curr.split('=')
18+
const isNormalKey = /^[A-Za-z0-9]+$/.test(key)
19+
if (isNormalKey)
20+
prev = [...prev, [key, value || true]]
21+
return prev
22+
}, []))
23+
},
1524
})
1625
.use(rehypeStringify)
1726
.process(await fs.readFile(new URL('./fixtures/a.md', import.meta.url)))

packages/shikiji/src/core/renderer-hast.ts

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ export function tokensToHast(
133133
style: options.rootStyle || `background-color:${options.bg};color:${options.fg}`,
134134
tabindex: '0',
135135
lang: options.lang,
136+
...options.meta,
136137
},
137138
children: [],
138139
}

packages/shikiji/src/types.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,14 @@ export type CodeOptionsThemes<Themes extends string = string> =
215215
| CodeOptionsSingleTheme<Themes>
216216
| CodeOptionsMultipleThemes<Themes>
217217

218+
export interface CodeOptionsMeta {
219+
meta?: Record<string, any>
220+
}
221+
218222
export type CodeToHastOptions<Languages extends string = string, Themes extends string = string> =
219223
& CodeToHastOptionsCommon<Languages>
220224
& CodeOptionsThemes<Themes>
225+
& CodeOptionsMeta
221226

222227
export interface ThemeRegistrationRaw extends IRawTheme {
223228

@@ -280,7 +285,7 @@ export interface HastTransformers {
280285
token?: (hast: Element, line: number, col: number, lineElement: Element) => Element | void
281286
}
282287

283-
export interface HtmlRendererOptions {
288+
export interface HtmlRendererOptionsCommon {
284289
lang?: string
285290
langId?: string
286291
fg?: string
@@ -308,6 +313,8 @@ export interface HtmlRendererOptions {
308313
mergeWhitespaces?: boolean
309314
}
310315

316+
export type HtmlRendererOptions = HtmlRendererOptionsCommon & CodeToHastOptions
317+
311318
export interface ThemedTokenScopeExplanation {
312319
scopeName: string
313320
themeMatches: any[]

0 commit comments

Comments
 (0)