Patterns / Media
Syntax
Markdown apps/gallery/src/patterns/syntax.rs
syntax::highlight(code, "rs") // -> Option<Vec<(Range<usize>, HighlightKind)>>Spans in document order, in bytes; everything outside them is plain text. A tag naming no grammar returns None and the block renders plain.
Installing it
use markdown::AppExt as _;
fn spans(language: &str, code: &str) -> Option<Vec<(Range<usize>, HighlightKind)>> {
syntax::highlight(code, language)
}
cx.set_highlighter(spans, syntax::lang::LANGS.iter().map(|lang| lang.name));markdown does not depend on syntax — the two meet at that function pointer. Note the argument order flips: Highlighter takes the language first, syntax::highlight takes the source first, and both are &str, so a swap compiles and silently colours nothing.
A language of your own
use syntax::lang::Lang;
static ZIG: Lang = Lang::new(
"zig",
&["zig"],
tree_sitter_zig::LANGUAGE,
include_str!("../queries/zig.scm"),
);
ZIG.highlight(code)Lang::new is const, so it sits beside the built-in rows and reaches the same query cache and HighlightKind vocabulary. Take the grammar's LanguageFn through syntax::tree_sitter_language — two tree-sitters in one graph are two unrelated types with the same name, and Lang::new rejects the stranger.
Features
syntax = { version = "0.0.2", default-features = false, features = ["rust"] }One per language, all on by default. Seven grammars down to one is a measured 12.4s clean build down to 3.5s. With none on, the table is empty and every block paints plain.
API
// syntax — eight languages, each answering to its fence aliases: rust/rs,
// python/py, typescript/ts, tsx/jsx/javascript/js, json/jsonc, go/golang,
// bash/sh/shell/zsh/console, toml.
/// Spans in document order, in bytes. Kinds become colours through
/// `SyntaxPalette`; a capture name with no slot degrades to `Variable`.
pub fn highlight(source: &str, language: &str) -> Option<Vec<(Range<usize>, HighlightKind)>>;
impl Lang {
/// `const`, so a language of your own sits beside the built-in rows and
/// reaches the same query cache and `HighlightKind` vocabulary.
pub const fn new(
name: &'static str,
aliases: &'static [&'static str],
grammar: LanguageFn,
query: &'static str,
) -> Self;
pub fn highlight(&'static self, source: &str) -> Option<Vec<(Range<usize>, HighlightKind)>>;
// ...
}// markdown — the seam. Nothing about it is tree-sitter: `Range<usize>` and
// `HighlightKind` are the whole vocabulary, so syntect or a regex pass is the
// same function with a different body.
pub trait AppExt {
fn set_highlighter(
&mut self,
highlighter: Highlighter,
languages: impl IntoIterator<Item = impl Into<SharedString>>,
);
}
// ...syntax is a peer crate, not part of the bezel facade, so an app that highlights nothing never compiles a grammar. A browser cannot run any of it — tree-sitter is C and wasm32-unknown-unknown has no libc — so the gallery highlights its samples in a build script and the wasm build looks the answer up.
The source is at apps/gallery/src/patterns/syntax.rs, and the highlighter it installs at apps/gallery/src/highlight.rs. Copy the file.