Current section

Files

Jump to
lumis README.md
Raw

README.md

# Lumis
<!-- MDOC -->
<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>
<div align="center">
<a href="https://hex.pm/packages/lumis">
<img alt="Hex Version" src="https://img.shields.io/hexpm/v/lumis">
</a>
<a href="https://hexdocs.pm/lumis">
<img alt="Hex Docs" src="http://img.shields.io/badge/hex.pm-docs-green.svg?style=flat">
</a>
<a href="https://opensource.org/licenses/MIT">
<img alt="MIT" src="https://img.shields.io/hexpm/l/lumis">
</a>
</div>
## Features
- **110+ Tree-sitter languages** - Fast, accurate, and updated syntax parsing
- **250+ built-in Neovim themes** - Updated and curated themes from the Neovim community
- **Built-in formatters** - HTML (inline/linked), Terminal (ANSI), Multi-theme (light/dark), BBCode
- **Custom formatters** - Build your own output
- **Language auto-detection** - File extension, shebang, and emacs-mode support
- **Line highlighting** - Mark and style individual lines, with custom HTML wrappers
- **Streaming-friendly** - Handles incomplete code
- **Parsers are dependencies** - Declared in `mix.exs`, compiled on first use
## Installation
Add Lumis and a parser for each language you highlight:
```elixir
def deps do
[
{:lumis, "~> 0.9"},
{:lumis_wasm_elixir, "~> 0.26.0"}
]
end
```
## Usage
```elixir
iex> Lumis.highlight!("Atom.to_string(:elixir)", formatter: {:html_inline, language: "elixir", theme: "github_light"})
```
The language is optional — Lumis detects it from the source, a filename, or a
shebang. The theme is optional too, but there is no default: without one,
`:html_inline` emits spans with no colors. Themes are named:
`theme: "github_light"`, or a `Lumis.Theme` struct built from your own JSON.
Formatters decide the output: `:html_inline`, `:html_linked`,
`:html_multi_themes`, `:terminal`, `:bbcode_scoped`, or your own.
For your own, implement `Lumis.Formatter` and build the output with
`Lumis.Formatter.HTML` or `Lumis.Formatter.ANSI`, which hold the same pieces the
built-in formatters use.
## Parsers
A parser is an ordinary dependency: add `{:lumis_wasm_elixir, "~> 0.26.0"}` and
`mix deps.get` delivers the bytes. Highlighting loads whatever a document
needs, including languages injected inside it, and keeps them for every
later request. Loading is global to the VM, so only the first process pays.
A language no dependency supplies is not fetched. A document's own language
missing is an error — `Lumis.ParserError` with the package to add — and a
language injected inside it missing costs that block its highlighting, not the
document. So add the ones a document can *inject* too, not only the ones it
names: Markdown fences reach
whatever language they label, HTML reaches `css` and `javascript`, and Elixir
reaches `comment`. A bundle package installs a set at once, such as
`{:lumis_wasm_bundle_web, "~> 0.1"}`, and the language catalog at
[docs.lumis.sh](https://docs.lumis.sh) lists every package name.
```elixir
# move the compile off the first request
Lumis.Languages.load(["elixir", "html", "javascript", "css"])
```
## Application startup
Warm parsers from your application's `start/2` so production does not compile
them on the first request:
```elixir
def start(_type, _args) do
Lumis.Languages.async_load(~w(elixir html javascript css))
Supervisor.start_link(children(), strategy: :one_for_one, name: MyApp.Supervisor)
end
```
It returns immediately, so the boot never waits on a compile, and a failed
warm-up is logged rather than able to stop the application from starting.
See the [deployment guide](https://lumis.hexdocs.pm/deployment.html) for the
full lifecycle example, bundles, and custom data directories.
The NIF is precompiled. Set `LUMIS_BUILD=1` to build it from source instead, or
`LUMIS_USE_LEGACY_ARTIFACTS=1` to take the legacy-CPU variant on a machine
without the newer instruction sets.
It downloads from GitHub Releases, mirrored to Cloudflare R2. Set
`config :lumis, artifact_source: :cloudflare` or `LUMIS_ARTIFACT_SOURCE=cloudflare`
to use the mirror when GitHub is down.
## Documentation
Guides for configuration, releases, Phoenix, formatters, themes and recipes are
at [docs.lumis.sh](https://docs.lumis.sh).
API reference: [hexdocs.pm/lumis](https://hexdocs.pm/lumis).
## Acknowledgements
* [Makeup](https://hex.pm/packages/makeup) for setting up the baseline and for the inspiration
* [Inkjet](https://crates.io/crates/inkjet) for the Rust implementation up to v0.2 and for the inspiration