lumis 0.1.2

Syntax highlighter powered by Tree-sitter and Neovim themes.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# Lumis

<p align="center">
  Syntax Highlighter powered by Tree-sitter and Neovim themes.
</p>

<p align="center">
  <a href="https://lumis.sh">https://lumis.sh</a>
</p>

<p align="center">
  <a href="https://crates.io/crates/lumis"><img src="https://img.shields.io/crates/v/lumis" alt="Crates.io"></a>
  <a href="https://docs.rs/lumis"><img src="https://img.shields.io/docsrs/lumis" alt="docs.rs"></a>
  <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue" alt="License"></a>
</p>

## 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 `Formatter` trait

## Installation

Add to your `Cargo.toml`:

```toml
[dependencies]
lumis = "0.1"
```

Or install the CLI:

```sh
cargo install lumis
```

## Quick Start

```rust
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()`:

```rust
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:

```rust
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):

```rust
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:

```rust
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:

```css
@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:

```rust
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:

```rust
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:

```rust
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:

```rust
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:

```rust
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:

```rust
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

```sh
# 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:

```toml
[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](https://github.com/leandrocp/lumis/blob/main/crates/lumis/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]https://crates.io/crates/inkjet for the Rust implementation in early versions
- The Neovim community for the beautiful colorschemes

## License

MIT