/
index.js
78 lines (63 loc) 路 2 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// @flow
import traverse from "babel-traverse";
import type { SourceMap } from "convert-source-map";
import type { ResolvedConfig, PluginPasses } from "../config";
import PluginPass from "./plugin-pass";
import loadBlockHoistPlugin from "./block-hoist-plugin";
import normalizeOptions from "./normalize-opts";
import normalizeFile from "./normalize-file";
import generateCode from "./file/generate";
import File from "./file/file";
export type FileResult = {
metadata: {},
options: {},
ast: {} | null,
code: string | null,
map: SourceMap | null,
};
export default function runTransform(
config: ResolvedConfig,
code: string,
ast?: {},
): FileResult {
const options = normalizeOptions(config);
const input = normalizeFile(options, code, ast);
const file = new File(options, input);
transformFile(file, config.passes);
const { outputCode, outputMap } = options.code ? generateCode(file) : {};
return {
metadata: file.metadata,
options: options,
ast: options.ast ? file.ast : null,
code: outputCode === undefined ? null : outputCode,
map: outputMap === undefined ? null : outputMap,
};
}
function transformFile(file: File, pluginPasses: PluginPasses): void {
for (const pluginPairs of pluginPasses) {
const passPairs = [];
const passes = [];
const visitors = [];
for (const plugin of pluginPairs.concat([loadBlockHoistPlugin()])) {
const pass = new PluginPass(file, plugin.key, plugin.options);
passPairs.push([plugin, pass]);
passes.push(pass);
visitors.push(plugin.visitor);
}
for (const [plugin, pass] of passPairs) {
const fn = plugin.pre;
if (fn) fn.call(pass, file);
}
// merge all plugin visitors into a single visitor
const visitor = traverse.visitors.merge(
visitors,
passes,
file.opts.wrapPluginVisitorMethod,
);
traverse(file.ast, visitor, file.scope);
for (const [plugin, pass] of passPairs) {
const fn = plugin.post;
if (fn) fn.call(pass, file);
}
}
}