Your editor’s grammar, on your page.
TextMate tokenization, embedded languages and grammar injections, with familiar Shiki-style HTML calls. The detail comes from the grammar your editor uses.
See the languages in actionTextMate syntax highlighting for Node.js, Rust and Vite. Keep the grammars and themes your editor uses, with a native engine and prepared language packages that arrive ready to work.
TextMate tokenization, embedded languages and grammar injections, with familiar Shiki-style HTML calls. The detail comes from the grammar your editor uses.
See the languages in actionStandard language packages include compiled regex programs and prepared scanners. Restore that work on startup, then highlight with native Rust.
How the preparation travelsHTML, CSS and JavaScript share a page. Ferriki follows each language into the next, down to the template literal inside the script.
<!doctype html>
<html lang="en">
<head>
<style>
.card {
color: rebeccapurple;
}
</style>
</head>
<body>
<button class="card" data-name="Ferriki">Say hello</button>
<script type="module">
const button = document.querySelector(".card");
button.addEventListener("click", () => {
const name = button.dataset.name ?? "you";
alert(`Hello, ${name}!`);
});
</script>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<style>
.card {
color: rebeccapurple;
}
</style>
</head>
<body>
<button class="card" data-name="Ferriki">Say hello</button>
<script type="module">
const button = document.querySelector(".card");
button.addEventListener("click", () => {
const name = button.dataset.name ?? "you";
alert(`Hello, ${name}!`);
});
</script>
</body>
</html>
The highlighted result comes straight from Ferriki. Its tokenizer keeps each embedded language in context, so a string inside JavaScript can receive a different treatment from the surrounding markup.
Standard language packages carry compiled regex programs and prepared static scanners. They are ready for production and enabled by default.
Matching runs in Ferroni’s native, Oniguruma-compatible engine, without translating patterns to JavaScript RegExp. A fresh process restores the prepared work, rather than rebuilding every static scanner.
The preparation adds download weight: Rust needs about 58 kB in total versus 18 kB for its grammar alone. TypeScript with required embeddings needs 4.65 MB versus 0.54 MB; Markdown needs 1.97 MB versus 61 kB. Decimal payload sizes, excluding themes and HTTP overhead. Keep the disk cache to reuse downloads; decoded data also takes disk space. Compare the download sizes.
Missing packages fall back to source. Capture-dependent end and while patterns stay dynamic to preserve TextMate behavior. Only requested languages and required dependencies load; optional code-fence languages stay optional.
Sponsored by Sebastian Software, which currently covers Ferriki’s CDN costs.
Keep an example beside the React component it explains. During a Vite 8 build, Ferriki turns that example into highlighted HTML and CSS.
import { Code } from "@ferriki/core/react/macro";
export function Answer() {
return (
<Code
language="ts"
source={`export const answer = 42;`}
/>
);
}
export const answer = 42;The prepared block is the adapter’s actual output. Your readers receive the finished example; the browser does not need to run a highlighter. Inspect the full transformed module.
Class-based output keeps token roles in the markup and theme rules in a stylesheet. Changing a theme does not mean highlighting the code again.
"hello"
Change the theme or enable the CSS override. The highlighted token elements stay in place.
Start with Shiki-style HTML calls in Node.js, or use the same TextMate engine directly from Rust.
import { createHighlighter } from "@ferriki/core";
const highlighter = await createHighlighter({
langs: ["typescript"],
themes: ["github-dark"],
});
try {
const html = highlighter.codeToHtml("const answer = 42;", {
lang: "typescript", theme: "github-dark",
});
console.log(html);
} finally {
highlighter.dispose();
}The Rust crate’s remote feature loads the release-pinned grammar and theme catalog. Both entry points use the same native engine.
Load a highlighter once, then keep using it. On our fourteen-file repository corpus, Ferriki delivered identical HTML to Shiki/WASM on both measured hosts.
With the languages and themes already loaded, repeated HTML calls were 3.7–4.4× faster than Shiki/WASM across Linux x86-64 and macOS ARM64. These are highlighting measurements, rather than total build times; another workload or machine can give different results.
Prepared packages also used about 45% less whole-process RSS after 600 documents across twelve loaded languages on both hosts. Six isolated processes per contender produced identical HTML. The detailed report keeps the startup cost, download weight and measurement conditions alongside the results.
TypeScript and TSX. Vue, Svelte, Astro and Angular. Rust, Python, Go and C/C++. TextMate grammars follow embedded languages and component expressions.
codeToHtml, reusable highlighters, the singleton, the themes map, language aliases, transformers and decorations.
67 standard language and format entries, plus 27 support grammars for embeddings and injections. Required dependencies load with the host; optional code-fence languages stay optional.
Register your own JSON grammars and themes, with embedded languages and injections.
Nested scope classes and themes as a stylesheet, through styleMode: "classes" or codeToHtmlWithCss. Switch themes with data-ferriki-theme, without highlighting again.
code() and <Code /> become HTML and CSS during the build through @ferriki/vite. Other build tools have no adapter.
cargo add ferriki gives Rust the same engine, with no Node.js in the process. Ferromark highlights Markdown and MDX code fences with it natively.
Linux x64 and arm64 (glibc and musl), macOS on Apple Silicon, Windows x64 and arm64, on Node.js 22.13 or newer.
Render in Node.js or Rust at build time or on the server. Pages receive HTML and CSS ready to display, with highlighting handled before the code reaches the browser.
Choose a language and a theme. Ferriki brings the prepared scanners and turns your code into HTML and CSS, ready for the page.