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+
112import { webNamespaces } from 'web-namespaces'
213import { h , s } from 'hastscript'
314
@@ -8,32 +19,49 @@ const DOCUMENT_NODE = 9
819const DOCUMENT_TYPE_NODE = 10
920const DOCUMENT_FRAGMENT_NODE = 11
1021
11- function transform ( value ) {
12- const node = value || { }
13-
22+ /**
23+ * @param {Node } node
24+ * @returns {HastNode|null }
25+ */
26+ function transform ( node ) {
1427 switch ( node . nodeType ) {
1528 case ELEMENT_NODE :
29+ // @ts -ignore TypeScript is wrong.
1630 return element ( node )
1731 case DOCUMENT_NODE :
1832 case DOCUMENT_FRAGMENT_NODE :
33+ // @ts -ignore TypeScript is wrong.
1934 return root ( node )
2035 case TEXT_NODE :
36+ // @ts -ignore TypeScript is wrong.
2137 return text ( node )
2238 case COMMENT_NODE :
39+ // @ts -ignore TypeScript is wrong.
2340 return comment ( node )
2441 case DOCUMENT_TYPE_NODE :
42+ // @ts -ignore TypeScript is wrong.
2543 return doctype ( node )
2644 default :
2745 return null
2846 }
2947}
3048
31- // Transform a document.
49+ /**
50+ * Transform a document.
51+ *
52+ * @param {Document|DocumentFragment } node
53+ * @returns {HastRoot }
54+ */
3255function root ( node ) {
3356 return { type : 'root' , children : all ( node ) }
3457}
3558
36- // Transform a doctype.
59+ /**
60+ * Transform a doctype.
61+ *
62+ * @param {DocumentType } node
63+ * @returns {HastDoctype }
64+ */
3765function doctype ( node ) {
3866 return {
3967 type : 'doctype' ,
@@ -43,57 +71,82 @@ function doctype(node) {
4371 }
4472}
4573
46- // Transform text.
74+ /**
75+ * Transform a text.
76+ *
77+ * @param {Text } node
78+ * @returns {HastText }
79+ */
4780function text ( node ) {
4881 return { type : 'text' , value : node . nodeValue }
4982}
5083
51- // Transform a comment.
84+ /**
85+ * Transform a comment.
86+ *
87+ * @param {Comment } node
88+ * @returns {HastComment }
89+ */
5290function comment ( node ) {
5391 return { type : 'comment' , value : node . nodeValue }
5492}
5593
56- // Transform an element.
94+ /**
95+ * Transform an element.
96+ *
97+ * @param {Element } node
98+ * @returns {HastElement }
99+ */
57100function element ( node ) {
58101 const space = node . namespaceURI
59102 const fn = space === webNamespaces . svg ? s : h
60103 const tagName =
61104 space === webNamespaces . html ? node . tagName . toLowerCase ( ) : node . tagName
105+ /** @type {DocumentFragment|Element } */
62106 const content =
107+ // @ts -ignore Types are wrong.
63108 space === webNamespaces . html && tagName === 'template' ? node . content : node
64109 const attributes = node . getAttributeNames ( )
65- const { length } = attributes
110+ /** @type { Object.<string, string> } */
66111 const props = { }
67- let index = 0
112+ let index = - 1
68113
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 ] )
73116 }
74117
75118 return fn ( tagName , props , all ( content ) )
76119}
77120
121+ /**
122+ * Transform an element.
123+ *
124+ * @param {Document|DocumentFragment|Element } node
125+ * @returns {Array.<HastChild> }
126+ */
78127function all ( node ) {
79128 const nodes = node . childNodes
80- const { length } = nodes
129+ /** @type { Array.<HastChild> } */
81130 const children = [ ]
82- let index = 0
131+ let index = - 1
83132
84- while ( index < length ) {
133+ while ( ++ index < nodes . length ) {
85134 const child = transform ( nodes [ index ] )
86135
87136 if ( child !== null ) {
137+ // @ts -ignore Assume no document inside document.
88138 children . push ( child )
89139 }
90-
91- index += 1
92140 }
93141
94142 return children
95143}
96144
145+ /**
146+ * @param {Node } node
147+ * @returns {HastNode }
148+ */
97149export 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 : [ ] }
99152}
0 commit comments