2
2
3
3
var information = require ( 'property-information' ) ;
4
4
var camelcase = require ( 'camelcase' ) ;
5
- var vfileLocation = require ( 'vfile-location' ) ;
6
5
var h = require ( 'hastscript' ) ;
6
+ var xtend = require ( 'xtend' ) ;
7
+ var count = require ( 'ccount' ) ;
7
8
8
9
module . exports = wrapper ;
9
10
@@ -32,7 +33,6 @@ function wrapper(ast, options) {
32
33
33
34
return transform ( ast , {
34
35
file : file ,
35
- toPosition : file ? vfileLocation ( file ) . toPosition : null ,
36
36
verbose : settings . verbose ,
37
37
location : false
38
38
} ) ;
@@ -43,20 +43,20 @@ function transform(ast, config) {
43
43
var fn = own . call ( map , ast . nodeName ) ? map [ ast . nodeName ] : element ;
44
44
var children ;
45
45
var node ;
46
- var position ;
46
+ var pos ;
47
47
48
48
if ( ast . childNodes ) {
49
49
children = nodes ( ast . childNodes , config ) ;
50
50
}
51
51
52
52
node = fn ( ast , children , config ) ;
53
53
54
- if ( ast . __location && config . toPosition ) {
55
- config . location = true ;
56
- position = location ( ast . __location , ast , node , config ) ;
54
+ if ( ast . sourceCodeLocation && config . file ) {
55
+ pos = location ( node , ast . sourceCodeLocation , config . verbose ) ;
57
56
58
- if ( position ) {
59
- node . position = position ;
57
+ if ( pos ) {
58
+ config . location = true ;
59
+ node . position = pos ;
60
60
}
61
61
}
62
62
@@ -79,25 +79,18 @@ function nodes(children, config) {
79
79
/* Transform a document.
80
80
* Stores `ast.quirksMode` in `node.data.quirksMode`. */
81
81
function root ( ast , children , config ) {
82
- var quirks = ast . mode === 'quirks' || ast . mode === 'limited-quirks' ;
83
- var node = { type : 'root' , children : children } ;
84
- var position ;
85
-
86
- node . data = { quirksMode : quirks } ;
82
+ var node = { type : 'root' , children : children , data : { } } ;
83
+ var doc ;
87
84
88
- if ( ast . __location ) {
89
- if ( config . toPosition ) {
90
- config . location = true ;
91
- position = ast . __location ;
92
- }
93
- } else if ( config . file && config . location ) {
94
- position = { startOffset : 0 , endOffset : String ( config . file ) . length } ;
95
- }
85
+ node . data . quirksMode = ast . mode === 'quirks' || ast . mode === 'limited-quirks' ;
96
86
97
- position = position && location ( position , ast , node , config ) ;
87
+ if ( config . file && config . location ) {
88
+ doc = String ( config . file ) ;
98
89
99
- if ( position ) {
100
- node . position = position ;
90
+ node . position = {
91
+ start : { line : 1 , column : 1 , offset : 0 } ,
92
+ end : { line : count ( doc , '\n' ) + 1 , column : doc . length - doc . lastIndexOf ( '\n' ) , offset : doc . length }
93
+ } ;
101
94
}
102
95
103
96
return node ;
@@ -131,7 +124,9 @@ function element(ast, children, config) {
131
124
var index = - 1 ;
132
125
var attr ;
133
126
var node ;
134
- var fragment ;
127
+ var pos ;
128
+ var start ;
129
+ var end ;
135
130
136
131
while ( ++ index < length ) {
137
132
attr = values [ index ] ;
@@ -141,74 +136,65 @@ function element(ast, children, config) {
141
136
node = h ( ast . tagName , props , children ) ;
142
137
143
138
if ( ast . nodeName === 'template' && 'content' in ast ) {
144
- fragment = ast . content ;
145
-
146
- if ( ast . __location ) {
147
- fragment . __location = {
148
- startOffset : ast . __location . startTag . endOffset ,
149
- endOffset : ast . __location . endTag . startOffset
150
- } ;
151
- }
139
+ pos = ast . sourceCodeLocation ;
140
+ start = pos && pos . startTag && position ( pos . startTag ) . end ;
141
+ end = pos && pos . endTag && position ( pos . endTag ) . start ;
152
142
153
143
node . content = transform ( ast . content , config ) ;
144
+
145
+ if ( ( start || end ) && config . file ) {
146
+ node . content . position = { start : start , end : end } ;
147
+ }
154
148
}
155
149
156
150
return node ;
157
151
}
158
152
159
153
/* Create clean positional information. */
160
- function loc ( toPosition , dirty ) {
161
- return {
162
- start : toPosition ( dirty . startOffset ) ,
163
- end : toPosition ( dirty . endOffset )
164
- } ;
165
- }
166
-
167
- /* Create clean positional information. */
168
- function location ( info , ast , node , config ) {
169
- var start = info . startOffset ;
170
- var end = info . endOffset ;
171
- var values = info . attrs || { } ;
172
- var propPositions = { } ;
154
+ function location ( node , location , verbose ) {
155
+ var pos = position ( location ) ;
156
+ var reference ;
157
+ var values ;
158
+ var props ;
173
159
var prop ;
174
160
var name ;
175
- var reference ;
176
-
177
- for ( prop in values ) {
178
- name = ( information ( prop ) || { } ) . propertyName || camelcase ( prop ) ;
179
- propPositions [ name ] = loc ( config . toPosition , values [ prop ] ) ;
180
- }
181
161
182
- /* Upstream: https://github.com/inikulin/parse5/issues/109 */
183
- if ( node . type === 'element' && ! info . endTag ) {
162
+ if ( node . type === 'element' ) {
184
163
reference = node . children [ node . children . length - 1 ] ;
185
164
186
- /* Unclosed with children: */
187
- if ( reference && reference . position ) {
188
- if ( reference . position . end ) {
189
- end = reference . position . end . offset ;
190
- } else {
191
- end = null ;
192
- }
165
+ /* Unclosed with children (upstream: https://github.com/inikulin/parse5/issues/109) */
166
+ if ( ! location . endTag && reference && reference . position && reference . position . end ) {
167
+ pos . end = xtend ( reference . position . end ) ;
193
168
}
194
- }
195
169
196
- if ( config . verbose && node . type === 'element' ) {
197
- node . data = {
198
- position : {
199
- opening : loc ( config . toPosition , info . startTag ) ,
200
- closing : info . endTag ? loc ( config . toPosition , info . endTag ) : null ,
201
- properties : propPositions
170
+ if ( verbose ) {
171
+ values = location . attrs ;
172
+ props = { } ;
173
+
174
+ for ( prop in values ) {
175
+ name = ( information ( prop ) || { } ) . propertyName || camelcase ( prop ) ;
176
+ props [ name ] = position ( values [ prop ] ) ;
202
177
}
203
- } ;
178
+
179
+ node . data = {
180
+ position : {
181
+ opening : position ( location . startTag ) ,
182
+ closing : location . endTag ? position ( location . endTag ) : null ,
183
+ properties : props
184
+ }
185
+ } ;
186
+ }
204
187
}
205
188
206
- start = typeof start === 'number' ? config . toPosition ( start ) : null ;
207
- end = typeof end === 'number' ? config . toPosition ( end ) : null ;
189
+ return pos ;
190
+ }
208
191
209
- if ( ! start && ! end ) {
210
- return undefined ;
211
- }
192
+ function position ( loc ) {
193
+ var start = point ( { line : loc . startLine , column : loc . startCol , offset : loc . startOffset } ) ;
194
+ var end = point ( { line : loc . endLine , column : loc . endCol , offset : loc . endOffset } ) ;
195
+ return start || end ? { start : start , end : end } : null ;
196
+ }
212
197
213
- return { start : start , end : end } ;
198
+ function point ( point ) {
199
+ return point . line && point . column ? point : null ;
214
200
}
0 commit comments