@shikijs/transformers
Common transformers for Shiki, inspired by shiki-processor.
Install
npm i -D @shikijs/transformers
Usage
import {
transformerNotationDiff,
// ...
} from '@shikijs/transformers'
import {
codeToHtml,
} from 'shiki'
const code = `console.log('hello')`
const html = await codeToHtml(code, {
lang: 'ts',
theme: 'nord',
transformers: [
transformerNotationDiff(),
// ...
],
})
Unstyled
Transformers only applies classes and does not come with styles; you can provide your own CSS rules to style them properly.
Transformers
transformerNotationDiff
Use [!code ++]
and [!code --]
to mark added and removed lines.
```ts
console.log('hewwo') // [!code --]
console.log('hello') // [!code ++]
console.log('goodbye')
```
Renders (with custom CSS rules):
console.log('hewwo')
console.log('hello')
console.log('goodbye')
// [!code ++]
outputs:<span class="line diff add">
// [!code --]
outputs:<span class="line diff remove">
- The outer
<pre>
tag is modified:<pre class="has-diff">
HTML Output
<!-- Output (stripped of `style` attributes for clarity) -->
<pre class="shiki has-diff"> <!-- Notice `has-diff` -->
<code>
<span class="line"></span>
<span class="line"><span>function</span><span>()</span><span></span><span>{</span></span>
<span class="line diff remove"> <!-- Notice `diff` and `remove` -->
<span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>hewwo</span><span>'</span><span>) </span>
</span>
<span class="line diff add"> <!-- Notice `diff` and `add` -->
<span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>hello</span><span>'</span><span>) </span>
</span>
<span class="line"><span></span><span>}</span></span>
<span class="line"><span></span></span>
</code>
</pre>
transformerNotationHighlight
Use [!code highlight]
to highlight a line.
```ts
console.log('Not highlighted')
console.log('Highlighted') // [!code highlight]
console.log('Not highlighted')
```
Renders (with custom CSS rules):
console.log('Not highlighted')
console.log('Highlighted')
console.log('Not highlighted')
// [!code highlight]
outputs:<span class="line highlighted">
- The outer
<pre>
tag is modified:<pre class="has-highlighted">
You can also highlight multiple lines with a single comment:
```ts
// [!code highlight:3]
console.log('Highlighted')
console.log('Highlighted')
console.log('Not highlighted')
```
Renders:
console.log('Highlighted')
console.log('Highlighted')
console.log('Not highlighted')
transformerNotationWordHighlight
Use [!code word:Hello]
to highlight the word Hello
in any subsequent code.
```ts
// [!code word:Hello]
const message = 'Hello World'
console.log(message) // prints Hello World
```
Renders (with custom CSS rules):
const message = 'Hello World'
console.log(message) // prints Hello World
Outputs: <span class="highlighted-word">Hello</span>
for matched words.
You can also specify the number of lines to highlight words on, e.g. [!code word:Hello:1]
will only highlight occurrences of Hello
on the next line.
```ts
// [!code word:Hello:1]
const message = 'Hello World'
console.log(message) // prints Hello World
```
Renders:
const message = 'Hello World'
console.log(message) // prints Hello World
transformerNotationFocus
Use [!code focus]
to focus a line.
```ts
console.log('Not focused');
console.log('Focused') // [!code focus]
console.log('Not focused');
```
Renders (with custom CSS rules):
console.log('Not focused')
console.log('Focused')
console.log('Not focused')
- Outputs:
<span class="line focused">
- The outer
<pre>
tag is modified:<pre class="has-focused">
You can also focus multiple lines with a single comment:
```ts
// [!code focus:3]
console.log('Focused')
console.log('Focused')
console.log('Not focused')
```
Renders:
console.log('Focused')
console.log('Focused')
console.log('Not focused')
transformerNotationErrorLevel
Use [!code error]
and [!code warning]
to mark a line with an error and warning levels.
```ts
console.log('No errors or warnings')
console.error('Error') // [!code error]
console.warn('Warning') // [!code warning]
```
- Outputs:
<span class="line highlighted error">
for errors - Outputs:
<span class="line highlighted warning">
for warnings - The outer
<pre>
tag is modified:<pre class="has-highlighted">
With some additional CSS rules, you can make it look like this:
console.log('No errors or warnings')
console.error('Error')
console.warn('Warning')
transformerRenderWhitespace
Render whitespaces (tabs and spaces) as individual spans, with classes tab
and space
.
With some additional CSS rules, you can make it look like this:
function block( ) {
space( )
tab( )
}
Example CSS
.vp-code .tab,
.vp-code .space {
position: relative;
}
.vp-code .tab::before {
content: '⇥';
position: absolute;
opacity: 0.3;
}
.vp-code .space::before {
content: '·';
position: absolute;
opacity: 0.3;
}
transformerMetaHighlight
Highlight lines based on the meta string provided on the code snippet.
```js {1,3-4}
console.log('1')
console.log('2')
console.log('3')
console.log('4')
```
Renders (with custom CSS rules):
console.log('1')
console.log('2')
console.log('3')
console.log('4')
- Outputs:
<span class="line highlighted">
for included lines.
transformerMetaWordHighlight
Highlight words based on the meta string provided on the code snippet.
```js /Hello/
const msg = 'Hello World'
console.log(msg)
console.log(msg) // prints Hello World
```
Renders (with custom CSS rules):
const msg = 'Hello World'
console.log(msg) // prints Hello World
Outputs: <span class="highlighted-word">Hello</span>
for matched words.
transformerCompactLineOptions
Support for shiki
's lineOptions
that is removed in shiki
.
transformerRemoveLineBreak
Remove line breaks between <span class="line">
. Useful when you set display: block
to .line
in CSS.
transformerRemoveNotationEscape
Transform // [\!code ...]
to // [!code ...]
. Avoid rendering the escaped notation syntax as it is.
transformerStyleToClass
Convert Shiki's inline styles to unique classes.
Class names are generated based on the hash value of the style object with the prefix/suffix you provide. You can put this transformer in multiple highlights passes and then get the CSS at the end to reuse the exact same styles. As Shiki doesn't handle CSS, it's on your integration to decide how to extract and apply/bundle the CSS.
For example:
import { transformerStyleToClass } from '@shikijs/transformers'
import { codeToHtml } from 'shiki'
const toClass = transformerStyleToClass({
classPrefix: '__shiki_',
})
const code = `console.log('hello')`
const html = await codeToHtml(code, {
lang: 'ts',
themes: {
dark: 'vitesse-dark',
light: 'vitesse-light',
},
defaultColor: false,
transformers: [toClass],
})
// The transformer instance exposes some methods to get the CSS
const css = toClass.getCSS()
// use `html` and `css` in your app
HTML output:
<pre class="shiki shiki-themes vitesse-dark vitesse-light __shiki_9knfln" tabindex="0"><code><span class="line">
<span class="__shiki_14cn0u">console</span>
<span class="__shiki_ps5uht">.</span>
<span class="__shiki_1zrdwt">log</span>
<span class="__shiki_ps5uht">(</span>
<span class="__shiki_236mh3">'</span>
<span class="__shiki_1g4r39">hello</span>
<span class="__shiki_236mh3">'</span>
<span class="__shiki_ps5uht">)</span>
</span></code></pre>
CSS output:
.__shiki_14cn0u {
--shiki-dark: #bd976a;
--shiki-light: #b07d48;
}
.__shiki_ps5uht {
--shiki-dark: #666666;
--shiki-light: #999999;
}
.__shiki_1zrdwt {
--shiki-dark: #80a665;
--shiki-light: #59873a;
}
.__shiki_236mh3 {
--shiki-dark: #c98a7d77;
--shiki-light: #b5695977;
}
.__shiki_1g4r39 {
--shiki-dark: #c98a7d;
--shiki-light: #b56959;
}
.__shiki_9knfln {
--shiki-dark: #dbd7caee;
--shiki-light: #393a34;
--shiki-dark-bg: #121212;
--shiki-light-bg: #ffffff;
}