ts-regex-builder
Advanced tools
Comparing version 1.0.1 to 1.1.0
@@ -20,2 +20,5 @@ "use strict"; | ||
} | ||
if (typeof element === 'object' && element instanceof RegExp) { | ||
return encodeRegExp(element); | ||
} | ||
if (typeof element.encode !== 'function') { | ||
@@ -43,2 +46,29 @@ throw new Error(`\`encodeNode\`: unknown element type ${element.type}`); | ||
} | ||
function encodeRegExp(regexp) { | ||
const pattern = regexp.source; | ||
if (pattern.length === 0) { | ||
throw new Error('`encodeRegExp`: received regexp should not be empty'); | ||
} | ||
// Encode at safe precedence | ||
return { | ||
precedence: isAtomicPattern(regexp.source) ? 'atom' : 'disjunction', | ||
pattern | ||
}; | ||
} | ||
// This is intended to catch only some popular atomic patterns like char classes. | ||
function isAtomicPattern(pattern) { | ||
var _pattern$match, _pattern$match2; | ||
if (pattern.length === 1) { | ||
return true; | ||
} | ||
if (pattern.startsWith('[') && pattern.endsWith(']') && ((_pattern$match = pattern.match(/[[\]]/g)) === null || _pattern$match === void 0 ? void 0 : _pattern$match.length) === 2) { | ||
return true; | ||
} | ||
if (pattern.startsWith('(') && pattern.endsWith(')') && ((_pattern$match2 = pattern.match(/[()]/g)) === null || _pattern$match2 === void 0 ? void 0 : _pattern$match2.length) === 2) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
function concatSequence(encoded) { | ||
@@ -45,0 +75,0 @@ if (encoded.length === 1) { |
@@ -13,2 +13,5 @@ import { escapeText } from '../utils/text'; | ||
} | ||
if (typeof element === 'object' && element instanceof RegExp) { | ||
return encodeRegExp(element); | ||
} | ||
if (typeof element.encode !== 'function') { | ||
@@ -36,2 +39,29 @@ throw new Error(`\`encodeNode\`: unknown element type ${element.type}`); | ||
} | ||
function encodeRegExp(regexp) { | ||
const pattern = regexp.source; | ||
if (pattern.length === 0) { | ||
throw new Error('`encodeRegExp`: received regexp should not be empty'); | ||
} | ||
// Encode at safe precedence | ||
return { | ||
precedence: isAtomicPattern(regexp.source) ? 'atom' : 'disjunction', | ||
pattern | ||
}; | ||
} | ||
// This is intended to catch only some popular atomic patterns like char classes. | ||
function isAtomicPattern(pattern) { | ||
var _pattern$match, _pattern$match2; | ||
if (pattern.length === 1) { | ||
return true; | ||
} | ||
if (pattern.startsWith('[') && pattern.endsWith(']') && ((_pattern$match = pattern.match(/[[\]]/g)) === null || _pattern$match === void 0 ? void 0 : _pattern$match.length) === 2) { | ||
return true; | ||
} | ||
if (pattern.startsWith('(') && pattern.endsWith(')') && ((_pattern$match2 = pattern.match(/[()]/g)) === null || _pattern$match2 === void 0 ? void 0 : _pattern$match2.length) === 2) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
function concatSequence(encoded) { | ||
@@ -38,0 +68,0 @@ if (encoded.length === 1) { |
@@ -12,3 +12,3 @@ import type { EncodeResult } from './encoder/types'; | ||
*/ | ||
export type RegexElement = RegexConstruct | string; | ||
export type RegexElement = RegexConstruct | string | RegExp; | ||
/** | ||
@@ -15,0 +15,0 @@ * Common interface for all regex constructs like character classes, quantifiers, and anchors. |
{ | ||
"name": "ts-regex-builder", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "TypeScript adaptation of Swift Regex Builder API", | ||
@@ -5,0 +5,0 @@ "main": "lib/commonjs/index", |
[](https://badge.fury.io/js/ts-regex-builder) | ||
 | ||
<a href="https://pkg-size.dev/ts-regex-builder?no-peers"><img src="https://pkg-size.dev/badge/bundle/4554" title="Bundle size for ts-regex-builder"></a> | ||
 | ||
[](http://makeapullrequest.com) | ||
@@ -9,3 +9,3 @@ [](https://github.com/callstack/ts-regex-builder/stargazers) | ||
A user-friendly regular expression builder for TypeScript and JavaScript. | ||
Build maintainable regular expressions for TypeScript and JavaScript. | ||
@@ -21,6 +21,6 @@ [API docs](./docs/API.md) | [Examples](./docs/Examples.md) | ||
```ts | ||
// Before | ||
// Regular JS RegExp | ||
const hexColor = /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/; | ||
// After | ||
// TS Regex Builder DSL | ||
const hexDigit = charClass( | ||
@@ -72,3 +72,3 @@ charRange('a', 'f'), | ||
- regex construct (`RegexConstruct`) - common name for all regex constructs like character classes, quantifiers, and anchors. | ||
- regex element (`RegexElement`) - a fundamental building block of a regular expression, defined as either a regex construct or a string. | ||
- regex element (`RegexElement`) - a fundamental building block of a regular expression, defined as either a regex construct, a string, or `RegExp` literal (`/.../`). | ||
- regex sequence (`RegexSequence`) - a sequence of regex elements forming a regular expression. For developer convenience, it also accepts a single element instead of an array. | ||
@@ -79,5 +79,6 @@ | ||
Examples of sequences: | ||
- single element (construct): `capture('abc')` | ||
- single element (construct): `capture('Hello')` | ||
- single element (string): `'Hello'` | ||
- array of elements: `['USD', oneOrMore(digit)]` | ||
- single element (`RegExp` literal): `/Hello/` | ||
- array of elements: `['USD', oneOrMore(digit), /Hello/]` | ||
@@ -87,11 +88,8 @@ Regex constructs can be composed into a tree structure: | ||
```ts | ||
const currencyCode = repeat(charRange('A', 'Z'), 3); | ||
const currencyAmount = buildRegExp([ | ||
choiceOf( | ||
'$', | ||
'€', | ||
repeat(charRange('A', 'Z'), 3), // ISO currency code | ||
), | ||
choiceOf('$', '€', currencyCode), // currency | ||
capture( | ||
oneOrMore(digit), // Integer part | ||
optional(['.', repeat(digit, 2)]), // Fractional part | ||
oneOrMore(digit), // integer part | ||
optional(['.', repeat(digit, 2)]), // fractional part | ||
), | ||
@@ -165,10 +163,15 @@ ]); | ||
## Inspiration | ||
TS Regex Builder is inspired by [Swift Regex Builder API](https://developer.apple.com/documentation/regexbuilder). | ||
## Reference | ||
- [ECMAScript Regular Expression BNF Grammar](https://262.ecma-international.org/7.0/#sec-regular-expressions) | ||
- [Swift Regex Builder API docs](https://developer.apple.com/documentation/regexbuilder) | ||
- [Swift Evolution 351: Regex Builder DSL](https://github.com/apple/swift-evolution/blob/main/proposals/0351-regex-builder.md) | ||
- [ECMAScript Regular Expression BNF Grammar](https://262.ecma-international.org/7.0/#sec-regular-expressions) | ||
--- | ||
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob) |
@@ -19,2 +19,6 @@ import type { RegexElement } from '../types'; | ||
if (typeof element === 'object' && element instanceof RegExp) { | ||
return encodeRegExp(element); | ||
} | ||
if (typeof element.encode !== 'function') { | ||
@@ -46,2 +50,33 @@ throw new Error(`\`encodeNode\`: unknown element type ${element.type}`); | ||
function encodeRegExp(regexp: RegExp): EncodeResult { | ||
const pattern = regexp.source; | ||
if (pattern.length === 0) { | ||
throw new Error('`encodeRegExp`: received regexp should not be empty'); | ||
} | ||
// Encode at safe precedence | ||
return { | ||
precedence: isAtomicPattern(regexp.source) ? 'atom' : 'disjunction', | ||
pattern, | ||
}; | ||
} | ||
// This is intended to catch only some popular atomic patterns like char classes. | ||
function isAtomicPattern(pattern: string): boolean { | ||
if (pattern.length === 1) { | ||
return true; | ||
} | ||
if (pattern.startsWith('[') && pattern.endsWith(']') && pattern.match(/[[\]]/g)?.length === 2) { | ||
return true; | ||
} | ||
if (pattern.startsWith('(') && pattern.endsWith(')') && pattern.match(/[()]/g)?.length === 2) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
function concatSequence(encoded: EncodeResult[]): EncodeResult { | ||
@@ -48,0 +83,0 @@ if (encoded.length === 1) { |
@@ -15,3 +15,3 @@ import type { EncodeResult } from './encoder/types'; | ||
*/ | ||
export type RegexElement = RegexConstruct | string; | ||
export type RegexElement = RegexConstruct | string | RegExp; | ||
@@ -18,0 +18,0 @@ /** |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
95594
1570
172