@jvs-milkdown/transformer 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/lib/index.d.ts +4 -0
  4. package/lib/index.d.ts.map +1 -0
  5. package/lib/index.js +384 -0
  6. package/lib/index.js.map +1 -0
  7. package/lib/parser/index.d.ts +3 -0
  8. package/lib/parser/index.d.ts.map +1 -0
  9. package/lib/parser/stack-element.d.ts +12 -0
  10. package/lib/parser/stack-element.d.ts.map +1 -0
  11. package/lib/parser/stack-element.spec.d.ts +2 -0
  12. package/lib/parser/stack-element.spec.d.ts.map +1 -0
  13. package/lib/parser/state.d.ts +23 -0
  14. package/lib/parser/state.d.ts.map +1 -0
  15. package/lib/parser/state.spec.d.ts +2 -0
  16. package/lib/parser/state.spec.d.ts.map +1 -0
  17. package/lib/parser/types.d.ts +13 -0
  18. package/lib/parser/types.d.ts.map +1 -0
  19. package/lib/serializer/index.d.ts +3 -0
  20. package/lib/serializer/index.d.ts.map +1 -0
  21. package/lib/serializer/stack-element.d.ts +14 -0
  22. package/lib/serializer/stack-element.d.ts.map +1 -0
  23. package/lib/serializer/stack-element.spec.d.ts +2 -0
  24. package/lib/serializer/stack-element.spec.d.ts.map +1 -0
  25. package/lib/serializer/state.d.ts +22 -0
  26. package/lib/serializer/state.d.ts.map +1 -0
  27. package/lib/serializer/state.spec.d.ts +2 -0
  28. package/lib/serializer/state.spec.d.ts.map +1 -0
  29. package/lib/serializer/types.d.ts +12 -0
  30. package/lib/serializer/types.d.ts.map +1 -0
  31. package/lib/tsconfig.tsbuildinfo +1 -0
  32. package/lib/utility/index.d.ts +3 -0
  33. package/lib/utility/index.d.ts.map +1 -0
  34. package/lib/utility/stack.d.ts +12 -0
  35. package/lib/utility/stack.d.ts.map +1 -0
  36. package/lib/utility/stack.spec.d.ts +2 -0
  37. package/lib/utility/stack.spec.d.ts.map +1 -0
  38. package/lib/utility/types.d.ts +31 -0
  39. package/lib/utility/types.d.ts.map +1 -0
  40. package/package.json +39 -0
  41. package/src/index.ts +3 -0
  42. package/src/parser/index.ts +2 -0
  43. package/src/parser/stack-element.spec.ts +25 -0
  44. package/src/parser/stack-element.ts +25 -0
  45. package/src/parser/state.spec.ts +265 -0
  46. package/src/parser/state.ts +217 -0
  47. package/src/parser/types.ts +55 -0
  48. package/src/serializer/index.ts +2 -0
  49. package/src/serializer/stack-element.spec.ts +17 -0
  50. package/src/serializer/stack-element.ts +30 -0
  51. package/src/serializer/state.spec.ts +287 -0
  52. package/src/serializer/state.ts +355 -0
  53. package/src/serializer/types.ts +51 -0
  54. package/src/utility/index.ts +2 -0
  55. package/src/utility/stack.spec.ts +30 -0
  56. package/src/utility/stack.ts +48 -0
  57. package/src/utility/types.ts +63 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020-present Mirone
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # @jvs-milkdown/transformer
2
+
3
+ The transformer module of [milkdown](https://milkdown.dev/).
4
+
5
+ # Official Documentation
6
+
7
+ Documentation can be found on the [Milkdown website](https://milkdown.dev/).
8
+
9
+ # License
10
+
11
+ Milkdown is open sourced software licensed under [MIT license](https://github.com/Milkdown/milkdown/blob/main/LICENSE).
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './parser';
2
+ export * from './serializer';
3
+ export * from './utility';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA"}
package/lib/index.js ADDED
@@ -0,0 +1,384 @@
1
+ import { createNodeInParserFail, parserMatchError, serializerMatchError, stackOverFlow } from "@jvs-milkdown/exception";
2
+ import { Mark } from "@jvs-milkdown/prose/model";
3
+ //#region src/utility/stack.ts
4
+ var StackElement = class {};
5
+ var Stack = class {
6
+ constructor() {
7
+ this.elements = [];
8
+ this.size = () => {
9
+ return this.elements.length;
10
+ };
11
+ this.top = () => {
12
+ return this.elements.at(-1);
13
+ };
14
+ this.push = (node) => {
15
+ this.top()?.push(node);
16
+ };
17
+ this.open = (node) => {
18
+ this.elements.push(node);
19
+ };
20
+ this.close = () => {
21
+ const el = this.elements.pop();
22
+ if (!el) throw stackOverFlow();
23
+ return el;
24
+ };
25
+ }
26
+ };
27
+ //#endregion
28
+ //#region src/parser/stack-element.ts
29
+ var ParserStackElement = class ParserStackElement extends StackElement {
30
+ constructor(type, content, attrs) {
31
+ super();
32
+ this.type = type;
33
+ this.content = content;
34
+ this.attrs = attrs;
35
+ }
36
+ push(node, ...rest) {
37
+ this.content.push(node, ...rest);
38
+ }
39
+ pop() {
40
+ return this.content.pop();
41
+ }
42
+ static create(type, content, attrs) {
43
+ return new ParserStackElement(type, content, attrs);
44
+ }
45
+ };
46
+ //#endregion
47
+ //#region src/parser/state.ts
48
+ var ParserState = class extends Stack {
49
+ #marks = Mark.none;
50
+ static {
51
+ this.create = (schema, remark) => {
52
+ const state = new this(schema);
53
+ return (text) => {
54
+ state.run(remark, text);
55
+ return state.toDoc();
56
+ };
57
+ };
58
+ }
59
+ constructor(schema) {
60
+ super();
61
+ this.injectRoot = (node, nodeType, attrs) => {
62
+ this.openNode(nodeType, attrs);
63
+ this.next(node.children);
64
+ return this;
65
+ };
66
+ this.openNode = (nodeType, attrs) => {
67
+ this.open(ParserStackElement.create(nodeType, [], attrs));
68
+ return this;
69
+ };
70
+ this.closeNode = () => {
71
+ try {
72
+ this.#closeNodeAndPush();
73
+ } catch (e) {
74
+ console.error(e);
75
+ }
76
+ return this;
77
+ };
78
+ this.addNode = (nodeType, attrs, content) => {
79
+ try {
80
+ this.#addNodeAndPush(nodeType, attrs, content);
81
+ } catch (e) {
82
+ console.error(e);
83
+ }
84
+ return this;
85
+ };
86
+ this.openMark = (markType, attrs) => {
87
+ this.#marks = markType.create(attrs).addToSet(this.#marks);
88
+ return this;
89
+ };
90
+ this.closeMark = (markType) => {
91
+ this.#marks = markType.removeFromSet(this.#marks);
92
+ return this;
93
+ };
94
+ this.addText = (text) => {
95
+ try {
96
+ const topElement = this.top();
97
+ if (!topElement) throw stackOverFlow();
98
+ const prevNode = topElement.pop();
99
+ const currNode = this.schema.text(text, this.#marks);
100
+ if (!prevNode) {
101
+ topElement.push(currNode);
102
+ return this;
103
+ }
104
+ const merged = this.#maybeMerge(prevNode, currNode);
105
+ if (merged) {
106
+ topElement.push(merged);
107
+ return this;
108
+ }
109
+ topElement.push(prevNode, currNode);
110
+ return this;
111
+ } catch (e) {
112
+ console.error(e);
113
+ return this;
114
+ }
115
+ };
116
+ this.build = () => {
117
+ let doc;
118
+ do
119
+ doc = this.#closeNodeAndPush();
120
+ while (this.size());
121
+ return doc;
122
+ };
123
+ this.next = (nodes = []) => {
124
+ [nodes].flat().forEach((node) => this.#runNode(node));
125
+ return this;
126
+ };
127
+ this.toDoc = () => this.build();
128
+ this.run = (remark, markdown) => {
129
+ const tree = remark.runSync(remark.parse(markdown), markdown);
130
+ this.next(tree);
131
+ return this;
132
+ };
133
+ this.schema = schema;
134
+ }
135
+ #hasText = (node) => node.isText;
136
+ #maybeMerge = (a, b) => {
137
+ if (this.#hasText(a) && this.#hasText(b) && Mark.sameSet(a.marks, b.marks)) return this.schema.text(a.text + b.text, a.marks);
138
+ };
139
+ #matchTarget = (node) => {
140
+ const result = Object.values({
141
+ ...this.schema.nodes,
142
+ ...this.schema.marks
143
+ }).find((x) => {
144
+ return x.spec.parseMarkdown.match(node);
145
+ });
146
+ if (!result) throw parserMatchError(node);
147
+ return result;
148
+ };
149
+ #runNode = (node) => {
150
+ const type = this.#matchTarget(node);
151
+ type.spec.parseMarkdown.runner(this, node, type);
152
+ };
153
+ #closeNodeAndPush = () => {
154
+ this.#marks = Mark.none;
155
+ const element = this.close();
156
+ return this.#addNodeAndPush(element.type, element.attrs, element.content);
157
+ };
158
+ #addNodeAndPush = (nodeType, attrs, content) => {
159
+ const node = nodeType.createAndFill(attrs, content, this.#marks);
160
+ if (!node) throw createNodeInParserFail(nodeType, attrs, content);
161
+ this.push(node);
162
+ return node;
163
+ };
164
+ };
165
+ //#endregion
166
+ //#region src/serializer/stack-element.ts
167
+ var SerializerStackElement = class SerializerStackElement extends StackElement {
168
+ constructor(type, children, value, props = {}) {
169
+ super();
170
+ this.type = type;
171
+ this.children = children;
172
+ this.value = value;
173
+ this.props = props;
174
+ this.push = (node, ...rest) => {
175
+ if (!this.children) this.children = [];
176
+ this.children.push(node, ...rest);
177
+ };
178
+ this.pop = () => this.children?.pop();
179
+ }
180
+ static {
181
+ this.create = (type, children, value, props = {}) => new SerializerStackElement(type, children, value, props);
182
+ }
183
+ };
184
+ //#endregion
185
+ //#region src/serializer/state.ts
186
+ var isFragment = (x) => Object.prototype.hasOwnProperty.call(x, "size");
187
+ var SerializerState = class extends Stack {
188
+ #marks = Mark.none;
189
+ static {
190
+ this.create = (schema, remark) => {
191
+ const state = new this(schema);
192
+ return (content) => {
193
+ state.run(content);
194
+ return state.toString(remark);
195
+ };
196
+ };
197
+ }
198
+ constructor(schema) {
199
+ super();
200
+ this.openNode = (type, value, props) => {
201
+ this.open(SerializerStackElement.create(type, void 0, value, props));
202
+ return this;
203
+ };
204
+ this.closeNode = () => {
205
+ this.#closeNodeAndPush();
206
+ return this;
207
+ };
208
+ this.addNode = (type, children, value, props) => {
209
+ this.#addNodeAndPush(type, children, value, props);
210
+ return this;
211
+ };
212
+ this.withMark = (mark, type, value, props) => {
213
+ this.#openMark(mark, type, value, props);
214
+ return this;
215
+ };
216
+ this.closeMark = (mark) => {
217
+ this.#closeMark(mark);
218
+ return this;
219
+ };
220
+ this.build = () => {
221
+ let doc = null;
222
+ do
223
+ doc = this.#closeNodeAndPush();
224
+ while (this.size());
225
+ return doc;
226
+ };
227
+ this.next = (nodes) => {
228
+ if (isFragment(nodes)) {
229
+ nodes.forEach((node) => {
230
+ this.#runNode(node);
231
+ });
232
+ return this;
233
+ }
234
+ this.#runNode(nodes);
235
+ return this;
236
+ };
237
+ this.toString = (remark) => remark.stringify(this.build());
238
+ this.run = (tree) => {
239
+ this.next(tree);
240
+ return this;
241
+ };
242
+ this.schema = schema;
243
+ }
244
+ #matchTarget = (node) => {
245
+ const result = Object.values({
246
+ ...this.schema.nodes,
247
+ ...this.schema.marks
248
+ }).find((x) => {
249
+ return x.spec.toMarkdown.match(node);
250
+ });
251
+ if (!result) throw serializerMatchError(node.type);
252
+ return result;
253
+ };
254
+ #runProseNode = (node) => {
255
+ return this.#matchTarget(node).spec.toMarkdown.runner(this, node);
256
+ };
257
+ #runProseMark = (mark, node) => {
258
+ return this.#matchTarget(mark).spec.toMarkdown.runner(this, mark, node);
259
+ };
260
+ #runNode = (node) => {
261
+ const { marks } = node;
262
+ const getPriority = (x) => x.type.spec.priority ?? 50;
263
+ if ([...marks].sort((a, b) => getPriority(a) - getPriority(b)).every((mark) => !this.#runProseMark(mark, node))) this.#runProseNode(node);
264
+ marks.forEach((mark) => this.#closeMark(mark));
265
+ };
266
+ #searchType = (child, type) => {
267
+ if (child.type === type) return child;
268
+ if (child.children?.length !== 1) return child;
269
+ const searchNode = (node) => {
270
+ if (node.type === type) return node.value != null ? null : node;
271
+ if (node.children?.length !== 1) return null;
272
+ const [firstChild] = node.children;
273
+ if (!firstChild) return null;
274
+ return searchNode(firstChild);
275
+ };
276
+ const target = searchNode(child);
277
+ if (!target) return child;
278
+ const tmp = target.children ? [...target.children] : void 0;
279
+ const node = {
280
+ ...child,
281
+ children: tmp
282
+ };
283
+ node.children = tmp;
284
+ target.children = [node];
285
+ return target;
286
+ };
287
+ #maybeMergeChildren = (node) => {
288
+ const { children } = node;
289
+ if (!children) return node;
290
+ node.children = children.reduce((nextChildren, child, index) => {
291
+ if (index === 0) return [child];
292
+ const last = nextChildren.at(-1);
293
+ if (last && last.isMark && child.isMark) {
294
+ child = this.#searchType(child, last.type);
295
+ const { children: currChildren, ...currRest } = child;
296
+ const { children: prevChildren, ...prevRest } = last;
297
+ if (child.type === last.type && currChildren && prevChildren && JSON.stringify(currRest) === JSON.stringify(prevRest)) {
298
+ const next = {
299
+ ...prevRest,
300
+ children: [...prevChildren, ...currChildren]
301
+ };
302
+ return nextChildren.slice(0, -1).concat(this.#maybeMergeChildren(next));
303
+ }
304
+ }
305
+ return nextChildren.concat(child);
306
+ }, []);
307
+ return node;
308
+ };
309
+ #createMarkdownNode = (element) => {
310
+ const node = {
311
+ ...element.props,
312
+ type: element.type
313
+ };
314
+ if (element.children) node.children = element.children;
315
+ if (element.value) node.value = element.value;
316
+ return node;
317
+ };
318
+ #moveSpaces = (element, onPush) => {
319
+ let startSpaces = "";
320
+ let endSpaces = "";
321
+ const children = element.children;
322
+ let first = -1;
323
+ let last = -1;
324
+ const findIndex = (node) => {
325
+ if (!node) return;
326
+ node.forEach((child, index) => {
327
+ if (child.type === "text" && child.value) {
328
+ if (first < 0) first = index;
329
+ last = index;
330
+ }
331
+ });
332
+ };
333
+ if (children) {
334
+ findIndex(children);
335
+ const lastChild = children?.[last];
336
+ const firstChild = children?.[first];
337
+ if (lastChild && lastChild.value.endsWith(" ")) {
338
+ const text = lastChild.value;
339
+ const trimmed = text.trimEnd();
340
+ endSpaces = text.slice(trimmed.length);
341
+ lastChild.value = trimmed;
342
+ }
343
+ if (firstChild && firstChild.value.startsWith(" ")) {
344
+ const text = firstChild.value;
345
+ const trimmed = text.trimStart();
346
+ startSpaces = text.slice(0, text.length - trimmed.length);
347
+ firstChild.value = trimmed;
348
+ }
349
+ }
350
+ if (startSpaces.length) this.#addNodeAndPush("text", void 0, startSpaces);
351
+ const result = onPush();
352
+ if (endSpaces.length) this.#addNodeAndPush("text", void 0, endSpaces);
353
+ return result;
354
+ };
355
+ #closeNodeAndPush = (trim = false) => {
356
+ const element = this.close();
357
+ const onPush = () => this.#addNodeAndPush(element.type, element.children, element.value, element.props);
358
+ if (trim) return this.#moveSpaces(element, onPush);
359
+ return onPush();
360
+ };
361
+ #addNodeAndPush = (type, children, value, props) => {
362
+ const element = SerializerStackElement.create(type, children, value, props);
363
+ const node = this.#maybeMergeChildren(this.#createMarkdownNode(element));
364
+ this.push(node);
365
+ return node;
366
+ };
367
+ #openMark = (mark, type, value, props) => {
368
+ if (mark.isInSet(this.#marks)) return this;
369
+ this.#marks = mark.addToSet(this.#marks);
370
+ return this.openNode(type, value, {
371
+ ...props,
372
+ isMark: true
373
+ });
374
+ };
375
+ #closeMark = (mark) => {
376
+ if (!mark.isInSet(this.#marks)) return;
377
+ this.#marks = mark.type.removeFromSet(this.#marks);
378
+ this.#closeNodeAndPush(true);
379
+ };
380
+ };
381
+ //#endregion
382
+ export { ParserState, SerializerState, Stack, StackElement };
383
+
384
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["#closeNodeAndPush","#addNodeAndPush","#marks","#maybeMerge","#runNode","#hasText","#matchTarget","#closeNodeAndPush","#addNodeAndPush","#openMark","#closeMark","#runNode","#matchTarget","#runProseMark","#runProseNode","#searchType","#maybeMergeChildren","#moveSpaces","#createMarkdownNode","#marks"],"sources":["../src/utility/stack.ts","../src/parser/stack-element.ts","../src/parser/state.ts","../src/serializer/stack-element.ts","../src/serializer/state.ts"],"sourcesContent":["import { stackOverFlow } from '@jvs-milkdown/exception'\n\n/// The element of the stack, which holds an array of nodes.\nexport abstract class StackElement<Node> {\n /// A method that can `push` a node into the element.\n abstract push(node: Node, ...rest: Node[]): void\n}\n\n/// The stack that is used to store the elements.\n///\n/// > Generally, you don't need to use this class directly.\n///\n/// When using the stack, users can call `stack.open` to push a new element into the stack.\n/// And use `stack.push` to push a node into the top element.\n/// Then use `stack.close` to close the top element and pop it.\n///\n/// For example: `stack.open(A).push(B).push(C).close()` will generate a structure like `A(B, C)`.\nexport class Stack<Node, Element extends StackElement<Node>> {\n protected elements: Element[] = []\n\n /// Get the size of the stack.\n size = (): number => {\n return this.elements.length\n }\n\n /// Get the top element of the stack.\n top = (): Element | undefined => {\n return this.elements.at(-1)\n }\n\n /// Push a node into the top element.\n push = (node: Node): void => {\n this.top()?.push(node)\n }\n\n /// Push a new element.\n open = (node: Element): void => {\n this.elements.push(node)\n }\n\n /// Close the top element and pop it.\n close = (): Element => {\n const el = this.elements.pop()\n if (!el) throw stackOverFlow()\n\n return el\n }\n}\n","import type { Attrs, Node, NodeType } from '@jvs-milkdown/prose/model'\n\nimport { StackElement } from '../utility'\n\nexport class ParserStackElement extends StackElement<Node> {\n constructor(\n public type: NodeType,\n public content: Node[],\n public attrs?: Attrs\n ) {\n super()\n }\n\n push(node: Node, ...rest: Node[]) {\n this.content.push(node, ...rest)\n }\n\n pop(): Node | undefined {\n return this.content.pop()\n }\n\n static create(type: NodeType, content: Node[], attrs?: Attrs) {\n return new ParserStackElement(type, content, attrs)\n }\n}\n","import type {\n Attrs,\n MarkType,\n Node,\n NodeType,\n Schema,\n} from '@jvs-milkdown/prose/model'\n\nimport {\n createNodeInParserFail,\n parserMatchError,\n stackOverFlow,\n} from '@jvs-milkdown/exception'\nimport { Mark } from '@jvs-milkdown/prose/model'\n\nimport type {\n MarkSchema,\n MarkdownNode,\n NodeSchema,\n RemarkParser,\n} from '../utility'\nimport type { Parser } from './types'\n\nimport { Stack } from '../utility'\nimport { ParserStackElement } from './stack-element'\n\n/// A state machine for parser. Transform remark AST into prosemirror state.\nexport class ParserState extends Stack<Node, ParserStackElement> {\n /// The schema in current editor.\n readonly schema: Schema\n\n /// @internal\n #marks: readonly Mark[] = Mark.none\n\n /// Create a parser from schema and remark instance.\n ///\n /// ```typescript\n /// const parser = ParserState.create(schema, remark)\n /// const prosemirrorNode = parser(SomeMarkdownText)\n /// ```\n static create = (schema: Schema, remark: RemarkParser): Parser => {\n const state = new this(schema)\n return (text) => {\n state.run(remark, text)\n return state.toDoc()\n }\n }\n\n /// @internal\n constructor(schema: Schema) {\n super()\n this.schema = schema\n }\n\n /// @internal\n #hasText = (node: Node): node is Node & { text: string } => node.isText\n\n /// @internal\n #maybeMerge = (a: Node, b: Node): Node | undefined => {\n if (this.#hasText(a) && this.#hasText(b) && Mark.sameSet(a.marks, b.marks))\n return this.schema.text(a.text + b.text, a.marks)\n\n return undefined\n }\n\n /// @internal\n #matchTarget = (node: MarkdownNode): NodeType | MarkType => {\n const result = Object.values({\n ...this.schema.nodes,\n ...this.schema.marks,\n }).find((x): x is NodeType | MarkType => {\n const spec = x.spec as NodeSchema | MarkSchema\n return spec.parseMarkdown.match(node)\n })\n\n if (!result) throw parserMatchError(node)\n\n return result\n }\n\n /// @internal\n #runNode = (node: MarkdownNode) => {\n const type = this.#matchTarget(node)\n const spec = type.spec as NodeSchema | MarkSchema\n\n spec.parseMarkdown.runner(this, node, type as NodeType & MarkType)\n }\n\n /// Inject root node for prosemirror state.\n injectRoot = (node: MarkdownNode, nodeType: NodeType, attrs?: Attrs) => {\n this.openNode(nodeType, attrs)\n this.next(node.children)\n\n return this\n }\n\n /// Open a new node, the next operations will\n /// add nodes into that new node until `closeNode` is called.\n openNode = (nodeType: NodeType, attrs?: Attrs) => {\n this.open(ParserStackElement.create(nodeType, [], attrs))\n return this\n }\n\n /// @internal\n #closeNodeAndPush = (): Node => {\n this.#marks = Mark.none\n const element = this.close()\n\n return this.#addNodeAndPush(element.type, element.attrs, element.content)\n }\n\n /// Close the current node and push it into the parent node.\n closeNode = () => {\n try {\n this.#closeNodeAndPush()\n } catch (e) {\n console.error(e)\n }\n return this\n }\n\n /// @internal\n #addNodeAndPush = (\n nodeType: NodeType,\n attrs?: Attrs,\n content?: Node[]\n ): Node => {\n const node = nodeType.createAndFill(attrs, content, this.#marks)\n if (!node) throw createNodeInParserFail(nodeType, attrs, content)\n\n this.push(node)\n\n return node\n }\n\n /// Add a node into current node.\n addNode = (nodeType: NodeType, attrs?: Attrs, content?: Node[]) => {\n try {\n this.#addNodeAndPush(nodeType, attrs, content)\n } catch (e) {\n console.error(e)\n }\n return this\n }\n\n /// Open a new mark, the next nodes added will have that mark.\n openMark = (markType: MarkType, attrs?: Attrs) => {\n const mark = markType.create(attrs)\n\n this.#marks = mark.addToSet(this.#marks)\n return this\n }\n\n /// Close a opened mark.\n closeMark = (markType: MarkType) => {\n this.#marks = markType.removeFromSet(this.#marks)\n return this\n }\n\n /// Add a text node into current node.\n addText = (text: string) => {\n try {\n const topElement = this.top()\n if (!topElement) throw stackOverFlow()\n\n const prevNode = topElement.pop()\n const currNode = this.schema.text(text, this.#marks)\n\n if (!prevNode) {\n topElement.push(currNode)\n return this\n }\n\n const merged = this.#maybeMerge(prevNode, currNode)\n if (merged) {\n topElement.push(merged)\n return this\n }\n topElement.push(prevNode, currNode)\n return this\n } catch (e) {\n console.error(e)\n return this\n }\n }\n\n /// @internal\n build = (): Node => {\n let doc: Node | undefined\n\n do doc = this.#closeNodeAndPush()\n while (this.size())\n\n return doc\n }\n\n /// Give the node or node list back to the state and\n /// the state will find a proper runner (by `match` method in parser spec) to handle it.\n next = (nodes: MarkdownNode | MarkdownNode[] = []) => {\n ;[nodes].flat().forEach((node) => this.#runNode(node))\n return this\n }\n\n /// Build the current state into a [prosemirror document](https://prosemirror.net/docs/ref/#model.Document_Structure).\n toDoc = () => this.build()\n\n /// Transform a markdown string into prosemirror state.\n run = (remark: RemarkParser, markdown: string) => {\n const tree = remark.runSync(\n remark.parse(markdown),\n markdown\n ) as MarkdownNode\n this.next(tree)\n\n return this\n }\n}\n","import type { MarkdownNode } from '..'\nimport type { JSONRecord } from '../utility'\n\nimport { StackElement } from '../utility'\n\nexport class SerializerStackElement extends StackElement<MarkdownNode> {\n constructor(\n public type: string,\n public children?: MarkdownNode[],\n public value?: string,\n public props: JSONRecord = {}\n ) {\n super()\n }\n\n static create = (\n type: string,\n children?: MarkdownNode[],\n value?: string,\n props: JSONRecord = {}\n ) => new SerializerStackElement(type, children, value, props)\n\n push = (node: MarkdownNode, ...rest: MarkdownNode[]) => {\n if (!this.children) this.children = []\n\n this.children.push(node, ...rest)\n }\n\n pop = (): MarkdownNode | undefined => this.children?.pop()\n}\n","import type {\n Fragment,\n MarkType,\n Node,\n NodeType,\n Schema,\n} from '@jvs-milkdown/prose/model'\n\nimport { serializerMatchError } from '@jvs-milkdown/exception'\nimport { Mark } from '@jvs-milkdown/prose/model'\n\nimport type {\n JSONRecord,\n MarkSchema,\n MarkdownNode,\n NodeSchema,\n RemarkParser,\n Root,\n} from '../utility'\nimport type { Serializer } from './types'\n\nimport { Stack } from '../utility'\nimport { SerializerStackElement } from './stack-element'\n\nconst isFragment = (x: Node | Fragment): x is Fragment =>\n Object.prototype.hasOwnProperty.call(x, 'size')\n\n/// State for serializer.\n/// Transform prosemirror state into remark AST.\nexport class SerializerState extends Stack<\n MarkdownNode,\n SerializerStackElement\n> {\n /// @internal\n #marks: readonly Mark[] = Mark.none\n /// Get the schema of state.\n readonly schema: Schema\n\n /// Create a serializer from schema and remark instance.\n ///\n /// ```typescript\n /// const serializer = SerializerState.create(schema, remark)\n /// const markdown = parser(prosemirrorDoc)\n /// ```\n static create = (schema: Schema, remark: RemarkParser): Serializer => {\n const state = new this(schema)\n return (content: Node) => {\n state.run(content)\n return state.toString(remark)\n }\n }\n\n /// @internal\n constructor(schema: Schema) {\n super()\n this.schema = schema\n }\n\n /// @internal\n #matchTarget = (node: Node | Mark): NodeType | MarkType => {\n const result = Object.values({\n ...this.schema.nodes,\n ...this.schema.marks,\n }).find((x): x is NodeType | MarkType => {\n const spec = x.spec as NodeSchema | MarkSchema\n return spec.toMarkdown.match(node as Node & Mark)\n })\n\n if (!result) throw serializerMatchError(node.type)\n\n return result\n }\n\n /// @internal\n #runProseNode = (node: Node) => {\n const type = this.#matchTarget(node)\n const spec = type.spec as NodeSchema\n return spec.toMarkdown.runner(this, node)\n }\n\n /// @internal\n #runProseMark = (mark: Mark, node: Node) => {\n const type = this.#matchTarget(mark)\n const spec = type.spec as MarkSchema\n return spec.toMarkdown.runner(this, mark, node)\n }\n\n /// @internal\n #runNode = (node: Node) => {\n const { marks } = node\n const getPriority = (x: Mark) => x.type.spec.priority ?? 50\n const tmp = [...marks].sort((a, b) => getPriority(a) - getPriority(b))\n const unPreventNext = tmp.every((mark) => !this.#runProseMark(mark, node))\n if (unPreventNext) this.#runProseNode(node)\n\n marks.forEach((mark) => this.#closeMark(mark))\n }\n\n /// @internal\n #searchType = (child: MarkdownNode, type: string): MarkdownNode => {\n if (child.type === type) return child\n\n if (child.children?.length !== 1) return child\n\n const searchNode = (node: MarkdownNode): MarkdownNode | null => {\n if (node.type === type) return node.value != null ? null : node\n\n if (node.children?.length !== 1) return null\n\n const [firstChild] = node.children\n if (!firstChild) return null\n\n return searchNode(firstChild)\n }\n\n const target = searchNode(child)\n\n if (!target) return child\n\n const tmp = target.children ? [...target.children] : undefined\n const node = { ...child, children: tmp }\n node.children = tmp\n target.children = [node]\n\n return target\n }\n\n /// @internal\n #maybeMergeChildren = (node: MarkdownNode): MarkdownNode => {\n const { children } = node\n if (!children) return node\n\n node.children = children.reduce((nextChildren, child, index) => {\n if (index === 0) return [child]\n\n const last = nextChildren.at(-1)\n if (last && last.isMark && child.isMark) {\n child = this.#searchType(child, last.type)\n const { children: currChildren, ...currRest } = child\n const { children: prevChildren, ...prevRest } = last\n if (\n child.type === last.type &&\n currChildren &&\n prevChildren &&\n JSON.stringify(currRest) === JSON.stringify(prevRest)\n ) {\n const next = {\n ...prevRest,\n children: [...prevChildren, ...currChildren],\n }\n return nextChildren\n .slice(0, -1)\n .concat(this.#maybeMergeChildren(next))\n }\n }\n return nextChildren.concat(child)\n }, [] as MarkdownNode[])\n\n return node\n }\n\n /// @internal\n #createMarkdownNode = (element: SerializerStackElement) => {\n const node: MarkdownNode = {\n ...element.props,\n type: element.type,\n }\n\n if (element.children) node.children = element.children\n\n if (element.value) node.value = element.value\n\n return node\n }\n\n /// Open a new node, the next operations will\n /// add nodes into that new node until `closeNode` is called.\n openNode = (type: string, value?: string, props?: JSONRecord) => {\n this.open(SerializerStackElement.create(type, undefined, value, props))\n return this\n }\n\n #moveSpaces = (\n element: SerializerStackElement,\n onPush: () => MarkdownNode\n ) => {\n let startSpaces = ''\n let endSpaces = ''\n const children = element.children\n let first = -1\n let last = -1\n const findIndex = (node: MarkdownNode[]) => {\n if (!node) return\n node.forEach((child, index) => {\n if (child.type === 'text' && child.value) {\n if (first < 0) first = index\n\n last = index\n }\n })\n }\n\n if (children) {\n findIndex(children)\n const lastChild = children?.[last] as\n | (MarkdownNode & { value: string })\n | undefined\n const firstChild = children?.[first] as\n | (MarkdownNode & { value: string })\n | undefined\n if (lastChild && lastChild.value.endsWith(' ')) {\n const text = lastChild.value\n const trimmed = text.trimEnd()\n endSpaces = text.slice(trimmed.length)\n lastChild.value = trimmed\n }\n if (firstChild && firstChild.value.startsWith(' ')) {\n const text = firstChild.value\n const trimmed = text.trimStart()\n startSpaces = text.slice(0, text.length - trimmed.length)\n firstChild.value = trimmed\n }\n }\n\n if (startSpaces.length) this.#addNodeAndPush('text', undefined, startSpaces)\n\n const result = onPush()\n\n if (endSpaces.length) this.#addNodeAndPush('text', undefined, endSpaces)\n\n return result\n }\n\n /// @internal\n #closeNodeAndPush = (trim: boolean = false): MarkdownNode => {\n const element = this.close()\n\n const onPush = () =>\n this.#addNodeAndPush(\n element.type,\n element.children,\n element.value,\n element.props\n )\n\n if (trim) return this.#moveSpaces(element, onPush)\n\n return onPush()\n }\n\n /// Close the current node and push it into the parent node.\n closeNode = () => {\n this.#closeNodeAndPush()\n return this\n }\n\n /// @internal\n #addNodeAndPush = (\n type: string,\n children?: MarkdownNode[],\n value?: string,\n props?: JSONRecord\n ): MarkdownNode => {\n const element = SerializerStackElement.create(type, children, value, props)\n const node: MarkdownNode = this.#maybeMergeChildren(\n this.#createMarkdownNode(element)\n )\n this.push(node)\n return node\n }\n\n /// Add a node into current node.\n addNode = (\n type: string,\n children?: MarkdownNode[],\n value?: string,\n props?: JSONRecord\n ) => {\n this.#addNodeAndPush(type, children, value, props)\n return this\n }\n\n /// @internal\n #openMark = (\n mark: Mark,\n type: string,\n value?: string,\n props?: JSONRecord\n ) => {\n const isIn = mark.isInSet(this.#marks)\n\n if (isIn) return this\n\n this.#marks = mark.addToSet(this.#marks)\n return this.openNode(type, value, { ...props, isMark: true })\n }\n\n /// @internal\n #closeMark = (mark: Mark): void => {\n const isIn = mark.isInSet(this.#marks)\n\n if (!isIn) return\n\n this.#marks = mark.type.removeFromSet(this.#marks)\n this.#closeNodeAndPush(true)\n }\n\n /// Open a new mark, the next nodes added will have that mark.\n /// The mark will be closed automatically.\n withMark = (mark: Mark, type: string, value?: string, props?: JSONRecord) => {\n this.#openMark(mark, type, value, props)\n return this\n }\n\n /// Close a opened mark.\n /// In most cases you don't need this because\n /// marks will be closed automatically.\n closeMark = (mark: Mark) => {\n this.#closeMark(mark)\n return this\n }\n\n /// @internal\n build = (): MarkdownNode => {\n let doc: MarkdownNode | null = null\n do doc = this.#closeNodeAndPush()\n while (this.size())\n\n return doc\n }\n\n /// Give the node or node list back to the state and\n /// the state will find a proper runner (by `match` method in serializer spec) to handle it.\n next = (nodes: Node | Fragment) => {\n if (isFragment(nodes)) {\n nodes.forEach((node) => {\n this.#runNode(node)\n })\n return this\n }\n this.#runNode(nodes)\n return this\n }\n\n /// Use a remark parser to serialize current AST stored.\n override toString = (remark: RemarkParser): string =>\n remark.stringify(this.build() as Root)\n\n /// Transform a prosemirror node tree into remark AST.\n run = (tree: Node) => {\n this.next(tree)\n\n return this\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export * from './state';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
@@ -0,0 +1,12 @@
1
+ import type { Attrs, Node, NodeType } from '@jvs-milkdown/prose/model';
2
+ import { StackElement } from '../utility';
3
+ export declare class ParserStackElement extends StackElement<Node> {
4
+ type: NodeType;
5
+ content: Node[];
6
+ attrs?: Attrs | undefined;
7
+ constructor(type: NodeType, content: Node[], attrs?: Attrs | undefined);
8
+ push(node: Node, ...rest: Node[]): void;
9
+ pop(): Node | undefined;
10
+ static create(type: NodeType, content: Node[], attrs?: Attrs): ParserStackElement;
11
+ }
12
+ //# sourceMappingURL=stack-element.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-element.d.ts","sourceRoot":"","sources":["../../src/parser/stack-element.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAEzC,qBAAa,kBAAmB,SAAQ,YAAY,CAAC,IAAI,CAAC;IAE/C,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,IAAI,EAAE;IACf,KAAK,CAAC,EAAE,KAAK;gBAFb,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,IAAI,EAAE,EACf,KAAK,CAAC,EAAE,KAAK,YAAA;IAKtB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE;IAIhC,GAAG,IAAI,IAAI,GAAG,SAAS;IAIvB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,CAAC,EAAE,KAAK;CAG7D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stack-element.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-element.spec.d.ts","sourceRoot":"","sources":["../../src/parser/stack-element.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,23 @@
1
+ import type { Attrs, MarkType, Node, NodeType, Schema } from '@jvs-milkdown/prose/model';
2
+ import type { MarkdownNode, RemarkParser } from '../utility';
3
+ import type { Parser } from './types';
4
+ import { Stack } from '../utility';
5
+ import { ParserStackElement } from './stack-element';
6
+ export declare class ParserState extends Stack<Node, ParserStackElement> {
7
+ #private;
8
+ readonly schema: Schema;
9
+ static create: (schema: Schema, remark: RemarkParser) => Parser;
10
+ constructor(schema: Schema);
11
+ injectRoot: (node: MarkdownNode, nodeType: NodeType, attrs?: Attrs) => this;
12
+ openNode: (nodeType: NodeType, attrs?: Attrs) => this;
13
+ closeNode: () => this;
14
+ addNode: (nodeType: NodeType, attrs?: Attrs, content?: Node[]) => this;
15
+ openMark: (markType: MarkType, attrs?: Attrs) => this;
16
+ closeMark: (markType: MarkType) => this;
17
+ addText: (text: string) => this;
18
+ build: () => Node;
19
+ next: (nodes?: MarkdownNode | MarkdownNode[]) => this;
20
+ toDoc: () => Node;
21
+ run: (remark: RemarkParser, markdown: string) => this;
22
+ }
23
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/parser/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,MAAM,EACP,MAAM,2BAA2B,CAAA;AASlC,OAAO,KAAK,EAEV,YAAY,EAEZ,YAAY,EACb,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAGpD,qBAAa,WAAY,SAAQ,KAAK,CAAC,IAAI,EAAE,kBAAkB,CAAC;;IAE9D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IAWvB,MAAM,CAAC,MAAM,GAAI,QAAQ,MAAM,EAAE,QAAQ,YAAY,KAAG,MAAM,CAM7D;gBAGW,MAAM,EAAE,MAAM;IAwC1B,UAAU,GAAI,MAAM,YAAY,EAAE,UAAU,QAAQ,EAAE,QAAQ,KAAK,UAKlE;IAID,QAAQ,GAAI,UAAU,QAAQ,EAAE,QAAQ,KAAK,UAG5C;IAWD,SAAS,aAOR;IAiBD,OAAO,GAAI,UAAU,QAAQ,EAAE,QAAQ,KAAK,EAAE,UAAU,IAAI,EAAE,UAO7D;IAGD,QAAQ,GAAI,UAAU,QAAQ,EAAE,QAAQ,KAAK,UAK5C;IAGD,SAAS,GAAI,UAAU,QAAQ,UAG9B;IAGD,OAAO,GAAI,MAAM,MAAM,UAwBtB;IAGD,KAAK,QAAO,IAAI,CAOf;IAID,IAAI,GAAI,QAAO,YAAY,GAAG,YAAY,EAAO,UAGhD;IAGD,KAAK,aAAqB;IAG1B,GAAG,GAAI,QAAQ,YAAY,EAAE,UAAU,MAAM,UAQ5C;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=state.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.spec.d.ts","sourceRoot":"","sources":["../../src/parser/state.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ import type { MarkType, Node, NodeType } from '@jvs-milkdown/prose/model';
2
+ import type { MarkdownNode } from '../utility/types';
3
+ import type { ParserState } from './state';
4
+ export type Parser = (text: string) => Node;
5
+ export interface NodeParserSpec {
6
+ match: (node: MarkdownNode) => boolean;
7
+ runner: (state: ParserState, node: MarkdownNode, proseType: NodeType) => void;
8
+ }
9
+ export interface MarkParserSpec {
10
+ match: (node: MarkdownNode) => boolean;
11
+ runner: (state: ParserState, node: MarkdownNode, proseType: MarkType) => void;
12
+ }
13
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/parser/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAEzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAG1C,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAG3C,MAAM,WAAW,cAAc;IAO7B,KAAK,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAA;IAatC,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,KAAK,IAAI,CAAA;CAC9E;AAGD,MAAM,WAAW,cAAc;IAO7B,KAAK,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAA;IAatC,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,KAAK,IAAI,CAAA;CAC9E"}
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export * from './state';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/serializer/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
@@ -0,0 +1,14 @@
1
+ import type { MarkdownNode } from '..';
2
+ import type { JSONRecord } from '../utility';
3
+ import { StackElement } from '../utility';
4
+ export declare class SerializerStackElement extends StackElement<MarkdownNode> {
5
+ type: string;
6
+ children?: MarkdownNode[] | undefined;
7
+ value?: string | undefined;
8
+ props: JSONRecord;
9
+ constructor(type: string, children?: MarkdownNode[] | undefined, value?: string | undefined, props?: JSONRecord);
10
+ static create: (type: string, children?: MarkdownNode[], value?: string, props?: JSONRecord) => SerializerStackElement;
11
+ push: (node: MarkdownNode, ...rest: MarkdownNode[]) => void;
12
+ pop: () => MarkdownNode | undefined;
13
+ }
14
+ //# sourceMappingURL=stack-element.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-element.d.ts","sourceRoot":"","sources":["../../src/serializer/stack-element.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAEzC,qBAAa,sBAAuB,SAAQ,YAAY,CAAC,YAAY,CAAC;IAE3D,IAAI,EAAE,MAAM;IACZ,QAAQ,CAAC,EAAE,YAAY,EAAE;IACzB,KAAK,CAAC,EAAE,MAAM;IACd,KAAK,EAAE,UAAU;gBAHjB,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,YAAY,EAAE,YAAA,EACzB,KAAK,CAAC,EAAE,MAAM,YAAA,EACd,KAAK,GAAE,UAAe;IAK/B,MAAM,CAAC,MAAM,GACX,MAAM,MAAM,EACZ,WAAW,YAAY,EAAE,EACzB,QAAQ,MAAM,EACd,QAAO,UAAe,4BACqC;IAE7D,IAAI,GAAI,MAAM,YAAY,EAAE,GAAG,MAAM,YAAY,EAAE,UAIlD;IAED,GAAG,QAAO,YAAY,GAAG,SAAS,CAAwB;CAC3D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stack-element.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-element.spec.d.ts","sourceRoot":"","sources":["../../src/serializer/stack-element.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import type { Fragment, Node, Schema } from '@jvs-milkdown/prose/model';
2
+ import { Mark } from '@jvs-milkdown/prose/model';
3
+ import type { JSONRecord, MarkdownNode, RemarkParser } from '../utility';
4
+ import type { Serializer } from './types';
5
+ import { Stack } from '../utility';
6
+ import { SerializerStackElement } from './stack-element';
7
+ export declare class SerializerState extends Stack<MarkdownNode, SerializerStackElement> {
8
+ #private;
9
+ readonly schema: Schema;
10
+ static create: (schema: Schema, remark: RemarkParser) => Serializer;
11
+ constructor(schema: Schema);
12
+ openNode: (type: string, value?: string, props?: JSONRecord) => this;
13
+ closeNode: () => this;
14
+ addNode: (type: string, children?: MarkdownNode[], value?: string, props?: JSONRecord) => this;
15
+ withMark: (mark: Mark, type: string, value?: string, props?: JSONRecord) => this;
16
+ closeMark: (mark: Mark) => this;
17
+ build: () => MarkdownNode;
18
+ next: (nodes: Node | Fragment) => this;
19
+ toString: (remark: RemarkParser) => string;
20
+ run: (tree: Node) => this;
21
+ }
22
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/serializer/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EAER,IAAI,EAEJ,MAAM,EACP,MAAM,2BAA2B,CAAA;AAGlC,OAAO,EAAE,IAAI,EAAE,MAAM,2BAA2B,CAAA;AAEhD,OAAO,KAAK,EACV,UAAU,EAEV,YAAY,EAEZ,YAAY,EAEb,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAOxD,qBAAa,eAAgB,SAAQ,KAAK,CACxC,YAAY,EACZ,sBAAsB,CACvB;;IAIC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IAQvB,MAAM,CAAC,MAAM,GAAI,QAAQ,MAAM,EAAE,QAAQ,YAAY,KAAG,UAAU,CAMjE;gBAGW,MAAM,EAAE,MAAM;IA4H1B,QAAQ,GAAI,MAAM,MAAM,EAAE,QAAQ,MAAM,EAAE,QAAQ,UAAU,UAG3D;IAuED,SAAS,aAGR;IAkBD,OAAO,GACL,MAAM,MAAM,EACZ,WAAW,YAAY,EAAE,EACzB,QAAQ,MAAM,EACd,QAAQ,UAAU,UAInB;IA6BD,QAAQ,GAAI,MAAM,IAAI,EAAE,MAAM,MAAM,EAAE,QAAQ,MAAM,EAAE,QAAQ,UAAU,UAGvE;IAKD,SAAS,GAAI,MAAM,IAAI,UAGtB;IAGD,KAAK,QAAO,YAAY,CAMvB;IAID,IAAI,GAAI,OAAO,IAAI,GAAG,QAAQ,UAS7B;IAGQ,QAAQ,GAAI,QAAQ,YAAY,KAAG,MAAM,CACV;IAGxC,GAAG,GAAI,MAAM,IAAI,UAIhB;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=state.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.spec.d.ts","sourceRoot":"","sources":["../../src/serializer/state.spec.ts"],"names":[],"mappings":""}