diff --git a/README.md b/README.md index e95265b..18db8ba 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ A simple utility to quickly replace text in one or more files or globs. Works sy - [Replace all occurrences](#replace-all-occurrences) - [Multiple values with the same replacement](#multiple-values-with-the-same-replacement) - [Multiple values with different replacements](#multiple-values-with-different-replacements) + - [Using callbacks for `from`](#using-callbacks-for-from) - [Using callbacks for `to`](#using-callbacks-for-to) - [Ignore a single file or glob](#ignore-a-single-file-or-glob) - [Ignore multiple files or globs](#ignore-multiple-files-or-globs) @@ -191,8 +192,19 @@ const options = { }; ``` +### Using callbacks for `from` +You can also specify a callback that returns a string or a regular expression. The callback receives the name of the file in which the replacement is being performed, thereby allowing the user to tailor the search string. The following example uses a callback to produce a search string dependent on the filename: + +```js +const options = { + files: 'path/to/file', + from: (file) => RegExp(`${foo('SomePattern[A-Za-z-]+', file)}`, g);, + to: 'bar', +}; +``` + ### Using callbacks for `to` -As the `to` parameter is passed straight to the native [String replace method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace), you can also specify a callback. The following example uses a callback to convert matching strings to lowercase: +As the `to` parameter is passed to the native [String replace method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace), you can also specify a callback. The following example uses a callback to convert matching strings to lowercase: ```js const options = { @@ -202,6 +214,19 @@ const options = { }; ``` +This callback provides for an extra argument above the String replace method, which is the name of the file in which the replacement is being performed. The following example replaces the matched string with the filename: + +```js +const options = { + files: 'path/to/file', + from: /SomePattern[A-Za-z-]+/g, + to: (...args) => { + const file = args.pop(); + return file; + }, +}; +``` + ### Ignore a single file or glob ```js diff --git a/lib/helpers/make-replacements.js b/lib/helpers/make-replacements.js index 74334c4..80ae460 100644 --- a/lib/helpers/make-replacements.js +++ b/lib/helpers/make-replacements.js @@ -28,6 +28,11 @@ module.exports = function makeReplacements(contents, from, to, file) { //Make replacements from.forEach((item, i) => { + //`from` callback is called with a filename argument + //and returns string or regexp + if (typeof item === 'function') { + item = item(file); + } //Get replacement value let replacement = getReplacement(to, isArray, i); @@ -36,6 +41,7 @@ module.exports = function makeReplacements(contents, from, to, file) { } if (typeof replacement === 'function') { const original = replacement; + //`to` callback is called with an additional filename argument replacement = (...args) => original(...args, file); } diff --git a/lib/replace-in-file.spec.js b/lib/replace-in-file.spec.js index e6b4862..65418a6 100644 --- a/lib/replace-in-file.spec.js +++ b/lib/replace-in-file.spec.js @@ -82,6 +82,23 @@ describe('Replace in file', () => { }); }); + it('should pass file as an arg to a "from" function', done => { + replace({ + files: 'test1', + from: (file) => { + expect(file).to.equal('test1'); + return /re\splace/g; + }, + to: 'b' + }).then(() => { + const test1 = fs.readFileSync('test1', 'utf8'); + const test2 = fs.readFileSync('test2', 'utf8'); + expect(test1).to.equal('a b c'); + expect(test2).to.equal(testData); + done(); + }); + }); + it('should pass the match as first arg and file as last arg to a replacer function replace contents in a single file with regex', done => { replace({ files: 'test1', @@ -392,6 +409,23 @@ describe('Replace in file', () => { }); }); + it('should pass file as an arg to a "from" function', done => { + replace({ + files: 'test1', + from: (file) => { + expect(file).to.equal('test1'); + return /re\splace/g; + }, + to: 'b' + }, () => { + const test1 = fs.readFileSync('test1', 'utf8'); + const test2 = fs.readFileSync('test2', 'utf8'); + expect(test1).to.equal('a b c'); + expect(test2).to.equal(testData); + done(); + }); + }); + it('should pass the match as first arg and file as last arg to a replacer function replace contents in a single file with regex', done => { replace({ files: 'test1', @@ -708,6 +742,21 @@ describe('Replace in file', () => { expect(test2).to.equal(testData); }); + it('should pass file as an arg to a "from" function', function() { + replace.sync({ + files: 'test1', + from: (file) => { + expect(file).to.equal('test1'); + return /re\splace/g; + }, + to: 'b' + }); + const test1 = fs.readFileSync('test1', 'utf8'); + const test2 = fs.readFileSync('test2', 'utf8'); + expect(test1).to.equal('a b c'); + expect(test2).to.equal(testData); + }); + it('should pass the match as first arg and file as last arg to a replacer function replace contents in a single file with regex', function() { replace.sync({ files: 'test1',