Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

compose-regexp

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

compose-regexp - npm Package Compare versions

Comparing version 0.4.2 to 0.5.2

change-log.md

236

compose-regexp.js

@@ -1,146 +0,134 @@

(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define('compose-regexp', ['exports'], factory) :
(factory((global.composeRegexp = {})));
}(this, function (exports) { 'use strict';
var empty = new RegExp('')
var empty = new RegExp('')
function normalize (source) {
if (source instanceof RegExp) return source.source
else return (source+'').replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")
}
function normalize (source) {
if (source instanceof RegExp) return source.source
else return (source+'').replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&")
}
// TODO investigate -] in charSets for isSequential and forSequence
var tokenMatcher = /(\\[^])|\[\-|[-()|\[\]]/g
// TODO investigate -] in charSets for isSequential and forSequence
var tokenMatcher = /(\\[^])|\[\-|[-()|\[\]]/g
// When composing expressions into a sequence, regexps that have a top-level
// choice operator must be wrapped in a non-capturing group. This function
// detects whether the group is needed or not.
function hasTopLevelChoice(source) {
if (source.indexOf('|') === -1) return false
var depth = 0, inCharSet = false, match
tokenMatcher.lastIndex = 0
while(match = tokenMatcher.exec(source)) {
if (match[1] != null) continue
if (!inCharSet && match[0] === '(') depth++
if (!inCharSet && match[0] === ')') depth--
if (!inCharSet && (match[0] === '[' || match[0] === '[-')) inCharSet = true
if (inCharSet && match[0] === ']') inCharSet = false
if (depth === 0 && !inCharSet && match[0] === '|') return true
}
return false
// When composing expressions into a sequence, regexps that have a top-level
// choice operator must be wrapped in a non-capturing group. This function
// detects whether the group is needed or not.
export function hasTopLevelChoice(source) {
if (source.indexOf('|') === -1) return false
var depth = 0, inCharSet = false, match
tokenMatcher.lastIndex = 0
while(match = tokenMatcher.exec(source)) {
if (match[1] != null) continue
if (!inCharSet && match[0] === '(') depth++
if (!inCharSet && match[0] === ')') depth--
if (!inCharSet && (match[0] === '[' || match[0] === '[-')) inCharSet = true
if (inCharSet && match[0] === ']') inCharSet = false
if (depth === 0 && !inCharSet && match[0] === '|') return true
}
return false
}
// helper function for isAtomic
function isOneGroup(source) {
if (source.charAt(0) !== '(' || source.charAt(source.length - 1) !== ')') return false
var depth = 0, inCharSet = false, match
tokenMatcher.lastIndex = 0
while(match = tokenMatcher.exec(source)) {
if (match[1] != null) {
if (match.index === source.length - 2) return false
continue
}
if (!inCharSet && match[0] === '(') depth++
if (!inCharSet && match[0] === ')') {
depth--
if (depth === 0 && match.index !== source.length - 1) return false
}
if (!inCharSet && (match[0] === '[' || match === '[-')) inCharSet = true
if (inCharSet && match[0] === ']') inCharSet = false
// helper function for isAtomic
export function isOneGroup(source) {
if (source.charAt(0) !== '(' || source.charAt(source.length - 1) !== ')') return false
var depth = 0, inCharSet = false, match
tokenMatcher.lastIndex = 0
while(match = tokenMatcher.exec(source)) {
if (match[1] != null) {
if (match.index === source.length - 2) return false
continue
}
return true
if (!inCharSet && match[0] === '(') depth++
if (!inCharSet && match[0] === ')') {
depth--
if (depth === 0 && match.index !== source.length - 1) return false
}
if (!inCharSet && (match[0] === '[' || match === '[-')) inCharSet = true
if (inCharSet && match[0] === ']') inCharSet = false
}
return true
}
function forSequence(source) {
source = normalize(source)
return hasTopLevelChoice(source) ? '(?:' + source + ')' : source
}
function forSequence(source) {
source = normalize(source)
return hasTopLevelChoice(source) ? '(?:' + source + ')' : source
}
// Determine if a pattern can take a suffix operator or if a non-capturing group
// is needed around it.
// We can safely have false negatives (consequence: useless non-capturing groups)
// whereas false positives would be bugs. We do ahve some false positives:
// some charsets will be marked as non-atomic.
function isAtomic(source) {
return source.length === 1 || /^\\[^]$|^\[(?:\\[^]|[^\]])*\]$/.test(source) || isOneGroup(source)
}
// Determine if a pattern can take a suffix operator or if a non-capturing group
// is needed around it.
// We can safely have false negatives (consequence: useless non-capturing groups)
// whereas false positives would be bugs. We do ahve some false positives:
// some charsets will be marked as non-atomic.
function isAtomic(source) {
return source.length === 1 || /^\\[^]$|^\[(?:\\[^]|[^\]])*\]$/.test(source) || isOneGroup(source)
}
var map = [].map
var map = [].map
function either() {
if (!arguments.length) return empty;
return new RegExp(map.call(arguments, normalize).join('|'))
}
export function either() {
if (!arguments.length) return empty;
return new RegExp(map.call(arguments, normalize).join('|'))
}
function _sequence() {
if (arguments.length === 0) return '';
if (arguments.length === 1) return normalize(arguments[0])
return map.call(arguments, forSequence).join('')
}
function _sequence() {
if (arguments.length === 0) return '';
if (arguments.length === 1) return normalize(arguments[0])
return map.call(arguments, forSequence).join('')
}
function sequence () {
return new RegExp(_sequence.apply(null, arguments))
}
export function sequence () {
return new RegExp(_sequence.apply(null, arguments))
}
var validSuffix = sequence(
/^/,
either(
'+', '*', '?',
/\{\s*\d+(?:\s*,\s*)?\d*\s*\}/
),
/\??$/
)
var validSuffix = sequence(
/^/,
either(
'+', '*', '?',
/\{\s*\d+(?:\s*,\s*)?\d*\s*\}/
),
/\??$/
)
var call = _suffix.call
function _suffix(operator) {
if (arguments.length === 1) return empty
// an attrocious hack to pass all arguements but the operator to `_sequence()`
// without allocating an array. The operator is passed as `this` which is ignored.
var res = call.apply(_sequence, arguments)
return new RegExp(isAtomic(res) ? res + operator : '(?:' + res + ')' + operator)
}
var call = _suffix.call
var push = [].push
function _suffix(operator) {
if (arguments.length === 1) return empty
// an attrocious hack to pass all arguements but the operator to `_sequence()`
// without allocating an array. The operator is passed as `this` which is ignored.
var res = call.apply(_sequence, arguments)
return new RegExp(isAtomic(res) ? res + operator : '(?:' + res + ')' + operator)
}
function suffix(suffix) {
if (!validSuffix.test(suffix)) throw new Error("Invalid suffix '" + suffix+ "'.")
return (arguments.length === 1)
? _suffix.bind(null, suffix)
: _suffix.apply(null, arguments)
}
export function suffix(suffix) {
if (!validSuffix.test(suffix)) throw new Error("Invalid suffix '" + suffix+ "'.")
return (arguments.length === 1)
? _suffix.bind(null, suffix)
: _suffix.apply(null, arguments)
}
function ref(n) {
return new RegExp('\\' + n)
}
export function ref(n) {
return new RegExp('\\' + n)
}
function lookAhead() {
if (!arguments.length) return empty;
return new RegExp('(?=' + _sequence.apply(null, arguments) + ')')
}
export function lookAhead() {
if (!arguments.length) return empty;
return new RegExp('(?=' + _sequence.apply(null, arguments) + ')')
}
function avoid() {
if (!arguments.length) return empty;
return new RegExp('(?!' + _sequence.apply(null, arguments) + ')')
}
export function avoid() {
if (!arguments.length) return empty;
return new RegExp('(?!' + _sequence.apply(null, arguments) + ')')
}
function flags(opts) {
return new RegExp(call.apply(_sequence, arguments), opts)
}
function _flags(opts) {
return new RegExp(call.apply(_sequence, arguments), opts)
}
function capture () {
if (!arguments.length) return new RegExp('()');
return new RegExp('(' + _sequence.apply(null, arguments) + ')')
}
export function flags(opts) {
return arguments.length === 1
? _flags.bind(null, opts)
: _flags.apply(null, arguments)
}
exports.hasTopLevelChoice = hasTopLevelChoice;
exports.isOneGroup = isOneGroup;
exports.either = either;
exports.sequence = sequence;
exports.suffix = suffix;
exports.ref = ref;
exports.lookAhead = lookAhead;
exports.avoid = avoid;
exports.flags = flags;
exports.capture = capture;
}));
export function capture () {
if (!arguments.length) return new RegExp('()');
return new RegExp('(' + _sequence.apply(null, arguments) + ')')
}
/**@license MIT-compose-regexp.js-©Pierre-Yves Gérardy*/
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define("compose-regexp",["exports"],n):n(e.composeRegexp={})}(this,function(e){"use strict";function n(e){return e instanceof RegExp?e.source:(e+"").replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}function t(e){if(-1===e.indexOf("|"))return!1;var n,t=0,r=!1;for(w.lastIndex=0;n=w.exec(e);)if(null==n[1]&&(r||"("!==n[0]||t++,r||")"!==n[0]||t--,r||"["!==n[0]&&"[-"!==n[0]||(r=!0),r&&"]"===n[0]&&(r=!1),0===t&&!r&&"|"===n[0]))return!0;return!1}function r(e){if("("!==e.charAt(0)||")"!==e.charAt(e.length-1))return!1;var n,t=0,r=!1;for(w.lastIndex=0;n=w.exec(e);)if(null==n[1]){if(r||"("!==n[0]||t++,!r&&")"===n[0]&&0===--t&&n.index!==e.length-1)return!1;r||"["!==n[0]&&"[-"!==n||(r=!0),r&&"]"===n[0]&&(r=!1)}else if(n.index===e.length-2)return!1;return!0}function u(e){return e=n(e),t(e)?"(?:"+e+")":e}function l(e){return 1===e.length||/^\\[^]$|^\[(?:\\[^]|[^\]])*\]$/.test(e)||r(e)}function i(){return arguments.length?new RegExp(E.call(arguments,n).join("|")):d}function o(){return 0===arguments.length?"":1===arguments.length?n(arguments[0]):E.call(arguments,u).join("")}function f(){return new RegExp(o.apply(null,arguments))}function p(e){if(1===arguments.length)return d;var n=y.apply(o,arguments);return new RegExp(l(n)?n+e:"(?:"+n+")"+e)}function c(e){if(!R.test(e))throw new Error("Invalid suffix '"+e+"'.");return 1===arguments.length?p.bind(null,e):p.apply(null,arguments)}function a(e){return new RegExp("\\"+e)}function g(){return arguments.length?new RegExp("(?="+o.apply(null,arguments)+")"):d}function s(){return arguments.length?new RegExp("(?!"+o.apply(null,arguments)+")"):d}function x(e){return new RegExp(y.apply(o,arguments),e)}function h(){return arguments.length?new RegExp("("+o.apply(null,arguments)+")"):new RegExp("()")}var d=new RegExp(""),w=/(\\[^])|\[\-|[-()|\[\]]/g,E=[].map,R=f(/^/,i("+","*","?",/\{\s*\d+(?:\s*,\s*)?\d*\s*\}/),/\??$/),y=p.call;e.hasTopLevelChoice=t,e.isOneGroup=r,e.either=i,e.sequence=f,e.suffix=c,e.ref=a,e.lookAhead=g,e.avoid=s,e.flags=x,e.capture=h});
!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define("compose-regexp",["exports"],e):e(n.composeRegexp={})}(this,function(n){"use strict";function e(n){return n instanceof RegExp?n.source:(n+"").replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}function t(n){if(-1===n.indexOf("|"))return!1;var e,t=0,r=!1;for(w.lastIndex=0;e=w.exec(n);)if(null==e[1]&&(r||"("!==e[0]||t++,r||")"!==e[0]||t--,r||"["!==e[0]&&"[-"!==e[0]||(r=!0),r&&"]"===e[0]&&(r=!1),0===t&&!r&&"|"===e[0]))return!0;return!1}function r(n){if("("!==n.charAt(0)||")"!==n.charAt(n.length-1))return!1;var e,t=0,r=!1;for(w.lastIndex=0;e=w.exec(n);)if(null==e[1]){if(r||"("!==e[0]||t++,!r&&")"===e[0]&&0===--t&&e.index!==n.length-1)return!1;r||"["!==e[0]&&"[-"!==e||(r=!0),r&&"]"===e[0]&&(r=!1)}else if(e.index===n.length-2)return!1;return!0}function u(n){return n=e(n),t(n)?"(?:"+n+")":n}function l(n){return 1===n.length||/^\\[^]$|^\[(?:\\[^]|[^\]])*\]$/.test(n)||r(n)}function i(){return arguments.length?new RegExp(E.call(arguments,e).join("|")):d}function o(){return 0===arguments.length?"":1===arguments.length?e(arguments[0]):E.call(arguments,u).join("")}function f(){return new RegExp(o.apply(null,arguments))}function p(n){if(1===arguments.length)return d;var e=y.apply(o,arguments);return new RegExp(l(e)?e+n:"(?:"+e+")"+n)}function c(n){if(!R.test(n))throw new Error("Invalid suffix '"+n+"'.");return 1===arguments.length?p.bind(null,n):p.apply(null,arguments)}function g(n){return new RegExp("\\"+n)}function a(){return arguments.length?new RegExp("(?="+o.apply(null,arguments)+")"):d}function s(){return arguments.length?new RegExp("(?!"+o.apply(null,arguments)+")"):d}function x(n){return console.log(n,arguments.length),1===arguments.length?x.bind(null,n):new RegExp(y.apply(o,arguments),n)}function h(){return arguments.length?new RegExp("("+o.apply(null,arguments)+")"):new RegExp("()")}var d=new RegExp(""),w=/(\\[^])|\[\-|[-()|\[\]]/g,E=[].map,R=f(/^/,i("+","*","?",/\{\s*\d+(?:\s*,\s*)?\d*\s*\}/),/\??$/),y=p.call;n.hasTopLevelChoice=t,n.isOneGroup=r,n.either=i,n.sequence=f,n.suffix=c,n.ref=g,n.lookAhead=a,n.avoid=s,n.flags=x,n.capture=h});
{
"name": "compose-regexp",
"version": "0.4.2",
"version": "0.5.2",
"description": "A set of functions to build and compose complex regular expressions",
"type": "",
"main": "compose-regexp.js",
"jsnext:main": "compose-regexp.es6.js",
"module": "compose-regexp.mjs",
"jsnext:main": "compose-regexp.mjs",
"exports": {
".": {}
},
"scripts": {
"test": "node tests/tests.js",
"test": "gosub rollup && ospec",
"build": "gosub rollup && gosub uglify && gosub gzip",
"rollup": "rollup compose-regexp.es6.js -o compose-regexp.js -f umd -n composeRegexp -u compose-regexp",
"uglify": "uglifyjs compose-regexp.js -cm --preamble '/**@license MIT-compose-regexp.js-©Pierre-Yves Gérardy*/' > dist/compose-regexp.min.js",
"uglifyv": "uglifyjs --version",
"gzip": "cat dist/compose-regexp.min.js | gzip -9 > dist/compose-regexp.min.js.gz",
"clean": "rm -f compose-regexp.js && rm -rf dist/*.*"
"rollup": "rollup compose-regexp.js -o commonjs/compose-regexp.js -f umd -n composeRegexp -u compose-regexp",
"uglify": "uglifyjs commpnjs/compose-regexp.js -cm --preamble '/**@license MIT-compose-regexp.js-©Pierre-Yves Gérardy*/' > dist/compose-regexp.min.js",
"gzip": "cat dist/compose-regexp.min.js | gzip -9 > dist/compose-regexp.min.js.gz"
},

@@ -36,5 +39,5 @@ "repository": {

"uglify-js": "^2.6.1",
"ospec": "^1.2.3",
"ospec": "pygy/ospec#module-and-parallel",
"gosub": "1.0.0"
}
}

