@supernova-studio/client 0.33.0 → 0.35.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.
@@ -73,6 +73,10 @@ export function prosemirrorDocToPage(
73
73
  };
74
74
  }
75
75
 
76
+ export function shallowProsemirrorNodeToBlock(prosemirrorNode: ProsemirrorNode, definition: PageBlockDefinition) {
77
+ return shallowProsemirrorNodeAndDefinitionToBlock(prosemirrorNode, definition);
78
+ }
79
+
76
80
  //
77
81
  // Sections
78
82
  //
@@ -134,7 +138,7 @@ function prosemirrorNodeToSectionColumns(
134
138
 
135
139
  return {
136
140
  id: id,
137
- blocks: internalProsemirrorNodesToBlocks(prosemirrorNode.content ?? [], definitionsMap),
141
+ blocks: internalProsemirrorNodesToBlocks(prosemirrorNode.content ?? [], definitionsMap, 0),
138
142
  };
139
143
  }
140
144
 
@@ -144,49 +148,49 @@ function prosemirrorNodeToSectionColumns(
144
148
 
145
149
  export function prosemirrorNodesToBlocks(prosemirrorNodes: ProsemirrorNode[], definitions: PageBlockDefinition[]) {
146
150
  const definitionsById = mapByUnique(definitions, d => d.id);
147
- return internalProsemirrorNodesToBlocks(prosemirrorNodes, definitionsById);
151
+ return internalProsemirrorNodesToBlocks(prosemirrorNodes, definitionsById, 0);
148
152
  }
149
153
 
150
154
  function internalProsemirrorNodesToPageItems(
151
155
  prosemirrorNodes: ProsemirrorNode[],
152
156
  definitionsMap: Map<string, PageBlockDefinition>
153
157
  ): (PageBlockEditorModel | PageSectionEditorModel)[] {
154
- return prosemirrorNodes
155
- .map(prosemirrorNode => {
156
- if (prosemirrorNode.type === "tabsSection") {
157
- return prosemirrorNodeToSection(prosemirrorNode, Array.from(definitionsMap.values()));
158
- } else {
159
- return internalProsemirrorNodeToBlock(prosemirrorNode, definitionsMap);
160
- }
161
- })
162
- .filter(nonNullFilter);
158
+ const result: (PageBlockEditorModel | PageSectionEditorModel)[] = [];
159
+
160
+ for (const prosemirrorNode of prosemirrorNodes) {
161
+ if (prosemirrorNode.type === "tabsSection") {
162
+ // Section
163
+ const section = prosemirrorNodeToSection(prosemirrorNode, Array.from(definitionsMap.values()));
164
+ section && result.push(section);
165
+ } else {
166
+ // Block
167
+ result.push(...internalProsemirrorNodeToBlock(prosemirrorNode, definitionsMap, 0));
168
+ }
169
+ }
170
+
171
+ return result;
163
172
  }
164
173
 
165
174
  function internalProsemirrorNodesToBlocks(
166
175
  prosemirrorNodes: ProsemirrorNode[],
167
- definitionsMap: Map<string, PageBlockDefinition>
176
+ definitionsMap: Map<string, PageBlockDefinition>,
177
+ depth: number
168
178
  ): PageBlockEditorModel[] {
169
- return prosemirrorNodes
170
- .map(prosemirrorNode => {
171
- return internalProsemirrorNodeToBlock(prosemirrorNode, definitionsMap);
172
- })
173
- .filter(nonNullFilter);
179
+ return prosemirrorNodes.flatMap(prosemirrorNode => {
180
+ return internalProsemirrorNodeToBlock(prosemirrorNode, definitionsMap, depth);
181
+ });
174
182
  }
175
183
 
176
184
  function internalProsemirrorNodeToBlock(
177
185
  prosemirrorNode: ProsemirrorNode,
178
- definitionsMap: Map<string, PageBlockDefinition>
179
- ) {
180
- let definitionId = getProsemirrorAttribute(prosemirrorNode, "definitionId", z.string());
186
+ definitionsMap: Map<string, PageBlockDefinition>,
187
+ depth: number
188
+ ): PageBlockEditorModel[] {
189
+ const definitionId = getProsemirrorAttribute(prosemirrorNode, "definitionId", z.string());
181
190
  if (!definitionId) {
182
191
  console.warn(`definitionId on ${prosemirrorNode.type} is required to be interpreted as a block, skipping node`);
183
192
 
184
- return null;
185
- }
186
-
187
- // TODO: remove
188
- if (definitionId === "io.supernova.block.token-detail") {
189
- definitionId = "io.supernova.block.token-list";
193
+ return [];
190
194
  }
191
195
 
192
196
  const definition = definitionsMap.get(definitionId);
@@ -195,13 +199,28 @@ function internalProsemirrorNodeToBlock(
195
199
  `Block definitionId "${definitionId}" (prosemirror node ${prosemirrorNode.type}) is not among available definitions`
196
200
  );
197
201
  console.warn(prosemirrorNode);
198
- return null;
202
+ return [];
199
203
  }
200
204
 
201
- return prosemirrorNodeToBlock(prosemirrorNode, definition);
205
+ return prosemirrorNodeAndDefinitionToBlock(prosemirrorNode, definition, definitionsMap, depth);
202
206
  }
203
207
 
