-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
/
index.js
98 lines (88 loc) 路 2.88 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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import rewritePattern from "regexpu-core";
import {
featuresKey,
FEATURES,
enableFeature,
runtimeKey,
hasFeature,
} from "./features";
import { generateRegexpuOptions } from "./util";
import pkg from "../package.json";
import { types as t } from "@babel/core";
import { pullFlag } from "@babel/helper-regex";
import annotateAsPure from "@babel/helper-annotate-as-pure";
// Note: Versions are represented as an integer. e.g. 7.1.5 is represented
// as 70000100005. This method is easier than using a semver-parsing
// package, but it breaks if we release x.y.z where x, y or z are
// greater than 99_999.
const version = pkg.version.split(".").reduce((v, x) => v * 1e5 + +x, 0);
const versionKey = "@babel/plugin-regexp-features/version";
export function createRegExpFeaturePlugin({ name, feature, options = {} }) {
return {
name,
pre() {
const { file } = this;
const features = file.get(featuresKey) ?? 0;
let newFeatures = enableFeature(features, FEATURES[feature]);
const { useUnicodeFlag, runtime = true } = options;
if (useUnicodeFlag === false) {
newFeatures = enableFeature(newFeatures, FEATURES.unicodeFlag);
}
if (newFeatures !== features) {
file.set(featuresKey, newFeatures);
}
if (!runtime) {
file.set(runtimeKey, false);
}
if (!file.has(versionKey) || file.get(versionKey) < version) {
file.set(versionKey, version);
}
},
visitor: {
RegExpLiteral(path) {
const { node } = path;
const { file } = this;
const features = file.get(featuresKey);
const runtime = file.get(runtimeKey) ?? true;
const regexpuOptions = generateRegexpuOptions(node, features);
if (regexpuOptions === null) {
return;
}
const namedCaptureGroups = {};
if (regexpuOptions.namedGroup) {
regexpuOptions.onNamedGroup = (name, index) => {
namedCaptureGroups[name] = index;
};
}
node.pattern = rewritePattern(node.pattern, node.flags, regexpuOptions);
if (
regexpuOptions.namedGroup &&
Object.keys(namedCaptureGroups).length > 0 &&
runtime &&
!isRegExpTest(path)
) {
const call = t.callExpression(this.addHelper("wrapRegExp"), [
node,
t.valueToNode(namedCaptureGroups),
]);
annotateAsPure(call);
path.replaceWith(call);
}
if (hasFeature(features, FEATURES.unicodeFlag)) {
pullFlag(node, "u");
}
if (hasFeature(features, FEATURES.dotAllFlag)) {
pullFlag(node, "s");
}
},
},
};
}
function isRegExpTest(path) {
return (
path.parentPath.isMemberExpression({
object: path.node,
computed: false,
}) && path.parentPath.get("property").isIdentifier({ name: "test" })
);
}