# rehype-lumis (/integrations/rehype-lumis)

[Full example on GitHub](https://github.com/leandrocp/lumis/tree/main/packages/javascript/rehype-lumis/examples/rehype)

Use `@lumis-sh/rehype-lumis` when your stack already has a rehype stage.

## Install

```bash
npm install @lumis-sh/rehype-lumis @lumis-sh/lumis @lumis-sh/themes \
  @lumis-sh/wasm-javascript @lumis-sh/wasm-rust
```

## Example

```ts
import rehypeLumis from '@lumis-sh/rehype-lumis'
import {htmlInline} from '@lumis-sh/lumis/formatters'
import plaintext from '@lumis-sh/lumis/langs/plaintext'
import javascript from '@lumis-sh/wasm-javascript'
import latte from '@lumis-sh/themes/catppuccin_latte'

processor.use(rehypeLumis, {
  formatter: (language) =>
    htmlInline({language, theme: latte}),
  languages: [javascript, plaintext],
})
```

This plugin replaces `pre > code` blocks in HAST with Lumis HTML output.

## Full pipeline

```ts
import {unified} from 'unified'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import rehypeStringify from 'rehype-stringify'
import rehypeLumis from '@lumis-sh/rehype-lumis'
import {htmlInline} from '@lumis-sh/lumis/formatters'
import plaintext from '@lumis-sh/lumis/langs/plaintext'
import javascript from '@lumis-sh/wasm-javascript'
import rust from '@lumis-sh/wasm-rust'
import latte from '@lumis-sh/themes/catppuccin_latte'

const file = await unified()
  .use(remarkParse)
  .use(remarkRehype)
  .use(rehypeLumis, {
    formatter: (language) =>
      htmlInline({language, theme: latte}),
    languages: [javascript, rust, plaintext],
  })
  .use(rehypeStringify)
  .process(markdown)
```

## Options

- `formatter` - required callback that receives the detected block language and returns a Lumis formatter
- `languages` - optional language definitions to register up front with `createHighlighter`
- `defaultLanguage` - language for blocks that name none; defaults to `"plaintext"`. Set it to `false` to leave unlabeled blocks untouched. An omitted or `undefined` value uses the default.

For example, use `defaultLanguage: 'elixir'` to highlight unlabeled fences as
Elixir. A language named on the block takes precedence.

- `inlineCode` - also highlight inline `<code>` that names its language; defaults to `false`. See [Inline code](#inline-code).

To skip one block, add `nohighlight` or `no-highlight` to its `<pre>` or `<code>`
classes. Either class leaves the block untouched, regardless of its language or
the `defaultLanguage` option.

## Inline code

With `inlineCode: true`, a `<code>` outside a `<pre>` is highlighted when it names
its language. Inline code that names none is left alone, so prose in backticks is
never recolored. In Markdown, end the code span with a `{:lang}` suffix:

```md
Declare it with `const answer = 42{:javascript}`.
```

In HTML, or with a remark plugin that adds attributes, use a `language-*` class
or `data-language` on the `<code>`:

```html
<code class="language-javascript">const answer = 42</code>
```

The `<code>` keeps its attributes, and its text is replaced with the
[inline structure](/formatters#inline-code) of the formatter's output. The
suffix is removed first. The formatter's theme colors go on the `<code>` with
the `lumis` class, as a block's `<pre>` would get them:

```html
<code class="lumis" style="color: #4c4f69; background-color: #eff1f5;"><span style="color: #8839ef;">const</span> …</code>
```

`nohighlight` and `no-highlight` skip inline code too. A formatter that is not
one of the built-in HTML formatters leaves inline code alone.

## Behavior

- visits `pre` elements in HAST whose first child is a `code` element
- reads languages from `language-*` classes on the `<code>` or `<pre>` node, or from `data-language` / `language` properties
- replaces each block with Lumis HTML output
- preserves authored properties on the `<pre>` and `<code>` elements, including classes, styles, ids, ARIA attributes, and data attributes, by handing them to the formatter as `preAttrs` and `codeAttrs` so `class` unions and `style` appends exactly once
- keeps anything the authored `<pre>` held after its `<code>`, such as a copy button another plugin added
- loads whatever language a fence names from its installed package, the same as every other runtime, so `languages` is a prefetch list rather than an allow-list
- a fence naming a language that cannot be loaded renders as plain text with the configured formatter; the rest of the document still renders

Use it in:

- `unified`
- MDX pipelines
- Next.js MDX
- Astro markdown and MDX
- `react-markdown`