bodokaiser
bodokaiser

Reputation: 15742

Dynamic replace in regular expression scope

I need to rewrite some require paths in JavaScript source files:

Example (foo => ../../../foo/baz):

  1. var a = require('foo/a'); => var b = require('../../../foo/baz/a');
  2. var a = require('foo/../b'); => var b = require('../../../foo/baz/../b');

Note: This replacement will be done on a complete js source files. So require(' and ') must be used as delimiter!

So far we have figured out to use some setup like this:

var source = '';

source += "var a = require('foo/a');\n";
source += "var b = require('foo/../b');\n";
source += "console.log(a + b);";

var options = {
  'foo': '../../../foo/baz'
};

for (var key in options) {
  var regex = new RegExp('require[(](\"|\')' + key, 'g');

  source = source.replace(regex, "require('" + options[key]);
}

console.log(source);

Though above source code is working. I am not sure if this is save as I am just skipping the closing delimiter.

Upvotes: 1

Views: 519

Answers (2)

anubhava
anubhava

Reputation: 784998

This should work:

var source = '';
source += "var a = require('foo/a');\n";
source += "var b = require('foo/../b');\n";
source += "console.log(a + b);";

var options = {
  'foo': '../../../foo/baz'
};

for (var key in options) {
  var regex = new RegExp('(require)\\((["\'])(' + key + ')([^"\']*)\\2\\)', 'g');
  source = source.replace(regex, "$1('" + options[key] + "$4')");
}
console.log(source);

OUTPUT:

var a = require('../../../foo/baz/a');
var b = require('../../../foo/baz/../b');
console.log(a + b); 

Upvotes: 2

T.J. Crowder
T.J. Crowder

Reputation: 1074148

I think this does it:

str = str.replace(/require\((['"])([^'"]*)foo\/([^'"]*)(['"])/g, "require($1$2../../../foo/baz/$3$4");

Here's that regex live: http://regex101.com/r/bE5jI4

Explanation:

  • require matches the characters require literally (case sensitive)

  • \( matches the character ( literally

  • 1st Capturing group (['"])

    • ['"] match either ' or " literally
  • 2nd Capturing group ([^'"]*)

    • [^'"]* match a single character not present in the list below

      • Quantifier: Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
    • '" a single character in the list '" literally

  • foo matches the characters foo literally (case sensitive)

  • \/ matches the character / literally

  • 3rd Capturing group ([^'"]*)

    • [^'"]* match a single character not present in the list below

      • Quantifier: Between zero and unlimited times, as many times as possible, giving back as needed [greedy]

      • '" a single character in the list '" literally

  • 4th Capturing group (['"])

    • ['"] match ' or " literally

You may have to tweak it if there's optional whitespace before the opening quotes, or if your paths may contain ' or " characters. (In that latter case, you'll need two replacements, one when the wrapper quotes are ' and the other when they're ".)

Upvotes: 2

Related Questions