1
1
/**
2
- * @typedef {import('hast').Root } HastRoot
3
- * @typedef {import('hast').RootContent } HastRootContent
2
+ * @typedef {import('hast').Comment } HastComment
4
3
* @typedef {import('hast').Doctype } HastDoctype
5
4
* @typedef {import('hast').Element } HastElement
6
- * @typedef {import('hast').Text } HastText
7
- * @typedef {import('hast').Comment } HastComment
8
5
* @typedef {import('hast').Nodes } HastNodes
6
+ * @typedef {import('hast').Properties } HastProperties
7
+ * @typedef {import('hast').Root } HastRoot
8
+ * @typedef {import('hast').RootContent } HastRootContent
9
+ * @typedef {import('hast').Text } HastText
10
+ *
11
+ * @typedef {import('property-information').Schema } Schema
9
12
*/
10
13
11
14
/**
15
18
* hast node that was handled.
16
19
* @param {Node } domNode
17
20
* Corresponding DOM node.
18
- * @returns {void }
21
+ * @returns {undefined | void }
19
22
* Nothing.
20
23
*
24
+ * Note: `void` included until TS infers `undefined` fine.
25
+ *
21
26
* @typedef Options
22
27
* Configuration.
23
28
* @property {AfterTransform | null | undefined } [afterTransform]
24
- * Callback called when each node is transformed.
29
+ * Callback called when each node is transformed (optional) .
25
30
* @property {Document | null | undefined } [document]
26
31
* Document interface to use (default: `globalThis.document`).
27
32
* @property {boolean | null | undefined } [fragment=false]
28
- * Whether to return a DOM fragment (`true`) or a whole document (`false`).
33
+ * Whether to return a DOM fragment (`true`) or a whole document (`false`)
34
+ * (default: `false`).
29
35
* @property {string | null | undefined } [namespace]
30
- * Namespace to use to create elements.
36
+ * Namespace to use to create elements (optional) .
31
37
*
32
38
* @typedef State
33
39
* Info passed around about the current state.
36
42
* @property {boolean } fragment
37
43
* Whether a fragment (`true`) or whole document (`false`) is built.
38
44
* @property {string | undefined } namespace
39
- * Namespace to use.
45
+ * Explicit namespace to use.
40
46
* @property {string | undefined } impliedNamespace
41
- * To do .
47
+ * Namespace .
42
48
* @property {AfterTransform | undefined } afterTransform
43
49
* Callback called after each hast node is transformed.
44
50
*/
45
51
46
52
/* eslint-env browser */
47
53
54
+ import { html , find , svg } from 'property-information'
48
55
import { webNamespaces } from 'web-namespaces'
49
- import { find , html , svg } from 'property-information'
50
56
51
57
const own = { } . hasOwnProperty
52
58
@@ -57,7 +63,7 @@ const own = {}.hasOwnProperty
57
63
* Tree to transform.
58
64
* @param {Options | null | undefined } [options]
59
65
* Configuration (optional).
60
- * @returns {XMLDocument | DocumentFragment | Text | DocumentType | Comment | Element }
66
+ * @returns {Comment | Document | DocumentFragment | DocumentType | Element | Text }
61
67
* Equivalent DOM node.
62
68
*/
63
69
export function toDom ( tree , options ) {
@@ -76,7 +82,7 @@ export function toDom(tree, options) {
76
82
* Node to transform.
77
83
* @param {State } state
78
84
* Info passed around about the current state.
79
- * @returns {XMLDocument | DocumentFragment | Text | DocumentType | Comment | Element }
85
+ * @returns {Comment | Document | DocumentFragment | DocumentType | Element | Text }
80
86
* Equivalent DOM node.
81
87
*/
82
88
function transform ( node , state ) {
@@ -92,7 +98,7 @@ function transform(node, state) {
92
98
* Node to transform.
93
99
* @param {State } state
94
100
* Info passed around about the current state.
95
- * @returns {XMLDocument | DocumentFragment | Text | DocumentType | Comment | Element }
101
+ * @returns {Comment | Document | DocumentFragment | DocumentType | Element | Text }
96
102
* Equivalent DOM node.
97
103
*/
98
104
function one ( node , state ) {
@@ -127,7 +133,7 @@ function one(node, state) {
127
133
* Node to transform.
128
134
* @param {State } state
129
135
* Info passed around about the current state.
130
- * @returns {XMLDocument | DocumentFragment | HTMLHtmlElement }
136
+ * @returns {Document | DocumentFragment | HTMLHtmlElement }
131
137
* Equivalent DOM node.
132
138
*/
133
139
function root ( node , state ) {
@@ -155,14 +161,14 @@ function root(node, state) {
155
161
156
162
const namespace = state . namespace || foundNamespace
157
163
// The root node will be `Document`, `DocumentFragment`, or `HTMLElement`.
158
- /** @type {XMLDocument | DocumentFragment | HTMLHtmlElement } */
164
+ /** @type {Document | DocumentFragment | HTMLHtmlElement } */
159
165
let result
160
166
161
167
if ( rootIsDocument ) {
162
168
result = state . doc . implementation . createDocument (
169
+ // Note: `null` is different from `undefined`.
163
170
namespace || null ,
164
- '' ,
165
- null
171
+ ''
166
172
)
167
173
} else if ( state . fragment ) {
168
174
result = state . doc . createDocumentFragment ( )
@@ -231,7 +237,6 @@ function comment(node, state) {
231
237
* @returns {Element }
232
238
* DOM element.
233
239
*/
234
- // eslint-disable-next-line complexity
235
240
function element ( node , state ) {
236
241
let impliedNamespace = state . impliedNamespace || state . namespace
237
242
// Important: unknown nodes are passed to `element`.
@@ -249,12 +254,37 @@ function element(node, state) {
249
254
impliedNamespace = webNamespaces . svg
250
255
}
251
256
252
- const schema = impliedNamespace === webNamespaces . svg ? svg : html
253
-
254
257
const result = impliedNamespace
255
258
? state . doc . createElementNS ( impliedNamespace , tagName )
256
259
: state . doc . createElement ( tagName )
257
260
261
+ addProperties (
262
+ result ,
263
+ properties ,
264
+ impliedNamespace === webNamespaces . svg ? svg : html
265
+ )
266
+
267
+ const currentImpliedNamespace = state . impliedNamespace
268
+ state . impliedNamespace = impliedNamespace
269
+ appendAll ( result , children , state )
270
+ state . impliedNamespace = currentImpliedNamespace
271
+
272
+ return result
273
+ }
274
+
275
+ /**
276
+ * Add all properties.
277
+ *
278
+ * @param {Element } result
279
+ * Element.
280
+ * @param {HastProperties } properties
281
+ * Properties from hast element.
282
+ * @param {Schema } schema
283
+ * Schema from `property-information`.
284
+ * @returns {undefined }
285
+ * Nothing.
286
+ */
287
+ function addProperties ( result , properties , schema ) {
258
288
/** @type {string } */
259
289
let key
260
290
@@ -268,7 +298,8 @@ function element(node, state) {
268
298
}
269
299
270
300
if ( info . mustUseProperty ) {
271
- // @ts -expect-error: fine.
301
+ // @ts -expect-error: setting the property is fine, according to
302
+ // `property-information`.
272
303
result [ info . property ] = value
273
304
}
274
305
@@ -279,6 +310,7 @@ function element(node, state) {
279
310
if ( value ) {
280
311
result . setAttribute ( info . attribute , '' )
281
312
} else {
313
+ // To do: remove, we create new elements, we don’t mutate existing ones.
282
314
result . removeAttribute ( info . attribute )
283
315
}
284
316
} else if ( info . booleanish ) {
@@ -290,34 +322,24 @@ function element(node, state) {
290
322
}
291
323
}
292
324
}
293
-
294
- const currentImpliedNamespace = state . impliedNamespace
295
- state . impliedNamespace = impliedNamespace
296
-
297
- appendAll ( result , children , state )
298
-
299
- state . impliedNamespace = currentImpliedNamespace
300
-
301
- return result
302
325
}
303
326
304
327
/**
305
328
* Add all children.
306
329
*
307
- * @param {Node } node
330
+ * @param {Document | DocumentFragment | Element } node
308
331
* DOM node to append to.
309
332
* @param {Array<HastRootContent> } children
310
333
* hast children.
311
334
* @param {State } state
312
335
* Info passed around about the current state.
313
- * @returns {void }
336
+ * @returns {undefined }
314
337
* Nothing.
315
338
*/
316
339
function appendAll ( node , children , state ) {
317
340
let index = - 1
318
341
319
342
while ( ++ index < children . length ) {
320
- // eslint-disable-next-line unicorn/prefer-dom-node-append
321
- node . appendChild ( transform ( children [ index ] , state ) )
343
+ node . append ( transform ( children [ index ] , state ) )
322
344
}
323
345
}
0 commit comments