1
1
/**
2
- * @typedef {import('parse5').DefaultTreeAdapterMap } DefaultTreeAdapterMap
3
- * @typedef {DefaultTreeAdapterMap['document'] } P5Document
4
- * @typedef {DefaultTreeAdapterMap['documentFragment'] } P5Fragment
5
- * @typedef {DefaultTreeAdapterMap['element'] } P5Element
6
- * @typedef {DefaultTreeAdapterMap['node'] } P5Node
7
- * @typedef {DefaultTreeAdapterMap['documentType'] } P5Doctype
8
- * @typedef {DefaultTreeAdapterMap['commentNode'] } P5Comment
9
- * @typedef {DefaultTreeAdapterMap['textNode'] } P5Text
10
- * @typedef {DefaultTreeAdapterMap['parentNode'] } P5Parent
11
- * @typedef {import('parse5').Token.Attribute } P5Attribute
12
- * @typedef {Exclude<P5Node, P5Document | P5Fragment> } P5Child
13
- * @typedef {import('property-information').Schema } Schema
14
- * @typedef {import('hast').Root } Root
2
+ * @typedef {import('hast').Comment } Comment
15
3
* @typedef {import('hast').Doctype } Doctype
16
4
* @typedef {import('hast').Element } Element
5
+ * @typedef {import('hast').Nodes } Nodes
6
+ * @typedef {import('hast').Root } Root
7
+ * @typedef {import('hast').RootContent } RootContent
17
8
* @typedef {import('hast').Text } Text
18
- * @typedef {import('hast').Comment } Comment
19
- * @typedef {import('hast').Content } Content
9
+ *
10
+ * @typedef {import('parse5').DefaultTreeAdapterMap['document'] } Parse5Document
11
+ * @typedef {import('parse5').DefaultTreeAdapterMap['documentFragment'] } Parse5Fragment
12
+ * @typedef {import('parse5').DefaultTreeAdapterMap['element'] } Parse5Element
13
+ * @typedef {import('parse5').DefaultTreeAdapterMap['node'] } Parse5Nodes
14
+ * @typedef {import('parse5').DefaultTreeAdapterMap['documentType'] } Parse5Doctype
15
+ * @typedef {import('parse5').DefaultTreeAdapterMap['commentNode'] } Parse5Comment
16
+ * @typedef {import('parse5').DefaultTreeAdapterMap['textNode'] } Parse5Text
17
+ * @typedef {import('parse5').DefaultTreeAdapterMap['parentNode'] } Parse5Parent
18
+ * @typedef {import('parse5').Token.Attribute } Parse5Attribute
19
+ *
20
+ * @typedef {import('property-information').Schema } Schema
20
21
*/
21
22
22
23
/**
23
- * @typedef {Content | Root } Node
24
- * @typedef {'html' | 'svg' } Space
25
- *
26
24
* @typedef Options
27
25
* Configuration.
28
26
* @property {Space | null | undefined } [space='html']
29
- * Which space the document is in.
27
+ * Which space the document is in (default: `'html'`) .
30
28
*
31
29
* When an `<svg>` element is found in the HTML space, this package already
32
30
* automatically switches to and from the SVG space when entering and exiting
33
31
* it.
32
+ *
33
+ * @typedef {Exclude<Parse5Nodes, Parse5Document | Parse5Fragment> } Parse5Content
34
+ *
35
+ * @typedef {'html' | 'svg' } Space
34
36
*/
35
37
36
38
import { stringify as commas } from 'comma-separated-tokens'
37
- import { html , svg , find } from 'property-information'
39
+ import { ok as assert } from 'devlop'
40
+ import { find , html , svg } from 'property-information'
38
41
import { stringify as spaces } from 'space-separated-tokens'
39
42
import { webNamespaces } from 'web-namespaces'
40
43
import { zwitch } from 'zwitch'
41
44
42
45
const own = { } . hasOwnProperty
43
46
44
- /** @type {(from: Node, schema: Schema) => P5Node } */
45
47
const one = zwitch ( 'type' , { handlers : { root, element, text, comment, doctype} } )
46
48
47
49
/**
48
50
* Transform a hast tree to Parse5’s AST.
49
51
*
50
- * @param {Node } tree
52
+ * @param {Nodes } tree
51
53
* Tree to transform.
52
54
* @param {Options | Space | null | undefined } [options]
53
- * Configuration.
54
- * @returns {P5Node }
55
+ * Configuration (optional) .
56
+ * @returns {Parse5Nodes }
55
57
* `parse5` node.
56
58
*/
57
59
export function toParse5 ( tree , options ) {
@@ -61,12 +63,14 @@ export function toParse5(tree, options) {
61
63
62
64
/**
63
65
* @param {Root } node
66
+ * Node (hast) to transform.
64
67
* @param {Schema } schema
65
68
* Current schema.
66
- * @returns {P5Document }
69
+ * @returns {Parse5Document }
70
+ * Parse5 node.
67
71
*/
68
72
function root ( node , schema ) {
69
- /** @type {P5Document } */
73
+ /** @type {Parse5Document } */
70
74
const result = {
71
75
nodeName : '#document' ,
72
76
// @ts -expect-error: `parse5` uses enums, which are actually strings.
@@ -80,12 +84,14 @@ function root(node, schema) {
80
84
81
85
/**
82
86
* @param {Root } node
87
+ * Node (hast) to transform.
83
88
* @param {Schema } schema
84
89
* Current schema.
85
- * @returns {P5Fragment }
90
+ * @returns {Parse5Fragment }
91
+ * Parse5 node.
86
92
*/
87
93
function fragment ( node , schema ) {
88
- /** @type {P5Fragment } */
94
+ /** @type {Parse5Fragment } */
89
95
const result = { nodeName : '#document-fragment' , childNodes : [ ] }
90
96
result . childNodes = all ( node . children , result , schema )
91
97
patch ( node , result )
@@ -94,17 +100,18 @@ function fragment(node, schema) {
94
100
95
101
/**
96
102
* @param {Doctype } node
97
- * @returns {P5Doctype }
103
+ * Node (hast) to transform.
104
+ * @returns {Parse5Doctype }
105
+ * Parse5 node.
98
106
*/
99
107
function doctype ( node ) {
100
- /** @type {P5Doctype } */
108
+ /** @type {Parse5Doctype } */
101
109
const result = {
102
110
nodeName : '#documentType' ,
103
111
name : 'html' ,
104
112
publicId : '' ,
105
113
systemId : '' ,
106
- // @ts -expect-error: change to `null` in a major?
107
- parentNode : undefined
114
+ parentNode : null
108
115
}
109
116
110
117
patch ( node , result )
@@ -113,31 +120,33 @@ function doctype(node) {
113
120
114
121
/**
115
122
* @param {Text } node
116
- * @returns {P5Text }
123
+ * Node (hast) to transform.
124
+ * @returns {Parse5Text }
125
+ * Parse5 node.
117
126
*/
118
127
function text ( node ) {
119
- /** @type {P5Text } */
128
+ /** @type {Parse5Text } */
120
129
const result = {
121
130
nodeName : '#text' ,
122
131
value : node . value ,
123
- // @ts -expect-error: no `parentNode`
124
- parentNode : undefined
132
+ parentNode : null
125
133
}
126
134
patch ( node , result )
127
135
return result
128
136
}
129
137
130
138
/**
131
139
* @param {Comment } node
132
- * @returns {P5Comment }
140
+ * Node (hast) to transform.
141
+ * @returns {Parse5Comment }
142
+ * Parse5 node.
133
143
*/
134
144
function comment ( node ) {
135
- /** @type {P5Comment } */
145
+ /** @type {Parse5Comment } */
136
146
const result = {
137
147
nodeName : '#comment' ,
138
148
data : node . value ,
139
- // @ts -expect-error: no `parentNode`
140
- parentNode : undefined
149
+ parentNode : null
141
150
}
142
151
143
152
patch ( node , result )
@@ -147,10 +156,11 @@ function comment(node) {
147
156
148
157
/**
149
158
* @param {Element } node
159
+ * Node (hast) to transform.
150
160
* @param {Schema } schema
151
161
* Current schema.
152
- * @returns {P5Element }
153
- * `parse5` node.
162
+ * @returns {Parse5Element }
163
+ * Parse5 node.
154
164
*/
155
165
function element ( node , schema ) {
156
166
const parentSchema = schema
@@ -164,7 +174,7 @@ function element(node, schema) {
164
174
currentSchema = svg
165
175
}
166
176
167
- /** @type {Array<P5Attribute > } */
177
+ /** @type {Array<Parse5Attribute > } */
168
178
const attrs = [ ]
169
179
/** @type {string } */
170
180
let prop
@@ -185,16 +195,19 @@ function element(node, schema) {
185
195
}
186
196
}
187
197
188
- /** @type {P5Element } */
198
+ const space = currentSchema . space
199
+ // `html` and `svg` both have a space.
200
+ assert ( space )
201
+
202
+ /** @type {Parse5Element } */
189
203
const result = {
190
204
nodeName : node . tagName ,
191
205
tagName : node . tagName ,
192
206
attrs,
193
- // @ts -expect-error: html and svg both have a space .
194
- namespaceURI : webNamespaces [ currentSchema . space ] ,
207
+ // @ts -expect-error: `parse5` types are wrong .
208
+ namespaceURI : webNamespaces [ space ] ,
195
209
childNodes : [ ] ,
196
- // @ts -expect-error: no `parentNode`
197
- parentNode : undefined
210
+ parentNode : null
198
211
}
199
212
result . childNodes = all ( node . children , result , currentSchema )
200
213
patch ( node , result )
@@ -214,19 +227,19 @@ function element(node, schema) {
214
227
* Current schema.
215
228
* @param {string } prop
216
229
* Key.
217
- * @param {Array<string | number > | string | number | boolean | null | undefined } value
230
+ * @param {Array<number | string > | boolean | number | string | null | undefined } value
218
231
* hast property value.
219
- * @returns {P5Attribute | void }
232
+ * @returns {Parse5Attribute | undefined }
220
233
* Field for runtime, optional.
221
234
*/
222
235
function createProperty ( schema , prop , value ) {
223
236
const info = find ( schema , prop )
224
237
225
238
// Ignore nullish and `NaN` values.
226
239
if (
227
- value === undefined ||
228
- value === null ||
229
240
value === false ||
241
+ value === null ||
242
+ value === undefined ||
230
243
( typeof value === 'number' && Number . isNaN ( value ) ) ||
231
244
( ! value && info . boolean )
232
245
) {
@@ -239,7 +252,7 @@ function createProperty(schema, prop, value) {
239
252
value = info . commaSeparated ? commas ( value ) : spaces ( value )
240
253
}
241
254
242
- /** @type {P5Attribute } */
255
+ /** @type {Parse5Attribute } */
243
256
const attribute = {
244
257
name : info . attribute ,
245
258
value : value === true ? '' : String ( value )
@@ -264,24 +277,23 @@ function createProperty(schema, prop, value) {
264
277
/**
265
278
* Transform all hast nodes.
266
279
*
267
- * @param {Array<Content > } children
280
+ * @param {Array<RootContent > } children
268
281
* List of children.
269
- * @param {P5Parent } parentNode
282
+ * @param {Parse5Parent } parentNode
270
283
* `parse5` parent node.
271
284
* @param {Schema } schema
272
285
* Current schema.
273
- * @returns {Array<P5Child > }
286
+ * @returns {Array<Parse5Content > }
274
287
* Transformed children.
275
288
*/
276
289
function all ( children , parentNode , schema ) {
277
290
let index = - 1
278
- /** @type {Array<P5Child > } */
291
+ /** @type {Array<Parse5Content > } */
279
292
const results = [ ]
280
293
281
294
if ( children ) {
282
295
while ( ++ index < children . length ) {
283
- /** @type {P5Child } */
284
- // @ts -expect-error assume no document.
296
+ /** @type {Parse5Content } */
285
297
const child = one ( children [ index ] , schema )
286
298
287
299
child . parentNode = parentNode
@@ -296,25 +308,26 @@ function all(children, parentNode, schema) {
296
308
/**
297
309
* Add position info from `from` to `to`.
298
310
*
299
- * @param {Node } from
311
+ * @param {Nodes } from
300
312
* hast node.
301
- * @param {P5Node } to
313
+ * @param {Parse5Nodes } to
302
314
* `parse5` node.
303
- * @returns {void }
315
+ * @returns {undefined }
304
316
* Nothing.
305
317
*/
306
318
function patch ( from , to ) {
307
319
const position = from . position
308
320
309
321
if ( position && position . start && position . end ) {
322
+ assert ( typeof position . start . offset === 'number' )
323
+ assert ( typeof position . end . offset === 'number' )
324
+
310
325
to . sourceCodeLocation = {
311
326
startLine : position . start . line ,
312
327
startCol : position . start . column ,
313
- // @ts -expect-error assume this is set.
314
328
startOffset : position . start . offset ,
315
329
endLine : position . end . line ,
316
330
endCol : position . end . column ,
317
- // @ts -expect-error assume this is set.
318
331
endOffset : position . end . offset
319
332
}
320
333
}
0 commit comments