diff --git a/README.md b/README.md index 2977751..c0f3cb5 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,9 @@ Register a new route. The order in which routes are registered does not matter. Routes can register multiple callbacks. The callback can return values when called. +### matchedRoute = router.match(route) +Matches a route and returns an object. The returned object contains the properties `{cb, params, route}`. This method does not invoke the callback of a route. If no route matches, the default route will be returned. If no default route matches, an error will be thrown. + ### val = router(route, [arg1, ...]) Match a route and execute the corresponding callback. Alias: `router.emit()`. Returns a values from the matched route (e.g. useful for streams). Any diff --git a/index.js b/index.js index 76990a3..97c5958 100644 --- a/index.js +++ b/index.js @@ -12,8 +12,9 @@ function Wayfarer (dft) { var _trie = trie() emit._trie = _trie - emit.emit = emit emit.on = on + emit.emit = emit + emit.match = match emit._wayfarer = true return emit @@ -40,26 +41,32 @@ function Wayfarer (dft) { // match and call a route // (str, obj?) -> null function emit (route) { - assert.notEqual(route, undefined, "'route' must be defined") + var matched = match(route) + var args = new Array(arguments.length) + args[0] = matched.params for (var i = 1; i < args.length; i++) { args[i] = arguments[i] } - var node = _trie.match(route) - if (node && node.cb) { - args[0] = node.params - var cb = node.cb - return cb.apply(cb, args) - } + return matched.cb.apply(matched.cb, args) + } + + function match (route) { + assert.notEqual(route, undefined, "'route' must be defined") + + var matched = _trie.match(route) + if (matched && matched.cb) return new Route(matched) var dft = _trie.match(_default) - if (dft && dft.cb) { - args[0] = dft.params - var dftcb = dft.cb - return dftcb.apply(dftcb, args) - } + if (dft && dft.cb) return new Route(dft) throw new Error("route '" + route + "' did not match") } + + function Route (matched) { + this.cb = matched.cb + this.route = matched.cb.route + this.params = matched.params + } } diff --git a/test/router.js b/test/router.js index 5bcb6d1..0f64dec 100644 --- a/test/router.js +++ b/test/router.js @@ -2,7 +2,7 @@ var wayfarer = require('../') var noop = require('noop2') var tape = require('tape') -tape('trie', function (t) { +tape('router', function (t) { t.test('should match a path', function (t) { t.plan(1) var r = wayfarer() @@ -62,6 +62,21 @@ tape('trie', function (t) { r('/foo/baz') }) + t.test('.match() should match paths', function (t) { + t.plan(2) + var r = wayfarer() + r.on('/foo/bar', function () { + t.fail('should not call callback') + }) + r.on('/foo/baz', noop) + + var bar = r.match('/foo/bar') + t.equal(bar.route, '/foo/bar') + + var baz = r.match('/foo/baz') + t.equal(baz.route, '/foo/baz') + }) + t.test('.emit() should match partials', function (t) { t.plan(1) var r = wayfarer() @@ -71,6 +86,14 @@ tape('trie', function (t) { r('/tobi') }) + t.test('.match() should match partials', function (t) { + t.plan(1) + var r = wayfarer() + r.on('/:user', noop) + var toby = r.match('/tobi') + t.equal(toby.params.user, 'tobi') + }) + t.test('.emit() should match paths before partials', function (t) { t.plan(1) var r = wayfarer() @@ -84,7 +107,9 @@ tape('trie', function (t) { t.test('.emit() should allow path overriding', function (t) { t.plan(1) var r = wayfarer() - r.on('/:user', noop) + r.on('/:user', function () { + t.fail('wrong callback called') + }) r.on('/:user', function () { t.pass('called') }) @@ -170,6 +195,16 @@ tape('trie', function (t) { // r10('/foo/bin/bar/baz') }) + t.test('.match() returns a handler of a route', function (t) { + t.plan(1) + var r = wayfarer() + r.on('/:user', function () { + t.pass('called') + }) + var toby = r.match('/tobi') + toby.cb() + }) + t.test('nested routes should call parent default route', function (t) { t.plan(4) var r1 = wayfarer('/404') @@ -281,7 +316,7 @@ tape('trie', function (t) { r('/test/hel%"Flo') }) - t.test('should expose .router property', function (t) { + t.test('should expose .route property', function (t) { t.plan(1) var r = wayfarer() r.on('/foo', function () {