@portabletext/block-tools 4.1.7 → 4.1.9

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 (34) hide show
  1. package/package.json +6 -10
  2. package/src/HtmlDeserializer/flatten-nested-blocks.test.ts +0 -248
  3. package/src/HtmlDeserializer/flatten-nested-blocks.ts +0 -173
  4. package/src/HtmlDeserializer/helpers.ts +0 -108
  5. package/src/HtmlDeserializer/index.ts +0 -315
  6. package/src/HtmlDeserializer/preprocessors/index.ts +0 -15
  7. package/src/HtmlDeserializer/preprocessors/preprocessor.gdocs.ts +0 -66
  8. package/src/HtmlDeserializer/preprocessors/preprocessor.html.ts +0 -57
  9. package/src/HtmlDeserializer/preprocessors/preprocessor.notion.ts +0 -25
  10. package/src/HtmlDeserializer/preprocessors/preprocessor.whitespace.ts +0 -56
  11. package/src/HtmlDeserializer/preprocessors/preprocessor.word.ts +0 -92
  12. package/src/HtmlDeserializer/preprocessors/xpathResult.ts +0 -13
  13. package/src/HtmlDeserializer/rules/index.ts +0 -21
  14. package/src/HtmlDeserializer/rules/rules.gdocs.ts +0 -188
  15. package/src/HtmlDeserializer/rules/rules.html.ts +0 -356
  16. package/src/HtmlDeserializer/rules/rules.notion.ts +0 -57
  17. package/src/HtmlDeserializer/rules/rules.whitespace-text-node.ts +0 -31
  18. package/src/HtmlDeserializer/rules/rules.word.ts +0 -95
  19. package/src/HtmlDeserializer/trim-whitespace.ts +0 -157
  20. package/src/HtmlDeserializer/word-online/asserters.word-online.ts +0 -153
  21. package/src/HtmlDeserializer/word-online/preprocessor.word-online.ts +0 -263
  22. package/src/HtmlDeserializer/word-online/rules.word-online.ts +0 -390
  23. package/src/constants.ts +0 -104
  24. package/src/index.ts +0 -49
  25. package/src/rules/_exports/index.ts +0 -1
  26. package/src/rules/flatten-tables.test.ts +0 -495
  27. package/src/rules/flatten-tables.ts +0 -216
  28. package/src/rules/index.ts +0 -1
  29. package/src/schema-matchers.ts +0 -41
  30. package/src/types.ts +0 -100
  31. package/src/util/findBlockType.ts +0 -13
  32. package/src/util/normalizeBlock.ts +0 -171
  33. package/src/util/randomKey.ts +0 -28
  34. package/src/util/resolveJsType.ts +0 -44
