https://github.com/fabrix-app/regexdot
Small utility to param match dot syntax strings
https://github.com/fabrix-app/regexdot
Last synced: over 1 year ago
JSON representation
Small utility to param match dot syntax strings
- Host: GitHub
- URL: https://github.com/fabrix-app/regexdot
- Owner: fabrix-app
- License: mit
- Created: 2019-10-23T17:42:03.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-01-24T00:43:11.000Z (over 3 years ago)
- Last Synced: 2025-02-19T06:04:11.080Z (over 1 year ago)
- Language: JavaScript
- Size: 219 KB
- Stars: 0
- Watchers: 5
- Forks: 0
- Open Issues: 12
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# regexdot
[![Gitter][gitter-image]][gitter-url]
[![NPM version][npm-image]][npm-url]
[![Build Status][ci-image]][ci-url]
[![Test Coverage][coverage-image]][coverage-url]
[![Dependency Status][daviddm-image]][daviddm-url]
[![Follow @FabrixApp on Twitter][twitter-image]][twitter-url]
[](https://conventionalcommits.org)
> A tiny utility that converts dot object access patterns into RegExp.
With `regexdot`, you may turn a path string (eg, `.users.:id`) into a regular expression.
An object with shape of `{ keys, pattern }` is returned, where `pattern` is the `RegExp` and `keys` is an array of your parameter name(s) in the order that they appeared.
This module does not create a `keys` dictionary, nor mutate an existing variable. Also, this only ships a parser, which only accept strings. Similarly, and most importantly, `regexdot` **only** handles basic path operators:
* Static (`.foo`, `.foo.bar`)
* Parameter (`.:title`, `.books.:title`, `.books.:genre.:title`)
* Parameter w. Suffix (`.movies.:title.mp4`, `.movies.:title.(mp4|mov)`)
* Optional Parameters (`.:title?`, `.books.:title?`, `.books.:genre.:title?`)
* Wildcards (`*`, `.books.*`, `.books.:genre.*`)
This module exposes two module definitions:
* **CommonJS**: `dist/index.js`
## Install
```
$ npm install --save regexdot
```
## Usage
```js
const { regexdot } = require('@fabrix/regexdot')
// Example param-assignment
function exec(path, result) {
let i=0, out={}
let matches = result.pattern.exec(path)
while (i < result.keys.length) {
out[ result.keys[i] ] = matches[++i] || null
}
return out
}
// Parameter, with Optional Parameter
// ---
let foo = regexdot('.books.:genre.:title?')
// foo.pattern => /^\.books\.([^\.]+?)(?:\.([^\.]+?))?\.?$/i
// foo.keys => ['genre', 'title']
foo.pattern.test('.books.horror') // => true
foo.pattern.test('.books.horror.goosebumps') // => true
exec('.books.horror', foo)
//=> { genre: 'horror', title: null }
exec('.books.horror.goosebumps', foo)
//=> { genre: 'horror', title: 'goosebumps' }
// Parameter, with suffix
// ---
let bar = regexdot('.movies.:title.(mp4|mov)')
// bar.pattern => /^\/movies\/([^\/]+?)\.(mp4|mov)\/?$/i
// bar.keys => ['title']
bar.pattern.test('.movies.narnia') //=> false
bar.pattern.test('.movies.narnia.mp3') //=> false
bar.pattern.test('.movies.narnia.mp4') //=> true
exec('.movies.narnia.mp4', bar)
//=> { title: 'narnia' }
// Wildcard
// ---
let baz = regexdot('users.*')
// baz.pattern => /^\.users\.(.*)\.?$/i
// baz.keys => ['wild']
baz.pattern.test('.users') //=> false
baz.pattern.test('.users.fabrix') //=> true
exec('.users.fabrix.repos.new', baz)
//=> { wild: 'fabrix/repos/new' }
```
> **Importnat:** Using `::` will assume that it is not a param but a message header. Eg. `messege::commplete` does not contain any parameters.
> **Important:** When matching/testing against a generated RegExp, your path **must** begin with a leading dot (`"."`)!
## Regular Expressions
For fine-tuned control, you may pass a `RegExp` value directly to `regexdot` as its only parameter.
In these situations, `regexdot` **does not** parse nor manipulate your pattern in any way! Because of this, `regexdot` has no "insight" on your route, and instead trusts your input fully. In code, this means that the return value's `keys` is always equal to `false` and the `pattern` is identical to your input value.
This also means that you must manage and parse your own `keys`~!
You may use [named capture groups](https://javascript.info/regexp-groups#named-groups) or traverse the matched segments manually the "old-fashioned" way:
```js
// Named capture group
const named = regexdot(/^\/posts[\.](?[0-9]{4})[\.](?[0-9]{2})[\.](?[^\.]+)/i);
const { groups } = named.pattern.exec('.posts.2019.05.hello-world');
console.log(groups);
//=> { year: '2019', month: '05', title: 'hello-world' }
// Widely supported / "Old-fashioned"
const named = regexdot(/^\.posts[\.]([0-9]{4})[\.]([0-9]{2})[\.]([^\.]+)/i);
const [url, year, month, title] = named.pattern.exec('.posts.2019.05.hello-world');
console.log(year, month, title);
//=> 2019 05 hello-world
```
## API
There are two API variants:
1) When passing a `String` input, the `loose` parameter is able to affect the output. [View API](#regexdotstr-loose)
2) When passing a `RegExp` value, that must be `regexdot`'s _only_ argument.
Your pattern is saved as written, so `loose` is ignored entirely. [View API](#regexdotrgx)
### regexdot(str, loose)
Returns: `Object`
Returns a `{ keys, pattern }` object, where `pattern` is a generated `RegExp` instance and `keys` is a list of extracted parameter names.
#### str
Type: `String`
The path string to convert.
> **Note:** It does not matter if your `str` begins with a `/` — it will be added if missing.
#### loose
Type: `Boolean`
Default: `false`
Should the `RegExp` match URLs that are longer than the [`str`](#str) pattern itself?
By default, the generated `RegExp` will test that the URL begins and _ends with_ the pattern.
```js
const { regexdot } = require('@fabrix/regexdot');
regexdot('.users').pattern.test('.users.fabrix'); //=> false
regexdot('.users', true).pattern.test('.users.fabrix'); //=> true
regexdot('.users.:name').pattern.test('.users.fabrix.repos'); //=> false
regexdot('.users.:name', true).pattern.test('.users.fabrix.repos'); //=> true
```
### regexdot(rgx)
Returns: `Object`
Returns a `{ keys, pattern }` object, where pattern is _identical_ to your `rgx` and `keys` is `false`, always.
#### rgx
Type: `RegExp`
Your RegExp pattern.
> **Important:** This pattern is used _as is_! No parsing or interpreting is done on your behalf.
### Release Instructions
When the master is tagged with a release, it will automatically publish to npm, updates the Changelog and bumps the version. Fabrix uses the [standard-version library](https://www.npmjs.com/package/standard-version) to manage it all.
To run a patch release:
```bash
npm run release -- --release-as patch
```
and then commit to master. `git push --follow-tags origin master`
You can also test the release by running
```bash
npm run release -- --dry-run --release-as patch
```
[npm-image]: https://img.shields.io/npm/v/@fabrix/regexdot.svg?style=flat-square
[npm-url]: https://npmjs.org/package/@fabrix/regexdot
[ci-image]: https://img.shields.io/circleci/project/github/fabrix-app/regexdot/master.svg
[ci-url]: https://circleci.com/gh/fabrix-app/regexdot/tree/master
[daviddm-image]: http://img.shields.io/david/fabrix-app/regexdot.svg?style=flat-square
[daviddm-url]: https://david-dm.org/fabrix-app/regexdot
[gitter-image]: http://img.shields.io/badge/+%20GITTER-JOIN%20CHAT%20%E2%86%92-1DCE73.svg?style=flat-square
[gitter-url]: https://gitter.im/fabrix-app/fabrix
[twitter-image]: https://img.shields.io/twitter/follow/FabrixApp.svg?style=social
[twitter-url]: https://twitter.com/FabrixApp
[coverage-image]: https://img.shields.io/codeclimate/coverage/github/fabrix-app/regexdot.svg?style=flat-square
[coverage-url]: https://codeclimate.com/github/fabrix-app/regexdot/coverage