@supernova-studio/client 0.9.1 → 0.9.3
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.js +71 -62
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +71 -62
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/docs-editor/prosemirror-to-blocks.ts +76 -65
package/package.json
CHANGED
|
@@ -37,15 +37,15 @@ import {
|
|
|
37
37
|
PageBlockItemTableNode,
|
|
38
38
|
PageBlockItemTableCell,
|
|
39
39
|
PageBlockTableCellAlignment,
|
|
40
|
-
DocumentationItemConfiguration,
|
|
41
40
|
PageBlockAppearanceV2,
|
|
42
|
-
PageBlockEditorModelV2,
|
|
43
41
|
ColorValue,
|
|
42
|
+
nullishToOptional,
|
|
44
43
|
} from "@supernova-studio/model";
|
|
45
44
|
import { PageBlockEditorModel } from "./model/block";
|
|
46
45
|
import { DocumentationPageEditorModel } from "./model/page";
|
|
47
46
|
import { BlockDefinitionUtils } from "./utils";
|
|
48
47
|
import { yXmlFragmentToProsemirrorJSON } from "y-prosemirror";
|
|
48
|
+
import { ZodAnyDef, ZodSchema, ZodTypeDef, z } from "zod";
|
|
49
49
|
|
|
50
50
|
export function yDocToPage(yDoc: Y.Doc, definitions: PageBlockDefinition[]): DocumentationPageEditorModel {
|
|
51
51
|
return yXmlFragmentToPage(yDoc.getXmlFragment("default"), definitions);
|
|
@@ -68,13 +68,23 @@ export function prosemirrorDocToPage(
|
|
|
68
68
|
return {
|
|
69
69
|
blocks: (prosemirrorDoc.content ?? [])
|
|
70
70
|
.map(prosemirrorNode => {
|
|
71
|
-
const definitionId =
|
|
72
|
-
if (!definitionId)
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
const definitionId = getProsemirrorAttribute(prosemirrorNode, "definitionId", z.string());
|
|
72
|
+
if (!definitionId) {
|
|
73
|
+
console.warn(
|
|
74
|
+
`definitionId on ${prosemirrorNode.type} is required to be interpreted as a block, skipping node`
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
75
79
|
|
|
76
80
|
const definition = definitionsById.get(definitionId);
|
|
77
|
-
if (!definition)
|
|
81
|
+
if (!definition) {
|
|
82
|
+
console.warn(
|
|
83
|
+
`Block definitionId "${definitionId}" (prosemirror node ${prosemirrorNode.type}) is not among available definitions`
|
|
84
|
+
);
|
|
85
|
+
console.warn(prosemirrorNode);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
78
88
|
|
|
79
89
|
return prosemirrorNodeToBlock(prosemirrorNode, definition);
|
|
80
90
|
})
|
|
@@ -122,13 +132,11 @@ function parseAsRichText(
|
|
|
122
132
|
definition: PageBlockDefinition,
|
|
123
133
|
property: PageBlockDefinitionProperty
|
|
124
134
|
): PageBlockEditorModel | null {
|
|
125
|
-
const id =
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
const variantIdRaw = parseProsemirrorOptionalBlockAttribute(prosemirrorNode, "variantId");
|
|
129
|
-
const variantId = typeof variantIdRaw === "string" ? variantIdRaw : undefined;
|
|
135
|
+
const id = getProsemirrorBlockId(prosemirrorNode);
|
|
136
|
+
if (!id) return null;
|
|
130
137
|
|
|
131
|
-
const
|
|
138
|
+
const variantId = getProsemirrorBlockVariantId(prosemirrorNode);
|
|
139
|
+
const calloutType = parseCalloutType(getProsemirrorAttribute(prosemirrorNode, "type", z.string().optional()));
|
|
132
140
|
|
|
133
141
|
return {
|
|
134
142
|
// TODO Artem: indent
|
|
@@ -181,11 +189,10 @@ function parseAsMultiRichText(
|
|
|
181
189
|
definition: PageBlockDefinition,
|
|
182
190
|
property: PageBlockDefinitionProperty
|
|
183
191
|
): PageBlockEditorModel | null {
|
|
184
|
-
const id =
|
|
185
|
-
if (
|
|
192
|
+
const id = getProsemirrorBlockId(prosemirrorNode);
|
|
193
|
+
if (!id) return null;
|
|
186
194
|
|
|
187
|
-
const
|
|
188
|
-
const variantId = typeof variantIdRaw === "string" ? variantIdRaw : undefined;
|
|
195
|
+
const variantId = getProsemirrorBlockVariantId(prosemirrorNode);
|
|
189
196
|
|
|
190
197
|
return {
|
|
191
198
|
// TODO Artem: indent
|
|
@@ -253,11 +260,8 @@ function parseRichTextAttribute(mark: ProsemirrorMark): PageBlockTextSpanAttribu
|
|
|
253
260
|
case "code":
|
|
254
261
|
return { type: "Code" };
|
|
255
262
|
case "link":
|
|
256
|
-
const
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
const hrefRaw = parseProsemirrorOptionalBlockAttribute(mark, "href");
|
|
260
|
-
const href = typeof hrefRaw === "string" ? hrefRaw : undefined;
|
|
263
|
+
const itemId = getProsemirrorAttribute(mark, "itemId", z.string().optional());
|
|
264
|
+
const href = getProsemirrorAttribute(mark, "href", z.string().optional());
|
|
261
265
|
|
|
262
266
|
return {
|
|
263
267
|
type: "Link",
|
|
@@ -279,13 +283,11 @@ function parseAsTable(
|
|
|
279
283
|
definition: PageBlockDefinition,
|
|
280
284
|
property: PageBlockDefinitionProperty
|
|
281
285
|
): PageBlockEditorModel | null {
|
|
282
|
-
const id =
|
|
283
|
-
if (
|
|
284
|
-
|
|
285
|
-
const variantIdRaw = parseProsemirrorOptionalBlockAttribute(prosemirrorNode, "variantId");
|
|
286
|
-
const variantId = typeof variantIdRaw === "string" ? variantIdRaw : undefined;
|
|
286
|
+
const id = getProsemirrorBlockId(prosemirrorNode);
|
|
287
|
+
if (!id) return null;
|
|
287
288
|
|
|
288
|
-
const
|
|
289
|
+
const variantId = getProsemirrorBlockVariantId(prosemirrorNode);
|
|
290
|
+
const hasBorder = getProsemirrorAttribute(prosemirrorNode, "hasBorder", z.boolean().optional()) !== false;
|
|
289
291
|
|
|
290
292
|
const tableChild = prosemirrorNode.content?.find(c => c.type === "table");
|
|
291
293
|
if (!tableChild) {
|
|
@@ -338,14 +340,14 @@ function parseAsTable(
|
|
|
338
340
|
}
|
|
339
341
|
|
|
340
342
|
function parseAsTableCell(prosemirrorNode: ProsemirrorNode): PageBlockItemTableCell | null {
|
|
341
|
-
const id =
|
|
342
|
-
if (
|
|
343
|
+
const id = getProsemirrorBlockId(prosemirrorNode);
|
|
344
|
+
if (!id) return null;
|
|
343
345
|
|
|
344
|
-
const textAlign =
|
|
346
|
+
const textAlign = getProsemirrorAttribute(prosemirrorNode, "textAlign", z.string().optional());
|
|
345
347
|
|
|
346
348
|
let columnWidth: number | undefined;
|
|
347
|
-
const columnWidthArray =
|
|
348
|
-
if (
|
|
349
|
+
const columnWidthArray = getProsemirrorAttribute(prosemirrorNode, "colwidth", z.array(z.number()).optional());
|
|
350
|
+
if (columnWidthArray) {
|
|
349
351
|
columnWidth = columnWidthArray[0];
|
|
350
352
|
}
|
|
351
353
|
|
|
@@ -384,8 +386,8 @@ function parseAsTableNode(prosemirrorNode: ProsemirrorNode): PageBlockItemTableN
|
|
|
384
386
|
};
|
|
385
387
|
|
|
386
388
|
case "image":
|
|
387
|
-
const url =
|
|
388
|
-
if (!url
|
|
389
|
+
const url = getProsemirrorAttribute(prosemirrorNode, "src", z.string().optional());
|
|
390
|
+
if (!url) return null;
|
|
389
391
|
|
|
390
392
|
return {
|
|
391
393
|
type: "Image",
|
|
@@ -458,15 +460,14 @@ function parseAsEmbed(
|
|
|
458
460
|
definition: PageBlockDefinition,
|
|
459
461
|
property: PageBlockDefinitionProperty
|
|
460
462
|
): PageBlockEditorModel | null {
|
|
461
|
-
const id =
|
|
462
|
-
if (
|
|
463
|
+
const id = getProsemirrorBlockId(prosemirrorNode);
|
|
464
|
+
if (!id) return null;
|
|
463
465
|
|
|
464
|
-
const
|
|
465
|
-
const variantId = typeof variantIdRaw === "string" ? variantIdRaw : undefined;
|
|
466
|
+
const variantId = getProsemirrorBlockVariantId(prosemirrorNode);
|
|
466
467
|
|
|
467
|
-
const url =
|
|
468
|
-
const caption =
|
|
469
|
-
const height =
|
|
468
|
+
const url = getProsemirrorAttribute(prosemirrorNode, "url", z.string().optional());
|
|
469
|
+
const caption = getProsemirrorAttribute(prosemirrorNode, "caption", z.string().optional());
|
|
470
|
+
const height = getProsemirrorAttribute(prosemirrorNode, "height", z.number().optional());
|
|
470
471
|
|
|
471
472
|
return {
|
|
472
473
|
id: id,
|
|
@@ -483,7 +484,7 @@ function parseAsEmbed(
|
|
|
483
484
|
[property.id]: {
|
|
484
485
|
value: url,
|
|
485
486
|
caption: caption,
|
|
486
|
-
height: height,
|
|
487
|
+
height: height ?? 200,
|
|
487
488
|
} as PageBlockItemEmbedValue,
|
|
488
489
|
},
|
|
489
490
|
},
|
|
@@ -500,11 +501,10 @@ function parseAsDivider(
|
|
|
500
501
|
prosemirrorNode: ProsemirrorNode,
|
|
501
502
|
definition: PageBlockDefinition
|
|
502
503
|
): PageBlockEditorModel | null {
|
|
503
|
-
const id =
|
|
504
|
-
if (
|
|
504
|
+
const id = getProsemirrorBlockId(prosemirrorNode);
|
|
505
|
+
if (!id) return null;
|
|
505
506
|
|
|
506
|
-
const
|
|
507
|
-
const variantId = typeof variantIdRaw === "string" ? variantIdRaw : undefined;
|
|
507
|
+
const variantId = getProsemirrorBlockVariantId(prosemirrorNode);
|
|
508
508
|
|
|
509
509
|
return {
|
|
510
510
|
id: id,
|
|
@@ -527,11 +527,10 @@ function parseAsCustomBlock(
|
|
|
527
527
|
prosemirrorNode: ProsemirrorNode,
|
|
528
528
|
definition: PageBlockDefinition
|
|
529
529
|
): PageBlockEditorModel | null {
|
|
530
|
-
const id =
|
|
531
|
-
if (
|
|
530
|
+
const id = getProsemirrorBlockId(prosemirrorNode);
|
|
531
|
+
if (!id) return null;
|
|
532
532
|
|
|
533
|
-
const
|
|
534
|
-
const variantId = typeof variantIdRaw === "string" ? variantIdRaw : undefined;
|
|
533
|
+
const variantId = getProsemirrorBlockVariantId(prosemirrorNode);
|
|
535
534
|
|
|
536
535
|
const appearance = parseAppearance(prosemirrorNode);
|
|
537
536
|
const parsedItems = parseBlockItems(prosemirrorNode, definition);
|
|
@@ -552,8 +551,8 @@ function parseAsCustomBlock(
|
|
|
552
551
|
}
|
|
553
552
|
|
|
554
553
|
function parseBlockItems(prosemirrorNode: ProsemirrorNode, definition: PageBlockDefinition): PageBlockItemV2[] | null {
|
|
555
|
-
const itemsString =
|
|
556
|
-
if (
|
|
554
|
+
const itemsString = getProsemirrorAttribute(prosemirrorNode, "items", z.string());
|
|
555
|
+
if (!itemsString) return null;
|
|
557
556
|
|
|
558
557
|
const itemsJson: unknown = JSON.parse(itemsString);
|
|
559
558
|
if (!Array.isArray(itemsJson)) {
|
|
@@ -567,13 +566,13 @@ function parseBlockItems(prosemirrorNode: ProsemirrorNode, definition: PageBlock
|
|
|
567
566
|
function parseAppearance(prosemirrorNode: ProsemirrorNode): PageBlockAppearanceV2 | undefined {
|
|
568
567
|
const appearance: PageBlockAppearanceV2 = {};
|
|
569
568
|
|
|
570
|
-
const columns
|
|
571
|
-
if (
|
|
569
|
+
const columns = getProsemirrorAttribute(prosemirrorNode, "columns", z.number().optional());
|
|
570
|
+
if (columns) {
|
|
572
571
|
appearance.numberOfColumns = columns;
|
|
573
572
|
}
|
|
574
573
|
|
|
575
|
-
const backgroundColor
|
|
576
|
-
if (
|
|
574
|
+
const backgroundColor = getProsemirrorAttribute(prosemirrorNode, "backgroundColor", z.string().optional());
|
|
575
|
+
if (backgroundColor) {
|
|
577
576
|
const parsedColor = ColorValue.safeParse(JSON.parse(backgroundColor));
|
|
578
577
|
if (parsedColor.success) {
|
|
579
578
|
appearance.itemBackgroundColor = parsedColor.data;
|
|
@@ -673,17 +672,29 @@ function valueSchemaForPropertyType(type: PageBlockDefinitionPropertyType) {
|
|
|
673
672
|
// Attributes
|
|
674
673
|
//
|
|
675
674
|
|
|
676
|
-
function
|
|
677
|
-
const
|
|
678
|
-
if (!
|
|
679
|
-
|
|
680
|
-
|
|
675
|
+
function getProsemirrorBlockId(prosemirrorNode: ProsemirrorNode): string | undefined {
|
|
676
|
+
const id = getProsemirrorAttribute(prosemirrorNode, "id", z.string());
|
|
677
|
+
if (!id) console.warn(`Prosemirror attribute "id" on ${prosemirrorNode.type} is required`);
|
|
678
|
+
return id;
|
|
679
|
+
}
|
|
681
680
|
|
|
682
|
-
|
|
681
|
+
function getProsemirrorBlockVariantId(prosemirrorNode: ProsemirrorNode): string | undefined {
|
|
682
|
+
return getProsemirrorAttribute(prosemirrorNode, "variantId", nullishToOptional(z.string()));
|
|
683
683
|
}
|
|
684
684
|
|
|
685
|
-
function
|
|
686
|
-
|
|
685
|
+
function getProsemirrorAttribute<I, O>(
|
|
686
|
+
prosemirrorNode: ProsemirrorNode,
|
|
687
|
+
attributeName: string,
|
|
688
|
+
validationSchema: ZodSchema<O, ZodTypeDef, I>
|
|
689
|
+
): O | undefined {
|
|
690
|
+
const parsedAttr = validationSchema.safeParse(prosemirrorNode.attrs?.[attributeName]);
|
|
691
|
+
if (parsedAttr.success) {
|
|
692
|
+
return parsedAttr.data;
|
|
693
|
+
} else {
|
|
694
|
+
console.warn(`Prosemirror attribute ${attributeName} on ${prosemirrorNode.type} is invalid`);
|
|
695
|
+
console.warn(parsedAttr.error.flatten());
|
|
696
|
+
return undefined;
|
|
697
|
+
}
|
|
687
698
|
}
|
|
688
699
|
|
|
689
700
|
//
|