Skip to content

Commit 8ad05bd

Browse files
serkodevantfu
andauthored
feat(core): add enforce options to ShikiTransformer (#1062)
Co-authored-by: Anthony Fu <[email protected]>
1 parent bda1a76 commit 8ad05bd

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

docs/guide/transformers.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,25 @@ You can access the raw meta using:
7373
this.options.meta
7474
// => { __raw: 'foo=bar baz-qux="qu ux"' }
7575
```
76+
77+
## Enforcing Transformer Ordering
78+
79+
For compatibility or fine-grained control, it may be necessary to enforce the order of a Shiki transformer. You can control the position of a transformer with the `enforce` modifier:
80+
81+
- `pre`: invoked before normal transformers
82+
- default: invoked as a normal transformers
83+
- `post`: invoked after normal transformers
84+
85+
Example:
86+
87+
```ts twoslash
88+
import type { ShikiTransformer } from 'shiki'
89+
90+
const customTransformer: ShikiTransformer = {
91+
name: 'my-transformer',
92+
enforce: 'pre',
93+
code(node) {
94+
// ...
95+
},
96+
}
97+
```

packages/core/src/highlight/_get-transformers.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,36 @@ const builtInTransformers: ShikiTransformer[] = [
66
]
77

88
export function getTransformers(options: TransformerOptions): ShikiTransformer[] {
9+
const transformers = sortTransformersByEnforcement(options.transformers || [])
910
return [
10-
...options.transformers || [],
11+
...transformers.pre,
12+
...transformers.normal,
13+
...transformers.post,
1114
...builtInTransformers,
1215
]
1316
}
17+
18+
function sortTransformersByEnforcement(transformers: ShikiTransformer[]): {
19+
pre: ShikiTransformer[]
20+
post: ShikiTransformer[]
21+
normal: ShikiTransformer[]
22+
} {
23+
const pre: ShikiTransformer[] = []
24+
const post: ShikiTransformer[] = []
25+
const normal: ShikiTransformer[] = []
26+
27+
for (const transformer of transformers) {
28+
switch (transformer.enforce) {
29+
case 'pre':
30+
pre.push(transformer)
31+
break
32+
case 'post':
33+
post.push(transformer)
34+
break
35+
default:
36+
normal.push(transformer)
37+
}
38+
}
39+
40+
return { pre, post, normal }
41+
}

packages/types/src/transformers.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ export interface ShikiTransformer {
5050
* Name of the transformer
5151
*/
5252
name?: string
53+
/**
54+
* Enforce plugin invocation tier similar to webpack loaders. Hooks ordering
55+
* is still subject to the `order` property in the hook object.
56+
*
57+
* Plugin invocation order:
58+
* - `enforce: 'pre'` plugins
59+
* - normal plugins
60+
* - `enforce: 'post'` plugins
61+
* - shiki post plugins
62+
*/
63+
enforce?: 'pre' | 'post'
5364
/**
5465
* Transform the raw input code before passing to the highlighter.
5566
*/

0 commit comments

Comments
 (0)