@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.
- package/package.json +5 -6
- package/src/HtmlDeserializer/flatten-nested-blocks.test.ts +0 -248
- package/src/HtmlDeserializer/flatten-nested-blocks.ts +0 -173
- package/src/HtmlDeserializer/helpers.ts +0 -108
- package/src/HtmlDeserializer/index.ts +0 -315
- package/src/HtmlDeserializer/preprocessors/index.ts +0 -15
- package/src/HtmlDeserializer/preprocessors/preprocessor.gdocs.ts +0 -66
- package/src/HtmlDeserializer/preprocessors/preprocessor.html.ts +0 -57
- package/src/HtmlDeserializer/preprocessors/preprocessor.notion.ts +0 -25
- package/src/HtmlDeserializer/preprocessors/preprocessor.whitespace.ts +0 -56
- package/src/HtmlDeserializer/preprocessors/preprocessor.word.ts +0 -92
- package/src/HtmlDeserializer/preprocessors/xpathResult.ts +0 -13
- package/src/HtmlDeserializer/rules/index.ts +0 -21
- package/src/HtmlDeserializer/rules/rules.gdocs.ts +0 -188
- package/src/HtmlDeserializer/rules/rules.html.ts +0 -356
- package/src/HtmlDeserializer/rules/rules.notion.ts +0 -57
- package/src/HtmlDeserializer/rules/rules.whitespace-text-node.ts +0 -31
- package/src/HtmlDeserializer/rules/rules.word.ts +0 -95
- package/src/HtmlDeserializer/trim-whitespace.ts +0 -157
- package/src/HtmlDeserializer/word-online/asserters.word-online.ts +0 -153
- package/src/HtmlDeserializer/word-online/preprocessor.word-online.ts +0 -263
- package/src/HtmlDeserializer/word-online/rules.word-online.ts +0 -390
- package/src/constants.ts +0 -104
- package/src/index.ts +0 -49
- package/src/rules/_exports/index.ts +0 -1
- package/src/rules/flatten-tables.test.ts +0 -495
- package/src/rules/flatten-tables.ts +0 -216
- package/src/rules/index.ts +0 -1
- package/src/schema-matchers.ts +0 -41
- package/src/types.ts +0 -100
- package/src/util/findBlockType.ts +0 -13
- package/src/util/normalizeBlock.ts +0 -171
- package/src/util/randomKey.ts +0 -28
- package/src/util/resolveJsType.ts +0 -44
package/src/rules/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './flatten-tables'
|
package/src/schema-matchers.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type {Schema} from '@portabletext/schema'
|
|
2
|
-
import type {ArbitraryTypedObject} from './types'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Use the current `Schema` as well as the potential element props to determine
|
|
6
|
-
* what Portable Text Object to use to represent the element.
|
|
7
|
-
*/
|
|
8
|
-
type ObjectSchemaMatcher<TProps extends Record<string, unknown>> = ({
|
|
9
|
-
context,
|
|
10
|
-
props,
|
|
11
|
-
}: {
|
|
12
|
-
context: {schema: Schema; keyGenerator: () => string}
|
|
13
|
-
props: TProps
|
|
14
|
-
}) => ArbitraryTypedObject | undefined
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Use the current `Schema` as well as the potential img element props to
|
|
18
|
-
* determine what Portable Text Object to use to represent the image.
|
|
19
|
-
* @beta
|
|
20
|
-
*/
|
|
21
|
-
export type ImageSchemaMatcher = ObjectSchemaMatcher<{
|
|
22
|
-
src?: string
|
|
23
|
-
alt?: string
|
|
24
|
-
[key: string]: string | undefined
|
|
25
|
-
}>
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @beta
|
|
29
|
-
*/
|
|
30
|
-
export type SchemaMatchers = {
|
|
31
|
-
/**
|
|
32
|
-
* Called whenever the HTML parsing encounters an `<img>` element that is
|
|
33
|
-
* inferred to be a block element.
|
|
34
|
-
*/
|
|
35
|
-
image?: ImageSchemaMatcher
|
|
36
|
-
/**
|
|
37
|
-
* Called whenever the HTML parsing encounters an `<img>` element that is
|
|
38
|
-
* inferred to be an inline element.
|
|
39
|
-
*/
|
|
40
|
-
inlineImage?: ImageSchemaMatcher
|
|
41
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import type {PortableTextObject} from '@portabletext/schema'
|
|
2
|
-
import type {SchemaMatchers} from './schema-matchers'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @public
|
|
6
|
-
*/
|
|
7
|
-
export interface TypedObject {
|
|
8
|
-
_type: string
|
|
9
|
-
_key?: string
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @public
|
|
14
|
-
*/
|
|
15
|
-
export interface ArbitraryTypedObject extends TypedObject {
|
|
16
|
-
[key: string]: unknown
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function isArbitraryTypedObject(
|
|
20
|
-
object: unknown,
|
|
21
|
-
): object is ArbitraryTypedObject {
|
|
22
|
-
return isRecord(object) && typeof object._type === 'string'
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
26
|
-
return !!value && (typeof value === 'object' || typeof value === 'function')
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface MinimalSpan {
|
|
30
|
-
_type: 'span'
|
|
31
|
-
_key?: string
|
|
32
|
-
text: string
|
|
33
|
-
marks?: string[]
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface MinimalBlock extends TypedObject {
|
|
37
|
-
_type: 'block'
|
|
38
|
-
children: TypedObject[]
|
|
39
|
-
markDefs?: TypedObject[]
|
|
40
|
-
style?: string
|
|
41
|
-
level?: number
|
|
42
|
-
listItem?: string
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface PlaceholderDecorator {
|
|
46
|
-
_type: '__decorator'
|
|
47
|
-
name: string
|
|
48
|
-
children: TypedObject[]
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface PlaceholderAnnotation {
|
|
52
|
-
_type: '__annotation'
|
|
53
|
-
markDef: PortableTextObject
|
|
54
|
-
children: TypedObject[]
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* @public
|
|
59
|
-
*/
|
|
60
|
-
export type HtmlParser = (html: string) => Document
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* @public
|
|
64
|
-
*/
|
|
65
|
-
export type WhiteSpacePasteMode = 'preserve' | 'remove' | 'normalize'
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @public
|
|
69
|
-
*/
|
|
70
|
-
export interface HtmlDeserializerOptions {
|
|
71
|
-
keyGenerator?: () => string
|
|
72
|
-
rules?: DeserializerRule[]
|
|
73
|
-
parseHtml?: HtmlParser
|
|
74
|
-
unstable_whitespaceOnPasteMode?: WhiteSpacePasteMode
|
|
75
|
-
/**
|
|
76
|
-
* Custom schema matchers to use when deserializing HTML to Portable Text.
|
|
77
|
-
* @beta
|
|
78
|
-
*/
|
|
79
|
-
matchers?: SchemaMatchers
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export interface HtmlPreprocessorOptions {
|
|
83
|
-
unstable_whitespaceOnPasteMode?: WhiteSpacePasteMode
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* @public
|
|
88
|
-
*/
|
|
89
|
-
export interface DeserializerRule {
|
|
90
|
-
deserialize: (
|
|
91
|
-
el: Node,
|
|
92
|
-
next: (
|
|
93
|
-
elements: Node | Node[] | NodeList,
|
|
94
|
-
) => TypedObject | TypedObject[] | undefined,
|
|
95
|
-
createBlock: (props: ArbitraryTypedObject) => {
|
|
96
|
-
_type: string
|
|
97
|
-
block: ArbitraryTypedObject
|
|
98
|
-
},
|
|
99
|
-
) => TypedObject | TypedObject[] | undefined
|
|
100
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type {BlockSchemaType, SchemaType} from '@sanity/types'
|
|
2
|
-
|
|
3
|
-
export function findBlockType(type: SchemaType): type is BlockSchemaType {
|
|
4
|
-
if (type.type) {
|
|
5
|
-
return findBlockType(type.type)
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
if (type.name === 'block') {
|
|
9
|
-
return true
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
return false
|
|
13
|
-
}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import type {Schema} from '@portabletext/schema'
|
|
2
|
-
import {
|
|
3
|
-
isSpan,
|
|
4
|
-
type PortableTextSpan,
|
|
5
|
-
type PortableTextTextBlock,
|
|
6
|
-
} from '@portabletext/schema'
|
|
7
|
-
import {isEqual} from 'lodash'
|
|
8
|
-
import type {TypedObject} from '../types'
|
|
9
|
-
import {keyGenerator} from './randomKey'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Block normalization options
|
|
13
|
-
*
|
|
14
|
-
* @public
|
|
15
|
-
*/
|
|
16
|
-
export interface BlockNormalizationOptions {
|
|
17
|
-
/**
|
|
18
|
-
* Decorator names that are allowed within portable text blocks, eg `em`, `strong`
|
|
19
|
-
*/
|
|
20
|
-
allowedDecorators?: string[]
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Name of the portable text block type, if not `block`
|
|
24
|
-
*/
|
|
25
|
-
blockTypeName?: string
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Custom key generator function
|
|
29
|
-
*/
|
|
30
|
-
keyGenerator?: () => string
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Normalizes a block by ensuring it has a `_key` property. If the block is a
|
|
35
|
-
* portable text block, additional normalization is applied:
|
|
36
|
-
*
|
|
37
|
-
* - Ensures it has `children` and `markDefs` properties
|
|
38
|
-
* - Ensures it has at least one child (adds an empty span if empty)
|
|
39
|
-
* - Joins sibling spans that has the same marks
|
|
40
|
-
* - Removes decorators that are not allowed according to the schema
|
|
41
|
-
* - Removes marks that have no annotation definition
|
|
42
|
-
*
|
|
43
|
-
* @param node - The block to normalize
|
|
44
|
-
* @param options - Options for normalization process. See {@link BlockNormalizationOptions}
|
|
45
|
-
* @returns Normalized block
|
|
46
|
-
* @public
|
|
47
|
-
*/
|
|
48
|
-
export function normalizeBlock(
|
|
49
|
-
node: TypedObject,
|
|
50
|
-
options: BlockNormalizationOptions = {},
|
|
51
|
-
): Omit<
|
|
52
|
-
TypedObject | PortableTextTextBlock<TypedObject | PortableTextSpan>,
|
|
53
|
-
'_key'
|
|
54
|
-
> & {
|
|
55
|
-
_key: string
|
|
56
|
-
} {
|
|
57
|
-
const schema: Schema = {
|
|
58
|
-
block: {
|
|
59
|
-
name: options.blockTypeName || 'block',
|
|
60
|
-
},
|
|
61
|
-
span: {
|
|
62
|
-
name: 'span',
|
|
63
|
-
},
|
|
64
|
-
styles: [],
|
|
65
|
-
lists: [],
|
|
66
|
-
decorators: [],
|
|
67
|
-
annotations: [],
|
|
68
|
-
blockObjects: [],
|
|
69
|
-
inlineObjects: [],
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (node._type !== (options.blockTypeName || 'block')) {
|
|
73
|
-
return '_key' in node
|
|
74
|
-
? (node as TypedObject & {_key: string})
|
|
75
|
-
: {
|
|
76
|
-
...node,
|
|
77
|
-
_key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const block: Omit<
|
|
82
|
-
PortableTextTextBlock<TypedObject | PortableTextSpan>,
|
|
83
|
-
'style'
|
|
84
|
-
> = {
|
|
85
|
-
_key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),
|
|
86
|
-
children: [],
|
|
87
|
-
markDefs: [],
|
|
88
|
-
...node,
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const lastChild = block.children[block.children.length - 1]
|
|
92
|
-
|
|
93
|
-
if (!lastChild) {
|
|
94
|
-
// A block must at least have an empty span type child
|
|
95
|
-
block.children = [
|
|
96
|
-
{
|
|
97
|
-
_type: 'span',
|
|
98
|
-
_key: options.keyGenerator ? options.keyGenerator() : keyGenerator(),
|
|
99
|
-
text: '',
|
|
100
|
-
marks: [],
|
|
101
|
-
},
|
|
102
|
-
]
|
|
103
|
-
return block
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const usedMarkDefs: string[] = []
|
|
107
|
-
const allowedDecorators =
|
|
108
|
-
options.allowedDecorators && Array.isArray(options.allowedDecorators)
|
|
109
|
-
? options.allowedDecorators
|
|
110
|
-
: false
|
|
111
|
-
|
|
112
|
-
block.children = block.children
|
|
113
|
-
.reduce(
|
|
114
|
-
(acc, child) => {
|
|
115
|
-
const previousChild = acc[acc.length - 1]
|
|
116
|
-
if (
|
|
117
|
-
previousChild &&
|
|
118
|
-
isSpan({schema}, child) &&
|
|
119
|
-
isSpan({schema}, previousChild) &&
|
|
120
|
-
isEqual(previousChild.marks, child.marks)
|
|
121
|
-
) {
|
|
122
|
-
if (
|
|
123
|
-
lastChild &&
|
|
124
|
-
lastChild === child &&
|
|
125
|
-
child.text === '' &&
|
|
126
|
-
block.children.length > 1
|
|
127
|
-
) {
|
|
128
|
-
return acc
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
previousChild.text += child.text
|
|
132
|
-
return acc
|
|
133
|
-
}
|
|
134
|
-
acc.push(child)
|
|
135
|
-
return acc
|
|
136
|
-
},
|
|
137
|
-
[] as (TypedObject | PortableTextSpan)[],
|
|
138
|
-
)
|
|
139
|
-
.map((child) => {
|
|
140
|
-
if (!child) {
|
|
141
|
-
throw new Error('missing child')
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
child._key = options.keyGenerator
|
|
145
|
-
? options.keyGenerator()
|
|
146
|
-
: keyGenerator()
|
|
147
|
-
|
|
148
|
-
if (isSpan({schema}, child)) {
|
|
149
|
-
if (!child.marks) {
|
|
150
|
-
child.marks = []
|
|
151
|
-
} else if (allowedDecorators) {
|
|
152
|
-
child.marks = child.marks.filter((mark) => {
|
|
153
|
-
const isAllowed = allowedDecorators.includes(mark)
|
|
154
|
-
const isUsed = block.markDefs?.some((def) => def._key === mark)
|
|
155
|
-
return isAllowed || isUsed
|
|
156
|
-
})
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
usedMarkDefs.push(...child.marks)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return child
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
// Remove leftover (unused) markDefs
|
|
166
|
-
block.markDefs = (block.markDefs || []).filter((markDef) =>
|
|
167
|
-
usedMarkDefs.includes(markDef._key),
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
return block
|
|
171
|
-
}
|
package/src/util/randomKey.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export function keyGenerator() {
|
|
2
|
-
return randomKey(12)
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
// WHATWG crypto RNG - https://w3c.github.io/webcrypto/Overview.html
|
|
6
|
-
function whatwgRNG(length = 16) {
|
|
7
|
-
const rnds8 = new Uint8Array(length)
|
|
8
|
-
crypto.getRandomValues(rnds8)
|
|
9
|
-
return rnds8
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const byteToHex: string[] = []
|
|
13
|
-
for (let i = 0; i < 256; ++i) {
|
|
14
|
-
byteToHex[i] = (i + 0x100).toString(16).slice(1)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Generate a random key of the given length
|
|
19
|
-
*
|
|
20
|
-
* @param length - Length of string to generate
|
|
21
|
-
* @returns A string of the given length
|
|
22
|
-
* @public
|
|
23
|
-
*/
|
|
24
|
-
export function randomKey(length: number): string {
|
|
25
|
-
return whatwgRNG(length)
|
|
26
|
-
.reduce((str, n) => str + byteToHex[n], '')
|
|
27
|
-
.slice(0, length)
|
|
28
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
const objectToString = Object.prototype.toString
|
|
2
|
-
|
|
3
|
-
// Copied from https://github.com/ForbesLindesay/type-of
|
|
4
|
-
// but inlined to have fine grained control
|
|
5
|
-
export function resolveJsType(val: unknown) {
|
|
6
|
-
switch (objectToString.call(val)) {
|
|
7
|
-
case '[object Function]':
|
|
8
|
-
return 'function'
|
|
9
|
-
case '[object Date]':
|
|
10
|
-
return 'date'
|
|
11
|
-
case '[object RegExp]':
|
|
12
|
-
return 'regexp'
|
|
13
|
-
case '[object Arguments]':
|
|
14
|
-
return 'arguments'
|
|
15
|
-
case '[object Array]':
|
|
16
|
-
return 'array'
|
|
17
|
-
case '[object String]':
|
|
18
|
-
return 'string'
|
|
19
|
-
default:
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (val === null) {
|
|
23
|
-
return 'null'
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (val === undefined) {
|
|
27
|
-
return 'undefined'
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
val &&
|
|
32
|
-
typeof val === 'object' &&
|
|
33
|
-
'nodeType' in val &&
|
|
34
|
-
(val as {nodeType: unknown}).nodeType === 1
|
|
35
|
-
) {
|
|
36
|
-
return 'element'
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (val === Object(val)) {
|
|
40
|
-
return 'object'
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return typeof val
|
|
44
|
-
}
|