UNPKG

marbles

Version:

Front-end framework for routing, http, and data handling

200 lines (173 loc) 5.07 kB
'use strict'; var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }; Object.defineProperty(exports, '__esModule', { value: true }); /* @flow weak */ var _Utils = require('./utils'); var _Utils2 = _interopRequireWildcard(_Utils); /* * * * * * * * * * * * * * * * * * * * Inspired by Backbone.js Router * * * * * * * * * * * * * * * * * * * */ /** * @memberof Marbles * @class * @see Marbles.History * @example * import Router from "marbles/router"; * import History from "marbles/history"; * var MyRouter = Router.createClass({ * displayName: "MyRouter", * * // routes are evaluated in the order they are defined * routes: [ * { path: "posts", handler: "posts" }, * * // :id will be available in the params * { path: "posts/:id", handler: "posts" }, * * // * will be available in the params as `splat` * { path: "posts/:id/*", handler: "posts" }, * ], * * beforeHandler: function (event) { // optional before hook * // same as handler:before event sent through dispatcher * // but only called for the router the handler belongs to * // and called before event is sent through dispatcher * }, * * posts: function (params, opts) { * // params is an array of objects, * // params[0] should be all you need unless * // you have multiple params of the same name * * // opts contains any extra properties given in a route object * } * }); * var history = new History(); * history.register(new MyRouter()); // register router * history.start(); // bring it to life */ var Router = _Utils2['default'].createClass({ displayName: 'Marbles.Router', willInitialize: function willInitialize(options) { options = options || {}; this.context = options.context; this.compileRoutes(); }, // register route handler // handler will be called with an array // of param objects, the first of which // will contain any named params route: (function (_route) { function route(_x, _x2, _x3) { return _route.apply(this, arguments); } route.toString = function () { return _route.toString(); }; return route; })(function (route, handler, opts) { var paramNames = []; if (typeof route.test !== 'function') { paramNames = this.routeParamNames(route); route = this.routeToRegExp(route); } var name; if (typeof handler === 'function') { name = handler.name || handler.displayName || null; } else { name = handler; handler = this[handler]; } this.routes.push({ route: route, name: name, handler: handler, paramNames: paramNames, opts: opts }); }), compileRoutes: function compileRoutes() { this.routes = []; var ctor = this.constructor; if (!ctor.routes) { throw new Error('You need to define ' + ctor.displayName || ctor.name + '.routes'); } var opts, k; for (var i = 0, _ref = ctor.routes, _len = _ref.length; i < _len; i++) { opts = {}; for (k in _ref[i]) { if (_ref[i].hasOwnProperty(k) && k !== 'path' && k !== 'handler') { opts[k] = _ref[i][k]; } } this.route(_ref[i].path, _ref[i].handler, opts); } }, routeToRegExp: function routeToRegExp(route) { if (route[0] === '/') { // trim / prefix route = route.substring(1); } var ctor = this.constructor; route = route.replace(ctor.regex.escape, '\\$&').replace(ctor.regex.namedParam, '([^/]+)').replace(ctor.regex.splatParam, '(.*?)'); return new RegExp('^' + route + '$'); }, routeParamNames: function routeParamNames(route) { var ctor = this.constructor; var paramNames = []; var _ref = route.match(ctor.regex.namedParam); if (_ref && _ref.length) { for (var i = 0, _len = _ref.length; i < _len; i++) { paramNames.push(_ref[i].slice(1)); } } _ref = route.match(ctor.regex.splatParam); if (_ref && _ref.length) { for (i = 0, _len = _ref.length; i < _len; i++) { paramNames.push('splat' + (i > 0 ? i + 1 : '')); } } return paramNames; }, extractNamedParams: function extractNamedParams(route, path, paramNames) { var values = [], params = {}; for (var i = 0, _ref = this.extractParams(route, path), _len = _ref.length; i < _len; i++) { values.push(decodeURIComponent(_ref[i])); } for (i = 0, _len = paramNames.length; i < _len; i++) { params[paramNames[i]] = values[i]; } return params; }, extractParams: function extractParams(route, path) { return route.exec(path).slice(1); } }); Router.regex = { namedParam: /:\w+/g, splatParam: /\*\w*/g, escape: /[-[\]{}()+?.,\\^$|#\s]/g }; Router.routes = []; Router.createClass = function (proto) { if (!proto.hasOwnProperty('displayName')) { proto.displayName = this.displayName; } var routes = this.routes; if (proto.hasOwnProperty('routes')) { routes = proto.routes; delete proto.routes; } proto.parentClass = this; var ctor = _Utils2['default'].createClass(proto); ctor.routes = routes; ctor.createClass = Router.createClass.bind(ctor); return ctor; }; exports['default'] = Router; module.exports = exports['default'];