Skip to content
sebastian-softwarePublic

About

Shiki-compatible syntax highlighting with a leaner Rust core and Node bindings.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

454 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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

Beautiful code. Head start included. Ferriki brings native, Oniguruma-compatible syntax highlighting to docs, blogs, and CMS content. Precompiled CDN packages are ready for production and enabled by default for standard grammars. Use familiar Shiki-style HTML calls in Node.js, call the Rust API directly, or prepare component examples with Vite 8 macros.

We ship the optimization

Native Oniguruma compatibility and precompiled delivery work together in Ferriki's production default. Standard language packages carry compiled regex programs and optimized static scanner automata alongside the syntax definition. The optimization becomes part of the download. Matching stays in Ferroni's native, Oniguruma-compatible engine, with no translation into JavaScript RegExp. Capture-dependent end and while patterns remain dynamic to preserve TextMate behavior.

Powered by Ferroni 2.8, we move static regex compilation and Eager scanner preparation into the asset pipeline. The CDN delivers that prepared work alongside the grammar. Each new process restores the scanners it needs, with their static optimizations already in place.

Keep the disk cache between builds and you keep the download, the unpacked packages, and the preparation. Prepared packages are the default with prefiltering on. Missing packages fall back to source, and dynamic patterns remain local. Only requested languages and required dependencies load; optional code-fence languages stay optional.

Sponsored by Sebastian Software, which currently covers Ferriki's CDN costs.

The payoff shows up at both ends: first HTML takes about half the time of Source Eager, while repeated highlighting keeps Eager's execution speed. In our fourteen-file Blacksmith corpus, Prepared starts within 6% of the unoptimized Source Off path on both hosts.

Same 14-file corpus, same HTML as Shiki/WASM Linux x86-64 macOS ARM64
First HTML vs. Shiki/WASM 4.2× faster 5.5× faster
Repeated highlighting vs. Shiki/WASM 3.7× faster 4.4× faster

Measured October 27, 2026 with Ferriki 1.3.0 and Ferroni 2.8.0. First HTML includes imports, setup, and rendering in a fresh process with the asset and decoded caches already populated; downloads, first cache fill, and process creation are excluded. These are highlighting measurements, not total build times. See every mode, machine, and raw result.

Choose your path

If you build with… Start with… Guide
Node.js npm install @ferriki/core Node.js package guide
Rust cargo add ferriki --features remote Rust API guide
Vite 8 and React npm install @ferriki/core @ferriki/vite Vite macros guide

See your first result in Node.js

Ferriki requires Node.js 22.13.0 or newer and uses ESM. npm installs the matching optional native package for Linux x64/arm64 (glibc or musl), macOS Apple Silicon, or Windows x64/arm64; keep optional dependencies enabled.

Install the package in your project:

npm install @ferriki/core

Language and theme payloads download from the release-pinned CDN on first use, are verified with SHA-256, and are cached locally. For offline builds, populate the cache ahead of time or use a mirror. See asset loading.

Save this complete ESM file as highlight.mjs, then run node highlight.mjs:

import { writeFile } from "node:fs/promises";
import { codeToHtml } from "@ferriki/core";

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

await writeFile("highlighted.html", html);
console.log("Saved highlighted.html. Open it in a browser to preview your code.");

Reuse one highlighter for repeat work

For a documentation build or CMS worker, create a highlighter with the languages and themes you need, then keep it around for the blocks you render. Calls with loaded languages and themes are synchronous. Create one highlighter per worker, and dispose it when that worker shuts down.

import { createHighlighter } from "@ferriki/core";

const highlighter = await createHighlighter({
  langs: ["typescript", "rust", "css"],
  themes: ["github-light", "github-dark"],
});

try {
  const html = highlighter.codeToHtml("const answer: number = 42;", {
    lang: "typescript",
    theme: "github-dark",
  });
  console.log(html);
} finally {
  highlighter.dispose();
}

What goes over the wire

Prepared scanners add download weight. Here is the tradeoff for the same requested languages, including their required dependencies:

Language Grammar-only CDN payload Total with prepared scanners
Rust 18 kB 58 kB · 3.2×
TypeScript 0.54 MB 4.65 MB · 8.6×
Markdown 61 kB 1.97 MB · 32.2×

Grammar-only is Ferriki's unoptimized grammar payload; Prepared keeps that payload and adds compiled programs and automata. Sizes are decimal and exclude themes and HTTP overhead. Optional fenced-code languages are not loaded. Keep the cache to reuse these downloads; decoded data takes additional disk space. See the exact sizes and source-definition comparison.

Memory looks good in the new capture, too. After 600 documents across twelve loaded languages, Prepared's whole-process RSS was 45% lower than Shiki/WASM on both hosts. For the large TypeScript workload, it was 67–69% lower. These are medians from six isolated processes per contender and workload, with identical HTML. See the memory measurements.

Syntax that follows your code

The catalog covers TypeScript, JSX and TSX, Vue, Svelte, Astro, and Angular; Rust, Python, Go, Java, C/C++, and C#; Markdown, MDX, SQL, JSON, YAML, and TOML; and build tools from shell scripts and Docker to Terraform and Nix.

TextMate grammars follow the context inside your code: embedded JavaScript and CSS in HTML, component expressions, tagged templates, and registered languages in Markdown fences. The catalog contains 67 standard entries for languages and formats, plus 27 support grammars for embeddings and injections, with 65 themes. Register custom TextMate grammars for syntax outside the curated catalog. Browse the coverage and examples.

More ways to use Ferriki

Need Ferriki provides
Shiki-shaped HTML codeToHtml, highlighters, singleton helpers, and transformer callbacks for Node.js
Stylesheet-driven themes Nested TextMate scope classes, generated CSS, and theme maps that switch without highlighting again
A grammar of your own Ferriki's curated catalog plus custom TextMate grammars, aliases, and injections; see the grammar guide
Code in Vite components code() and React <Code /> macros that prepare highlighted output at build time on Vite 8
Native Rust highlighting The ferriki crate: tokens, line HTML, and class-based HTML

Import @ferriki/core/macro or @ferriki/core/react/macro in the modules whose examples you want prepared. The build delivers highlighted output, and React <Code /> uses a small framework-free presentation module in the browser. Grammar payloads stay on the build side; see the Vite guide for the quickstart, SSR behavior, and limits.

Start with Rust

Enable the remote asset catalog with cargo add ferriki --features remote. This small program highlights a Rust function and prints HTML:

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

Compatibility

Ferriki follows semantic versioning: breaking changes to its public API require a major version; see the changelog. It pins Shiki v4.4.3 and vscode-textmate v9.3.2 as behavioral references. Shiki's tests run unchanged from a pinned mirror, each classified as supported, deferred, or out of scope; the tokenizer is checked against the full vscode-textmate oracle. Node's public output is HTML, while transformer callbacks can inspect token and HAST data. The Rust crate exposes tokens and HTML rendering. See the compatibility policy and Shiki migration guide.

Documentation

Contributing

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

License

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

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

Sebastian Software
TypeScript, React & Rust consulting
Experts in Agentic Software Development
Work with us · More open source

Copyright © 2026 Sebastian Software GmbH

About

Shiki-compatible syntax highlighting with a leaner Rust core and Node bindings.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages