UNPKG

shifty-router

Version:

Fast, modular client router, based on sheet-router

106 lines (88 loc) 3.05 kB
var pathname = require('./_pathname') var wayfarer = require('wayfarer') var assert = require('assert') var isLocalFile = (/file:\/\//.test(typeof window === 'object' && window.location && window.location.origin)) // electron support module.exports = sheetRouter // Fast, modular client router // fn(str, any[..]) -> fn(str, any[..]) function sheetRouter (opts, tree) { if (!tree) { tree = opts opts = {} } assert.equal(typeof opts, 'object', 'sheet-router: opts must be a object') assert.ok(Array.isArray(tree), 'sheet-router: tree must be an array') var dft = opts.default || '/404' assert.equal(typeof dft, 'string', 'sheet-router: dft must be a string') var router = wayfarer(dft) var prevCallback = null var prevRoute = null match._router = router // register tree in router // tree[0] is a string, thus a route // tree[0] is an array, thus not a route // tree[1] is a function // tree[2] is an array // tree[2] is not an array // tree[1] is an array ;(function walk (tree, fullRoute) { if (typeof tree[0] === 'string') { var route = tree[0].replace(/^[#/]/, '') } else { var rootArr = tree[0] } var cb = (typeof tree[1] === 'function') ? tree[1] : null var children = (Array.isArray(tree[1])) ? tree[1] : Array.isArray(tree[2]) ? tree[2] : null if (rootArr) { tree.forEach(function (node) { walk(node, fullRoute) }) } if (cb) { var innerRoute = route ? fullRoute.concat(route).join('/') : fullRoute.length ? fullRoute.join('/') : route // if opts.thunk is false or only enabled for match, don't thunk var handler = (opts.thunk === false || opts.thunk === 'match') ? cb : thunkify(cb) router.on(innerRoute, handler) } if (Array.isArray(children)) { walk(children, fullRoute.concat(route)) } })(tree, []) return match // match a route on the router // // no thunking -> call route with all arguments // thunking only for match -> call route with all arguments // thunking and route is same -> call prev cb with new args // thunking and route is diff -> create cb and call with new args // // (str, [any..]) -> any function match (route, arg1, arg2, arg3, arg4, arg5) { assert.equal(typeof route, 'string', 'sheet-router: route must be a string') if (opts.thunk === false) { return router(pathname(route, isLocalFile), arg1, arg2, arg3, arg4, arg5) } else if (route === prevRoute) { return prevCallback(arg1, arg2, arg3, arg4, arg5) } else { prevRoute = pathname(route, isLocalFile) prevCallback = router(prevRoute) return prevCallback(arg1, arg2, arg3, arg4, arg5) } } } // wrap a function in a function so it can be called at a later time // fn -> obj -> (any, any, any, any, any) function thunkify (cb) { return function (params) { return function (arg1, arg2, arg3, arg4, arg5) { return cb(params, arg1, arg2, arg3, arg4, arg5) } } }