5 releases
| 0.1.3 | Feb 20, 2026 |
|---|---|
| 0.1.2 | Feb 19, 2026 |
| 0.1.1 | Jan 27, 2026 |
| 0.1.0 | Jan 23, 2026 |
| 0.0.1 | Jan 8, 2026 |
#1345 in Text processing
673 downloads per month
Used in 2 crates
147MB
4M
SLoC
Lumis
Syntax Highlighter powered by Tree-sitter and Neovim themes.
Features
- 70+ languages with Tree-sitter parsing
- 120+ Neovim themes
- HTML output with inline styles or CSS classes
- Multi-theme support for light/dark mode
- Terminal output with ANSI colors
- Language auto-detection via file extensions and shebangs
- Line highlighting with custom styling
- Custom HTML wrappers for code blocks
- Streaming-friendly - handles incomplete code gracefully
- Custom formatters via the
Formattertrait
Installation
Add to your Cargo.toml:
[dependencies]
lumis = "0.1"
Or install the CLI:
cargo install lumis
Quick Start
use lumis::{highlight, HtmlInlineBuilder, languages::Language, themes};
let code = r#"fn main() { println!("Hello, world!"); }"#;
let theme = themes::get("dracula").unwrap();
let formatter = HtmlInlineBuilder::new()
.lang(Language::Rust)
.theme(Some(theme))
.build()
.unwrap();
let html = highlight(code, formatter);
For streaming to files or other writers, use write_highlight():
use lumis::{write_highlight, HtmlInlineBuilder, languages::Language};
use std::fs::File;
let code = "fn main() { }";
let formatter = HtmlInlineBuilder::new()
.lang(Language::Rust)
.build()
.unwrap();
let mut file = File::create("output.html").unwrap();
write_highlight(&mut file, code, formatter).unwrap();
Formatters
Lumis provides four built-in formatters:
| Formatter | Output | Use When |
|---|---|---|
HtmlInlineBuilder |
HTML with inline styles | Standalone HTML, emails, no external CSS |
HtmlMultiThemesBuilder |
HTML with CSS variables | Light/dark mode, theme switching |
HtmlLinkedBuilder |
HTML with CSS classes | Multiple code blocks, custom styling |
TerminalBuilder |
ANSI escape codes | CLI tools, terminal output |
HTML Inline
Generates HTML with inline styles for each token:
use lumis::{highlight, HtmlInlineBuilder, languages::Language, themes};
let code = "puts 'Hello from Ruby!'";
let theme = themes::get("catppuccin_mocha").unwrap();
let formatter = HtmlInlineBuilder::new()
.lang(Language::Ruby)
.theme(Some(theme))
.pre_class(Some("code-block".to_string())) // Custom CSS class for <pre>
.italic(true) // Enable italic styles
.include_highlights(true) // Add data-highlight attributes
.build()
.unwrap();
let html = highlight(code, formatter);
HTML Linked
Generates HTML with CSS classes for styling (requires external CSS):
use lumis::{highlight, HtmlLinkedBuilder, languages::Language};
let code = "<div>Hello World</div>";
let formatter = HtmlLinkedBuilder::new()
.lang(Language::HTML)
.pre_class(Some("my-code".to_string()))
.build()
.unwrap();
let html = highlight(code, formatter);
CSS theme files are available in the css/ directory of the crate.
HTML Multi-Themes
Generates HTML with CSS custom properties for multiple themes, enabling light/dark mode support:
use lumis::{highlight, HtmlMultiThemesBuilder, languages::Language, themes};
use std::collections::HashMap;
let code = "const x = 42;";
let mut themes_map = HashMap::new();
themes_map.insert("light".to_string(), themes::get("github_light").unwrap());
themes_map.insert("dark".to_string(), themes::get("github_dark").unwrap());
let formatter = HtmlMultiThemesBuilder::new()
.lang(Language::JavaScript)
.themes(themes_map)
.default_theme("light") // or "light-dark()" for CSS function
.build()
.unwrap();
let html = highlight(code, formatter);
Use CSS media queries for automatic theme switching:
@media (prefers-color-scheme: dark) {
.lumis,
.lumis span {
color: var(--lumis-dark) !important;
background-color: var(--lumis-dark-bg) !important;
}
}
Terminal
Generates ANSI escape codes for terminal output:
use lumis::{highlight, TerminalBuilder, languages::Language, themes};
let code = "puts 'Hello from Ruby!'";
let theme = themes::get("dracula").unwrap();
let formatter = TerminalBuilder::new()
.lang(Language::Ruby)
.theme(Some(theme))
.build()
.unwrap();
let ansi = highlight(code, formatter);
println!("{}", ansi);
Line Highlighting
Highlight specific lines with custom styling:
use lumis::{highlight, HtmlInlineBuilder, languages::Language, themes};
use lumis::formatter::html_inline::{HighlightLines, HighlightLinesStyle};
let code = "line 1\nline 2\nline 3\nline 4";
let theme = themes::get("catppuccin_mocha").unwrap();
let highlight_lines = HighlightLines {
lines: vec![1..=1, 3..=4], // Highlight lines 1, 3, and 4
style: Some(HighlightLinesStyle::Theme),
class: None,
};
let formatter = HtmlInlineBuilder::new()
.lang(Language::PlainText)
.theme(Some(theme))
.highlight_lines(Some(highlight_lines))
.build()
.unwrap();
let html = highlight(code, formatter);
Custom HTML Wrappers
Wrap the formatted output with custom HTML elements:
use lumis::{highlight, HtmlInlineBuilder, languages::Language, formatter::HtmlElement};
let code = "fn main() { }";
let formatter = HtmlInlineBuilder::new()
.lang(Language::Rust)
.header(Some(HtmlElement {
open_tag: "<div class=\"code-wrapper\">".to_string(),
close_tag: "</div>".to_string(),
}))
.build()
.unwrap();
let html = highlight(code, formatter);
// Output: <div class="code-wrapper"><pre class="lumis">...</pre></div>
Themes
120+ themes from popular Neovim colorschemes:
use lumis::themes;
// Get a theme by name
let theme = themes::get("dracula").unwrap();
// Parse from string
let theme: themes::Theme = "catppuccin_mocha".parse().unwrap();
// List all available themes
for theme in themes::available_themes() {
println!("{} ({})", theme.name, theme.appearance);
}
// Filter by appearance
use lumis::themes::Appearance;
let dark_themes: Vec<_> = themes::available_themes()
.filter(|t| t.appearance == Appearance::Dark)
.collect();
Custom Themes
Load themes from JSON files or strings:
use lumis::themes;
// From file
let theme = themes::from_file("my_theme.json").unwrap();
// From JSON string
let json = r#"{
"name": "my_theme",
"appearance": "dark",
"revision": "v1.0.0",
"highlights": {
"keyword": { "fg": "#ff79c6", "bold": true },
"string": { "fg": "#f1fa8c" },
"comment": { "fg": "#6272a4", "italic": true }
}
}"#;
let theme = themes::from_json(json).unwrap();
Custom Formatters
Implement the Formatter trait to create custom output formats:
use lumis::{
formatter::Formatter,
highlight::highlight_iter,
languages::Language,
themes,
};
use std::io::{self, Write};
struct CsvFormatter {
language: Language,
theme: Option<themes::Theme>,
}
impl Formatter for CsvFormatter {
fn format(&self, source: &str, output: &mut dyn Write) -> io::Result<()> {
writeln!(output, "text,start,end,scope,fg")?;
highlight_iter(source, self.language, self.theme.clone(), |text, range, scope, style| {
let fg = style.fg.as_deref().unwrap_or("none");
let escaped = text.replace('"', "\"\"");
writeln!(output, "\"{}\",{},{},{},{}", escaped, range.start, range.end, scope, fg)
})
.map_err(io::Error::other)
}
}
CLI Usage
# Highlight a file
lumis highlight src/main.rs --theme dracula
# Highlight with a specific language
lumis highlight code.txt --language rust --theme github_dark
# Output to terminal (default)
lumis highlight src/main.rs --theme catppuccin_mocha
# List available themes
lumis themes
# List available languages
lumis languages
Language Feature Flags
By default, Lumis includes all languages. To reduce compile time and binary size, enable only the languages you need:
[dependencies]
lumis = { version = "0.1", default-features = false, features = ["lang-rust", "lang-javascript"] }
Available features:
all-languages- Enable all languages (default)lang-rust,lang-javascript,lang-typescript,lang-python, etc.
See the full list of language features in Cargo.toml.
Supported Languages
| Language | File Extensions |
|---|---|
| Angular | *.angular, component.html |
| Assembly | *.s, *.asm |
| Astro | *.astro |
| Bash | *.bash, *.sh, *.zsh, and more |
| C | *.c |
| C++ | *.cpp, *.cc, *.h, *.hpp |
| C# | *.cs |
| CSS | *.css |
| Clojure | *.clj, *.cljs, *.cljc |
| Dart | *.dart |
| Dockerfile | Dockerfile, *.dockerfile |
| Elixir | *.ex, *.exs |
| Erlang | *.erl, *.hrl |
| F# | *.fs, *.fsx |
| Gleam | *.gleam |
| Go | *.go |
| GraphQL | *.graphql |
| HTML | *.html, *.htm |
| Haskell | *.hs |
| HCL | *.hcl, *.tf |
| Java | *.java |
| JavaScript | *.js, *.mjs, *.cjs |
| JSON | *.json |
| Kotlin | *.kt |
| LaTeX | *.tex |
| Lua | *.lua |
| Markdown | *.md |
| Nix | *.nix |
| OCaml | *.ml, *.mli |
| PHP | *.php |
| Python | *.py |
| Ruby | *.rb |
| Rust | *.rs |
| SQL | *.sql |
| Scala | *.scala |
| Swift | *.swift |
| TOML | *.toml |
| TypeScript | *.ts |
| TSX | *.tsx |
| Vue | *.vue |
| YAML | *.yaml, *.yml |
| Zig | *.zig |
| ...and more | See docs for full list |
Available Themes
Themes are sourced from popular Neovim colorschemes:
- Catppuccin: catppuccin_frappe, catppuccin_latte, catppuccin_macchiato, catppuccin_mocha
- Dracula: dracula, dracula_soft
- GitHub: github_dark, github_light, github_dark_dimmed, and more
- Gruvbox: gruvbox_dark, gruvbox_light, and variants
- Tokyo Night: tokyonight_day, tokyonight_moon, tokyonight_night, tokyonight_storm
- One Dark: onedark, onedark_cool, onedark_darker, onelight
- Rose Pine: rosepine_dark, rosepine_dawn, rosepine_moon
- Nord: nord, nordic, nordfox
- Material: material_darker, material_oceanic, material_palenight
- Kanagawa: kanagawa_wave, kanagawa_dragon, kanagawa_lotus
- ...and 100+ more
Use themes::available_themes() or the CLI lumis themes for the complete list.
Acknowledgements
- Inkjet for the Rust implementation in early versions
- The Neovim community for the beautiful colorschemes
License
MIT
Dependencies
~8–125MB
~3.5M SLoC