Skip to main content

Shiki plugin for Lume

This plugin uses shiki library to search and syntax highlight the code of any <pre><code> element.

It exists a markdown-it plugin for Shiki, but we made the choice to be engine agnostic as highlight.js plugin and prism.js plugin.

Features:

  • CSS customization
  • Add extra CSS
  • Generate CSS variable by theme color
  • Use Dark/Light theme
  • Plugins like copy to clipboard, language label and title label

Check the demo directory.

Installation

Import this plugin in your _config.ts file to use it:

import lume from "https://deno.land/x/lume/mod.ts";
import shiki from "https://deno.land/x/lume_shiki/mod.ts";

const site = lume();

site.use(shiki(/* Options */));

export default site;

Example with a single theme

import lume from "https://deno.land/x/lume/mod.ts";
import shiki from "https://deno.land/x/lume_shiki/mod.ts";

const site = lume();

site.use(
  shiki({
    highlighter: {
      langs: ["javascript"],
      themes: ["github-light"],
    },
    theme: "github-light",
  })
);

export default site;

Example with multiple themes

import lume from "https://deno.land/x/lume/mod.ts";
import shikijfrom "https://deno.land/x/lume_shiki/mod.ts";

const site = lume();

site.use(
  shiki({
    highlighter: {
      langs: ["javascript"],
      themes: ["github-light", "github-dark"],
    },
    themes: {
      light: "github-light",
      dark: "github-dark",
    },
    defaultColor: "light",
  })
);

export default site;

Example with custom variable

import lume from "https://deno.land/x/lume/mod.ts";
import shiki from "https://deno.land/x/lume_shiki/mod.ts";

const site = lume();

site.use(
  shiki({
    highlighter: {
      langs: ["javascript"],
      themes: ["github-light", "github-dark"],
    },
    themes: {
      light: "github-light",
      dark: "github-dark",
    },
    defaultColor: "light",
    cssThemedVariables: [
      "border-color",
    ],
    extraCSS: `
:root {
  --shiki-dark-border-color: #ffaa22;
  --shiki-light-border-color: #0088ff;
}

.shiki {
  border: 5px var(--shiki-border-color) solid;
}
`
  })
);

export default site;

Common Options

type CommonOptions = {
  /**
   * The list of extensions this plugin applies to
   * @default [".html"]
   */
  extensions?: string[];

  /**
   * Set the css filename for all generated styles, Set to false to insert a style tag per page.
   * @default false
   */
  cssFile?: string | false

  /**
   * Highlighter options to configure theme and languages to load
   */
  highlighter?: BundledHighlighterOptions<BuiltinLanguage, BuiltinTheme>;

  /**
   * Inject extra
   */
  extraCSS?: string;

  /**
   * Transform the generated HAST tree.
   */
  transformers?: ShikiTransformer[];

  /**
   * Prefix of CSS variables used to store the color of the other theme.
   * @default '--shiki-'
   */
  cssVariablePrefix?: string;

  /**
   * Add variables that needs to be themed
   * You can optionaly give a defaultValue
   */
  cssThemedVariables?: (string | [variableSuffix: string, defaultValue: string])[];

  /**
   * Use dark/light mode
   */
  useColorScheme?: boolean;
}

Single theme options

type SingleThemeOptions = CommonOptions & {
  /**
   * Single theme used
   * @default 'vitesse-light'
   */
  theme: ShikiThemes<Themes>;
}

Multi themes options

type MultiThemeOptions = CommonOptions & {
  /**
   * A map of color names to themes.
   * This allows you to specify multiple themes for the generated code.
   *
   * @see https://github.com/antfu/shiki#lightdark-dual-themes
   */
  themes?: Record<string, ShikiThemes<Themes>>;

  /**
   * Add [data-color] attribute to body element
   * It does not work like shiki implementation
   *
   * @default false
   */
  defaultColor?: string | false;
}

Plugins

shikiCopy

This plugin adds a copy to clipboard button.

import lume from "https://deno.land/x/lume/mod.ts";
import shiki from "https://deno.land/x/lume_shiki/mod.ts";
import shikiCopy from "https://deno.land/x/lume_shiki/plugins/copy/mod.ts";

const site = lume();

site.use(
  shiki({
    highlighter: {
      langs: ["javascript"],
      themes: ["github-light"],
    },
    theme: "github-light",
  })
);

site.use(shikiCopy());

export default site;

You need to add this comment to your layout:

<head>
  ...
  <!-- shiki-imports -->
</head>

Options

interface Options {
  /**
   * Label position
   * @default "top"
   */
  position?: "top" | "bottom";

  /**
   * Icon order position
   */
  order?: number;

  /**
   * Content of the <button>
   */
  content?: (document: Document) => Node;

  /**
   * Override script from copy.js
   */
  scriptPath?: string;

  /**
   * Base directory of CSS files
   * Must ends with "/"
   * @default "/scripts/shiki/"
   */
  baseDir?: string;
}

shikiAttribute

This plugin adds an attribute to your code block.

Usage

import lume from "https://deno.land/x/lume/mod.ts";
import shiki from "https://deno.land/x/lume_shiki/mod.ts";
import shikiAttribute from "https://deno.land/x/lume_shiki/plugins/attribute/mod.ts";

const site = lume();

site.use(
  shiki({
    highlighter: {
      langs: ["javascript"],
      themes: ["github-light"],
    },
    theme: "github-light",
  })
);

site.use(shikiAttribute({
  attribute: "filename"
}));

export default site;

Example:

\`\`\`js{filename=main.js}
const msg = "Hello World";
\`\`\`

Options

interface Options {
  /**
   * HTML attribute to use for labeling
   * @default "label"
   */
  attribute?: string;

  /**
   * Label format
   */
  format?: (value: string, document: Document) => Node;

  /**
   * Label position
   * @default "top"
   */
  position?: "top" | "bottom";

  /**
   * Get default attribute value when not specified
   */
  getDefaultValue?: (el: Element, document: Document) => string | undefined;

  /**
   * attribre order position
   */
  order?: number;
}

shikiLang

This plugin adds language alias in the header/footer code block.

Usage

import lume from "https://deno.land/x/lume/mod.ts";
import shiki from "https://deno.land/x/lume_shiki/mod.ts";
import shikiLang from "https://deno.land/x/lume_shiki/plugins/lang/mod.ts";

const site = lume();

site.use(
  shiki({
    highlighter: {
      langs: ["javascript"],
      themes: ["github-light"],
    },
    theme: "github-light",
  })
);

site.use(shikiLang());

export default site;

Options

interface Options {
  /**
   * Label position
   * @default "top"
   */
  position?: "top" | "bottom";

  /**
   * Set lang order position
   */
  order?: number;
}

shikiCSS

This plugin adds extra CSS, CSS variables for shiki-transformers.

Usage

import lume from "https://deno.land/x/lume/mod.ts";
import shiki from "https://deno.land/x/lume_shiki/mod.ts";
import shikiLang from "https://deno.land/x/lume_shiki/plugins/lang/mod.ts";

const site = lume();

site.use(
  shiki({
    highlighter: {
      langs: ["javascript"],
      themes: ["github-light"],
    },
    theme: "github-light",
  })
);

site.use(shikiCSS());

export default site;

You need to add this comment to your layout:

<head>
  ...
  <!-- shiki-imports -->
</head>

Options

interface Options {
  /**
   * CSS files to includes
   */
  includes?: Record<string, boolean>;

  /**
   * Base directory of CSS files
   * Must ends with "/"
   * @default "/styles/shiki/"
   */
  baseDir?: string;
}