Skip to content

Instantly share code, notes, and snippets.

@DavidJCobb
Created January 23, 2022 21:02
Show Gist options
  • Save DavidJCobb/d0249210961e0af6ae9f947c124d1248 to your computer and use it in GitHub Desktop.
Save DavidJCobb/d0249210961e0af6ae9f947c124d1248 to your computer and use it in GitHub Desktop.
Helper for defining regexes
//
// This file contains a JavaScript tag function to let you
// define regexes without needing to backslash-escape every
// forward slash in the regex text; good for URLs.
//
function regex(tag) {
return new RegExp(tag.raw, "i");
}
//
// Examples:
//
// // using a normal regex literal
// location.href.match(/https?\:\/\/(?:www\.)?nexusmods\.com\/(?:[^\/]+\/)?users\/(\d+)\/?(?:[#\?].*)?$/i);
//
// // using the function above on a template literal
// location.href.match(regex `https?://(?:www\.)?nexusmods\.com/(?:[^/]+/)?users/(\d+)/?(?:[#\?].*)?$`);
//
//
// Consider the following:
//
// // basic regex. lots of escaping for those forward slashes, since that's the
// // delimiter for regex literals... can we avoid doing that?
// location.href.match(/https?\:\/\/(?:www\.)?nexusmods\.com\/(?:[^\/]+\/)?users\/(\d+)\/?(?:[#\?].*)?$/i);
//
// // doesn't work: backslashes in template literals still act as escape sequences,
// // so `\.` is "\." is /./
// location.href.match(new RegExp(`https?://(?:www\.)?nexusmods\.com/(?:[^/]+/)?users/(\d+)/?(?:[#\?].*)?$`, "i"));
//
// // works, but doubling each backslash is awkward. bit easy to forget, too
// location.href.match(new RegExp("https?://(?:www\\.)?nexusmods\\.com/(?:[^/]+/)?users/(\\d+)/?(?:[#\\?].*)?$", "i"));
//
// // works, but is the longest syntax yet
// location.href.match(new RegExp(String.raw `https?://(?:www\.)?nexusmods\.com/(?:[^/]+/)?users/(\d+)/?(?:[#\?].*)?$`, "i"));
//
// // the custom "regex" tag function mimics the behavior of String.raw, and
// // passses the result to the RegExp constructor
// location.href.match(regex `https?://(?:www\.)?nexusmods\.com/(?:[^/]+/)?users/(\d+)/?(?:[#\?].*)?$`);
//
@micalevisk
Copy link

micalevisk commented Jan 24, 2022

cool 🔥

Another API that supports defining flags:

function regex(flags) {
  return (tag) => new RegExp(tag.raw, flags)
}

console.log(
  regex()`https?://(?:www\.)?nexusmods\.com/(?:[^/]+/)?users/(\d+)/?(?:[#\?].*)?$`
)
console.log(
  regex('ig')`https?://(?:www\.)?nexusmods\.com/(?:[^/]+/)?users/(\d+)/?(?:[#\?].*)?$`
)

or this another one:

function regex([_, pattern = _], flags) {
  return new RegExp(pattern, flags)
}

console.log(
  regex`https?://(?:www\.)?nexusmods\.com/(?:[^/]+/)?users/(\d+)/?(?:[#\?].*)?$`
)
console.log(
  regex`${'ig'}https?://(?:www\.)?nexusmods\.com/(?:[^/]+/)?users/(\d+)/?(?:[#\?].*)?$`
)

or even using the builder pattern like:

class RegExpBuilder {
  #flags = [];

  build(pattern) {
    return new RegExp(pattern.raw, this.#flags.join(''))
  }

  get g() {
    this.#flags[0] = 'g'
    return this
  }
  get i() {
    this.#flags[1] = 'i'
    return this
  }
  get m() {
    this.#flags[2] = 'm'
    return this
  }
  get u() {
    this.#flags[3] = 'u'
    return this
  }
  get y() {
    this.#flags[4] = 'y'
    return this
  }
}


console.log(
  new RegExpBuilder()
    .build`https?://(?:www\.)?nexusmods\.com/(?:[^/]+/)?users/(\d+)/?(?:[#\?].*)?$`
)

console.log(
  new RegExpBuilder()
    .i
    .g
    .build`https?://(?:www\.)?nexusmods\.com/(?:[^/]+/)?users/(\d+)/?(?:[#\?].*)?$`
)

outputs

/https?:\/\/(?:www\.)?nexusmods\.com\/(?:[^/]+\/)?users\/(\d+)\/?(?:[#\?].*)?$/
/https?:\/\/(?:www\.)?nexusmods\.com\/(?:[^/]+\/)?users\/(\d+)\/?(?:[#\?].*)?$/gi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment