lighthigh

A little highlight with no markup.

Theme

Text stays text.

No span around each token. Selection, undo and your framework keep the original text node.

Any lexer.

Prism, Shiki, Highlight.js, Lezer, or anything that returns { start, end, type }.

18 palettes.

GitHub to Catppuccin, Shiki theme colors, or your own.

Add a light high.

<pre><code data-lighthigh="javascript">
const answer = 42
</code></pre>

<script defer src="https://cdn.jsdelivr.net/npm/lighthigh@1"
  data-theme="github-light"></script>
npm i lighthigh prismjs
import highlight from 'lighthigh'
import { prism } from 'lighthigh/adapters.js'
import Prism from 'prismjs'

const code = document.querySelector('code')

highlight(code, source =>
  prism(Prism.tokenize(source, Prism.languages.js))
)
npm i lighthigh shiki
import highlight from 'lighthigh'
import { shiki } from 'lighthigh/adapters.js'
import { codeToTokens } from 'shiki'

const code = document.querySelector('code')
const result = await codeToTokens(code.textContent, {
  lang: 'javascript', theme: 'github-light'
})
const { tokens, theme } = shiki(result)
highlight(code, tokens, { theme })
npm i lighthigh highlight.js
import highlight from 'lighthigh'
import { hljs } from 'lighthigh/adapters.js'
import hljsCore from 'highlight.js/lib/core'
import javascript from 'highlight.js/lib/languages/javascript'

hljsCore.registerLanguage('javascript', javascript)
const code = document.querySelector('code')

highlight(code, source =>
  hljs(hljsCore.highlight(source, { language: 'javascript' }))
)
npm i lighthigh @lezer/javascript @lezer/highlight
import highlight from 'lighthigh'
import { lezer } from 'lighthigh/adapters.js'
import { parser } from '@lezer/javascript'
import { highlightTree, classHighlighter } from '@lezer/highlight'

const code = document.querySelector('code')

highlight(code, source =>
  lezer(parser.parse(source), highlightTree, classHighlighter)
)
npm i lighthigh gpu-lexer
import highlight from 'lighthigh'
import { parse } from 'gpu-lexer'

const code = document.querySelector('code')
const tokens = await parse(code.textContent)
highlight(code, tokens)

FAQ

How light?

The renderer is 1.4 KB gzipped, no dependencies. The script with 14 languages and 18 palettes is 24 KB.

Can I keep my themes?

Shiki colors work as-is. For others, pass a type → color map. Colors only: no bold or italics.

React, Vue, Sprae?

Call highlight(el, tokens) after render. It returns a cleanup for unmount.

Build time or a Worker?

Tokenize there, send [start, end, type] tuples, paint in the browser.