GithubNPM

RXP

A descriptive constructor for regular expressions

RXP is a small library that provides a constructor for regular expressions, providing the following benefits

  • Plain English Descriptions

    Replace cryptic regex with intuitive descriptions inspired by the Mocha / Chai syntax
  • Modular and Composable Regex Components

    Build regex as small, manageable pieces and combine or extend them as needed
  • Automatic Escaping of Characters

    Write regex with a WYSIWYG mindset and let RXP handle escaping of special characters for you
  • Accepts Strings, Regex, or Other RXP Units

    Highly flexible constructor that can format strings or accept other regex or RXP constructors - RXP will reconcile everything behind the scenes
  • Automatically Formats Regex Variables

    Define a regex variable once, store it as an old-fashioned JavaScript variable, and insert it wherever you want - RXP will reconfigure it to work correctly, regardless of positioning

    Examples

  • Matching a specific email pattern

    Target: JRose@support.company.net

    // original regex:
    const emailMatch = 
        /[A-Z]{2}[a-z]+@(?:support\.)?company\.net/
            
    // RXP version:
    const emailMatch = init(
        anyUpperCase.occurs(2),
        anyLowerCase.occursOnceOrMore,
        "@",
        optional("support."),
        "company.net"
      ).construct()
  • Matching someone with a specific family name

    Target: Jeff Rose

    // original regex:
    const nameMatch = 
        /\w+?\s[rR]ose/
            
    // RXP version:
    const nameMatch = init(
        anyLetter.occursOnceOrMore,
        " ",
        upperOrLowerCase("r"), // either("r", "R") is equivalent
        "ose"
      ).construct()
  • Matching a US zip code after the state abbreviation

    Target: VA, 12345-6789

    // original regex:
    const zipCodeMatch = 
        /(?<=\w{2},\s)\d{5}(?:(?:(?:-|\s)\d{4})|(?:\d{4}))?/
            
    // RXP version:
    const stateAbbreviation = init(anyUpperCase.occurs(2), ", ")
    const zipCode = anyDigit.occurs(5)
    const extendedZipCode = anyDigit.occurs(4)
    const extendedZipWithSpace = init(either("-", " "), extendedZipCode)
            
    const zipCodeMatch = init(
        zipCode,
        either(extendedZipCode, extendedZipWithSpace).isOptional
      )
      .precededBy(stateAbbreviation)
      .construct()
  • Matching a phone number with extension

    Target: (123) 456-7899 ext.: 9999

    // original regex:
    const phoneMatch = 
        /\(?\d{3}\)?(?:-|\s)?\d{3}(?:-|\s)?\d{4}(?:\s[eE]xt.:\s\d{2,4})?/g
            
    // RXP version:
    const areaCode = init(
        optional("("),
        anyDigit.occurs(3),
        optional(")"),
        either("-", " ").isOptional // optional(either("-", " ")) also works
      )
            
    const firstThreeDigits = areaCode
    const lastFourDigits = anyDigit.occurs(4)
    const extension = optional(
        " ",
        upperOrLowerCase("e"),
        "xt.: ",
        anyDigit.occursBetween(2, 4)
      )
            
    const phoneMatch = init(
        areaCode,
        firstThreeDigits,
        lastFourDigits,
        extension
      ).construct("g")