0
# @milkdown/transformer
1
2
@milkdown/transformer is a TypeScript library that provides bidirectional transformation between markdown AST and ProseMirror document structures. It serves as a critical bridge component in the Milkdown ecosystem, enabling seamless conversion between markdown source and the editor's internal document representation while maintaining semantic consistency and supporting extensible parser/serializer specifications.
3
4
## Package Information
5
6
- **Package Name**: @milkdown/transformer
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @milkdown/transformer`
10
11
## Core Imports
12
13
```typescript
14
import {
15
ParserState,
16
SerializerState,
17
Parser,
18
Serializer,
19
NodeParserSpec,
20
MarkParserSpec,
21
NodeSerializerSpec,
22
MarkSerializerSpec
23
} from "@milkdown/transformer";
24
```
25
26
For CommonJS:
27
28
```javascript
29
const {
30
ParserState,
31
SerializerState
32
} = require("@milkdown/transformer");
33
```
34
35
**External Dependencies:**
36
37
This package integrates with ProseMirror and remark. Key external types include:
38
39
```typescript
40
// From @milkdown/prose/model (ProseMirror types)
41
import type {
42
Schema, // ProseMirror schema definition
43
Node, // ProseMirror document node
44
NodeType, // ProseMirror node type
45
MarkType, // ProseMirror mark type
46
NodeSpec, // ProseMirror node specification
47
MarkSpec, // ProseMirror mark specification
48
Attrs, // Node/mark attributes object
49
Fragment, // Collection of ProseMirror nodes
50
Mark // ProseMirror mark instance
51
} from "@milkdown/prose/model";
52
53
// From remark ecosystem
54
import type { remark } from "remark";
55
import type { Plugin, Transformer } from "unified";
56
```
57
58
## Basic Usage
59
60
```typescript
61
import { ParserState, SerializerState } from "@milkdown/transformer";
62
import { remark } from "remark";
63
import { schema } from "@milkdown/prose/model";
64
65
// Create parser to convert markdown to ProseMirror
66
const parser = ParserState.create(schema, remark());
67
const prosemirrorDoc = parser("# Hello World\n\nThis is **bold** text.");
68
69
// Create serializer to convert ProseMirror to markdown
70
const serializer = SerializerState.create(schema, remark());
71
const markdown = serializer(prosemirrorDoc);
72
73
console.log(markdown); // "# Hello World\n\nThis is **bold** text."
74
```
75
76
## Architecture
77
78
@milkdown/transformer is built around several key components:
79
80
- **Parser System**: `ParserState` class providing a state machine for transforming markdown AST to ProseMirror nodes
81
- **Serializer System**: `SerializerState` class providing a state machine for transforming ProseMirror nodes to markdown AST
82
- **Specification System**: Interfaces for defining custom node and mark transformations (`NodeParserSpec`, `MarkParserSpec`, etc.)
83
- **Stack System**: Generic stack implementations for managing nested transformation contexts
84
- **Type System**: Comprehensive TypeScript interfaces and utilities for markdown and ProseMirror integration
85
86
## Capabilities
87
88
### Parser System
89
90
State machine and specification system for converting markdown AST into ProseMirror document structures with extensible node and mark processing.
91
92
```typescript { .api }
93
class ParserState extends Stack<Node, ParserStackElement> {
94
static create(schema: Schema, remark: RemarkParser): Parser;
95
injectRoot(node: MarkdownNode, nodeType: NodeType, attrs?: Attrs): ParserState;
96
openNode(nodeType: NodeType, attrs?: Attrs): ParserState;
97
closeNode(): ParserState;
98
addNode(nodeType: NodeType, attrs?: Attrs, content?: Node[]): ParserState;
99
openMark(markType: MarkType, attrs?: Attrs): ParserState;
100
closeMark(markType: MarkType): ParserState;
101
addText(text: string): ParserState;
102
next(nodes: MarkdownNode | MarkdownNode[]): ParserState;
103
toDoc(): Node;
104
run(remark: RemarkParser, markdown: string): ParserState;
105
}
106
107
type Parser = (text: string) => Node;
108
```
109
110
[Parser System](./parser.md)
111
112
### Serializer System
113
114
State machine and specification system for converting ProseMirror document structures into markdown AST with extensible node and mark processing.
115
116
```typescript { .api }
117
class SerializerState extends Stack<MarkdownNode, SerializerStackElement> {
118
static create(schema: Schema, remark: RemarkParser): Serializer;
119
openNode(type: string, value?: string, props?: JSONRecord): SerializerState;
120
closeNode(): SerializerState;
121
addNode(type: string, children?: MarkdownNode[], value?: string, props?: JSONRecord): SerializerState;
122
withMark(mark: Mark, type: string, value?: string, props?: JSONRecord): SerializerState;
123
closeMark(mark: Mark): SerializerState;
124
next(nodes: Node | Fragment): SerializerState;
125
toString(remark: RemarkParser): string;
126
run(tree: Node): SerializerState;
127
}
128
129
type Serializer = (content: Node) => string;
130
```
131
132
[Serializer System](./serializer.md)
133
134
### Specification System
135
136
Interfaces and types for defining custom transformation behavior between markdown and ProseMirror elements.
137
138
```typescript { .api }
139
interface NodeParserSpec {
140
match: (node: MarkdownNode) => boolean;
141
runner: (state: ParserState, node: MarkdownNode, proseType: NodeType) => void;
142
}
143
144
interface MarkParserSpec {
145
match: (node: MarkdownNode) => boolean;
146
runner: (state: ParserState, node: MarkdownNode, proseType: MarkType) => void;
147
}
148
149
interface NodeSerializerSpec {
150
match: (node: Node) => boolean;
151
runner: (state: SerializerState, node: Node) => void;
152
}
153
154
interface MarkSerializerSpec {
155
match: (mark: Mark) => boolean;
156
runner: (state: SerializerState, mark: Mark, node: Node) => void | boolean;
157
}
158
```
159
160
[Specification System](./specifications.md)
161
162
### Utility System
163
164
Base classes, type definitions, and utility functions for stack management and type safety.
165
166
```typescript { .api }
167
class Stack<Node, Element extends StackElement<Node>> {
168
size(): number;
169
top(): Element | undefined;
170
push(node: Node): void;
171
open(node: Element): void;
172
close(): Element;
173
}
174
175
abstract class StackElement<Node> {
176
abstract push(node: Node, ...rest: Node[]): void;
177
}
178
179
type RemarkParser = ReturnType<typeof remark>;
180
type MarkdownNode = Node & { children?: MarkdownNode[] };
181
```
182
183
[Utility System](./utilities.md)
184
185
## Types
186
187
```typescript { .api }
188
interface NodeSchema extends NodeSpec {
189
readonly toMarkdown: NodeSerializerSpec;
190
readonly parseMarkdown: NodeParserSpec;
191
readonly priority?: number;
192
}
193
194
interface MarkSchema extends MarkSpec {
195
readonly toMarkdown: MarkSerializerSpec;
196
readonly parseMarkdown: MarkParserSpec;
197
}
198
199
interface RemarkPlugin<T = Record<string, unknown>> {
200
plugin: Plugin<[T], Root>;
201
options: T;
202
}
203
204
type JSONRecord = Record<string, JSONValue>;
205
type JSONValue = string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue };
206
```