mirror of
https://github.com/zhigang1992/replace-in-file.git
synced 2026-01-12 09:33:39 +08:00
4.0.0 (#74)
* Bump dependencies * [feature] #38 Count number of matches * Update make-replacements.js * [feature] #42 Differentiate number of matches and number of replacements * [enhance] #56 Support for CWD parameter * Default config value * [enhance] #63 Add --quiet flag to supress console output in CLI * Update success-handler.js * Update readme and add change log
This commit is contained in:
23
CHANGELOG.md
Normal file
23
CHANGELOG.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# 4.0.0
|
||||
|
||||
## Breaking changes
|
||||
The return value is now a results array instead of an array with changed files. The new results array includes each file that was processed, with a flag to indicate whether or not the file was changed, and optionally information about the number of matches and replacements that were made. See the readme for more details.
|
||||
|
||||
To update existing code and obtain an array of changed files again, simply convert the results array as follows:
|
||||
|
||||
```js
|
||||
const results = await replace(options);
|
||||
const changedFiles = results
|
||||
.filter(result => result.hasChanged)
|
||||
.map(result => result.file);
|
||||
```
|
||||
|
||||
## New features
|
||||
- Added `countMatches` flag to count the number of matches and replacements per file [#38](https://github.com/adamreisnz/replace-in-file/issues/38), [#42](https://github.com/adamreisnz/replace-in-file/issues/42), [#61](https://github.com/adamreisnz/replace-in-file/issues/61)
|
||||
- Added `--quiet` flag for CLI to suppress success output [#63](https://github.com/adamreisnz/replace-in-file/issues/63)
|
||||
- Added `cwd` configuration parameter for network drive replacements [#56](https://github.com/adamreisnz/replace-in-file/issues/56)
|
||||
|
||||
# 3.0.0
|
||||
|
||||
## Breaking changes
|
||||
From version 3.0.0 onwards, replace in file requires Node 6 or higher. If you need support for Node 4 or 5, please use version 2.x.x.
|
||||
110
README.md
110
README.md
@@ -16,6 +16,7 @@ A simple utility to quickly replace text in one or more files or globs. Works sy
|
||||
- [Asynchronous replacement with callback](#asynchronous-replacement-with-callback)
|
||||
- [Synchronous replacement](#synchronous-replacement)
|
||||
- [Return value](#return-value)
|
||||
- [Counting matches and replacements](#counting-matches-and-replacements)
|
||||
- [Advanced usage](#advanced-usage)
|
||||
- [Replace a single file or glob](#replace-a-single-file-or-glob)
|
||||
- [Replace multiple files or globs](#replace-multiple-files-or-globs)
|
||||
@@ -30,7 +31,8 @@ A simple utility to quickly replace text in one or more files or globs. Works sy
|
||||
- [Ignore multiple files or globs](#ignore-multiple-files-or-globs)
|
||||
- [Allow empty/invalid paths](#allow-emptyinvalid-paths)
|
||||
- [Disable globs](#disable-globs)
|
||||
- [Specify glob configuration](#glob-configuration)
|
||||
- [Specify glob configuration](#specify-glob-configuration)
|
||||
- [Making replacements on network drives](#making-replacements-on-network-drives)
|
||||
- [Specify character encoding](#specify-character-encoding)
|
||||
- [Dry run](#dry-run)
|
||||
- [CLI usage](#cli-usage)
|
||||
@@ -65,8 +67,8 @@ const options = {
|
||||
|
||||
```js
|
||||
try {
|
||||
const changes = await replace(options)
|
||||
console.log('Modified files:', changes.join(', '));
|
||||
const results = await replace(options)
|
||||
console.log('Replacement results:', results);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error occurred:', error);
|
||||
@@ -77,8 +79,8 @@ catch (error) {
|
||||
|
||||
```js
|
||||
replace(options)
|
||||
.then(changes => {
|
||||
console.log('Modified files:', changes.join(', '));
|
||||
.then(results => {
|
||||
console.log('Replacement results:', results);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error occurred:', error);
|
||||
@@ -88,11 +90,11 @@ replace(options)
|
||||
### Asynchronous replacement with callback
|
||||
|
||||
```js
|
||||
replace(options, (error, changes) => {
|
||||
replace(options, (error, results) => {
|
||||
if (error) {
|
||||
return console.error('Error occurred:', error);
|
||||
}
|
||||
console.log('Modified files:', changes.join(', '));
|
||||
console.log('Replacement results:', results);
|
||||
});
|
||||
```
|
||||
|
||||
@@ -100,8 +102,8 @@ replace(options, (error, changes) => {
|
||||
|
||||
```js
|
||||
try {
|
||||
const changes = replace.sync(options);
|
||||
console.log('Modified files:', changes.join(', '));
|
||||
const results = replace.sync(options);
|
||||
console.log('Replacement results:', results);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error occurred:', error);
|
||||
@@ -110,22 +112,84 @@ catch (error) {
|
||||
|
||||
### Return value
|
||||
|
||||
The return value of the library is an array of file names of files that were modified (e.g.
|
||||
had some of the contents replaced). If no replacements were made, the return array will be empty.
|
||||
The return value of the library is an array of replacement results against each file that was processed. This includes files in which no replacements were made.
|
||||
|
||||
Each result contains the following values:
|
||||
|
||||
- `file`: The path to the file that was processed
|
||||
- `hasChanged`: Flag to indicate if the file was changed or not
|
||||
|
||||
```js
|
||||
const changes = replace.sync({
|
||||
const results = replace.sync({
|
||||
files: 'path/to/files/*.html',
|
||||
from: 'foo',
|
||||
from: /foo/g,
|
||||
to: 'bar',
|
||||
});
|
||||
|
||||
console.log(changes);
|
||||
console.log(results);
|
||||
|
||||
// [
|
||||
// 'path/to/files/file1.html',
|
||||
// 'path/to/files/file3.html',
|
||||
// 'path/to/files/file5.html',
|
||||
// {
|
||||
// file: 'path/to/files/file1.html',
|
||||
// hasChanged: true,
|
||||
// },
|
||||
// {
|
||||
// file: 'path/to/files/file2.html',
|
||||
// hasChanged: true,
|
||||
// },
|
||||
// {
|
||||
// file: 'path/to/files/file3.html',
|
||||
// hasChanged: false,
|
||||
// },
|
||||
// ]
|
||||
|
||||
```
|
||||
|
||||
To get an array of changed files, simply map the results as follows:
|
||||
|
||||
```js
|
||||
const changedFiles = results
|
||||
.filter(result => result.hasChanged)
|
||||
.map(result => result.file);
|
||||
```
|
||||
|
||||
### Counting matches and replacements
|
||||
By setting the `countMatches` configuration flag to `true`, the number of matches and replacements per file will be counted and present in the results array.
|
||||
|
||||
- `numMatches`: Indicates the number of times a match was found in the file
|
||||
- `numReplacements`: Indicates the number of times a replacement was made in the file
|
||||
|
||||
Note that the number of matches can be higher than the number of replacements if a match and replacement are the same string.
|
||||
|
||||
```js
|
||||
const results = replace.sync({
|
||||
files: 'path/to/files/*.html',
|
||||
from: /foo/g,
|
||||
to: 'bar',
|
||||
countMatches: true,
|
||||
});
|
||||
|
||||
console.log(results);
|
||||
|
||||
// [
|
||||
// {
|
||||
// file: 'path/to/files/file1.html',
|
||||
// hasChanged: true,
|
||||
// numMatches: 3,
|
||||
// numReplacements: 3,
|
||||
// },
|
||||
// {
|
||||
// file: 'path/to/files/file2.html',
|
||||
// hasChanged: true,
|
||||
// numMatches: 1,
|
||||
// numReplacements: 1,
|
||||
// },
|
||||
// {
|
||||
// file: 'path/to/files/file3.html',
|
||||
// hasChanged: false,
|
||||
// numMatches: 0,
|
||||
// numReplacements: 0,
|
||||
// },
|
||||
// ]
|
||||
```
|
||||
|
||||
@@ -293,6 +357,9 @@ const options = {
|
||||
|
||||
Please note that the setting `nodir` will always be passed as `false`.
|
||||
|
||||
### Making replacements on network drives
|
||||
To make replacements in files on network drives, you may need to specify the UNC path as the `cwd` config option. This will then be passed to glob and prefixed to your paths accordingly. See [#56](https://github.com/adamreisnz/replace-in-file/issues/56) for more details.
|
||||
|
||||
### Specify character encoding
|
||||
Use a different character encoding for reading/writing files. Defaults to `utf-8`.
|
||||
|
||||
@@ -321,6 +388,7 @@ replace-in-file from to some/file.js,some/**/glob.js
|
||||
[--disableGlobs]
|
||||
[--isRegex]
|
||||
[--verbose]
|
||||
[--quiet]
|
||||
[--dry]
|
||||
```
|
||||
|
||||
@@ -331,7 +399,9 @@ The flags `--disableGlobs`, `--ignore` and `--encoding` are supported in the CLI
|
||||
The setting `allowEmptyPaths` is not supported in the CLI as the replacement is
|
||||
synchronous, and this setting is only relevant for asynchronous replacement.
|
||||
|
||||
To list the changed files, use the `--verbose` flag. To do a dry run, use `--dry`.
|
||||
To list the changed files, use the `--verbose` flag. Success output can be suppressed by using the `--quiet` flag.
|
||||
|
||||
To do a dry run without making any actual changes, use `--dry`.
|
||||
|
||||
A regular expression may be used for the `from` parameter by specifying the `--isRegex` flag.
|
||||
|
||||
@@ -343,7 +413,9 @@ Node’s built in `path.resolve()`, so you can pass in an absolute or relative p
|
||||
## Version information
|
||||
From version 3.0.0 onwards, replace in file requires Node 6 or higher. If you need support for Node 4 or 5, please use version 2.x.x.
|
||||
|
||||
See the [Changelog](CHANGELOG.md) for more information.
|
||||
|
||||
## License
|
||||
(MIT License)
|
||||
|
||||
Copyright 2015-2018, [Adam Reis](https://adam.reis.nz), co-founder at [Hello Club](https://helloclub.com/?source=npm)
|
||||
Copyright 2015-2019, [Adam Reis](https://adam.reis.nz), Co-founder at [Hello Club](https://helloclub.com/?source=npm)
|
||||
|
||||
12
bin/cli.js
12
bin/cli.js
@@ -24,7 +24,7 @@ const config = loadConfig(configFile);
|
||||
const options = combineConfig(config, argv);
|
||||
|
||||
//Extract settings
|
||||
const {from, to, files, isRegex, verbose} = options;
|
||||
const {from, to, files, isRegex, verbose, quiet} = options;
|
||||
|
||||
//Single star globs already get expanded in the command line
|
||||
options.files = files.reduce((files, file) => {
|
||||
@@ -44,12 +44,16 @@ if (isRegex) {
|
||||
}
|
||||
|
||||
//Log
|
||||
console.log(`Replacing '${from}' with '${to}'`);
|
||||
if (!quiet) {
|
||||
console.log(`Replacing '${from}' with '${to}'`);
|
||||
}
|
||||
|
||||
//Replace
|
||||
try {
|
||||
const changes = replace.sync(options);
|
||||
successHandler(changes, verbose);
|
||||
const results = replace.sync(options);
|
||||
if (!quiet) {
|
||||
successHandler(results, verbose);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
errorHandler(error);
|
||||
|
||||
@@ -8,9 +8,10 @@ const globAsync = require('./glob-async');
|
||||
/**
|
||||
* Get paths asynchrously
|
||||
*/
|
||||
module.exports = function getPathsAsync(
|
||||
patterns, ignore, disableGlobs, allowEmptyPaths, cfg
|
||||
) {
|
||||
module.exports = function getPathsAsync(patterns, config) {
|
||||
|
||||
//Extract relevant config
|
||||
const {ignore, disableGlobs, allowEmptyPaths, glob: cfg} = config;
|
||||
|
||||
//Not using globs?
|
||||
if (disableGlobs) {
|
||||
|
||||
@@ -8,7 +8,10 @@ const glob = require('glob');
|
||||
/**
|
||||
* Get paths (sync)
|
||||
*/
|
||||
module.exports = function getPathsSync(patterns, ignore, disableGlobs, cfg) {
|
||||
module.exports = function getPathsSync(patterns, config) {
|
||||
|
||||
//Extract relevant config
|
||||
const {ignore, disableGlobs, glob: globConfig, cwd} = config;
|
||||
|
||||
//Not using globs?
|
||||
if (disableGlobs) {
|
||||
@@ -16,12 +19,24 @@ module.exports = function getPathsSync(patterns, ignore, disableGlobs, cfg) {
|
||||
}
|
||||
|
||||
//Prepare glob config
|
||||
cfg = Object.assign({ignore}, cfg, {nodir: true});
|
||||
const cfg = Object.assign({ignore}, globConfig, {nodir: true});
|
||||
|
||||
//Append CWD configuration if given (#56)
|
||||
//istanbul ignore if
|
||||
if (cwd) {
|
||||
cfg.cwd = cwd;
|
||||
}
|
||||
|
||||
//Get paths
|
||||
const paths = patterns
|
||||
.map(pattern => glob.sync(pattern, cfg));
|
||||
const paths = patterns.map(pattern => glob.sync(pattern, cfg));
|
||||
const flattened = [].concat.apply([], paths);
|
||||
|
||||
//Prefix each path with CWD if given (#56)
|
||||
//istanbul ignore if
|
||||
if (cwd) {
|
||||
return flattened.map(path => `${cwd}${path}`);
|
||||
}
|
||||
|
||||
//Return flattened
|
||||
return [].concat.apply([], paths);
|
||||
return flattened;
|
||||
};
|
||||
|
||||
@@ -16,20 +16,27 @@ function getReplacement(replace, isArray, i) {
|
||||
/**
|
||||
* Helper to make replacements
|
||||
*/
|
||||
module.exports = function makeReplacements(contents, from, to, file) {
|
||||
module.exports = function makeReplacements(contents, from, to, file, count) {
|
||||
|
||||
//Turn into array
|
||||
if (!Array.isArray(from)) {
|
||||
from = [from];
|
||||
}
|
||||
|
||||
//Check if replace value is an array
|
||||
//Check if replace value is an array and prepare result
|
||||
const isArray = Array.isArray(to);
|
||||
const result = {file};
|
||||
|
||||
//Counting? Initialize number of matches
|
||||
if (count) {
|
||||
result.numMatches = 0;
|
||||
result.numReplacements = 0;
|
||||
}
|
||||
|
||||
//Make replacements
|
||||
from.forEach((item, i) => {
|
||||
const newContents = from.reduce((contents, item, i) => {
|
||||
|
||||
//Call function if given, passing the filename
|
||||
//Call function if given, passing in the filename
|
||||
if (typeof item === 'function') {
|
||||
item = item(file);
|
||||
}
|
||||
@@ -37,7 +44,7 @@ module.exports = function makeReplacements(contents, from, to, file) {
|
||||
//Get replacement value
|
||||
let replacement = getReplacement(to, isArray, i);
|
||||
if (replacement === null) {
|
||||
return;
|
||||
return contents;
|
||||
}
|
||||
|
||||
//Call function if given, appending the filename
|
||||
@@ -46,10 +53,23 @@ module.exports = function makeReplacements(contents, from, to, file) {
|
||||
replacement = (...args) => original(...args, file);
|
||||
}
|
||||
|
||||
//Make replacement
|
||||
contents = contents.replace(item, replacement);
|
||||
});
|
||||
//Count matches
|
||||
if (count) {
|
||||
const matches = contents.match(item);
|
||||
if (matches) {
|
||||
const replacements = matches.filter(match => match !== replacement);
|
||||
result.numMatches += matches.length;
|
||||
result.numReplacements += replacements.length;
|
||||
}
|
||||
}
|
||||
|
||||
//Return modified contents
|
||||
return contents;
|
||||
//Make replacement
|
||||
return contents.replace(item, replacement);
|
||||
}, contents);
|
||||
|
||||
//Check if changed
|
||||
result.hasChanged = (newContents !== contents);
|
||||
|
||||
//Return result and new contents
|
||||
return [result, newContents];
|
||||
};
|
||||
|
||||
@@ -8,10 +8,13 @@ const defaults = {
|
||||
encoding: 'utf-8',
|
||||
disableGlobs: false,
|
||||
allowEmptyPaths: false,
|
||||
countMatches: false,
|
||||
isRegex: false,
|
||||
verbose: false,
|
||||
quiet: false,
|
||||
dry: false,
|
||||
glob: {},
|
||||
cwd: null,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -28,7 +31,7 @@ module.exports = function parseConfig(config) {
|
||||
config.glob = config.glob || {};
|
||||
|
||||
//Extract data
|
||||
const {files, from, to, ignore, encoding, glob} = config;
|
||||
const {files, from, to, ignore, encoding} = config;
|
||||
|
||||
//Validate values
|
||||
if (typeof files === 'undefined') {
|
||||
@@ -40,9 +43,6 @@ module.exports = function parseConfig(config) {
|
||||
if (typeof to === 'undefined') {
|
||||
throw new Error('Must specify a replacement (can be blank string)');
|
||||
}
|
||||
if (typeof glob !== 'object') {
|
||||
throw new Error('Invalid glob config');
|
||||
}
|
||||
|
||||
//Ensure arrays
|
||||
if (!Array.isArray(files)) {
|
||||
|
||||
@@ -9,32 +9,36 @@ const makeReplacements = require('./make-replacements');
|
||||
/**
|
||||
* Helper to replace in a single file (async)
|
||||
*/
|
||||
module.exports = function replaceAsync(file, from, to, enc, dry) {
|
||||
module.exports = function replaceAsync(file, from, to, config) {
|
||||
|
||||
//Extract relevant config
|
||||
const {encoding, dry, countMatches} = config;
|
||||
|
||||
//Wrap in promise
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(file, enc, (error, contents) => {
|
||||
fs.readFile(file, encoding, (error, contents) => {
|
||||
//istanbul ignore if
|
||||
if (error) {
|
||||
return reject(error);
|
||||
}
|
||||
|
||||
//Replace contents and check if anything changed
|
||||
let newContents = makeReplacements(contents, from, to, file);
|
||||
if (newContents === contents) {
|
||||
return resolve({file, hasChanged: false});
|
||||
}
|
||||
//Make replacements
|
||||
const [result, newContents] = makeReplacements(
|
||||
contents, from, to, file, countMatches
|
||||
);
|
||||
|
||||
//Dry run, resolve
|
||||
if (dry) {
|
||||
return resolve({file, hasChanged: true});
|
||||
//Not changed or dry run?
|
||||
if (!result.hasChanged || dry) {
|
||||
return resolve(result);
|
||||
}
|
||||
|
||||
//Write to file
|
||||
fs.writeFile(file, newContents, enc, error => {
|
||||
fs.writeFile(file, newContents, encoding, error => {
|
||||
//istanbul ignore if
|
||||
if (error) {
|
||||
return reject(error);
|
||||
}
|
||||
resolve({file, hasChanged: true});
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,23 +9,22 @@ const makeReplacements = require('./make-replacements');
|
||||
/**
|
||||
* Helper to replace in a single file (sync)
|
||||
*/
|
||||
module.exports = function replaceSync(file, from, to, enc, dry) {
|
||||
module.exports = function replaceSync(file, from, to, config) {
|
||||
|
||||
//Read contents
|
||||
const contents = fs.readFileSync(file, enc);
|
||||
//Extract relevant config and read file contents
|
||||
const {encoding, dry, countMatches} = config;
|
||||
const contents = fs.readFileSync(file, encoding);
|
||||
|
||||
//Replace contents and check if anything changed
|
||||
const newContents = makeReplacements(contents, from, to, file);
|
||||
if (newContents === contents) {
|
||||
return false;
|
||||
const [result, newContents] = makeReplacements(
|
||||
contents, from, to, file, countMatches
|
||||
);
|
||||
|
||||
//Contents changed and not a dry run? Write to file
|
||||
if (result.hasChanged && !dry) {
|
||||
fs.writeFileSync(file, newContents, encoding);
|
||||
}
|
||||
|
||||
//Dry run?
|
||||
if (dry) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Write to file
|
||||
fs.writeFileSync(file, newContents, enc);
|
||||
return true;
|
||||
//Return result
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -8,11 +8,13 @@ const chalk = require('chalk');
|
||||
/**
|
||||
* Success handler
|
||||
*/
|
||||
module.exports = function successHandler(changes, verbose = false) {
|
||||
if (changes.length > 0) {
|
||||
console.log(chalk.green(changes.length, 'file(s) were changed'));
|
||||
module.exports = function successHandler(results, verbose) {
|
||||
const changed = results.filter(result => result.hasChanged);
|
||||
const numChanges = changed.length;
|
||||
if (numChanges > 0) {
|
||||
console.log(chalk.green(`${numChanges} file(s) were changed`));
|
||||
if (verbose) {
|
||||
changes.forEach(file => console.log(chalk.grey('-', file)));
|
||||
changed.forEach(result => console.log(chalk.grey('-', result.file)));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -27,10 +27,7 @@ function replaceInFile(config, cb) {
|
||||
}
|
||||
|
||||
//Get config
|
||||
const {
|
||||
files, from, to, encoding, ignore, allowEmptyPaths, disableGlobs,
|
||||
dry, verbose, glob,
|
||||
} = config;
|
||||
const {files, from, to, dry, verbose} = config;
|
||||
|
||||
//Dry run?
|
||||
//istanbul ignore if: No need to test console logs
|
||||
@@ -39,26 +36,19 @@ function replaceInFile(config, cb) {
|
||||
}
|
||||
|
||||
//Find paths
|
||||
return getPathsAsync(files, ignore, disableGlobs, allowEmptyPaths, glob)
|
||||
return getPathsAsync(files, config)
|
||||
|
||||
//Make replacements
|
||||
.then(paths => Promise.all(paths.map(file => {
|
||||
return replaceAsync(file, from, to, encoding, dry);
|
||||
})))
|
||||
|
||||
//Convert results to array of changed files
|
||||
.then(results => {
|
||||
return results
|
||||
.filter(result => result.hasChanged)
|
||||
.map(result => result.file);
|
||||
})
|
||||
.then(paths => Promise.all(
|
||||
paths.map(file => replaceAsync(file, from, to, config))
|
||||
))
|
||||
|
||||
//Success handler
|
||||
.then(changedFiles => {
|
||||
.then(results => {
|
||||
if (cb) {
|
||||
cb(null, changedFiles);
|
||||
cb(null, results);
|
||||
}
|
||||
return changedFiles;
|
||||
return results;
|
||||
})
|
||||
|
||||
//Error handler
|
||||
@@ -81,27 +71,17 @@ replaceInFile.sync = function(config) {
|
||||
config = parseConfig(config);
|
||||
|
||||
//Get config, paths, and initialize changed files
|
||||
const {
|
||||
files, from, to, encoding, ignore, disableGlobs, dry, verbose, glob,
|
||||
} = config;
|
||||
const paths = getPathsSync(files, ignore, disableGlobs, glob);
|
||||
const changedFiles = [];
|
||||
const {files, from, to, dry, verbose} = config;
|
||||
const paths = getPathsSync(files, config);
|
||||
|
||||
//Dry run?
|
||||
//istanbul ignore if: No need to test console logs
|
||||
if (dry && verbose) {
|
||||
console.log(chalk.yellow('Dry run, not making any changes'));
|
||||
console.log(chalk.yellow('Dry run, not making actual changes'));
|
||||
}
|
||||
|
||||
//Process synchronously
|
||||
paths.forEach(path => {
|
||||
if (replaceSync(path, from, to, encoding, dry)) {
|
||||
changedFiles.push(path);
|
||||
}
|
||||
});
|
||||
|
||||
//Return changed files
|
||||
return changedFiles;
|
||||
//Process synchronously and return results
|
||||
return paths.map(path => replaceSync(path, from, to, config));
|
||||
};
|
||||
|
||||
//Export
|
||||
|
||||
@@ -68,15 +68,6 @@ describe('Replace in file', () => {
|
||||
})).to.eventually.be.rejectedWith(Error);
|
||||
});
|
||||
|
||||
it('should throw an error when invalid `glob` config defined', () => {
|
||||
return expect(replace({
|
||||
files: 'test1',
|
||||
from: /re\splace/g,
|
||||
to: 'test',
|
||||
glob: 'invalid',
|
||||
})).to.eventually.be.rejectedWith(Error);
|
||||
});
|
||||
|
||||
it('should replace contents in a single file with regex', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
@@ -236,49 +227,54 @@ describe('Replace in file', () => {
|
||||
}).should.be.fulfilled;
|
||||
});
|
||||
|
||||
it('should return a changed files array', done => {
|
||||
it('should return a results array', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
}).then(changedFiles => {
|
||||
expect(changedFiles).to.be.instanceof(Array);
|
||||
}).then(results => {
|
||||
expect(results).to.be.instanceof(Array);
|
||||
expect(results).to.have.length(1);
|
||||
expect(results[0].file).to.equal('test1');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return in files if something was replaced', done => {
|
||||
it('should mark if something was replaced', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
}).then(changedFiles => {
|
||||
expect(changedFiles).to.have.length(1);
|
||||
expect(changedFiles[0]).to.equal('test1');
|
||||
}).then(results => {
|
||||
expect(results[0].hasChanged).to.equal(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not return in files if nothing replaced', done => {
|
||||
it('should not mark if nothing was replaced', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: 'nope',
|
||||
to: 'b',
|
||||
}).then(changedFiles => {
|
||||
expect(changedFiles).to.have.length(0);
|
||||
}).then(results => {
|
||||
expect(results[0].hasChanged).to.equal(false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return changed files for multiple files', done => {
|
||||
it('should return correct results for multiple files', done => {
|
||||
replace({
|
||||
files: ['test1', 'test2', 'test3'],
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
}).then(changedFiles => {
|
||||
expect(changedFiles).to.have.length(2);
|
||||
expect(changedFiles).to.contain('test1');
|
||||
expect(changedFiles).to.contain('test2');
|
||||
}).then(results => {
|
||||
expect(results).to.have.length(3);
|
||||
expect(results[0].file).to.equal('test1');
|
||||
expect(results[0].hasChanged).to.equal(true);
|
||||
expect(results[1].file).to.equal('test2');
|
||||
expect(results[1].hasChanged).to.equal(true);
|
||||
expect(results[2].file).to.equal('test3');
|
||||
expect(results[2].hasChanged).to.equal(false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -346,10 +342,14 @@ describe('Replace in file', () => {
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
dry: true,
|
||||
}).then(changedFiles => {
|
||||
expect(changedFiles).to.have.length(2);
|
||||
expect(changedFiles).to.contain('test1');
|
||||
expect(changedFiles).to.contain('test2');
|
||||
}).then(results => {
|
||||
expect(results).to.have.length(3);
|
||||
expect(results[0].file).to.equal('test1');
|
||||
expect(results[0].hasChanged).to.equal(true);
|
||||
expect(results[1].file).to.equal('test2');
|
||||
expect(results[1].hasChanged).to.equal(true);
|
||||
expect(results[2].file).to.equal('test3');
|
||||
expect(results[2].hasChanged).to.equal(false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -382,6 +382,41 @@ describe('Replace in file', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should count matches if specified in config', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: [/re/g, /place/g],
|
||||
to: 'test',
|
||||
countMatches: true,
|
||||
}).then(results => {
|
||||
expect(results[0].numMatches).to.equal(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not count matches if not specified in config', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: [/re/g, /place/g],
|
||||
to: 'test',
|
||||
}).then(results => {
|
||||
expect(results[0].numMatches).to.be.undefined;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 0 matches if match not found', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: 'nope',
|
||||
to: 'test',
|
||||
countMatches: true,
|
||||
}).then(results => {
|
||||
expect(results[0].numMatches).to.equal(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -589,49 +624,54 @@ describe('Replace in file', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should return a changed files array', done => {
|
||||
it('should return a results array', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
}, (error, changedFiles) => {
|
||||
expect(changedFiles).to.be.instanceof(Array);
|
||||
}, (error, results) => {
|
||||
expect(results).to.be.instanceof(Array);
|
||||
expect(results).to.have.length(1);
|
||||
expect(results[0].file).to.equal('test1');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return in files if something was replaced', done => {
|
||||
it('should mark if something was replaced', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
}, (error, changedFiles) => {
|
||||
expect(changedFiles).to.have.length(1);
|
||||
expect(changedFiles[0]).to.equal('test1');
|
||||
}, (error, results) => {
|
||||
expect(results[0].hasChanged).to.equal(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not return in files if nothing replaced', done => {
|
||||
it('should not mark if nothing was replaced', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: 'nope',
|
||||
to: 'b',
|
||||
}, (error, changedFiles) => {
|
||||
expect(changedFiles).to.have.length(0);
|
||||
}, (error, results) => {
|
||||
expect(results[0].hasChanged).to.equal(false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return changed files for multiple files', done => {
|
||||
it('should return correct results for multiple files', done => {
|
||||
replace({
|
||||
files: ['test1', 'test2', 'test3'],
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
}, (error, changedFiles) => {
|
||||
expect(changedFiles).to.have.length(2);
|
||||
expect(changedFiles).to.contain('test1');
|
||||
expect(changedFiles).to.contain('test2');
|
||||
}, (error, results) => {
|
||||
expect(results).to.have.length(3);
|
||||
expect(results[0].file).to.equal('test1');
|
||||
expect(results[0].hasChanged).to.equal(true);
|
||||
expect(results[1].file).to.equal('test2');
|
||||
expect(results[1].hasChanged).to.equal(true);
|
||||
expect(results[2].file).to.equal('test3');
|
||||
expect(results[2].hasChanged).to.equal(false);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -692,6 +732,41 @@ describe('Replace in file', () => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should count matches if specified in config', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: [/re/g, /place/g],
|
||||
to: 'test',
|
||||
countMatches: true,
|
||||
}, (error, results) => {
|
||||
expect(results[0].numMatches).to.equal(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not count matches if not specified in config', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: [/re/g, /place/g],
|
||||
to: 'test',
|
||||
}, (error, results) => {
|
||||
expect(results[0].numMatches).to.be.undefined;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return 0 matches if match not found', done => {
|
||||
replace({
|
||||
files: 'test1',
|
||||
from: 'nope',
|
||||
to: 'test',
|
||||
countMatches: true,
|
||||
}, (error, results) => {
|
||||
expect(results[0].numMatches).to.equal(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -861,43 +936,48 @@ describe('Replace in file', () => {
|
||||
expect(test2).to.equal('a b c');
|
||||
});
|
||||
|
||||
it('should return a changed files array', function() {
|
||||
const changedFiles = replace.sync({
|
||||
it('should return a results array', function() {
|
||||
const results = replace.sync({
|
||||
files: 'test1',
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
});
|
||||
expect(changedFiles).to.be.instanceof(Array);
|
||||
expect(results).to.be.instanceof(Array);
|
||||
expect(results).to.have.length(1);
|
||||
expect(results[0].file).to.equal('test1');
|
||||
});
|
||||
|
||||
it('should return in changed files if something was replaced', function() {
|
||||
const changedFiles = replace.sync({
|
||||
it('should mark if something was replaced', function() {
|
||||
const results = replace.sync({
|
||||
files: 'test1',
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
});
|
||||
expect(changedFiles).to.have.length(1);
|
||||
expect(changedFiles[0]).to.equal('test1');
|
||||
expect(results[0].hasChanged).to.equal(true);
|
||||
});
|
||||
|
||||
it('should not return in changed files if nothing replaced', function() {
|
||||
const changedFiles = replace.sync({
|
||||
it('should not mark if nothing was replaced', function() {
|
||||
const results = replace.sync({
|
||||
files: 'test1',
|
||||
from: 'nope',
|
||||
to: 'b',
|
||||
});
|
||||
expect(changedFiles).to.have.length(0);
|
||||
expect(results[0].hasChanged).to.equal(false);
|
||||
});
|
||||
|
||||
it('should return changed files for multiple files', function() {
|
||||
const changedFiles = replace.sync({
|
||||
it('should return corret results for multiple files', function() {
|
||||
const results = replace.sync({
|
||||
files: ['test1', 'test2', 'test3'],
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
});
|
||||
expect(changedFiles).to.have.length(2);
|
||||
expect(changedFiles).to.contain('test1');
|
||||
expect(changedFiles).to.contain('test2');
|
||||
expect(results).to.have.length(3);
|
||||
expect(results[0].file).to.equal('test1');
|
||||
expect(results[0].hasChanged).to.equal(true);
|
||||
expect(results[1].file).to.equal('test2');
|
||||
expect(results[1].hasChanged).to.equal(true);
|
||||
expect(results[2].file).to.equal('test3');
|
||||
expect(results[2].hasChanged).to.equal(false);
|
||||
});
|
||||
|
||||
it('should make multiple replacements with the same string', () => {
|
||||
@@ -1002,15 +1082,73 @@ describe('Replace in file', () => {
|
||||
});
|
||||
|
||||
it('should return changed files for a dry run', () => {
|
||||
const changedFiles = replace.sync({
|
||||
const results = replace.sync({
|
||||
files: ['test1', 'test2', 'test3'],
|
||||
from: /re\splace/g,
|
||||
to: 'b',
|
||||
dry: true,
|
||||
});
|
||||
expect(changedFiles).to.have.length(2);
|
||||
expect(changedFiles).to.contain('test1');
|
||||
expect(changedFiles).to.contain('test2');
|
||||
expect(results).to.have.length(3);
|
||||
expect(results[0].file).to.equal('test1');
|
||||
expect(results[0].hasChanged).to.equal(true);
|
||||
expect(results[1].file).to.equal('test2');
|
||||
expect(results[1].hasChanged).to.equal(true);
|
||||
expect(results[2].file).to.equal('test3');
|
||||
expect(results[2].hasChanged).to.equal(false);
|
||||
});
|
||||
|
||||
it('should count matches and replacements if specified in config', () => {
|
||||
const results = replace.sync({
|
||||
files: 'test1',
|
||||
from: [/re/g, /place/g],
|
||||
to: 'test',
|
||||
countMatches: true,
|
||||
});
|
||||
expect(results[0].numMatches).to.equal(2);
|
||||
expect(results[0].numReplacements).to.equal(2);
|
||||
});
|
||||
|
||||
it('should differentiate between matches and replacements', () => {
|
||||
const results = replace.sync({
|
||||
files: 'test1',
|
||||
from: [/re/g, /place/g],
|
||||
to: 're',
|
||||
countMatches: true,
|
||||
});
|
||||
expect(results[0].numMatches).to.equal(2);
|
||||
expect(results[0].numReplacements).to.equal(1);
|
||||
});
|
||||
|
||||
it('should count multiple replacements correctly', () => {
|
||||
const results = replace.sync({
|
||||
files: 'test1',
|
||||
from: [/re/g, /place/g],
|
||||
to: 'place',
|
||||
countMatches: true,
|
||||
});
|
||||
expect(results[0].numMatches).to.equal(3);
|
||||
expect(results[0].numReplacements).to.equal(1);
|
||||
});
|
||||
|
||||
it('should not count matches or replacements if not specified in config', () => {
|
||||
const results = replace.sync({
|
||||
files: 'test1',
|
||||
from: [/re/g, /place/g],
|
||||
to: 'test',
|
||||
});
|
||||
expect(results[0].numMatches).to.be.undefined;
|
||||
expect(results[0].numReplacements).to.be.undefined;
|
||||
});
|
||||
|
||||
it('should return 0 matches and replacements if match not found', () => {
|
||||
const results = replace.sync({
|
||||
files: 'test1',
|
||||
from: 'nope',
|
||||
to: 'test',
|
||||
countMatches: true,
|
||||
});
|
||||
expect(results[0].numMatches).to.equal(0);
|
||||
expect(results[0].numReplacements).to.equal(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,12 +38,12 @@
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"bluebird": "^3.5.3",
|
||||
"bluebird": "^3.5.4",
|
||||
"chai": "^4.2.0",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"istanbul": "^1.0.0-alpha.2",
|
||||
"mocha": "^6.0.2"
|
||||
"mocha": "^6.1.4"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
|
||||
Reference in New Issue
Block a user