diff --git a/README.md b/README.md index 113cd09..74ba183 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,31 @@ module.exports = { } ``` +### Strict mode replacement: + +You can set strict mode to ensure that the replacement was done: + +In your `webpack.config.js`: + +```javascript +module.exports = { + // ... + module: { + loaders: [ + { + test: /fileInWhichJQueryIsUndefined\.js$/, + loader: 'string-replace', + query: { + search: 'jQuery', + replace: 'window.$', + strict: true + } + } + ] + } +} +``` + ## Contributing: Feel free to open issues to propose stuff and participate. Pull requests are also welcome. diff --git a/index.js b/index.js index 10cfb6a..1a4c2e7 100644 --- a/index.js +++ b/index.js @@ -7,10 +7,21 @@ function processOptions(source, options) { options.search = new RegExp(options.search, options.flags); } - source = source.replace(options.search, options.replace); + newSource = source.replace(options.search, options.replace); + if (options.strict === true && newSource === source) { + throw new Error('Cannot replace ' + options.search + ' → ' + options.replace); + } } - return source; + if (options.strict === true && _.isUndefined(options.search)) { + throw new Error('Cannot replace: search option is not defined → ' + JSON.stringify(options)); + } + + if (options.strict === true && _.isUndefined(options.replace)) { + throw new Error('Cannot replace: replace option is not defined → ' + JSON.stringify(options)); + } + + return newSource; } module.exports = function (source) { @@ -20,6 +31,7 @@ module.exports = function (source) { if (_.isArray(options.multiple)) { options.multiple.forEach(function (suboptions) { + suboptions.strict = !_.isUndefined(suboptions.strict) ? suboptions.strict : options.strict; source = processOptions(source, suboptions); }); } else { diff --git a/test/index.test.js b/test/index.test.js index 4ff917f..1cfb5c4 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -8,36 +8,40 @@ var outputDirPath = path.join(__dirname, 'build'); var outputFileName = 'build.js'; var outputFilePath = path.join(outputDirPath, outputFileName); +function getTestWebPackConfig(loader) { + return { + entry: entryFilePath, + output: { + path: outputDirPath, + filename: outputFileName + }, + module: { + loaders: [ + loader + ] + } + } +} + describe('Webpack replace loader ...', function () { it('should replace with string search', function (done) { - webpack( + webpack(getTestWebPackConfig( { - entry: entryFilePath, - output: { - path: outputDirPath, - filename: outputFileName - }, - module: { - loaders: [ - { - test: /\.js$/, - loader: '__this-loader', - query: { - search: 'var value', - replace: 'var a' - } - } - ] + test: /\.js$/, + loader: '__this-loader', + query: { + search: 'var value', + replace: 'var a' } - }, + }), function (error, stats) { expect(error).to.equal(null); fs.readFile(outputFilePath, 'utf8', function (error, contents) { expect(error).to.equal(null); expect(contents).to.be.a('string'); - expect(contents.indexOf('var value')).to.equal(-1); - expect(contents.indexOf('var a')).to.not.equal(-1); + expect(contents).is.not.include('var value'); + expect(contents).is.include('var a'); done(); }); } @@ -45,35 +49,24 @@ describe('Webpack replace loader ...', function () { }); it('should replace with pattern search', function (done) { - webpack( + webpack(getTestWebPackConfig( { - entry: entryFilePath, - output: { - path: outputDirPath, - filename: outputFileName - }, - module: { - loaders: [ - { - test: /\.js$/, - loader: '__this-loader', - query: { - search: 'var VALUE = \'\.*\'', - replace: 'var a = \'\'', - flags: 'i' - } - } - ] + test: /\.js$/, + loader: '__this-loader', + query: { + search: 'var VALUE = \'\.*\'', + replace: 'var a = \'\'', + flags: 'i' } - }, + }), function (error, stats) { expect(error).to.equal(null); fs.readFile(outputFilePath, 'utf8', function (error, contents) { expect(error).to.equal(null); expect(contents).to.be.a('string'); - expect(contents.indexOf('var value')).to.equal(-1); - expect(contents.indexOf('var a = \'\'')).to.not.equal(-1); + expect(contents).is.not.include('var value'); + expect(contents).is.include('var a = \'\''); done(); }); } @@ -81,124 +74,244 @@ describe('Webpack replace loader ...', function () { }); it('should replace scoped', function (done) { - webpack( + webpack(getTestWebPackConfig( + { + test: /\.js$/, + loader: '__this-loader', + query: { + search: 'var value', + replace: 'var a' + } + }, + { + test: /bar\.js$/, + loader: '__this-loader', + query: { + search: 'var value', + replace: 'var bar' + } + }), + function (error, stats) { + expect(error).to.equal(null); + + fs.readFile(outputFilePath, 'utf8', function (error, contents) { + expect(error).to.equal(null); + expect(contents).to.be.a('string'); + expect(contents).is.not.include('var value'); + expect(contents).is.include('var a'); + expect(contents).is.include('var bar'); + done(); + }); + } + ); + }); + + it('should replace using multiple queries', function (done) { + webpack(getTestWebPackConfig( { - entry: entryFilePath, - output: { - path: outputDirPath, - filename: outputFileName - }, - module: { - loaders: [ + test: /\.js$/, + loader: '__this-loader', + query: { + multiple: [ { - test: /\.js$/, - loader: '__this-loader', - query: { - search: 'var value', - replace: 'var a' - } + search: 'var value', + replace: 'var a' }, { - test: /bar\.js$/, - loader: '__this-loader', - query: { - search: 'var value', - replace: 'var bar' - } + search: 'module.exports = value', + replace: 'module.exports = a' } ] } - }, + }), function (error, stats) { expect(error).to.equal(null); fs.readFile(outputFilePath, 'utf8', function (error, contents) { expect(error).to.equal(null); expect(contents).to.be.a('string'); - expect(contents.indexOf('var value')).to.equal(-1); - expect(contents.indexOf('var a')).to.not.equal(-1); - expect(contents.indexOf('var bar')).to.not.equal(-1); + expect(contents).is.not.include('var value'); + expect(contents).is.include('var a'); + expect(contents).is.not.include('module.exports = value'); + expect(contents).is.include('module.exports = a'); done(); }); } ); }); - it('should replace using multiple queries', function (done) { - webpack( + it('should replace using multiple queries as strings', function (done) { + webpack(getTestWebPackConfig( + { + test: /\.js$/, + loaders: [ + '__this-loader?search=var value&replace=var a', + '__this-loader?search=module.exports = value&replace=module.exports = a' + ] + }), + function (error, stats) { + expect(error).to.equal(null); + + fs.readFile(outputFilePath, 'utf8', function (error, contents) { + expect(error).to.equal(null); + expect(contents).to.be.a('string'); + expect(contents).is.not.include('var value'); + expect(contents).is.include('var a'); + expect(contents).is.not.include('module.exports = value'); + expect(contents).is.include('module.exports = a'); + done(); + }); + } + ); + }); + + it('should not throw error when cannot replace in single mode', function (done) { + webpack(getTestWebPackConfig( + { + test: /\.js$/, + loader: '__this-loader', + query: { + search: 'unexisting value', + replace: 'var a' + } + }), + function (error, stats) { + expect(error).to.equal(null); + + fs.readFile(outputFilePath, 'utf8', function (error, contents) { + expect(error).to.equal(null); + expect(contents).is.not.include('Cannot replace unexisting value → var a'); + done(); + }); + } + ); + }); + + it('should not throw error when cannot replace in single mode and strict is object', function (done) { + webpack(getTestWebPackConfig( + { + test: /\.js$/, + loader: '__this-loader', + query: { + search: 'unexisting value', + replace: 'var a', + strict: 'some string' + } + }), + function (error, stats) { + expect(error).to.equal(null); + + fs.readFile(outputFilePath, 'utf8', function (error, contents) { + expect(error).to.equal(null); + expect(contents).is.not.include('Cannot replace unexisting value → var a'); + done(); + }); + } + ); + }); + + it('should not throw error when cannot replace in multiple mode', function (done) { + webpack(getTestWebPackConfig( { - entry: entryFilePath, - output: { - path: outputDirPath, - filename: outputFileName - }, - module: { - loaders: [ + test: /\.js$/, + loader: '__this-loader', + query: { + multiple: [ { - test: /\.js$/, - loader: '__this-loader', - query: { - multiple: [ - { - search: 'var value', - replace: 'var a' - }, - { - search: 'module.exports = value', - replace: 'module.exports = a' - } - ] - } + search: 'unexisting value', + replace: 'var a', + strict: false } - ] + ], + strict: true } - }, + }), function (error, stats) { expect(error).to.equal(null); fs.readFile(outputFilePath, 'utf8', function (error, contents) { expect(error).to.equal(null); expect(contents).to.be.a('string'); - expect(contents.indexOf('var value')).to.equal(-1); - expect(contents.indexOf('var a')).to.not.equal(-1); - expect(contents.indexOf('module.exports = value')).to.equal(-1); - expect(contents.indexOf('module.exports = a')).to.not.equal(-1); + expect(contents).is.not.include('Cannot replace unexisting value → var a'); done(); }); } ); }); - it('should replace using multiple queries as strings', function (done) { - webpack( + it('should throw error when cannot replace in single strict mode', function (done) { + webpack(getTestWebPackConfig( + { + test: /\.js$/, + loader: '__this-loader', + query: { + search: 'unexisting value', + replace: 'var a', + strict: true + } + }), + function (error, stats) { + expect(error).to.equal(null); + + fs.readFile(outputFilePath, 'utf8', function (error, contents) { + expect(error).to.equal(null); + expect(contents).to.be.a('string'); + expect(contents).is.include('Cannot replace unexisting value → var a'); + done(); + }); + } + ); + }); + + it('should throw error when cannot replace in multiple strict mode', function (done) { + webpack(getTestWebPackConfig( { - entry: entryFilePath, - output: { - path: outputDirPath, - filename: outputFileName - }, - module: { - loaders: [ + test: /\.js$/, + loader: '__this-loader', + query: { + multiple: [ { - test: /\.js$/, - loaders: [ - '__this-loader?search=var value&replace=var a', - '__this-loader?search=module.exports = value&replace=module.exports = a' - ] + search: 'unexisting value', + replace: 'var a' } - ] + ], + strict: true } - }, + }), + function (error, stats) { + expect(error).to.equal(null); + + fs.readFile(outputFilePath, 'utf8', function (error, contents) { + expect(error).to.equal(null); + expect(contents).to.be.a('string'); + expect(contents).is.include('Cannot replace unexisting value → var a'); + done(); + }); + } + ); + }); + + it('should throw error when search is not defined in strict mode', function (done) { + webpack(getTestWebPackConfig( + { + test: /\.js$/, + loader: '__this-loader', + query: { + multiple: [ + { + replace: 'var a' + } + ], + strict: true + } + }), function (error, stats) { expect(error).to.equal(null); fs.readFile(outputFilePath, 'utf8', function (error, contents) { expect(error).to.equal(null); expect(contents).to.be.a('string'); - expect(contents.indexOf('var value')).to.equal(-1); - expect(contents.indexOf('var a')).to.not.equal(-1); - expect(contents.indexOf('module.exports = value')).to.equal(-1); - expect(contents.indexOf('module.exports = a')).to.not.equal(-1); + expect(contents).is.include('Cannot replace: search option is not defined'); done(); }); }