Skip to content

Commit 04895fa

Browse files
committed
feat: typeofReplacements option for plugin-replace
1 parent 9874740 commit 04895fa

File tree

7 files changed

+74
-3
lines changed

7 files changed

+74
-3
lines changed

packages/replace/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,39 @@ For example, if you pass `typeof window` in `values` to-be-replaced, then you co
7070
- `typeof window.document` **will not** be replaced due to `(?!\.)` boundary
7171
- `typeof windowSmth` **will not** be replaced due to a `\b` boundary
7272

73+
### `typeofReplacements`
74+
75+
Type: `Boolean`<br>
76+
Default: `false`
77+
78+
When replacing dot-separated object properties like `process.env.NODE_ENV`, will also replace typeof checks against the objects
79+
with `"object"`.
80+
81+
For example:
82+
83+
```js
84+
replace({
85+
values: {
86+
'process.env.NODE_ENV': '"production"',
87+
},
88+
});
89+
```
90+
91+
```js
92+
// Input
93+
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') {
94+
console.log('production');
95+
}
96+
// Without `typeofReplacements`
97+
if (typeof process !== 'undefined' && 'production' === 'production') {
98+
console.log('production');
99+
}
100+
// With `typeofReplacements`
101+
if ('object' !== 'undefined' && 'production' === 'production') {
102+
console.log('production');
103+
}
104+
```
105+
73106
### `preventAssignment`
74107

75108
Type: `Boolean`<br>

packages/replace/src/index.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ function getReplacements(options) {
2424
delete values.exclude;
2525
delete values.sourcemap;
2626
delete values.sourceMap;
27+
delete values.typeofReplacements;
2728
return values;
2829
}
2930

@@ -35,10 +36,27 @@ function mapToFunctions(object) {
3536
}, {});
3637
}
3738

39+
const objKeyRegEx = /^([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)(\.([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*))+$/;
40+
function expandTypeofReplacements(replacements) {
41+
Object.keys(replacements).forEach((key) => {
42+
const objMatch = key.match(objKeyRegEx);
43+
if (!objMatch) return;
44+
let dotIndex = objMatch[1].length;
45+
let lastIndex = 0;
46+
do {
47+
replacements[`typeof ${key.slice(lastIndex, dotIndex)}`] = '"object"';
48+
lastIndex = dotIndex + 1;
49+
dotIndex = key.indexOf('.', lastIndex);
50+
} while (dotIndex !== -1);
51+
});
52+
}
53+
3854
export default function replace(options = {}) {
3955
const filter = createFilter(options.include, options.exclude);
40-
const { delimiters, preventAssignment } = options;
41-
const functionValues = mapToFunctions(getReplacements(options));
56+
const { delimiters, preventAssignment, typeofReplacements } = options;
57+
const replacements = getReplacements(options);
58+
if (typeofReplacements) expandTypeofReplacements(replacements);
59+
const functionValues = mapToFunctions(replacements);
4260
const keys = Object.keys(functionValues).sort(longest).map(escape);
4361
const lookahead = preventAssignment ? '(?!\\s*=[^=])' : '';
4462
const pattern = delimiters
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
description: 'Handles process type guards in replacements',
3+
options: {
4+
'process.env.NODE_ENV': '"production"',
5+
preventAssignment: true,
6+
typeofReplacements: true
7+
}
8+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') {
2+
console.log('production');
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
process.env.DEBUG = 'test';

packages/replace/test/snapshots/form.js.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,20 @@ Generated by [AVA](https://avajs.dev).
3939
exclude␊
4040
`);`
4141

42+
## process-check: Handles process type guards in replacements
43+
44+
> Snapshot 1
45+
46+
`if ("object" !== 'undefined' && "production" === 'production') {␊
47+
console.log('production');␊
48+
}`
49+
4250
## replace-nothing: replaces nothing
4351

4452
> Snapshot 1
4553
4654
`console.log('as-it'); // eslint-disable-line␊
47-
console.log(typeof window.document); // eslint-disable-line`
55+
console.log("object".document); // eslint-disable-line`
4856

4957
## replace-strings: replaces strings
5058

66 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)