npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

rexx

v0.0.2

Published

A human-friendly regex library with structured syntax and variable support.

Downloads

2

Readme

🦖 Rexx

Rexx: A human-friendly regex library with structured syntax and variable support.

Introduction

  • Human readable.
  • Structured syntax.
  • Support for variables and comments.
  • Easily build regular expression patterns.

Installation

# Install rexx using npm
npm install rexx

# using Yarn
yarn add rexx

# using pnpm 
pnpm install rexx

Usage

Browser

<script src="dist/rexx.js"></script>
<!--or via CDN-->
<script src="https://www.jsdelivr.com/package/npm/rexx"></script>

Node.js

// CommonJS
const Rexx = require('rexx')
// or ES6 Modules
import Rexx from 'rexx'

Examples

Semantic Versioning

Semantic Versioning (SemVer) follows the pattern major.minor.patch, where major, minor, and patch are non-negative integers.

const regExp = rexx(`
    digits = { one_or_more { digit } }

    semVer = {
        begin
        optional {'v'}
        group('major') { digits }
        '.'
        group('minor') { digits }
        '.'
        group('patch') { digits }
        end
    }
    `
console.log(regExp)
// {
//     digits: /\d+/,
//     semVer: /^v?(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)$/,
//     default: /(?:)/,
// }
regExp.semVer.test('v1.2.3')     // true

URL

A URL contains several components - the protocol, host, path, query, and hash.

http://www.example.com/foo/bar.html?a=b&c=d#hash

const urlRegexp = rexx(`
    protocol = { optional { one_of{'http', 'https'} } }           // http
    host  = { one_or_more { except{'/'} } }                       // www.example.com
    path  = { loop(0..) {'/', one_or_more { except{'/?#'} } } }   // /foo/bar.html
    query = { optional {'?', one_or_more { except{'#'} } } }      // ?a=b&c=d
    hash  = { optional {'#', one_or_more { any } } }              // #hash
    url   = {
        group('protocol'){ protocol }
        optional{'://'}
        group('host'){ host }
        group('path'){ path }
        group('query'){ query }
        group('hash'){ hash }
    }
`)
console.log(urlRegexp.url)
// /(?<protocol>(?:(?:http|https))?)(?:\:\/\/)?(?<host>(?:[^\/])+)(?<path>(?:\/(?:[^\/\?#])+)*)(?<query>(?:\?(?:[^#])+)?)(?<hash>(?:#.+)?)/
urlRegexp.url.test('http://www.example.com/foo/bar.html?a=b&c=d#hash') // true

Password validation

The password must contain characters from at least 3 of the following 4 rules: upper case, lower case, numbers, non-alphanumeric.

const pwdRegexp = rexx(`
    lower = { one_of {range {'a', 'z'} } }
    upper = { one_of {range {'A', 'Z'} } }
    _any  = { loop(0..) { any } }
    hasLower = { followed_by { _any, lower } }
    hasUpper = { followed_by { _any, upper } }
    hasDigit = { followed_by { _any, digit } }
    hasSymbol = { followed_by { _any, non_word } }
    password = {
        begin
        one_of {
            {hasLower, hasUpper, hasDigit}
            {hasLower, hasUpper, hasSymbol}
            {hasLower, hasDigit, hasSymbol}
            {hasUpper, hasDigit, hasSymbol}
        }
        loop(8..){ any }
        end
    }
`)
console.log(pwdRegexp.password)
// /^(?:(?=.*[a-z])(?=.*[A-Z])(?=.*\d)|(?=.*[a-z])(?=.*[A-Z])(?=.*\W)|(?=.*[a-z])(?=.*\d)(?=.*\W)|(?=.*[A-Z])(?=.*\d)(?=.*\W)).{8,}$/

Cheat sheet

| Rexx | RegExp | | Rexx | RegExp | |-------------------------------------|-----------------|----|----------------|-----------------| | one_of { 'a', 'b', 'c' } | [abc] | | word | \w | | one_of { 'foo', 'bar' } | foo|bar | | non_word | \W | | one_of { range {'a', 'z'} } | [a-z] | | digit | \d | | optional {'a'} / loop(0..) {'a'} | a? | | non_digit | \D | | optional {'abc'} | (?:abc)? | | whitespace | \s | | loop(0..) {'a'} | a* | | non_whitespace | \S | | one_or_more {'a'} / loop(1..) {'a'} | a+ | | boundary | \b | | loop(2) {'a'} | a{2} | | non_boundary | \B | | loop(2..3) {'a'} | a{2,3} | | chinese | [\u4e00-\u9fa5] | | except {'a'} | [^a] | | '\d' | \d | | except { range {'a', 'z'} } | [^a-z] | | '\uffff' | \uffff | | group{'foo'} | (foo) | | newline | \n | | group('year'){'2024'} | (?<year>2024) | | tab | \t | | ref {1} | \1 | | any | . |
| ref {year} | \k<year> | | begin | ^ | | followed_by {'a'} | (?=a) | | end | $ | | not_followed_by {'a'} | (?!a) | | global | g | | preceded_by {'a'} | (?<=) | | ignore_case | i | | not_preceded_by {'a'} | (?<!) | | multiline | m | | loop (1..) {'a'} lazy | a+? |

Syntax

' ... '

Matches exact characters.

Example: 'foo' in Rexx translates to foo in regex.

one_of

Syntax: one_of { pattern, pattern, ... }

Matches any one of the listed alternatives. Commas are optional.

Example: one_of { 'foo', 'bar' } translates to foo|bar in regex.

range

Syntax: range { 'start', 'end' }

Creates a range of characters.

Example: one_of { range { 'a', 'z' } } translates to [a-z].

optional

Syntax: optional { pattern }

Marks the pattern as optional.

Example: optional { 'foo' } translates to foo?.

loop

Syntax: loop(from..to) { pattern } or loop(times) { pattern }

Specifies a pattern to repeat.

Example: loop(1..3) { 'a' } translates to a{1,3}.

except

Syntax: except { pattern }

Matches any character except the given pattern.

Example: except { 'a' } becomes [^a].

group

Syntax: group { pattern } or group('name') { pattern }

Capturing group is assigned a name or sequential number.

Example: group { 'abc' } or group('name'){ 'abc' } translates to (abc) or (?<name>abc).

ref

Syntax: ref { 1 } or ref { 'name' }

References a previously matched group.

Example: ref { 1 } or ref { 'name' } translates to \1 or \k<name>.

followed_by

Syntax: followed_by { 'pattern' }

Asserts that what follows the current position is the specified pattern.

Example: followed_by { 'a' } translates to (?=a).

not_followed_by

Syntax: not_followed_by { 'pattern' }

Asserts that what follows the current position is not the specified pattern.

Example: not_followed_by { 'a' } translates to (?!a) .

preceded_by

Syntax: preceded_by { 'pattern' }

Asserts that what precedes the current position is the specified pattern.

Example: preceded_by { 'a' } translates to (?<=a).

not_preceded_by

Syntax: not_preceded_by { 'pattern' }

Asserts that what precedes the current position is not the specified pattern.

Example: not_preceded_by { 'a' } translates to (?<!a).

Comments

Syntax: // This is a comment

Adds a comment to the pattern for explanation.

Variable

  • To define a variable in a pattern, use variable_name = { pattern }.
  • All variables must be declared before they are used.
  • Once a variable is declared, you can reference it in your pattern using its name.
  • Variable declarations can also include flags that alter the behavior of the regex. There are three kinds of flags: ignore_case, global, multiline.

Similar packages

Rexx

digits = { one_or_more { digit } }

semVer = {
    begin
    optional {'v'}
    group('major') { digits }
    '.'
    group('minor') { digits }
    '.'
    group('patch') { digits }
    end
}
// /^v?(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)$/

melody

<start>;
option of "v";
capture major {
  some of <digit>;
}
".";
capture minor {
  some of <digit>;
}
".";
capture patch {
  some of <digit>;
}
<end>;
// /^v?(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)$/

megic-regexp

import { createRegExp, maybe, oneOrMore, exactly, digit } from 'magic-regexp'

const regExp = createRegExp(
    maybe('v')
    .and(oneOrMore(digit).groupedAs('major'))
    .and(exactly('.'))
    .and(oneOrMore(digit).groupedAs('minor'))
    .and(exactly('.'))
    .and(oneOrMore(digit).groupedAs('patch'))
    .at.lineStart()
    .at.lineEnd()
)
// /^v?(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)$/

JSVerbalExpressions

const regExp = VerEx()
    .startOfLine()
    .maybe('v')
    .beginCapture()
        .digit().oneOrMore()
    .endCapture()
    .then('.')
    .beginCapture()
        .digit().oneOrMore()
    .endCapture()
    .then('.')
    .beginCapture()
        .digit().oneOrMore()
    .endCapture()
    .endOfLine()
    // /^(?:v)?(\d+)(?:\.)(\d+)(?:\.)(\d+)$/

Contributing

Contributions to this project are welcome.

Clone and fork:

git clone https://github.com/yyytcool/rexx.git

License

Apache License.

Copyright (c) 2024-present, yyyt