From 5793b26b7a02678c97745c043a5b4754bc19b7bf Mon Sep 17 00:00:00 2001 From: Rabbani Date: Mon, 6 May 2019 18:32:46 -0400 Subject: [PATCH 1/3] Added ability to use suffixes in match strings For example, replace matches like @@env.css.darkStyle@@ instead of just @@env.css.darkStyle. This is needed to avoid erroneously substituting a partial match like @@env.css.darkStyle_header with the @@env.css.darkStyle when darkStyle_header is not found in json. --- src/plugins.js | 194 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 175 insertions(+), 19 deletions(-) diff --git a/src/plugins.js b/src/plugins.js index 618a522..83322f8 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -9,33 +9,189 @@ // dependencies -var path = require('path'); +var _ = require('lodash'); +var plugins = require('./plugins'); -// private +// took from MDN +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions -// var dir = path.join(__dirname, '/plugins'); +var escapeRegExp = function (string) { + return string.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1"); +}; -var plugins = [ - require('./plugins/yaml'), - require('./plugins/cson'), - require('./plugins/json') -]; +var getPatterns = function (applause) { + var opts = applause.options; + // shallow patterns + var patterns = _.chain(opts.patterns) + .clone() + .compact() + .filter(function (pattern) { + return !_.isEmpty(pattern); + }) + .value(); + // backward compatibility + var variables = opts.variables; + if (!_.isEmpty(variables)) { + patterns.push({ + json: variables + }); + } + // process + for (var i = patterns.length - 1; i >= 0; i -= 1) { + var pattern = patterns[i]; + // plugins + plugins.forEach(function (plugin) { + if (plugin.match(pattern, opts) === true) { + plugin.transform(pattern, opts, function (items) { + if (items instanceof Error) { + throw items; + } else { + // store transformed pattern in context + pattern = items; + } + }); + } else { + // plugin doesn't apply + } + }); + // convert to array + if (!_.isArray(pattern)) { + pattern = [pattern]; + } + // link with pattern with original source + pattern.forEach(function (pattern) { + pattern.source = patterns[i]; + }); + // attach index + Array.prototype.splice.apply(patterns, [i, 1].concat(pattern)); + } + if (opts.preserveOrder !== true) { + // only sort non regex patterns (prevents replace issues like head, header) + patterns.sort(function (a, b) { + var x = a.match; + var y = b.match; + if (_.isString(x) && _.isString(y)) { + return y.length - x.length; + } else if (_.isString(x)) { + return -1; + } + return 1; + }); + } + return patterns; +}; -// took plugins from folder +// applause -/* require('fs').readdirSync(dir).forEach(function (file) { - if (file.match(/.+\.js/g) !== null && file !== 'index.js') { - var plugin = require(path.join(dir, file)); - plugins.push(plugin); +var Applause = function (opts) { + this.options = _.defaults(opts, { + patterns: [], + prefix: opts.usePrefix === false ? '' : '@@', + usePrefix: true, + preservePrefix: false, + delimiter: '.', + preserveOrder: false, + detail: false, + suffix: opts.useSuffix === true ? '@@' : '', + useSuffix: false + }); +}; + +Applause.prototype.replace = function (content, process) { + var opts = this.options; + // prevent null + content = content || ''; + // prepare patterns + var patterns = getPatterns(this); + var detail = []; + var total_count = 0; + // iterate over each pattern and make replacement + patterns.forEach(function (pattern, i) { + // filter empty patterns + var match = pattern.match; + // support replace flag too + var replacement = pattern.replacement; + if (replacement === undefined || replacement === null) { + replacement = pattern.replace; + } + var source = pattern.source; + var expression = false; + // match check + if (match !== undefined && match !== null) { + if (_.isRegExp(match)) { + expression = true; + } else if (_.isString(match)) { + if (match.length > 0) { + match = new RegExp(opts.prefix + escapeRegExp(match) + opts.suffix, 'g'); + } else { + // empty match + return; + } + } else { + throw new Error('Unsupported match type (RegExp or String expected).'); + } + } else { + throw new Error('Match attribute expected in pattern definition.'); + } + // replacement check + if (replacement !== undefined && replacement !== null) { + if (!_.isFunction(replacement)) { + if (!_.isString(replacement)) { + // transform object to string + replacement = JSON.stringify(replacement); + } + if (expression === false) { + // escape dollar sequences in easy mode + replacement = replacement.replace(/\$/g, '$$$'); + // preserve prefix + if (opts.preservePrefix === true) { + replacement = opts.prefix + replacement; + } + } + } else { + // replace using function return value + replacement = function () { + var args = Array.prototype.slice.call(arguments); + return pattern.replacement.apply(this, args.concat(process || [])); + }; + } + } else { + throw new Error('Replacement attribute expected in pattern definition.'); + } + // replace logic + var count = (content.match(match) || []).length; + if (count > 0) { + // update content + content = content.replace(match, replacement); + // save detail data + detail.push({ + source: pattern.source, + count: count + }); + total_count += count; + } + }); + if (detail.length === 0) { + content = false; + } + if (opts.detail === true) { + return { + content: content, + detail: detail, + count: total_count + }; } -}); */ + return content; +}; + +// static -// priority sort +Applause.create = function (opts) { + return new Applause(opts); +}; -plugins.sort(function (a, b) { - return (a.priority || 0) - (b.priority || 0); -}); +Applause.VERSION = require('../package.json').version; // expose -module.exports = plugins; +module.exports = Applause; From d6110076173704e26ae294e6c9f9351d9e6f145e Mon Sep 17 00:00:00 2001 From: Rabbani Date: Mon, 6 May 2019 18:39:20 -0400 Subject: [PATCH 2/3] wrong file updated, reverting to original --- src/plugins.js | 194 +++++-------------------------------------------- 1 file changed, 19 insertions(+), 175 deletions(-) diff --git a/src/plugins.js b/src/plugins.js index 83322f8..618a522 100644 --- a/src/plugins.js +++ b/src/plugins.js @@ -9,189 +9,33 @@ // dependencies -var _ = require('lodash'); -var plugins = require('./plugins'); +var path = require('path'); -// took from MDN -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions +// private -var escapeRegExp = function (string) { - return string.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1"); -}; +// var dir = path.join(__dirname, '/plugins'); -var getPatterns = function (applause) { - var opts = applause.options; - // shallow patterns - var patterns = _.chain(opts.patterns) - .clone() - .compact() - .filter(function (pattern) { - return !_.isEmpty(pattern); - }) - .value(); - // backward compatibility - var variables = opts.variables; - if (!_.isEmpty(variables)) { - patterns.push({ - json: variables - }); - } - // process - for (var i = patterns.length - 1; i >= 0; i -= 1) { - var pattern = patterns[i]; - // plugins - plugins.forEach(function (plugin) { - if (plugin.match(pattern, opts) === true) { - plugin.transform(pattern, opts, function (items) { - if (items instanceof Error) { - throw items; - } else { - // store transformed pattern in context - pattern = items; - } - }); - } else { - // plugin doesn't apply - } - }); - // convert to array - if (!_.isArray(pattern)) { - pattern = [pattern]; - } - // link with pattern with original source - pattern.forEach(function (pattern) { - pattern.source = patterns[i]; - }); - // attach index - Array.prototype.splice.apply(patterns, [i, 1].concat(pattern)); - } - if (opts.preserveOrder !== true) { - // only sort non regex patterns (prevents replace issues like head, header) - patterns.sort(function (a, b) { - var x = a.match; - var y = b.match; - if (_.isString(x) && _.isString(y)) { - return y.length - x.length; - } else if (_.isString(x)) { - return -1; - } - return 1; - }); - } - return patterns; -}; +var plugins = [ + require('./plugins/yaml'), + require('./plugins/cson'), + require('./plugins/json') +]; -// applause +// took plugins from folder -var Applause = function (opts) { - this.options = _.defaults(opts, { - patterns: [], - prefix: opts.usePrefix === false ? '' : '@@', - usePrefix: true, - preservePrefix: false, - delimiter: '.', - preserveOrder: false, - detail: false, - suffix: opts.useSuffix === true ? '@@' : '', - useSuffix: false - }); -}; - -Applause.prototype.replace = function (content, process) { - var opts = this.options; - // prevent null - content = content || ''; - // prepare patterns - var patterns = getPatterns(this); - var detail = []; - var total_count = 0; - // iterate over each pattern and make replacement - patterns.forEach(function (pattern, i) { - // filter empty patterns - var match = pattern.match; - // support replace flag too - var replacement = pattern.replacement; - if (replacement === undefined || replacement === null) { - replacement = pattern.replace; - } - var source = pattern.source; - var expression = false; - // match check - if (match !== undefined && match !== null) { - if (_.isRegExp(match)) { - expression = true; - } else if (_.isString(match)) { - if (match.length > 0) { - match = new RegExp(opts.prefix + escapeRegExp(match) + opts.suffix, 'g'); - } else { - // empty match - return; - } - } else { - throw new Error('Unsupported match type (RegExp or String expected).'); - } - } else { - throw new Error('Match attribute expected in pattern definition.'); - } - // replacement check - if (replacement !== undefined && replacement !== null) { - if (!_.isFunction(replacement)) { - if (!_.isString(replacement)) { - // transform object to string - replacement = JSON.stringify(replacement); - } - if (expression === false) { - // escape dollar sequences in easy mode - replacement = replacement.replace(/\$/g, '$$$'); - // preserve prefix - if (opts.preservePrefix === true) { - replacement = opts.prefix + replacement; - } - } - } else { - // replace using function return value - replacement = function () { - var args = Array.prototype.slice.call(arguments); - return pattern.replacement.apply(this, args.concat(process || [])); - }; - } - } else { - throw new Error('Replacement attribute expected in pattern definition.'); - } - // replace logic - var count = (content.match(match) || []).length; - if (count > 0) { - // update content - content = content.replace(match, replacement); - // save detail data - detail.push({ - source: pattern.source, - count: count - }); - total_count += count; - } - }); - if (detail.length === 0) { - content = false; - } - if (opts.detail === true) { - return { - content: content, - detail: detail, - count: total_count - }; +/* require('fs').readdirSync(dir).forEach(function (file) { + if (file.match(/.+\.js/g) !== null && file !== 'index.js') { + var plugin = require(path.join(dir, file)); + plugins.push(plugin); } - return content; -}; - -// static +}); */ -Applause.create = function (opts) { - return new Applause(opts); -}; +// priority sort -Applause.VERSION = require('../package.json').version; +plugins.sort(function (a, b) { + return (a.priority || 0) - (b.priority || 0); +}); // expose -module.exports = Applause; +module.exports = plugins; From b2c42fd465b2bb3e24d1040c486bc64d56c13f47 Mon Sep 17 00:00:00 2001 From: Rabbani Date: Mon, 6 May 2019 18:42:12 -0400 Subject: [PATCH 3/3] Added ability to use suffixes in match strings It's necessary to use suffix sometimes when there are unintended partial matches due to missing json keys in the pattern json object. For example, be able to replace matches like @@env.css.darkStyle@@ instead of just @@env.css.darkStyle. This is needed to avoid erroneously substituting a partial match like @@env.css.darkStyle_header with the @@env.css.darkStyle match when darkStyle_header is not found in the pattern json. 5793b26 --- src/applause.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/applause.js b/src/applause.js index 8d3e915..83322f8 100644 --- a/src/applause.js +++ b/src/applause.js @@ -90,7 +90,10 @@ var Applause = function (opts) { usePrefix: true, preservePrefix: false, delimiter: '.', - preserveOrder: false + preserveOrder: false, + detail: false, + suffix: opts.useSuffix === true ? '@@' : '', + useSuffix: false }); }; @@ -119,7 +122,7 @@ Applause.prototype.replace = function (content, process) { expression = true; } else if (_.isString(match)) { if (match.length > 0) { - match = new RegExp(opts.prefix + escapeRegExp(match), 'g'); + match = new RegExp(opts.prefix + escapeRegExp(match) + opts.suffix, 'g'); } else { // empty match return; @@ -162,23 +165,23 @@ Applause.prototype.replace = function (content, process) { content = content.replace(match, replacement); // save detail data detail.push({ - match: match, - replacement: replacement, source: pattern.source, count: count }); total_count += count; } }); - // FIXME: always return detailed result if (detail.length === 0) { content = false; } - return { - content: content, - detail: detail, - count: total_count - }; + if (opts.detail === true) { + return { + content: content, + detail: detail, + count: total_count + }; + } + return content; }; // static @@ -187,7 +190,7 @@ Applause.create = function (opts) { return new Applause(opts); }; -Applause.version = require('../package.json').version; +Applause.VERSION = require('../package.json').version; // expose