Skip to content

Commit 17ce0be

Browse files
committed
Make key prefix/suffix/modifier/separator optional
1 parent 8b74404 commit 17ce0be

File tree

3 files changed

+31
-50
lines changed

3 files changed

+31
-50
lines changed

Readme.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -242,25 +242,26 @@ A `parse` function is available and returns `TokenData`, the set of tokens and o
242242

243243
### Token Information
244244

245-
- `name` The name of the token (`string` for named or `number` for unnamed index)
246-
- `prefix` The prefix string for the segment (e.g. `"/"`)
247-
- `suffix` The suffix string for the segment (e.g. `""`)
248-
- `pattern` The RegExp used to match this token (`string`)
249-
- `modifier` The modifier character used for the segment (e.g. `?`)
250-
- `separator` _(optional)_ The string used to separate repeated parameters (modifier is `+` or `*`)
251-
- `optional` _(optional)_ A boolean used to indicate whether the parameter is optional (modifier is `?` or `*`)
245+
- `name` The name of the token
246+
- `prefix` _(optional)_ The prefix string for the segment (e.g. `"/"`)
247+
- `suffix` _(optional)_ The suffix string for the segment (e.g. `""`)
248+
- `pattern` _(optional)_ The pattern defined to match this token
249+
- `modifier` _(optional)_ The modifier character used for the segment (e.g. `?`)
250+
- `separator` _(optional)_ The string used to separate repeated parameters
252251

253252
## Errors
254253

255254
An effort has been made to ensure ambiguous paths from previous releases throw an error. This means you might be seeing an error when things worked before.
256255

257256
### Unexpected `?`, `*`, or `+`
258257

259-
In previous major versions, `/` or `.` were used as implicit prefixes of parameters. So `/:key?` was implicitly `{/:key}?`.
258+
In previous major versions `/` and `.` were used as implicit prefixes of parameters. So `/:key?` was implicitly `{/:key}?`. For example:
260259

261-
This has been made explicit. Assuming `?` as the modifier, if you have a `/` or `.` before the parameter, you want `{.:ext}?` or `{/:ext}?`. If not, you want `{:ext}?`.
260+
- `/:key?``{/:key}?` or `/:key*``{/:key}*` or `/:key+``{/:key}+`
261+
- `.:key?``{.:key}?` or `.:key*``{.:key}*` or `.:key+``{.:key}+`
262+
- `:key?``{:key}?` or `:key*``{:key}*` or `:key+``{:key}+`
262263

263-
### Unexpected `!`, `@`, or `;`
264+
### Unexpected `!`, `@`, `,`, or `;`
264265

265266
These characters have been reserved for future use.
266267

src/index.spec.ts

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,19 @@ const PARSER_TESTS: ParserTestSet[] = [
3636
},
3737
{
3838
path: "/:test",
39-
expected: [
40-
"/",
41-
{ name: "test", prefix: "", suffix: "", pattern: "", modifier: "" },
42-
],
39+
expected: ["/", { name: "test" }],
4340
},
4441
{
4542
path: "/:0",
46-
expected: [
47-
"/",
48-
{ name: "0", prefix: "", suffix: "", pattern: "", modifier: "" },
49-
],
43+
expected: ["/", { name: "0" }],
5044
},
5145
{
5246
path: "/:_",
53-
expected: [
54-
"/",
55-
{ name: "_", prefix: "", suffix: "", pattern: "", modifier: "" },
56-
],
47+
expected: ["/", { name: "_" }],
5748
},
5849
{
5950
path: "/:café",
60-
expected: [
61-
"/",
62-
{ name: "café", prefix: "", suffix: "", pattern: "", modifier: "" },
63-
],
51+
expected: ["/", { name: "café" }],
6452
},
6553
];
6654

