From 5dd36592ff094c0227a32467d80fd5df43d3ff3f Mon Sep 17 00:00:00 2001 From: hajamie Date: Wed, 8 May 2024 17:55:00 +0200 Subject: [PATCH 1/3] Split paths using original regex Instead of creating a new regex which doesn't have match groups, just find the whole named group and use that instead. The original regex is also fine for checking if a part is a named group (as far as I'm aware). --- lib/util/split-path.js | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/util/split-path.js b/lib/util/split-path.js index 42fcf3a8..c98ba445 100644 --- a/lib/util/split-path.js +++ b/lib/util/split-path.js @@ -5,19 +5,6 @@ const namedGroupPattern = require( './named-group-regexp' ).pattern; -// Convert capture groups to non-matching groups, because all capture groups -// are included in the resulting array when an RE is passed to `.split()` -// (We re-use the existing named group's capture pattern instead of creating -// a new RegExp just for this purpose) -const patternWithoutSubgroups = namedGroupPattern - .replace( /([^\\])\(([^?])/g, '$1(?:$2' ); - -// Make a new RegExp using the same pattern as one single unified capture group, -// so the match as a whole will be preserved after `.split()`. Permit non-slash -// characters before or after the named capture group, although those components -// will not yield functioning setters. -const namedGroupRE = new RegExp( '([^/]*' + patternWithoutSubgroups + '[^/]*)' ); - /** * Divide a route string up into hierarchical components by breaking it apart * on forward slash characters. @@ -29,14 +16,24 @@ const namedGroupRE = new RegExp( '([^/]*' + patternWithoutSubgroups + '[^/]*)' ) * @param {String} pathStr A route path string to break into components * @returns {String[]} An array of route component strings */ -module.exports = pathStr => pathStr - // Divide a string like "/some/path/(?P)/etc" into an +module.exports = pathStr => { + let parts = [pathStr]; + // Find the named group. + const namedGroupMatch = pathStr.match(namedGroupRE); + if (namedGroupMatch) { + const namedGroup = namedGroupMatch[0]; + // Split the string into the parts surrounding the named group. + parts = pathStr.split(namedGroup); + // Add the named group into the array. + parts.splice(1, 0, namedGroup); + } + // This divides a string like "/some/path/(?P)/etc" into an // array `[ "/some/path/", "(?P)", "/etc" ]`. - .split( namedGroupRE ) + // Then, reduce through the array of parts, splitting any non-capture-group // parts on forward slashes and discarding empty strings to create the final // array of path components. - .reduce( ( components, part ) => { + return parts.reduce( ( components, part ) => { if ( ! part ) { // Ignore empty strings parts return components; @@ -50,3 +47,4 @@ module.exports = pathStr => pathStr // Split the part on / and filter out empty strings return components.concat( part.split( '/' ).filter( Boolean ) ); }, [] ); +} From d34081216cab7419ec9b1ef4c1599d638b44d999 Mon Sep 17 00:00:00 2001 From: hajamie Date: Wed, 8 May 2024 17:57:05 +0200 Subject: [PATCH 2/3] Missed a bit --- lib/util/split-path.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util/split-path.js b/lib/util/split-path.js index c98ba445..6d5341ad 100644 --- a/lib/util/split-path.js +++ b/lib/util/split-path.js @@ -3,7 +3,7 @@ */ 'use strict'; -const namedGroupPattern = require( './named-group-regexp' ).pattern; +const namedGroupRE = require( './named-group-regexp' ).namedGroupRE; /** * Divide a route string up into hierarchical components by breaking it apart From 84fc8f0239e7a10385bd420e4cd8e64494505b69 Mon Sep 17 00:00:00 2001 From: hajamie Date: Wed, 8 May 2024 18:00:10 +0200 Subject: [PATCH 3/3] Update named-group-regexp.js Match balanced parentheses to a couple of levels (https://stackoverflow.com/questions/546433/regular-expression-to-match-balanced-parentheses). --- lib/util/named-group-regexp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util/named-group-regexp.js b/lib/util/named-group-regexp.js index 3eaeb787..dc7372b7 100644 --- a/lib/util/named-group-regexp.js +++ b/lib/util/named-group-regexp.js @@ -14,7 +14,7 @@ const pattern = [ '[>\']', // Get everything up to the end of the capture group: this is the RegExp used // when matching URLs to this route, which we can use for validation purposes. - '([^\\)]*(\\))?)\\??', + '((?:[^)(]|\\((?:[^)(]|\\((?:[^)(]|\\([^)(]*\\))*\\))*\\))*)', // Capture group end '\\)', ].join( '' );