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

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 7.0.0 to 7.1.0

35

dist/index.d.ts

@@ -11,7 +11,7 @@ /**

/**
* Set the default delimiter for repeat parameters. (default: `'/'`)
* The default delimiter for segments. (default: `'/'`)
*/
delimiter?: string;
/**
* Function for encoding input strings for output into path.
* A function for encoding input strings.
*/

@@ -22,20 +22,24 @@ encodePath?: Encode;

/**
* When `true` the regexp will be case sensitive. (default: `false`)
* Regexp will be case sensitive. (default: `false`)
*/
sensitive?: boolean;
/**
* Allow delimiter to be arbitrarily repeated. (default: `true`)
* Allow the delimiter to be arbitrarily repeated. (default: `true`)
*/
loose?: boolean;
/**
* When `true` the regexp will match to the end of the string. (default: `true`)
* Verify patterns are valid and safe to use. (default: `false`)
*/
end?: boolean;
strict?: boolean;
/**
* When `true` the regexp will match from the beginning of the string. (default: `true`)
* Match from the beginning of the string. (default: `true`)
*/
start?: boolean;
/**
* When `true` the regexp allows an optional trailing delimiter to match. (default: `true`)
* Match to the end of the string. (default: `true`)
*/
end?: boolean;
/**
* Allow optional trailing delimiter to match. (default: `true`)
*/
trailing?: boolean;

@@ -51,12 +55,16 @@ }

/**
* When `true` the validation will be case sensitive. (default: `false`)
* Regexp will be case sensitive. (default: `false`)
*/
sensitive?: boolean;
/**
* Allow delimiter to be arbitrarily repeated. (default: `true`)
* Allow the delimiter to be arbitrarily repeated. (default: `true`)
*/
loose?: boolean;
/**
* When `false` the function can produce an invalid (unmatched) path. (default: `true`)
* Verify patterns are valid and safe to use. (default: `false`)
*/
strict?: boolean;
/**
* Verifies the function is producing a valid path. (default: `true`)
*/
validate?: boolean;

@@ -83,3 +91,3 @@ /**

*/
export declare function compile<P extends object = object>(path: Path, options?: CompileOptions): PathFunction<P>;
export declare function compile<P extends ParamData = ParamData>(path: Path, options?: CompileOptions): PathFunction<P>;
export type ParamData = Partial<Record<string, string | string[]>>;

@@ -126,5 +134,2 @@ export type PathFunction<P extends ParamData> = (data?: P) => string;

