microlighter README

The project's README from github.com/davatron5000/microlighter. As one markdown file: README.md.

MicroLighter

CI License: MIT

A tiny, dependency-free syntax highlighter for the web.

MicroLighter uses the CSS Custom Highlight API and TextMate grammars. It highlights code without adding a <span> around every token, so your markup stays clean and editable.

Features

Install

npm install microlighter

Quick start

Add a language class to your code:

<pre><code class="language-javascript">const answer = 42;</code></pre>

Import a theme and run the highlighter:

import "microlighter/themes/github.css";
import { highlightAll } from "microlighter";

document.body.dataset.syntaxTheme = "github";
await highlightAll();

That's it. MicroLighter finds every pre > code block with a supported language and highlights it.

Usage

Programmatic API

The main package exports highlightAll(). Importing it has no side effects.

import { highlightAll } from "microlighter";

await highlightAll();

Pass options to limit the scan or add project-specific language aliases:

await highlightAll({
  root: document.querySelector("#docs"),
  selector: "pre.code > code",
  languageAliases: {
    ecmascript: "javascript",
    shellsession: "bash"
  }
});
Option Default Description
root document Element or document to search
selector "pre > code" Selector used to find code blocks
languageAliases {} Extra aliases mapped to bundled grammars

highlightAll() returns a promise containing the highlighted code elements.

Automatic highlighting

Import the auto runner to highlight the page as soon as the module loads:

<link rel="stylesheet" href="./node_modules/microlighter/themes/github.css">
<script type="module" src="./node_modules/microlighter/microlighter.min.js"></script>

<body data-syntax-theme="github">

After adding or changing code, dispatch this event to highlight again:

document.dispatchEvent(new Event("syntax-highlight"));

The event can also bubble from a code block or one of its parents.

CDN

Use the auto runner directly from a CDN:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/microlighter@2/themes/github.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/microlighter@2/microlighter.min.js"></script>

<body data-syntax-theme="github">
  <pre><code class="language-javascript">const answer = 42;</code></pre>
</body>

Web component

Import the optional <micro-lighter> custom element:

<link rel="stylesheet" href="./node_modules/microlighter/themes/github.css">
<script type="module" src="./node_modules/microlighter/micro-lighter-element.min.js"></script>

<body data-syntax-theme="github">
  <micro-lighter language="javascript" controls="copy" line-numbers>
    <pre><code>const answer = 42;</code></pre>
  </micro-lighter>
</body>
Attribute Description
language Language to use. Overrides language metadata on <pre> or <code>
controls="copy" Adds a copy button
line-numbers Adds a line number gutter without changing copied code

Style the controls with ::part(copy-button) and ::part(line-numbers).

TypeScript

Declarations ship with the package, including for the grammar and auto-run entry points. They are generated from the JSDoc types in src/, so the source and the published types cannot drift.

import { highlightAll, type HighlightAllOptions } from "microlighter";
import javascript from "microlighter/grammars/javascript.js";

Importing microlighter/micro-lighter-element.js also registers <micro-lighter> in HTMLElementTagNameMap, so querySelector returns a typed element.

Language detection

The recommended format is a language-* class:

<pre><code class="language-typescript">const answer: number = 42;</code></pre>

You can also use data-language on <code> or <pre>:

<pre data-language="typescript"><code>const answer: number = 42;</code></pre>

Avoid <pre lang="typescript"> in new code. MicroLighter supports it for compatibility, but the HTML lang attribute should describe human language.

Common aliases work automatically:

Aliases Language
js, jsx javascript
ts typescript
sh, shell, zsh bash
yml yaml
md markdown
sass scss
docker dockerfile
py python
rb ruby
gql graphql

Custom aliases passed to highlightAll() must point to a bundled language.

Languages

MicroLighter includes these grammars:

assembly, astro, bash, c, cpp, csharp, css, dart, dockerfile, elixir, git-diff, go, graphql, heex, html, ini, java, javascript, json, kotlin, lua, markdown, nginx, objective-c, perl, php, powershell, python, r, ruby, rust, scss, sql, svelte, swift, toml, tsx, typescript, vue, and yaml.

Grammars are ES modules and load on demand.

Themes

Load one theme and set the matching data-syntax-theme value on <body> or any container:

<link rel="stylesheet" href="./node_modules/microlighter/themes/night-owl.css">

<section data-syntax-theme="night-owl">
  <!-- code blocks -->
</section>

Bundled themes:

Themes use CSS custom properties for a small color palette:

Property Token categories
--syntax-comment Comments and quotes
--syntax-keyword Keywords, storage, at-rules, and sections
--syntax-operator Operators and punctuation
--syntax-string Strings, regular expressions, links, and attribute values
--syntax-constant Numbers, booleans, constants, symbols, and entities
--syntax-function Functions, decorators, and animations
--syntax-type Types and support tokens
--syntax-variable Variables and interpolation
--syntax-property Properties, keys, and attribute names
--syntax-tag Tags
--syntax-selector Selectors
--syntax-inserted Inserted text
--syntax-deleted Deleted text

Editable code

MicroLighter keeps code as plain text, so code blocks can remain editable. Call the highlighter after each change:

