ferriki 0.14.0

Reusable native Rust syntax highlighter with TextMate grammars
Documentation

Part of Ferramenta, a family of Rust tools.

Ferriki

Powered by Sebastian Software CI Coverage gate >= 89% License: MIT OR Apache-2.0 Node >= 22.13.0 npm version crates.io docs.rs

Ferriki is a native syntax highlighter for Node.js and Rust. Shiki brought editor-grade highlighting to the web; Ferriki keeps its HTML API, grammars and themes and runs them on a Rust port of VS Code's TextMate tokenizer, so Rust programs, Node.js and Vite builds share one engine. Ferriki is in beta: until 1.0, a minor release can change the API, and the changelog lists each change.

Why Ferriki

  1. One engine, two languages. The ferriki crate is the highlighter, @ferriki/core runs it through a native addon, and Ferromark uses it to highlight Markdown and MDX fences natively. Shiki runs on JavaScript, with Oniguruma in WebAssembly or a JavaScript regex engine, and has no Rust form.
  2. Build-time macros in Vite 8. With @ferriki/vite, code() and <Code /> become highlighted HTML and CSS during the build; the browser receives no grammar and no engine. Only modules that import a macro are touched. Shiki's official content integrations work on Markdown; it has no build-time macro for components.
  3. Class-based output with nested scopes. styleMode: "classes" renders grammar scopes as nested spans for stylesheet themes. codeToHtmlWithCss derives the CSS from unchanged TextMate themes, and a theme map switches through data-ferriki-theme without highlighting again. Inspired by GitHub's PrettyLights and starry-night.
  4. Native highlighting, small installs. Ferroni, Oniguruma in Rust, runs grammar patterns as written. Each platform's addon is its own optional package, and grammars and themes download on first use from a release-pinned CDN, verified by SHA-256 and cached.
  5. Continuity. Shiki's codeToHtml, highlighters, singleton, themes map and custom grammars keep their call shapes, and the @shikijs/transformers notation plugs in as is. A pinned, unmodified mirror of Shiki v4.4.3's tests and the vscode-textmate v9.3.2 oracle check this in CI.

Load once. Highlight block after block. For a CMS, documentation server or site build, keep one highlighter with its loaded languages and themes. On our 14-file Blacksmith corpus, Ferriki produced the same HTML as both Shiki engines and ran 4.7× faster than Shiki/WASM on Linux x86-64 and 5.5× on macOS ARM64 with reused highlighters. These are measured corpus totals, not a guarantee for every workload. The benchmarks include both hosts, JSON/Astro, first-use timings and committed raw reports.

Keep the default regex prefilter for repeated work. For a short-lived process, regexPrefilter: false in Node or .with_regex_prefilter(false) in Rust avoids prefilter construction. In the recorded Node full-corpus run, it shortened first use by 35–37% but made repeated highlighting take 51–68% longer. See choosing the prefilter for the timing boundary and the singleton's reuse behavior.

Install and highlight

npm install @ferriki/core                  # Node.js
npm install @ferriki/core @ferriki/vite    # Vite 8, one shared version
cargo add ferriki --features remote        # Rust
import { codeToHtml } from "@ferriki/core";

const html = await codeToHtml("const answer = 42;", { lang: "typescript", theme: "github-dark" });
use ferriki::{Highlighter, RemoteAssets, RenderOptions, StandardAssetCatalogs, render_html};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut highlighter = Highlighter::builder()
        .with_assets(StandardAssetCatalogs::remote(RemoteAssets::default())?)
        .load_languages(["rust"])
        .load_themes(["github-dark"])
        .build()?;
    let tokens = highlighter.highlight("fn main() {}", "rust", "github-dark")?;
    println!("{}", render_html(&tokens, &RenderOptions::default()));
    Ok(())
}
// vite.config.ts
import react from "@vitejs/plugin-react";
import { ferriki } from "@ferriki/vite";

export default { plugins: [ferriki({ theme: "github-dark" }), react()] };

// Example.tsx: the build replaces <Code /> with highlighted HTML and its CSS.
import { Code } from "@ferriki/core/react/macro";

export const Example = () => <Code language="ts" source={`const answer = 42;`} />;

The first use of a language or theme downloads it, verifies it and caches it; asset loading covers mirrors and offline builds.

What you get

Feature Details
HTML output codeToHtml with Shiki's markup, inline styles and escaped source
Class-based CSS output styleMode: "classes", or codeToHtmlWithCss for { html, css }
Single and multi-theme theme, or a themes map switched by CSS variables or data-ferriki-theme
Transformers Shiki's hooks and decorations, including the @shikijs/transformers notation
260 grammars, 65 themes Loaded on demand and cached; a mirror or warm cache serves offline builds
Custom grammars and themes TextMate JSON with aliases and injections, validated before use
Rust crate and Ferromark ferriki: tokens, line HTML, class HTML; Ferromark's ferriki feature
Vite build-time macros @ferriki/vite: code() and <Code /> on Vite 8
Platforms Node.js 22.13.0 or newer, ESM-only; Linux x64/arm64 (glibc, musl), macOS arm64, Windows x64/arm64

Compatibility

Ferriki pins one release of each upstream, currently Shiki v4.4.3 and vscode-textmate v9.3.2. Both are mirrored unmodified and checked in CI, and every Shiki test is classified as supported, deferred or out of scope. HTML is the Node output: transformer callbacks receive token and HAST data, and the Rust crate returns tokens. Ferriki runs in Node.js and Rust; browsers get its build-time output. See the compatibility policy and the migration guide.

Documentation

Contributing

See CONTRIBUTING.md for the build, the test lanes and the repository layout, and adr/ for the decisions.

License

Licensed under either of MIT or Apache-2.0 at your option.

More from Ferramenta

Ferramenta — A family of Rust tools.

Engines

Tool Job
ferroni Oniguruma-compatible regex engine
ferromark Markdown to HTML, sanitized by default
ferrolex Spell checking for text and code
ferrocat Translation catalog engine
ferralk Glob matching and parallel filesystem walking
ferrugo PDF previews for untrusted files

Applications

Tool Job
palamedes Internationalization for TypeScript applications
dalo Your team's agent setup, versioned like code
ardo Documentation sites built with React