@ferriki/core
v0.12.0
Published
native syntax highlighting with HTML and CSS-class output
Maintainers
Readme
Ferriki
Ferriki is native syntax highlighting with HTML and CSS-class output for Node.js: Shiki's HTML API, grammars and themes on a Rust engine. Shiki brought editor-grade highlighting to the web; Ferriki runs the same TextMate grammars on a Rust port of VS Code's tokenizer and Ferroni, Oniguruma in Rust, without WebAssembly or regex translation. Ferriki is in beta: until 1.0, a minor release can change the API.
Install
npm install @ferriki/coreFerriki requires Node.js 22.13.0 or newer and is ESM-only. The package declares one optional native package for each supported target (Linux x64 and arm64 with glibc or musl, macOS arm64, Windows x64 and arm64), and the package manager installs the matching one. The main package ships no native addon of its own, so keep optional dependencies enabled in production installs.
The package ships no grammar or theme payloads either. The first time a
language or theme is loaded, Ferriki downloads it from assets.ferriki.dev,
pinned to this release and verified by SHA-256, and caches it in
node_modules/.cache/ferriki. Offline builds reuse a populated cache or point
FERRIKI_ASSETS_BASE_URL at a mirror; FERRIKI_ASSETS_REMOTE=0 turns
downloads off. See asset loading
for cache, proxy and certificate settings.
Highlight code
Use the shorthand for one-off highlighting:
import { codeToHtml } from "@ferriki/core";
const html = await codeToHtml('console.log("Hello")', {
lang: "javascript",
theme: "nord",
});Highlight once, reuse
A highlighter loads its languages and themes once; calls on it are synchronous.
Call highlighter.dispose() when you are done, or declare it with using in
TypeScript:
import { createHighlighter } from "@ferriki/core";
const highlighter = await createHighlighter({
langs: ["javascript", "typescript"],
themes: ["vitesse-light", "vitesse-dark"],
});
const html = highlighter.codeToHtml("const answer = 42", {
lang: "typescript",
theme: "vitesse-dark",
});getSingletonHighlighter() shares one highlighter per process, and the
shorthand functions use it. Custom languages and themes take Shiki's TextMate
registration shapes in langs and themes and are validated before they reach
the native engine. Languages embedded by a grammar load with it; lazy
embeddings load after an explicit loadLanguage. The synchronous factories
accept already-resolved names and registrations only.
Light and dark themes
Pass an ordered theme map. With defaultColor: false, Ferriki emits CSS
variables for every theme and leaves the choice to your stylesheet:
const html = highlighter.codeToHtml("const answer = 42", {
lang: "typescript",
themes: { light: "vitesse-light", dark: "vitesse-dark" },
defaultColor: false,
});Class-based output
styleMode: "classes" renders every grammar scope as a nested span with
readable classes such as tok-string, for your own stylesheet.
codeToHtmlWithCss returns { html, css } with the CSS derived from unchanged
TextMate themes. With a theme map, data-ferriki-theme="dark" on the block or
an ancestor switches themes without highlighting again:
import { codeToHtmlWithCss } from "@ferriki/core";
const { html, css } = await codeToHtmlWithCss("const answer = 42", {
lang: "typescript",
themes: { light: "github-light", dark: "github-dark" },
});The mode is inspired by GitHub's PrettyLights and wooorm's starry-night. The class-based highlighting guide covers the class names, custom CSS and theme switching.
Transformers
Shiki transformers and decorations run in JavaScript while Ferriki renders
HTML, and their callbacks receive typed token and HAST data. The notation
helpers from @shikijs/transformers for focus, highlights, diffs and word
highlights work with them.
Build-time macros
@ferriki/vite
turns code() from @ferriki/core/macro and <Code /> from
@ferriki/core/react/macro into highlighted HTML and CSS during a Vite 8
build, so the browser receives neither a grammar nor a highlighter. Install it
with the same version as this package:
npm install @ferriki/core @ferriki/viteSee the inline code macros guide.
Rust
The same engine is the ferriki crate; see
the Rust API guide.
Compatibility
Ferriki follows Shiki v4.4.3. Shiki's own tests run unchanged against the
native addon from a pinned mirror, each one classified as supported, deferred
or out of scope, and the tokenizer is checked against the complete
vscode-textmate v9.3.2 oracle. HTML is the package's output; token and HAST
data reach transformer callbacks. Terminal ANSI input is rejected with
ShikiError instead of rendered.
Documentation
- Ferriki API reference
- Shiki migration guide
- Compatibility policy: the Shiki baseline and the supported targets
- Troubleshooting: native-loader and offline failures
- Code example authoring: focus, highlights, diffs and copy behavior
- ferriki.dev: guides and benchmarks
License
Licensed under either of MIT or Apache-2.0 at your option.
ferriki is part of the Ferramenta family — A family of Rust tools.
Siblings: 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 · palamedes — Internationalization for TypeScript applications · dalo — Your team's agent setup, versioned like code · ardo — Documentation sites built with React.
