Curtis
Curtis

Reputation: 2704

Cleaner approach to find and replace in NodeJS?

I'm currently attempting to read a file, pass the contents and multiple arrays to the function; see if any of it matches using regex and then replace & finally update.

The code I've put together which looks ugly and clumpy is this:

find_and_replace: function(file, ...items) {
    let str = _.clone(file);
    let valid = {};
    let do_escape = true;
    let hit;
    if (items != null ? items.length : void 0) {
        for (let i = 0, len = items.length; i < len; i++) {
            let obj = items[i];
            try {
                for (k in obj) {
                    let v = obj[k];
                    if (valid[k] == null) {
                        valid[k] = v;
                    }
                }
            } catch (error) { }
        }
        try {
            str = str.replace('/{{([\s\S]+?)}}/g', function(a, b) {
                if (hit = valid[b]) {
                    if (do_escape) {
                        return escape(hit);
                    } else {
                        return hit;
                    }
                }
                return '';
            });
        } catch (error) {
            console.log(error);
        }
    }
    return str;
},

The use of the function is as follows:

for (let _i = 0, _len = files.length; _i < _len; _i++) {
    let x = files[_i];
    if(x.includes('node_modules')) {
        continue;
    }
    builder.find_and_replace(builder.read_file(x), main_config, second_config);
    break;
}

The functionality of this "system" is to find any {{tag}} placeholders from within the file & replace with the correct key from inside the ...items combined array

I'd greatly appreciate if anyone could point me in the right direction to lower the amount of code required.

Upvotes: 0

Views: 62

Answers (2)

ponury-kostek
ponury-kostek

Reputation: 8070

When you use function rest parameters (...items), you always get an array under items so if (items != null ? items.length : void 0) is redundant.

items.reduce((all, obj) => ({...all, ...obj}), {}) creates single object from ...items

(string, [key, value]) => string.replace(new RegExp(`{{${key}}}`, "gi"), value) will find all occurrences of keys from object and replace them with values

const tr = (string, ...items) => "" + Object.entries(items.reduce((all, obj) => ({...all, ...obj}), {})).reduce((string, [key, value]) => string.replace(new RegExp(`{{${key}}}`, "gi"), value), string);

console.log(tr("{{h}} {{w}}!", {h:"Hello"}, {w:"world"}));

Upvotes: 0

Krzysztof Krzeszewski
Krzysztof Krzeszewski

Reputation: 6769

Some simplification may include using Object.entries or Array.reduce methods

function find_and_replace(file, ...items) {
  let str = _.clone(file);
  let do_escape = true;
  let hit;

  if (items != null ? items.length : void 0) {
    const valid = items.reduce((valid, obj) => {
      Object.entries(obj)
        .map([k, v] => {
          valid[key] = v;
        });
      return valid;
    }, {});

    try {
      str = str.replace('/{{([\s\S]+?)}}/g', (a, b) => hit === valid[b] ? (do_escape ? escape(hit) : hit) : '');
    } catch (error) {
      console.log(error);
    }
  }
  return str;
},

Upvotes: 2

Related Questions