@@ -1,495 +0,0 @@
1
- import {compileSchema, defineSchema} from '@portabletext/schema'
2
- import {getTersePt} from '@portabletext/test'
3
- import {JSDOM} from 'jsdom'
4
- import {describe, expect, test} from 'vitest'
5
- import {createTestKeyGenerator} from '../../test/test-key-generator'
6
- import {htmlToBlocks} from '../index'
7
- import type {ImageSchemaMatcher} from '../schema-matchers'
8
- import type {HtmlDeserializerOptions} from '../types'
9
- import {createFlattenTableRule} from './flatten-tables'
10
-
11
- describe(createFlattenTableRule.name, () => {
12
- const imageMatcher: ImageSchemaMatcher = ({context, props}) => {
13
- if (
14
- !context.schema.blockObjects.some(
15
- (blockObject) => blockObject.name === 'image',
16
- )
17
- ) {
18
- return undefined
19
- }
20
-
21
- return {
22
- _type: 'image',
23
- ...(props.src ? {src: props.src} : {}),
24
- ...(props.alt ? {alt: props.alt} : {}),
25
- }
26
- }
27
-
28
- const inlineImageMatcher: ImageSchemaMatcher = ({context, props}) => {
29
- if (
30
- !context.schema.inlineObjects.some(
31
- (inlineObject) => inlineObject.name === 'image',
32
- )
33
- ) {
34
- return undefined
35
- }
36
-
37
- return {
38
- _type: 'image',
39
- ...(props.src ? {src: props.src} : {}),
40
- ...(props.alt ? {alt: props.alt} : {}),
41
- }
42
- }
43
-
44
- const schema = compileSchema(
45
- defineSchema({
46
- blockObjects: [{name: 'image', fields: [{name: 'src', type: 'string'}]}],
47
- inlineObjects: [{name: 'image', fields: [{name: 'src', type: 'string'}]}],
48
- }),
49
- )
50
-
51
- function transform(html: string, options?: HtmlDeserializerOptions) {
52
- return htmlToBlocks(html, schema, {
53
- parseHtml: (html) => new JSDOM(html).window.document,
54
- keyGenerator: createTestKeyGenerator('k'),
55
- ...options,
56
- })
57
- }
58
-
59
- const flattenTableRule = createFlattenTableRule({
60
- schema,
61
- separator: () => ({_type: 'span', text: ' '}),
62
- })
63
-
64
- test('ordinary table', () => {
65
- /**
66
- * | Year | Sales | Expenses | Profit |
67
- * | ---- | -------- | -------- | ------- |
68
- * | 2022 | \$8,000 | \$5,000 | \$3,000 |
69
- * | 2023 | \$10,000 | \$6,500 | \$3,500 |
70
- * | 2024 | \$15,000 | \$9,000 | \$6,000 |
71
- */
72
- const html = [
73
- '<table>',
74
- '<thead>',
75
- '<tr>',
76
- '<th>Year</th>',
77
- '<th>Sales</th>',
78
- '<th>Expenses</th>',
79
- '<th>Profit</th>',
80
- '</tr>',
81
- '</thead>',
82
- '<tbody>',
83
- '<tr>',
84
- '<td>2022</td>',
85
- '<td>$8,000</td>',
86
- '<td>$5,000</td>',
87
- '<td>$3,000</td>',
88
- '</tr>',
89
- '<tr>',
90
- '<td>2023</td>',
91
- '<td>$10,000</td>',
92
- '<td>$6,500</td>',
93
- '<td>$3,500</td>',
94
- '</tr>',
95
- '<tr>',
96
- '<td>2024</td>',
97
- '<td>$15,000</td>',
98
- '<td>$9,000</td>',
99
- '<td>$6,000</td>',
100
- '</tr>',
101
- '</tbody>',
102
- '</table>',
103
- ].join('')
104
-
105
- expect(
106
- getTersePt({
107
- schema,
108
- value: transform(html, {
109
- rules: [flattenTableRule],
110
- }),
111
- }),
112
- ).toEqual([
113
- 'Year, ,2022',
114
- 'Sales, ,$8,000',
115
- 'Expenses, ,$5,000',
116
- 'Profit, ,$3,000',
117
- 'Year, ,2023',
118
- 'Sales, ,$10,000',
119
- 'Expenses, ,$6,500',
120
- 'Profit, ,$3,500',
121
- 'Year, ,2024',
122
- 'Sales, ,$15,000',
123
- 'Expenses, ,$9,000',
124
- 'Profit, ,$6,000',
125
- ])
126
- })
127
-
128
- test('ordinary table without thead and tbody', () => {
129
- /**
130
- * | Year | Sales | Expenses | Profit |
131
- * | 2022 | \$8,000 | \$5,000 | \$3,000 |
132
- * | 2023 | \$10,000 | \$6,500 | \$3,500 |
133
- * | 2024 | \$15,000 | \$9,000 | \$6,000 |
134
- */
135
- const html = [
136
- '<table>',
137
- '<tr>',
138
- '<td>Year</td>',
139
- '<td>Sales</td>',
140
- '<td>Expenses</td>',
141
- '<td>Profit</td>',
142
- '</tr>',
143
- '<tr>',
144
- '<td>2022</td>',
145
- '<td>$8,000</td>',
146
- '<td>$5,000</td>',
147
- '<td>$3,000</td>',
148
- '</tr>',
149
- '<tr>',
150
- '<td>2023</td>',
151
- '<td>$10,000</td>',
152
- '<td>$6,500</td>',
153
- '<td>$3,500</td>',
154
- '</tr>',
155
- '<tr>',
156
- '<td>2024</td>',
157
- '<td>$15,000</td>',
158
- '<td>$9,000</td>',
159
- '<td>$6,000</td>',
160
- '</tr>',
161
- '</table>',
162
- ].join('')
163
-
164
- expect(
165
- getTersePt({
166
- schema,
167
- value: transform(html, {
168
- rules: [flattenTableRule],
169
- }),
170
- }),
171
- ).toEqual([
172
- 'Year',
173
- 'Sales',
174
- 'Expenses',
175
- 'Profit',
176
- '2022',
177
- '$8,000',
178
- '$5,000',
179
- '$3,000',
180
- '2023',
181
- '$10,000',
182
- '$6,500',
183
- '$3,500',
184
- '2024',
185
- '$15,000',
186
- '$9,000',
187
- '$6,000',
188
- ])
189
- })
190
-
191
- test('ordinary table without thead', () => {
192
- /**
193
- * | Year | Sales | Expenses | Profit |
194
- * | 2022 | \$8,000 | \$5,000 | \$3,000 |
195
- * | 2023 | \$10,000 | \$6,500 | \$3,500 |
196
- * | 2024 | \$15,000 | \$9,000 | \$6,000 |
197
- */
198
- const html = [
199
- '<table>',
200
- '<tbody>',
201
- '<tr>',
202
- '<td>Year</td>',
203
- '<td>Sales</td>',
204
- '<td>Expenses</td>',
205
- '<td>Profit</td>',
206
- '</tr>',
207
- '<tr>',
208
- '<td>2022</td>',
209
- '<td>$8,000</td>',
210
- '<td>$5,000</td>',
211
- '<td>$3,000</td>',
212
- '</tr>',
213
- '<tr>',
214
- '<td>2023</td>',
215
- '<td>$10,000</td>',
216
- '<td>$6,500</td>',
217
- '<td>$3,500</td>',
218
- '</tr>',
219
- '<tr>',
220
- '<td>2024</td>',
221
- '<td>$15,000</td>',
222
- '<td>$9,000</td>',
223
- '<td>$6,000</td>',
224
- '</tr>',
225
- '</tbody>',
226
- '</table>',
227
- ].join('')
228
-
229
- expect(
230
- getTersePt({
231
- schema,
232
- value: transform(html, {
233
- rules: [flattenTableRule],
234
- }),
235
- }),
236
- ).toEqual([
237
- 'Year',
238
- 'Sales',
239
- 'Expenses',
240
- 'Profit',
241
- '2022',
242
- '$8,000',
243
- '$5,000',
244
- '$3,000',
245
- '2023',
246
- '$10,000',
247
- '$6,500',
248
- '$3,500',
249
- '2024',
250
- '$15,000',
251
- '$9,000',
252
- '$6,000',
253
- ])
254
- })
255
-
256
- test('ordinary table without tbody', () => {
257
- /**
258
- * | Year | Sales | Expenses | Profit |
259
- * | 2022 | \$8,000 | \$5,000 | \$3,000 |
260
- * | 2023 | \$10,000 | \$6,500 | \$3,500 |
261
- * | 2024 | \$15,000 | \$9,000 | \$6,000 |
262
- */
263
- const html = [
264
- '<table>',
265
- '<thead>',
266
- '<tr>',
267
- '<td>Year</td>',
268
- '<td>Sales</td>',
269
- '<td>Expenses</td>',
270
- '<td>Profit</td>',
271
- '</tr>',
272
- '</thead>',
273
- '<tr>',
274
- '<td>2022</td>',
275
- '<td>$8,000</td>',
276
- '<td>$5,000</td>',
277
- '<td>$3,000</td>',
278
- '</tr>',
279
- '<tr>',
280
- '<td>2023</td>',
281
- '<td>$10,000</td>',
282
- '<td>$6,500</td>',
283
- '<td>$3,500</td>',
284
- '</tr>',
285
- '<tr>',
286
- '<td>2024</td>',
287
- '<td>$15,000</td>',
288
- '<td>$9,000</td>',
289
- '<td>$6,000</td>',
290
- '</tr>',
291
- '</table>',
292
- ].join('')
293
-
294
- expect(
295
- getTersePt({
296
- schema,
297
- value: transform(html, {
298
- rules: [flattenTableRule],
299
- }),
300
- }),
301
- ).toEqual([
302
- 'Year, ,2022',
303
- 'Sales, ,$8,000',
304
- 'Expenses, ,$5,000',
305
- 'Profit, ,$3,000',
306
- 'Year, ,2023',
307
- 'Sales, ,$10,000',
308
- 'Expenses, ,$6,500',
309
- 'Profit, ,$3,500',
310
- 'Year, ,2024',
311
- 'Sales, ,$15,000',
312
- 'Expenses, ,$9,000',
313
- 'Profit, ,$6,000',
314
- ])
315
- })
316
-
317
- test('multiple header rows', () => {
318
- /**
319
- * | Name | Age |
320
- * | Navn | Alder |
321
- * | --- | --- |
322
- * | John Doe | 18 |
323
- * | Jane Smith | 20 |
324
- */
325
- const html = [
326
- '<table>',
327
- '<thead>',
328
- '<tr>',
329
- '<th>Name</th>',
330
- '<th>Age</th>',
331
- '</tr>',
332
- '<tr>',
333
- '<th>Navn</th>',
334
- '<th>Alder</th>',
335
- '</tr>',
336
- '</thead>',
337
- '<tbody>',
338
- '<tr>',
339
- '<td>John Doe</td>',
340
- '<td>18</td>',
341
- '</tr>',
342
- '<tr>',
343
- '<td>Jane Smith</td>',
344
- '<td>20</td>',
345
- '</tr>',
346
- '</tbody>',
347
- '</table>',
348
- ].join('')
349
-
350
- expect(
351
- getTersePt({
352
- schema,
353
- value: transform(html, {
354
- rules: [flattenTableRule],
355
- }),
356
- }),
357
- ).toEqual([
358
- 'Name',
359
- 'Age',
360
- 'Navn',
361
- 'Alder',
362
- 'John Doe',
363
- '18',
364
- 'Jane Smith',
365
- '20',
366
- ])
367
- })
368
-
369
- test('only thead', () => {
370
- /**
371
- * | Name | John Doe |
372
- * | Age | 18 |
373
- */
374
- const html = [
375
- '<table>',
376
- '<thead>',
377
- '<tr>',
378
- '<th>Name</th>',
379
- '<th>John Doe</th>',
380
- '</tr>',
381
- '<tr>',
382
- '<th>Age</th>',
383
- '<th>18</th>',
384
- '</tr>',
385
- '</thead>',
386
- '</table>',
387
- ].join('')
388
-
389
- expect(
390
- getTersePt({
391
- schema,
392
- value: transform(html, {
393
- rules: [flattenTableRule],
394
- }),
395
- }),
396
- ).toEqual(['Name', 'John Doe', 'Age', '18'])
397
- })
398
-
399
- describe('table with images', () => {
400
- /**
401
- * | Name | Photo |
402
- * | --- | --- |
403
- * | John Doe | <img src="https://via.placeholder.com/150" alt="John Doe" /> |
404
- * | Jane Smith | <img src="https://via.placeholder.com/150" alt="Jane Smith" /> |
405
- */
406
- const html = [
407
- '<table>',
408
- '<thead>',
409
- '<tr>',
410
- '<th>Name</th>',
411
- '<th>Photo</th>',
412
- '</tr>',
413
- '</thead>',
414
- '<tbody>',
415
- '<tr>',
416
- '<td>John Doe</td>',
417
- '<td><img src="https://via.placeholder.com/150" alt="John Doe" /></td>',
418
- '</tr>',
419
- '<tr>',
420
- '<td>Jane Smith</td>',
421
- '<td><img src="https://via.placeholder.com/150" alt="Jane Smith" /></td>',
422
- '</tr>',
423
- '</tbody>',
424
- '</table>',
425
- ].join('')
426
-
427
- test('no image matcher', () => {
428
- expect(
429
- getTersePt({
430
- schema,
431
- value: transform(html, {
432
- matchers: undefined,
433
- rules: [flattenTableRule],
434
- }),
435
- }),
436
- ).toEqual(['Name, ,John Doe', 'Photo', 'Name, ,Jane Smith', 'Photo'])
437
- })
438
-
439
- test('block image matcher', () => {
440
- expect(
441
- getTersePt({
442
- schema,
443
- value: transform(html, {
444
- matchers: {
445
- image: imageMatcher,
446
- },
447
- rules: [flattenTableRule],
448
- }),
449
- }),
450
- ).toEqual([
451
- 'Name, ,John Doe',
452
- 'Photo',
453
- '{image}',
454
- 'Name, ,Jane Smith',
455
- 'Photo',
456
- '{image}',
457
- ])
458
- })
459
-
460
- test('block and inline image matcher', () => {
461
- expect(
462
- getTersePt({
463
- schema,
464
- value: transform(html, {
465
- matchers: {
466
- image: imageMatcher,
467
- inlineImage: inlineImageMatcher,
468
- },
469
- rules: [flattenTableRule],
470
- }),
471
- }),
472
- ).toEqual([
473
- 'Name, ,John Doe',
474
- 'Photo, ,{image}',
475
- 'Name, ,Jane Smith',
476
- 'Photo, ,{image}',
477
- ])
478
- })
479
-
480
- describe('Google Docs', () => {
481
- test('simple table with thead', () => {
482
- const html = `<meta charset='utf-8'><meta charset="utf-8"><b style="font-weight:normal;" id="docs-internal-guid-e0aa048e-7fff-f3cb-0d6d-5e68751be0e3"><div dir="ltr" style="margin-left:0pt;" align="left"><table style="border:none;border-collapse:collapse;table-layout:fixed;width:468pt"><colgroup><col /><col /></colgroup><thead><tr style="height:0pt"><th style="border-left:solid #000000 1pt;border-right:solid #000000 1pt;border-bottom:solid #000000 1pt;border-top:solid #000000 1pt;vertical-align:top;padding:5pt 5pt 5pt 5pt;overflow:hidden;overflow-wrap:break-word;" scope="col"><p dir="ltr" style="line-height:1.2;margin-top:0pt;margin-bottom:0pt;"><span style="font-size:12pt;font-family:Arial,sans-serif;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Header 1</span></p></th><th style="border-left:solid #000000 1pt;border-right:solid #000000 1pt;border-bottom:solid #000000 1pt;border-top:solid #000000 1pt;vertical-align:top;padding:5pt 5pt 5pt 5pt;overflow:hidden;overflow-wrap:break-word;" scope="col"><p dir="ltr" style="line-height:1.2;margin-top:0pt;margin-bottom:0pt;"><span style="font-size:12pt;font-family:Arial,sans-serif;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Header 2</span></p></th></tr></thead><tbody><tr style="height:0pt"><td style="border-left:solid #000000 1pt;border-right:solid #000000 1pt;border-bottom:solid #000000 1pt;border-top:solid #000000 1pt;vertical-align:top;padding:5pt 5pt 5pt 5pt;overflow:hidden;overflow-wrap:break-word;"><p dir="ltr" style="line-height:1.2;margin-top:0pt;margin-bottom:0pt;"><span style="font-size:12pt;font-family:Arial,sans-serif;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Cell 1</span></p></td><td style="border-left:solid #000000 1pt;border-right:solid #000000 1pt;border-bottom:solid #000000 1pt;border-top:solid #000000 1pt;vertical-align:top;padding:5pt 5pt 5pt 5pt;overflow:hidden;overflow-wrap:break-word;"><p dir="ltr" style="line-height:1.2;margin-top:0pt;margin-bottom:0pt;"><span style="font-size:12pt;font-family:Arial,sans-serif;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Cell 2</span></p></td></tr></tbody></table></div></b>`
483
-
484
- expect(
485
- getTersePt({
486
- schema,
487
- value: transform(html, {
488
- rules: [flattenTableRule],
489
- }),
490
- }),
491
- ).toEqual(['Header 1, ,Cell 1', 'Header 2, ,Cell 2'])
492
- })
493
- })
494
- })
495
- })
@@ -1,216 +0,0 @@
1
- import {
2
- isTextBlock,
3
- type PortableTextObject,
4
- type PortableTextSpan,
5
- type Schema,
6
- } from '@portabletext/schema'
7
- import {flattenNestedBlocks} from '../HtmlDeserializer/flatten-nested-blocks'
8
- import {isElement, tagName} from '../HtmlDeserializer/helpers'
9
- import type {
10
- ArbitraryTypedObject,
11
- DeserializerRule,
12
- TypedObject,
13
- } from '../types'
14
-
15
- /**
16
- * An opinionated `DeserializerRule` that flattens tables in a way that repeats
17
- * the header row for each cell in the row.
18
- *
19
- * @example
20
- * ```html
21
- * <table>
22
- * <thead>
23
- * <tr>
24
- * <th>Header 1</th>
25
- * <th>Header 2</th>
26
- * </tr>
27
- * </thead>
28
- * <tbody>
29
- * <tr>
30
- * <td>Cell 1</td>
31
- * <td>Cell 2</td>
32
- * </tr>
33
- * </tbody>
34
- * </table>
35
- * ```
36
- * Turns into
37
- * ```json
38
- * [
39
- * {
40
- * _type: 'block',
41
- * children: [
42
- * {
43
- * _type: 'text',
44
- * text: 'Header 1'
45
- * },
46
- * {
47
- * _type: 'text',
48
- * text: 'Cell 1'
49
- * }
50
- * ]
51
- * },
52
- * {
53
- * _type: 'block',
54
- * children: [
55
- * {
56
- * _type: 'text',
57
- * text: 'Header 2'
58
- * },
59
- * {
60
- * _type: 'text',
61
- * text: 'Cell 2'
62
- * }
63
- * ]
64
- * }
65
- * ]
66
- * ```
67
- *
68
- * Use the `separator` option to control if a child element should separate
69
- * headers and cells.
70
- *
71
- * @beta
72
- */
73
- export function createFlattenTableRule({
74
- schema,
75
- separator,
76
- }: {
77
- schema: Schema
78
- separator?: () =>
79
- | (Omit<PortableTextSpan, '_key'> & {_key?: string})
80
- | (Omit<PortableTextObject, '_key'> & {_key?: string})
81
- | undefined
82
- }): DeserializerRule {
83
- return {
84
- deserialize: (node, next) => {
85
- if (!isElement(node) || tagName(node) !== 'table') {
86
- return undefined
87
- }
88
-
89
- const columnCounts = [...node.querySelectorAll('tr')].map((row) => {
90
- const cells = row.querySelectorAll('td, th')
91
- return cells.length
92
- })
93
-
94
- const firstColumnCount = columnCounts[0]
95
-
96
- if (
97
- !firstColumnCount ||
98
- !columnCounts.every((count) => count === firstColumnCount)
99
- ) {
100
- // If the column counts are not all the same, we return undefined.
101
- return undefined
102
- }
103
-
104
- const thead = node.querySelector('thead')
105
- const headerRows = thead?.querySelectorAll('tr')
106
- const tbody = node.querySelector('tbody')
107
- const bodyRows = tbody ? [...tbody.querySelectorAll('tr')] : []
108
-
109
- if (!headerRows || !bodyRows) {
110
- return undefined
111
- }
112
-
113
- const headerRow = [...headerRows][0]
114
-
115
- if (!headerRow || headerRows.length > 1) {
116
- return undefined
117
- }
118
-
119
- const headerCells = headerRow.querySelectorAll('th, td')
120
- const headerResults = [...headerCells].map((headerCell) =>
121
- next(headerCell),
122
- )
123
-
124
- // Process tbody rows and combine with headers
125
- const rows: TypedObject[] = []
126
-
127
- for (const row of bodyRows) {
128
- const cells = row.querySelectorAll('td')
129
-
130
- let cellIndex = 0
131
- for (const cell of cells) {
132
- const result = next(cell)
133
-
134
- if (!result) {
135
- cellIndex++
136
- continue
137
- }
138
-
139
- const headerResult = headerResults[cellIndex]
140
-
141
- if (!headerResult) {
142
- // If we can't find a corresponding header, then we just push
143
- // the deserialized cell as is.
144
- if (Array.isArray(result)) {
145
- rows.push(...result)
146
- } else {
147
- rows.push(result)
148
- }
149
- cellIndex++
150
- continue
151
- }
152
-
153
- const flattenedHeaderResult = flattenNestedBlocks(
154
- {schema},
155
- (Array.isArray(headerResult)
156
- ? headerResult
157
- : [headerResult]) as Array<ArbitraryTypedObject>,
158
- )
159
- const firstFlattenedHeaderResult = flattenedHeaderResult[0]
160
- const flattenedResult = flattenNestedBlocks(
161
- {schema},
162
- (Array.isArray(result)
163
- ? result
164
- : [result]) as Array<ArbitraryTypedObject>,
165
- )
166
- const firstFlattenedResult = flattenedResult[0]
167
-
168
- if (
169
- flattenedHeaderResult.length === 1 &&
170
- isTextBlock({schema}, firstFlattenedHeaderResult) &&
171
- flattenedResult.length === 1 &&
172
- isTextBlock({schema}, firstFlattenedResult)
173
- ) {
174
- const separatorChild = separator?.()
175
- // If the header result and the cell result are text blocks then
176
- // we merge them together.
177
- const mergedTextBlock = {
178
- ...firstFlattenedHeaderResult,
179
- children: [
180
- ...firstFlattenedHeaderResult.children,
181
- ...(separatorChild ? [separatorChild] : []),
182
- ...firstFlattenedResult.children,
183
- ],
184
- markDefs: [
185
- ...(firstFlattenedHeaderResult.markDefs ?? []),
186
- ...(firstFlattenedResult.markDefs ?? []),
187
- ],
188
- }
189
-
190
- rows.push(mergedTextBlock)
191
- cellIndex++
192
- continue
193
- }
194
-
195
- // Otherwise, we push the header result and the cell result as is.
196
- if (Array.isArray(headerResult)) {
197
- rows.push(...headerResult)
198
- } else {
199
- rows.push(headerResult)
200
- }
201
-
202
- if (Array.isArray(result)) {
203
- rows.push(...result)
204
- } else {
205
- rows.push(result)
206
- }
207
-
208
- cellIndex++
209
- }
210
- }
211
-
212
- // Return the processed rows as individual text blocks
213
- return rows
214
- },
215
- }
216
- }