Skip to content

Commit

Permalink
feat: typeofReplacements option for plugin-replace
Browse files Browse the repository at this point in the history
  • Loading branch information
guybedford committed Jan 8, 2022
1 parent 9874740 commit 04895fa
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 3 deletions.
33 changes: 33 additions & 0 deletions packages/replace/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,39 @@ For example, if you pass `typeof window` in `values` to-be-replaced, then you co
- `typeof window.document` **will not** be replaced due to `(?!\.)` boundary
- `typeof windowSmth` **will not** be replaced due to a `\b` boundary

### `typeofReplacements`

Type: `Boolean`<br>
Default: `false`

When replacing dot-separated object properties like `process.env.NODE_ENV`, will also replace typeof checks against the objects
with `"object"`.

For example:

```js
replace({
values: {
'process.env.NODE_ENV': '"production"',
},
});
```

```js
// Input
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') {
console.log('production');
}
// Without `typeofReplacements`
if (typeof process !== 'undefined' && 'production' === 'production') {
console.log('production');
}
// With `typeofReplacements`
if ('object' !== 'undefined' && 'production' === 'production') {
console.log('production');
}
```

### `preventAssignment`

Type: `Boolean`<br>
Expand Down
22 changes: 20 additions & 2 deletions packages/replace/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function getReplacements(options) {
delete values.exclude;
delete values.sourcemap;
delete values.sourceMap;
delete values.typeofReplacements;
return values;
}

Expand All @@ -35,10 +36,27 @@ function mapToFunctions(object) {
}, {});
}

const objKeyRegEx = /^([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)(\.([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*))+$/;
function expandTypeofReplacements(replacements) {
Object.keys(replacements).forEach((key) => {
const objMatch = key.match(objKeyRegEx);
if (!objMatch) return;
let dotIndex = objMatch[1].length;
let lastIndex = 0;
do {
replacements[`typeof ${key.slice(lastIndex, dotIndex)}`] = '"object"';
lastIndex = dotIndex + 1;
dotIndex = key.indexOf('.', lastIndex);
} while (dotIndex !== -1);
});
}

export default function replace(options = {}) {
const filter = createFilter(options.include, options.exclude);
const { delimiters, preventAssignment } = options;
const functionValues = mapToFunctions(getReplacements(options));
const { delimiters, preventAssignment, typeofReplacements } = options;
const replacements = getReplacements(options);
if (typeofReplacements) expandTypeofReplacements(replacements);
const functionValues = mapToFunctions(replacements);
const keys = Object.keys(functionValues).sort(longest).map(escape);
const lookahead = preventAssignment ? '(?!\\s*=[^=])' : '';
const pattern = delimiters
Expand Down
8 changes: 8 additions & 0 deletions packages/replace/test/fixtures/form/process-check/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
description: 'Handles process type guards in replacements',
options: {
'process.env.NODE_ENV': '"production"',
preventAssignment: true,
typeofReplacements: true
}
};
3 changes: 3 additions & 0 deletions packages/replace/test/fixtures/form/process-check/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if (typeof process !== 'undefined' && process.env.NODE_ENV === 'production') {
console.log('production');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
process.env.DEBUG = 'test';
10 changes: 9 additions & 1 deletion packages/replace/test/snapshots/form.js.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,20 @@ Generated by [AVA](https://avajs.dev).
exclude␊
`);`

## process-check: Handles process type guards in replacements

> Snapshot 1
`if ("object" !== 'undefined' && "production" === 'production') {␊
console.log('production');␊
}`

## replace-nothing: replaces nothing

> Snapshot 1
`console.log('as-it'); // eslint-disable-line␊
console.log(typeof window.document); // eslint-disable-line`
console.log("object".document); // eslint-disable-line`

## replace-strings: replaces strings

Expand Down
Binary file modified packages/replace/test/snapshots/form.js.snap
Binary file not shown.

0 comments on commit 04895fa

Please sign in to comment.