@supernova-studio/client 0.31.0 → 0.32.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.
- package/dist/index.d.mts +33 -107
- package/dist/index.d.ts +33 -107
- package/dist/index.js +273 -121
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +261 -109
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/api/dto/elements/documentation/group.ts +3 -2
- package/src/yjs/docs-editor/blocks-to-prosemirror.ts +125 -105
- package/src/yjs/docs-editor/list-tree-builder.ts +194 -0
- package/src/yjs/docs-editor/prosemirror/schema.ts +3 -0
- package/src/yjs/docs-editor/prosemirror-to-blocks.ts +1 -1
package/package.json
CHANGED
|
@@ -84,8 +84,9 @@ export const DTOCreateDocumentationTabInput = z.object({
|
|
|
84
84
|
// New group persistent id
|
|
85
85
|
persistentId: z.string().uuid(),
|
|
86
86
|
|
|
87
|
-
//
|
|
88
|
-
|
|
87
|
+
// If this is page, we will attempt to convert it to tab
|
|
88
|
+
// If this is tab group, we will add a new tab to it
|
|
89
|
+
tabContainerPersistentId: z.string(),
|
|
89
90
|
tabName: z.string(),
|
|
90
91
|
});
|
|
91
92
|
|
|
@@ -7,14 +7,12 @@ import {
|
|
|
7
7
|
PageBlockTextSpanAttribute,
|
|
8
8
|
PageBlockItemRichTextValue,
|
|
9
9
|
PageBlockCalloutType,
|
|
10
|
-
PageBlockItemMultiRichTextValue,
|
|
11
10
|
PageBlockTableCellAlignment,
|
|
12
11
|
PageBlockItemTableNode,
|
|
13
12
|
PageBlockItemTableCell,
|
|
14
13
|
PageBlockItemTableValue,
|
|
15
14
|
PageBlockItemTableRow,
|
|
16
15
|
PageBlockDefinitionRichTextOptions,
|
|
17
|
-
PageBlockDefinitionMutiRichTextOptions,
|
|
18
16
|
PageBlockItemImageValue,
|
|
19
17
|
SupernovaException,
|
|
20
18
|
PageSectionItemV2,
|
|
@@ -27,6 +25,7 @@ import { BlockDefinitionUtils, BlockParsingUtils } from "./utils";
|
|
|
27
25
|
import { DocumentationPageEditorModel } from "./model";
|
|
28
26
|
import { prosemirrorJSONToYXmlFragment } from "y-prosemirror";
|
|
29
27
|
import { pmSchema } from "./prosemirror";
|
|
28
|
+
import { ListNode, ListTreeBuilder } from "./list-tree-builder";
|
|
30
29
|
|
|
31
30
|
//
|
|
32
31
|
// Types
|
|
@@ -45,10 +44,6 @@ type RichTextInputWithValue = InputWithProperty & {
|
|
|
45
44
|
richTextPropertyValue: PageBlockItemRichTextValue;
|
|
46
45
|
};
|
|
47
46
|
|
|
48
|
-
type MultiRichTextInputWithValue = InputWithProperty & {
|
|
49
|
-
multiRichTextPropertyValue: PageBlockItemMultiRichTextValue;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
47
|
//
|
|
53
48
|
// Implementation
|
|
54
49
|
//
|
|
@@ -59,6 +54,7 @@ export function pageToYXmlFragment(
|
|
|
59
54
|
fragment: Y.XmlFragment
|
|
60
55
|
): Y.XmlFragment {
|
|
61
56
|
const doc = pageToProsemirrorDoc(page, definitions);
|
|
57
|
+
// console.log(JSON.stringify(doc, null, 2));
|
|
62
58
|
return prosemirrorJSONToYXmlFragment(pmSchema, doc, fragment);
|
|
63
59
|
}
|
|
64
60
|
|
|
@@ -68,42 +64,36 @@ export function pageToProsemirrorDoc(
|
|
|
68
64
|
): ProsemirrorNode {
|
|
69
65
|
const definitionsMap = mapByUnique(definitions, d => d.id);
|
|
70
66
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
.filter(nonNullFilter),
|
|
83
|
-
};
|
|
84
|
-
}
|
|
67
|
+
const children: ProsemirrorNode[] = [];
|
|
68
|
+
let blockBuffer: PageBlockEditorModel[] = [];
|
|
69
|
+
|
|
70
|
+
page.blocks.forEach(b => {
|
|
71
|
+
if (b.type === "Block") {
|
|
72
|
+
blockBuffer.push(b);
|
|
73
|
+
} else if (b.type === "Section") {
|
|
74
|
+
if (blockBuffer.length) {
|
|
75
|
+
children.push(...blocksToProsemirrorNodes(blockBuffer, definitionsMap));
|
|
76
|
+
blockBuffer = [];
|
|
77
|
+
}
|
|
85
78
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
children.push(internalSectionToProsemirrorNode(b, definitionsMap));
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (blockBuffer.length) {
|
|
84
|
+
children.push(...blocksToProsemirrorNodes(blockBuffer, definitionsMap));
|
|
90
85
|
}
|
|
91
86
|
|
|
92
|
-
return
|
|
87
|
+
return {
|
|
88
|
+
type: "doc",
|
|
89
|
+
content: children,
|
|
90
|
+
};
|
|
93
91
|
}
|
|
94
92
|
|
|
95
93
|
//
|
|
96
94
|
// Sections
|
|
97
95
|
//
|
|
98
96
|
|
|
99
|
-
export function sectionToProsemirrorNode(
|
|
100
|
-
section: PageSectionEditorModel,
|
|
101
|
-
definitions: PageBlockDefinition[]
|
|
102
|
-
): ProsemirrorNode {
|
|
103
|
-
const definitionsMap = mapByUnique(definitions, d => d.id);
|
|
104
|
-
return internalSectionToProsemirrorNode(section, definitionsMap);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
97
|
function internalSectionToProsemirrorNode(
|
|
108
98
|
section: PageSectionEditorModel,
|
|
109
99
|
definitionsMap: Map<string, PageBlockDefinition>
|
|
@@ -136,11 +126,7 @@ function sectionColumnToProsemirrorNode(
|
|
|
136
126
|
sectionColumn: PageSectionColumnV2,
|
|
137
127
|
definitionsMap: Map<string, PageBlockDefinition>
|
|
138
128
|
): ProsemirrorNode {
|
|
139
|
-
const blocks = sectionColumn.blocks
|
|
140
|
-
.map(block => {
|
|
141
|
-
return internalBlockToProsemirrorNode(block, definitionsMap);
|
|
142
|
-
})
|
|
143
|
-
.filter(nonNullFilter);
|
|
129
|
+
const blocks = blocksToProsemirrorNodes(sectionColumn.blocks, definitionsMap);
|
|
144
130
|
|
|
145
131
|
if (!blocks.length) {
|
|
146
132
|
blocks.push({
|
|
@@ -165,19 +151,51 @@ function sectionColumnToProsemirrorNode(
|
|
|
165
151
|
// Blocks
|
|
166
152
|
//
|
|
167
153
|
|
|
168
|
-
function
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
154
|
+
function blocksToProsemirrorNodes(
|
|
155
|
+
blocks: PageBlockEditorModel[],
|
|
156
|
+
definitionsMap: Map<string, PageBlockDefinition>
|
|
157
|
+
): ProsemirrorNode[] {
|
|
158
|
+
const result: ProsemirrorNode[] = [];
|
|
159
|
+
|
|
160
|
+
const listTreeBuilder = new ListTreeBuilder();
|
|
161
|
+
|
|
162
|
+
blocks.forEach(b => {
|
|
163
|
+
const definition = definitionsMap.get(b.data.packageId);
|
|
164
|
+
if (!definition) {
|
|
165
|
+
console.warn(`Could not find definition for ${b.id} (${b.data.packageId})`);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const multiRichTextProp = BlockDefinitionUtils.firstMultiRichTextProperty(definition);
|
|
170
|
+
|
|
171
|
+
if (multiRichTextProp) {
|
|
172
|
+
// This is list
|
|
173
|
+
const node = listTreeBuilder.add(b, multiRichTextProp);
|
|
174
|
+
if (node) {
|
|
175
|
+
result.push(serializeAsMultiRichTextBlock(node));
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
// This is not a list
|
|
179
|
+
// Flush the tree builder to inject a non-tree block after it
|
|
180
|
+
const tree = listTreeBuilder.flush();
|
|
181
|
+
if (tree) {
|
|
182
|
+
result.push(serializeAsMultiRichTextBlock(tree));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const node = blockToProsemirrorNode(b, definition);
|
|
186
|
+
node && result.push(node);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const tree = listTreeBuilder.flush();
|
|
191
|
+
if (tree) {
|
|
192
|
+
result.push(serializeAsMultiRichTextBlock(tree));
|
|
172
193
|
}
|
|
173
194
|
|
|
174
|
-
return
|
|
195
|
+
return result;
|
|
175
196
|
}
|
|
176
197
|
|
|
177
|
-
|
|
178
|
-
block: PageBlockEditorModel,
|
|
179
|
-
definition: PageBlockDefinition
|
|
180
|
-
): ProsemirrorNode | null {
|
|
198
|
+
function blockToProsemirrorNode(block: PageBlockEditorModel, definition: PageBlockDefinition): ProsemirrorNode | null {
|
|
181
199
|
// Single rich text
|
|
182
200
|
const richTextProperty = BlockDefinitionUtils.firstRichTextProperty(definition);
|
|
183
201
|
if (richTextProperty) {
|
|
@@ -188,16 +206,6 @@ export function blockToProsemirrorNode(
|
|
|
188
206
|
});
|
|
189
207
|
}
|
|
190
208
|
|
|
191
|
-
// Multi rich text
|
|
192
|
-
const multiRichTextProperty = BlockDefinitionUtils.firstMultiRichTextProperty(definition);
|
|
193
|
-
if (multiRichTextProperty) {
|
|
194
|
-
return serializeAsMultiRichTextBlock({
|
|
195
|
-
block: block,
|
|
196
|
-
definition: definition,
|
|
197
|
-
property: multiRichTextProperty,
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
|
|
201
209
|
const tableProperty = BlockDefinitionUtils.firstTableProperty(definition);
|
|
202
210
|
if (tableProperty) {
|
|
203
211
|
return serializeAsTable({
|
|
@@ -254,7 +262,7 @@ function serializeAsRichTextBlock(input: InputWithProperty): ProsemirrorNode {
|
|
|
254
262
|
function serializeAsParagraph(input: RichTextInputWithValue): ProsemirrorNode {
|
|
255
263
|
return {
|
|
256
264
|
type: "paragraph",
|
|
257
|
-
attrs: serializeBlockNodeAttributes(input),
|
|
265
|
+
attrs: serializeBlockNodeAttributes(input.block),
|
|
258
266
|
...serializeRichTextNodePart(input.richTextPropertyValue.value),
|
|
259
267
|
};
|
|
260
268
|
}
|
|
@@ -263,7 +271,7 @@ function serializeAsHeading(input: RichTextInputWithValue): ProsemirrorNode {
|
|
|
263
271
|
return {
|
|
264
272
|
type: "heading",
|
|
265
273
|
attrs: {
|
|
266
|
-
...serializeBlockNodeAttributes(input),
|
|
274
|
+
...serializeBlockNodeAttributes(input.block),
|
|
267
275
|
level: richTextHeadingLevel(input.property),
|
|
268
276
|
},
|
|
269
277
|
...serializeRichTextNodePart(input.richTextPropertyValue.value),
|
|
@@ -273,7 +281,7 @@ function serializeAsHeading(input: RichTextInputWithValue): ProsemirrorNode {
|
|
|
273
281
|
function serializeAsBlockquote(input: RichTextInputWithValue): ProsemirrorNode {
|
|
274
282
|
return {
|
|
275
283
|
type: "blockquote",
|
|
276
|
-
attrs: serializeBlockNodeAttributes(input),
|
|
284
|
+
attrs: serializeBlockNodeAttributes(input.block),
|
|
277
285
|
...serializeRichTextNodePart(input.richTextPropertyValue.value),
|
|
278
286
|
};
|
|
279
287
|
}
|
|
@@ -284,7 +292,7 @@ function serializeAsCallout(input: RichTextInputWithValue): ProsemirrorNode {
|
|
|
284
292
|
return {
|
|
285
293
|
type: "callout",
|
|
286
294
|
attrs: {
|
|
287
|
-
...serializeBlockNodeAttributes(input),
|
|
295
|
+
...serializeBlockNodeAttributes(input.block),
|
|
288
296
|
type: serializeCalloutType(calloutType),
|
|
289
297
|
},
|
|
290
298
|
...serializeRichTextNodePart(input.richTextPropertyValue.value),
|
|
@@ -295,66 +303,78 @@ function serializeAsCallout(input: RichTextInputWithValue): ProsemirrorNode {
|
|
|
295
303
|
// Multi rich text blocks
|
|
296
304
|
//
|
|
297
305
|
|
|
298
|
-
function serializeAsMultiRichTextBlock(
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
const textPropertyValue = BlockParsingUtils.multiRichTextPropertyValue(blockItem, multiRichTextProperty.id);
|
|
303
|
-
|
|
304
|
-
const enrichedInput: MultiRichTextInputWithValue = { ...input, multiRichTextPropertyValue: textPropertyValue };
|
|
305
|
-
|
|
306
|
-
const parsedOptions = PageBlockDefinitionMutiRichTextOptions.optional().parse(multiRichTextProperty.options);
|
|
307
|
-
const style = parsedOptions?.multiRichTextStyle ?? "Default";
|
|
308
|
-
|
|
309
|
-
switch (style) {
|
|
310
|
-
case "Default":
|
|
311
|
-
return serializeAsMultiParagraph(enrichedInput);
|
|
312
|
-
|
|
313
|
-
case "OL":
|
|
314
|
-
return serializeAsOrderedList(enrichedInput);
|
|
306
|
+
function serializeAsMultiRichTextBlock(node: ListNode): ProsemirrorNode {
|
|
307
|
+
switch (node.listType) {
|
|
308
|
+
case "Ordered":
|
|
309
|
+
return serializeAsOrderedList(node);
|
|
315
310
|
|
|
316
|
-
case "
|
|
317
|
-
return serializeAsUnorderedList(
|
|
311
|
+
case "Unordered":
|
|
312
|
+
return serializeAsUnorderedList(node);
|
|
318
313
|
}
|
|
319
314
|
}
|
|
320
315
|
|
|
321
|
-
function
|
|
322
|
-
return {
|
|
323
|
-
type: "bulletList",
|
|
324
|
-
attrs: {
|
|
325
|
-
...serializeBlockNodeAttributes(input),
|
|
326
|
-
},
|
|
327
|
-
content: input.multiRichTextPropertyValue.value.map(serializeAsListItem),
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
function serializeAsOrderedList(input: MultiRichTextInputWithValue): ProsemirrorNode {
|
|
316
|
+
function serializeAsOrderedList(tree: ListNode): ProsemirrorNode {
|
|
332
317
|
return {
|
|
333
318
|
type: "orderedList",
|
|
334
319
|
attrs: {
|
|
335
|
-
...serializeBlockNodeAttributes(
|
|
320
|
+
...serializeBlockNodeAttributes(tree.block),
|
|
336
321
|
start: "1",
|
|
337
322
|
},
|
|
338
|
-
content:
|
|
323
|
+
content: serializeListContent(tree),
|
|
339
324
|
};
|
|
340
325
|
}
|
|
341
326
|
|
|
342
|
-
function serializeAsUnorderedList(
|
|
327
|
+
function serializeAsUnorderedList(tree: ListNode): ProsemirrorNode {
|
|
343
328
|
return {
|
|
344
329
|
type: "bulletList",
|
|
345
330
|
attrs: {
|
|
346
|
-
...serializeBlockNodeAttributes(
|
|
331
|
+
...serializeBlockNodeAttributes(tree.block),
|
|
347
332
|
},
|
|
348
|
-
content:
|
|
333
|
+
content: serializeListContent(tree),
|
|
349
334
|
};
|
|
350
335
|
}
|
|
351
336
|
|
|
352
|
-
function
|
|
337
|
+
function serializeListContent(tree: ListNode): ProsemirrorNode[] {
|
|
338
|
+
const result: ProsemirrorNode[] = tree.leadingChildren.map(i => serializeAsTextListItem(i.text));
|
|
339
|
+
|
|
340
|
+
for (const child of tree.children) {
|
|
341
|
+
if (child.type === "ListItem") {
|
|
342
|
+
// Text list item
|
|
343
|
+
|
|
344
|
+
result.push(serializeAsTextListItem(child.text));
|
|
345
|
+
} else if (child.type === "List") {
|
|
346
|
+
// List list item
|
|
347
|
+
|
|
348
|
+
const previousNode = result[result.length - 1];
|
|
349
|
+
if (!previousNode) {
|
|
350
|
+
throw SupernovaException.shouldNotHappen("List node without previous node");
|
|
351
|
+
}
|
|
352
|
+
if (!previousNode.content) {
|
|
353
|
+
throw SupernovaException.shouldNotHappen("List item node has no content");
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const serializedList = serializeAsMultiRichTextBlock(child);
|
|
357
|
+
previousNode.content.push(serializedList);
|
|
358
|
+
} else {
|
|
359
|
+
// Should noit happen
|
|
360
|
+
|
|
361
|
+
throw SupernovaException.shouldNotHappen(`Unknown list node type: ${child}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return result;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function serializeAsTextListItem(text: PageBlockText): ProsemirrorNode {
|
|
353
369
|
return {
|
|
354
370
|
type: "listItem",
|
|
355
371
|
content: [
|
|
356
372
|
{
|
|
357
373
|
type: "paragraph",
|
|
374
|
+
attrs: {
|
|
375
|
+
definitionId: "io.supernova.block.rich-text",
|
|
376
|
+
variantId: "default",
|
|
377
|
+
},
|
|
358
378
|
content: serializeRichText(text),
|
|
359
379
|
},
|
|
360
380
|
],
|
|
@@ -374,7 +394,7 @@ function serializeAsTable(input: InputWithProperty): ProsemirrorNode {
|
|
|
374
394
|
return {
|
|
375
395
|
type: "tableContainer",
|
|
376
396
|
attrs: {
|
|
377
|
-
...serializeBlockNodeAttributes(input),
|
|
397
|
+
...serializeBlockNodeAttributes(input.block),
|
|
378
398
|
hasBorder: table.showBorder ?? true,
|
|
379
399
|
},
|
|
380
400
|
|
|
@@ -482,7 +502,7 @@ function serializeTableNode(node: PageBlockItemTableNode): ProsemirrorNode {
|
|
|
482
502
|
function serializeAsDivider(input: BaseInput): ProsemirrorNode {
|
|
483
503
|
return {
|
|
484
504
|
type: "horizontalRule",
|
|
485
|
-
attrs: serializeBlockNodeAttributes(input),
|
|
505
|
+
attrs: serializeBlockNodeAttributes(input.block),
|
|
486
506
|
};
|
|
487
507
|
}
|
|
488
508
|
|
|
@@ -490,9 +510,7 @@ function serializeAsDivider(input: BaseInput): ProsemirrorNode {
|
|
|
490
510
|
// Attributes
|
|
491
511
|
//
|
|
492
512
|
|
|
493
|
-
function serializeBlockNodeAttributes(
|
|
494
|
-
const { block } = input;
|
|
495
|
-
|
|
513
|
+
function serializeBlockNodeAttributes(block: PageBlockEditorModel) {
|
|
496
514
|
return {
|
|
497
515
|
id: block.id,
|
|
498
516
|
definitionId: block.data.packageId,
|
|
@@ -552,6 +570,8 @@ function serializeRichText(richText: PageBlockText) {
|
|
|
552
570
|
}
|
|
553
571
|
|
|
554
572
|
function serializeTextSpan(span: PageBlockTextSpan): ProsemirrorNode[] {
|
|
573
|
+
const hardBreakType = "hardBreak";
|
|
574
|
+
|
|
555
575
|
const marks = span.attributes.map(serializeTextSpanAttribute);
|
|
556
576
|
|
|
557
577
|
const textParts = span.text.split("\n");
|
|
@@ -567,7 +587,7 @@ function serializeTextSpan(span: PageBlockTextSpan): ProsemirrorNode[] {
|
|
|
567
587
|
for (let i = 1; i < textParts.length; i++) {
|
|
568
588
|
interspersed.push(
|
|
569
589
|
{
|
|
570
|
-
type:
|
|
590
|
+
type: hardBreakType,
|
|
571
591
|
},
|
|
572
592
|
{
|
|
573
593
|
type: "text",
|
|
@@ -578,7 +598,7 @@ function serializeTextSpan(span: PageBlockTextSpan): ProsemirrorNode[] {
|
|
|
578
598
|
);
|
|
579
599
|
}
|
|
580
600
|
|
|
581
|
-
return interspersed.filter(t => !!t.text);
|
|
601
|
+
return interspersed.filter(t => t.type === hardBreakType || !!t.text);
|
|
582
602
|
}
|
|
583
603
|
|
|
584
604
|
function serializeTextSpanAttribute(spanAttribute: PageBlockTextSpanAttribute): ProsemirrorMark {
|
|
@@ -588,7 +608,7 @@ function serializeTextSpanAttribute(spanAttribute: PageBlockTextSpanAttribute):
|
|
|
588
608
|
case "Italic":
|
|
589
609
|
return { type: "italic", attrs: {} };
|
|
590
610
|
case "Strikethrough":
|
|
591
|
-
return { type: "
|
|
611
|
+
return { type: "strike", attrs: {} };
|
|
592
612
|
case "Code":
|
|
593
613
|
return { type: "code", attrs: {} };
|
|
594
614
|
case "Link":
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PageBlockDefinition,
|
|
3
|
+
PageBlockDefinitionMutiRichTextOptions,
|
|
4
|
+
PageBlockDefinitionProperty,
|
|
5
|
+
PageBlockText,
|
|
6
|
+
} from "@supernova-studio/model";
|
|
7
|
+
import { PageBlockEditorModel } from "./model";
|
|
8
|
+
import { BlockParsingUtils } from "./utils";
|
|
9
|
+
|
|
10
|
+
type Node = ListNode | ListItemNode;
|
|
11
|
+
|
|
12
|
+
export type ListNode = {
|
|
13
|
+
type: "List";
|
|
14
|
+
listType: "Ordered" | "Unordered";
|
|
15
|
+
block: PageBlockEditorModel;
|
|
16
|
+
leadingChildren: ListItemNode[];
|
|
17
|
+
children: Node[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type ListItemNode = {
|
|
21
|
+
type: "ListItem";
|
|
22
|
+
text: PageBlockText;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export class ListTreeBuilder {
|
|
26
|
+
private rootNode: ListNode | undefined;
|
|
27
|
+
|
|
28
|
+
add(block: PageBlockEditorModel, multiRichTextProperty: PageBlockDefinitionProperty): ListNode | undefined {
|
|
29
|
+
const list = this.createList(block, multiRichTextProperty);
|
|
30
|
+
|
|
31
|
+
// No root
|
|
32
|
+
if (!this.rootNode) {
|
|
33
|
+
this.rootNode = list;
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Inserting at the root
|
|
38
|
+
if (block.data.indentLevel <= 0) {
|
|
39
|
+
// We are at the root
|
|
40
|
+
if (this.rootNode.listType === list.listType) {
|
|
41
|
+
// Merge items into the current list
|
|
42
|
+
this.rootNode.children.push(...list.leadingChildren);
|
|
43
|
+
return;
|
|
44
|
+
} else {
|
|
45
|
+
const flushed = this.flush();
|
|
46
|
+
this.rootNode = list;
|
|
47
|
+
return flushed;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Inserting at a depth
|
|
52
|
+
const listParent = this.getParentOfDepth(block.data.indentLevel);
|
|
53
|
+
|
|
54
|
+
const lastChild = listParent.children[listParent.children.length - 1];
|
|
55
|
+
if (lastChild?.type === "List") {
|
|
56
|
+
// Merge items into the current list
|
|
57
|
+
lastChild.children.push(...list.leadingChildren);
|
|
58
|
+
return;
|
|
59
|
+
} else {
|
|
60
|
+
// We can add this list as a child of another list
|
|
61
|
+
listParent.children.push(list);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
flush(): ListNode | undefined {
|
|
66
|
+
const node = this.rootNode;
|
|
67
|
+
this.rootNode = undefined;
|
|
68
|
+
return node;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private getParentOfDepth(depth: number): ListNode {
|
|
72
|
+
if (!this.rootNode || depth <= 0) throw new Error("Invalid state");
|
|
73
|
+
|
|
74
|
+
let currentNode = this.rootNode;
|
|
75
|
+
let currentDepth = depth - 1;
|
|
76
|
+
|
|
77
|
+
while (currentDepth > 0) {
|
|
78
|
+
// Check if we can go any lower
|
|
79
|
+
if (currentNode.children.length === 0) return currentNode;
|
|
80
|
+
|
|
81
|
+
const lastChild = currentNode.children[currentNode.children.length - 1];
|
|
82
|
+
if (lastChild.type !== "List") {
|
|
83
|
+
// Cannot go lower if last child is not a list
|
|
84
|
+
return currentNode;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
currentNode = lastChild;
|
|
88
|
+
currentDepth--;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return currentNode;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// next(block: PageBlockEditorModel, multiRichTextProperty: PageBlockDefinitionProperty): ListNode | undefined {
|
|
95
|
+
// console.log("Next");
|
|
96
|
+
// const list = this.createList(block, multiRichTextProperty);
|
|
97
|
+
|
|
98
|
+
// if (this.currentList) {
|
|
99
|
+
// if (this.currentList.listType === list.listType) {
|
|
100
|
+
// // Merge items into the current list
|
|
101
|
+
// this.currentList.children.push(...list.leadingChildren);
|
|
102
|
+
// return undefined;
|
|
103
|
+
// } else {
|
|
104
|
+
// // Close the current list and start a new one
|
|
105
|
+
// if (!this.currentParentList) {
|
|
106
|
+
// const flushed = this.flush();
|
|
107
|
+
// this.currentList = list;
|
|
108
|
+
// return flushed;
|
|
109
|
+
// } else {
|
|
110
|
+
// this.currentList = list;
|
|
111
|
+
// this.currentParentList.children.push(list);
|
|
112
|
+
// this.parentMap.set(list, this.currentParentList);
|
|
113
|
+
|
|
114
|
+
// return undefined;
|
|
115
|
+
// }
|
|
116
|
+
// }
|
|
117
|
+
// } else {
|
|
118
|
+
// this.currentList = list;
|
|
119
|
+
// return undefined;
|
|
120
|
+
// }
|
|
121
|
+
// }
|
|
122
|
+
|
|
123
|
+
// stepIn(block: PageBlockEditorModel, multiRichTextProperty: PageBlockDefinitionProperty): void {
|
|
124
|
+
// console.log("Step in");
|
|
125
|
+
// if (!this.currentList) {
|
|
126
|
+
// throw new Error("Cannot step in without a list");
|
|
127
|
+
// }
|
|
128
|
+
|
|
129
|
+
// const list = this.createList(block, multiRichTextProperty);
|
|
130
|
+
|
|
131
|
+
// this.currentParentList = this.currentList;
|
|
132
|
+
// this.currentList = list;
|
|
133
|
+
// this.currentParentList.children.push(list);
|
|
134
|
+
// this.parentMap.set(list, this.currentParentList);
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
// stepOut(block: PageBlockEditorModel, multiRichTextProperty: PageBlockDefinitionProperty): ListNode | undefined {
|
|
138
|
+
// console.log("Step out");
|
|
139
|
+
|
|
140
|
+
// if (!this.currentList) {
|
|
141
|
+
// throw new Error("Cannot step out without a list");
|
|
142
|
+
// }
|
|
143
|
+
|
|
144
|
+
// if (!this.currentParentList) {
|
|
145
|
+
// throw new Error("Cannot step out without a parent list");
|
|
146
|
+
// }
|
|
147
|
+
|
|
148
|
+
// const newCurrentList = this.currentParentList;
|
|
149
|
+
// const newParent = this.parentMap.get(newCurrentList);
|
|
150
|
+
|
|
151
|
+
// this.currentList = newCurrentList;
|
|
152
|
+
// this.currentParentList = newParent;
|
|
153
|
+
|
|
154
|
+
// return this.next(block, multiRichTextProperty);
|
|
155
|
+
// }
|
|
156
|
+
|
|
157
|
+
// flush(): ListNode | undefined {
|
|
158
|
+
// const result = this.currentList;
|
|
159
|
+
|
|
160
|
+
// this.currentList = undefined;
|
|
161
|
+
// this.currentParentList = undefined;
|
|
162
|
+
// this.parentMap.clear();
|
|
163
|
+
|
|
164
|
+
// return result;
|
|
165
|
+
// }
|
|
166
|
+
|
|
167
|
+
private createList(block: PageBlockEditorModel, multiRichTextProperty: PageBlockDefinitionProperty): ListNode {
|
|
168
|
+
const blockItem = BlockParsingUtils.singleBlockItem(block);
|
|
169
|
+
const multiRichTextValue = BlockParsingUtils.multiRichTextPropertyValue(blockItem, multiRichTextProperty.id);
|
|
170
|
+
|
|
171
|
+
const parsedOptions = PageBlockDefinitionMutiRichTextOptions.optional().parse(multiRichTextProperty.options);
|
|
172
|
+
|
|
173
|
+
const style = parsedOptions?.multiRichTextStyle ?? "Default";
|
|
174
|
+
|
|
175
|
+
const leadingChildren: ListNode["leadingChildren"] = multiRichTextValue.value.map(t => {
|
|
176
|
+
return {
|
|
177
|
+
type: "ListItem",
|
|
178
|
+
text: t,
|
|
179
|
+
};
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
if (!leadingChildren.length) {
|
|
183
|
+
leadingChildren.push({ type: "ListItem", text: { spans: [] } });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
type: "List",
|
|
188
|
+
listType: style === "OL" ? "Ordered" : "Unordered",
|
|
189
|
+
leadingChildren: leadingChildren,
|
|
190
|
+
block: block,
|
|
191
|
+
children: [],
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -363,7 +363,7 @@ function parseRichTextAttribute(mark: ProsemirrorMark): PageBlockTextSpanAttribu
|
|
|
363
363
|
return { type: "Bold" };
|
|
364
364
|
case "italic":
|
|
365
365
|
return { type: "Italic" };
|
|
366
|
-
case "
|
|
366
|
+
case "strike":
|
|
367
367
|
return { type: "Strikethrough" };
|
|
368
368
|
case "code":
|
|
369
369
|
return { type: "Code" };
|