# HTML Linked Formatter (/formatters/html-linked)

Class-based HTML that pairs with a CSS theme file. Smaller output than inline styles.

## Options

| Runtime | Options |
| --- | --- |
| Rust | `language`, `structure`, `pre_class`, `pre_attrs`, `code_attrs`, `highlight_lines`, `line_numbers`, `header` |
| Elixir | `language`, `structure`, `pre_class`, `pre_attrs`, `code_attrs`, `highlight_lines`, `line_numbers`, `header` |
| JavaScript / TypeScript | `language`, `structure`, `preClass`, `preAttrs`, `codeAttrs`, `highlightLines`, `lineNumbers`, `header` |
| Java | `withLang()`, `withFormatter(Formatter.HTML_LINKED)` |
| CLI | `--structure`, `--pre-class`, `--pre-attr`, `--no-pre-attr`, `--code-attr`, `--no-code-attr`, `--highlight-lines`, `--highlight-lines-class`, `--line-numbers`, `--header-open`, `--header-close` |

## Basic example

### JavaScript / TypeScript

```js
import '@lumis-sh/themes/css/catppuccin_frappe.css'
import {highlight} from '@lumis-sh/lumis'
import {htmlLinked} from '@lumis-sh/lumis/formatters'
import javascript from '@lumis-sh/wasm-javascript'

const html = await highlight(
  'const x = 1',
  htmlLinked({language: javascript}),
)
```

### Rust

```rust
use lumis::{
    highlight, languages::Language, HtmlLinkedBuilder,
};

let html = highlight(
    "const x = 1",
    HtmlLinkedBuilder::new()
        .language(Language::JavaScript)
        .pre_class(Some("demo".to_string()))
        .build()
        .unwrap(),
);
```

### Elixir

```elixir
Lumis.highlight!(
  "const x = 1",
  formatter:
    {:html_linked,
     language: "javascript", pre_class: "demo"}
)
```

### Java

```java
import io.roastedroot.lumis4j.core.Formatter;
import io.roastedroot.lumis4j.core.Lang;
import io.roastedroot.lumis4j.core.Lumis;

var lumis = Lumis.builder().build();

var highlighter = lumis.highlighter()
    .withLang(Lang.JAVASCRIPT)
    .withFormatter(Formatter.HTML_LINKED)
    .build();

var html = highlighter.highlight("const x = 1").string();
lumis.close();
```

### CLI

```bash
lumis highlight index.js --formatter html-linked
```


## Theme files

Use CSS theme files from:

- `@lumis-sh/themes/css/<theme>.css`
- `https://unpkg.com/@lumis-sh/themes/dist/css/<theme>.css`
- `priv/static/css/` in Elixir

See [CSS Theme Files](/themes/css-files) for the full setup.

## Output format

HTML Linked wraps each line in a span and uses CSS classes for token styling:

```html
<pre class="lumis"><code class="language-javascript" translate="no" tabindex="0"><span class="l-line" data-line="1"><span class="l-keyword">const</span> <span class="l-variable">x</span></span></code></pre>
```

- `<pre class="lumis">` is the outer wrapper
- `<code class="language-*">` identifies the language and keeps the block focusable
- `<span class="l-line" data-line="N">` wraps only a line's content
- `<span class="l-line-number">` opens the line when `line_numbers` is on, see [Line Numbers](/recipes/line-numbers)
- Lines are separated by `\n` text nodes; nothing follows the last line element
- A final source newline ends its line rather than adding an empty numbered line
- `<span class="...">` carries semantic highlight classes such as `l-keyword` or `l-string`

With `structure: "inline"` only the token spans are written, for a `<code>` or
other element of your own. See [Inline code](/formatters#inline-code).

The theme stylesheet gives each line the full code-block width, keeps empty
lines one row tall, and excludes line numbers from selection copy. Layout rules
use `@layer lumis`, so unlayered CSS can override them. See
[Line layout](/themes/css-files#line-layout) for custom line styles and
[Tailwind CSS](/recipes/tailwind-css) for cascade-layer ordering.

For CSS or formatters written for line divs, see
[HTML line markup migration](/migrate/html-lines).

## When to use it

- many code blocks
- shared stylesheet pipeline
- cacheable theme CSS
- smaller HTML output