ferriki 1.0.0

Reusable native Rust syntax highlighter with TextMate grammars
Documentation
<!-- This file is generated by mdtheme. Edit README.md.src instead. -->

Part of [Ferramenta](https://ferramenta.dev), a family of Rust tools.

# Ferriki

[![Powered by Sebastian Software](https://img.shields.io/badge/Powered_by-Sebastian_Software-005164?style=flat)](https://oss.sebastian-software.com) [![CI](https://github.com/sebastian-software/ferriki/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/sebastian-software/ferriki/actions/workflows/ci.yml)
[![Coverage gate >= 89%](https://img.shields.io/badge/coverage%20gate-%3E%3D%2089%25-brightgreen.svg)](./.github/workflows/ci.yml)
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](./LICENSE-MIT)
[![Node >= 22.13.0](https://img.shields.io/badge/node-%3E%3D22.13.0-brightgreen.svg)](https://nodejs.org)
[![npm version](https://img.shields.io/npm/v/%40ferriki%2Fcore.svg?logo=npm&label=npm)](https://www.npmjs.com/package/@ferriki/core)
[![crates.io](https://img.shields.io/crates/v/ferriki.svg?logo=rust)](https://crates.io/crates/ferriki)
[![docs.rs](https://img.shields.io/docsrs/ferriki.svg?logo=docs.rs&label=docs.rs)](https://docs.rs/ferriki)

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](node/ferriki/CHANGELOG.md) lists each change.

## Why Ferriki

1. **One engine, two languages.** The [`ferriki`]https://crates.io/crates/ferriki
   crate is the highlighter, `@ferriki/core` runs it through a native addon,
   and [Ferromark]https://ferromark.dev 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`]node/vite/README.md,
   `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]https://github.com/wooorm/starry-night.
4. **Native highlighting, small installs.**
   [Ferroni]https://ferroni.dev, 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](https://ferriki.dev/evidence/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](docs/ferriki-api.md#choosing-the-regex-prefilter) for
the timing boundary and the singleton's reuse behavior.

## Install and highlight

```sh
npm install @ferriki/core                  # Node.js
npm install @ferriki/core @ferriki/vite    # Vite 8, one shared version
cargo add ferriki --features remote        # Rust
```

```js
import { codeToHtml } from "@ferriki/core";

const html = await codeToHtml("const answer = 42;", { lang: "typescript", theme: "github-dark" });
```

```rust
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(())
}
```

```tsx
// 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](docs/asset-loading.md) 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`]https://docs.rs/ferriki: tokens, line HTML, class HTML; Ferromark's `ferriki` feature |
| Vite build-time macros | [`@ferriki/vite`]node/vite/README.md: `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](docs/compatibility.md) and
the [migration guide](docs/migrations/shiki-to-ferriki.md).

## Documentation

- [ferriki.dev]https://ferriki.dev: guides and [benchmarks]https://ferriki.dev/evidence/benchmarks
- [API reference]docs/ferriki-api.md, [class-based highlighting]docs/class-highlighting.md, [asset loading]docs/asset-loading.md
- [Inline code macros]docs/inline-code-macros.md, [code example authoring]docs/code-example-authoring.md
- [Rust API and Ferromark]docs/rust-api.md, [troubleshooting]docs/troubleshooting.md

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for the build, the test lanes and the
repository layout, and [`adr/`](adr/README.md) for the decisions.

## License

Licensed under either of [MIT](./LICENSE-MIT) or [Apache-2.0](./LICENSE-APACHE)
at your option.

### <a href="https://ferramenta.dev"><img src="https://raw.githubusercontent.com/sebastian-software/ferramenta/main/app/assets/brand/logo-light.svg" width="24" height="24" alt="" /> More from Ferramenta</a>

[Ferramenta](https://ferramenta.dev) — A family of Rust tools.

**Engines**

| Tool | Job |
| --- | --- |
| [ferroni]https://ferroni.dev | Oniguruma-compatible regex engine |
| [ferromark]https://ferromark.dev | Markdown to HTML, sanitized by default |
| [ferrolex]https://github.com/sebastian-software/ferrolex | Spell checking for text and code |
| [ferrocat]https://ferrocat.dev | Translation catalog engine |
| [ferralk]https://github.com/sebastian-software/ferralk | Glob matching and parallel filesystem walking |
| [ferrugo]https://github.com/sebastian-software/ferrugo | PDF previews for untrusted files |

**Applications**

| Tool | Job |
| --- | --- |
| [palamedes]https://palamedes.dev | Internationalization for TypeScript applications |
| [dalo]https://dalo.sh | Your team's agent setup, versioned like code |
| [ardo]https://ardo-docs.dev | Documentation sites built with React |

---

<p align="center">
  <a href="https://oss.sebastian-software.com"><img src="https://raw.githubusercontent.com/sebastian-software/oss.sebastian-software.com/main/app/assets/logo-software.svg" alt="Sebastian Software" width="160" /></a><br />
  TypeScript, React &amp; Rust consulting<br />
  Experts in Agentic Software Development<br />
  <a href="https://sebastian-software.de">Work with us</a> · <a href="https://oss.sebastian-software.com">More open source</a>
</p>

<p align="center">Copyright &copy; 2026 Sebastian Software GmbH</p>