Socket
Socket
Sign inDemoInstall

path-to-regexp

Package Overview
Dependencies
Maintainers
5
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

path-to-regexp - npm Package Compare versions

Comparing version 5.0.0 to 6.0.0

305

dist.es2015/index.js
/**
* Default configs.
* Tokenize input string.
*/
var DEFAULT_DELIMITER = "/";
/**
* Balanced bracket helper function.
*/
function balanced(open, close, str, index) {
var count = 0;
var i = index;
function lexer(str) {
var tokens = [];
var i = 0;
while (i < str.length) {
if (str[i] === "\\") {
i += 2;
var char = str[i];
if (char === "*" || char === "+" || char === "?") {
tokens.push({ type: "MODIFIER", index: i, value: str[i++] });
continue;
}
if (str[i] === close) {
count--;
if (count === 0)
return i + 1;
if (char === "\\") {
tokens.push({ type: "ESCAPED_CHAR", index: i++, value: str[i++] });
continue;
}
if (str[i] === open) {
count++;
if (char === "{") {
tokens.push({ type: "OPEN", index: i, value: str[i++] });
continue;
}
i++;
}
return -1;
}
/**
* Parse a string for the raw tokens.
*/
export function parse(str, options) {
if (options === void 0) { options = {}; }
var _a, _b;
var tokens = [];
var defaultDelimiter = (_a = options.delimiter, (_a !== null && _a !== void 0 ? _a : DEFAULT_DELIMITER));
var whitelist = (_b = options.whitelist, (_b !== null && _b !== void 0 ? _b : undefined));
var i = 0;
var key = 0;
var path = "";
var isEscaped = false;
// tslint:disable-next-line
while (i < str.length) {
var prefix = "";
var name = "";
var pattern = "";
// Ignore escaped sequences.
if (str[i] === "\\") {
i++;
path += str[i++];
isEscaped = true;
if (char === "}") {
tokens.push({ type: "CLOSE", index: i, value: str[i++] });
continue;
}
if (str[i] === ":") {
while (++i < str.length) {
var code = str.charCodeAt(i);
if (char === ":") {
var name = "";
var j = i + 1;
while (j < str.length) {
var code = str.charCodeAt(j);
if (

@@ -65,3 +39,3 @@ // `0-9`

code === 95) {
name += str[i];
name += str[j++];
continue;

@@ -71,62 +45,131 @@ }

}
// False positive on param name.
if (!name)
i--;
throw new TypeError("Missing parameter name at " + i);
tokens.push({ type: "NAME", index: i, value: name });
i = j;
continue;
}
if (str[i] === "(") {
var end = balanced("(", ")", str, i);
// False positive on matching brackets.
if (end > -1) {
pattern = str.slice(i + 1, end - 1);
i = end;
if (pattern[0] === "?") {
throw new TypeError("Path pattern must be a capturing group");
if (char === "(") {
var count = 1;
var pattern = "";
var j = i + 1;
if (str[j] === "?") {
throw new TypeError("Pattern cannot start with \"?\" at " + j);
}
while (j < str.length) {
if (str[j] === "\\") {
pattern += str[j++] + str[j++];
continue;
}
if (/\((?=[^?])/.test(pattern)) {
var validPattern = pattern.replace(/\((?=[^?])/, "(?:");
throw new TypeError("Capturing groups are not allowed in pattern, use a non-capturing group: (" + validPattern + ")");
if (str[j] === ")") {
count--;
if (count === 0) {
j++;
break;
}
}
else if (str[j] === "(") {
count++;
if (str[j + 1] !== "?") {
throw new TypeError("Capturing groups are not allowed at " + j);
}
}
pattern += str[j++];
}
}
// Add regular characters to the path string.
if (name === "" && pattern === "") {
path += str[i++];
isEscaped = false;
if (count)
throw new TypeError("Unbalanced pattern at " + i);
if (!pattern)
throw new TypeError("Missing pattern at " + i);
tokens.push({ type: "PATTERN", index: i, value: pattern });
i = j;
continue;
}
// Extract the final character from `path` for the prefix.
if (path.length && !isEscaped) {
var char = path[path.length - 1];
var matches = whitelist ? whitelist.indexOf(char) > -1 : true;
if (matches) {
prefix = char;
path = path.slice(0, -1);
tokens.push({ type: "CHAR", index: i, value: str[i++] });
}
tokens.push({ type: "END", index: i, value: "" });
return tokens;
}
/**
* Parse a string for the raw tokens.
*/
export function parse(str, options) {
if (options === void 0) { options = {}; }
var tokens = lexer(str);
var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a;
var defaultPattern = "[^" + escapeString(options.delimiter || "/") + "]+?";
var result = [];
var key = 0;
var i = 0;
var path = "";
var tryConsume = function (type) {
if (i < tokens.length && tokens[i].type === type)
return tokens[i++].value;
};
var mustConsume = function (type) {
var value = tryConsume(type);
if (value !== undefined)
return value;
var _a = tokens[i], nextType = _a.type, index = _a.index;
throw new TypeError("Unexpected " + nextType + " at " + index + ", expected " + type);
};
var consumeText = function () {
var result = "";
var value;
// tslint:disable-next-line
while ((value = tryConsume("CHAR") || tryConsume("ESCAPED_CHAR"))) {
result += value;
}
return result;
};
while (i < tokens.length) {
var char = tryConsume("CHAR");
var name = tryConsume("NAME");
var pattern = tryConsume("PATTERN");
if (name || pattern) {
var prefix = char || "";
if (prefixes.indexOf(prefix) === -1) {
path += prefix;
prefix = "";
}
if (path) {
result.push(path);
path = "";
}
result.push({
name: name || key++,
prefix: prefix,
suffix: "",
pattern: pattern || defaultPattern,
modifier: tryConsume("MODIFIER") || ""
});
continue;
}
// Push the current path onto the list of tokens.
if (path.length) {
tokens.push(path);
var value = char || tryConsume("ESCAPED_CHAR");
if (value) {
path += value;
continue;
}
if (path) {
result.push(path);
path = "";
}
var repeat = str[i] === "+" || str[i] === "*";
var optional = str[i] === "?" || str[i] === "*";
var delimiter = prefix || defaultDelimiter;
// Increment `i` past modifier token.
if (repeat || optional)
i++;
tokens.push({
name: name || key++,
prefix: prefix,
delimiter: delimiter,
optional: optional,
repeat: repeat,
pattern: pattern ||
"[^" + escapeString(delimiter === defaultDelimiter
? delimiter
: delimiter + defaultDelimiter) + "]+?"
});
var open = tryConsume("OPEN");
if (open) {
var prefix = consumeText();
var name_1 = tryConsume("NAME") || "";
var pattern_1 = tryConsume("PATTERN") || "";
var suffix = consumeText();
mustConsume("CLOSE");
result.push({
name: name_1 || (pattern_1 ? key++ : ""),
pattern: name_1 && !pattern_1 ? defaultPattern : pattern_1,
prefix: prefix,
suffix: suffix,
modifier: tryConsume("MODIFIER") || ""
});
continue;
}
mustConsume("END");
}
if (path.length)
tokens.push(path);
return tokens;
return result;
}

@@ -161,8 +204,10 @@ /**

var value = data ? data[token.name] : undefined;
var optional = token.modifier === "?" || token.modifier === "*";
var repeat = token.modifier === "*" || token.modifier === "+";
if (Array.isArray(value)) {
if (!token.repeat) {
if (!repeat) {
throw new TypeError("Expected \"" + token.name + "\" to not repeat, but got an array");
}
if (value.length === 0) {
if (token.optional)
if (optional)
continue;

@@ -176,3 +221,3 @@ throw new TypeError("Expected \"" + token.name + "\" to not be empty");

}
path += (j === 0 ? token.prefix : token.delimiter) + segment;
path += token.prefix + segment + token.suffix;
}

@@ -186,8 +231,8 @@ continue;

}
path += token.prefix + segment;
path += token.prefix + segment + token.suffix;
continue;
}
if (token.optional)
if (optional)
continue;
var typeOfMessage = token.repeat ? "an array" : "a string";
var typeOfMessage = repeat ? "an array" : "a string";
throw new TypeError("Expected \"" + token.name + "\" to be " + typeOfMessage);

@@ -223,4 +268,4 @@ }

var key = keys[i - 1];
if (key.repeat) {
params[key.name] = m[i].split(key.delimiter).map(function (value) {
if (key.modifier === "*" || key.modifier === "+") {
params[key.name] = m[i].split(key.prefix + key.suffix).map(function (value) {
return decode(value, key);

@@ -264,5 +309,4 @@ });

prefix: "",
delimiter: "",
optional: false,
repeat: false,
suffix: "",
modifier: "",
pattern: ""

@@ -292,9 +336,5 @@ });

if (options === void 0) { options = {}; }
var strict = options.strict, _a = options.start, start = _a === void 0 ? true : _a, _b = options.end, end = _b === void 0 ? true : _b, _c = options.delimiter, delimiter = _c === void 0 ? DEFAULT_DELIMITER : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d;
var endsWith = (typeof options.endsWith === "string"
? options.endsWith.split("")
: options.endsWith || [])
.map(escapeString)
.concat("$")
.join("|");
var _a = options.strict, strict = _a === void 0 ? false : _a, _b = options.start, start = _b === void 0 ? true : _b, _c = options.end, end = _c === void 0 ? true : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d;
var endsWith = "[" + escapeString(options.endsWith || "") + "]|$";
var delimiter = "[" + escapeString(options.delimiter || "/") + "]";
var route = start ? "^" : "";

@@ -308,17 +348,22 @@ // Iterate over the tokens and create our regexp string.

else {
var capture = token.repeat
? "(?:" + token.pattern + ")(?:" + escapeString(token.delimiter) + "(?:" + token.pattern + "))*"
: token.pattern;
if (keys)
keys.push(token);
if (token.optional) {
if (!token.prefix) {
route += "(" + capture + ")?";
var prefix = escapeString(encode(token.prefix));
var suffix = escapeString(encode(token.suffix));
if (token.pattern) {
if (keys)
keys.push(token);
if (prefix || suffix) {
if (token.modifier === "+" || token.modifier === "*") {
var mod = token.modifier === "*" ? "?" : "";
route += "(?:" + prefix + "((?:" + token.pattern + ")(?:" + suffix + prefix + "(?:" + token.pattern + "))*)" + suffix + ")" + mod;
}
else {
route += "(?:" + prefix + "(" + token.pattern + ")" + suffix + ")" + token.modifier;
}
}
else {
route += "(?:" + escapeString(token.prefix) + "(" + capture + "))?";
route += "(" + token.pattern + ")" + token.modifier;
}
}
else {
route += escapeString(token.prefix) + "(" + capture + ")";
route += "(?:" + prefix + suffix + ")" + token.modifier;
}

@@ -329,3 +374,3 @@ }

if (!strict)
route += "(?:" + escapeString(delimiter) + ")?";
route += delimiter + "?";
route += endsWith === "$" ? "$" : "(?=" + endsWith + ")";

@@ -336,10 +381,10 @@ }

var isEndDelimited = typeof endToken === "string"
? endToken[endToken.length - 1] === delimiter
? delimiter.indexOf(endToken[endToken.length - 1]) > -1
: // tslint:disable-next-line
endToken === undefined;
if (!strict) {
route += "(?:" + escapeString(delimiter) + "(?=" + endsWith + "))?";
route += "(?:" + delimiter + "(?=" + endsWith + "))?";
}
if (!isEndDelimited) {
route += "(?=" + escapeString(delimiter) + "|" + endsWith + ")";
route += "(?=" + delimiter + "|" + endsWith + ")";
}

@@ -357,10 +402,8 @@ }

export function pathToRegexp(path, keys, options) {
if (path instanceof RegExp) {
if (path instanceof RegExp)
return regexpToRegexp(path, keys);
}
if (Array.isArray(path)) {
if (Array.isArray(path))
return arrayToRegexp(path, keys, options);
}
return stringToRegexp(path, keys, options);
}
//# sourceMappingURL=index.js.map

@@ -7,5 +7,5 @@ export interface ParseOptions {

/**
* List of characters to consider delimiters when parsing. (default: `undefined`, any character)
* List of characters to automatically consider prefixes when parsing.
*/
whitelist?: string | string[];
prefixes?: string;
}

@@ -75,6 +75,5 @@ /**

prefix: string;
delimiter: string;
optional: boolean;
repeat: boolean;
suffix: string;
pattern: string;
modifier: string;
}

@@ -109,3 +108,3 @@ /**

*/
endsWith?: string | string[];
endsWith?: string;
/**

@@ -112,0 +111,0 @@ * Encode path tokens for use in the `RegExp`.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Default configs.
* Tokenize input string.
*/
var DEFAULT_DELIMITER = "/";
/**
* Balanced bracket helper function.
*/
function balanced(open, close, str, index) {
var count = 0;
var i = index;
function lexer(str) {
var tokens = [];
var i = 0;
while (i < str.length) {
if (str[i] === "\\") {
i += 2;
var char = str[i];
if (char === "*" || char === "+" || char === "?") {
tokens.push({ type: "MODIFIER", index: i, value: str[i++] });
continue;
}
if (str[i] === close) {
count--;
if (count === 0)
return i + 1;
if (char === "\\") {
tokens.push({ type: "ESCAPED_CHAR", index: i++, value: str[i++] });
continue;
}
if (str[i] === open) {
count++;
if (char === "{") {
tokens.push({ type: "OPEN", index: i, value: str[i++] });
continue;
}
i++;
}
return -1;
}
/**
* Parse a string for the raw tokens.
*/
function parse(str, options) {
if (options === void 0) { options = {}; }
var _a, _b;
var tokens = [];
var defaultDelimiter = (_a = options.delimiter, (_a !== null && _a !== void 0 ? _a : DEFAULT_DELIMITER));
var whitelist = (_b = options.whitelist, (_b !== null && _b !== void 0 ? _b : undefined));
var i = 0;
var key = 0;
var path = "";
var isEscaped = false;
// tslint:disable-next-line
while (i < str.length) {
var prefix = "";
var name = "";
var pattern = "";
// Ignore escaped sequences.
if (str[i] === "\\") {
i++;
path += str[i++];
isEscaped = true;
if (char === "}") {
tokens.push({ type: "CLOSE", index: i, value: str[i++] });
continue;
}
if (str[i] === ":") {
while (++i < str.length) {
var code = str.charCodeAt(i);
if (char === ":") {
var name = "";
var j = i + 1;
while (j < str.length) {
var code = str.charCodeAt(j);
if (

@@ -67,3 +41,3 @@ // `0-9`

code === 95) {
name += str[i];
name += str[j++];
continue;

@@ -73,62 +47,131 @@ }

}
// False positive on param name.
if (!name)
i--;
throw new TypeError("Missing parameter name at " + i);
tokens.push({ type: "NAME", index: i, value: name });
i = j;
continue;
}
if (str[i] === "(") {
var end = balanced("(", ")", str, i);
// False positive on matching brackets.
if (end > -1) {
pattern = str.slice(i + 1, end - 1);
i = end;
if (pattern[0] === "?") {
throw new TypeError("Path pattern must be a capturing group");
if (char === "(") {
var count = 1;
var pattern = "";
var j = i + 1;
if (str[j] === "?") {
throw new TypeError("Pattern cannot start with \"?\" at " + j);
}
while (j < str.length) {
if (str[j] === "\\") {
pattern += str[j++] + str[j++];
continue;
}
if (/\((?=[^?])/.test(pattern)) {
var validPattern = pattern.replace(/\((?=[^?])/, "(?:");
throw new TypeError("Capturing groups are not allowed in pattern, use a non-capturing group: (" + validPattern + ")");
if (str[j] === ")") {
count--;
if (count === 0) {
j++;
break;
}
}
else if (str[j] === "(") {
count++;
if (str[j + 1] !== "?") {
throw new TypeError("Capturing groups are not allowed at " + j);
}
}
pattern += str[j++];
}
}
// Add regular characters to the path string.
if (name === "" && pattern === "") {
path += str[i++];
isEscaped = false;
if (count)
throw new TypeError("Unbalanced pattern at " + i);
if (!pattern)
throw new TypeError("Missing pattern at " + i);
tokens.push({ type: "PATTERN", index: i, value: pattern });
i = j;
continue;
}
// Extract the final character from `path` for the prefix.
if (path.length && !isEscaped) {
var char = path[path.length - 1];
var matches = whitelist ? whitelist.indexOf(char) > -1 : true;
if (matches) {
prefix = char;
path = path.slice(0, -1);
tokens.push({ type: "CHAR", index: i, value: str[i++] });
}
tokens.push({ type: "END", index: i, value: "" });
return tokens;
}
/**
* Parse a string for the raw tokens.
*/
function parse(str, options) {
if (options === void 0) { options = {}; }
var tokens = lexer(str);
var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a;
var defaultPattern = "[^" + escapeString(options.delimiter || "/") + "]+?";
var result = [];
var key = 0;
var i = 0;
var path = "";
var tryConsume = function (type) {
if (i < tokens.length && tokens[i].type === type)
return tokens[i++].value;
};
var mustConsume = function (type) {
var value = tryConsume(type);
if (value !== undefined)
return value;
var _a = tokens[i], nextType = _a.type, index = _a.index;
throw new TypeError("Unexpected " + nextType + " at " + index + ", expected " + type);
};
var consumeText = function () {
var result = "";
var value;
// tslint:disable-next-line
while ((value = tryConsume("CHAR") || tryConsume("ESCAPED_CHAR"))) {
result += value;
}
return result;
};
while (i < tokens.length) {
var char = tryConsume("CHAR");
var name = tryConsume("NAME");
var pattern = tryConsume("PATTERN");
if (name || pattern) {
var prefix = char || "";
if (prefixes.indexOf(prefix) === -1) {
path += prefix;
prefix = "";
}
if (path) {
result.push(path);
path = "";
}
result.push({
name: name || key++,
prefix: prefix,
suffix: "",
pattern: pattern || defaultPattern,
modifier: tryConsume("MODIFIER") || ""
});
continue;
}
// Push the current path onto the list of tokens.
if (path.length) {
tokens.push(path);
var value = char || tryConsume("ESCAPED_CHAR");
if (value) {
path += value;
continue;
}
if (path) {
result.push(path);
path = "";
}
var repeat = str[i] === "+" || str[i] === "*";
var optional = str[i] === "?" || str[i] === "*";
var delimiter = prefix || defaultDelimiter;
// Increment `i` past modifier token.
if (repeat || optional)
i++;
tokens.push({
name: name || key++,
prefix: prefix,
delimiter: delimiter,
optional: optional,
repeat: repeat,
pattern: pattern ||
"[^" + escapeString(delimiter === defaultDelimiter
? delimiter
: delimiter + defaultDelimiter) + "]+?"
});
var open = tryConsume("OPEN");
if (open) {
var prefix = consumeText();
var name_1 = tryConsume("NAME") || "";
var pattern_1 = tryConsume("PATTERN") || "";
var suffix = consumeText();
mustConsume("CLOSE");
result.push({
name: name_1 || (pattern_1 ? key++ : ""),
pattern: name_1 && !pattern_1 ? defaultPattern : pattern_1,
prefix: prefix,
suffix: suffix,
modifier: tryConsume("MODIFIER") || ""
});
continue;
}
mustConsume("END");
}
if (path.length)
tokens.push(path);
return tokens;
return result;
}

@@ -165,8 +208,10 @@ exports.parse = parse;

var value = data ? data[token.name] : undefined;
var optional = token.modifier === "?" || token.modifier === "*";
var repeat = token.modifier === "*" || token.modifier === "+";
if (Array.isArray(value)) {
if (!token.repeat) {
if (!repeat) {
throw new TypeError("Expected \"" + token.name + "\" to not repeat, but got an array");
}
if (value.length === 0) {
if (token.optional)
if (optional)
continue;

@@ -180,3 +225,3 @@ throw new TypeError("Expected \"" + token.name + "\" to not be empty");

}
path += (j === 0 ? token.prefix : token.delimiter) + segment;
path += token.prefix + segment + token.suffix;
}

@@ -190,8 +235,8 @@ continue;

}
path += token.prefix + segment;
path += token.prefix + segment + token.suffix;
continue;
}
if (token.optional)
if (optional)
continue;
var typeOfMessage = token.repeat ? "an array" : "a string";
var typeOfMessage = repeat ? "an array" : "a string";
throw new TypeError("Expected \"" + token.name + "\" to be " + typeOfMessage);

@@ -229,4 +274,4 @@ }

var key = keys[i - 1];
if (key.repeat) {
params[key.name] = m[i].split(key.delimiter).map(function (value) {
if (key.modifier === "*" || key.modifier === "+") {
params[key.name] = m[i].split(key.prefix + key.suffix).map(function (value) {
return decode(value, key);

@@ -271,5 +316,4 @@ });

prefix: "",
delimiter: "",
optional: false,
repeat: false,
suffix: "",
modifier: "",
pattern: ""

@@ -299,9 +343,5 @@ });

if (options === void 0) { options = {}; }
var strict = options.strict, _a = options.start, start = _a === void 0 ? true : _a, _b = options.end, end = _b === void 0 ? true : _b, _c = options.delimiter, delimiter = _c === void 0 ? DEFAULT_DELIMITER : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d;
var endsWith = (typeof options.endsWith === "string"
? options.endsWith.split("")
: options.endsWith || [])
.map(escapeString)
.concat("$")
.join("|");
var _a = options.strict, strict = _a === void 0 ? false : _a, _b = options.start, start = _b === void 0 ? true : _b, _c = options.end, end = _c === void 0 ? true : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d;
var endsWith = "[" + escapeString(options.endsWith || "") + "]|$";
var delimiter = "[" + escapeString(options.delimiter || "/") + "]";
var route = start ? "^" : "";

@@ -315,17 +355,22 @@ // Iterate over the tokens and create our regexp string.

else {
var capture = token.repeat
? "(?:" + token.pattern + ")(?:" + escapeString(token.delimiter) + "(?:" + token.pattern + "))*"
: token.pattern;
if (keys)
keys.push(token);
if (token.optional) {
if (!token.prefix) {
route += "(" + capture + ")?";
var prefix = escapeString(encode(token.prefix));
var suffix = escapeString(encode(token.suffix));
if (token.pattern) {
if (keys)
keys.push(token);
if (prefix || suffix) {
if (token.modifier === "+" || token.modifier === "*") {
var mod = token.modifier === "*" ? "?" : "";
route += "(?:" + prefix + "((?:" + token.pattern + ")(?:" + suffix + prefix + "(?:" + token.pattern + "))*)" + suffix + ")" + mod;
}
else {
route += "(?:" + prefix + "(" + token.pattern + ")" + suffix + ")" + token.modifier;
}
}
else {
route += "(?:" + escapeString(token.prefix) + "(" + capture + "))?";
route += "(" + token.pattern + ")" + token.modifier;
}
}
else {
route += escapeString(token.prefix) + "(" + capture + ")";
route += "(?:" + prefix + suffix + ")" + token.modifier;
}

@@ -336,3 +381,3 @@ }

if (!strict)
route += "(?:" + escapeString(delimiter) + ")?";
route += delimiter + "?";
route += endsWith === "$" ? "$" : "(?=" + endsWith + ")";

@@ -343,10 +388,10 @@ }

var isEndDelimited = typeof endToken === "string"
? endToken[endToken.length - 1] === delimiter
? delimiter.indexOf(endToken[endToken.length - 1]) > -1
: // tslint:disable-next-line
endToken === undefined;
if (!strict) {
route += "(?:" + escapeString(delimiter) + "(?=" + endsWith + "))?";
route += "(?:" + delimiter + "(?=" + endsWith + "))?";
}
if (!isEndDelimited) {
route += "(?=" + escapeString(delimiter) + "|" + endsWith + ")";
route += "(?=" + delimiter + "|" + endsWith + ")";
}

@@ -365,8 +410,6 @@ }

function pathToRegexp(path, keys, options) {
if (path instanceof RegExp) {
if (path instanceof RegExp)
return regexpToRegexp(path, keys);
}
if (Array.isArray(path)) {
if (Array.isArray(path))
return arrayToRegexp(path, keys, options);
}
return stringToRegexp(path, keys, options);

@@ -373,0 +416,0 @@ }

{
"name": "path-to-regexp",
"description": "Express style path to RegExp utility",
"version": "5.0.0",
"version": "6.0.0",
"main": "dist/index.js",

@@ -37,3 +37,3 @@ "typings": "dist/index.d.ts",

"path": "dist/index.js",
"limit": "1.75 kB"
"limit": "2 kB"
}

@@ -40,0 +40,0 @@ ],

@@ -36,6 +36,6 @@ # Path-to-RegExp

- **start** When `true` the regexp will match from the beginning of the string. (default: `true`)
- **delimiter** The default delimiter for segments. (default: `'/'`)
- **delimiter** The default delimiter for segments, e.g. `[^/]` for `:named` patterns. (default: `'/'`)
- **endsWith** Optional character, or list of characters, to treat as "end" characters.
- **whitelist** List of characters to consider delimiters when parsing. (default: `undefined`, any character)
- **encode** A function to encode strings before inserting into `RegExp`. (default: `x => x`)
- **prefixes** List of characters to automatically consider prefixes when parsing. (default: `./`)

@@ -53,7 +53,7 @@ ```javascript

The path argument is used to define parameters and populate the list of keys.
The path argument is used to define parameters and populate keys.
#### Named Parameters
Named parameters are defined by prefixing a colon to the parameter name (`:foo`). By default, the parameter will match until the next prefix (e.g. `[^/]+`).
Named parameters are defined by prefixing a colon to the parameter name (`:foo`).

@@ -70,4 +70,58 @@ ```js

#### Parameter Modifiers
##### Custom Matching Parameters
Parameters can have a custom regexp, which overrides the default match (`[^/]+`). For example, you can match digits or names in a path:
```js
const regexpNumbers = pathToRegexp("/icon-:foo(\\d+).png");
// keys = [{ name: 'foo', ... }]
regexpNumbers.exec("/icon-123.png");
//=> ['/icon-123.png', '123']
regexpNumbers.exec("/icon-abc.png");
//=> null
const regexpWord = pathToRegexp("/(user|u)");
// keys = [{ name: 0, ... }]
regexpWord.exec("/u");
//=> ['/u', 'u']
regexpWord.exec("/users");
//=> null
```
**Tip:** Backslashes need to be escaped with another backslash in JavaScript strings.
##### Custom Prefix and Suffix
Parameters can be wrapped in `{}` to create custom prefixes or suffixes for your segment:
```js
const regexp = pathToRegexp("/:attr1?{-:attr2}?{-:attr3}?");
regexp.exec("/test");
// => ['/test', 'test', undefined, undefined]
regexp.exec("/test-test");
// => ['/test', 'test', 'test', undefined]
```
#### Unnamed Parameters
It is possible to write an unnamed parameter that only consists of a regexp. It works the same the named parameter, except it will be numerically indexed:
```js
const regexp = pathToRegexp("/:foo/(.*)");
// keys = [{ name: 'foo', ... }, { name: 0, ... }]
regexp.exec("/test/route");
//=> [ '/test/route', 'test', 'route', index: 0, input: '/test/route', groups: undefined ]
```
#### Modifiers
Modifiers must be placed after the parameter (e.g. `/:foo?`, `/(test)?`, or `/:foo(test)?`).
##### Optional

@@ -92,3 +146,3 @@

Parameters can be suffixed with an asterisk (`*`) to denote a zero or more parameter matches. The prefix is used for each match.
Parameters can be suffixed with an asterisk (`*`) to denote a zero or more parameter matches.

@@ -108,3 +162,3 @@ ```js

Parameters can be suffixed with a plus sign (`+`) to denote a one or more parameter matches. The prefix is used for each match.
Parameters can be suffixed with a plus sign (`+`) to denote a one or more parameter matches.

@@ -122,58 +176,32 @@ ```js

#### Unnamed Parameters
### Match
It is possible to write an unnamed parameter that only consists of a matching group. It works the same as a named parameter, except it will be numerically indexed.
The `match` function will return a function for transforming paths into parameters:
```js
const regexp = pathToRegexp("/:foo/(.*)");
// keys = [{ name: 'foo', ... }, { name: 0, ... }]
// Make sure you consistently `decode` segments.
const match = match("/user/:id", { decode: decodeURIComponent });
regexp.exec("/test/route");
//=> [ '/test/route', 'test', 'route', index: 0, input: '/test/route', groups: undefined ]
match("/user/123"); //=> { path: '/user/123', index: 0, params: { id: '123' } }
match("/invalid"); //=> false
match("/user/caf%C3%A9"); //=> { path: '/user/caf%C3%A9', index: 0, params: { id: 'café' } }
```
#### Custom Matching Parameters
#### Process Pathname
All parameters can have a custom regexp, which overrides the default match (`[^/]+`). For example, you can match digits or names in a path:
You should make sure variations of the same path match the expected `path`. Here's one possible solution using `encode`:
```js
const regexpNumbers = pathToRegexp("/icon-:foo(\\d+).png");
// keys = [{ name: 'foo', ... }]
const match = match("/café", { encode: encodeURI, decode: decodeURIComponent });
regexpNumbers.exec("/icon-123.png");
//=> ['/icon-123.png', '123']
regexpNumbers.exec("/icon-abc.png");
//=> null
const regexpWord = pathToRegexp("/(user|u)");
// keys = [{ name: 0, ... }]
regexpWord.exec("/u");
//=> ['/u', 'u']
regexpWord.exec("/users");
//=> null
match("/user/caf%C3%A9"); //=> { path: '/user/caf%C3%A9', index: 0, params: { id: 'café' } }
```
**Tip:** Backslashes need to be escaped with another backslash in JavaScript strings.
**Note:** [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) automatically encodes pathnames for you.
### Match
##### Alternative Using Normalize
The `match` function will return a function for transforming paths into parameters:
Sometimes you won't have an already normalized pathname. You can normalize it yourself before processing:
```js
// Make sure you consistently `decode` segments.
const match = match("/user/:id", { decode: decodeURIComponent });
match("/user/123"); //=> { path: '/user/123', index: 0, params: { id: '123' } }
match("/invalid"); //=> false
match("/user/caf%C3%A9"); //=> { path: '/user/caf%C3%A9', index: 0, params: { id: 'café' } }
```
#### Normalize Pathname
You should make sure variations of the same path to match your input `path`. Here's one possible solution:
```js
/**

@@ -195,2 +223,3 @@ * Normalize a pathname for matching, replaces multiple slashes with a single

// Two possible ways of writing `/café`:
const re = pathToRegexp("/caf\u00E9");

@@ -203,4 +232,2 @@ const input = encodeURI("/cafe\u0301");

**Note:** [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) automatically encodes pathnames for you, which would result in a consistent match if you use `encodeURI` in `pathToRegexp` options.
### Parse

@@ -258,7 +285,7 @@

**Note:** The generated function will throw on invalid input. It will do all necessary checks to ensure the generated path is valid. This method only works with strings.
**Note:** The generated function will throw on invalid input.
### Working with Tokens
Path-To-RegExp exposes the two functions used internally that accept an array of tokens.
Path-To-RegExp exposes the two functions used internally that accept an array of tokens:

@@ -271,7 +298,6 @@ - `tokensToRegexp(tokens, keys?, options?)` Transform an array of tokens into a matching regular expression.

- `name` The name of the token (`string` for named or `number` for unnamed index)
- `prefix` The prefix character for the segment (e.g. `/`)
- `delimiter` The delimiter for the segment (same as prefix or default delimiter)
- `optional` Indicates the token is optional (`boolean`)
- `repeat` Indicates the token is repeated (`boolean`)
- `prefix` The prefix string for the segment (e.g. `"/"`)
- `suffix` The suffix string for the segment (e.g. `""`)
- `pattern` The RegExp used to match this token (`string`)
- `modifier` The modifier character used for the segment (e.g. `?`)

@@ -278,0 +304,0 @@ ## Compatibility with Express <= 4.x

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

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 too big to display

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