svelte-codemirror-editor
Drop CodeMirror 6 into any Svelte 5 app with a single fully-typed component.
Repository Health
Technical Analysis
svelte-codemirror-editor wraps CodeMirror 6 in a single Svelte 5 component, exposing every extension point—language support, themes, keymaps, folding, autocompletion—as typed props instead of manual CodeMirror wiring. It mirrors CodeMirror’s own extension model internally, so changing a prop like lang or theme triggers an efficient live reconfigure of the editor rather than a full remount.
The component ships with sensible defaults (line numbers, history, bracket matching, autocompletion, fold gutter) all enabled out of the box and individually toggleable, plus SSR-safe rendering that falls back to a plain <pre> preview until the browser mounts the real editor.
What You Get
- A single
<CodeMirror>Svelte component with two-waybind:valuebinding - Typed props for every major CodeMirror 6 extension (language, theme, keymaps, folding, autocompletion, search, linting)
- Automatic reconfiguration of the live
EditorViewwhen props change, without destroying editor state - SSR-safe fallback rendering (a static
<pre>preview) for use inside SvelteKit server-rendered pages - Direct access to the underlying CodeMirror
EditorViewinstance via theonreadycallback for advanced customization
Common Use Cases
- Embedding a syntax-highlighted code editor in a documentation or admin site built with SvelteKit
- Building in-browser playgrounds or REPLs that need live JavaScript/TypeScript/CSS/HTML editing
- Adding a configuration or script editor to a SaaS product’s settings UI
- Building developer tools (query editors, template editors) inside Svelte apps
Under The Hood
Architecture
The entire component lives in a single file, src/lib/CodeMirror.svelte, which composes CodeMirror’s extension system through Svelte 5 runes: a $derived state_extensions array combines base extensions (line numbers, history, folding, autocompletion, etc.), a theme extension, and any user-supplied extensions, while two $effects push value changes and extension changes into the live EditorView — the latter via StateEffect.reconfigure, so prop updates reconfigure the running editor instead of tearing it down and remounting it. onMount/onDestroy handle the view’s lifecycle, and a browser check gates rendering so the component degrades to a static <pre> preview during SSR. There is no further internal layering — everything the library does routes through this one component plus a small debounce utility, which is appropriately scoped for its size but leaves little separation of concerns if the surface area grows.
Tech Stack
Built on Svelte 5 (runes: $state, $derived, $effect, $bindable) and CodeMirror 6, pulling in @codemirror/autocomplete, @codemirror/commands, @codemirror/language, @codemirror/lint, @codemirror/search, @codemirror/state, and @codemirror/view directly rather than through a meta-package. SvelteKit and @sveltejs/adapter-static are used only to build and deploy the demo/docs site (src/routes/), not the published package. Build tooling is Vite 7 plus @sveltejs/package to produce the publishable dist, svelte-check for type-checking, ESLint 9/typescript-eslint and Prettier for style, and semantic-release with GitHub Actions handling versioned npm publishes and GitHub Pages deployment of the demo.
Code Quality
No test files exist anywhere in the repository (no *.test.*/*.spec.* matches) — the npm run test script only runs prettier --check and svelte-check, so correctness relies entirely on TypeScript types and lint rules rather than executable tests. Types are used extensively: the exported CodeMirrorProps interface documents every prop with JSDoc, and config types (e.g. HistoryConfig, FoldGutterConfig) are derived directly from CodeMirror’s own function signatures via Parameters<typeof x>, keeping them in sync with upstream automatically. Naming is consistent (snake_case internal functions/state, camelCase public props) and error handling is minimal but appropriate given the component has no I/O beyond DOM/CodeMirror calls.
What Makes It Unique
Most CodeMirror wrappers for component frameworks either expose a thin imperative ref API or require consumers to hand-build a CodeMirror EditorState/EditorView themselves. This library instead maps nearly the entire CodeMirror 6 extension surface onto typed, individually toggleable props (each of which can also accept a config object instead of just true/false), and reconfigures the live view reactively rather than remounting on every prop change — a comprehensive typed surface more than a novel editing technique.