diff --git a/Readme.md b/Readme.md index 9bd7dfe..2fc5d8b 100644 --- a/Readme.md +++ b/Readme.md @@ -185,6 +185,9 @@ toPath({ id: 123 }) //=> "/user/123" toPath({ id: 'café' }) //=> "/user/caf%C3%A9" toPath({ id: '/' }) //=> "/user/%2F" +toPath({ id: ':' }) //=> "/user/%3A" +toPath({ id: ':' }, { pretty: true }) //=> "/user/:" + var toPathRepeated = pathToRegexp.compile('/:segment+') toPathRepeated({ segment: 'foo' }) //=> "/foo" @@ -194,7 +197,7 @@ var toPathRegexp = pathToRegexp.compile('/user/:id(\\d+)') toPathRegexp({ id: 123 }) //=> "/user/123" toPathRegexp({ id: '123' }) //=> "/user/123" -toPathRegexp({ id: 'abc' }) //=> throws TypeError +toPathRegexp({ id: 'abc' }) //=> Throws `TypeError`. ``` **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. diff --git a/index.d.ts b/index.d.ts index a3d546b..89d94e1 100644 --- a/index.d.ts +++ b/index.d.ts @@ -45,9 +45,13 @@ declare namespace pathToRegexp { pattern: string; } + interface PathFunctionOptions { + pretty?: boolean; + } + export type Token = string | Key; export type Path = string | RegExp | Array; - export type PathFunction = (data?: Object) => string; + export type PathFunction = (data?: Object, options?: PathFunctionOptions) => string; } export = pathToRegexp; \ No newline at end of file diff --git a/index.js b/index.js index 1550455..ea32ea6 100644 --- a/index.js +++ b/index.js @@ -105,12 +105,24 @@ function parse (str) { * Compile a string to a template function for the path. * * @param {string} str - * @return {!function(Object=)} + * @return {!function(Object=, Object=)} */ function compile (str) { return tokensToFunction(parse(str)) } +/** + * Encode characters for segment that could cause trouble for parsing. + * + * @param {string} + * @return {string} + */ +function encodeURIComponentPretty (str) { + return encodeURI(str).replace(/[/?#'"]/g, function (c) { + return '%' + c.charCodeAt(0).toString(16).toUpperCase() + }) +} + /** * Expose a method for transforming tokens into the path function. */ @@ -125,9 +137,11 @@ function tokensToFunction (tokens) { } } - return function (obj) { + return function (obj, opts) { var path = '' var data = obj || {} + var options = opts || {} + var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent for (var i = 0; i < tokens.length; i++) { var token = tokens[i] @@ -163,7 +177,7 @@ function tokensToFunction (tokens) { } for (var j = 0; j < value.length; j++) { - segment = encodeURIComponent(value[j]) + segment = encode(value[j]) if (!matches[i].test(segment)) { throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') @@ -175,7 +189,7 @@ function tokensToFunction (tokens) { continue } - segment = encodeURIComponent(value) + segment = encode(value) if (!matches[i].test(segment)) { throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') diff --git a/test.ts b/test.ts index 3abbc1b..45cd1a7 100644 --- a/test.ts +++ b/test.ts @@ -398,11 +398,14 @@ var TESTS: Test[] = [ ['/another', ['/another', 'another']], ['/something/else', null], ['/route.json', ['/route.json', 'route.json']], - ['/something%2Felse', ['/something%2Felse', 'something%2Felse']] + ['/something%2Felse', ['/something%2Felse', 'something%2Felse']], + ['/something%2Felse%2Fmore', ['/something%2Felse%2Fmore', 'something%2Felse%2Fmore']], + ['/;,:@&=+$-_.!~*()', ['/;,:@&=+$-_.!~*()', ';,:@&=+$-_.!~*()']] ], [ [{ test: 'route' }, '/route'], - [{ test: 'something/else' }, '/something%2Felse'] + [{ test: 'something/else' }, '/something%2Felse'], + [{ test: 'something/else/more' }, '/something%2Felse%2Fmore'] ] ], [ @@ -799,12 +802,14 @@ var TESTS: Test[] = [ } ], [ - ['/anything/goes/here', ['/anything/goes/here', 'anything/goes/here']] + ['/anything/goes/here', ['/anything/goes/here', 'anything/goes/here']], + ['/;,:@&=/+$-_.!/~*()', ['/;,:@&=/+$-_.!/~*()', ';,:@&=/+$-_.!/~*()']] ], [ [{ test: '' }, '/'], [{ test: 'abc' }, '/abc'], - [{ test: 'abc/123' }, '/abc%2F123'] + [{ test: 'abc/123' }, '/abc%2F123'], + [{ test: 'abc/123/456' }, '/abc%2F123%2F456'] ] ], [ @@ -1981,6 +1986,16 @@ describe('path-to-regexp', function () { }) }) + describe('compile', function () { + it('should allow pretty option', function () { + var value = ';,:@&=+$-_.!~*()' + var toPath = pathToRegexp.compile('/:value') + var path = toPath({ value }, { pretty: true }) + + expect(path).to.equal(`/${value}`) + }) + }) + describe('compile errors', function () { it('should throw when a required param is undefined', function () { var toPath = pathToRegexp.compile('/a/:b/c')