Skip to content

Transformers

Shikiji used hast (a AST format for HTML) to process the result and generate the HTML.

You can provide your own transformers to customize the generated HTML by manipulating the hast tree. You can pass custom functions to modify the tree for different types of nodes. For example:

ts
import { addClassToHast(alias) function addClassToHast(node: Element, className: string | string[]): void
import addClassToHast, codeToHtml(alias) const codeToHtml: (code: string, options: CodeToHastOptions<BuiltinLanguage, BuiltinTheme>) => Promise<string>
import codeToHtml } from 'shikiji'

const codeconst code: string = await codeToHtml(alias) codeToHtml(code: string, options: CodeToHastOptions<BuiltinLanguage, BuiltinTheme>): Promise<string>
import codeToHtml('foo\bar', {
  lang(property) lang: "js": 'js',
  theme(property) CodeOptionsSingleTheme<BuiltinTheme>.theme: ThemeRegistration | ThemeRegistrationRaw | StringLiteralUnion<BuiltinTheme, string>: 'vitesse-light',
  transformers(property) transformers: {
    code(this: ShikijiTransformerContext, node: Element): void;
    line(this: ShikijiTransformerContext, node: Element, line: number): void;
    token(this: ShikijiTransformerContext, node: Element, line: number, col: number): void;
}[]: [
    {
      code(method) ShikijiTransformer.code?(this: ShikijiTransformerContext, hast: Element): void | Element(node(parameter) node: Element) {
        addClassToHast(alias) addClassToHast(node: Element, className: string | string[]): void
import addClassToHast(node(parameter) node: Element, 'language-js')
      },
      line(method) ShikijiTransformer.line?(this: ShikijiTransformerContext, hast: Element, line: number): void | Element(node(parameter) node: Element, line(parameter) line: number) {
        node(parameter) node: Element.properties(property) Element.properties: Properties['data-line'] = line(parameter) line: number
        if ([1, 3, 4].includes(method) Array<number>.includes(searchElement: number, fromIndex?: number | undefined): boolean(line(parameter) line: number))
          addClassToHast(alias) addClassToHast(node: Element, className: string | string[]): void
import addClassToHast(node(parameter) node: Element, 'highlight')
      },
      token(method) ShikijiTransformer.token?(this: ShikijiTransformerContext, hast: Element, line: number, col: number, lineElement: Element): void | Element(node(parameter) node: Element, line(parameter) line: number, col(parameter) col: number) {
        node(parameter) node: Element.properties(property) Element.properties: Properties['data-token'] = `token:${line(parameter) line: number}:${col(parameter) col: number}`
      },
    },
  ]
})

We also provide some common transformers for you to use, check shikiji-transforms for more details.

codeToHast

You can also got the intermediate hast to do your custom rendering without serialize them into HTML with codeToHast. You can also further integrate the ast the unified ecosystem.

js
const root = shiki.codeToHast(
  'const a = 1',
  { lang: 'javascript', theme: 'nord' }
)

console.log(root)
ts
{
  type: 'root',
  children: [
    {
      type: 'element',
      tagName: 'pre',
      properties: {
        class: 'shiki vitesse-light',
        style: 'background-color:#ffffff;color:#393a34',
        tabindex: '0'
      },
      children: [
        {
          type: 'element',
          tagName: 'code',
          properties: {},
          children: [
            {
              type: 'element',
              tagName: 'span',
              properties: { class: 'line' },
              children: [
                {
                  type: 'element',
                  tagName: 'span',
                  properties: { style: 'color:#AB5959' },
                  children: [ { type: 'text', value: 'const' } ]
                },
                {
                  type: 'element',
                  tagName: 'span',
                  properties: { style: 'color:#B07D48' },
                  children: [ { type: 'text', value: ' a' } ]
                },
                {
                  type: 'element',
                  tagName: 'span',
                  properties: { style: 'color:#999999' },
                  children: [ { type: 'text', value: ' =' } ]
                },
                {
                  type: 'element',
                  tagName: 'span',
                  properties: { style: 'color:#2F798A' },
                  children: [ { type: 'text', value: ' 1' } ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

Released under the MIT License.