Nodes vs Marks
Nodes
Nodes are structural pieces of your document. They define the content type and can contain other nodes or text.Examples: Paragraph, Heading, Image, CodeBlock, BulletList
Marks
Marks are formatting applied to text. They annotate nodes without changing the structure.Examples: Bold, Italic, Link, Code, Highlight
Key Differences
Rule of thumb: If it’s a block element or defines structure, it’s a node. If it’s formatting that can be applied to text, it’s a mark.
Creating Nodes
Nodes are created usingNode.create():
/home/daytona/workspace/source/packages/extension-paragraph/src/paragraph.ts:41
Node Configuration
string
required
The unique name of the node.
string
The group(s) this node belongs to. Used in content expressions.Common groups:
'block'- Block-level content'inline'- Inline content'list'- List items
/home/daytona/workspace/source/packages/core/src/Node.ts:83string
What content this node can contain. Uses ProseMirror’s content expression syntax.Source:
/home/daytona/workspace/source/packages/core/src/Node.ts:42boolean
Whether this is an inline node.Source:
/home/daytona/workspace/source/packages/core/src/Node.ts:96boolean
If true, the node is treated as a single unit (cursor cannot enter it).Source:
/home/daytona/workspace/source/packages/core/src/Node.ts:113boolean
default:"true"
Whether the node can be selected.Source:
/home/daytona/workspace/source/packages/core/src/Node.ts:131boolean
default:"false"
Whether the node can be dragged.Source:
/home/daytona/workspace/source/packages/core/src/Node.ts:147boolean
default:"false"
If true, boundaries of this node are treated as boundaries for editing operations.Source:
/home/daytona/workspace/source/packages/core/src/Node.ts:236() => ParseRule[]
Rules for parsing HTML into this node.Source:
/home/daytona/workspace/source/packages/core/src/Node.ts:256({ node, HTMLAttributes }) => DOMOutputSpec
How to render this node to HTML.The
0 indicates where child content should be inserted.Source: /home/daytona/workspace/source/packages/core/src/Node.ts:284() => Attributes
Define custom attributes for the node.Source:
/home/daytona/workspace/source/packages/core/src/Node.ts:326Creating Marks
Marks are created usingMark.create():
/home/daytona/workspace/source/packages/extension-bold/src/bold.tsx:56
Mark Configuration
string
required
The unique name of the mark.
boolean | ((config) => boolean)
Whether the mark should be included when typing at the edge.Source:
/home/daytona/workspace/source/packages/core/src/Mark.ts:32string
Which other marks this mark excludes. Use Source:
'_' to exclude all marks./home/daytona/workspace/source/packages/core/src/Mark.ts:45boolean
Whether the user can exit the mark by pressing the right arrow at the end.Source:
/home/daytona/workspace/source/packages/core/src/Mark.ts:58boolean
Whether the mark should persist when a node is split.Source:
/home/daytona/workspace/source/packages/core/src/Mark.ts:27() => ParseRule[]
Rules for parsing HTML into this mark.Source:
/home/daytona/workspace/source/packages/core/src/Mark.ts:102({ mark, HTMLAttributes }) => DOMOutputSpec
How to render this mark to HTML.Source:
/home/daytona/workspace/source/packages/core/src/Mark.ts:113() => Attributes
Define custom attributes for the mark.Source:
/home/daytona/workspace/source/packages/core/src/Mark.ts:132Content Expressions
Content expressions define what a node can contain. They use a simple syntax:Common Patterns
Node Examples
Block Node: Heading
Inline Node: Mention
Leaf Node: Image
Mark Examples
Simple Mark: Italic
Mark with Attributes: Link
Accessing Node/Mark Types
You can access the ProseMirror types from the schema:Best Practices
Choose the Right Type
- Use nodes for structural content (paragraphs, headings, images)
- Use marks for text formatting (bold, italic, links)
- If it can overlap with other formatting, it should be a mark
- If it defines a block or structure, it should be a node
Define Content Carefully
Think carefully about what content a node should accept:
- Most block nodes use
content: 'inline*' - Container nodes use
content: 'block+' - Leaf nodes (images, etc.) have no content expression
Use Groups
Group similar nodes together:This makes it easier to reference them in content expressions.
Parse and Render Correctly
Ensure your
parseHTML and renderHTML methods handle all variations:- Different HTML tags (
<b>vs<strong>) - Inline styles
- Data attributes
Related
Extensions
Learn about the extension system
Schema
Learn how nodes and marks create the schema
Commands
Learn how to manipulate nodes and marks
Editor
Learn about the Editor class