codemirror-json-schema

JSON Schema-powered linting, autocomplete, and hover tooltips for CodeMirror 6, across JSON, JSON5, and YAML documents.

Library
npm
v0.8.1
109stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
46/100Fair
Development Activity0
Maintenance44
Community68
Maturity52
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture78
Code Quality74
Innovation70
Learning Curve90

codemirror-json-schema is a set of CodeMirror 6 extensions that bring full JSON Schema tooling to the editor: real-time lint diagnostics, schema-aware autocompletion with snippet-based value insertion, and hover tooltips that surface a property’s type, enum, and description straight from the schema. It ships bundled entry points for JSON (@codemirror/lang-json), JSON5 (codemirror-json5), and YAML (@codemirror/lang-yaml), so the same schema can validate and assist across all three document formats without writing separate integration code for each.

Under the hood it pairs json-schema-library (Draft 04 for validation, Draft 07 for schema resolution during completion) with a lezer syntax-tree walker that maps cursor position to JSON Pointer paths, letting it resolve $ref, oneOf/anyOf/allOf, and patternProperties against the live document data rather than the schema alone. Schemas can be set once at editor creation or swapped at runtime via updateSchema, with a CodeMirror StateField driving lint refresh automatically. The project publishes both ESM and CommonJS builds, and its lower-level stateExtensions/handleRefresh exports let consumers compose the linter, hover, and completion extensions with their own CodeMirror configuration instead of using the bundled jsonSchema()/json5Schema() helpers.

What You Get

  • Bundled jsonSchema() and json5Schema() extensions that wire up linting, autocomplete, and hover with one function call
  • Draft 04/07 JSON Schema validation via json-schema-library, including $ref, oneOf/anyOf/allOf resolution
  • Snippet-based autocompletion that inserts property keys and guessed values (enums, defaults, examples) with cursor placement
  • Hover tooltips rendering a property’s type, enum, pattern, and Markdown-rendered description
  • Separate JSON, JSON5, and YAML entry points (./json5, ./yaml) sharing the same schema and state machinery
  • Runtime schema swapping via updateSchema() without recreating the editor state

Common Use Cases

  • Config file editors - give users JSON/YAML editing with schema validation for tool configs (package manifests, CI files) in a web-based IDE
  • API playground / request builders - validate and autocomplete request bodies against an OpenAPI-derived JSON Schema as the user types
  • Low-code / form-builder tools - let users hand-edit the underlying JSON5 or YAML representation of a visually-built form with schema-guided completions
  • Documentation sites with live schema explorers - embed an editor that validates snippets against a published JSON Schema (e.g. schemastore.org schemas)

Under The Hood

Architecture The package is organized as a set of feature extensions (features/validation.ts, features/completion.ts, features/hover.ts, features/state.ts) unified by a shared schemaStateField (a CodeMirror StateField) that stores the active JSON Schema per editor instance and is updated via a dispatched StateEffect (updateSchema). Each feature independently pulls the schema from state, constructs a json-schema-library Draft instance (Draft04 for validation/hover, Draft07 for completion’s schema resolution), and reuses a mode-aware DocumentParser abstraction (parsers/json-parser.ts, json5-parser.ts, yaml-parser.ts, selected by parsers/index.ts’s getDefaultParser), so the same class-based logic (JSONValidation, JSONCompletion, JSONHover) works across JSON, JSON5, and YAML by only swapping the parser and lezer token-name mapping. The three per-format entry points (json/bundled.ts, json5/bundled.ts, yaml/bundled.ts) compose these primitives with CodeMirror’s own language/linter/hoverTooltip extensions into single jsonSchema()/json5Schema()/yamlSchema() functions; the abstraction most other code depends on is the lezer-to-JSON-Pointer mapping (getJsonPointerAt) that every feature uses to correlate cursor position with schema location.

Tech Stack TypeScript targeting ES2017/ESNext modules, built with tsc for ESM output (dist/) and a second tsc --module commonjs pass for CJS (cjs/), plus a separate Vite build for the dev/ demo app deployed to Netlify. Core dependencies are json-schema-library (Draft04/Draft07 validation and schema resolution), @sagold/json-pointer, yaml (YAML parsing), best-effort-json-parser (tolerant parsing while typing), markdown-it plus shiki/@shikijs/markdown-it (Markdown and code rendering in hover/error messages), and loglevel for debug logging. CodeMirror itself (@codemirror/state, view, language, lint, autocomplete, lang-json, lang-yaml) and codemirror-json5 are declared as peer/optional dependencies so consumers bring their own CodeMirror version. Package management is pnpm with Changesets driving versioned releases and GitHub Actions publishing to npm.

Code Quality The repo has real automated test coverage — seven Vitest spec files under __tests__ directories covering parsers, validation, hover, completion, and JSON-pointer utilities — run via vitest --dom with @vitest/coverage-v8, and CI runs pnpm test:coverage plus pnpm audit --prod on every push and pull request. TypeScript is configured in strict mode with isolatedModules. Error handling favors explicit try/catch around schema validation and parsing but sometimes swallows exceptions silently (a bare catch {} around schema validation) rather than surfacing them, a minor weak point. Naming is consistent (classes mirror their file names), Prettier enforces formatting, and lefthook wires up pre-commit hooks, though there is no dedicated root ESLint config.

What Makes It Unique Unlike most JSON-in-CodeMirror integrations that lint against a static schema alone, this library resolves schemas contextually — its completion logic combines the lezer syntax-tree position with the live parsed document data (not just the schema) to resolve oneOf/anyOf/conditional branches, then falls back to a “lax” schema (required/additionalProperties relaxed) when the strict schema yields no completions, a deliberate two-pass strategy many competing integrations skip. It is also one of few actively maintained options that unifies JSON, JSON5, and YAML behind one shared validation/completion/hover core rather than shipping separate libraries per format, and supports live schema swapping via CodeMirror’s StateField/StateEffect pattern without recreating the editor.

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