codemirror-lang-svelte

Svelte language support for CodeMirror 6, with a native Lezer grammar, nested JS/CSS parsing, indentation, and code folding.

Library
npm
v6.0.0
33stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
21/100Needs Attention
Development Activity0
Maintenance0
Community20
Maturity52
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
51/100Fair
Architecture68
Code Quality35
Innovation55
Learning Curve45

@replit/codemirror-lang-svelte adds first-class Svelte support to the CodeMirror 6 editor by defining a dedicated Lezer grammar for Svelte’s template syntax rather than reusing HTML’s grammar with patches. It understands Svelte-specific constructs — {#if}/{:else}/{/if}, {#each}/{:then}/{:catch}, {#await}, {#key}, {@html}, {@debug}, {@const} blocks, component tags, directives like on:, bind:, use:, transition:, and interpolated expressions — as real grammar nodes, so indentation, code folding, and syntax highlighting all key off actual Svelte semantics instead of generic markup rules.

Under the hood it composes CodeMirror’s own JavaScript and CSS language parsers into the Svelte grammar using Lezer’s parseMixed mechanism, so <script> and <style> blocks are parsed with @codemirror/lang-javascript and @codemirror/lang-css (including type/lang attribute detection for TypeScript and SCSS) while the surrounding markup is parsed as Svelte. It ships as the svelte() extension plus the underlying svelteLanguage and raw svelteParser exports for consumers building on top of it directly, such as Replit’s own web-based Svelte editing surface.

What You Get

  • A dedicated Lezer grammar (src/syntax.grammar) for Svelte templates, covering {#if}, {#each}, {#await}, {#key}, {@html}, {@debug}, {@const} blocks and all directive forms (on:, bind:, use:, transition:, in:, out:, animate:, class:, style:, let:).
  • The svelte() LanguageSupport extension, ready to drop into a CodeMirror EditorView alongside basicSetup.
  • Nested parsing of <script> and <style> contents via @codemirror/lang-javascript and @codemirror/lang-css, with automatic TypeScript/SCSS detection from lang/type attributes.
  • Node-aware indentation and code folding for Svelte blocks and elements, plus a Svelte-specific autoCloseTags input handler for auto-closing component and element tags.
  • Exported lower-level primitives (svelteLanguage, svelteParser, svelteHighlighting) for consumers who need to extend or compose the grammar themselves.

Common Use Cases

  • Adding Svelte editing support to a browser-based IDE or REPL built on CodeMirror 6, such as Replit’s own editor.
  • Building a Svelte playground or documentation site with an embedded live code editor.
  • Powering syntax highlighting and folding for .svelte files in a CodeMirror-based code viewer or diff tool.
  • Prototyping a custom Svelte tooling extension (linter overlay, snippet engine) on top of the exposed Lezer parse tree.

Under The Hood

Architecture The package is layered as a Lezer grammar (src/syntax.grammar) compiled to a parser, external tokenizers (src/tokens.ts) that hand-scan balanced-delimiter JS-like expressions and HTML comments, a content.js module that uses Lezer’s parseMixed to nest the JavaScript and CSS parsers inside <script>/<style> regions based on tag attributes, and an index.ts that wires the configured parser into a CodeMirror LRLanguage plus LanguageSupport extension with custom indentNodeProp/foldNodeProp handlers and a hand-rolled autoCloseTags input handler (duplicated from CodeMirror’s HTML extension because it explicitly checks for the HTML language type). Every downstream layer — highlighting, indentation, folding, nesting — is keyed directly to named grammar nodes, so the grammar file is the single source of truth the rest of the package depends on.

Tech Stack Written in TypeScript on top of the Lezer parser system (@lezer/common, @lezer/lr, @lezer/highlight, @lezer/generator) and CodeMirror 6 packages (@codemirror/state, @codemirror/view, @codemirror/language, @codemirror/lang-javascript, @codemirror/lang-css, @codemirror/lang-html, @codemirror/autocomplete). The grammar and package are built with @codemirror/buildhelper’s cm-buildhelper CLI, a dev-only Vite server (dev/) provides a live preview, and Yarn manages dependencies; there is no CI configuration in the repository.

Code Quality No test files or test fixtures exist anywhere in the repository despite package.json declaring a test script (cm-runtests, the @codemirror/buildhelper test runner) — testing is effectively absent. Naming is consistent and descriptive throughout (PascalCase grammar nodes, camelCase functions), but type safety is inconsistent: most of src/ is TypeScript, while content.js and html-tokens.js are plain untyped JavaScript mixed into the same module graph, and index.ts carries an explicit @ts-expect-error suppressing a parser type mismatch. There is no ESLint configuration, only Prettier for formatting, and no CI workflow to enforce any of it.

What Makes It Unique Rather than treating Svelte templates as HTML with light patching, the grammar models Svelte’s block syntax and directives as first-class nodes, which lets indentation and folding understand constructs like {:else}/{:then}/{:catch} continuations that a generic HTML-based highlighter cannot. Combined with attribute-driven nested parsing of <script>/<style> content, this mirrors the approach CodeMirror’s own lang-html package takes for embedded JS/CSS, extended to cover Svelte’s additional block and directive grammar — a solid, correct application of an established pattern to a templating language CodeMirror doesn’t natively support, rather than a wholly novel parsing technique.

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

Search