<editable-code>
  <pre><code class="language-javascript">const answer = 42;</code></pre>
</editable-code>

<script type="module">
  import "microlighter/microlighter.min.js";

  class EditableCode extends HTMLElement {
    connectedCallback() {
      const code = this.querySelector("pre > code");
      if (!code) return;

      code.contentEditable = "plaintext-only";
      code.spellcheck = false;
      code.setAttribute("aria-label", "Editable code");
      this.addEventListener("input", () => {
        this.dispatchEvent(new Event("syntax-highlight", { bubbles: true }));
      });
    }
  }

  customElements.define("editable-code", EditableCode);
</script>

Keep <pre><code> in the light DOM so MicroLighter can find it.

How it works

MicroLighter reads TextMate grammars with the browser's native RegExp. It turns matching token ranges into Highlight objects and styles them with ::highlight(). It does not use Oniguruma, WebAssembly, or generated token markup.

This keeps the library small. The trade-off is less language coverage and grammar accuracy than larger tools such as Shiki.

The low-level tokenizer is available from microlighter/highlight.js for advanced integrations.

Development

Requires Node.js 18 or newer.

npm install
npm run build
npm test

Useful commands:

Command Description
npm run build Build dist/, update the local demo package, and report sizes
npm test Build and run Node.js and Playwright tests
npm run size Print the size report without changing files
npm run docs:update-homepage-stats Update the homepage bundle size
npx serve docs Serve the demo at http://localhost:3000

The build fails when the minified bundle exceeds the gzip size limit in package.json.

See CONTRIBUTING.md for the project structure and guides for adding grammars and themes.

Prior art

MicroLighter builds on TextMate grammars and work across the syntax highlighting community:

License

MIT © Dave Rupert

microlighter (davatron5000/microlighter)

Searching Database…

这是什么?MicroLighter 是一个面向网页的极简语法高亮工具,没有任何依赖。它基于 CSS Custom Highlight API 和 TextMate 语法为代码上色,运行时零依赖,压缩后只有约 2 KiB。
它和 Prism、highlight.js 这类高亮工具有什么不同?它从不用标签包裹代码片段:匹配结果会变成用 ::highlight() 设置样式的 CSS Highlight 对象,因此 DOM 保持干净,代码块仍然是可直接编辑的纯文本。它用浏览器原生的 RegExp 来读取 TextMate 语法,而不是 Oniguruma。
怎么把它加到我的网站上?安装这个包,导入一个主题,然后运行 highlightAll() —— 它会找出页面上所有带有受支持语言类名的 pre > code 代码块并高亮它们。它还提供自动运行器和可选的 web component。
它需要其他库、WebAssembly 或复杂的工具链吗?不需要 —— 它运行时零依赖,压缩后只有约 2 KiB。它使用浏览器原生的 RegExp,而不是 Oniguruma 或 WebAssembly;只有在构建和测试时才需要 Node.js 18+。
那它有什么不足?主要是准确度和覆盖范围:原生 RegExp 的方案牺牲了一部分语法的精确性,因此支持的语言比 Shiki 这类大型工具更少、精确度也更低。此外,自定义语言别名必须指向某个内置的语法文件。
它适合用在什么样的网页上?文档、博客、教程 —— 任何需要在网页上展示代码的地方。它专门保证代码块可以保持可编辑状态,每次修改后都会重新高亮。
它是运行在浏览器里,还是需要服务器上装 Node?它在浏览器里客户端运行,通过 CSS Highlights API 为文本设置样式 —— 完全不涉及服务器。Node.js 18+ 只用于构建、跑测试这类开发工作。
可以在我自己的项目里免费使用吗?可以 —— 它由 Dave Rupert 以 MIT 协议发布,商业使用、修改和再分发都没有问题。
它自带多少种语言支持?内置 37 种语法,按需加载 —— 包括 JavaScript、TypeScript/TSX、Python、Rust、Go、HTML、CSS、SQL、Dockerfile、Markdown、YAML、Vue、Svelte 等。js、py、rb、yml 这类常见别名会自动映射,额外的别名必须指向某个内置的语法文件。
我可以自己调整配色吗?可以。内置十套主题(dracula、monokai、gruvbox、github、tokyo-night 等),通过 data-syntax-theme 属性选择。每套主题都由 --syntax-keyword、--syntax-string 这类 CSS 自定义属性驱动,所以你可以直接用普通 CSS 覆盖各种代码元素的颜色。
自动高亮是它唯一的运行方式吗?不是。你可以用 root、selector、languageAliases 等选项手动调用 highlightAll(),可以在 DOM 变化后派发一个事件来重新高亮,也可以使用可选的 web component —— 它会附加复制按钮和行号栏,且不会改变复制出来的代码。
它自带 TypeScript 类型吗?有 —— 类型声明随包一起发布,并由 src/ 中的 JSDoc 类型生成,所以源码和发布的类型不会出现不一致。导入 web component 时,它还会注册到 HTMLElementTagNameMap 中,让 querySelector 返回带类型的结果。
Size
0.2 MB
Stars
1.1K
Age
2mo
Commits · 90 Days