Skip to content

Commit 9f79565

Browse files
committed
Initial commit
0 parents  commit 9f79565

File tree

26 files changed

+3095
-0
lines changed

26 files changed

+3095
-0
lines changed

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.DS_Store
2+
*.log
3+
.nyc_output/
4+
coverage/
5+
node_modules/
6+
hast-util-from-parse5.js
7+
hast-util-from-parse5.min.js

.travis.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
language: node_js
2+
node_js:
3+
- '0.11'
4+
- '0.12'
5+
- '4.0'
6+
- '5.0'
7+
- '6.0'
8+
after_success: bash <(curl -s https://codecov.io/bash)
9+
deploy:
10+
- provider: npm
11+
12+
api_key:
13+
secure: dBnjo9a2nD89IRK7gtRCRo3HSJGmfSyLwXg14RspN1Mh86zg55UJF6F+ZbMbERFapoh7qNip/iU20Y3R6KLgSHHPIUqZ/yR4+0EoJ1przAknnSs8+disRl8LQSxc+cwKFcNYLCaIzsiPJ22REu5PeWsyUPJhnMNQEZX3UI9upFN2H5Hw4Ja9d+u7pUhsySVCg1hiFQwJhCEApLaOkU+ZO+jpuQOzJIEZ1fCvP0AiVTBA6nrd6fVnRz2Nq+wn1GBeL5CqfkTtNhrjSUIXaBWXd6jecQHB8Mee16DYKNncCPOGKZSXZ/b1Teqr03sxrXF4fyCGxO6UTBFGBA0f9kvSk81YNKi2tQpL4XUUgvtUqNIS809CgRi7iQgRtSuPf+7bNST7yC2GJQjlKfN687akCwpfWtz5hwd71HFcv5sXAVpPPzMea+SKPe3MZ3H6fBNr5+w5HNCyUIQvB51keR7pf18qRgB8Gn4cpCNRAd6AVd5m9AwsCxAmvb5EEg8kwjucOG1bBSYrPCr1bDjPAZoRdmgrkKCbedWcHEpxEA1n97fs/F1v0Lo5ZQqeJi83vQ4HPzaHzhay3FhGn44rqpUia0zhNs0J0vo6QMFM18NyzPv+fCoJtCDfFDzreXv4WYzBn5r/453Fs7bTiLq+ExD/lWoRkurtzYpKLmOsNkqZgxA=
14+
on:
15+
tags: true
16+
node: '5.0'
17+
- provider: releases
18+
api_key:
19+
secure: D32bcNwl0l5PKZNzjp0qjHuNJb7Eb3qvzuTcAwust5OsDBsuLPgADjj1spqthLJbV6ZXHfTCCG2K8pvnkF9uTlBlAKBySN2Pr4P8YLuhKAbzrkCdq0/grRhKwxlsESzcPlLNl5bQ85CLbupMIcuujEnxxwJuX+ISDm72ODjlZdEVHigaB7jsW9V0rGa3mQvucr3wLgCSVD6eTiwWXTX144O96it0Wn3vdyfv10gHC9EtVG8cDJCLp2nKdP7dTzDTbxEaGGox8cCs5MqkCKCjiHR97OYLOX4kCclgcfR+iNfbs9AFC3mIxY8OQgsoS/gw5iOp/7IRMk1Gc5Ey5gwbdKvNfwxFVJImCOszZLpMluN9nWWELhw3lclG58o5PYlS8BB04ZJRze4QVloUv1HRrJxU6OKvhz0ilqqwdRpfUjyzVFKXjUWhNXhOBCV+KqG5MCShx2F2eFrAvCLO7tD8d7QJs/oImDvY/hLc2aTfLZGSyUjRIDTNBPzI/6iEuPxEFawZMOo4xKd2vdttF53tj4mKKgnYwGcKDmWC/LpicOlhS0btd5jt7klpeEprSPJXU90dc3EmlcGQW5hEwsoU9ioKYjC5PQfX7uTLIr4VnYECNFUwsj5BPpkDneC6wZ61dfXWD7+RUCdAbDMNl9mIVuuoASELG+oEVkcp+ji8iv4=
20+
file:
21+
- "hast-util-from-parse5.js"
22+
- "hast-util-from-parse5.min.js"
23+
on:
24+
tags: true
25+
node: '6.0'

LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
(The MIT License)
2+
3+
Copyright (c) 2016 Titus Wormer <[email protected]>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining
6+
a copy of this software and associated documentation files (the
7+
'Software'), to deal in the Software without restriction, including
8+
without limitation the rights to use, copy, modify, merge, publish,
9+
distribute, sublicense, and/or sell copies of the Software, and to
10+
permit persons to whom the Software is furnished to do so, subject to
11+
the following conditions:
12+
13+
The above copyright notice and this permission notice shall be
14+
included in all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

example.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Dependencies:
2+
var parse5 = require('parse5');
3+
var inspect = require('unist-util-inspect');
4+
var vfile = require('vfile');
5+
var fromParse5 = require('./index.js');
6+
7+
// Fixture:
8+
var doc = '<!doctype html><title>Hello!</title><h1 id="world">World!<!--after-->';
9+
10+
// Parse:
11+
var ast = parse5.parse(doc, {locationInfo: true});
12+
13+
// Transform:
14+
var hast = fromParse5(ast, vfile(doc));
15+
16+
// Yields:
17+
console.log('txt', inspect.noColor(hast));

history.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<!--remark setext-->
2+
3+
<!--lint disable no-multiple-toplevel-headings-->
4+
5+
0.0.0 / 2016-07-25
6+
==================

index.js

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
/**
2+
* @author Titus Wormer
3+
* @copyright 2016 Titus Wormer
4+
* @license MIT
5+
* @module hast-util-from-parse5
6+
* @fileoverview Transform Parse5’s AST to HAST.
7+
*/
8+
9+
'use strict';
10+
11+
/* Dependencies. */
12+
var information = require('property-information');
13+
var camelcase = require('camelcase');
14+
var vfileLocation = require('vfile-location');
15+
var has = require('has');
16+
var h = require('hastscript');
17+
18+
/* Expose. */
19+
module.exports = wrapper;
20+
21+
/* Handlers. */
22+
var map = {
23+
'#document': root,
24+
'#document-fragment': root,
25+
'#text': text,
26+
'#comment': comment,
27+
'#documentType': doctype
28+
};
29+
30+
/**
31+
* Wrapper to normalise options.
32+
*
33+
* @param {ASTNode} ast - Parse5 node.
34+
* @param {VFile|Object?} [options] - Configuration.
35+
* @return {HASTNode} - HAST node.
36+
*/
37+
function wrapper(ast, options) {
38+
var settings = options || {};
39+
var file;
40+
41+
if (settings.messages) {
42+
file = settings;
43+
settings = {};
44+
} else {
45+
file = settings.file;
46+
}
47+
48+
return transform(ast, {
49+
file: file,
50+
toPosition: file ? vfileLocation(file).toPosition : null,
51+
verbose: settings.verbose
52+
});
53+
}
54+
55+
/**
56+
* Transform a node.
57+
*
58+
* @param {ASTNode} ast - Parse5 node.
59+
* @param {Object} config - Configuration.
60+
* @return {HASTNode} - HAST node.
61+
*/
62+
function transform(ast, config) {
63+
var fn = has(map, ast.nodeName) ? map[ast.nodeName] : element;
64+
var children;
65+
var node;
66+
67+
if (ast.childNodes) {
68+
children = nodes(ast.childNodes, config);
69+
}
70+
71+
node = fn(ast, children, config);
72+
73+
if (ast.__location && config.toPosition) {
74+
node.position = location(ast.__location, ast, node, config);
75+
}
76+
77+
return node;
78+
}
79+
80+
/**
81+
* Transform children.
82+
*
83+
* @param {Array.<ASTNode>} children - Parse5 nodes.
84+
* @param {Object} config - Configuration.
85+
* @return {Array.<HASTNode>} - HAST nodes.
86+
*/
87+
function nodes(children, config) {
88+
var length = children.length;
89+
var index = -1;
90+
var result = [];
91+
92+
while (++index < length) {
93+
result[index] = transform(children[index], config);
94+
}
95+
96+
return result;
97+
}
98+
99+
/**
100+
* Transform a document.
101+
*
102+
* Stores `ast.quirksMode` in `node.data.quirksMode`.
103+
*
104+
* @param {ASTNode.<Document>} ast - Parse5 document.
105+
* @param {Array.<ASTNode>} children - Children of `ast`.
106+
* @param {Object} config - Configuration.
107+
* @return {HASTRoot} - Root node.
108+
*/
109+
function root(ast, children, config) {
110+
var node = {
111+
type: 'root',
112+
children: children,
113+
data: {
114+
quirksMode: ast.quirksMode
115+
}
116+
};
117+
118+
if (config.file) {
119+
node.position = location({
120+
startOffset: 0,
121+
endOffset: String(config.file).length
122+
}, ast, node, config);
123+
}
124+
125+
return node;
126+
}
127+
128+
/**
129+
* Transform a doctype.
130+
*
131+
* @param {ASTNode.<DocumentType>} ast - Parse5 doctype.
132+
* @return {HASTDoctype} - Doctype node.
133+
*/
134+
function doctype(ast) {
135+
return {
136+
type: 'doctype',
137+
name: ast.name || '',
138+
public: ast.publicId || null,
139+
system: ast.systemId || null
140+
};
141+
}
142+
143+
/**
144+
* Transform a text.
145+
*
146+
* @param {ASTNode.<Text>} ast - Parse5 text.
147+
* @return {HASTText} - Text node.
148+
*/
149+
function text(ast) {
150+
return {type: 'text', value: ast.value};
151+
}
152+
153+
/**
154+
* Transform a comment.
155+
*
156+
* @param {ASTNode.<Comment>} ast - Parse5 comment.
157+
* @return {HASTComment} - Comment node.
158+
*/
159+
function comment(ast) {
160+
return {type: 'comment', value: ast.data};
161+
}
162+
163+
/**
164+
* Transform an element.
165+
*
166+
* @param {ASTNode.<Element>} ast - Parse5 element.
167+
* @param {Array.<ASTNode>} children - Children of `ast`.
168+
* @return {HASTElement} - Element node.
169+
*/
170+
function element(ast, children) {
171+
var props = {};
172+
var values = ast.attrs;
173+
var length = values.length;
174+
var index = -1;
175+
var attr;
176+
177+
while (++index < length) {
178+
attr = values[index];
179+
props[(attr.prefix ? attr.prefix + ':' : '') + attr.name] = attr.value;
180+
}
181+
182+
return h(ast.tagName, props, children);
183+
}
184+
185+
/**
186+
* Create clean positional information.
187+
*
188+
* @param {Function} toPosition - Offset to position.
189+
* @param {Object?} [dirty] - Parse5 location information.
190+
* @return {Location} - Start and end positions.
191+
*/
192+
function loc(toPosition, dirty) {
193+
return {
194+
start: toPosition(dirty.startOffset),
195+
end: toPosition(dirty.endOffset)
196+
};
197+
}
198+
199+
/**
200+
* Create clean positional information.
201+
*
202+
* @param {Object} info - Parse5 location information.
203+
* @param {HASTNode} node - HAST node.
204+
* @param {Object} ast - Parse5 node.
205+
* @param {Object} config - Options.
206+
* @return {Location} - Start and end positions.
207+
*/
208+
function location(info, ast, node, config) {
209+
var end = info.endOffset;
210+
var values = info.attrs || {};
211+
var propPositions = {};
212+
var prop;
213+
var name;
214+
var reference;
215+
216+
for (prop in values) {
217+
name = (information(prop) || {}).propertyName || camelcase(prop);
218+
propPositions[name] = loc(config.toPosition, values[prop]);
219+
}
220+
221+
/* Upstream: https://github.com/inikulin/parse5/issues/109 */
222+
if (node.type === 'element' && !info.endTag) {
223+
reference = node.children[node.children.length - 1];
224+
225+
/* Unclosed with children: */
226+
if (reference && reference.position) {
227+
end = reference.position.end.offset;
228+
/* Unclosed without children: */
229+
} else if (info.startTag) {
230+
end = info.startTag.endOffset;
231+
}
232+
}
233+
234+
if (config.verbose && node.type === 'element') {
235+
node.data = {
236+
position: {
237+
opening: loc(config.toPosition, info.startTag || info),
238+
closing: info.endTag ? loc(config.toPosition, info.endTag) : null,
239+
properties: propPositions
240+
}
241+
};
242+
}
243+
244+
return {
245+
start: config.toPosition(info.startOffset),
246+
end: config.toPosition(end)
247+
};
248+
}

0 commit comments

Comments
 (0)