export type Path = string | TokenData;
export type PathRegExp = RegExp & {
keys: Key[];
};
/**

@@ -131,0 +136,0 @@ * Normalize the given path string, returning a regular expression.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pathToRegexp = exports.match = exports.compile = exports.parse = exports.TokenData = void 0;
exports.TokenData = void 0;
exports.parse = parse;
exports.compile = compile;
exports.match = match;
exports.pathToRegexp = pathToRegexp;
const DEFAULT_DELIMITER = "/";
const NOOP_VALUE = (value) => value;
const ID_CHAR = /^\p{XID_Continue}$/u;
const DEBUG_URL = "https://git.new/pathToRegexpError";
const SIMPLE_TOKENS = {

@@ -106,3 +111,3 @@ "!": "!",

const { type: nextType, index } = this.peek();
throw new TypeError(`Unexpected ${nextType} at ${index}, expected ${type}: https://git.new/pathToRegexpError`);
throw new TypeError(`Unexpected ${nextType} at ${index}, expected ${type}: ${DEBUG_URL}`);
}

@@ -118,3 +123,3 @@ text() {

modifier() {
return (this.tryConsume("?") || this.tryConsume("*") || this.tryConsume("+") || "");
return this.tryConsume("?") || this.tryConsume("*") || this.tryConsume("+");
}

@@ -136,3 +141,3 @@ }

function parse(str, options = {}) {
const { delimiter = DEFAULT_DELIMITER, encodePath = NOOP_VALUE } = options;
const { encodePath = NOOP_VALUE, delimiter = encodePath(DEFAULT_DELIMITER) } = options;
const tokens = [];

@@ -154,3 +159,3 @@ const it = lexer(str);

if (next.type === "*") {
throw new TypeError(`Unexpected * at ${next.index}, you probably want \`/*\` or \`{/:foo}*\`: https://git.new/pathToRegexpError`);
throw new TypeError(`Unexpected * at ${next.index}, you probably want \`/*\` or \`{/:foo}*\`: ${DEBUG_URL}`);
}

@@ -163,3 +168,3 @@ continue;

name: String(key++),
pattern: `[^${escape(delimiter)}]*`,
pattern: `(?:(?!${escape(delimiter)}).)*`,
modifier: "*",

@@ -176,3 +181,3 @@ separator: delimiter,

const suffix = it.text();
const separator = it.tryConsume(";") ? it.text() : prefix + suffix;
const separator = it.tryConsume(";") && it.text();
it.consume("}");

@@ -195,3 +200,2 @@ const modifier = it.modifier();

}
exports.parse = parse;
/**

@@ -204,3 +208,2 @@ * Compile a string to a template function for the path.

}
exports.compile = compile;
/**

@@ -216,3 +219,3 @@ * Convert a single token into a path building function.

const optional = token.modifier === "?" || token.modifier === "*";
const { prefix = "", suffix = "", separator = "" } = token;
const { prefix = "", suffix = "", separator = suffix + prefix } = token;
if (encode && repeated) {

@@ -269,13 +272,12 @@ const stringify = (value, index) => {

function compileTokens(data, options) {
const { encode = encodeURIComponent, loose = true, validate = true, } = options;
const reFlags = flags(options);
const { encode = encodeURIComponent, loose = true, validate = true, strict = false, } = options;
const flags = toFlags(options);
const stringify = toStringify(loose, data.delimiter);
const keyToRegexp = toKeyRegexp(stringify, data.delimiter);
const sources = toRegExpSource(data, stringify, [], flags, strict);
// Compile all the tokens into regexps.
const encoders = data.tokens.map((token) => {
const encoders = data.tokens.map((token, index) => {
const fn = tokenToFunction(token, encode);
if (!validate || typeof token === "string")
return fn;
const pattern = keyToRegexp(token);
const validRe = new RegExp(`^${pattern}$`, reFlags);
const validRe = new RegExp(`^${sources[index]}$`, flags);
return (data) => {

@@ -307,3 +309,4 @@ const value = fn(data);

if (decode && (key.modifier === "+" || key.modifier === "*")) {
const re = new RegExp(stringify(key.separator || ""), "g");
const { prefix = "", suffix = "", separator = suffix + prefix } = key;
const re = new RegExp(stringify(separator), "g");
return (value) => value.split(re).map(decode);

@@ -313,4 +316,4 @@ }

});
return function match(pathname) {
const m = re.exec(pathname);
return function match(input) {
const m = re.exec(input);
if (!m)

@@ -330,3 +333,2 @@ return false;

}
exports.match = match;
/**

@@ -336,3 +338,3 @@ * Escape a regular expression string.

function escape(str) {
return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
return str.replace(/([.+*?^${}()[\]|/\\])/g, "\\$1");
}

@@ -343,3 +345,4 @@ /**

function looseReplacer(value, loose) {
return loose ? `${escape(value)}+` : escape(value);
const escaped = escape(value);
return loose ? `(?:${escaped})+(?!${escaped})` : escaped;
}

@@ -352,3 +355,3 @@ /**

return escape;
const re = new RegExp(`[^${escape(delimiter)}]+|(.)`, "g");
const re = new RegExp(`(?:(?!${escape(delimiter)}).)+|(.)`, "g");
return (value) => value.replace(re, looseReplacer);

@@ -359,3 +362,3 @@ }

*/
function flags(options) {
function toFlags(options) {
return options.sensitive ? "" : "i";

@@ -367,20 +370,12 @@ }

function tokensToRegexp(data, keys, options) {
const { trailing = true, start = true, end = true, loose = true } = options;
const { trailing = true, loose = true, start = true, end = true, strict = false, } = options;
const flags = toFlags(options);
const stringify = toStringify(loose, data.delimiter);
const keyToRegexp = toKeyRegexp(stringify, data.delimiter);
const sources = toRegExpSource(data, stringify, keys, flags, strict);
let pattern = start ? "^" : "";
for (const token of data.tokens) {
if (typeof token === "string") {
pattern += stringify(token);
}
else {
if (token.name)
keys.push(token);
pattern += keyToRegexp(token);
}
}
pattern += sources.join("");
if (trailing)
pattern += `(?:${stringify(data.delimiter)})?`;
pattern += end ? "$" : `(?=${escape(data.delimiter)}|$)`;
return new RegExp(pattern, flags(options));
return new RegExp(pattern, flags);
}

@@ -390,20 +385,53 @@ /**

*/
function toKeyRegexp(stringify, delimiter) {
const segmentPattern = `[^${escape(delimiter)}]+?`;
return (key) => {
const prefix = key.prefix ? stringify(key.prefix) : "";
const suffix = key.suffix ? stringify(key.suffix) : "";
const modifier = key.modifier || "";
if (key.name) {
const pattern = key.pattern || segmentPattern;
if (key.modifier === "+" || key.modifier === "*") {
const mod = key.modifier === "*" ? "?" : "";
const split = key.separator ? stringify(key.separator) : "";
return `(?:${prefix}((?:${pattern})(?:${split}(?:${pattern}))*)${suffix})${mod}`;
function toRegExpSource(data, stringify, keys, flags, strict) {
const defaultPattern = `(?:(?!${escape(data.delimiter)}).)+?`;
let backtrack = "";
let safe = true;
return data.tokens.map((token, index) => {
if (typeof token === "string") {
backtrack = token;
return stringify(token);
}
const { prefix = "", suffix = "", separator = suffix + prefix, modifier = "", } = token;
const pre = stringify(prefix);
const post = stringify(suffix);
if (token.name) {
const pattern = token.pattern ? `(?:${token.pattern})` : defaultPattern;
const re = checkPattern(pattern, token.name, flags);
safe || (safe = safePattern(re, prefix || backtrack));
if (!safe) {
throw new TypeError(`Ambiguous pattern for "${token.name}": ${DEBUG_URL}`);
}
return `(?:${prefix}(${pattern})${suffix})${modifier}`;
safe = !strict || safePattern(re, suffix);
backtrack = "";
keys.push(token);
if (modifier === "+" || modifier === "*") {
const mod = modifier === "*" ? "?" : "";
const sep = stringify(separator);
if (!sep) {
throw new TypeError(`Missing separator for "${token.name}": ${DEBUG_URL}`);
}
safe || (safe = !strict || safePattern(re, separator));
if (!safe) {
throw new TypeError(`Ambiguous pattern for "${token.name}" separator: ${DEBUG_URL}`);
}
safe = !strict;
return `(?:${pre}(${pattern}(?:${sep}${pattern})*)${post})${mod}`;
}
return `(?:${pre}(${pattern})${post})${modifier}`;
}
return `(?:${prefix}${suffix})${modifier}`;
};
return `(?:${pre}${post})${modifier}`;
});
}
function checkPattern(pattern, name, flags) {
try {
return new RegExp(`^${pattern}$`, flags);
}
catch (err) {
throw new TypeError(`Invalid pattern for "${name}": ${err.message}`);
}
}
function safePattern(re, value) {
return value ? !re.test(value) : false;
}
/**

@@ -422,3 +450,2 @@ * Normalize the given path string, returning a regular expression.

}
exports.pathToRegexp = pathToRegexp;
//# sourceMappingURL=index.js.map
{
"name": "path-to-regexp",
"version": "7.0.0",
"version": "7.1.0",
"description": "Express style path to RegExp utility",

@@ -37,4 +37,5 @@ "keywords": [

"@vitest/coverage-v8": "^1.4.0",
"recheck": "^4.4.5",
"size-limit": "^11.1.2",
"typescript": "^5.1.6"
"typescript": "^5.5.3"
},

@@ -41,0 +42,0 @@ "engines": {

@@ -35,8 +35,9 @@ # Path-to-RegExp

- **sensitive** Regexp will be case sensitive. (default: `false`)
- **trailing** Regexp allows an optional trailing delimiter to match. (default: `true`)
- **trailing** Allows optional trailing delimiter to match. (default: `true`)
- **strict** Verify patterns are valid and safe to use. (default: `false`, recommended: `true`)
- **end** Match to the end of the string. (default: `true`)
- **start** Match from the beginning of the string. (default: `true`)
- **loose** Allow the delimiter to be repeated an arbitrary number of times. (default: `true`)
- **loose** Allow the delimiter to be arbitrarily repeated, e.g. `/` or `///`. (default: `true`)
- **delimiter** The default delimiter for segments, e.g. `[^/]` for `:named` parameters. (default: `'/'`)
- **encodePath** A function to encode strings before inserting into `RegExp`. (default: `x => x`, recommended: [`encodeurl`](https://github.com/pillarjs/encodeurl))
- **encodePath** A function for encoding input strings. (default: `x => x`, recommended: [`encodeurl`](https://github.com/pillarjs/encodeurl) for unicode encoding)

@@ -168,2 +169,16 @@ ```js

##### Custom separator
By default, parameters set the separator as the `prefix + suffix` of the token. Using `;` you can modify this:
```js
const regexp = pathToRegexp("/name{/:parts;-}+");
regexp.exec("/name");
//=> null
regexp.exec("/bar/1-2-3");
//=> [ '/name/1-2-3', '1-2-3', index: 0 ]
```
#### Wildcard

@@ -193,4 +208,3 @@

```js
// Make sure you consistently `decode` segments.
const fn = match("/user/:id", { decode: decodeURIComponent });
const fn = match("/user/:id");

@@ -216,5 +230,4 @@ fn("/user/123"); //=> { path: '/user/123', index: 0, params: { id: '123' } }

toPath({ id: 123 }); //=> "/user/123"
toPath({ id: "name" }); //=> "/user/name"
toPath({ id: "café" }); //=> "/user/caf%C3%A9"
toPath({ id: ":/" }); //=> "/user/%3A%2F"

@@ -225,3 +238,3 @@ // When disabling `encode`, you need to make sure inputs are encoded correctly. No arrays are accepted.

toPathRaw({ id: "%3A%2F" }); //=> "/user/%3A%2F"
toPathRaw({ id: ":/" }); //=> "/user/:/", throws when `validate: false` is not set.
toPathRaw({ id: ":/" }); //=> Throws, "/user/:/" when `validate` is `false`.

@@ -243,2 +256,3 @@ const toPathRepeated = compile("{/:segment}+");

- If matches are intended to be exact, you need to set `loose: false`, `trailing: false`, and `sensitive: true`.
- Enable `strict: true` to detect ReDOS issues.

@@ -249,4 +263,6 @@ ### Parse

### Token Information
### Tokens
The `tokens` returned by `TokenData` is an array of strings or keys, represented as objects, with the following properties:
- `name` The name of the token

@@ -259,2 +275,16 @@ - `prefix` _(optional)_ The prefix string for the segment (e.g. `"/"`)

### Custom path
In some applications, you may not be able to use the `path-to-regexp` syntax (e.g. file-based routing), but you can still use this library for `match`, `compile`, and `pathToRegexp` by building your own `TokenData` instance. For example:
```js
import { TokenData, match } from "path-to-regexp";
const tokens = ["/", { name: "foo" }];
const path = new TokenData(tokens, "/");
const fn = match(path);
fn("/test"); //=> { path: '/test', index: 0, params: { foo: 'test' } }
```
## Errors

@@ -272,4 +302,8 @@

### Unexpected `!`, `@`, `,`, or `;`
### Unexpected `;`
Used as a [custom separator](#custom-separator) for repeated parameters.
### Unexpected `!`, `@`, or `,`
These characters have been reserved for future use.

@@ -276,0 +310,0 @@

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