DEV Community

Cover image for The more-proper introduction to ReX.js
Arek Nawo
Arek Nawo

Posted on

The more-proper introduction to ReX.js

For starters

ReX.js (a shortcut from Regular eXpressions) is a library for (obviously) creating regexps. By its functional API, you can easily build regexps with a set of chainable methods. It allows you to build complex & long regexps with more readability & option to easily write comments aside. Let me show you a trivia example taken from the "README" file of the repo:

import { Matcher } from '@areknawo/rex'

const expr = new Matcher()
.find('Reg')
.whitespace()
.capture((expr) => {
  expr.find('Exp')
}).test('Reg Exp'); //true
Enter fullscreen mode Exit fullscreen mode

Is it a joke?

Before you'll shout at me about why not write something just like this:

/Reg Exp/.test('Reg Exp') // true
Enter fullscreen mode Exit fullscreen mode

Just wait a moment. As I written ReX.js is written to create complex regexps faster and easier. If you don't agree with me then how about this:

// IP Address verification regexp taken from https://regexr.com
// Long regex coming!
        /\b(?:(?:2(?:[0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9])\.){3}(?:(?:2([0-4][0-9]|5[0-5])|[0-1]?[0-9]?[0-9]))\b/ig
Enter fullscreen mode Exit fullscreen mode

How about the reliability of this creation? Just please - don't miss the point - regexps are awesome and extremely useful tool and it's definitely worth learning instead of the whole API of ReX.js. It's not the purpose of ReX.js to replace regexp. Its purpose is to provide tool for those already knowing regexps syntax for better development experience. That's why ReX.js methods are named directly after the names of certain regexp constructions. So let's rewrite the regexp monstrosity above using ReX.js!

import { Matcher } from '@areknawo/rex'

const expr = new Matcher()
  .wordBoundary()
  .capture((expr) => {
    expr
      .capture((expr) => {
        expr
          .find('2')
          .capture((expr) => {
            expr
              .range(0, 4)
              .range(0, 9).or('5')
              .range(0, 5)
          }).negate() // negate method is just negating last operation
          .or((expr) => {
            expr.range(0, 1)
          }).optional()
          .range(0, 9).optional()
          .range(0, 9)
      }).negate() // so it means just a non-capturing group (logical)
      .find('.')
  }).negate() // negate also works with other operations that can be negated
  .quantify(3, 3)
  .capture((expr) => {
    expr
      .capture((expr) => {
        expr
          .find('2')
          .capture((expr) => {
            expr
              .range(0, 4)
              .range(0, 9).or('5')
              .range(0, 5)
          }).or((expr) => {
            expr.range(0, 1)
          }).optional()
          .range(0, 9).optional()
          .range(0, 9)
      })
  })
  .wordBoundary()
  .i().g();
expr.test('123.123.123.256') // false
expr.test('123.123.123.123') // true
Enter fullscreen mode Exit fullscreen mode

Whoa! That's pretty long actually but much, much more readable (at least IMHO). Remember that the creation above is just a literal copy of given regex. Using ReX.js API it can be shortened a bit.

Alright... I'm interested

That's not all ReX.js is written in TypeScript (I know - misleading postfix) so it provides in-editor autocompletion for all of its methods.

Final

If I was able to make you interested in ReX.js feel free to check the official documentation, Github Repo and Codesandbox playground!

Top comments (0)