@codemirror/language
Language support infrastructure for the CodeMirror 6 editor: parsing, indentation, code folding, bracket matching, and syntax highlighting.
Repository Health
Technical Analysis
@codemirror/language is the language-support layer of the CodeMirror 6 code editor. It defines the core Language and LRLanguage classes that wrap a Lezer parser and expose it to the editor as an incrementally-updated syntax tree, plus the facets and node-prop conventions that let a language attach indentation rules, foldable regions, bracket matching, and syntax highlighting to that tree.
Rather than shipping a specific language mode, the package provides the building blocks that CodeMirror’s per-language packages (@codemirror/lang-javascript, @codemirror/lang-python, etc.) and third-party language extensions are built on top of, along with a StreamLanguage adapter for porting legacy CodeMirror 5-style line-based parsers into the same system.
What You Get
- Language, LRLanguage, and StreamLanguage classes for defining a language from a Lezer parser or a legacy stream/line parser
- syntaxTree()/ensureSyntaxTree() APIs for reading the current (or forced) parse tree from editor state
- An indentation system (indentService, indentNodeProp, continuedIndent, delimitedIndent) for computing per-line indent from the syntax tree
- Code folding (foldService, foldNodeProp, foldGutter, codeFolding) driven off the same tree
- Bracket matching (bracketMatching) and tag-based syntax highlighting (HighlightStyle, syntaxHighlighting, defaultHighlightStyle)
Common Use Cases
- Implementing a new language mode for CodeMirror 6 by wrapping a Lezer grammar in an LRLanguage
- Adding editor features (indent-on-enter, code folding, bracket matching, syntax-aware theming) that need to read the current syntax tree
- Porting an existing CodeMirror 5 mode to CodeMirror 6 via the StreamLanguage/StreamParser adapter
- Building custom tooling (linters, formatters, structural navigation) on top of the live incremental parse tree
Under The Hood
Architecture: The package centers on the Language class (src/language.ts), which pairs a Lezer Parser with a language-data Facet and exposes the parsed document as a StateField-backed syntax tree, kept incrementally up to date by a background ViewPlugin (LanguageState, ParseContext) that reparses only changed regions rather than the whole document. LRLanguage specializes this for Lezer LR grammars, while stream-parser.ts implements a StreamParser/StreamLanguage adapter that wraps CodeMirror 5-style, line-based token parsers into a Lezer-compatible incremental Parser, letting legacy modes plug into the same tree-based pipeline. Everything downstream is built as independent modules that read that shared tree through Lezer NodeProps registered on the grammar: indent.ts computes per-line indentation via an indentService facet and node-prop-driven strategies (continuedIndent, delimitedIndent, flatIndent); fold.ts derives foldable ranges via foldService/foldNodeProp and renders a foldGutter view plugin; matchbrackets.ts walks the tree to find and highlight matching bracket pairs; and highlight.ts maps Lezer highlighting tags to CSS via HighlightStyle/syntaxHighlighting. All of these compose as ordinary CodeMirror 6 Extensions (facets, state fields, view plugins), so a language author only needs to attach node props to their grammar to get indentation, folding, and highlighting largely for free.
Tech Stack: 100% TypeScript, published as dual ESM/CJS (dist/index.js / dist/index.cjs) with bundled .d.ts types via @codemirror/buildhelper. Runtime dependencies are entirely within the CodeMirror/Lezer ecosystem: @codemirror/state and @codemirror/view (^6.x) for the extension/state model, @lezer/common, @lezer/highlight, and @lezer/lr (^1.x) for tree/parser primitives, and style-mod for scoped stylesheet injection. There are no dependencies outside that ecosystem, and the test-only devDependency on @lezer/javascript is used purely as a sample grammar for the test suite. The build/test scripts (cm-buildhelper, cm-runtests) are the same shared tooling used across all CodeMirror 6 monorepo packages, so the package follows CodeMirror’s standard release and versioning conventions.
Code Quality: The test/ directory (three files, ~225 lines) exercises incremental parsing correctness and timing (test-syntax.ts), the stream-parser adapter (test-stream-parser.ts), and folding (test-fold.ts) using the lightweight ist assertion library in a describe/it structure. Coverage is real but narrow relative to the ~2,800 lines of source — there’s no dedicated test file for highlight.ts or matchbrackets.ts in the sampled suite. The source itself is unusually well documented: 233 /// doc comments across the module (used to generate the published API reference at codemirror.net/docs/ref), consistent camelCase naming, and explicit thrown Errors for invalid input (e.g. indentUnit validation) rather than silent failures or fallbacks.
API Design: The entire public surface is re-exported from a single src/index.ts, so consumers get one import path (@codemirror/language) covering language definition, indentation, folding, highlighting, and bracket matching rather than having to reach into submodules. The API follows CodeMirror 6’s own Facet/StateField/NodeProp conventions throughout, which is a low-friction, idiomatic fit for anyone already building on @codemirror/state/@codemirror/view, but represents real boilerplate and a non-trivial ramp-up for newcomers unfamiliar with that extension model. The README supplies one concrete usage example (defining an LRLanguage from a Lezer parser) and links out to the full hosted API reference rather than embedding extensive inline examples.
Used by 67 apps in this directory
Dokploy
Devops · Hosting Control Panel · Security
Self-hosted PaaS that deploys apps and databases on your own VPS using Docker, Traefik, and multi-build-system orchestration
Enso
Analytics · Data Engineering · Low Code Platforms
A visual and textual programming platform for data prep and analysis where the node graph and the underlying Enso code are always perfectly in sync, built by an Alteryx co-founder on a GraalVM engine.
Epicenter
Developer Tools · Knowledge Management · Note Taking
A local-first monorepo led by Whispering, an open-source speech-to-text app, built on an MIT toolkit that turns your data into plain Markdown and SQLite files you own instead of a database you rent.
evidence
Analytics · Data Engineering
Turn SQL queries and markdown files into polished, interactive data apps and business intelligence reports — no drag-and-drop, no GUI, just code.
Frappe Books
Invoicing Finance
Offline desktop accounting with double-entry, POS, and custom invoice templates
Ghost
Blogging · CMS
Open source headless Node.js CMS for professional publishing, paid memberships, and newsletters with a fully owned audience.
GitButler
AI Development · Developer Tools · Devops
Git, but better — a modern version control client with stacked branches, parallel workflows, unlimited undo, and first-class support for AI-powered development.
Gitea
Developer Tools · Devops · Project Management
Self-hosted DevOps in a single Go binary — Git hosting, GitHub Actions-compatible CI/CD, and 30+ package registries without any SaaS dependency.
Grafana
Analytics · Monitoring
The open-source observability platform that unifies metrics, logs, and traces from any data source into dynamic, queryable dashboards.