204
- export function prosemirrorNodeToBlock(
208
+ function prosemirrorNodeAndDefinitionToBlock(
209
+ prosemirrorNode: ProsemirrorNode,
210
+ definition: PageBlockDefinition,
211
+ definitionsMap: Map<string, PageBlockDefinition>,
212
+ depth: number
213
+ ): PageBlockEditorModel[] {
214
+ const multiRichTextProperty = BlockDefinitionUtils.firstMultiRichTextProperty(definition);
215
+ if (multiRichTextProperty) {
216
+ return parseAsMultiRichText(prosemirrorNode, definition, multiRichTextProperty, definitionsMap, depth);
217
+ }
218
+
219
+ const block = shallowProsemirrorNodeAndDefinitionToBlock(prosemirrorNode, definition);
220
+ return block ? [block] : [];
221
+ }
222
+
223
+ function shallowProsemirrorNodeAndDefinitionToBlock(
205
224
  prosemirrorNode: ProsemirrorNode,
206
225
  definition: PageBlockDefinition
207
226
  ): PageBlockEditorModel | null {
@@ -210,11 +229,6 @@ export function prosemirrorNodeToBlock(
210
229
  return parseAsRichText(prosemirrorNode, definition, richTextProperty);
211
230
  }
212
231
 
213
- const multiRichTextProperty = BlockDefinitionUtils.firstMultiRichTextProperty(definition);
214
- if (multiRichTextProperty) {
215
- return parseAsMultiRichText(prosemirrorNode, definition, multiRichTextProperty);
216
- }
217
-
218
232
  const tableProperty = BlockDefinitionUtils.firstTableProperty(definition);
219
233
  if (tableProperty) {
220
234
  return parseAsTable(prosemirrorNode, definition, tableProperty);
@@ -294,46 +308,75 @@ function parseCalloutType(prosemirrorCalloutType: unknown): PageBlockCalloutType
294
308
  function parseAsMultiRichText(
295
309
  prosemirrorNode: ProsemirrorNode,
296
310
  definition: PageBlockDefinition,
297
- property: PageBlockDefinitionProperty
298
- ): PageBlockEditorModel | null {
311
+ property: PageBlockDefinitionProperty,
312
+ definitionsMap: Map<string, PageBlockDefinition>,
313
+ depth: number
314
+ ): PageBlockEditorModel[] {
299
315
  const id = getProsemirrorBlockId(prosemirrorNode);
300
- if (!id) return null;
316
+ if (!id) return [];
301
317
 
302
318
  const variantId = getProsemirrorBlockVariantId(prosemirrorNode);
319
+ const result: PageBlockEditorModel[] = [];
303
320
 
304
- return {
305
- // TODO Artem: indent
306
- id: id,
307
- type: "Block",
308
- data: {
309
- packageId: definition.id,
310
- indentLevel: 0,
311
-
312
- ...(variantId && { variantId: variantId }),
321
+ // Flatten items
322
+ const listItems: ProsemirrorNode[] = [];
323
+ prosemirrorNode.content?.forEach(c => {
324
+ // Illegal child of a list
325
+ if (c.type !== "listItem") return;
313
326
 
314
- items: [
315
- {
316
- id: id,
317
- props: {
318
- [property.id]: {
319
- // Required
320
- value: (prosemirrorNode.content ?? [])
321
- .map(listItem => {
322
- if (listItem.type !== "listItem") return null;
323
- if (!listItem.content?.length) return parseRichText([]);
324
-
325
- const paragraph = listItem.content[0];
326
- if (paragraph.type !== "paragraph") return parseRichText([]);
327
+ c.content?.forEach(cc => {
328
+ listItems.push(cc);
329
+ });
330
+ });
327
331
 
332
+ // Text list items buffering
333
+ let bufferedTextItems: ProsemirrorNode[] = [];
334
+ function flushBufferedTextItems() {
335
+ if (!bufferedTextItems.length) return;
336
+
337
+ const idSuffix = result.length ? `-${result.length}` : "";
338
+
339
+ result.push({
340
+ id: id + idSuffix,
341
+ type: "Block",
342
+ data: {
343
+ packageId: definition.id,
344
+ indentLevel: depth,
345
+ ...(variantId && { variantId: variantId }),
346
+ items: [
347
+ {
348
+ id: id + idSuffix,
349
+ props: {
350
+ [property.id]: {
351
+ value: bufferedTextItems.map(paragraph => {
328
352
  return parseRichText(paragraph.content ?? []);
329
- })
330
- .filter(nonNullFilter),
331
- } satisfies PageBlockItemMultiRichTextValue,
353
+ }),
354
+ } satisfies PageBlockItemMultiRichTextValue,
355
+ },
332
356
  },
333
- },
334
- ],
335
- },
336
- };
357
+ ],
358
+ },
359
+ });
360
+
361
+ bufferedTextItems = [];
362
+ }
363
+
364
+ listItems.forEach(item => {
365
+ if (item.type === "paragraph") {
366
+ bufferedTextItems.push(item);
367
+ return;
368
+ }
369
+
370
+ // This is not a paragraph, flush text items first
371
+ flushBufferedTextItems();
372
+
373
+ result.push(...internalProsemirrorNodeToBlock(item, definitionsMap, depth + 1));
374
+ });
375
+
376
+ // Flush text items at the end
377
+ flushBufferedTextItems();
378
+
379
+ return result;
337
380
  }
338
381
 
339
382
  //