Line Numbers

How to enable line numbers in code blocks using Shiki.

ShikiMarkdownMDX

Preview

.ts
const code = `function greet() {
  console.log("Hello, World!");
}`;
const highlighter = await highlight();
const html = highlighter.codeToHtml(code, {
  lang: "javascript",
  theme: "one-light",
});

Installation

shadcn/ui

shadcn/ui Command
pnpm dlx shadcn@latest add https://code-blocks.pheralb.dev/r/shiki-show-line-numbers.json

Manual

  1. Copy the showLineNumbers transformer into your project:
.ts
import type { ShikiTransformer } from "shiki";

interface ShowLineNumbersOptions {
  /**
   * Always show line numbers regardless of meta properties
   * @default false
   */
  activateByDefault?: boolean;
}

const showLineNumbers = (
  options: ShowLineNumbersOptions = {},
): ShikiTransformer => {
  const { activateByDefault = false } = options;

  return {
    name: "AddLineNumbers",
    pre(node) {
      const rawMeta = this.options.meta?.__raw;
      const hasLineNumbersMeta = rawMeta?.includes("lineNumbers") ?? false;
      const addLineNumbers = activateByDefault || hasLineNumbersMeta;

      if (!addLineNumbers) {
        return;
      }

      const existingClass = node.properties.class;
      const className = "shiki-line-numbers";

      if (Array.isArray(existingClass)) {
        if (!existingClass.includes(className)) {
          existingClass.push(className);
        }
      } else if (typeof existingClass === "string") {
        const classes = existingClass.split(" ");
        if (!classes.includes(className)) {
          node.properties.class = `${existingClass} ${className}`;
        }
      } else {
        node.properties.class = [className];
      }
    },
  };
};

export { showLineNumbers };
  1. Customize the styles in your CSS file if needed:
shikiShiki Highlighter#styles

The main highlighter utility to render syntax highlighted code.

Usage

shikijs/rehype

  1. Import the transformer in your rehypeShiki plugin:
Rehype Shiki Options
import { showLineNumbers } from "@/utils/shiki/transformers/show-line-numbers";

const rehypeShikiOptions: RehypeShikiCoreOptions = {
  //...
  transformers: [showLineNumbers()],
};

export { rehypeShikiOptions };
  1. To enable line numbers in your code blocks, add the lineNumbers property to the code block in your MDX files:
MDX Code Block with Line Numbers
```ts lineNumbers
// Your TypeScript code here
```

highlight

  1. Import the transformer in your highlight():
Usage with highlighter
import { highlight } from "@/utils/shiki";
import { showLineNumbers } from "@/utils/shiki/transformers/show-line-numbers";

const code = `console.log('hello')`;
const highlighter = await highlight();
const html = highlighter.codeToHtml(code, {
  //...
  transformers: [showLineNumbers()],
});
  1. Add shiki-line-numbers class to the <pre> element:
.html
<pre class="shiki-line-numbers">
  <code>
    <!-- Highlighted code lines here -->
  </code>
</pre>

Properties

activateByDefault

By default, line numbers are only shown when the lineNumbers meta property is present in the MDX code block. You can activate line numbers for all code blocks by default by passing the activateByDefault option to the transformer:

Activating Line Numbers by Default
showLineNumbers({ activateByDefault: true })