Syntax Highlighting
Choose from four syntax highlighting engines in unifast: tree-sitter, syntect, Shiki, and highlight.js.
unifast supports four syntax highlighting engines. Two run inside the Rust compiler (tree-sitter, syntect), and two run in JavaScript (Shiki, highlight.js).
Comparison
| tree-sitter | syntect | Shiki | highlight.js | |
|---|---|---|---|---|
| Runtime | Rust (built-in) | Rust (built-in) | JavaScript | JavaScript |
| Parsing | AST-based (tree-sitter grammars) | Regex-based (TextMate grammars) | Regex-based (VS Code grammars) | Regex-based (highlight.js grammars) |
| Speed | Fastest | Fast | Slower | Slower |
| Languages | 29 languages + syntect fallback | 100+ (TextMate) | VS Code grammars | 190+ |
| CSS output | Class-based (ts-*) | Class-based (sy-*) | Inline styles or class-based | Class-based (hljs) |
| Package | @unifast/node | @unifast/node | @unifast/shiki | @unifast/highlight |
| Best for | Precise highlighting, broad coverage | Simple setup, fast startup | Fine-grained theme control | highlight.js theme ecosystem |
Using tree-sitter
tree-sitter uses AST-based parsing for precise syntax highlighting. It runs inside the Rust compiler and supports 29 languages natively. For unsupported languages, it automatically falls back to syntect.
tree-sitter is included in @unifast/node — no separate install needed.
import { compile, treeSitter } from "@unifast/node";
const result = compile(
'```typescript\nconst x: number = 42;\n```',
{ plugins: [treeSitter()] }
);tree-sitter generates CSS class names prefixed with ts-. You need to provide CSS rules for these classes in your stylesheet.
Supported languages
TypeScript, TSX, JavaScript, HTML, CSS, Python, Rust, JSON, YAML, Go, Ruby, TOML, Swift, PHP, Java, Lua, Scala, Zig, Elixir, OCaml, R, Make, Nix, Regex, Erlang, Bash, C, C++, CMake
Language aliases are also supported (e.g. ts, py, rs, sh, yml, rb).
Using syntect
syntect uses TextMate grammars and runs entirely inside the Rust compiler — no additional JavaScript overhead.
syntect is included in @unifast/node — no separate install needed.
import { compile, syntect } from "@unifast/node";
const result = compile(
'```typescript\nconst x: number = 42;\n```',
{ plugins: [syntect()] }
);syntect generates CSS class names prefixed with sy-. You need to provide CSS rules for these classes in your stylesheet.
Using Shiki
Shiki uses VS Code’s TextMate grammar engine for accurate highlighting with theme support.
import { compile } from "@unifast/node";
import { createShikiPlugin } from "@unifast/shiki";
const shiki = await createShikiPlugin({
theme: "github-dark",
langs: ["typescript", "rust", "bash"],
});
const result = compile(
'```typescript\nconst x: number = 42;\n```',
{ plugins: [shiki] }
);Using highlight.js
@unifast/highlight uses lowlight (highlight.js) and runs as a HAST transform in JavaScript. It supports 190+ languages and works with any highlight.js theme.
import { compile } from "@unifast/node";
import { highlight } from "@unifast/highlight";
const result = compile(
'```typescript\nconst x: number = 42;\n```',
{ plugins: [highlight()] }
);highlight.js generates class names with the hljs prefix. Use any highlight.js theme CSS for styling.
Line Numbers
All engines support line numbers. Enable them in the compile options:
import { compile, treeSitter } from "@unifast/node";
const result = compile(source, {
plugins: [treeSitter()],
lineNumbers: true,
});Each line is wrapped in a <span> with a data-line attribute for CSS-based styling:
[data-line]::before {
content: attr(data-line);
display: inline-block;
width: 2rem;
text-align: right;
margin-right: 1rem;
color: #6b7280;
}See Also
syntect() - syntect API reference
createShikiPlugin() - Shiki API reference