UNPKG

2.07 kBJavaScriptView Raw
1var parse = require('esprima').parse;
2
3module.exports = function (src, opts, fn) {
4 if (typeof opts === 'function') {
5 fn = opts;
6 opts = {};
7 }
8 if (typeof src === 'object') {
9 opts = src;
10 src = opts.source;
11 delete opts.source;
12 }
13 src = src || opts.source;
14 opts.range = true;
15 if (typeof src !== 'string') src = String(src);
16
17 var ast = parse(src, opts);
18
19 var result = {
20 chunks : src.split(''),
21 toString : function () { return result.chunks.join('') },
22 inspect : function () { return result.toString() }
23 };
24 var index = 0;
25
26 (function walk (node, parent) {
27 insertHelpers(node, parent, result.chunks);
28
29 Object.keys(node).forEach(function (key) {
30 if (key === 'parent') return;
31
32 var child = node[key];
33 if (Array.isArray(child)) {
34 child.forEach(function (c) {
35 if (c && typeof c.type === 'string') {
36 walk(c, node);
37 }
38 });
39 }
40 else if (child && typeof child.type === 'string') {
41 insertHelpers(child, node, result.chunks);
42 walk(child, node);
43 }
44 });
45 fn(node);
46 })(ast, undefined);
47
48 return result;
49};
50
51function insertHelpers (node, parent, chunks) {
52 if (!node.range) return;
53
54 node.parent = parent;
55
56 node.source = function () {
57 return chunks.slice(
58 node.range[0], node.range[1] + 1
59 ).join('');
60 };
61
62 if (node.update && typeof node.update === 'object') {
63 var prev = node.update;
64 Object.keys(prev).forEach(function (key) {
65 update[key] = prev[key];
66 });
67 node.update = update;
68 }
69 else {
70 node.update = update;
71 }
72
73 function update (s) {
74 chunks[node.range[0]] = s;
75 for (var i = node.range[0] + 1; i < node.range[1] + 1; i++) {
76 chunks[i] = '';
77 }
78 };
79}