refractor

Lightweight virtual syntax highlighter that wraps Prism to output hast syntax trees instead of HTML strings.

Library
npm
v5.0.0
870 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
41 /100 Fair
Development Activity 0
Maintenance 32
Community 44
Maturity 60
Momentum 28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
78 /100 Good
Architecture 80
Code Quality 88
Innovation 62
Learning Curve 80

Refractor wraps Prism, the widely used browser syntax highlighter, so that highlighting produces a hast (HTML AST) tree instead of a serialized HTML string. That distinction matters for any tool built on virtual DOM diffing (React, Preact) or on unified/rehype content pipelines: instead of dropping dangerouslySetInnerHTML strings into the DOM, callers get a structured tree of element and text nodes they can diff, transform, or serialize themselves.

The package ships three entry points sized for different needs: refractor (36 common languages by default), refractor/core (zero languages, register only what you use), and refractor/all (all 290+ Prism-supported grammars). Because Prism’s own grammar files rely on global state and aren’t independently importable, refractor re-packages every supported grammar as a self-contained function that can be registered against a refractor/core instance, keeping bundle size proportional to the languages actually used.

It is the syntax-highlighting engine underneath several popular downstream packages, including react-syntax-highlighter and rehype-prism-plus, which is why most consumers never call it directly but still depend on its correctness and language coverage.

What You Get

  • A refractor.highlight(value, language) API that returns a hast Root node instead of an HTML string
  • Three tiered entry points — refractor (common languages), refractor/core (bring your own), and refractor/all (everything) — so bundle size scales with actual language usage
  • Every Prism grammar re-packaged as an importable, registerable function (refractor/markdown, refractor/rust, etc.), working around Prism’s normal reliance on global state
  • Alias support (refractor.alias) and introspection (refractor.registered, refractor.listLanguages) for managing which languages and shorthand names are active
  • Full TypeScript types generated via JSDoc + tsc, with 100% type coverage enforced in CI

Common Use Cases

  • Rendering syntax-highlighted code blocks in React or Preact apps without injecting raw HTML strings
  • Powering markdown/MDX pipelines built on remark/rehype that need highlighted code as part of the AST, not as a final HTML blob
  • Serving as the highlighting engine inside higher-level packages like react-syntax-highlighter or rehype-prism-plus
  • Building custom code renderers that target non-HTML output — ANSI terminal colors, PDF, or other tree-consuming serializers
  • Selectively bundling only the languages a docs site or editor actually needs via the refractor/core + refractor/* entry points

Under The Hood

Architecture The package is organized around a single core module (lib/core.js) that implements a Refractor class wrapping a patched copy of Prism’s tokenizer (lib/prism-core.js), with lib/common.js and lib/all.js acting as pre-configured entry points that import and register subsets of the 290+ per-language files under lang/. Each language file in lang/ is a small function of shape (prism: Refractor) => void that calls prism.languages[...] to register a grammar plus any aliases, decoupling grammar registration from Prism’s normal reliance on browser globals. Highlighting itself walks Prism’s token stream and converts it into hast element/text nodes rather than HTML markup, which is the one architectural change that differentiates this package from vanilla Prism; the script/languages.js and script/list.js build scripts regenerate the lang/ directory and its documentation table from upstream Prism on demand.

Tech Stack The project is plain ESM JavaScript ("type": "module") with no runtime framework dependency beyond hastscript (hast node construction), parse-entities (HTML entity decoding), and @types/hast/@types/prismjs for typing — prismjs itself is a dev dependency only, vendored and patched via patch-package at build time rather than depended on directly. Type safety comes from TypeScript’s checkJs mode operating directly over JSDoc-annotated .js files (tsc --build) rather than authoring .ts sources, with type-coverage enforcing 100% coverage in CI. Linting and formatting run through xo and prettier, and the whole repo is unified/remark-linted via remark-preset-wooorm, reflecting its place in Titus Wormer’s broader unified/rehype/remark ecosystem.

Code Quality Tests live under test/index.js and run via Node’s built-in node:test runner against refractor/all, covering the public API (highlight, register, alias, registered, listLanguages) plus per-language fixture comparisons stored in test/fixtures/. Coverage is enforced at 100% via c8 --check-coverage, and the test script chains generation, build, formatting, and coverage gates together, so a change that breaks typing, linting, or coverage fails CI outright. Error handling is explicit and deliberate — invalid value/language arguments throw descriptive TypeError-style messages that are directly asserted against in tests, rather than failing silently.

What Makes It Unique Refractor’s core insight is narrow but valuable: Prism is a mature, widely trusted highlighter, but its output is an HTML string, which is awkward for any tool built on ASTs or virtual DOM diffing. Refractor solves this by re-exporting Prism’s tokenizer output as hast nodes and re-packaging all of Prism’s otherwise-global-dependent grammar files as independently importable functions — without reimplementing Prism’s actual tokenization logic. That combination of AST-native output and per-language tree-shakeable imports is why it became the de facto highlighting layer for the rehype/unified ecosystem and for React-based code renderers, despite not introducing any novel highlighting algorithm itself.

Used by 5 apps in this directory

Python
63%
BSD 3

Flagsmith

Ab Testing Experimentation · Developer Tools · Devops

6,577

Open-source feature flagging, remote config, and A/B/multivariate testing platform for web, mobile, and server-side apps — self-host or use the hosted SaaS.

View details
90
Repo Health
82
Technical
63
Dependency
Built with
Python 63%
TypeScript 31%
Updated 6 days ago
Rust
52%
Other

hoodik

File Storage · Security

1,484

Self-hosted, end-to-end encrypted cloud storage with browser-based encryption and S3-compatible storage support

View details
79
Repo Health
71
Technical
63
Dependency
Built with
Rust 52%
TypeScript 33%
Vue 14%
Updated 1 weeks ago
TypeScript
85%
GPL 3.0

Notesnook

File Storage · Note Taking · Security

14,660

End-to-end encrypted, open-source note-taking where your data stays yours — even from the server.

View details
90
Repo Health
84
Technical
60
Dependency
Built with
TypeScript 85%
JavaScript 12%
Updated 5 days ago
TypeScript
97%
Other

Outline

Collaboration · Knowledge Management

40,729

A fast, real-time collaborative knowledge base for growing teams built on React, Node.js, and ProseMirror.

View details
91
Repo Health
87
Technical
68
Dependency
Built with
TypeScript 97%
Updated 5 days ago
TypeScript
99%
MIT

Sanity

CMS

6,338

Open-source headless CMS with a fully customizable React Studio, real-time collaborative editing, structured content modeling, and GROQ query language

View details
92
Repo Health
90
Technical
66
Dependency
Built with
TypeScript 99%
Updated 4 days ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers