prosemirror-model

The persistent document model and schema system at the core of the ProseMirror rich-text editor.

Library
npm
v1.25.12
338 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 4
Maintenance 0
Community 80
Maturity 60
Momentum 20

Technical Analysis

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

prosemirror-model implements the document model that every ProseMirror-based editor is built on: an immutable tree of Node and Fragment instances, together with the Schema system that defines which node and mark types a document may contain and how they nest. It underpins collaborative editors like TipTap, Atlassian’s editor, and countless custom rich-text tools that need a version-controllable, diffable representation of structured content rather than raw HTML.

Because nodes and fragments are persistent (never mutated in place), edits produce new document versions that share unchanged structure with the old one — a foundation that operational-transform and CRDT-based collaboration layers (prosemirror-collab, y-prosemirror) build directly on top of. The package also ships a bidirectional DOM bridge (DOMParser and DOMSerializer) so schemas can round-trip through contentEditable without the editor ever touching raw HTML strings directly.

What You Get

  • Node and Fragment classes: an immutable tree structure representing a document’s content, size, and children
  • Schema, NodeSpec, and MarkSpec APIs for declaring the node/mark types, attributes, and content-expression rules a document must obey
  • ContentMatch for validating and auto-completing sequences of child nodes against a schema’s content expressions
  • DOMParser and DOMSerializer for converting between the document model and browser DOM/HTML, driven by declarative parse and serialization rules
  • ResolvedPos and NodeRange for resolving integer document positions into structured, depth-aware location info
  • Slice and replace() for representing and applying structural edits (cut/paste-style content splicing) across the document tree

Common Use Cases

  • Building a custom rich-text or structured-content editor on top of ProseMirror’s view and state packages
  • Defining a constrained document schema (e.g. only headings, paragraphs, and specific inline marks) for a CMS or comment editor
  • Implementing collaborative editing where documents need a diffable, structure-sharing representation for OT/CRDT syncing
  • Converting between HTML and a validated document tree when importing/exporting content from a rich-text field

Under The Hood

Architecture

The module is organized as a small set of tightly coupled classes rather than layered subsystems: node.ts defines Node (and its leaf TextNode variant), fragment.ts defines Fragment as the ordered child-list container each Node holds, and mark.ts defines Mark for inline formatting attached to nodes — together forming an immutable tree where every mutation-looking operation (Node.replace, Fragment.append, etc.) returns a new instance built via comparedeep.ts’s structural-sharing helpers rather than mutating in place. schema.ts defines Schema, NodeType, and MarkType, which own the NodeSpec/MarkSpec content-expression strings; those expressions are compiled by content.ts’s ContentMatch (a hand-rolled NFA→DFA compiler: parseExpr/nfa/dfa functions) into a matcher used both to validate document trees at construction time and to auto-fill required content. resolvedpos.ts’s ResolvedPos resolves a flat integer document offset into a full ancestor path, letting replace.ts’s Slice/replace() implement schema-aware content splicing (used for cut/paste-like operations) by walking up and down the resolved position’s ancestor chain to find the correct open/close boundaries. from_dom.ts (DOMParser, ~850 lines, the largest file in the module) and to_dom.ts (DOMSerializer) form the DOM boundary layer, converting between the tree and the browser DOM via declarative ParseRule/DOMOutputSpec objects rather than imperative walking code, so schema authors describe HTML shape declaratively instead of writing parser logic themselves.

Tech Stack

prosemirror-model is a zero-runtime-framework TypeScript library (100% TypeScript per GitHub’s language breakdown) with exactly one runtime dependency: orderedmap (^2.0.0), used internally by Schema to keep node/mark type definitions in an order-preserving map. It has no build-time bundler config of its own — package.json’s prepare script (pm-buildhelper src/index.ts) delegates compilation and multi-format output (dist/index.js as ESM, dist/index.cjs as CJS, dist/index.d.ts for types) to @prosemirror/buildhelper, a shared tool used across the whole ProseMirror monorepo family, and the package is declared “type”: “module” with sideEffects: false so bundlers can tree-shake it. Test-only dependencies are jsdom (^20.0.0, to exercise the DOM parser/serializer without a real browser) and prosemirror-test-builder (a companion ProseMirror package providing schema/document test fixtures), run via the pm-runtests script from the same buildhelper toolchain rather than a general-purpose test runner config checked into this repo.

Code Quality