@@ -109,3 +109,3 @@

#### flags(opts, regexps...)
#### flags(opts, regexps...), flags(opts)(regexps...)

@@ -115,2 +115,4 @@ ```JavaScript

/a/gm
> global = flags(g); global('a')
/a/g
```

@@ -155,6 +157,16 @@

#### suffix(operator, regexprs...), greedy(suffix)(regexprs...)
#### suffix(operator, regexprs...), suffix(operator)(regexprs...)
Valid suffixes: (`?`, `*`, `+`, `{n}`, `{n,}` and `{m, n}`; `??`, `*?`, `+?`, `{n}?`, `{n,}?` and `{m, n}?`)
Valid operators:
| greedy | non-greedy |
|----------|------------|
| `?` | `??` |
| `*` | `*?` |
| `+` | `+?` |
| `{n}` | `{n}?` |
| `{n,}` | `{n,}?` |
| `{m, n}` | `{m, n}?` |
```JS

@@ -161,0 +173,0 @@ > suffix("*", either(/a/, /b/, /c/))

var o = require('ospec')
var CR = require('../')
var CR = require('../commonjs/compose-regexp')
function req(a, b) {
if (a.source !== b.source) throw new Error ("expected " + b.source + " got " + a.source)
o(a.source).equals(b.source)((new Error).stack.split('\n')[2])
}
function eq(a, b) {
if (a !== b) throw new Error("expected " + b + " got " + a)
}

@@ -21,86 +18,106 @@ var either = CR.either

req(either('a'), /a/)
req(either('a','b'), /a|b/)
req(either('a', 'b', 'c'), /a|b|c/)
o('either', function() {
req(either('a'), /a/)
req(either('a','b'), /a|b/)
req(either('a', 'b', 'c'), /a|b|c/)
})
// normalization
;[
either, sequence,
suffix('*'),
lookAhead, avoid,
flags.bind(null, ''), capture
].forEach(function(m) {
// normalization
req(m(/\./), m('.'))
// empty arg list
if (m !== capture)
req(m(), new RegExp(''))
else
req(m(), /()/)
o('string and no arguments normalization', function(){
[
either, sequence,
suffix('*'),
lookAhead, avoid,
flags(''), capture
].forEach(function(m) {
// normalization
req(m(/\./), m('.'))
// empty arg list
if (m !== capture)
req(m(), new RegExp(''))
else
req(m(), /()/)
})
})
o('sequence', function() {
req(sequence('a'), /a/)
req(sequence('a', 'b'), /ab/)
req(sequence('a', 'b', 'c'), /abc/)
req(sequence('a', /b|c/), /a(?:b|c)/)
req(sequence(/^/, 'b', /$/), /^b$/)
req(sequence(/a|b/), /a|b/)
req(either(sequence(sequence(/a|b/))), /a|b/)
req(sequence('thingy', either(/[a]/, /b/)), /thingy(?:[a]|b)/)
})
req(sequence('a'), /a/)
req(sequence('a', 'b'), /ab/)
req(sequence('a', 'b', 'c'), /abc/)
req(sequence('a', /b|c/), /a(?:b|c)/)
req(sequence(/^/, 'b', /$/), /^b$/)
req(sequence(/a|b/), /a|b/)
req(either(sequence(sequence(/a|b/))), /a|b/)
req(sequence('thingy', either(/[a]/, /b/)), /thingy(?:[a]|b)/)
o('avoid', function(){
req(avoid('a'), /(?!a)/)
req(avoid('a', 'b'), /(?!ab)/)
req(avoid('a', 'b', 'c'), /(?!abc)/)
})
o('lookAhead', function(){
req(lookAhead('a'), /(?=a)/)
req(lookAhead('a', 'b'), /(?=ab)/)
req(lookAhead('a', 'b', 'c'), /(?=abc)/)
})
o('captiure', function(){
req(capture('a'), /(a)/)
req(capture('a', 'b'), /(ab)/)
req(capture('a', 'b', 'c'), /(abc)/)
})
req(avoid('a'), /(?!a)/)
req(avoid('a', 'b'), /(?!ab)/)
req(avoid('a', 'b', 'c'), /(?!abc)/)
req(lookAhead('a'), /(?=a)/)
req(lookAhead('a', 'b'), /(?=ab)/)
req(lookAhead('a', 'b', 'c'), /(?=abc)/)
req(capture('a'), /(a)/)
req(capture('a', 'b'), /(ab)/)
req(capture('a', 'b', 'c'), /(abc)/)
req(ref(1), /\1/)
req(ref(9), /\9/)
req(suffix('?', /foo/), /(?:foo)?/)
req(suffix('*', /foo/), /(?:foo)*/)
req(suffix('+', /foo/), /(?:foo)+/)
eq(flags('m', /o/).multiline, true)
eq(flags('i', /o/).multiline, false)
;[
'*', '+', '?', '{2}', '{2,}', '{2,4}',
'*?', '+?', '??', '{2}?', '{2,}?', '{2,4}?',
].forEach(function(op){
req(suffix(op, 'a'), {source: 'a' + op})
req(suffix(op, /a|b/), {source: '(?:a|b)' + op})
req(suffix(op, /(a)b/), {source: '(?:(a)b)' + op})
req(suffix(op)('a'), {source: 'a' + op})
o('req', function(){
req(ref(1), /\1/)
req(ref(9), /\9/)
})
;['a', '5.', '{5.4}'].forEach(function(op){
var caught
caught = false
try {
suffix(op, 'a')
} catch (e) {
caught = true
o('flags', function(){
var flagKinds = {
g: 'global',
i: 'ignoreCase',
m: 'multiline'
}
eq(caught, true)
caught = false
try {
suffix(op)
} catch (e) {
caught = true
;[['s', 'dotAll'], ['u', 'unicode'], ['y', 'sticky']].forEach(function(pair){
try {
new RegExp('', pair[0])
flagKinds[pair[0]] = pair[1]
} catch(e) {}
})
flags('g')
for (var k in flagKinds) {
o(flags(k, /o/)[flagKinds[k]]).equals(true)
o(flags(k)(/o/)[flagKinds[k]]).equals(true)
for (kk in flagKinds) if (k !== kk) {
o(flags(kk, /o/)[flagKinds[k]]).equals(false)
o(flags(kk)(/o/)[flagKinds[k]]).equals(false)
}
}
eq(caught, true)
o(flags('m', /o/).multiline).equals(true)
o(flags('i', /o/).multiline).equals(false)
})
o.spec('suffx', function(){
o('works', function(){
[
'*', '+', '?', '{2}', '{2,}', '{2,4}',
'*?', '+?', '??', '{2}?', '{2,}?', '{2,4}?',
].forEach(function(op){
req(suffix(op, 'a'), {source: 'a' + op})
req(suffix(op, /foo/), {source: '(?:foo)' + op})
req(suffix(op, /a|b/), {source: '(?:a|b)' + op})
req(suffix(op, /(a)b/), {source: '(?:(a)b)' + op})
req(suffix(op)('a'), {source: 'a' + op})
})
})
o('invalid ranges throw', function(){
['a', '5.', '{5.4}'].forEach(function(op){
o(function() { suffix(op, 'a') }).throws(Error)
o(function() { suffix(op) }).throws(Error)
})
})
})
o.spec('parsers', function(){

@@ -116,3 +133,1 @@ o('hasTopLevelChoice', function(){

})
o.run()

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc