replace-in-file
Advanced tools
Comparing version 6.2.0 to 7.0.1
@@ -0,1 +1,4 @@ | ||
## 7.0.0 | ||
Strings provided to the `from` value are now escaped for regex matching when counting of matches is enabled. This is unlikely to result in any breaking changes, but as a precaution the major version has been bumped. | ||
## 6.0.0 | ||
@@ -2,0 +5,0 @@ From version 6.0.0 onwards, replace in file requires Node 10 or higher. If you need support for Node 8, please use version 5.x.x. |
@@ -17,2 +17,12 @@ 'use strict'; | ||
/** | ||
* Escape string to make it safe for use in a regex | ||
*/ | ||
function escapeRegex(string) { | ||
if (typeof string === 'string') { | ||
return string.replace(/[.*+?^${}()|[\]\\/]/g, '\\$&'); | ||
} | ||
return string; | ||
} | ||
/** | ||
* Helper to make replacements | ||
@@ -59,3 +69,3 @@ */ | ||
if (count) { | ||
const matches = contents.match(item); | ||
const matches = contents.match(escapeRegex(item)); | ||
if (matches) { | ||
@@ -62,0 +72,0 @@ const replacements = matches.filter(match => match !== replacement); |
@@ -34,14 +34,21 @@ 'use strict'; | ||
//Extract data | ||
const {files, from, to, ignore, encoding} = config; | ||
const {files, from, to, processor, ignore, encoding} = config; | ||
//Validate values | ||
if (typeof files === 'undefined') { | ||
throw new Error('Must specify file or files'); | ||
if (typeof processor !== 'undefined') { | ||
if (typeof processor !== 'function' && !Array.isArray(processor)) { | ||
throw new Error('Processor should be either a function or an array of functions'); | ||
} | ||
} else { | ||
//Validate values | ||
if (typeof files === 'undefined') { | ||
throw new Error('Must specify file or files'); | ||
} | ||
if (typeof from === 'undefined') { | ||
throw new Error('Must specify string or regex to replace'); | ||
} | ||
if (typeof to === 'undefined') { | ||
throw new Error('Must specify a replacement (can be blank string)'); | ||
} | ||
} | ||
if (typeof from === 'undefined') { | ||
throw new Error('Must specify string or regex to replace'); | ||
} | ||
if (typeof to === 'undefined') { | ||
throw new Error('Must specify a replacement (can be blank string)'); | ||
} | ||
@@ -48,0 +55,0 @@ //Ensure arrays |
@@ -12,2 +12,3 @@ 'use strict'; | ||
const replaceAsync = require('./helpers/replace-async'); | ||
const processFile = require('./process-file'); | ||
@@ -19,2 +20,7 @@ /** | ||
// If custom processor is provided use it instead | ||
if (config && config.processor) { | ||
return processFile(config, cb); | ||
} | ||
//Parse config | ||
@@ -72,2 +78,7 @@ try { | ||
// If custom processor is provided use it instead | ||
if (config && config.processor) { | ||
return processFile.processFileSync(config); | ||
} | ||
//Parse config | ||
@@ -74,0 +85,0 @@ config = parseConfig(config); |
@@ -18,2 +18,3 @@ 'use strict'; | ||
const testData = 'a re place c'; | ||
const testData2 = `app.setVersion('\${sourceVersion}');`; | ||
@@ -27,2 +28,3 @@ /** | ||
writeFile('test3', 'nope', 'utf8'), | ||
writeFile('test4', testData2, 'utf8'), | ||
])); | ||
@@ -37,2 +39,3 @@ | ||
deleteFile('test3'), | ||
deleteFile('test4'), | ||
])); | ||
@@ -971,3 +974,3 @@ | ||
it('should return corret results for multiple files', function() { | ||
it('should return correct results for multiple files', function() { | ||
const results = replace.sync({ | ||
@@ -1176,2 +1179,36 @@ files: ['test1', 'test2', 'test3'], | ||
}); | ||
//https://github.com/adamreisnz/replace-in-file/issues/156 | ||
describe('special characters', () => { | ||
it(`should replace contents with special characters and count matches correctly`, done => { | ||
const results = replace.sync({ | ||
files: 'test4', | ||
from: '${sourceVersion}', | ||
to: '1.0.0', | ||
countMatches: true, | ||
}); | ||
const test4 = fs.readFileSync('test4', 'utf8'); | ||
expect(test4).to.equal(`app.setVersion('1.0.0');`); | ||
expect(results).to.have.length(1); | ||
expect(results[0].file).to.equal('test4'); | ||
expect(results[0].hasChanged).to.equal(true); | ||
expect(results[0].numMatches).to.equal(1); | ||
done(); | ||
}); | ||
it(`should replace contents with special characters and count matches correctly (2)`, done => { | ||
const results = replace.sync({ | ||
files: 'test4', | ||
from: `\${sourceVersion}')`, | ||
to: '1.0.0', | ||
countMatches: true, | ||
}); | ||
const test4 = fs.readFileSync('test4', 'utf8'); | ||
expect(test4).to.equal(`app.setVersion('1.0.0;`); | ||
expect(results).to.have.length(1); | ||
expect(results[0].file).to.equal('test4'); | ||
expect(results[0].hasChanged).to.equal(true); | ||
expect(results[0].numMatches).to.equal(1); | ||
done(); | ||
}); | ||
}); | ||
}); |
{ | ||
"name": "replace-in-file", | ||
"version": "6.2.0", | ||
"version": "7.0.1", | ||
"description": "A simple utility to quickly replace text in one or more files.", | ||
@@ -37,17 +37,17 @@ "homepage": "https://github.com/adamreisnz/replace-in-file#readme", | ||
"dependencies": { | ||
"chalk": "^4.1.0", | ||
"glob": "^7.1.6", | ||
"yargs": "^16.2.0" | ||
"chalk": "^4.1.2", | ||
"glob": "^8.1.0", | ||
"yargs": "^17.7.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.12.10", | ||
"@babel/cli": "^7.12.10", | ||
"@babel/preset-env": "^7.12.11", | ||
"@babel/register": "^7.12.10", | ||
"babel-plugin-istanbul": "^6.0.0", | ||
"@babel/core": "^7.15.8", | ||
"@babel/cli": "^7.15.7", | ||
"@babel/preset-env": "^7.15.8", | ||
"@babel/register": "^7.15.3", | ||
"babel-plugin-istanbul": "^6.1.1", | ||
"bluebird": "^3.7.2", | ||
"chai": "^4.2.0", | ||
"chai": "^4.3.4", | ||
"chai-as-promised": "^7.1.1", | ||
"dirty-chai": "^2.0.1", | ||
"mocha": "^8.2.1", | ||
"mocha": "^10.2.0", | ||
"nyc": "^15.0.1" | ||
@@ -54,0 +54,0 @@ }, |
# Replace in file | ||
[![npm version](https://img.shields.io/npm/v/replace-in-file.svg)](https://www.npmjs.com/package/replace-in-file) | ||
[![node dependencies](https://david-dm.org/adamreisnz/replace-in-file.svg)](https://david-dm.org/adamreisnz/replace-in-file) | ||
[![build status](https://travis-ci.org/adamreisnz/replace-in-file.svg?branch=master)](https://travis-ci.org/adamreisnz/replace-in-file) | ||
@@ -11,16 +10,2 @@ [![coverage status](https://coveralls.io/repos/github/adamreisnz/replace-in-file/badge.svg?branch=master)](https://coveralls.io/github/adamreisnz/replace-in-file?branch=master) | ||
> Hey there ๐๐ผ, thank you for using `replace-in-file`! | ||
> Sorry for the interruption, but as you probably know, I donโt get paid for maintaining this package, and I also haven't put up a donation thingy of any kind. | ||
> However, I _am_ trying to grow our start-up [Hello Club](https://helloclub.com/?source=npm) internationally, and would _really_ appreciate it if you could have a quick look on our [website](https://helloclub.com/?source=npm) to see what we're all about. ๐ | ||
> As the name implies, we offer an [all-in-one club and membership management solution](https://helloclub.com/?source=npm) complete with booking system, automated membership renewals, online payments and integrated access and light control. | ||
> Clubs that have switched to Hello Club have been saving so much time managing their members and finances, and the members themselves really enjoy using it, with overwhelmingly positive feedback. | ||
> Check us out if you belong to any kind of club or if you know someone who helps run a club! | ||
> Thank you so much for your time, now go and replace some data in your files! ๐ | ||
# Index | ||
@@ -35,2 +20,3 @@ - [Installation](#installation) | ||
- [Counting matches and replacements](#counting-matches-and-replacements) | ||
- [Custom processor](#custom-processor) | ||
- [Advanced usage](#advanced-usage) | ||
@@ -213,2 +199,34 @@ - [Replace a single file or glob](#replace-a-single-file-or-glob) | ||
### Custom processor | ||
For advanced usage where complex processing is needed it's possible to use a callback that will receive content as an argument and should return it processed. | ||
```js | ||
const results = replace.sync({ | ||
files: 'path/to/files/*.html', | ||
processor: (input) => input.replace(/foo/g, 'bar'), | ||
}); | ||
``` | ||
### Array of custom processors | ||
Passing processor function also supports passing an array of functions that will be executed sequentially | ||
```js | ||
function someProcessingA(input) { | ||
const chapters = input.split('###') | ||
chapters[1] = chapters[1].replace(/foo/g, 'bar') | ||
return chapters.join('###') | ||
} | ||
function someProcessingB(input) { | ||
return input.replace(/foo/g, 'bar') | ||
} | ||
const results = replace.sync({ | ||
files: 'path/to/files/*.html', | ||
processor: [someProcessingA, someProcessingB], | ||
}); | ||
``` | ||
## Advanced usage | ||
@@ -372,2 +390,3 @@ | ||
//Glob settings here | ||
dot: true, //E.g. to include file names starting with a dot | ||
}, | ||
@@ -374,0 +393,0 @@ }; |
@@ -41,3 +41,3 @@ | ||
type FromCallback = (file: string) => string | RegExp | string[] | RegExp[]; | ||
type FromCallback = (file: string) => string | RegExp | (RegExp | string)[]; | ||
type ToCallback = (match: string, file: string) => string | string[]; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
97002
33
2494
496
7
+ Addedbrace-expansion@2.0.1(transitive)
+ Addedcliui@8.0.1(transitive)
+ Addedglob@8.1.0(transitive)
+ Addedminimatch@5.1.6(transitive)
+ Addedyargs@17.7.2(transitive)
+ Addedyargs-parser@21.1.1(transitive)
- Removedbrace-expansion@1.1.11(transitive)
- Removedcliui@7.0.4(transitive)
- Removedconcat-map@0.0.1(transitive)
- Removedglob@7.2.3(transitive)
- Removedminimatch@3.1.2(transitive)
- Removedpath-is-absolute@1.0.1(transitive)
- Removedyargs@16.2.0(transitive)
- Removedyargs-parser@20.2.9(transitive)
Updatedchalk@^4.1.2
Updatedglob@^8.1.0
Updatedyargs@^17.7.2