1
1
'use strict'
2
2
3
3
var xtend = require ( 'xtend' )
4
+ var html = require ( 'property-information/html' )
5
+ var svg = require ( 'property-information/svg' )
6
+ var find = require ( 'property-information/find' )
4
7
var toH = require ( 'hast-to-hyperscript' )
5
- var NS = require ( 'web-namespaces' )
8
+ var ns = require ( 'web-namespaces' )
6
9
var zwitch = require ( 'zwitch' )
7
- var mapz = require ( 'mapz' )
8
10
9
11
module . exports = transform
10
12
11
- var own = { } . hasOwnProperty
12
- var one = zwitch ( 'type' )
13
- var all = mapz ( one , { key : 'children' , indices : false } )
13
+ var ignoredSpaces = [ 'svg' , 'html' ]
14
14
15
- var customProps = [
16
- 'sourceCodeLocation' ,
17
- 'childNodes' ,
18
- 'content' ,
19
- 'parentNode' ,
20
- 'namespaceURI'
21
- ]
15
+ var one = zwitch ( 'type' )
22
16
23
17
one . handlers . root = root
24
18
one . handlers . element = element
25
19
one . handlers . text = text
26
20
one . handlers . comment = comment
27
21
one . handlers . doctype = doctype
28
22
29
- /* Map of tag-names starting new namespaces. */
30
- var namespaces = {
31
- math : NS . mathml ,
32
- svg : NS . svg
23
+ // Transform a tree from HAST to Parse5’s AST.
24
+ function transform ( tree , space ) {
25
+ return one ( tree , space === 'svg' ? svg : html )
33
26
}
34
27
35
- /* Map of attributes with namespaces. */
36
- var attributeSpaces = {
37
- 'xlink:actuate' : { prefix : 'xlink' , name : 'actuate' , namespace : NS . xlink } ,
38
- 'xlink:arcrole' : { prefix : 'xlink' , name : 'arcrole' , namespace : NS . xlink } ,
39
- 'xlink:href' : { prefix : 'xlink' , name : 'href' , namespace : NS . xlink } ,
40
- 'xlink:role' : { prefix : 'xlink' , name : 'role' , namespace : NS . xlink } ,
41
- 'xlink:show' : { prefix : 'xlink' , name : 'show' , namespace : NS . xlink } ,
42
- 'xlink:title' : { prefix : 'xlink' , name : 'title' , namespace : NS . xlink } ,
43
- 'xlink:type' : { prefix : 'xlink' , name : 'type' , namespace : NS . xlink } ,
44
- 'xml:base' : { prefix : 'xml' , name : 'base' , namespace : NS . xml } ,
45
- 'xml:lang' : { prefix : 'xml' , name : 'lang' , namespace : NS . xml } ,
46
- 'xml:space' : { prefix : 'xml' , name : 'space' , namespace : NS . xml } ,
47
- xmlns : { prefix : '' , name : 'xmlns' , namespace : NS . xmlns } ,
48
- 'xmlns:xlink' : { prefix : 'xmlns' , name : 'xlink' , namespace : NS . xmlns }
28
+ function root ( node , schema ) {
29
+ var data = node . data || { }
30
+ var mode = data . quirksMode ? 'quirks' : 'no-quirks'
31
+
32
+ return patch ( node , { nodeName : '#document' , mode : mode } , schema )
49
33
}
50
34
51
- /* Transform a tree from HAST to Parse5’s AST. */
52
- function transform ( tree ) {
53
- return patch ( one ( tree ) , null , NS . html )
35
+ function fragment ( node , schema ) {
36
+ return patch ( node , { nodeName : '#document-fragment' } , schema )
54
37
}
55
38
56
- function root ( node ) {
57
- var data = node . data || { }
58
- var qs = own . call ( data , 'quirksMode' ) ? Boolean ( data . quirksMode ) : false
39
+ function doctype ( node , schema ) {
40
+ return patch (
41
+ node ,
42
+ {
43
+ nodeName : '#documentType' ,
44
+ name : node . name ,
45
+ publicId : node . public || '' ,
46
+ systemId : node . system || ''
47
+ } ,
48
+ schema
49
+ )
50
+ }
59
51
60
- return {
61
- nodeName : '#document' ,
62
- mode : qs ? 'quirks' : 'no-quirks' ,
63
- childNodes : all ( node )
64
- }
52
+ function text ( node , schema ) {
53
+ return patch ( node , { nodeName : '#text' , value : node . value } , schema )
54
+ }
55
+
56
+ function comment ( node , schema ) {
57
+ return patch ( node , { nodeName : '#comment' , data : node . value } , schema )
65
58
}
66
59
67
- function element ( node ) {
68
- var shallow = xtend ( node )
60
+ function element ( node , schema ) {
61
+ var space = schema . space
62
+ var shallow = xtend ( node , { children : [ ] } )
69
63
70
- shallow . children = [ ]
64
+ return toH ( h , shallow , { space : space } )
71
65
72
- return toH ( function ( name , attrs ) {
66
+ function h ( name , attrs ) {
73
67
var values = [ ]
74
- var content
68
+ var p5
75
69
var value
76
70
var key
71
+ var info
72
+ var pos
77
73
78
74
for ( key in attrs ) {
75
+ info = find ( schema , key )
79
76
value = { name : key , value : attrs [ key ] }
80
77
81
- if ( own . call ( attributeSpaces , key ) ) {
82
- value = xtend ( value , attributeSpaces [ key ] )
78
+ if ( info . space && ignoredSpaces . indexOf ( info . space ) === - 1 ) {
79
+ pos = key . indexOf ( ':' )
80
+
81
+ if ( pos === - 1 ) {
82
+ value . prefix = ''
83
+ } else {
84
+ value . name = key . slice ( pos + 1 )
85
+ value . prefix = key . slice ( 0 , pos )
86
+ }
87
+ value . namespace = ns [ info . space ]
83
88
}
84
89
85
90
values . push ( value )
86
91
}
87
92
93
+ p5 = patch ( node , { nodeName : name , tagName : name , attrs : values } , schema )
94
+
88
95
if ( name === 'template' ) {
89
- content = transform ( shallow . content )
90
- delete content . mode
91
- content . nodeName = '#document-fragment'
96
+ p5 . content = fragment ( shallow . content , schema )
92
97
}
93
98
94
- return wrap (
95
- node ,
96
- {
97
- nodeName : node . tagName ,
98
- tagName : node . tagName ,
99
- attrs : values ,
100
- childNodes : node . children ? all ( node ) : [ ]
101
- } ,
102
- content
103
- )
104
- } , shallow )
99
+ return p5
100
+ }
105
101
}
106
102
107
- function doctype ( node ) {
108
- return wrap ( node , {
109
- nodeName : '#documentType' ,
110
- name : node . name ,
111
- publicId : node . public || '' ,
112
- systemId : node . system || ''
113
- } )
114
- }
103
+ // Patch specific properties.
104
+ function patch ( node , p5 , parentSchema ) {
105
+ var schema = parentSchema
106
+ var position = node . position
107
+ var children = node . children
108
+ var childNodes = [ ]
109
+ var length = children ? children . length : 0
110
+ var index = - 1
111
+ var child
112
+
113
+ if ( node . type === 'element' ) {
114
+ if ( schema . space === 'html' && node . tagName === 'svg' ) {
115
+ schema = svg
116
+ }
115
117
116
- function text ( node ) {
117
- return wrap ( node , {
118
- nodeName : '#text' ,
119
- value : node . value
120
- } )
121
- }
118
+ p5 . namespaceURI = ns [ schema . space ]
119
+ }
122
120
123
- function comment ( node ) {
124
- return wrap ( node , {
125
- nodeName : '#comment' ,
126
- data : node . value
127
- } )
128
- }
121
+ while ( ++ index < length ) {
122
+ child = one ( children [ index ] , schema )
123
+ child . parentNode = p5
124
+ childNodes [ index ] = child
125
+ }
129
126
130
- /* Patch position. */
131
- function wrap ( node , ast , content ) {
132
- var position = node . position
127
+ if ( node . type === 'element' || node . type === 'root' ) {
128
+ p5 . childNodes = childNodes
129
+ }
133
130
134
131
if ( position && position . start && position . end ) {
135
- ast . sourceCodeLocation = {
132
+ p5 . sourceCodeLocation = {
136
133
startLine : position . start . line ,
137
134
startCol : position . start . column ,
138
135
startOffset : position . start . offset ,
@@ -142,59 +139,5 @@ function wrap(node, ast, content) {
142
139
}
143
140
}
144
141
145
- if ( content ) {
146
- ast . content = content
147
- }
148
-
149
- return ast
150
- }
151
-
152
- /* Patch a tree recursively, by adding namespaces
153
- * and parent references where needed. */
154
- function patch ( node , parent , ns ) {
155
- var location = node . sourceCodeLocation
156
- var children = node . childNodes
157
- var name = node . tagName
158
- var replacement = { }
159
- var length
160
- var index
161
- var key
162
-
163
- for ( key in node ) {
164
- if ( customProps . indexOf ( key ) === - 1 ) {
165
- replacement [ key ] = node [ key ]
166
- }
167
- }
168
-
169
- if ( own . call ( namespaces , name ) ) {
170
- ns = namespaces [ name ]
171
- }
172
-
173
- if ( own . call ( replacement , 'tagName' ) ) {
174
- replacement . namespaceURI = ns
175
- }
176
-
177
- if ( children ) {
178
- replacement . childNodes = children
179
- length = children . length
180
- index = - 1
181
-
182
- while ( ++ index < length ) {
183
- children [ index ] = patch ( children [ index ] , replacement , ns )
184
- }
185
- }
186
-
187
- if ( name === 'template' ) {
188
- replacement . content = patch ( node . content , null , ns )
189
- }
190
-
191
- if ( parent ) {
192
- replacement . parentNode = parent
193
- }
194
-
195
- if ( location ) {
196
- replacement . sourceCodeLocation = location
197
- }
198
-
199
- return replacement
142
+ return p5
200
143
}
0 commit comments