From c32c146dcb1cc86fbb8c39f06dbcc72aafd767d1 Mon Sep 17 00:00:00 2001 From: Marc Bachmann Date: Mon, 15 Jan 2018 14:28:56 +0100 Subject: [PATCH] Remove curry option and change api to use Prototypes (#13) New api: ``` const router = require('nanorouter')() router.on('/path', noop) // registers route router.emit('/path') // executes handler router.match('/path') // returns match {route: 'path', params: {}, cb: noop} ``` --- index.js | 66 ++++++++++++++------------------ package.json | 4 +- test.js | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 40 deletions(-) create mode 100644 test.js diff --git a/index.js b/index.js index d49cbca..bca0a30 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,12 @@ +var assert = require('assert') var wayfarer = require('wayfarer') -var isLocalFile = (/file:\/\//.test(typeof window === 'object' && - window.location && window.location.origin)) // electron support +// electron support +var isLocalFile = (/file:\/\//.test( + typeof window === 'object' && + window.location && + window.location.origin +)) /* eslint-disable no-useless-escape */ var electron = '^(file:\/\/|\/)(.*\.html?\/?)?' @@ -18,47 +23,32 @@ var suffix = new RegExp(qs) module.exports = Nanorouter function Nanorouter (opts) { + if (!(this instanceof Nanorouter)) return new Nanorouter(opts) opts = opts || {} + this.router = wayfarer(opts.default || '/404') +} - var router = wayfarer(opts.default || '/404') - var curry = opts.curry || false - var prevCallback = null - var prevRoute = null - - emit.router = router - emit.on = on - emit.match = match - return emit - - function on (routename, listener) { - routename = routename.replace(/^[#/]/, '') - router.on(routename, listener) - } +Nanorouter.prototype.on = function (routename, listener) { + assert.equal(typeof routename, 'string') + routename = routename.replace(/^[#/]/, '') + this.router.on(routename, listener) +} - function emit (route) { - if (!curry) { - return router(route) - } else { - route = pathname(route, isLocalFile) - if (route === prevRoute) { - return prevCallback() - } else { - prevRoute = route - prevCallback = router(route) - return prevCallback() - } - } - } +Nanorouter.prototype.emit = function (routename) { + assert.equal(typeof routename, 'string') + routename = pathname(routename, isLocalFile) + return this.router.emit(routename) +} - function match (route) { - route = pathname(route, isLocalFile) - return router.match(route) - } +Nanorouter.prototype.match = function (routename) { + assert.equal(typeof routename, 'string') + routename = pathname(routename, isLocalFile) + return this.router.match(routename) } // replace everything in a route but the pathname and hash -function pathname (route, isElectron) { - if (isElectron) route = route.replace(stripElectron, '') - else route = route.replace(prefix, '') - return route.replace(suffix, '').replace(normalize, '/') +function pathname (routename, isElectron) { + if (isElectron) routename = routename.replace(stripElectron, '') + else routename = routename.replace(prefix, '') + return routename.replace(suffix, '').replace(normalize, '/') } diff --git a/package.json b/package.json index 63cc25c..5c36ee3 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "deps": "dependency-check . && dependency-check . --extra --no-dev", "start": "node .", - "test": "standard && npm run deps" + "test": "standard && npm run deps && tape test.js" }, "dependencies": { "wayfarer": "^6.6.3" @@ -15,7 +15,7 @@ "dependency-check": "^2.8.0", "nyc": "^10.1.2", "standard": "^9.0.1", - "tape": "^4.6.3" + "tape": "^4.8.0" }, "keywords": [ "router", diff --git a/test.js b/test.js new file mode 100644 index 0000000..ed94dc5 --- /dev/null +++ b/test.js @@ -0,0 +1,104 @@ +var tape = require('tape') +var nanorouter = require('./') +function noop () {} + +tape('router', function (t) { + t.test('.on() throws type errors for invalid parameters', function (t) { + t.plan(2) + var r = nanorouter() + t.throws(r.on.bind(r, 123), /string/, 'route must be a string') + t.throws(r.on.bind(r, '/', 123), /function/, 'handler must be a function') + }) + + t.test('.emit() throws if if no route is found', function (t) { + t.plan(2) + var r = nanorouter() + t.throws(r.emit.bind(r, '/'), /route '\/' did not match/) + t.throws(r.emit.bind(r, '/test'), /route '\/test' did not match/) + }) + + t.test('.emit() should match a path', function (t) { + t.plan(2) + var r = nanorouter() + r.on('/foo', function () { + t.pass('called') + }) + r.on('/foo/bar', function () { + t.pass('called') + }) + r.emit('/foo') + r.emit('/foo/bar') + }) + + t.test('.emit() should fallback to a default path', function (t) { + t.plan(2) + var r1 = nanorouter() + var r2 = nanorouter({default: '/custom-error'}) + r1.on('/404', function () { + t.pass('default called') + }) + r2.on('/custom-error', function () { + t.pass('custom error called') + }) + r1.emit('/nope') + r2.emit('/custom-error') + }) + + t.test('.emit() should match partials', function (t) { + t.plan(2) + var r = nanorouter() + r.on('/:foo/:bar', function (param) { + t.equal(param.foo, 'baz', 'first param matched') + t.equal(param.bar, 'qux', 'second param matched') + }) + r.emit('/baz/qux') + }) + + t.test('.emit() should match a hash', function (t) { + t.plan(1) + var r = nanorouter() + r.on('#test', function () { + t.pass('called') + }) + r.emit('#test') + }) + + t.test('.match() should match a path', function (t) { + t.plan(2) + var r = nanorouter() + r.on('/foo', function () { + t.fail('accidentally called') + }) + r.on('/foo/bar', function () { + t.fail('accidentally called') + }) + t.ok(r.match('/foo')) + t.ok(r.match('/foo/bar')) + }) + + t.test('.match() returns a an object with a handler', function (t) { + t.plan(1) + var r = nanorouter() + r.on('/:foo/:bar', function () { + t.pass('called') + }) + r.match('/baz/qux').cb() + }) + + t.test('.match() should match partials', function (t) { + t.plan(3) + var r = nanorouter() + r.on('/:foo/:bar', noop) + var matched = r.match('/baz/qux') + t.equal(matched.params.foo, 'baz') + t.equal(matched.params.bar, 'qux') + t.equal(Object.keys(matched.params).length, 2) + }) + + t.test('.match() returns a an object with a route property', function (t) { + t.plan(1) + var r = nanorouter() + r.on('/:foo/:bar', noop) + t.equal(r.match('/baz/qux').route, ':foo/:bar') + }) +})