Part of Ferramenta, a family of Rust tools.
Ferriki
Ferriki provides Shiki-shaped HTML syntax highlighting through a lean Rust core and Node bindings.
It keeps familiar highlighter factories and HTML calls, while removing the old JS/WASM multi-engine direction from the runtime. The goal is simple: keep the developer experience familiar, move the heavy lifting into Rust, and end up with a smaller, cleaner architecture that is easier to reason about and easier to ship.
Why Ferriki
- Shiki-shaped HTML API: reusable highlighters and familiar highlight options support common migrations.
- Rust-first by design: grammar handling, theme application, state management, and rendering belong in the native core.
- Standard language and theme assets load lazily from a release-pinned CDN, so their payloads stay out of the packages.
- Leaner runtime shape: no product dependency on the historical JS/WASM engine stack.
- Verifiable compatibility: the Node layer is checked against a strict mirrored Shiki release-tag suite, while the tokenizer is checked against a pinned vscode-textmate oracle.
Ferriki is for teams that like Shiki's familiar highlighter and HTML flow and want a cleaner native foundation underneath.
Product Scope
Ferriki is intentionally narrow right now.
| Area | Status | Notes |
|---|---|---|
| Core highlighting runtime | Integrated | Native Rust core, Node bindings, Shiki-shaped HTML rendering API |
| HTML output | Primary Node path | codeToHtml renders HTML; styleMode: "classes" adds nested scope classes; codeToHtmlWithCss also returns resolved theme CSS |
| HAST and token output | Removed before 1.0 | Standalone Node methods are removed; typed token/HAST data remain available to HTML transformer callbacks, and Rust token APIs remain public |
| Transformers | Integrated | User-supplied JavaScript hooks receive internal token/HAST data while rendering HTML (ADR 0008) |
| Optional Vite adapter | Available | @ferriki/vite highlights marked HTML and static JSX during Vite transforms, outside the core runtime |
colorized-brackets, markdown-it, rehype, and VitePress integrations |
Out of scope | These remain optional adapter projects, not Ferriki core exports |
Removing public Node HAST and token methods before 1.0 is an intentional breaking divergence from Shiki, with no deprecated aliases or compatibility package. See ADR 0017 and the migration guide for the supported path.
The mirrored Shiki workspace under node/compat/upstream/shiki exists to verify compatibility claims. It is not a statement that every mirrored package is a Ferriki feature.
Products
This repository has a Rust library and a Node package:
ferriki(repository root package): reusable Rust highlighter and renderernode/ferriki: the Node-facing package surface
The private ferriki-core crate hosts the N-API binding
over the same Rust runtime.
Repository Layout
src: theferrikicrate, native highlighter and asset catalogscrates/ferriki-core: N-API hostnode/ferriki: Node packagenode/compat/harness: Ferriki-specific compatibility gluenode/compat/upstream/shiki: strict upstream Shiki mirrornode/compat/upstream/vscode-textmate: strict tokenizer source and test oracleadr: architecture decision records (index)
Contributor workflow, test lanes, and the mirror rules are documented in
CONTRIBUTING.md.
User-facing documentation lives in the docs/ directory:
- Ferriki API reference
- Rust API and Ferromark integration
- Shiki migration guide
- Compatibility and support policy
- Troubleshooting
- Code example authoring
- Ferromark + Ardo example
The repository root is intentionally Rust-first. All Node, npm, and upstream
compatibility machinery lives under node.
Quick Start
Prerequisites: a stable Rust toolchain (cargo), Node.js >= 22.13.0, and pnpm
(the pinned version in node/package.json is picked up via corepack).
Rust:
Node (build:native compiles the Rust core and copies the addon into the
package):
The compatibility workspace contains upstream prepare scripts that rewrite
generated files. Installs intentionally skip package lifecycle scripts; the
explicit prepare:compat command runs those generators in a temporary
checkout and keeps the tracked mirror immutable.
The TextMate compatibility lane runs selected, unchanged Shiki tests with
honest aliases so every highlighted result passes through the native addon.
The broader test:ferriki-compat:core lane also runs the Ferriki-owned API,
error, catalog, registration, multi-theme, transformer, token-state, packaging,
and Ferromark/Ardo contract checks. Upstream cases outside that accepted
boundary remain explicitly classified in the compatibility manifest.
Class-based output (next release)
Inspired by GitHub's PrettyLights and wooorm's starry-night.
Use styleMode: "classes" for nested scope classes and custom CSS.
codeToHtmlWithCss returns { html, css } using unchanged TextMate themes,
including theme maps that switch via data-ferriki-theme without retokenizing.
See the class-based highlighting guide for examples and integration details.
Compatibility
Ferriki tracks one approved Shiki release tag at a time — currently
Shiki v4.4.3 (machine-readable source of truth:
node/compat/upstream/shiki/.source.json).
- Upstream-derived files under
node/compat/upstream/shikiare mirrored, not hand-edited. - vscode-textmate source and tests under
node/compat/upstream/vscode-textmateare likewise pinned and never hand-edited. - Ferriki-specific behavior lives outside that mirror, mainly in
node/compat/harnessand the Ferriki product paths. - “Shiki-compatible” in this repository means compatibility is intended to be checked, not just claimed.
- Compatibility coverage is broader than product scope. Ferriki may still test selected optional upstream adapters separately, but that does not make them first-class Ferriki features.
Status
The native TextMate runtime from issue #30 is implemented. It is a mechanical port of pinned vscode-textmate v9.3.2 onto the Scanner API of Ferroni, integrated with Ferriki's asset catalogs, native renderer, N-API host, and focused Node surface. Its inner vscode-textmate oracle and honest Shiki v4.4.3 structural gate are green.
The accepted API contract and its focused checks own token/state, lifecycle, transformer, and registration behavior. Upstream adapter fixtures that do not describe Ferriki's native boundary remain classified as explicit non-goals. The current core direction is:
- Rust owns runtime behavior
- Node is the thin facade and compatibility layer
- optional ecosystem adapters do not define the core product boundary or release gate
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 |