diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..f7ef086
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,7 @@
+{
+ "presets": [
+ "react",
+ "es2015",
+ "stage-0"
+ ]
+}
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..440c58e
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,4 @@
+/node_modules/
+/dist/
+/dist-components/
+/__tests__/
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..f52d209
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,85 @@
+{
+ "parser": "babel-eslint",
+ "rules": {
+ "eqeqeq": [2, "allow-null"],
+ "no-extra-semi": 2,
+ "semi": ["error", "always"],
+ "no-cond-assign": 2,
+ "accessor-pairs": 2,
+ "no-with": 2,
+ "no-sparse-arrays": 2,
+ "vars-on-top": 2,
+ "no-void": 2,
+ "no-undef": 2,
+ "no-caller": 2,
+ "no-new": 2,
+ "yoda": 2,
+ "no-whitespace-before-property": 2,
+ "no-inner-declarations": 2,
+ "no-ex-assign": 2,
+ "no-else-return": 2,
+ "no-dupe-keys": 2,
+ "constructor-super": 2,
+ "no-extra-boolean-cast": 2,
+ "no-obj-calls": 2,
+ "no-empty": 2,
+ "semi-spacing": ["error", {
+ "before": false, "after": true
+ }],
+ "keyword-spacing": ["error", {"overrides": {
+ "if": {"after": true},
+ "else": {"before": true, "after": true},
+ "for": {"after": false},
+ "while": {"after": false},
+ "function": {"after": true}
+ }}],
+ "space-before-function-paren": ["error", {
+ "anonymous": "never", "named": "never"
+ }],
+ "comma-dangle": [2, "never"],
+ "comma-style": [2, "last"],
+ "comma-spacing": ["error", {
+ "before": false, "after": true
+ }],
+ "quotes": [2, "single", "avoid-escape"],
+ "no-trailing-spaces": 2,
+ "no-lonely-if": 0,
+ "eol-last": 2,
+ "no-nested-ternary": 2,
+ "space-in-parens": [2, "never"],
+ "brace-style": [2, "1tbs", {
+ "allowSingleLine": true
+ }],
+ "object-curly-spacing": [2, "always", {
+ "objectsInObjects": true,
+ "arraysInObjects": true
+ }],
+ "computed-property-spacing": ["error", "never"],
+ "block-spacing": ["error", "always"],
+ "one-var": [2, {
+ "let": "always",
+ "const": "never"
+ }],
+ "no-spaced-func": 2,
+ "spaced-comment": 0,
+ "quote-props": [2, "as-needed", {
+ "keywords": true
+ }],
+ "linebreak-style": ["error", "unix"],
+ "guard-for-in": 2,
+ "prefer-const": 2,
+ "no-var": 2,
+ "prefer-arrow-callback": 2,
+ "no-const-assign": 2,
+ "arrow-parens": [2, "as-needed"],
+ "arrow-spacing": [2, {
+ "before": true,
+ "after": true
+ }]
+ },
+ "globals": {
+ "console": true,
+ "process": true,
+ "__DEV__": true
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bee974f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/node_modules/
+/.idea/
+/coverage/
+*.DS_Store
+npm-debug.log
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..64978c4
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,22 @@
+/.idea/
+/__tests__/
+/gulp/
+/src/example/
+/src/component/js/
+/coverage/
+/docs/
+/webpack/
+/src/component/index.html
+/src/component/index.js
+demo.gif
+.editorconfig
+.babelrc
+.eslintignore
+.eslintrc
+.gitignore
+.scsslint.yml
+.travis.yml
+config.json
+gulpfile.babel.js
+webpack.config.babel.js
+webpack.config.example.babel.js
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..75f3da2
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,9 @@
+language: node_js
+node_js:
+ - "6"
+before_install:
+ - npm install -g gulp
+ - npm install -g eslint
+ - npm install -g babel-eslint
+script:
+ - "npm run lint && npm test"
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..698f395
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Fernando de França
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d4a06b9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,124 @@
+# react-director-router
+A versatile React Router based on [Director](https://github.com/flatiron/director)
+
+## Features
+- Auto wraps views with custom Higher Order Components.
+- Inject route props into your views (route parameters, query parameters).
+- Inject custom props into your views.
+- Route handler functions be fired on route change and will receive route params, query params and injected props.
+- Small footprint.
+
+## Advantages
+Makes your components cleaner by:
+
+- discouraging to rely on `componentDidMount` for http operations or state management.
+- avoiding repetitive "glue code" by auto wrapping HOCs.
+
+By using route handlers your view components can be **more functional**, **more view related** and carry **less business logic**.
+
+Therefore view component tests would be simpler.
+
+## Demo ##
+`yarn start-example`
+
+## Usage ##
+
+### Install
+`yarn add react-director-router`
+
+### App.js
+```
+import Router from '../../component'
+
+import HomeView from '../Views/HomeView'
+import BookWithStatus from '../Views/BookWithStatus'
+import NotFoundView from '../Views/NotFoundView'
+
+const routes = [
+ {
+ path:'/',
+ viewClass: HomeView,
+ handler: () => {
+ console.log('Home handler');
+ }
+ },
+ {
+ path:'/book/:status/:id',
+ viewClass: BookWithStatus,
+ handler: (params) => {
+ console.log('/book/:status/:id > ', params)
+ },
+ },
+ {
+ path:'/not-found',
+ viewClass: NotFoundView
+ },
+]
+
+const notFoundPath = '/not-found'
+
+const customProps = {
+ foo: 'bar',
+ count: 9000,
+ userRoles: ['basic-user']
+}
+
+const HOCs = [
+ view => someHigherOrderComponent(view),
+ view => anotherHigherOrderComponent(view),
+]
+
+const middlewares = [
+ (injectedProps, params, queryParams, route) => {
+ console.log(':: Log Middleware ::', route.viewClass.name);
+ }
+]
+
+class App extends Component {
+ render() {
+ return (
+
+
+
+ )
+ }
+}
+export default App
+```
+
+### Middlewares
+Middlewares are functions that can intercept every route change and are a great opportunity to restrict a route or redirect the navigation flow.
+
+By returning false on any middleware function, the middleware execution sequence will be interrupted, the view will not render and the route handler will not run. You can then redirect the navigation flow acording to the desired business logic.
+
+Another common use for a middleware is logging navigation activity.
+
+#### Example
+
+A role restriction middleware:
+
+```
+import { redirect } from 'react-director-router'
+
+export default function roleRestrictedMiddleware(injectedProps, params, queryParams, route) {
+ if (route.requiredRoles && injectedProps.userRoles){
+ console.log(':: roleRestrictedMiddleware ::');
+ const isAllowed = injectedProps.userRoles === route.requiredRoles
+
+ if (!isAllowed){
+ redirect('restricted-content')
+ return isAllowed
+ }
+ }
+ }
+```
+
+## Roadmap
+- Hash navigation
+- Async routing
\ No newline at end of file
diff --git a/__mocks__/styleMock.js b/__mocks__/styleMock.js
new file mode 100644
index 0000000..d988e23
--- /dev/null
+++ b/__mocks__/styleMock.js
@@ -0,0 +1,3 @@
+// __mocks__/styleMock.js
+
+module.exports = {};
diff --git a/__tests__/Component-test.js b/__tests__/Component-test.js
new file mode 100644
index 0000000..9478192
--- /dev/null
+++ b/__tests__/Component-test.js
@@ -0,0 +1,50 @@
+'use strict'
+
+jest.disableAutomock()
+
+import React from 'react'
+import { findDOMNode } from 'react-dom'
+import { createRenderer, Simulate, renderIntoDocument } from 'react-dom/test-utils'
+// import renderer from 'react-test-renderer'
+// import { shallow, mount } from 'enzyme'
+// import toJson from 'enzyme-to-json'
+
+import Router, { redirect } from '../src/component'
+
+import HomeView from '../src/example/Views/HomeView.js'
+import BookWithStatus from '../src/example/Views/BookWithStatus.js'
+import NotFoundView from '../src/example/Views/NotFoundView.js'
+
+const routes = [
+ {
+ path:'/',
+ viewClass: HomeView,
+ handler: () => {
+ console.log('Home handler')
+ }
+ },
+ {
+ path:'/book/:status/:id',
+ viewClass: BookWithStatus,
+ handler: (params) => {
+ console.log('/book/:status/:id > ', params)
+ },
+ },
+ {
+ path:'/not-found',
+ viewClass: NotFoundView
+ },
+]
+
+const notFoundPath = '/not-found'
+
+describe('Render', () => {
+ it('should render', () => {
+ const renderer = createRenderer()
+ renderer.render(
+
+ )
+ const component = renderer.getRenderOutput()
+ expect(component.type.name).toBe('HomeView')
+ })
+})
diff --git a/config.json b/config.json
new file mode 100644
index 0000000..8d1b77c
--- /dev/null
+++ b/config.json
@@ -0,0 +1,7 @@
+{
+ "scripts": {
+ "fileName": "component",
+ "entry": "index",
+ "library": "Component"
+ }
+}
diff --git a/dist/main.js b/dist/main.js
new file mode 100644
index 0000000..0c16b1e
--- /dev/null
+++ b/dist/main.js
@@ -0,0 +1,1889 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("react"));
+ else if(typeof define === 'function' && define.amd)
+ define(["react"], factory);
+ else if(typeof exports === 'object')
+ exports["Component"] = factory(require("react"));
+ else
+ root["Component"] = factory(root["React"]);
+})(this, function(__WEBPACK_EXTERNAL_MODULE_2__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // identity function for calling harmony imports with the correct context
+/******/ __webpack_require__.i = function(value) { return value; };
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, {
+/******/ configurable: false,
+/******/ enumerable: true,
+/******/ get: getter
+/******/ });
+/******/ }
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "/";
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = 15);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.goTo = exports.getRouter = exports.initRouter = undefined;
+
+var _director = __webpack_require__(6);
+
+var _director2 = _interopRequireDefault(_director);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var DirectorRouter = _director2.default.Router;
+
+var router = null;
+
+function initRouter(routes, config) {
+ if (getRouter()) return getRouter();
+
+ router = DirectorRouter(routes);
+ router.configure(config);
+ router.init();
+ return router;
+}
+
+function getRouter() {
+ return router;
+}
+
+function goTo(path) {
+ setRouteFix();
+ getRouter().setRoute(path);
+}
+
+// window.onpopstate pode estar indisponivel
+// durante o load da pagina.
+// Por consequencia, redirects imediatos no carregamento
+// podem não funcionar
+function setRouteFix() {
+ // Verifica se já redefiniu
+ if (getRouter().setRoute.name === 'customSetRoute') return;
+
+ var oldSetRoute = getRouter().setRoute;
+ getRouter().setRoute = function customSetRoute(route) {
+ var isDirectorReady = function isDirectorReady(callback) {
+ var interval;
+
+ if (window.onpopstate !== null) {
+ callback();
+ return;
+ }
+ interval = setInterval(function () {
+ if (window.onpopstate !== null) {
+ callback();
+ clearInterval(interval);
+ }
+ }, 100);
+ };
+
+ isDirectorReady(function () {
+ oldSetRoute.call(getRouter(), route);
+ });
+ };
+}
+
+exports.initRouter = initRouter;
+exports.getRouter = getRouter;
+exports.goTo = goTo;
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _RoutingEngine = __webpack_require__(0);
+
+function redirect(to) {
+ (0, _RoutingEngine.goTo)(to);
+}
+
+exports.default = redirect;
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE_2__;
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+var _RoutingEngine = __webpack_require__(0);
+
+var _react = __webpack_require__(2);
+
+var _react2 = _interopRequireDefault(_react);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var Link = function (_Component) {
+ _inherits(Link, _Component);
+
+ function Link() {
+ _classCallCheck(this, Link);
+
+ return _possibleConstructorReturn(this, (Link.__proto__ || Object.getPrototypeOf(Link)).apply(this, arguments));
+ }
+
+ _createClass(Link, [{
+ key: 'handleClick',
+ value: function handleClick(evt) {
+ evt.preventDefault();
+
+ var to = this.props.to;
+
+ if (!to) return;
+
+ (0, _RoutingEngine.goTo)(to);
+ }
+ }, {
+ key: 'render',
+ value: function render() {
+ var _props = this.props,
+ className = _props.className,
+ to = _props.to;
+
+
+ return _react2.default.createElement(
+ 'a',
+ { href: to, className: 'Link ' + (className || ''), onClick: this.handleClick.bind(this) },
+ this.props.children
+ );
+ }
+ }]);
+
+ return Link;
+}(_react.Component);
+
+exports.default = Link;
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+
+var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+var _react = __webpack_require__(2);
+
+var _react2 = _interopRequireDefault(_react);
+
+var _propTypes = __webpack_require__(11);
+
+var _propTypes2 = _interopRequireDefault(_propTypes);
+
+var _queryString = __webpack_require__(13);
+
+var _queryString2 = _interopRequireDefault(_queryString);
+
+var _RoutingEngine = __webpack_require__(0);
+
+var _redirect = __webpack_require__(1);
+
+var _redirect2 = _interopRequireDefault(_redirect);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+var NOT_FOUND_FALLBACK = '/not-found';
+
+function parseRouteParams(path, args) {
+ var paramNames = path.split('/').filter(function (item) {
+ return item.indexOf(':') === 0;
+ });
+
+ var paramsObj = {};
+ for (var i = 0; i < paramNames.length; i++) {
+ var name = paramNames[i];
+ paramsObj[name.substr(1)] = args[i];
+ }
+
+ return paramsObj;
+}
+
+function getQueryParams() {
+ if (!window.location) return null;
+ return _queryString2.default.parse(window.location.search);
+}
+
+var Router = function (_Component) {
+ _inherits(Router, _Component);
+
+ function Router(props) {
+ _classCallCheck(this, Router);
+
+ var _this = _possibleConstructorReturn(this, (Router.__proto__ || Object.getPrototypeOf(Router)).call(this, props));
+
+ _this.state = {
+ viewClass: null,
+ route: null,
+ params: {}
+ };
+
+ if (!props.routes) {
+ throw new Error('Provide the router property "routes".');
+ }
+
+ if (!props.notFoundPath) {
+ throw new Error('Provide the router property "notFoundPath".');
+ }
+ return _this;
+ }
+
+ _createClass(Router, [{
+ key: 'execMiddlewares',
+ value: function execMiddlewares(injectProps) {
+ var _this2 = this;
+
+ if (!this.props.middlewares) return;
+
+ var middlewares = this.props.middlewares;
+
+ var _middlewares = middlewares.slice();
+
+ var shouldStop = false;
+
+ var getArgsList = function getArgsList() {
+ return Object.keys(injectProps).map(function (propName) {
+ return injectProps[propName];
+ });
+ };
+ var getNextMiddleware = function getNextMiddleware() {
+ return _middlewares.shift();
+ };
+ var execMiddlewareLoop = function execMiddlewareLoop() {
+ var middlewareFn = getNextMiddleware();
+ if (middlewareFn) {
+
+ var success = middlewareFn.apply(_this2, getArgsList());
+
+ if (success === false) {
+ shouldStop = true;
+ return;
+ } else {
+ execMiddlewareLoop();
+ }
+ }
+ };
+ execMiddlewareLoop();
+
+ return shouldStop;
+ }
+ }, {
+ key: 'componentWillMount',
+ value: function componentWillMount() {
+ var _this3 = this;
+
+ var props = this.props;
+ var injectProps = props.injectProps,
+ notFoundPath = props.notFoundPath,
+ middlewares = props.middlewares;
+
+
+ var parsedRoutes = {};
+ props.routes.forEach(function (route) {
+ parsedRoutes[route.path] = function () {
+ for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ if (!route.viewClass) {
+ throw new Error('The chosen route "' + route.path + '" should have a "viewClass" property.');
+ }
+
+ var params = parseRouteParams(route.path, args);
+ var queryParams = getQueryParams();
+
+ // Executa middlewares
+ var middlewareProps = { props: injectProps, params: params, queryParams: queryParams, route: route };
+ if (_this3.execMiddlewares(middlewareProps) === true) return;
+
+ // Executa o handler da rota
+ route.handler && route.handler(_extends({}, injectProps, { params: params, queryParams: queryParams }));
+
+ // Modifica estado -> dispara render
+ _this3.setState({ route: route, viewClass: route.viewClass, params: params, queryParams: queryParams });
+ };
+ });
+
+ (0, _RoutingEngine.initRouter)(parsedRoutes, _extends({
+ notfound: function notfound() {
+ (0, _redirect2.default)(notFoundPath || NOT_FOUND_FALLBACK);
+ },
+ html5history: true,
+ strict: false
+ }, props.config));
+ }
+
+ // Adiciona os higher order components
+
+ }, {
+ key: 'wrapHOCs',
+ value: function wrapHOCs(viewClass) {
+ this.props.viewHOCs.forEach(function (hoc) {
+ viewClass = hoc(viewClass);
+ });
+
+ return viewClass;
+ }
+ }, {
+ key: 'render',
+ value: function render() {
+ var _state = this.state,
+ viewClass = _state.viewClass,
+ params = _state.params,
+ queryParams = _state.queryParams;
+ var injectProps = this.props.injectProps;
+
+
+ if (!viewClass) return null;
+
+ var View = this.wrapHOCs(viewClass);
+
+ return _react2.default.createElement(View, _extends({}, injectProps, { params: params, queryParams: queryParams }));
+ }
+ }]);
+
+ return Router;
+}(_react.Component);
+
+Router.propTypes = {
+ routes: _propTypes2.default.array,
+ notFoundPath: _propTypes2.default.string,
+ injectProps: _propTypes2.default.object,
+ middlewares: _propTypes2.default.array,
+ viewHOCs: _propTypes2.default.array
+};
+
+Router.defaultProps = {
+ injectProps: {},
+ middlewares: [],
+ viewHOCs: []
+};
+
+exports.default = Router;
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+var token = '%[a-f0-9]{2}';
+var singleMatcher = new RegExp(token, 'gi');
+var multiMatcher = new RegExp('(' + token + ')+', 'gi');
+
+function decodeComponents(components, split) {
+ try {
+ // Try to decode the entire string first
+ return decodeURIComponent(components.join(''));
+ } catch (err) {
+ // Do nothing
+ }
+
+ if (components.length === 1) {
+ return components;
+ }
+
+ split = split || 1;
+
+ // Split the array in 2 parts
+ var left = components.slice(0, split);
+ var right = components.slice(split);
+
+ return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right));
+}
+
+function decode(input) {
+ try {
+ return decodeURIComponent(input);
+ } catch (err) {
+ var tokens = input.match(singleMatcher);
+
+ for (var i = 1; i < tokens.length; i++) {
+ input = decodeComponents(tokens, i).join('');
+
+ tokens = input.match(singleMatcher);
+ }
+
+ return input;
+ }
+}
+
+function customDecodeURIComponent(input) {
+ // Keep track of all the replacements and prefill the map with the `BOM`
+ var replaceMap = {
+ '%FE%FF': '\uFFFD\uFFFD',
+ '%FF%FE': '\uFFFD\uFFFD'
+ };
+
+ var match = multiMatcher.exec(input);
+ while (match) {
+ try {
+ // Decode as big chunks as possible
+ replaceMap[match[0]] = decodeURIComponent(match[0]);
+ } catch (err) {
+ var result = decode(match[0]);
+
+ if (result !== match[0]) {
+ replaceMap[match[0]] = result;
+ }
+ }
+
+ match = multiMatcher.exec(input);
+ }
+
+ // Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else
+ replaceMap['%C2'] = '\uFFFD';
+
+ var entries = Object.keys(replaceMap);
+
+ for (var i = 0; i < entries.length; i++) {
+ // Replace all decoded components
+ var key = entries[i];
+ input = input.replace(new RegExp(key, 'g'), replaceMap[key]);
+ }
+
+ return input;
+}
+
+module.exports = function (encodedURI) {
+ if (typeof encodedURI !== 'string') {
+ throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + (typeof encodedURI === 'undefined' ? 'undefined' : _typeof(encodedURI)) + '`');
+ }
+
+ try {
+ encodedURI = encodedURI.replace(/\+/g, ' ');
+
+ // Try the built in decoder first
+ return decodeURIComponent(encodedURI);
+ } catch (err) {
+ // Fallback to a more advanced decoder
+ return customDecodeURIComponent(encodedURI);
+ }
+};
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+//
+// Generated on Tue Dec 16 2014 12:13:47 GMT+0100 (CET) by Charlie Robbins, Paolo Fragomeni & the Contributors (Using Codesurgeon).
+// Version 1.2.6
+//
+
+(function (exports) {
+
+ /*
+ * browser.js: Browser specific functionality for director.
+ *
+ * (C) 2011, Charlie Robbins, Paolo Fragomeni, & the Contributors.
+ * MIT LICENSE
+ *
+ */
+
+ var dloc = document.location;
+
+ function dlocHashEmpty() {
+ // Non-IE browsers return '' when the address bar shows '#'; Director's logic
+ // assumes both mean empty.
+ return dloc.hash === '' || dloc.hash === '#';
+ }
+
+ var listener = {
+ mode: 'modern',
+ hash: dloc.hash,
+ history: false,
+
+ check: function check() {
+ var h = dloc.hash;
+ if (h != this.hash) {
+ this.hash = h;
+ this.onHashChanged();
+ }
+ },
+
+ fire: function fire() {
+ if (this.mode === 'modern') {
+ this.history === true ? window.onpopstate() : window.onhashchange();
+ } else {
+ this.onHashChanged();
+ }
+ },
+
+ init: function init(fn, history) {
+ var self = this;
+ this.history = history;
+
+ if (!Router.listeners) {
+ Router.listeners = [];
+ }
+
+ function onchange(onChangeEvent) {
+ for (var i = 0, l = Router.listeners.length; i < l; i++) {
+ Router.listeners[i](onChangeEvent);
+ }
+ }
+
+ //note IE8 is being counted as 'modern' because it has the hashchange event
+ if ('onhashchange' in window && (document.documentMode === undefined || document.documentMode > 7)) {
+ // At least for now HTML5 history is available for 'modern' browsers only
+ if (this.history === true) {
+ // There is an old bug in Chrome that causes onpopstate to fire even
+ // upon initial page load. Since the handler is run manually in init(),
+ // this would cause Chrome to run it twise. Currently the only
+ // workaround seems to be to set the handler after the initial page load
+ // http://code.google.com/p/chromium/issues/detail?id=63040
+ setTimeout(function () {
+ window.onpopstate = onchange;
+ }, 500);
+ } else {
+ window.onhashchange = onchange;
+ }
+ this.mode = 'modern';
+ } else {
+ //
+ // IE support, based on a concept by Erik Arvidson ...
+ //
+ var frame = document.createElement('iframe');
+ frame.id = 'state-frame';
+ frame.style.display = 'none';
+ document.body.appendChild(frame);
+ this.writeFrame('');
+
+ if ('onpropertychange' in document && 'attachEvent' in document) {
+ document.attachEvent('onpropertychange', function () {
+ if (event.propertyName === 'location') {
+ self.check();
+ }
+ });
+ }
+
+ window.setInterval(function () {
+ self.check();
+ }, 50);
+
+ this.onHashChanged = onchange;
+ this.mode = 'legacy';
+ }
+
+ Router.listeners.push(fn);
+
+ return this.mode;
+ },
+
+ destroy: function destroy(fn) {
+ if (!Router || !Router.listeners) {
+ return;
+ }
+
+ var listeners = Router.listeners;
+
+ for (var i = listeners.length - 1; i >= 0; i--) {
+ if (listeners[i] === fn) {
+ listeners.splice(i, 1);
+ }
+ }
+ },
+
+ setHash: function setHash(s) {
+ // Mozilla always adds an entry to the history
+ if (this.mode === 'legacy') {
+ this.writeFrame(s);
+ }
+
+ if (this.history === true) {
+ window.history.pushState({}, document.title, s);
+ // Fire an onpopstate event manually since pushing does not obviously
+ // trigger the pop event.
+ this.fire();
+ } else {
+ dloc.hash = s[0] === '/' ? s : '/' + s;
+ }
+ return this;
+ },
+
+ writeFrame: function writeFrame(s) {
+ // IE support...
+ var f = document.getElementById('state-frame');
+ var d = f.contentDocument || f.contentWindow.document;
+ d.open();
+ d.write("
+