feather-route-matcher
Advanced tools
Comparing version 3.1.0 to 4.0.0
@@ -5,3 +5,3 @@ (function (global, factory) { | ||
(global = global || self, global.createMatcher = factory()); | ||
}(this, function () { 'use strict'; | ||
}(this, (function () { 'use strict'; | ||
@@ -22,4 +22,4 @@ // regexes borrowed from backbone | ||
// It has been modified for extraction of | ||
// named paramaters from the URL | ||
function parsePattern (pattern) { | ||
// named parameters from the URL | ||
var parsePattern = function (pattern) { | ||
var names = []; | ||
@@ -33,3 +33,3 @@ pattern = pattern | ||
}) | ||
.replace(splatParam, function (match, optional) { | ||
.replace(splatParam, function () { | ||
names.push('path'); | ||
@@ -43,6 +43,7 @@ return '([^?]*?)' | ||
} | ||
} | ||
}; | ||
function index (routes, fallback) { | ||
function index (routes) { | ||
var keys = Object.keys(routes); | ||
var routeCache = {}; | ||
@@ -53,7 +54,5 @@ // loop through each route we're | ||
for (var item in routes) { | ||
if (routes.hasOwnProperty(item)) { | ||
routes[item] = { | ||
value: routes[item] | ||
}; | ||
} | ||
routeCache[item] = { | ||
value: routes[item] | ||
}; | ||
} | ||
@@ -73,3 +72,3 @@ | ||
// there will always be one | ||
route = routes[key]; | ||
route = routeCache[key]; | ||
@@ -102,3 +101,3 @@ // if the route doesn't already have | ||
// reduce our match to an object of named paramaters | ||
// reduce our match to an object of named parameters | ||
// we've extracted from the url | ||
@@ -118,9 +117,2 @@ params = result.reduce(function (obj, val, index) { | ||
if (!matchFound) { | ||
if (fallback) { | ||
return { | ||
page: fallback, | ||
url: url, | ||
params: null | ||
} | ||
} | ||
return null | ||
@@ -130,3 +122,3 @@ } | ||
return { | ||
page: route.value, | ||
value: route.value, | ||
params: params, | ||
@@ -141,3 +133,3 @@ url: url, | ||
})); | ||
}))); | ||
//# sourceMappingURL=feather-route-matcher.js.map |
@@ -1,2 +0,2 @@ | ||
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):(e=e||self).createMatcher=r()}(this,function(){"use strict";var c=/\((.*?)\)/g,o=/(\(\?)?:\w+/g,s=/[\-{}\[\]+?.,\\\^$|#\s]/g,f=/\*/g;return function(p,e){var r=Object.keys(p);for(var n in p)p.hasOwnProperty(n)&&(p[n]={value:p[n]});return function(a){var t,u;return r.some(function(e){var r;(u=p[e]).regExp||(r=function(e){var n=[];return e=e.replace(s,"\\$&").replace(c,"(?:$1)?").replace(o,function(e,r){return n.push(e.slice(1)),r?e:"([^/?]+)"}).replace(f,function(){return n.push("path"),"([^?]*?)"}),{regExp:new RegExp("^"+e+"(?:\\?([\\s\\S]*))?$"),namedParams:n}}(e),u.regExp=r.regExp,u.namedParams=r.namedParams,u.pattern=e);var n=u.regExp.exec(a);if(n)return n=n.slice(1,-1),t=n.reduce(function(e,r,n){return r&&(e[u.namedParams[n]]=r),e},{}),!0})?{page:u.value,params:t,url:a,pattern:u.pattern}:e?{page:e,url:a,params:null}:null}}}); | ||
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):(e=e||self).createMatcher=r()}(this,function(){"use strict";var i=/\((.*?)\)/g,o=/(\(\?)?:\w+/g,s=/[\-{}\[\]+?.,\\\^$|#\s]/g,l=/\*/g;return function(e){var r=Object.keys(e),f={};for(var n in e)f[n]={value:e[n]};return function(u){var c,p;return r.some(function(e){var r,n,t;(p=f[e]).regExp||(t=[],n=(n=e).replace(s,"\\$&").replace(i,"(?:$1)?").replace(o,function(e,r){return t.push(e.slice(1)),r?e:"([^/?]+)"}).replace(l,function(){return t.push("path"),"([^?]*?)"}),r={regExp:new RegExp("^"+n+"(?:\\?([\\s\\S]*))?$"),namedParams:t},p.regExp=r.regExp,p.namedParams=r.namedParams,p.pattern=e);var a=p.regExp.exec(u);if(a)return a=a.slice(1,-1),c=a.reduce(function(e,r,n){return r&&(e[p.namedParams[n]]=r),e},{}),!0})?{value:p.value,params:c,url:u,pattern:p.pattern}:null}}}); | ||
//# sourceMappingURL=feather-route-matcher.min.js.map |
28
index.js
@@ -15,4 +15,4 @@ // regexes borrowed from backbone | ||
// It has been modified for extraction of | ||
// named paramaters from the URL | ||
function parsePattern (pattern) { | ||
// named parameters from the URL | ||
var parsePattern = function (pattern) { | ||
var names = [] | ||
@@ -26,3 +26,3 @@ pattern = pattern | ||
}) | ||
.replace(splatParam, function (match, optional) { | ||
.replace(splatParam, function () { | ||
names.push('path') | ||
@@ -38,4 +38,5 @@ return '([^?]*?)' | ||
export default function (routes, fallback) { | ||
export default function (routes) { | ||
var keys = Object.keys(routes) | ||
var routeCache = {} | ||
@@ -46,6 +47,4 @@ // loop through each route we're | ||
for (var item in routes) { | ||
if (routes.hasOwnProperty(item)) { | ||
routes[item] = { | ||
value: routes[item] | ||
} | ||
routeCache[item] = { | ||
value: routes[item] | ||
} | ||
@@ -66,3 +65,3 @@ } | ||
// there will always be one | ||
route = routes[key] | ||
route = routeCache[key] | ||
@@ -95,3 +94,3 @@ // if the route doesn't already have | ||
// reduce our match to an object of named paramaters | ||
// reduce our match to an object of named parameters | ||
// we've extracted from the url | ||
@@ -111,9 +110,2 @@ params = result.reduce(function (obj, val, index) { | ||
if (!matchFound) { | ||
if (fallback) { | ||
return { | ||
page: fallback, | ||
url: url, | ||
params: null | ||
} | ||
} | ||
return null | ||
@@ -123,3 +115,3 @@ } | ||
return { | ||
page: route.value, | ||
value: route.value, | ||
params: params, | ||
@@ -126,0 +118,0 @@ url: url, |
{ | ||
"name": "feather-route-matcher", | ||
"description": "featherweight url to handler matching", | ||
"version": "3.1.0", | ||
"version": "4.0.0", | ||
"author": "Henrik Joreteg <henrik@joreteg.com>", | ||
@@ -10,10 +10,11 @@ "bugs": { | ||
"devDependencies": { | ||
"rollup": "^1.12.2", | ||
"rollup-plugin-commonjs": "^10.0.0", | ||
"rollup-plugin-filesize": "^6.0.1", | ||
"rollup-plugin-node-resolve": "^5.0.0", | ||
"rollup-plugin-uglify": "^6.0.2", | ||
"standard": "^12.0.1", | ||
"tap-spec": "^5.0.0", | ||
"tape": "^4.10.1" | ||
"rollup": "2.10.5", | ||
"rollup-plugin-commonjs": "10.1.0", | ||
"rollup-plugin-filesize": "9.0.0", | ||
"rollup-plugin-node-resolve": "5.2.0", | ||
"rollup-plugin-uglify": "6.0.4", | ||
"standard": "14.3.4", | ||
"tap": "14.10.7", | ||
"tap-spec": "5.0.0", | ||
"tape": "5.0.0" | ||
}, | ||
@@ -45,3 +46,8 @@ "homepage": "https://github.com/henrikjoreteg/feather-route-matcher", | ||
] | ||
}, | ||
"prettier": { | ||
"semi": false, | ||
"singleQuote": true, | ||
"trailingComma": "none" | ||
} | ||
} |
@@ -30,3 +30,3 @@ # feather-route-matcher | ||
This returns a function that can be called to retrieve the value, along with extracted paramaters: | ||
This returns a function that can be called to retrieve the value, along with extracted parameters: | ||
@@ -42,3 +42,3 @@ **other.js** | ||
// { | ||
// page: homePage, | ||
// value: homePage, | ||
// url: '/', | ||
@@ -51,6 +51,6 @@ // params: null | ||
// { | ||
// page: courseDetailPage, | ||
// value: courseDetailPage, | ||
// url: '/', | ||
// params: { | ||
// id: '47' | ||
// id: '47' | ||
// } | ||
@@ -62,3 +62,3 @@ // } | ||
// { | ||
// page: notFoundPage, | ||
// value: notFoundPage, | ||
// url: '/some/garbage', | ||
@@ -78,7 +78,7 @@ // params: { | ||
If you treat the `url` in a clientside app as just another piece of application state in a frontend app you'll likely need some sort of `switch` statement or set of `if`/`else` blocks to match the current url with the page you want to show. | ||
If you treat the `url` in a clientside app as just another piece of application state in a frontend app you'll likely need some sort of `switch` statement or set of `if`/`else` blocks to match the current url with the component you want to show. | ||
That's easy with urls that are known ahead of time, such as `/home` but becomes a bit more arduous when you want to see whether it matches a given pattern and want to extract values such as: `/user/42`. That's where this module helps with. | ||
The result of the matcher is a great candidate for going into a [redux](http://redux.js.org/) store. | ||
The result of the matcher is a great candidate for going into a state store, like [redux](http://redux.js.org/). | ||
@@ -144,2 +144,4 @@ This module could be used as a really lightweight routing system for a react/redux app without the need for React Router. | ||
* `4.0.0` - Breaking changes: In the matched response, the property called `page` was renamed `value`. Removed `fallback` option because it's easy to do in app code using this. Fixed bug where passed in route object was being mutated. | ||
* `3.1.0` - Non-breaking conversion of `./index.js` into an esm module. umd version remains available as `./feather-route-matcher.js` and `./feather-route-matcher.min.js` | ||
@@ -146,0 +148,0 @@ |
110
test.js
@@ -6,16 +6,67 @@ var test = require('tape') | ||
var cases = [ | ||
['/:first/:second', '/ok', null, 'should not match if missing required params'], | ||
[ | ||
'/:first/:second', | ||
'/ok', | ||
null, | ||
'should not match if missing required params' | ||
], | ||
['/:first', '/ok', { first: 'ok' }, 'should extract simple, named params'], | ||
['/:first/', '/ok', null, 'should not tolerate missing trailing slashes'], | ||
['/:first/', '/ok/', { first: 'ok' }, 'should tolerate trailing slashes when explicit'], | ||
['/:first/:second', '/ok/', null, 'should not match if has slash but no value'], | ||
['/:first/:second', '/ok/second', { first: 'ok', second: 'second' }, 'can extract two values'], | ||
['/:first(/:second)', '/ok/second', { first: 'ok', second: 'second' }, 'second value optional and is supplied'], | ||
['/:first(/:second)', '/ok', { first: 'ok' }, 'second value optional and not supplied'], | ||
['/users/:id', '/something-else', null, 'make sure example works as written in readme'], | ||
['/users/:id', '/users/scrooge-mc-duck', { id: 'scrooge-mc-duck' }, 'make sure examples works as written in readme'], | ||
['/users/:id', '/users/47', { id: '47' }, 'make sure example works as written in readme'], | ||
['/schools/:schoolId/teachers/:teacherId', '/schools/richland/teachers/47', { schoolId: 'richland', teacherId: '47' }, 'example from readme'], | ||
[ | ||
'/:first/', | ||
'/ok/', | ||
{ first: 'ok' }, | ||
'should tolerate trailing slashes when explicit' | ||
], | ||
[ | ||
'/:first/:second', | ||
'/ok/', | ||
null, | ||
'should not match if has slash but no value' | ||
], | ||
[ | ||
'/:first/:second', | ||
'/ok/second', | ||
{ first: 'ok', second: 'second' }, | ||
'can extract two values' | ||
], | ||
[ | ||
'/:first(/:second)', | ||
'/ok/second', | ||
{ first: 'ok', second: 'second' }, | ||
'second value optional and is supplied' | ||
], | ||
[ | ||
'/:first(/:second)', | ||
'/ok', | ||
{ first: 'ok' }, | ||
'second value optional and not supplied' | ||
], | ||
[ | ||
'/users/:id', | ||
'/something-else', | ||
null, | ||
'make sure example works as written in readme' | ||
], | ||
[ | ||
'/users/:id', | ||
'/users/scrooge-mc-duck', | ||
{ id: 'scrooge-mc-duck' }, | ||
'make sure examples works as written in readme' | ||
], | ||
[ | ||
'/users/:id', | ||
'/users/47', | ||
{ id: '47' }, | ||
'make sure example works as written in readme' | ||
], | ||
[ | ||
'/schools/:schoolId/teachers/:teacherId', | ||
'/schools/richland/teachers/47', | ||
{ schoolId: 'richland', teacherId: '47' }, | ||
'example from readme' | ||
], | ||
['/random/*', '/random/something/stuff', { path: 'something/stuff' }], | ||
['/*', '/sdfasfas', { path: 'sdfasfas' }] | ||
['/*', '/sdfasfas', { path: 'sdfasfas' }, 'matches wildcards'], | ||
['/', '/blah', null, 'returns null if not matching'] | ||
] | ||
@@ -25,6 +76,3 @@ | ||
var routes = {} | ||
var pattern = testCase[0] | ||
var url = testCase[1] | ||
var expectedResult = testCase[2] | ||
var description = testCase[3] | ||
var [pattern, url, expectedResult, description] = testCase | ||
var SOME_PAGE = {} | ||
@@ -43,11 +91,17 @@ | ||
} | ||
t.deepEqual(result, { | ||
page: SOME_PAGE, | ||
url: url, | ||
params: expectedResult, | ||
pattern: pattern | ||
}, description) | ||
t.deepEqual( | ||
result, | ||
{ | ||
value: SOME_PAGE, | ||
url: url, | ||
params: expectedResult, | ||
pattern: pattern | ||
}, | ||
description | ||
) | ||
} else { | ||
if (expectedResult) { | ||
t.fail('should have gotten a match, pattern: ' + pattern + ' url: ' + url) | ||
t.fail( | ||
'should have gotten a match, pattern: ' + pattern + ' url: ' + url | ||
) | ||
} else { | ||
@@ -61,1 +115,13 @@ t.pass('got null as expected') | ||
}) | ||
test('does not modify route object passed in', (t) => { | ||
const startingRouteObject = { | ||
'/': 'something', | ||
'/else': 'somethingelse' | ||
} | ||
const serialized = JSON.stringify(startingRouteObject) | ||
createMatcher(startingRouteObject) | ||
t.equal(serialized, JSON.stringify(startingRouteObject)) | ||
t.end() | ||
}) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
27144
363
154
9