diff --git a/index.js b/index.js index f5c77ea..d2d0910 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,5 @@ -var wayfarer = require('wayfarer') +var trie = require('wayfarer/trie') +var assert = require('assert') var isLocalFile = (/file:\/\//.test(typeof window === 'object' && window.location && window.location.origin)) // electron support @@ -20,33 +21,68 @@ module.exports = Nanorouter function Nanorouter (opts) { opts = opts || {} - var router = wayfarer(opts.default || '/404') + var _trie = trie() + var _default = (opts.default || '').replace(/^\//, '') || '/404' var curry = opts.curry || false - var prevCallback = null var prevRoute = null + var prevMatch = null - emit.router = router + emit._trie = _trie emit.on = on + emit.match = match return emit - function on (routename, listener) { - routename = routename.replace(/^[#/]/, '') - router.on(routename, listener) + function on (route, cb) { + assert.equal(typeof route, 'string') + assert.equal(typeof cb, 'function') + route = route.replace(/^[#/]/, '') || '/' + cb.route = route + + if (cb && cb._trie) { + _trie.mount(route, cb._trie.trie) + } else { + var node = _trie.create(route) + node.cb = cb + } } function emit (route) { + var matched + var args = new Array(arguments.length) + for (var i = 1; i < args.length; i++) { + args[i] = arguments[i] + } + if (!curry) { - return router(route) + matched = match(route) + args[0] = matched.params + return matched.handler.apply(matched.handler, args) + } + + route = pathname(route, isLocalFile) + if (route === prevRoute) { + matched = prevMatch } else { - route = pathname(route, isLocalFile) - if (route === prevRoute) { - return prevCallback() - } else { - prevRoute = route - prevCallback = router(route) - return prevCallback() - } + matched = match(route) + prevRoute = route + prevMatch = matched } + + args[0] = matched.params + return matched.handler.apply(matched.handler, args)() + } + + function match (route) { + assert.notEqual(route, undefined, "'route' must be defined") + if (route === prevRoute) return prevMatch + + var matched = _trie.match(route) + if (matched && matched.cb) return toMatchObj(matched) + + var dft = _trie.match(_default) + if (dft && dft.cb) return toMatchObj(dft) + + throw new Error("route '" + route + "' did not match") } } @@ -56,3 +92,7 @@ function pathname (route, isElectron) { else route = route.replace(prefix, '') return route.replace(suffix, '').replace(normalize, '/') } + +function toMatchObj (match) { + return {handler: match.cb, params: match.params, route: match.cb.route} +}