hash-brown-router
Advanced tools
Comparing version 1.3.3 to 1.4.0
26
index.js
@@ -7,3 +7,10 @@ var pathToRegexp = require('path-to-regexp-with-reversible-keys') | ||
module.exports = function Router(hashLocation) { | ||
module.exports = function Router(opts, hashLocation) { | ||
if (isHashLocation(opts)) { | ||
hashLocation = opts | ||
opts = null | ||
} | ||
opts = opts || {} | ||
if (!hashLocation) { | ||
@@ -15,3 +22,3 @@ hashLocation = browserHashLocation(window) | ||
var onHashChange = evaluateCurrentPath.bind(null, routes, hashLocation) | ||
var onHashChange = evaluateCurrentPath.bind(null, routes, hashLocation, !!opts.reverse) | ||
@@ -34,4 +41,4 @@ hashLocation.on('hashchange', onHashChange) | ||
function evaluateCurrentPath(routes, hashLocation) { | ||
evaluatePath(routes, hashLocation.get()) | ||
function evaluateCurrentPath(routes, hashLocation, reverse) { | ||
evaluatePath(routes, hashLocation.get(), reverse) | ||
} | ||
@@ -47,3 +54,3 @@ | ||
function evaluatePath(routes, path) { | ||
function evaluatePath(routes, path, reverse) { | ||
var pathParts = getPathParts(path) | ||
@@ -53,3 +60,3 @@ path = pathParts.path | ||
var matchingRoute = routes.find("".match, path) | ||
var matchingRoute = (reverse ? reverseArray(routes) : routes).find("".match, path) | ||
@@ -66,2 +73,6 @@ if (matchingRoute) { | ||
function reverseArray(ary) { | ||
return ary.slice().reverse() | ||
} | ||
function makeParametersObjectFromRegexResult(keys, regexResult) { | ||
@@ -95,1 +106,4 @@ return keys.reduce(function(memo, urlKey, index) { | ||
function isHashLocation(hashLocation) { | ||
return hashLocation && hashLocation.go && hashLocation.replace && hashLocation.on | ||
} |
{ | ||
"name": "hash-brown-router", | ||
"version": "1.3.3", | ||
"version": "1.4.0", | ||
"description": "A client-side router that only cares about the bits after the #", | ||
@@ -28,9 +28,9 @@ "main": "index.js", | ||
"devDependencies": { | ||
"domready": "^1.0.7", | ||
"domready": "^1.0.8", | ||
"tap-browser-color": "^0.1.2", | ||
"tape": "^3.0.1" | ||
"tape": "^4.0.0" | ||
}, | ||
"dependencies": { | ||
"array.prototype.find": "^1.0.0", | ||
"path-to-regexp-with-reversible-keys": "^1.0.1", | ||
"path-to-regexp-with-reversible-keys": "^1.0.3", | ||
"xtend": "^4.0.0" | ||
@@ -37,0 +37,0 @@ }, |
@@ -16,47 +16,66 @@ # hash-brown-router | ||
var makeRouter = require('hash-brown-router') | ||
```js | ||
var makeRouter = require('hash-brown-router') | ||
var router = makeRouter() | ||
var router = makeRouter(options) | ||
``` | ||
## `add(routeString, cb)` - add routes | ||
`options`: an object with one possible option, "reverse", which defaults to false. | ||
router.add('/page/:pageName', function(parameters) { | ||
console.log(parameters.pageName) | ||
}) | ||
If the reverse option is false, routes are matched from oldest to newest - if there are multiple matching routes for the current url, the first one that was added is used. | ||
If reverse is set to true, the most recently added match is used. | ||
## `router.add(routeString, cb)` - add routes | ||
```js | ||
router.add('/page/:pageName', function(parameters) { | ||
console.log(parameters.pageName) | ||
}) | ||
``` | ||
Parses [express-style](https://forbeslindesay.github.io/express-route-tester/) route paths, using a fork of [path-to-regexp](https://github.com/pillarjs/path-to-regexp). | ||
## `setDefault(cb)` - set a default/404 route | ||
## `router.setDefault(cb)` - set a default/404 route | ||
router.setDefault(function(path, parameters) { | ||
console.log("you went to", path, "but that doesn't go anywhere, I guess you just end up here") | ||
}) | ||
```js | ||
router.setDefault(function(path, parameters) { | ||
console.log("you went to", path, "but that doesn't go anywhere, I guess you just end up here") | ||
}) | ||
``` | ||
Called whenever the hash route changes, but no other matching route is found. | ||
## `go(newPath)` - navigate to a new path | ||
## `router.go(newPath)` - navigate to a new path | ||
router.go('/some-other/path') | ||
```js | ||
router.go('/some-other/path') | ||
``` | ||
Changes the current location hash. | ||
## `replace(newPath)` - replace the current route in the browser history | ||
## `router.replace(newPath)` - replace the current route in the browser history | ||
router.add('/page/:pageName', function(parameters) { | ||
if (doesNotExistInTheDatabase(parameters.pageName)) { | ||
router.replace('/pageNotFound') | ||
} | ||
}) | ||
```js | ||
router.add('/page/:pageName', function(parameters) { | ||
if (doesNotExistInTheDatabase(parameters.pageName)) { | ||
router.replace('/pageNotFound') | ||
} | ||
}) | ||
``` | ||
Changes the current location hash, replacing the last location in the browser history, i.e. `location.replace(location.origin + location.pathname + '#' + newPath)`. | ||
## `evaluateCurrent(defaultPath)` - evaluate the current url | ||
## `router.evaluateCurrent(defaultPath)` - evaluate the current url | ||
Forces the library to evaluate the current route from location.hash. Probably best do do once the [dom is ready](https://www.npmjs.org/package/domready). | ||
router.evaluateCurrent('/home') | ||
```js | ||
router.evaluateCurrent('/home') | ||
``` | ||
If location.hash is currently empty, it changes the path to the default path value you pass in. | ||
## `stop()` | ||
## `router.stop()` | ||
@@ -63,0 +82,0 @@ If for some reason you want the router to start ignoring hash change events. you can call `router.stop()`. |
var router = require('../') | ||
var test = require('tape') | ||
module.exports = function tests(tester) { | ||
tester.add('routing on a simple url', function(t, locationHash, done) { | ||
var route = router(locationHash) | ||
module.exports = function tests(locationHash) { | ||
function getRoute() { | ||
locationHash.go('') | ||
return router(locationHash) | ||
} | ||
test('routing on a simple url', function(t) { | ||
var route = getRoute() | ||
t.timeoutAfter(300) | ||
t.plan(1) | ||
route.add('/non-butts', function() { | ||
@@ -14,3 +18,5 @@ t.fail('the wrong route was called') | ||
route.add('/butts', function() { | ||
route.stop() | ||
t.pass('the correct route was called') | ||
t.end() | ||
}) | ||
@@ -26,10 +32,9 @@ | ||
route.stop() | ||
done() | ||
}, 200) | ||
}) | ||
tester.add('default function is called when nothing matches', function(t, locationHash, done) { | ||
t.plan(2) | ||
test('default function is called when nothing matches', function(t) { | ||
var route = getRoute() | ||
var route = router(locationHash) | ||
t.timeoutAfter(300) | ||
@@ -44,2 +49,4 @@ var fail = t.fail.bind(t, 'the wrong route was called') | ||
t.equal('/lulz', path, 'the default path was passed in') | ||
route.stop() | ||
t.end() | ||
}) | ||
@@ -51,8 +58,7 @@ | ||
route.stop() | ||
done() | ||
}, 200) | ||
}) | ||
tester.add('evaluating the current path instead of waiting for an onhashchange', function(t, locationHash, done) { | ||
t.plan(1) | ||
test('evaluating the current path instead of waiting for an onhashchange', function(t) { | ||
var route = getRoute() | ||
@@ -62,3 +68,3 @@ locationHash.go('/butts') | ||
setTimeout(function() { | ||
var route = router(locationHash) | ||
t.plan(1) | ||
@@ -82,10 +88,10 @@ route.add('/non-butts', function() { | ||
done() | ||
t.end() | ||
}, 200) | ||
}) | ||
tester.add('matching an express-style url, getting parameters back', function(t, locationHash, done) { | ||
var route = router(locationHash) | ||
test('matching an express-style url, getting parameters back', function(t) { | ||
var route = getRoute() | ||
t.plan(3) | ||
t.timeoutAfter(300) | ||
@@ -98,2 +104,4 @@ route.add('/no/way', t.fail.bind(t, 'the wrong route was called')) | ||
t.equal(parameters.special, 'input') | ||
route.stop() | ||
t.end() | ||
}) | ||
@@ -105,12 +113,16 @@ | ||
route.stop() | ||
done() | ||
}, 200) | ||
}) | ||
tester.add('route.evaluateCurrent calls the default route when the current path is empty', function(t, locationHash, done) { | ||
var route = router(locationHash) | ||
test('route.evaluateCurrent calls the default route when the current path is empty', function(t) { | ||
var route = getRoute() | ||
t.plan(2) | ||
t.timeoutAfter(300) | ||
route.add('/default', t.pass.bind(t, 'the default route was called')) | ||
route.add('/default', function() { | ||
t.pass('the default route was called') | ||
t.equal(locationHash.get(), '/default', 'the hash was set to the default from the route.evaluateCurrent call') | ||
route.stop() | ||
t.end() | ||
}) | ||
route.add('/other', t.fail.bind(t, 'the wrong route was called')) | ||
@@ -120,20 +132,23 @@ | ||
setTimeout(function() { | ||
t.equal(locationHash.get(), '/default', 'the hash was set to the default from the route.evaluateCurrent call') | ||
route.stop() | ||
done() | ||
}, 200) | ||
}) | ||
tester.add('route.evaluateCurrent does not call the default route when the current path is not empty', function(t, locationHash, done) { | ||
test('route.evaluateCurrent does not call the default route when the current path is not empty', function(t) { | ||
var route = getRoute() | ||
t.timeoutAfter(400) | ||
locationHash.go('/starting-path') | ||
t.plan(1) | ||
route.add('/default', t.fail.bind(t, 'the default route was called incorrectly')) | ||
route.add('/starting-path', function() { | ||
t.pass('the correct route was called') | ||
route.stop() | ||
t.end() | ||
}) | ||
setTimeout(function() { | ||
var route = router(locationHash) | ||
route.add('/default', t.fail.bind(t, 'the default route was called incorrectly')) | ||
route.add('/starting-path', t.pass.bind(t, 'the correct route was called')) | ||
route.evaluateCurrent('/default') | ||
@@ -143,3 +158,2 @@ | ||
route.stop() | ||
done() | ||
}, 200) | ||
@@ -151,7 +165,6 @@ | ||
tester.add('parameters include values from querystring', function(t, locationHash, done) { | ||
t.plan(4) | ||
test('parameters include values from querystring', function(t) { | ||
var route = getRoute() | ||
t.timeoutAfter(300) | ||
var route = router(locationHash) | ||
route.add('myroute/:fromUrl', function(parameters) { | ||
@@ -162,2 +175,4 @@ t.equal(typeof parameters, 'object', 'parameters object is an object') | ||
t.equal(parameters.fromQueryString, 'value2', 'Value from the query string is correct') | ||
route.stop() | ||
t.end() | ||
}) | ||
@@ -167,12 +182,12 @@ | ||
setTimeout(function() { | ||
route.stop() | ||
done() | ||
}, 200) | ||
}) | ||
tester.add('parameters from route overwrite querystring parameters', function(t, locationHash, done) { | ||
t.plan(3) | ||
test('parameters from route overwrite querystring parameters', function(t) { | ||
var route = getRoute() | ||
var route = router(locationHash) | ||
t.timeoutAfter(300) | ||
@@ -183,2 +198,4 @@ route.add('myroute/:fromUrl', function(parameters) { | ||
t.equal(parameters.fromUrl, 'value1', 'Value is from the route parameter') | ||
route.stop() | ||
t.end() | ||
}) | ||
@@ -190,10 +207,9 @@ | ||
route.stop() | ||
done() | ||
}, 200) | ||
}) | ||
tester.add('querystring parameters passed to the default route', function(t, locationHash, done) { | ||
var route = router(locationHash) | ||
test('querystring parameters passed to the default route', function(t) { | ||
var route = getRoute() | ||
t.plan(3) | ||
t.timeoutAfter(300) | ||
@@ -204,2 +220,5 @@ route.setDefault(function(path, parameters) { | ||
t.equal(path, '/default', 'the /default path was correctly passed in') | ||
route.stop() | ||
t.end() | ||
}) | ||
@@ -211,5 +230,84 @@ | ||
route.stop() | ||
done() | ||
}, 200) | ||
}) | ||
test('replacing a url', function(t) { | ||
var route = getRoute() | ||
t.timeoutAfter(2000) | ||
function shouldHappenOnce(name, cb) { | ||
var happened = false | ||
return function() { | ||
if (happened) { | ||
t.fail(name + ' already happened once') | ||
} else { | ||
t.pass(name + ' happened') | ||
happened = true | ||
} | ||
cb && cb.apply(null, arguments) | ||
} | ||
} | ||
route.add('/initial', shouldHappenOnce('initial route', function() { | ||
route.go('/redirect') | ||
})) | ||
route.add('/redirect', shouldHappenOnce('redirect route', function() { | ||
route.replace('/destination') | ||
})) | ||
route.add('/destination', shouldHappenOnce('destination route', function() { | ||
t.pass('it got here I guess') | ||
route.stop() | ||
t.end() | ||
})) | ||
route.setDefault(t.fail.bind(t, 'default route called')) | ||
route.go('/initial') | ||
}) | ||
test('by default, routes are evaluated oldest-to-newest', function(t) { | ||
var route = getRoute() | ||
t.timeoutAfter(500) | ||
route.add('/route/:oneThing', function() { | ||
t.pass('the first route was called') | ||
route.stop() | ||
t.end() | ||
}) | ||
route.add('/route/:anotherThing', function() { | ||
t.fail('the second route was called') | ||
}) | ||
setTimeout(function() { | ||
locationHash.go('/route/butts') | ||
}, 50) | ||
}) | ||
test('routes can be evaluated newest-to-oldest', function(t) { | ||
locationHash.go('') | ||
var route = router({ reverse: true }, locationHash) | ||
t.timeoutAfter(500) | ||
route.add('/route/:oneThing', function() { | ||
t.fail('the first route was called') | ||
route.stop() | ||
t.end() | ||
}) | ||
route.add('/route/:anotherThing', function() { | ||
t.pass('the second route was called') | ||
route.stop() | ||
t.end() | ||
}) | ||
setTimeout(function() { | ||
locationHash.go('/route/butts') | ||
}, 50) | ||
}) | ||
} |
@@ -1,11 +0,4 @@ | ||
var test = require('tape') | ||
var hashLocationMockFactory = require('../hash-location-mock') | ||
var allTests = require('./all-tests') | ||
allTests({ | ||
add: function(name, fn) { | ||
test(name, function(t) { | ||
fn(t, hashLocationMockFactory(), t.end.bind(t)) | ||
}) | ||
} | ||
}) | ||
allTests(hashLocationMockFactory()) |
@@ -1,47 +0,9 @@ | ||
var router = require('../') | ||
var tester = require('./jankety-test-harness') | ||
var allTests = require('./all-tests') | ||
var tapBrowserColor = require('tap-browser-color') | ||
var browserHashLocation = require('../hash-location.js') | ||
allTests(tester) | ||
var hashLocation = browserHashLocation(window) | ||
tester.add('replacing a url', function(t, locationHash, done) { | ||
t.plan(4) | ||
allTests(hashLocation) | ||
var route = router() | ||
var startingHistoryLength = history.length | ||
function shouldHappenOnce(name, cb) { | ||
var happened = false | ||
return function() { | ||
if (happened) { | ||
t.fail(name + ' already happened once') | ||
} else { | ||
t.pass(name + ' happened') | ||
happened = true | ||
} | ||
cb && cb.apply(null, arguments) | ||
} | ||
} | ||
route.add('/initial', shouldHappenOnce('initial route', function() { | ||
route.go('/redirect') // history length++ | ||
})) | ||
route.add('/redirect', shouldHappenOnce('redirect route', function() { | ||
route.replace('/destination') | ||
})) | ||
route.add('/destination', shouldHappenOnce('destination route', function() { | ||
var historyDepth = history.length - startingHistoryLength | ||
t.equal(historyDepth, 2, 'should be two more items in the history then there were before (was ' + historyDepth + ')') | ||
done() | ||
})) | ||
route.setDefault(t.fail.bind(t, 'default route called')) | ||
route.go('/initial') // history length++ | ||
}) | ||
tester.start() | ||
tapBrowserColor() |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15425
92
12
360