@portabletext/block-tools 4.1.8 → 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 +5 -6
  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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/block-tools",
3
- "version": "4.1.8",
3
+ "version": "4.1.9",
4
4
  "description": "Can format HTML, Slate JSON or Sanity block array into any other format.",
5
5
  "keywords": [
6
6
  "portable-text",
@@ -33,14 +33,13 @@
33
33
  "main": "./lib/index.js",
34
34
  "types": "./lib/index.d.ts",
35
35
  "files": [
36
- "lib",
37
- "src"
36
+ "lib"
38
37
  ],
39
38
  "dependencies": {
40
39
  "@sanity/types": "^4.20.3",
41
40
  "lodash": "^4.17.21",
42
- "@portabletext/sanity-bridge": "^1.2.11",
43
- "@portabletext/schema": "^2.0.0"
41
+ "@portabletext/sanity-bridge": "^1.2.12",
42
+ "@portabletext/schema": "^2.0.1"
44
43
  },
45
44
  "devDependencies": {
46
45
  "@sanity/pkg-utils": "^10.1.1",
@@ -52,7 +51,7 @@
52
51
  "jsdom": "^27.0.0",
53
52
  "typescript": "5.9.3",
54
53
  "vitest": "^4.0.14",
55
- "@portabletext/test": "^1.0.1"
54
+ "@portabletext/test": "^1.0.2"
56
55
  },
57
56
  "engines": {
58
57
  "node": ">=20.19 <22 || >=22.12"
@@ -1,248 +0,0 @@
1
- import {compileSchema, defineSchema} from '@portabletext/schema'
2
- import {describe, expect, test} from 'vitest'
3
- import {createTestKeyGenerator} from '../../test/test-key-generator'
4
- import {flattenNestedBlocks} from './flatten-nested-blocks'
5
-
6
- describe(flattenNestedBlocks.name, () => {
7
- test('flattening text blocks', () => {
8
- const schema = compileSchema(defineSchema({}))
9
- expect(
10
- flattenNestedBlocks({schema}, [
11
- {
12
- _type: 'block',
13
- children: [
14
- {
15
- _type: 'block',
16
- children: [
17
- {
18
- _type: 'span',
19
- marks: [],
20
- text: 'foo',
21
- },
22
- ],
23
- markDefs: [],
24
- style: 'normal',
25
- },
26
- ],
27
- markDefs: [],
28
- style: 'normal',
29
- },
30
- ]),
31
- ).toEqual([
32
- {
33
- _type: 'block',
34
- children: [{_type: 'span', text: 'foo', marks: []}],
35
- markDefs: [],
36
- style: 'normal',
37
- },
38
- ])
39
- })
40
-
41
- test('flattening text blocks with block objects in schema', () => {
42
- const schema = compileSchema(
43
- defineSchema({blockObjects: [{name: 'image'}]}),
44
- )
45
- expect(
46
- flattenNestedBlocks({schema}, [
47
- {
48
- _type: 'block',
49
- children: [
50
- {
51
- _type: 'block',
52
- children: [
53
- {
54
- _type: 'span',
55
- text: 'foo',
56
- marks: [],
57
- },
58
- ],
59
- markDefs: [],
60
- style: 'normal',
61
- },
62
- ],
63
- markDefs: [],
64
- style: 'normal',
65
- },
66
- ]),
67
- ).toEqual([
68
- {
69
- _type: 'block',
70
- children: [{_type: 'span', text: 'foo', marks: []}],
71
- markDefs: [],
72
- style: 'normal',
73
- },
74
- ])
75
- })
76
-
77
- test('flattening text blocks with styles in schema', () => {
78
- const schema = compileSchema(
79
- defineSchema({
80
- styles: [{name: 'h1'}],
81
- }),
82
- )
83
- expect(
84
- flattenNestedBlocks({schema}, [
85
- {
86
- _type: 'block',
87
- children: [
88
- {
89
- _type: 'block',
90
- children: [
91
- {
92
- _type: 'span',
93
- marks: [],
94
- text: 'foo',
95
- },
96
- ],
97
- markDefs: [],
98
- style: 'normal',
99
- },
100
- ],
101
- markDefs: [],
102
- style: 'h1',
103
- },
104
- ]),
105
- ).toEqual([
106
- {
107
- _type: 'block',
108
- children: [{_type: 'span', text: 'foo', marks: []}],
109
- markDefs: [],
110
- style: 'normal',
111
- },
112
- ])
113
- })
114
-
115
- test('splitting text block', () => {
116
- const keyGenerator = createTestKeyGenerator('k')
117
- const schema = compileSchema(
118
- defineSchema({
119
- styles: [{name: 'h1'}],
120
- annotations: [{name: 'link'}],
121
- blockObjects: [{name: 'image'}],
122
- }),
123
- )
124
- const blockKey = keyGenerator()
125
- const fooKey = keyGenerator()
126
- const imageKey = keyGenerator()
127
- const barKey = keyGenerator()
128
- const linkKey = keyGenerator()
129
-
130
- expect(
131
- flattenNestedBlocks({schema}, [
132
- {
133
- _key: blockKey,
134
- _type: 'block',
135
- children: [
136
- {
137
- _key: fooKey,
138
- _type: 'span',
139
- text: 'foo',
140
- },
141
- {
142
- _key: imageKey,
143
- _type: 'image',
144
- },
145
- {
146
- _key: barKey,
147
- _type: 'span',
148
- text: 'bar',
149
- marks: [linkKey],
150
- },
151
- ],
152
- style: 'h1',
153
- markDefs: [
154
- {
155
- _key: linkKey,
156
- _type: 'link',
157
- },
158
- ],
159
- },
160
- ]),
161
- ).toEqual([
162
- {
163
- _key: blockKey,
164
- _type: 'block',
165
- children: [{_key: fooKey, _type: 'span', text: 'foo'}],
166
- style: 'h1',
167
- markDefs: [{_key: linkKey, _type: 'link'}],
168
- },
169
- {
170
- _key: imageKey,
171
- _type: 'image',
172
- },
173
- {
174
- _key: blockKey,
175
- _type: 'block',
176
- children: [
177
- {_key: barKey, _type: 'span', text: 'bar', marks: [linkKey]},
178
- ],
179
- style: 'h1',
180
- markDefs: [{_key: linkKey, _type: 'link'}],
181
- },
182
- ])
183
- })
184
-
185
- test('splitting text block with __block', () => {
186
- const keyGenerator = createTestKeyGenerator('k')
187
- const schema = compileSchema(
188
- defineSchema({
189
- blockObjects: [{name: 'image'}],
190
- }),
191
- )
192
- const blockKey = keyGenerator()
193
- const fooKey = keyGenerator()
194
- const imageKey = keyGenerator()
195
- const barKey = keyGenerator()
196
-
197
- expect(
198
- flattenNestedBlocks({schema}, [
199
- {
200
- _key: blockKey,
201
- _type: 'block',
202
- children: [
203
- {
204
- _key: fooKey,
205
- _type: 'span',
206
- text: 'foo',
207
- marks: [],
208
- },
209
- {
210
- _type: '__block',
211
- block: {
212
- _key: imageKey,
213
- _type: 'image',
214
- },
215
- },
216
- {
217
- _key: barKey,
218
- _type: 'span',
219
- text: 'bar',
220
- marks: [],
221
- },
222
- ],
223
- style: 'normal',
224
- markDefs: [],
225
- },
226
- ]),
227
- ).toEqual([
228
- {
229
- _key: blockKey,
230
- _type: 'block',
231
- children: [{_key: fooKey, _type: 'span', text: 'foo', marks: []}],
232
- style: 'normal',
233
- markDefs: [],
234
- },
235
- {
236
- _key: imageKey,
237
- _type: 'image',
238
- },
239
- {
240
- _key: blockKey,
241
- _type: 'block',
242
- children: [{_key: barKey, _type: 'span', text: 'bar', marks: []}],
243
- style: 'normal',
244
- markDefs: [],
245
- },
246
- ])
247
- })
248
- })
@@ -1,173 +0,0 @@
1
- import type {Schema} from '@portabletext/schema'
2
- import {
3
- isSpan,
4
- isTextBlock,
5
- type PortableTextBlock,
6
- type PortableTextObject,
7
- type PortableTextSpan,
8
- type PortableTextTextBlock,
9
- } from '@portabletext/schema'
10
- import {isEqual} from 'lodash'
11
- import {
12
- isArbitraryTypedObject,
13
- type ArbitraryTypedObject,
14
- type TypedObject,
15
- } from '../types'
16
-
17
- export function flattenNestedBlocks(
18
- context: {
19
- schema: Schema
20
- },
21
- blocks: Array<ArbitraryTypedObject>,
22
- ): TypedObject[] {
23
- const flattened = blocks.flatMap((block) => {
24
- if (isBlockContainer(block)) {
25
- return flattenNestedBlocks(context, [block.block])
26
- }
27
-
28
- if (isTextBlock(context, block)) {
29
- const hasBlockObjects = block.children.some((child) => {
30
- const knownBlockObject = context.schema.blockObjects.some(
31
- (blockObject) => blockObject.name === child._type,
32
- )
33
- return knownBlockObject
34
- })
35
- const hasBlocks = block.children.some(
36
- (child) => child._type === '__block' || child._type === 'block',
37
- )
38
-
39
- if (hasBlockObjects || hasBlocks) {
40
- const splitChildren = getSplitChildren(context, block)
41
-
42
- if (
43
- splitChildren.length === 1 &&
44
- splitChildren[0].type === 'children' &&
45
- isEqual(splitChildren[0].children, block.children)
46
- ) {
47
- return [block]
48
- }
49
-
50
- return splitChildren.flatMap((slice) => {
51
- if (slice.type === 'block object') {
52
- return [slice.block]
53
- }
54
-
55
- if (slice.type === 'block') {
56
- return flattenNestedBlocks(context, [
57
- slice.block as ArbitraryTypedObject,
58
- ])
59
- }
60
-
61
- if (slice.children.length > 0) {
62
- if (
63
- slice.children.every(
64
- (child) => isSpan(context, child) && child.text.trim() === '',
65
- )
66
- ) {
67
- return []
68
- }
69
-
70
- return flattenNestedBlocks(context, [
71
- {
72
- ...block,
73
- children: slice.children,
74
- },
75
- ])
76
- }
77
-
78
- return []
79
- })
80
- }
81
-
82
- return [block]
83
- }
84
-
85
- return [block]
86
- })
87
-
88
- return flattened
89
- }
90
-
91
- function isBlockContainer(
92
- block: ArbitraryTypedObject,
93
- ): block is BlockContainer {
94
- return block._type === '__block' && isArbitraryTypedObject(block.block)
95
- }
96
-
97
- type BlockContainer = {
98
- _type: '__block'
99
- block: ArbitraryTypedObject
100
- }
101
-
102
- function getSplitChildren(
103
- context: {schema: Schema},
104
- block: PortableTextTextBlock,
105
- ) {
106
- return block.children.reduce(
107
- (slices, child) => {
108
- const knownInlineObject = context.schema.inlineObjects.some(
109
- (inlineObject) => inlineObject.name === child._type,
110
- )
111
- const knownBlockObject = context.schema.blockObjects.some(
112
- (blockObject) => blockObject.name === child._type,
113
- )
114
-
115
- const lastSlice = slices.pop()
116
-
117
- if (!isSpan(context, child) && !knownInlineObject) {
118
- if (knownBlockObject) {
119
- return [
120
- ...slices,
121
- ...(lastSlice ? [lastSlice] : []),
122
- {type: 'block object' as const, block: child},
123
- ]
124
- }
125
- }
126
-
127
- if (child._type === '__block') {
128
- return [
129
- ...slices,
130
- ...(lastSlice ? [lastSlice] : []),
131
- {
132
- type: 'block object' as const,
133
- block: (child as any).block,
134
- },
135
- ]
136
- }
137
-
138
- if (child._type === 'block') {
139
- return [
140
- ...slices,
141
- ...(lastSlice ? [lastSlice] : []),
142
- {type: 'block' as const, block: child},
143
- ]
144
- }
145
-
146
- if (lastSlice) {
147
- if (lastSlice.type === 'children') {
148
- return [
149
- ...slices,
150
- {
151
- type: 'children' as const,
152
- children: [...lastSlice.children, child],
153
- },
154
- ]
155
- }
156
- }
157
-
158
- return [
159
- ...slices,
160
- ...(lastSlice ? [lastSlice] : []),
161
- {type: 'children' as const, children: [child]},
162
- ]
163
- },
164
- [] as Array<
165
- | {
166
- type: 'children'
167
- children: Array<PortableTextSpan | PortableTextObject>
168
- }
169
- | {type: 'block object'; block: PortableTextObject}
170
- | {type: 'block'; block: PortableTextBlock}
171
- >,
172
- )
173
- }
@@ -1,108 +0,0 @@
1
- import type {Schema} from '@portabletext/schema'
2
- import {isTextBlock, type PortableTextObject} from '@portabletext/schema'
3
- import {DEFAULT_BLOCK} from '../constants'
4
- import type {
5
- ArbitraryTypedObject,
6
- HtmlParser,
7
- MinimalBlock,
8
- MinimalSpan,
9
- PlaceholderAnnotation,
10
- PlaceholderDecorator,
11
- TypedObject,
12
- } from '../types'
13
- import {resolveJsType} from '../util/resolveJsType'
14
-
15
- /**
16
- * Utility function that always return a lowerCase version of the element.tagName
17
- *
18
- * @param el - Element to get tag name for
19
- * @returns Lowercase tagName for that element, or undefined if not an element
20
- */
21
- export function tagName(el: HTMLElement | Node | null): string | undefined {
22
- if (el && 'tagName' in el) {
23
- return el.tagName.toLowerCase()
24
- }
25
-
26
- return undefined
27
- }
28
-
29
- /**
30
- * A default `parseHtml` function that returns the html using `DOMParser`.
31
- *
32
- * @returns HTML Parser based on `DOMParser`
33
- */
34
- export function defaultParseHtml(): HtmlParser {
35
- if (resolveJsType(DOMParser) === 'undefined') {
36
- throw new Error(
37
- 'The native `DOMParser` global which the `Html` deserializer uses by ' +
38
- 'default is not present in this environment. ' +
39
- 'You must supply the `options.parseHtml` function instead.',
40
- )
41
- }
42
- return (html) => {
43
- return new DOMParser().parseFromString(html, 'text/html')
44
- }
45
- }
46
-
47
- export function ensureRootIsBlocks(
48
- schema: Schema,
49
- objects: Array<ArbitraryTypedObject>,
50
- ): ArbitraryTypedObject[] {
51
- return objects.reduce((blocks, node, i, original) => {
52
- if (node._type === 'block') {
53
- blocks.push(node)
54
- return blocks
55
- }
56
-
57
- if (node._type === '__block') {
58
- blocks.push((node as any).block)
59
- return blocks
60
- }
61
-
62
- const lastBlock = blocks[blocks.length - 1]
63
- if (
64
- i > 0 &&
65
- !isTextBlock({schema}, original[i - 1]) &&
66
- isTextBlock({schema}, lastBlock)
67
- ) {
68
- lastBlock.children.push(node as PortableTextObject)
69
- return blocks
70
- }
71
-
72
- const block = {
73
- ...DEFAULT_BLOCK,
74
- children: [node],
75
- }
76
-
77
- blocks.push(block)
78
- return blocks
79
- }, [] as ArbitraryTypedObject[])
80
- }
81
-
82
- export function isNodeList(node: unknown): node is NodeList {
83
- return Object.prototype.toString.call(node) === '[object NodeList]'
84
- }
85
-
86
- export function isMinimalSpan(node: TypedObject): node is MinimalSpan {
87
- return node._type === 'span'
88
- }
89
-
90
- export function isMinimalBlock(node: TypedObject): node is MinimalBlock {
91
- return node._type === 'block'
92
- }
93
-
94
- export function isPlaceholderDecorator(
95
- node: TypedObject,
96
- ): node is PlaceholderDecorator {
97
- return node._type === '__decorator'
98
- }
99
-
100
- export function isPlaceholderAnnotation(
101
- node: TypedObject,
102
- ): node is PlaceholderAnnotation {
103
- return node._type === '__annotation'
104
- }
105
-
106
- export function isElement(node: Node): node is Element {
107
- return node.nodeType === 1
108
- }