1
+ /**
2
+ * @typedef {import('hast').Parent } HastParent
3
+ * @typedef {import('hast').Root } HastRoot
4
+ * @typedef {import('hast').DocType } HastDoctype
5
+ * @typedef {import('hast').Element } HastElement
6
+ * @typedef {import('hast').Text } HastText
7
+ * @typedef {import('hast').Comment } HastComment
8
+ * @typedef {HastParent['children'][number] } HastChild
9
+ * @typedef {HastChild|HastRoot } HastNode
10
+ */
11
+
1
12
import { webNamespaces } from 'web-namespaces'
2
13
import { h , s } from 'hastscript'
3
14
@@ -8,32 +19,49 @@ const DOCUMENT_NODE = 9
8
19
const DOCUMENT_TYPE_NODE = 10
9
20
const DOCUMENT_FRAGMENT_NODE = 11
10
21
11
- function transform ( value ) {
12
- const node = value || { }
13
-
22
+ /**
23
+ * @param {Node } node
24
+ * @returns {HastNode|null }
25
+ */
26
+ function transform ( node ) {
14
27
switch ( node . nodeType ) {
15
28
case ELEMENT_NODE :
29
+ // @ts -ignore TypeScript is wrong.
16
30
return element ( node )
17
31
case DOCUMENT_NODE :
18
32
case DOCUMENT_FRAGMENT_NODE :
33
+ // @ts -ignore TypeScript is wrong.
19
34
return root ( node )
20
35
case TEXT_NODE :
36
+ // @ts -ignore TypeScript is wrong.
21
37
return text ( node )
22
38
case COMMENT_NODE :
39
+ // @ts -ignore TypeScript is wrong.
23
40
return comment ( node )
24
41
case DOCUMENT_TYPE_NODE :
42
+ // @ts -ignore TypeScript is wrong.
25
43
return doctype ( node )
26
44
default :
27
45
return null
28
46
}
29
47
}
30
48
31
- // Transform a document.
49
+ /**
50
+ * Transform a document.
51
+ *
52
+ * @param {Document|DocumentFragment } node
53
+ * @returns {HastRoot }
54
+ */
32
55
function root ( node ) {
33
56
return { type : 'root' , children : all ( node ) }
34
57
}
35
58
36
- // Transform a doctype.
59
+ /**
60
+ * Transform a doctype.
61
+ *
62
+ * @param {DocumentType } node
63
+ * @returns {HastDoctype }
64
+ */
37
65
function doctype ( node ) {
38
66
return {
39
67
type : 'doctype' ,
@@ -43,57 +71,82 @@ function doctype(node) {
43
71
}
44
72
}
45
73
46
- // Transform text.
74
+ /**
75
+ * Transform a text.
76
+ *
77
+ * @param {Text } node
78
+ * @returns {HastText }
79
+ */
47
80
function text ( node ) {
48
81
return { type : 'text' , value : node . nodeValue }
49
82
}
50
83
51
- // Transform a comment.
84
+ /**
85
+ * Transform a comment.
86
+ *
87
+ * @param {Comment } node
88
+ * @returns {HastComment }
89
+ */
52
90
function comment ( node ) {
53
91
return { type : 'comment' , value : node . nodeValue }
54
92
}
55
93
56
- // Transform an element.
94
+ /**
95
+ * Transform an element.
96
+ *
97
+ * @param {Element } node
98
+ * @returns {HastElement }
99
+ */
57
100
function element ( node ) {
58
101
const space = node . namespaceURI
59
102
const fn = space === webNamespaces . svg ? s : h
60
103
const tagName =
61
104
space === webNamespaces . html ? node . tagName . toLowerCase ( ) : node . tagName
105
+ /** @type {DocumentFragment|Element } */
62
106
const content =
107
+ // @ts -ignore Types are wrong.
63
108
space === webNamespaces . html && tagName === 'template' ? node . content : node
64
109
const attributes = node . getAttributeNames ( )
65
- const { length } = attributes
110
+ /** @type { Object.<string, string> } */
66
111
const props = { }
67
- let index = 0
112
+ let index = - 1
68
113
69
- while ( index < length ) {
70
- const key = attributes [ index ]
71
- props [ key ] = node . getAttribute ( key )
72
- index += 1
114
+ while ( ++ index < attributes . length ) {
115
+ props [ attributes [ index ] ] = node . getAttribute ( attributes [ index ] )
73
116
}
74
117
75
118
return fn ( tagName , props , all ( content ) )
76
119
}
77
120
121
+ /**
122
+ * Transform an element.
123
+ *
124
+ * @param {Document|DocumentFragment|Element } node
125
+ * @returns {Array.<HastChild> }
126
+ */
78
127
function all ( node ) {
79
128
const nodes = node . childNodes
80
- const { length } = nodes
129
+ /** @type { Array.<HastChild> } */
81
130
const children = [ ]
82
- let index = 0
131
+ let index = - 1
83
132
84
- while ( index < length ) {
133
+ while ( ++ index < nodes . length ) {
85
134
const child = transform ( nodes [ index ] )
86
135
87
136
if ( child !== null ) {
137
+ // @ts -ignore Assume no document inside document.
88
138
children . push ( child )
89
139
}
90
-
91
- index += 1
92
140
}
93
141
94
142
return children
95
143
}
96
144
145
+ /**
146
+ * @param {Node } node
147
+ * @returns {HastNode }
148
+ */
97
149
export function fromDom ( node ) {
98
- return transform ( node ) || { type : 'root' , children : [ ] }
150
+ // @ts -ignore Code can handle empty “node”.
151
+ return transform ( node || { } ) || { type : 'root' , children : [ ] }
99
152
}
0 commit comments