@@ -2913,10 +2901,7 @@ describe("path-to-regexp", () => {
29132901
const expectedKeys = [
29142902
{
29152903
name: "id",
2916-
prefix: "",
2917-
suffix: "",
2918-
modifier: "",
2919-
pattern: "",
2904+
pattern: undefined,
29202905
},
29212906
];
29222907

src/index.ts

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -258,15 +258,12 @@ export function parse(str: string, options: ParseOptions = {}): TokenData {
258258
if (path) tokens.push(encodePath(path));
259259

260260
const name = it.tryConsume("NAME");
261-
const pattern = it.tryConsume("PATTERN") || "";
261+
const pattern = it.tryConsume("PATTERN");
262262

263263
if (name || pattern) {
264264
tokens.push({
265265
name: name || String(key++),
266-
prefix: "",
267-
suffix: "",
268266
pattern,
269-
modifier: "",
270267
});
271268

272269
const next = it.peek();
@@ -283,8 +280,6 @@ export function parse(str: string, options: ParseOptions = {}): TokenData {
283280
if (asterisk) {
284281
tokens.push({
285282
name: String(key++),
286-
prefix: "",
287-
suffix: "",
288283
pattern: `[^${escape(delimiter)}]*`,
289284
modifier: "*",
290285
separator: delimiter,
@@ -296,7 +291,7 @@ export function parse(str: string, options: ParseOptions = {}): TokenData {
296291
if (open) {
297292
const prefix = it.text();
298293
const name = it.tryConsume("NAME");
299-
const pattern = it.tryConsume("PATTERN") || "";
294+
const pattern = it.tryConsume("PATTERN");
300295
const suffix = it.text();
301296
const separator = it.tryConsume(";") ? it.text() : prefix + suffix;
302297

@@ -350,6 +345,7 @@ function tokenToFunction(
350345
const encodeValue = encode || NOOP_VALUE;
351346
const repeated = token.modifier === "+" || token.modifier === "*";
352347
const optional = token.modifier === "?" || token.modifier === "*";
348+
const { prefix = "", suffix = "", separator = "" } = token;
353349

354350
if (encode && repeated) {
355351
const stringify = (value: string, index: number) => {
@@ -366,9 +362,7 @@ function tokenToFunction(
366362

367363
if (value.length === 0) return "";
368364

369-
return (
370-
token.prefix + value.map(stringify).join(token.separator) + token.suffix
371-
);
365+
return prefix + value.map(stringify).join(separator) + suffix;
372366
};
373367

374368
if (optional) {
@@ -389,7 +383,7 @@ function tokenToFunction(
389383
if (typeof value !== "string") {
390384
throw new TypeError(`Expected "${token.name}" to be a string`);
391385
}
392-
return token.prefix + encodeValue(value) + token.suffix;
386+
return prefix + encodeValue(value) + suffix;
393387
};
394388

395389
if (optional) {
@@ -546,10 +540,10 @@ function flags(options: { sensitive?: boolean }) {
546540
*/
547541
export interface Key {
548542
name: string;
549-
prefix: string;
550-
suffix: string;
551-
pattern: string;
552-
modifier: string;
543+
prefix?: string;
544+
suffix?: string;
545+
pattern?: string;
546+
modifier?: string;
553547
separator?: string;
554548
}
555549

@@ -593,20 +587,21 @@ function toKeyRegexp(stringify: Encode, delimiter: string) {
593587
const segmentPattern = `[^${escape(delimiter)}]+?`;
594588

595589
return (key: Key) => {
596-
const prefix = stringify(key.prefix);
597-
const suffix = stringify(key.suffix);
590+
const prefix = key.prefix ? stringify(key.prefix) : "";
591+
const suffix = key.suffix ? stringify(key.suffix) : "";
592+
const modifier = key.modifier || "";
598593

599594
if (key.name) {
600595
const pattern = key.pattern || segmentPattern;
601596
if (key.modifier === "+" || key.modifier === "*") {
602597
const mod = key.modifier === "*" ? "?" : "";
603-
const split = stringify(key.separator || "");
598+
const split = key.separator ? stringify(key.separator) : "";
604599
return `(?:${prefix}((?:${pattern})(?:${split}(?:${pattern}))*)${suffix})${mod}`;
605600
}
606-
return `(?:${prefix}(${pattern})${suffix})${key.modifier}`;
601+
return `(?:${prefix}(${pattern})${suffix})${modifier}`;
607602
}
608603

609-
return `(?:${prefix}${suffix})${key.modifier}`;
604+
return `(?:${prefix}${suffix})${modifier}`;
610605
};
611606
}
612607

0 commit comments

Comments
 (0)