Start with Rust
Bring editor-grade code highlighting to your Rust app. Start with the opt-in remote feature, load the languages you need, and render ready-to-use HTML.
Highlight your first snippet
Create a binary crate, add Ferriki with remote assets enabled, and save the program
below as src/main.rs:
cargo new ferriki-demo
cd ferriki-demo
cargo add ferriki --features remote
The optional remote feature loads standard assets from Ferriki's release-pinned asset
service. On first use, Ferriki downloads missing payloads, verifies their size and
SHA-256 against the release manifest, then caches them.
use ferriki::{Highlighter, RemoteAssets, RenderOptions, StandardAssetCatalogs, render_html};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let assets = StandardAssetCatalogs::remote(RemoteAssets::default())?;
let mut highlighter = Highlighter::builder()
.with_assets(assets)
.load_languages(["rust"])
.load_themes(["github-dark"])
.build()?;
let tokens = highlighter.highlight(
"fn main() { println!(\"Hello, Ferriki!\"); }",
"rust",
"github-dark",
)?;
let html = render_html(&tokens, &RenderOptions::default());
println!("{html}");
Ok(())
}
Run it with cargo run. The program prints a standalone <pre><code> HTML block
with inline theme styles. This remote path needs no Ferriki checkout or
assets/standard directory, and the crate runs without Node.js or an N-API runtime.
Keep highlighting
Reuse one Highlighter across code blocks and documents. It loads the requested
languages and themes when you build it, then keeps those decoded assets in memory; the
verified payloads also remain in the disk cache for later runs.
A highlighter is !Send: move the StandardAssetCatalogs to a worker thread and build
one highlighter there. Custom grammars and themes register through
LanguageRegistration and ThemeData, or from JSON with register_language_json and
register_theme_json.
Keep the default regex prefilter for a CMS worker or a build that highlights many
blocks. For a short-lived highlighter, add .with_regex_prefilter(false) to the builder
to skip prefilter construction. This choice applies to loaded grammars, including
embeddings and injections; it does not change matching or colors. The
benchmark page shows the setup/reuse tradeoff measured through
the Node API. Its percentages do not measure standalone Rust calls.
Run offline
After one run has filled the cache, set FERRIKI_ASSETS_REMOTE=0 to use cached
payloads only. Keep the same FERRIKI_CACHE_DIR if you chose a custom cache path; a
cache miss returns AssetUnavailable. FERRIKI_ASSETS_BASE_URL points at a mirror.
The remote feature is unavailable on wasm32.
For a deployment that provisions assets itself, use a release-matched asset directory or embed the payloads. The Rust API guide details both options and release-digest verification.
With Ferromark
Ferromark, the Markdown parser of the
same family, highlights fenced code with this crate natively: no Node.js
process and no N-API boundary in between. Its optional ferriki feature
provides FerrikiHighlightHooks for the HTML renderer and FerrikiJsxHooks
for the JSX renderer.
To write your own hook, implement HtmlRenderHooks::highlight_code_block: it
receives each fenced block's code and language. Ferriki highlights the lines;
Ferromark keeps the wrapper, the fence metadata and the fallback for unknown
languages.
use ferriki::{Highlighter, RenderOptions};
use ferromark::{CodeHighlightInput, HighlightedCodeBlock, HtmlRenderHooks};
struct FerrikiHook<'a> {
highlighter: &'a mut Highlighter,
theme: &'a str,
}
impl HtmlRenderHooks for FerrikiHook<'_> {
fn highlight_code_block(
&mut self,
input: CodeHighlightInput<'_>,
) -> Option<HighlightedCodeBlock> {
let language = input.language?.to_ascii_lowercase();
let highlighted = self
.highlighter
.highlight_html_lines(input.code, &language, self.theme, &RenderOptions::default())
.ok()?;
Some(
HighlightedCodeBlock::new(highlighted.lines)
.with_colors(highlighted.foreground, highlighted.background),
)
}
}
Returning None makes Ferromark render escaped plain code. The full contract
is in docs/rust-api.md; the API itself is on
docs.rs/ferriki.
If you are comparing Rust HTML highlighters, see Ferriki and syntect. That comparison covers grammar and theme inputs, assets, language detection, output formats, and the limits of the current timing evidence. Ferriki currently renders HTML; it has no ANSI renderer.