Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
titaniumnetwork-dev
GitHub Repository: titaniumnetwork-dev/Ultraviolet
Path: blob/main/src/rewrite/js.js
304 views
1
import { parseScript } from "meriyah";
2
// import { parse } from 'acorn-hammerhead';
3
import { generate } from "astring";
4
import EventEmitter from "events";
5
6
class JS extends EventEmitter {
7
constructor() {
8
super();
9
/*
10
this.parseOptions = {
11
allowReturnOutsideFunction: true,
12
allowImportExportEverywhere: true,
13
ecmaVersion: 2021,
14
};
15
*/
16
this.parseOptions = {
17
ranges: true,
18
module: true,
19
globalReturn: true,
20
};
21
this.generationOptions = {
22
format: {
23
quotes: "double",
24
escapeless: true,
25
compact: true,
26
},
27
};
28
this.parse = parseScript /*parse*/;
29
this.generate = generate;
30
}
31
rewrite(str, data = {}) {
32
return this.recast(str, data, "rewrite");
33
}
34
source(str, data = {}) {
35
return this.recast(str, data, "source");
36
}
37
recast(str, data = {}, type = "") {
38
try {
39
const output = [];
40
const ast = this.parse(str, this.parseOptions);
41
const meta = {
42
data,
43
changes: [],
44
input: str,
45
ast,
46
get slice() {
47
return slice;
48
},
49
};
50
let slice = 0;
51
52
this.iterate(ast, (node, parent = null) => {
53
if (parent && parent.inTransformer) node.isTransformer = true;
54
node.parent = parent;
55
56
this.emit(node.type, node, meta, type);
57
});
58
59
meta.changes.sort((a, b) => a.start - b.start || a.end - b.end);
60
61
for (const change of meta.changes) {
62
if ("start" in change && typeof change.start === "number")
63
output.push(str.slice(slice, change.start));
64
if (change.node)
65
output.push(
66
typeof change.node === "string"
67
? change.node
68
: generate(change.node, this.generationOptions)
69
);
70
if ("end" in change && typeof change.end === "number")
71
slice = change.end;
72
}
73
output.push(str.slice(slice));
74
return output.join("");
75
} catch (e) {
76
return str;
77
}
78
}
79
iterate(ast, handler) {
80
if (typeof ast != "object" || !handler) return;
81
walk(ast, null, handler);
82
function walk(node, parent, handler) {
83
if (typeof node != "object" || !handler) return;
84
handler(node, parent, handler);
85
for (const child in node) {
86
if (child === "parent") continue;
87
if (Array.isArray(node[child])) {
88
node[child].forEach((entry) => {
89
if (entry) walk(entry, node, handler);
90
});
91
} else {
92
if (node[child]) walk(node[child], node, handler);
93
}
94
}
95
if (typeof node.iterateEnd === "function") node.iterateEnd();
96
}
97
}
98
}
99
100
export default JS;
101
102