Skip to content

Commit 0da6272

Browse files
committed
Fix support for nodes missing location info
1 parent a56a784 commit 0da6272

File tree

2 files changed

+160
-9
lines changed

2 files changed

+160
-9
lines changed

index.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ function wrapper(ast, options) {
4848
return transform(ast, {
4949
file: file,
5050
toPosition: file ? vfileLocation(file).toPosition : null,
51-
verbose: settings.verbose
51+
verbose: settings.verbose,
52+
location: false
5253
});
5354
}
5455

@@ -63,6 +64,7 @@ function transform(ast, config) {
6364
var fn = has(map, ast.nodeName) ? map[ast.nodeName] : element;
6465
var children;
6566
var node;
67+
var position;
6668

6769
if (ast.childNodes) {
6870
children = nodes(ast.childNodes, config);
@@ -71,7 +73,12 @@ function transform(ast, config) {
7173
node = fn(ast, children, config);
7274

7375
if (ast.__location && config.toPosition) {
74-
node.position = location(ast.__location, ast, node, config);
76+
config.location = true;
77+
position = location(ast.__location, ast, node, config);
78+
79+
if (position) {
80+
node.position = position;
81+
}
7582
}
7683

7784
return node;
@@ -115,7 +122,7 @@ function root(ast, children, config) {
115122
}
116123
};
117124

118-
if (config.file) {
125+
if (config.file && config.location) {
119126
node.position = location({
120127
startOffset: 0,
121128
endOffset: String(config.file).length
@@ -206,6 +213,7 @@ function loc(toPosition, dirty) {
206213
* @return {Location} - Start and end positions.
207214
*/
208215
function location(info, ast, node, config) {
216+
var start = info.startOffset;
209217
var end = info.endOffset;
210218
var values = info.attrs || {};
211219
var propPositions = {};
@@ -224,7 +232,11 @@ function location(info, ast, node, config) {
224232

225233
/* Unclosed with children: */
226234
if (reference && reference.position) {
227-
end = reference.position.end.offset;
235+
if (reference.position.end) {
236+
end = reference.position.end.offset;
237+
} else {
238+
end = null;
239+
}
228240
/* Unclosed without children: */
229241
} else if (info.startTag) {
230242
end = info.startTag.endOffset;
@@ -241,8 +253,12 @@ function location(info, ast, node, config) {
241253
};
242254
}
243255

244-
return {
245-
start: config.toPosition(info.startOffset),
246-
end: config.toPosition(end)
247-
};
256+
start = typeof start === 'number' ? config.toPosition(start) : null;
257+
end = typeof end === 'number' ? config.toPosition(end) : null;
258+
259+
if (!start && !end) {
260+
return undefined;
261+
}
262+
263+
return {start: start, end: end};
248264
}

test/index.js

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,142 @@ test('hast-util-from-parse5', function (t) {
164164
'should accept a file as options'
165165
);
166166

167-
// console.log(JSON.stringify(fromParse5(parse5.parse(input, {locationInfo: true}), file), 0, 2));
167+
t.deepEqual(
168+
fromParse5(parse5.parse(input), file),
169+
{
170+
type: 'root',
171+
children: [
172+
{
173+
type: 'element',
174+
tagName: 'html',
175+
properties: {},
176+
children: [
177+
{
178+
type: 'element',
179+
tagName: 'head',
180+
properties: {},
181+
children: [
182+
{
183+
type: 'element',
184+
tagName: 'title',
185+
properties: {},
186+
children: [
187+
{
188+
type: 'text',
189+
value: 'Hello!'
190+
}
191+
]
192+
}
193+
]
194+
},
195+
{
196+
type: 'element',
197+
tagName: 'body',
198+
properties: {},
199+
children: [
200+
{
201+
type: 'element',
202+
tagName: 'h1',
203+
properties: {},
204+
children: [
205+
{
206+
type: 'text',
207+
value: 'World!'
208+
}
209+
]
210+
}
211+
]
212+
}
213+
]
214+
}
215+
],
216+
data: {quirksMode: true}
217+
},
218+
'should accept a file as options (without location info)'
219+
);
220+
221+
t.deepEqual(
222+
fromParse5({
223+
nodeName: 'title',
224+
tagName: 'title',
225+
attrs: [],
226+
namespaceURI: 'http://www.w3.org/1999/xhtml',
227+
childNodes: [{
228+
nodeName: '#text',
229+
value: 'Hello!',
230+
__location: {}
231+
}],
232+
__location: {
233+
line: 1,
234+
col: 1,
235+
startOffset: 0,
236+
endOffset: 21,
237+
startTag: {line: 1, col: 1, startOffset: 0, endOffset: null},
238+
endTag: {}
239+
}
240+
}, file),
241+
{
242+
type: 'element',
243+
tagName: 'title',
244+
properties: {},
245+
children: [
246+
{
247+
type: 'text',
248+
value: 'Hello!'
249+
}
250+
],
251+
position: {
252+
start: {column: 1, line: 1, offset: 0},
253+
end: {column: 22, line: 1, offset: 21}
254+
}
255+
},
256+
'should support synthetic locations'
257+
);
258+
259+
t.deepEqual(
260+
fromParse5({
261+
nodeName: 'p',
262+
tagName: 'p',
263+
attrs: [],
264+
namespaceURI: 'http://www.w3.org/1999/xhtml',
265+
childNodes: [{
266+
nodeName: '#text',
267+
value: 'Hello!',
268+
__location: {
269+
line: 1,
270+
col: 1,
271+
startOffset: 0,
272+
endOffset: null
273+
}
274+
}],
275+
__location: {
276+
line: 1,
277+
col: 1,
278+
startOffset: 0,
279+
endOffset: 21,
280+
startTag: {line: 1, col: 1, startOffset: 0, endOffset: null}
281+
}
282+
}, file),
283+
{
284+
type: 'element',
285+
tagName: 'p',
286+
properties: {},
287+
children: [{
288+
type: 'text',
289+
value: 'Hello!',
290+
position: {
291+
start: {column: 1, line: 1, offset: 0},
292+
end: null
293+
}
294+
}],
295+
position: {
296+
start: {column: 1, line: 1, offset: 0},
297+
end: null
298+
}
299+
},
300+
'should support synthetic locations on unclosed elements'
301+
);
302+
168303
t.end();
169304
});
170305

0 commit comments

Comments
 (0)