Tests live under test/ as one file per module (test-node.ts, test-content.ts, test-dom.ts, test-replace.ts, test-resolve.ts, test-slice.ts, test-mark.ts, test-diff.ts) using the minimal ist assertion library and Mocha-style describe/it blocks, exercising both the public API and edge cases like custom toDebugString/leafText overrides in test-node.ts — coverage reads as thorough for a module this central, though there’s no CI config or coverage report checked into this specific clone to verify enforced thresholds. Source files are consistently documented with /// doc comments used to generate the published API reference (visible throughout node.ts, schema.ts, and content.ts), and error handling is explicit rather than silent: RangeError is thrown with descriptive messages for invalid attributes (schema.ts’s checkAttrs) and invalid content (content.ts, replace.ts’s ReplaceError), so schema/document misuse fails fast at construction time instead of producing corrupt trees. Naming is terse but consistent with the rest of the ProseMirror ecosystem (nodeSize, childCount, resolve), and TypeScript’s strict typing (readonly properties throughout Node/Fragment/Mark) enforces the immutability contract at compile time rather than relying on documentation alone.

API Design The public API favors a small number of orthogonal, composable primitives over convenience wrappers: Node, Fragment, Schema, and Slice cover essentially every editing operation, and higher-level packages (prosemirror-transform, prosemirror-state) build entirely on top of this module’s exported surface rather than reaching into internals — index.ts’s export list is deliberately narrow. Getting started requires defining a Schema with NodeSpec/MarkSpec objects before anything else, which is more upfront boilerplate than schema-less alternatives like plain contentEditable, but that investment is what makes the rest of the API (matchType, contentMatchAt, DOMParser.fromSchema) type-safe and validated. Documentation is dense and reference-oriented — the /// comments in src/*.ts are extracted into the published API docs on prosemirror.net referenced from README.md and src/README.md — favoring precision over tutorial-style hand-holding, which fits an audience of editor-framework authors more than end-application developers dropping the package in for a five-minute integration.

Used by 19 apps in this directory

JavaScript
55%
Other

Lokus

Knowledge Management · Note Taking

829

Local-first note-taking with graph view, canvas & AI plugins—your Markdown files, zero telemetry, blazing-fast Rust performance.

View details
75
Repo Health
75
Technical
64
Dependency
Built with
JavaScript 55%
HTML 21%
Rust 12%
Updated 2 months ago
TypeScript
44%
Other

Magic

AI Agents · Automation · Low Code Platforms

5,055

Magic is an enterprise-grade open-source AI agent platform combining a generalist AI agent, workflow engine, IM, and collaborative office system for running an AI-powered digital workforce.

View details
68
Repo Health
79
Technical
65
Dependency
Built with
TypeScript 44%
PHP 32%
Updated 2 months ago
Python
38%
Other

Open WebUI

AI Agents · AI Assistants

156,607

The extensible, privacy-first AI platform that runs Ollama, OpenAI, and any LLM backend behind a polished, feature-packed web interface.

View details
92
Repo Health
75
Technical
66
Dependency
Built with
Python 38%
Svelte 35%
JavaScript 19%
Updated 1 weeks ago
TypeScript
93%
Apache 2.0

Openship

Devops · Hosting Control Panel

14,912

Openship is an open-source, self-hostable deployment platform that points at a repo and builds, ships, routes, and TLS-terminates the app — driven from a desktop app, web dashboard, or CLI.

View details
84
Repo Health
85
Technical
65
Dependency
Built with
TypeScript 93%
Updated 1 weeks ago
Elixir
55%
Other

Operately

AI Assistants · Collaboration · Productivity

592

The open source company operating system that unifies OKRs, projects, and team execution with built-in accountability cadences.

View details
86
Repo Health
80
Technical
74
Dependency
Built with
Elixir 55%
TypeScript 44%
Updated 1 weeks ago
TypeScript
98%
Other

Outline

Collaboration · Knowledge Management

41,045

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 98%
Updated 1 weeks ago
Python
55%
Other

PostHog

Ab Testing Experimentation · Analytics · Developer Tools

40,397

The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.

View details
92
Repo Health
80
Technical
65
Dependency
Built with
Python 55%
TypeScript 36%
Updated 1 weeks ago
TypeScript
96%
Other

Refly

AI Development · Automation · No Code Platforms

7,537

Build deterministic, versioned agent skills from natural language—run them anywhere from Claude Code to Slack.

View details
68
Repo Health
76
Technical
63
Dependency
Built with
TypeScript 96%
Updated 1 weeks ago
TypeScript
98%
Apache 2.0

rowboat

AI Assistants · AI Development

18,060

Build, test, and deploy multi-agent AI workflows with a visual editor, RAG data sources, MCP tool integration, and a production-ready REST API.

View details
88
Repo Health
72
Technical
65
Dependency
Built with
TypeScript 98%
Updated 1 weeks 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