UNPKG

regex-replace-loader

Version:

A webpack loader to replace values in files using regex

137 lines (117 loc) 3.09 kB
'use strict' var loaderUtils = require('loader-utils') var NAME = 'Regex Replace Loader' /** * @typedef {Object} LoaderOptions * @property {string|RegExp} regex * @property {string} [flags] * @property {string|((match: RegExpExecArray) => string)} value * @property {LoaderOptions[]} [stages] */ /** * The Regex Replace Loader. * * Replace values from the source via a regular expression. * * @param {string} source * @returns {string} */ function regexReplaceLoader(source) { var options = getOptions(this) var stages = Array.isArray(options.stages) ? options.stages : [options] var result = source stages.forEach(function (stage) { var regex = getRegex(stage.regex, stage.flags) result = replace(regex, result, stage) }) return 'module.exports = ' + JSON.stringify(result) } /** * Return the options object. * * @param {LoaderContext} context * @returns {LoaderOptions} */ function getOptions(context) { return loaderUtils.getOptions(context) } /** * Return the type of an object as a string. * * @param {any} object * @returns {string} */ function typeOf(object) { return Object.prototype.toString.call(object).slice(8, -1) } /** * Transform regex into a RegExp if it isn't one already. * * @param {any} regex * @param {string} flags * @returns {RegExp} */ function getRegex(regex, flags) { var result = typeOf(regex) === 'String' ? new RegExp(regex, flags || '') : regex if (typeOf(result) !== 'RegExp') { throw new Error( NAME + ': option "regex" must be a string or a RegExp object') } return result } /** * If 'value' is a function, return a match function; * otherwise return the original value. * * @param {any} value * @returns {any} */ function getValueOrMatchFn(value) { if (typeof value === 'function') { return getMatchFn(value) } if (typeof value !== 'string') { throw new Error( NAME + ': option "value" must be a string or a function') } return value } /** * Return a function for use with string.replace that converts that * function's arguments into a RegExpMatchArray and calls the * value function. * * @param {(match: RegExpMatchArray) => string} valueFn * @returns {(m: string, ...args: string[], i: number, s: string) => string} */ function getMatchFn(valueFn) { return function () { var len = arguments.length // Create a RegExp match object. var match = Array.prototype.slice.call(arguments, 0, -2) .reduce(function (map, g, i) { map[i] = g return map }, {index: arguments[len - 2], input: arguments[len - 1]}) // Call the original function. return valueFn(match) } } /** * Execute a replace operation and return the modified source. * * @param {RegExp} regex * @param {string} source * @param {LoaderOptions} options * @returns {string} */ function replace(regex, source, options) { var valueOrFn = getValueOrMatchFn(options.value) source.replace(regex, function () { return '' }) return source.replace(regex, valueOrFn) } module.exports = regexReplaceLoader