From dbe3e183a43c0df33df9f063c787c82c65b74156 Mon Sep 17 00:00:00 2001 From: ctcpip Date: Wed, 7 Aug 2024 22:43:59 -0500 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20change=20lookahead=20to=20non-c?= =?UTF-8?q?apturing=20group?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.js | 2 +- test.js | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 7ad98c6..0f9d4dc 100644 --- a/index.js +++ b/index.js @@ -123,7 +123,7 @@ function pathtoRegexp(path, keys, options) { } // If the path is non-ending, match until the end or a slash. - path += (end ? '$' : (path[path.length - 1] === '/' ? '' : '(?=\\/|$)')); + path += (end ? '$' : (path[path.length - 1] === '/' ? '' : '(?:\/|$)')); return new RegExp(path, flags); }; diff --git a/test.js b/test.js index 412cff9..6613b2e 100644 --- a/test.js +++ b/test.js @@ -516,14 +516,15 @@ describe('path-to-regexp', function () { it('should do non-ending matches', function () { var params = []; - var m = pathToRegExp('/:test', params, { end: false }).exec('/test/route'); + var re = pathToRegExp('/:test', params, { end: false }) + var m = re.exec('/test/route'); assert.equal(params.length, 1); assert.equal(params[0].name, 'test'); assert.equal(params[0].optional, false); assert.equal(m.length, 2); - assert.equal(m[0], '/test'); + assert.equal(m[0], '/test/'); assert.equal(m[1], 'test'); }); @@ -558,7 +559,7 @@ describe('path-to-regexp', function () { m = re.exec('/route/test'); assert.equal(m.length, 1); - assert.equal(m[0], '/route'); + assert.equal(m[0], '/route/'); m = re.exec('/route'); @@ -568,7 +569,7 @@ describe('path-to-regexp', function () { m = re.exec('/route//'); assert.equal(m.length, 1); - assert.equal(m[0], '/route/'); + assert.equal(m[0], '/route//'); }); it('should match trailing slashing in non-ending strict mode', function () { @@ -613,7 +614,7 @@ describe('path-to-regexp', function () { m = re.exec('/route/'); assert.ok(m.length, 1); - assert.equal(m[0], '/route'); + assert.equal(m[0], '/route/'); }); it('should match text after an express param', function () { From b5520e31b27a38315338468dc131ddbf69a84fe9 Mon Sep 17 00:00:00 2001 From: ctcpip Date: Tue, 20 Aug 2024 00:03:25 -0500 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=A8=20add=20lookahead=20support=20as?= =?UTF-8?q?=20an=20option,=20skip=20test=20that=20cannot=20pass=20in=20nod?= =?UTF-8?q?e=20<10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.js | 7 +++++- test.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 0f9d4dc..6bab4ac 100644 --- a/index.js +++ b/index.js @@ -31,6 +31,7 @@ function pathtoRegexp(path, keys, options) { var strict = options.strict; var end = options.end !== false; var flags = options.sensitive ? '' : 'i'; + var lookahead = options.lookahead !== false; var extraOffset = 0; var keysOffset = keys.length; var i = 0; @@ -123,7 +124,11 @@ function pathtoRegexp(path, keys, options) { } // If the path is non-ending, match until the end or a slash. - path += (end ? '$' : (path[path.length - 1] === '/' ? '' : '(?:\/|$)')); + if (end) { + path += '$'; + } else if (path[path.length - 1] !== '/') { + path += lookahead ? '(?=\\/|$)' : '(?:\/|$)'; + } return new RegExp(path, flags); }; diff --git a/test.js b/test.js index 6613b2e..9023fe7 100644 --- a/test.js +++ b/test.js @@ -516,8 +516,20 @@ describe('path-to-regexp', function () { it('should do non-ending matches', function () { var params = []; - var re = pathToRegExp('/:test', params, { end: false }) - var m = re.exec('/test/route'); + var m = pathToRegExp('/:test', params, { end: false }).exec('/test/route'); + + assert.equal(params.length, 1); + assert.equal(params[0].name, 'test'); + assert.equal(params[0].optional, false); + + assert.equal(m.length, 2); + assert.equal(m[0], '/test'); + assert.equal(m[1], 'test'); + }); + + it('should do non-ending matches (no lookahead)', function () { + var params = []; + var m = pathToRegExp('/:test', params, { end: false, lookahead: false }).exec('/test/route'); assert.equal(params.length, 1); assert.equal(params[0].name, 'test'); @@ -558,6 +570,34 @@ describe('path-to-regexp', function () { m = re.exec('/route/test'); + assert.equal(m.length, 1); + assert.equal(m[0], '/route'); + + m = re.exec('/route'); + + assert.equal(m.length, 1); + assert.equal(m[0], '/route'); + + m = re.exec('/route//'); + + assert.equal(m.length, 1); + assert.equal(m[0], '/route/'); + }); + + it('should match trailing slashes in non-ending non-strict mode (no lookahead)', function () { + var params = []; + var re = pathToRegExp('/route/', params, { end: false, lookahead: false }); + var m; + + assert.equal(params.length, 0); + + m = re.exec('/route/'); + + assert.equal(m.length, 1); + assert.equal(m[0], '/route/'); + + m = re.exec('/route/test'); + assert.equal(m.length, 1); assert.equal(m[0], '/route/'); @@ -613,6 +653,24 @@ describe('path-to-regexp', function () { m = re.exec('/route/'); + assert.ok(m.length, 1); + assert.equal(m[0], '/route'); + }); + + it('should not match trailing slashes in non-ending strict mode (no lookahead)', function () { + var params = []; + var re = pathToRegExp('/route', params, { end: false, strict: true, lookahead: false }); + var m; + + assert.equal(params.length, 0); + + m = re.exec('/route'); + + assert.equal(m.length, 1); + assert.equal(m[0], '/route'); + + m = re.exec('/route/'); + assert.ok(m.length, 1); assert.equal(m[0], '/route/'); }); @@ -729,6 +787,12 @@ describe('path-to-regexp', function () { }); it('should pull out matching named groups', function () { + const majorVersion = Number(process.version.split('.')[0].replace('v', '')); + if (majorVersion < 10) { + console.log('skipping test: node <10 does not support named capture groups'); + return; + } + var params = []; var re = pathToRegExp(/\/(.*)\/(?.*)\/(.*)/, params); var m;