Skip to Content
  • Website
Codsen
  • Home
  • Open Source
  • Articles
  • About

prevOpen Source→easy-replacenext

easy-replace

Replace strings with optional lookarounds, but without regexes

Downloads per monthMIT Licenselibera manifesto
  • the top
  • PURPOSE
  • API — ER()
  • SIMPLE REPLAC…
  • MAYBES
  • NEGATIVE LOO…
  • POSITIVE LOOK…
  • NEGATIVE LOO…
  • REAL LIFE SCEN…

Purpose

This program can replace parts of string, while looking around.

ECMAScript has been evolving. For example, since 2018 ECMAScript has native negative lookbehindopens in a new tab regex assertions. It’s slowly catching up to the level of this program’s capabilities, but this program can still do more. For example, the latest ECMAScript can’t do both, lookahead and lookbehind assertions, while this package can.

In simple cases, it’s best to use native JS regexes. In more complex cases, this program can do things which regexes can’t.

API — er()

The main function er() is imported like this:

It’s a function which takes three input arguments:

Input argumentTypeObligatoryDescription
source
Type: String
Obligatory: yes
sourceStringyesOriginal string
opts
Type: Plain Object
Obligatory: yes
optsPlain ObjectyesObligatory Options Object.
replacement
Type: String
Obligatory: no
replacementStringnoReplace all the findings with this. If missing, library runs on delete mode.

The Obligatory Options Object has the following shape:

Obligatory Options Object’s keyValue’s typeObligatoryDescription
leftOutsideNot
Obligatory: no
leftOutsideNotString/Array of stringsnoEquivalent of regex negative lookbehind. This/these string(s) must not be present to the left of searchFor (plus any “maybe’s” strings, see below), in order for searchFor to be counted as “found”. This input’s contents are not replaced/deleted.
leftOutside
Obligatory: no
leftOutsideString/Array of stringsnoEquivalent of regex positive lookbehind. This/these string(s) must be present to the left of searchFor (plus any “maybe’s” strings, see below), in order for searchFor to be counted as “found”. This input’s contents are not replaced/deleted.
leftMaybe
Obligatory: no
leftMaybeString/ArraynoIf this is present on the left side of the searchFor, replace/delete it together with searchFor, but don’t fret if it’s not found.
searchFor
Obligatory: yes
searchForString onlyyesThe keyword to look for in the source_string
rightMaybe
Obligatory: no
rightMaybeString/Array of stringsnoIf this is present on the right side of the searchFor, replace/delete it together with searchFor, but don’t fret if it’s not found.
rightOutside
Obligatory: no
rightOutsideString/Array of stringsnoEquivalent of regex positive lookahead. This/these string(s) must be present to the right of searchFor (plus any “maybe’s” strings, see higher), in order for searchFor to be counted as “found”. This input’s contents are not replaced/deleted.
rightOutsideNot
Obligatory: no
rightOutsideNotString/Array of stringsnoEquivalent of regex negative lookahead. This/these string(s) must not be present to the right of searchFor (plus any “maybe’s” strings, see higher), in order for searchFor to be counted as “found”. This input’s contents are not replaced/deleted.
i
Obligatory: no
iPlain objectnoEach key mentioned above can be set to a Boolean true/false to optionally be case-insensitive. Same thing as i flag in regexes.

Function returns a string with all findings replaced.

Simple replace

An Example replacement recipe in words — replace all instances of x with 🦄.

Solution using this library:

import { er } from "easy-replace";
const res = er(
  "a x c x d",
  {
    leftOutsideNot: "",
    leftOutside: "",
    leftMaybe: "",
    searchFor: "x",
    rightMaybe: "",
    rightOutside: "",
    rightOutsideNot: "",
  },
  "🦄",
);
console.log(res);
//=> 'a 🦄 c 🦄 d'

Case insensitive setting — set each and every key you want to ignore the case via opts.i:

import { er } from "easy-replace";
const res = er(
  "a X c x d",
  {
    leftOutsideNot: "",
    leftOutside: "",
    leftMaybe: "",
    searchFor: "x",
    rightMaybe: "",
    rightOutside: "",
    rightOutsideNot: "",
    i: {
      searchFor: true,
    },
  },
  "🦄",
);
console.log(res);
//=> 'a 🦄 c 🦄 d'

Maybes

That’s optional surrounding strings to be replaced.

Example replacement recipe in words — Replace all instances of i. If there are 🐴 or 🦄 characters on the left, count them as part of found i and replace together as one thing. If there are 🐴 or 🦄 characters on the right, count them as part of found i and replace together as one thing.

Solution using this library:

import { er } from "easy-replace";
const res = er(
  "🐴i🦄 🐴i i🦄 i",
  {
    leftOutsideNot: "",
    leftOutside: "",
    leftMaybe: ["🐴", "🦄"],
    searchFor: "i",
    rightMaybe: ["🐴", "🦄"],
    rightOutside: "",
    rightOutsideNot: "",
  },
  "x",
);
console.log(res);
//=> 'x x x x'

By the way, notice, how the values except searchFor can be strings or arrays! For multiple replacement, list ofsearchFor values, you should use JavaScript loops.

Case-insensitive setting will cover more surroundings’ cases:

import { er } from "easy-replace";
const res = er(
  "Ai ib Aib i",
  {
    leftOutsideNot: "",
    leftOutside: "",
    leftMaybe: ["a", "z"],
    searchFor: "i",
    rightMaybe: ["y", "b"],
    rightOutside: "",
    rightOutsideNot: "",
    i: {
      leftMaybe: true,
    },
  },
  "x",
);
console.log(res);
//=> 'x x x x'

Negative lookahead

Used if you want to match something not followed by something else

Example replacement recipe in words — Replace all instances of 🦄, but only ones that don’t have c or d on the right.

Solution using this library:

import { er } from "easy-replace";
const res = er(
  "a🦄c x🦄x",
  {
    leftOutsideNot: "",
    leftOutside: "",
    leftMaybe: "",
    searchFor: "🦄",
    rightMaybe: "",
    rightOutside: "",
    rightOutsideNot: ["c", "d"],
  },
  "🐴",
);
console.log(res);
//=> 'a🦄c x🐴x'

Case insensitive setting will narrow-down the amount of findings/replacements:

import { er } from "easy-replace";
const res = er(
  "a🦄C x🦄x",
  {
    leftOutsideNot: "",
    leftOutside: "",
    leftMaybe: "",
    searchFor: "🦄",
    rightMaybe: "",
    rightOutside: "",
    rightOutsideNot: ["c", "d"],
    i: {
      rightOutsideNot: true,
    },
  },
  "🐴",
);
console.log(res);
//=> 'a🦄c x🐴x'

Positive lookbehind

Used when you want to match something that is preceded by something else.

For example, search for space characters that have another space right to their left, and delete them

Example replacement recipe in words — Replace all occurrences of space character, but only those that have another space character in front of them.

Solution using this library:

import { er } from "easy-replace";
const res = er(
  "zzzzz  zzzzzz zzzzzz",
  {
    leftOutsideNot: "",
    leftOutside: " ", // <- space
    leftMaybe: "",
    searchFor: " ", // <- space
    rightMaybe: "",
    rightOutside: "",
    rightOutsideNot: "",
  },
  "", // <- empty string
);
console.log(res);
//=> 'zzzzz zzzzzz zzzzzz'

Negative lookbehind

Used when you want to match something that is NOT preceded by something else.

For example, our <br /> sometimes look like <br/>. Replace all occurrences of /> with {{space character}}/> (disregard curly braces, it’s only to make it more visible here) if they are not preceded with space already:

Example replacement recipe in words — Add missing spaces before closing slashes on tags. Do not add spaces where they exist already.

Solution using this library:

import { er } from "easy-replace";
const res = er(
  "<br /><br/><br />",
  {
    leftOutsideNot: " ",
    leftOutside: "",
    leftMaybe: "",
    searchFor: "/>",
    rightMaybe: "",
    rightOutside: "",
    rightOutsideNot: "",
  },
  " />",
);
console.log(res);
//=> '<br /><br /><br />'

Real life scenario

Example replacement recipe in words — Add a missing semicolon and/or ampersand on &nbsp;, but only where they are missing.

Solution using this library:

import { er } from "easy-replace";
const res = er(
  "&nbsp; nbsp &nbsp nbsp;",
  {
    leftOutsideNot: "",
    leftOutside: "",
    leftMaybe: "&",
    searchFor: "nbsp",
    rightMaybe: ";",
    rightOutside: "",
    rightOutsideNot: "",
  },
  "&nbsp;",
);
console.log(res);
//=> '&nbsp; &nbsp; &nbsp; &nbsp;'

If you want to cover cases of random letter capitalisation of n, b, s and p, just set case-insensitive flag for searchFor:

import { er } from "easy-replace";
const res = er(
  "&nBsp; NBsp &nbSP NbsP;",
  {
    leftOutsideNot: "",
    leftOutside: "",
    leftMaybe: "&",
    searchFor: "nbsp",
    rightMaybe: ";",
    rightOutside: "",
    rightOutsideNot: "",
    i: {
      searchFor: true,
    },
  },
  "&nbsp;",
);
console.log(res);
//=> '&nbsp; &nbsp; &nbsp; &nbsp;'
↑ back to top
prev next

Copyright

All rights reserved © Roy Revelt 2026
All our open source packages are under MIT licenceopens in a new tab

Activities

🐛 See a bug? Raise an issueopens in a new tab
💘 Check out the Indiewebopens in a new tab and Libera manifestoopens in a new tab