@portabletext/block-tools 5.0.4 → 5.1.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.
- package/README.md +29 -140
- package/lib/index.d.ts +85 -6
- package/lib/index.js +32 -1212
- package/lib/index.js.map +1 -1
- package/lib/rules/index.d.ts +22 -1
- package/lib/rules/index.js +1 -66
- package/lib/rules/index.js.map +1 -1
- package/package.json +3 -2
- package/lib/_chunks-dts/types.d.ts +0 -85
- package/lib/_chunks-es/helpers.js +0 -297
- package/lib/_chunks-es/helpers.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
# `@portabletext/block-tools`
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Sanity-flavored HTML to Portable Text conversion
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This package wraps [`@portabletext/html`](../html) for use with Sanity schemas. If you're not using Sanity's schema system, use `@portabletext/html` directly - it has the same features with a simpler API.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## When to use which
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
| Package | Use when |
|
|
10
|
+
| --------------------------- | --------------------------------------------------------------- |
|
|
11
|
+
| `@portabletext/html` | Standalone projects, custom schemas, or any non-Sanity context |
|
|
12
|
+
| `@portabletext/block-tools` | Sanity projects where you already have a compiled Sanity schema |
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```ts
|
|
12
17
|
import {htmlToBlocks} from '@portabletext/block-tools'
|
|
13
18
|
import {Schema} from '@sanity/schema'
|
|
14
19
|
|
|
15
|
-
// Start with compiling a schema we can work against
|
|
16
20
|
const defaultSchema = Schema.compile({
|
|
17
21
|
name: 'myBlog',
|
|
18
22
|
types: [
|
|
@@ -36,161 +40,46 @@ const defaultSchema = Schema.compile({
|
|
|
36
40
|
],
|
|
37
41
|
})
|
|
38
42
|
|
|
39
|
-
// The compiled schema type for the content type that holds the block array
|
|
40
43
|
const blockContentType = defaultSchema
|
|
41
44
|
.get('blogPost')
|
|
42
45
|
.fields.find((field) => field.name === 'body').type
|
|
43
46
|
|
|
44
|
-
// Convert HTML to block array
|
|
45
47
|
const blocks = htmlToBlocks(
|
|
46
|
-
'<html><body><h1>Hello world!</h1
|
|
48
|
+
'<html><body><h1>Hello world!</h1></body></html>',
|
|
47
49
|
blockContentType,
|
|
48
50
|
)
|
|
49
|
-
// Outputs
|
|
50
|
-
//
|
|
51
|
-
// {
|
|
52
|
-
// _type: 'block',
|
|
53
|
-
// style: 'h1'
|
|
54
|
-
// children: [
|
|
55
|
-
// {
|
|
56
|
-
// _type: 'span'
|
|
57
|
-
// text: 'Hello world!'
|
|
58
|
-
// }
|
|
59
|
-
// ]
|
|
60
|
-
// }
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Methods
|
|
64
|
-
|
|
65
|
-
### `htmlToBlocks(html, blockContentType, options)` (html deserializer)
|
|
66
|
-
|
|
67
|
-
This will deserialize the input html (string) into blocks.
|
|
68
|
-
|
|
69
|
-
#### Params
|
|
70
|
-
|
|
71
|
-
##### `html`
|
|
72
|
-
|
|
73
|
-
The stringified version of the HTML you are importing
|
|
74
|
-
|
|
75
|
-
##### `blockContentType`
|
|
76
|
-
|
|
77
|
-
A compiled version of the block content schema type.
|
|
78
|
-
|
|
79
|
-
The deserializer will respect the schema when deserializing the HTML elements to blocks.
|
|
80
|
-
|
|
81
|
-
It only supports a subset of HTML tags. Any HTML tag not in the block-tools [whitelist](https://github.com/portabletext/editor/blob/main/packages/block-tools/src/constants.ts) will be deserialized to normal blocks/spans.
|
|
82
|
-
|
|
83
|
-
For instance, if the schema doesn't allow H2 styles, all H2 HTML elements will be output like this:
|
|
84
|
-
|
|
85
|
-
```js
|
|
86
|
-
{
|
|
87
|
-
_type: 'block',
|
|
88
|
-
style: 'normal'
|
|
89
|
-
children: [
|
|
90
|
-
{
|
|
91
|
-
_type: 'span'
|
|
92
|
-
text: 'Hello world!'
|
|
93
|
-
}
|
|
94
|
-
]
|
|
95
|
-
}
|
|
96
51
|
```
|
|
97
52
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
###### `parseHtml`
|
|
101
|
-
|
|
102
|
-
The HTML-deserialization is done by default by the browser's native DOMParser.
|
|
103
|
-
On the server side you can give the function `parseHtml`
|
|
104
|
-
that parses the html into a DOMParser compatible model / API.
|
|
53
|
+
### `htmlToBlocks(html, blockContentType, options?)`
|
|
105
54
|
|
|
106
|
-
|
|
55
|
+
Converts HTML to Portable Text blocks using a Sanity block content schema type.
|
|
107
56
|
|
|
108
|
-
|
|
109
|
-
const {JSDOM} = require('jsdom')
|
|
110
|
-
const {htmlToBlocks} = require('@portabletext/block-tools')
|
|
57
|
+
Internally delegates to `@portabletext/html` after converting the Sanity schema. Supports the same `parseHtml`, `rules`, and `keyGenerator` options. See the [`@portabletext/html` README](../html/README.md) for full documentation on rules, whitespace handling, image matchers, and paste source support.
|
|
111
58
|
|
|
112
|
-
|
|
113
|
-
'<html><body><h1>Hello world!</h1><body></html>',
|
|
114
|
-
blockContentType,
|
|
115
|
-
{
|
|
116
|
-
parseHtml: (html) => new JSDOM(html).window.document,
|
|
117
|
-
},
|
|
118
|
-
)
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
##### `rules`
|
|
59
|
+
**NOTE:** To use in Node.js, you need to provide a `parseHtml` option - generally using `JSDOM`:
|
|
122
60
|
|
|
123
|
-
|
|
61
|
+
```ts
|
|
62
|
+
import {JSDOM} from 'jsdom'
|
|
124
63
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
blockContentType,
|
|
129
|
-
{
|
|
130
|
-
parseHtml: (html) => new JSDOM(html),
|
|
131
|
-
rules: [
|
|
132
|
-
// Special rule for code blocks
|
|
133
|
-
{
|
|
134
|
-
deserialize(el, next, block) {
|
|
135
|
-
if (el.tagName.toLowerCase() != 'pre') {
|
|
136
|
-
return undefined
|
|
137
|
-
}
|
|
138
|
-
const code = el.children[0]
|
|
139
|
-
const childNodes =
|
|
140
|
-
code && code.tagName.toLowerCase() === 'code'
|
|
141
|
-
? code.childNodes
|
|
142
|
-
: el.childNodes
|
|
143
|
-
let text = ''
|
|
144
|
-
childNodes.forEach((node) => {
|
|
145
|
-
text += node.textContent
|
|
146
|
-
})
|
|
147
|
-
// Return this as an own block (via block helper function), instead of appending it to a default block's children
|
|
148
|
-
return block({
|
|
149
|
-
_type: 'code',
|
|
150
|
-
language: 'javascript',
|
|
151
|
-
text: text,
|
|
152
|
-
})
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
],
|
|
156
|
-
},
|
|
157
|
-
)
|
|
64
|
+
const blocks = htmlToBlocks(html, blockContentType, {
|
|
65
|
+
parseHtml: (html) => new JSDOM(html).window.document,
|
|
66
|
+
})
|
|
158
67
|
```
|
|
159
68
|
|
|
160
|
-
### `normalizeBlock(block,
|
|
69
|
+
### `normalizeBlock(block, options?)`
|
|
161
70
|
|
|
162
|
-
Normalize a block object structure to
|
|
71
|
+
Normalize a block object structure to ensure it has `_key`, `_type`, `children`, and `markDefs`.
|
|
163
72
|
|
|
164
|
-
```
|
|
73
|
+
```ts
|
|
165
74
|
import {normalizeBlock} from '@portabletext/block-tools'
|
|
166
75
|
|
|
167
|
-
const
|
|
76
|
+
const normalized = normalizeBlock({
|
|
168
77
|
_type: 'block',
|
|
169
|
-
children: [
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
text: 'Foobar',
|
|
173
|
-
marks: ['strong', 'df324e2qwe'],
|
|
174
|
-
},
|
|
175
|
-
],
|
|
176
|
-
}
|
|
177
|
-
normalizeBlock(partialBlock, {allowedDecorators: ['strong']})
|
|
78
|
+
children: [{_type: 'span', text: 'Hello', marks: ['strong']}],
|
|
79
|
+
})
|
|
80
|
+
// => { _key: '...', _type: 'block', children: [{ _key: '...', _type: 'span', text: 'Hello', marks: ['strong'] }], markDefs: [] }
|
|
178
81
|
```
|
|
179
82
|
|
|
180
|
-
|
|
83
|
+
## License
|
|
181
84
|
|
|
182
|
-
|
|
183
|
-
{
|
|
184
|
-
_key: 'randomKey0',
|
|
185
|
-
_type: 'block',
|
|
186
|
-
children: [
|
|
187
|
-
{
|
|
188
|
-
_key: 'randomKey00',
|
|
189
|
-
_type: 'span',
|
|
190
|
-
marks: ['strong'],
|
|
191
|
-
text: 'Foobar'
|
|
192
|
-
}
|
|
193
|
-
],
|
|
194
|
-
markDefs: []
|
|
195
|
-
}
|
|
196
|
-
```
|
|
85
|
+
MIT
|
package/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,88 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import * as _portabletext_schema1 from "@portabletext/schema";
|
|
3
|
-
import { PortableTextBlock, PortableTextObject, PortableTextSpan, PortableTextSpan as PortableTextSpan$1, PortableTextTextBlock, PortableTextTextBlock as PortableTextTextBlock$1, Schema } from "@portabletext/schema";
|
|
1
|
+
import { PortableTextBlock, PortableTextBlock as PortableTextBlock$1, PortableTextObject, PortableTextObject as PortableTextObject$1, PortableTextSpan, PortableTextSpan as PortableTextSpan$1, PortableTextTextBlock, PortableTextTextBlock as PortableTextTextBlock$1, Schema } from "@portabletext/schema";
|
|
4
2
|
import { ArraySchemaType } from "@sanity/types";
|
|
3
|
+
/**
|
|
4
|
+
* Use the current `Schema` as well as the potential element props to determine
|
|
5
|
+
* what Portable Text Object to use to represent the element.
|
|
6
|
+
*/
|
|
7
|
+
type ObjectSchemaMatcher<TProps extends Record<string, unknown>> = ({
|
|
8
|
+
context,
|
|
9
|
+
props
|
|
10
|
+
}: {
|
|
11
|
+
context: {
|
|
12
|
+
schema: Schema;
|
|
13
|
+
keyGenerator: () => string;
|
|
14
|
+
};
|
|
15
|
+
props: TProps;
|
|
16
|
+
}) => ArbitraryTypedObject | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Use the current `Schema` as well as the potential img element props to
|
|
19
|
+
* determine what Portable Text Object to use to represent the image.
|
|
20
|
+
* @beta
|
|
21
|
+
*/
|
|
22
|
+
type ImageSchemaMatcher = ObjectSchemaMatcher<{
|
|
23
|
+
src?: string;
|
|
24
|
+
alt?: string;
|
|
25
|
+
[key: string]: string | undefined;
|
|
26
|
+
}>;
|
|
27
|
+
/**
|
|
28
|
+
* @beta
|
|
29
|
+
*/
|
|
30
|
+
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
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
interface TypedObject {
|
|
46
|
+
_type: string;
|
|
47
|
+
_key?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* @public
|
|
51
|
+
*/
|
|
52
|
+
interface ArbitraryTypedObject extends TypedObject {
|
|
53
|
+
[key: string]: unknown;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
58
|
+
type HtmlParser = (html: string) => Document;
|
|
59
|
+
/**
|
|
60
|
+
* @public
|
|
61
|
+
*/
|
|
62
|
+
type WhiteSpacePasteMode = 'preserve' | 'remove' | 'normalize';
|
|
63
|
+
/**
|
|
64
|
+
* @public
|
|
65
|
+
*/
|
|
66
|
+
interface HtmlDeserializerOptions {
|
|
67
|
+
keyGenerator?: () => string;
|
|
68
|
+
rules?: DeserializerRule[];
|
|
69
|
+
parseHtml?: HtmlParser;
|
|
70
|
+
unstable_whitespaceOnPasteMode?: WhiteSpacePasteMode;
|
|
71
|
+
/**
|
|
72
|
+
* Custom schema matchers to use when deserializing HTML to Portable Text.
|
|
73
|
+
* @beta
|
|
74
|
+
*/
|
|
75
|
+
matchers?: SchemaMatchers;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* @public
|
|
79
|
+
*/
|
|
80
|
+
interface DeserializerRule {
|
|
81
|
+
deserialize: (el: Node, next: (elements: Node | Node[] | NodeList) => TypedObject | TypedObject[] | undefined, createBlock: (props: ArbitraryTypedObject) => {
|
|
82
|
+
_type: string;
|
|
83
|
+
block: ArbitraryTypedObject;
|
|
84
|
+
}) => TypedObject | TypedObject[] | undefined;
|
|
85
|
+
}
|
|
5
86
|
/**
|
|
6
87
|
* Block normalization options
|
|
7
88
|
*
|
|
@@ -56,7 +137,5 @@ declare function randomKey(length: number): string;
|
|
|
56
137
|
* @returns Array of blocks
|
|
57
138
|
* @public
|
|
58
139
|
*/
|
|
59
|
-
declare function htmlToBlocks(html: string, schemaType: ArraySchemaType | Schema, options?: HtmlDeserializerOptions):
|
|
60
|
-
_key: string;
|
|
61
|
-
})[];
|
|
140
|
+
declare function htmlToBlocks(html: string, schemaType: ArraySchemaType | Schema, options?: HtmlDeserializerOptions): PortableTextBlock$1[];
|
|
62
141
|
export { type ArbitraryTypedObject, type BlockNormalizationOptions, type DeserializerRule, type HtmlDeserializerOptions, type HtmlParser, type ImageSchemaMatcher, type PortableTextBlock, type PortableTextObject, type PortableTextSpan, type PortableTextTextBlock, type SchemaMatchers, type TypedObject, htmlToBlocks, normalizeBlock, randomKey };
|