├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── lib ├── components.js ├── index.js └── utils.js ├── package.json ├── src ├── components.es6 ├── index.es6 └── utils.es6 ├── test.es6 └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw[pon] 2 | node_modules/ 3 | *.map 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 (2015-10-27) 2 | 3 | react-router 1.0.0rc-3 support. 4 | 5 | - `````` can accept ```routes``` via both props or context. 6 | - Fixed reverse algorithm to concatenate routes using ```url-join``` now that 7 | react-router discerns between relative and absolute paths in nested routes. 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Kevin Ngo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | react-router-reverse 2 | ==================== 3 | 4 | Components and helpers for route reversal in react-router@1.x.x. 5 | 6 | ## \ 7 | 8 | Wraps react-router's ```Link``` component to handle route reversal. 9 | ```routes``` can either be passed explicitly as props or implicitly as context. 10 | Since react-router@1.0.0-rc1+ stopped using context, you can still tell your 11 | app to pass down routes using ```childContextTypes``` and ```getChildContext```. 12 | 13 | **With props:** 14 | 15 | ```js 16 | import React from 'react'; 17 | import {ReverseLink} from 'react-router-reverse'; 18 | 19 | 20 | class MyComponentWithProps extends React.Component { 21 | static propTypes = { 22 | routes: React.PropTypes.array.isRequired 23 | } 24 | 25 | render() { 26 | return ( 27 | 35 | ); 36 | } 37 | } 38 | ``` 39 | 40 | **With context:** 41 | 42 | ```js 43 | import React from 'react'; 44 | import {ReverseLink} from 'react-router-reverse'; 45 | 46 | 47 | class MyComponentWithContext extends React.Component { 48 | static contextTypes = { 49 | routes: React.PropTypes.array.isRequired 50 | } 51 | 52 | render() { 53 | return ( 54 | 58 | ); 59 | } 60 | } 61 | ``` 62 | 63 | ## reverse(routes, name, params) 64 | 65 | Reverses a route name given a react-router's ```routes```. 66 | 67 | ```js 68 | import React from 'react'; 69 | import {reverse} from 'react-router-reverse'; 70 | 71 | 72 | class MyComponent extends React.Component { 73 | static propTypes = { 74 | routes: React.PropTypes.array.isRequired 75 | } 76 | 77 | transitionHome = () => { 78 | const path = reverse(this.props.routes, 'landing'); 79 | this.router.transition(path); 80 | } 81 | 82 | render() { 83 | return ( 84 | 85 | ); 86 | } 87 | } 88 | ``` 89 | 90 | ## Contributors 91 | 92 | - [maslianok](https://github.com/maslianok) for writing reverse util. 93 | - [joellanciaux](https://github.com/joellanciaux) for upgrading from 94 | react-router@1.0.0-beta3 to react-router@1.0.0-rc3. 95 | -------------------------------------------------------------------------------- /lib/components.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | 7 | 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; }; 8 | 9 | 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; }; })(); 10 | 11 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 12 | 13 | exports.createReverseLink = createReverseLink; 14 | 15 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 16 | 17 | 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; } 18 | 19 | var _utils = require('./utils'); 20 | 21 | function createReverseLink(React, Link) { 22 | return (function (_React$Component) { 23 | _inherits(ReverseLink, _React$Component); 24 | 25 | function ReverseLink() { 26 | _classCallCheck(this, ReverseLink); 27 | 28 | _get(Object.getPrototypeOf(ReverseLink.prototype), 'constructor', this).apply(this, arguments); 29 | } 30 | 31 | _createClass(ReverseLink, [{ 32 | key: 'render', 33 | value: function render() { 34 | var path = (0, _utils.reverse)(this.props.routes || this.context.routes, this.props.to, this.props.params); 35 | return React.createElement(Link, _extends({}, this.props, { to: path })); 36 | } 37 | }], [{ 38 | key: 'propTypes', 39 | value: { 40 | to: React.PropTypes.string, 41 | params: React.PropTypes.object, 42 | routes: React.PropTypes.array 43 | }, 44 | enumerable: true 45 | }, { 46 | key: 'contextTypes', 47 | value: { 48 | routes: React.PropTypes.array 49 | }, 50 | enumerable: true 51 | }]); 52 | 53 | return ReverseLink; 54 | })(React.Component); 55 | } -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | 7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8 | 9 | var _react = require('react'); 10 | 11 | var _react2 = _interopRequireDefault(_react); 12 | 13 | var _reactRouter = require('react-router'); 14 | 15 | var _components = require('./components'); 16 | 17 | var _utils = require('./utils'); 18 | 19 | var ReverseLink = (0, _components.createReverseLink)(_react2['default'], _reactRouter.Link); 20 | exports.ReverseLink = ReverseLink; 21 | exports.reverse = _utils.reverse; -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | exports.reverse = reverse; 7 | 8 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 9 | 10 | var _reactRouterLibPatternUtils = require('react-router/lib/PatternUtils'); 11 | 12 | var _urlJoin = require('url-join'); 13 | 14 | var _urlJoin2 = _interopRequireDefault(_urlJoin); 15 | 16 | /** 17 | * @author Adapted from https://github.com/maslianok. 18 | */ 19 | 20 | function reverse(routes, name, params) { 21 | var parentPath = arguments.length <= 3 || arguments[3] === undefined ? '' : arguments[3]; 22 | 23 | if (!routes) { 24 | console.error('Routes were not provided for reverse().'); 25 | } 26 | 27 | for (var i = 0; i < routes.length; i++) { 28 | var route = routes[i]; 29 | 30 | var currentPath = undefined; 31 | if (route.path && route.path[0] === '/') { 32 | // Absolute path. 33 | currentPath = route.path; 34 | } else { 35 | // Relative path. 36 | currentPath = (0, _urlJoin2['default'])(parentPath, route.path || '/'); 37 | } 38 | 39 | if (name == route.name) { 40 | return (0, _reactRouterLibPatternUtils.formatPattern)(currentPath, params); 41 | }; 42 | 43 | if (route.childRoutes) { 44 | var url = reverse(route.childRoutes, name, params, currentPath); 45 | if (url) { 46 | return url; 47 | } 48 | } 49 | }; 50 | if (!parentPath) { 51 | console.error('No reverse match for name \'' + name + '\''); 52 | } 53 | } 54 | 55 | ; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-router-reverse", 3 | "version": "1.0.2", 4 | "description": "Components and helpers for route reversal in react-router@1.x.x.", 5 | "main": "./lib/index.js", 6 | "devDependencies": { 7 | "babel": "^5.4.7", 8 | "babel-runtime": "^5.8.20", 9 | "history": "^1.12.1", 10 | "jsdom": "^3.1.2", 11 | "mocha": "^2.2.5", 12 | "mocha-jsdom": "^1.0.0", 13 | "react": "^0.14.0", 14 | "react-dom": "^0.14.0", 15 | "react-router": "^1.0.0-rc3" 16 | }, 17 | "peerDependencies": { 18 | "react": "^0.14.0", 19 | "react-router": "^1.0.0-rc3" 20 | }, 21 | "scripts": { 22 | "build:lib": "babel --stage 0 src --out-dir lib", 23 | "pretest": "babel --stage 0 test.es6 -o test.js && npm run build:lib", 24 | "test": "mocha test.js", 25 | "prepublish": "npm run build:lib" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "https://github.com/ngokevin/react-router-reverse" 30 | }, 31 | "keywords": [ 32 | "react", 33 | "react-router", 34 | "router", 35 | "reverse", 36 | "route", 37 | "link", 38 | "react-component" 39 | ], 40 | "author": "Kevin Ngo ", 41 | "license": "MIT", 42 | "bugs": { 43 | "url": "https://github.com/ngokevin/react-router-reverse/issues" 44 | }, 45 | "homepage": "https://github.com/ngokevin/react-router-reverse", 46 | "dependencies": { 47 | "url-join": "0.0.1" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/components.es6: -------------------------------------------------------------------------------- 1 | import {reverse} from './utils'; 2 | 3 | 4 | export function createReverseLink(React, Link) { 5 | return class ReverseLink extends React.Component { 6 | static propTypes = { 7 | to: React.PropTypes.string, 8 | params: React.PropTypes.object, 9 | routes: React.PropTypes.array 10 | }; 11 | 12 | static contextTypes = { 13 | routes: React.PropTypes.array 14 | } 15 | 16 | render() { 17 | const path = reverse(this.props.routes || this.context.routes, 18 | this.props.to, this.props.params); 19 | return 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/index.es6: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Link} from 'react-router'; 3 | 4 | import {createReverseLink} from './components'; 5 | import {reverse} from './utils'; 6 | 7 | 8 | export const ReverseLink = createReverseLink(React, Link); 9 | export {reverse}; 10 | -------------------------------------------------------------------------------- /src/utils.es6: -------------------------------------------------------------------------------- 1 | import {formatPattern} from 'react-router/lib/PatternUtils'; 2 | import urlJoin from 'url-join'; 3 | 4 | 5 | /** 6 | * @author Adapted from https://github.com/maslianok. 7 | */ 8 | export function reverse(routes, name, params, parentPath='') { 9 | if (!routes) { 10 | console.error('Routes were not provided for reverse().'); 11 | } 12 | 13 | for (let i = 0; i < routes.length; i++) { 14 | let route = routes[i]; 15 | 16 | let currentPath; 17 | if (route.path && route.path[0] === '/') { 18 | // Absolute path. 19 | currentPath = route.path; 20 | } else { 21 | // Relative path. 22 | currentPath = urlJoin(parentPath, (route.path || '/')); 23 | } 24 | 25 | if (name == route.name) { 26 | return formatPattern(currentPath, params); 27 | }; 28 | 29 | if (route.childRoutes) { 30 | let url = reverse(route.childRoutes, name, params, currentPath); 31 | if (url) { 32 | return url; 33 | } 34 | } 35 | }; 36 | if (!parentPath) { 37 | console.error(`No reverse match for name '${name}'`); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /test.es6: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import _jsdom from 'jsdom'; 3 | import mochaJsdom from 'mocha-jsdom'; 4 | import ReactDOM from 'react-dom'; 5 | import {Route, Router} from 'react-router'; 6 | 7 | import {reverse, ReverseLink} from './lib/index'; 8 | 9 | 10 | global.document = _jsdom.jsdom(''); 11 | global.window = document.parentWindow; 12 | global.navigator = window.navigator; 13 | const jsdom = mochaJsdom.bind(this, {skipWindowCheck: true}); 14 | 15 | 16 | describe('ReverseLink', () => { 17 | jsdom(); 18 | const React = require('react'); 19 | const {createMemoryHistory} = require('history'); 20 | 21 | class TestComponent extends React.Component { 22 | render() { 23 | return 30 | } 31 | } 32 | 33 | 34 | 35 | let div; 36 | beforeEach(() => { 37 | div = document.createElement('div'); 38 | }); 39 | afterEach(() => { 40 | ReactDOM.unmountComponentAtNode(div); 41 | }); 42 | 43 | it('reverses relative path', done => { 44 | const router = ( 45 | 46 | 47 | 48 | 49 | 51 | 52 | 53 | 54 | ); 55 | 56 | ReactDOM.render(router, div, () => { 57 | const homeLink = div.querySelectorAll('a')[0]; 58 | assert.equal(homeLink.getAttribute('href'), '/'); 59 | assert.equal(homeLink.innerHTML, 'Home'); 60 | 61 | const detailLink = div.querySelectorAll('a')[1]; 62 | assert.equal(detailLink.getAttribute('href'), '/detail/5'); 63 | assert.equal(detailLink.innerHTML, 'Detail'); 64 | 65 | const editLink = div.querySelectorAll('a')[2]; 66 | assert.equal(editLink.getAttribute('href'), '/detail/10/kev/edit'); 67 | assert.equal(editLink.innerHTML, 'Edit Post'); 68 | done(); 69 | }); 70 | }); 71 | 72 | it('reverses absolute nested path', done => { 73 | const router = ( 74 | 75 | 76 | 77 | 78 | 80 | 81 | 82 | 83 | ); 84 | 85 | ReactDOM.render(router, div, () => { 86 | const homeLink = div.querySelectorAll('a')[0]; 87 | assert.equal(homeLink.getAttribute('href'), '/'); 88 | assert.equal(homeLink.innerHTML, 'Home'); 89 | 90 | const detailLink = div.querySelectorAll('a')[1]; 91 | assert.equal(detailLink.getAttribute('href'), '/detail/5'); 92 | assert.equal(detailLink.innerHTML, 'Detail'); 93 | 94 | const editLink = div.querySelectorAll('a')[2]; 95 | assert.equal(editLink.getAttribute('href'), '/user/kev/edit'); 96 | assert.equal(editLink.innerHTML, 'Edit Post'); 97 | done(); 98 | }); 99 | }); 100 | }); 101 | 102 | 103 | describe('ReverseLink nested context', () => { 104 | jsdom(); 105 | const React = require('react'); 106 | const {createMemoryHistory} = require('history'); 107 | 108 | class App extends React.Component { 109 | render() { 110 | return
111 | {this.props.children} 112 |
113 | } 114 | } 115 | 116 | class Header extends React.Component { 117 | render() { 118 | return
119 | 123 |
124 | } 125 | } 126 | 127 | class TestComponent extends React.Component { 128 | render() { 129 | return
130 |
131 |
132 | } 133 | } 134 | 135 | const router = 136 | 137 | 138 | 139 | 140 | 141 | 142 | let div; 143 | beforeEach(() => { 144 | div = document.createElement('div'); 145 | }); 146 | afterEach(() => { 147 | ReactDOM.unmountComponentAtNode(div); 148 | }); 149 | 150 | it('reverses', done => { 151 | ReactDOM.render(router, div, () => { 152 | const homeLink = div.querySelectorAll('a')[0]; 153 | assert.equal(homeLink.getAttribute('href'), '/'); 154 | assert.equal(homeLink.innerHTML, 'Home'); 155 | done(); 156 | }); 157 | }); 158 | }); 159 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 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; }; })(); 4 | 5 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; 6 | 7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8 | 9 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } 10 | 11 | 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; } 12 | 13 | var _assert = require('assert'); 14 | 15 | var _assert2 = _interopRequireDefault(_assert); 16 | 17 | var _jsdom2 = require('jsdom'); 18 | 19 | var _jsdom3 = _interopRequireDefault(_jsdom2); 20 | 21 | var _mochaJsdom = require('mocha-jsdom'); 22 | 23 | var _mochaJsdom2 = _interopRequireDefault(_mochaJsdom); 24 | 25 | var _reactDom = require('react-dom'); 26 | 27 | var _reactDom2 = _interopRequireDefault(_reactDom); 28 | 29 | var _reactRouter = require('react-router'); 30 | 31 | var _libIndex = require('./lib/index'); 32 | 33 | global.document = _jsdom3['default'].jsdom(''); 34 | global.window = document.parentWindow; 35 | global.navigator = window.navigator; 36 | var jsdom = _mochaJsdom2['default'].bind(undefined, { skipWindowCheck: true }); 37 | 38 | describe('ReverseLink', function () { 39 | jsdom(); 40 | var React = require('react'); 41 | 42 | var _require = require('history'); 43 | 44 | var createMemoryHistory = _require.createMemoryHistory; 45 | 46 | var TestComponent = (function (_React$Component) { 47 | _inherits(TestComponent, _React$Component); 48 | 49 | function TestComponent() { 50 | _classCallCheck(this, TestComponent); 51 | 52 | _get(Object.getPrototypeOf(TestComponent.prototype), 'constructor', this).apply(this, arguments); 53 | } 54 | 55 | _createClass(TestComponent, [{ 56 | key: 'render', 57 | value: function render() { 58 | return React.createElement( 59 | 'nav', 60 | null, 61 | React.createElement( 62 | _libIndex.ReverseLink, 63 | { to: 'landing', routes: this.props.routes }, 64 | 'Home' 65 | ), 66 | React.createElement( 67 | _libIndex.ReverseLink, 68 | { to: 'detail', params: { id: 5 }, routes: this.props.routes }, 69 | 'Detail' 70 | ), 71 | React.createElement( 72 | _libIndex.ReverseLink, 73 | { to: 'detail-edit', params: { id: 10, user: 'kev' }, routes: this.props.routes }, 74 | 'Edit Post' 75 | ) 76 | ); 77 | } 78 | }]); 79 | 80 | return TestComponent; 81 | })(React.Component); 82 | 83 | var div = undefined; 84 | beforeEach(function () { 85 | div = document.createElement('div'); 86 | }); 87 | afterEach(function () { 88 | _reactDom2['default'].unmountComponentAtNode(div); 89 | }); 90 | 91 | it('reverses relative path', function (done) { 92 | var router = React.createElement( 93 | _reactRouter.Router, 94 | { history: createMemoryHistory() }, 95 | React.createElement( 96 | _reactRouter.Route, 97 | { name: 'app', component: TestComponent }, 98 | React.createElement(_reactRouter.Route, { name: 'landing', path: '/', component: TestComponent }), 99 | React.createElement( 100 | _reactRouter.Route, 101 | { name: 'detail', path: '/detail/:id', component: TestComponent }, 102 | React.createElement(_reactRouter.Route, { name: 'detail-edit', path: ':user/edit', 103 | component: TestComponent }) 104 | ) 105 | ) 106 | ); 107 | 108 | _reactDom2['default'].render(router, div, function () { 109 | var homeLink = div.querySelectorAll('a')[0]; 110 | _assert2['default'].equal(homeLink.getAttribute('href'), '/'); 111 | _assert2['default'].equal(homeLink.innerHTML, 'Home'); 112 | 113 | var detailLink = div.querySelectorAll('a')[1]; 114 | _assert2['default'].equal(detailLink.getAttribute('href'), '/detail/5'); 115 | _assert2['default'].equal(detailLink.innerHTML, 'Detail'); 116 | 117 | var editLink = div.querySelectorAll('a')[2]; 118 | _assert2['default'].equal(editLink.getAttribute('href'), '/detail/10/kev/edit'); 119 | _assert2['default'].equal(editLink.innerHTML, 'Edit Post'); 120 | done(); 121 | }); 122 | }); 123 | 124 | it('reverses absolute nested path', function (done) { 125 | var router = React.createElement( 126 | _reactRouter.Router, 127 | { history: createMemoryHistory() }, 128 | React.createElement( 129 | _reactRouter.Route, 130 | { name: 'app', component: TestComponent }, 131 | React.createElement(_reactRouter.Route, { name: 'landing', path: '/', component: TestComponent }), 132 | React.createElement( 133 | _reactRouter.Route, 134 | { name: 'detail', path: 'detail/:id', component: TestComponent }, 135 | React.createElement(_reactRouter.Route, { name: 'detail-edit', path: '/user/:user/edit', 136 | component: TestComponent }) 137 | ) 138 | ) 139 | ); 140 | 141 | _reactDom2['default'].render(router, div, function () { 142 | var homeLink = div.querySelectorAll('a')[0]; 143 | _assert2['default'].equal(homeLink.getAttribute('href'), '/'); 144 | _assert2['default'].equal(homeLink.innerHTML, 'Home'); 145 | 146 | var detailLink = div.querySelectorAll('a')[1]; 147 | _assert2['default'].equal(detailLink.getAttribute('href'), '/detail/5'); 148 | _assert2['default'].equal(detailLink.innerHTML, 'Detail'); 149 | 150 | var editLink = div.querySelectorAll('a')[2]; 151 | _assert2['default'].equal(editLink.getAttribute('href'), '/user/kev/edit'); 152 | _assert2['default'].equal(editLink.innerHTML, 'Edit Post'); 153 | done(); 154 | }); 155 | }); 156 | }); 157 | 158 | describe('ReverseLink nested context', function () { 159 | jsdom(); 160 | var React = require('react'); 161 | 162 | var _require2 = require('history'); 163 | 164 | var createMemoryHistory = _require2.createMemoryHistory; 165 | 166 | var App = (function (_React$Component2) { 167 | _inherits(App, _React$Component2); 168 | 169 | function App() { 170 | _classCallCheck(this, App); 171 | 172 | _get(Object.getPrototypeOf(App.prototype), 'constructor', this).apply(this, arguments); 173 | } 174 | 175 | _createClass(App, [{ 176 | key: 'render', 177 | value: function render() { 178 | return React.createElement( 179 | 'div', 180 | null, 181 | this.props.children 182 | ); 183 | } 184 | }]); 185 | 186 | return App; 187 | })(React.Component); 188 | 189 | var Header = (function (_React$Component3) { 190 | _inherits(Header, _React$Component3); 191 | 192 | function Header() { 193 | _classCallCheck(this, Header); 194 | 195 | _get(Object.getPrototypeOf(Header.prototype), 'constructor', this).apply(this, arguments); 196 | } 197 | 198 | _createClass(Header, [{ 199 | key: 'render', 200 | value: function render() { 201 | return React.createElement( 202 | 'header', 203 | null, 204 | React.createElement( 205 | 'nav', 206 | null, 207 | React.createElement( 208 | 'li', 209 | null, 210 | React.createElement( 211 | _libIndex.ReverseLink, 212 | { to: 'landing', routes: this.props.routes }, 213 | 'Home' 214 | ) 215 | ), 216 | React.createElement( 217 | 'li', 218 | null, 219 | React.createElement( 220 | _libIndex.ReverseLink, 221 | { to: 'detail', routes: this.props.routes }, 222 | 'Detail' 223 | ) 224 | ) 225 | ) 226 | ); 227 | } 228 | }]); 229 | 230 | return Header; 231 | })(React.Component); 232 | 233 | var TestComponent = (function (_React$Component4) { 234 | _inherits(TestComponent, _React$Component4); 235 | 236 | function TestComponent() { 237 | _classCallCheck(this, TestComponent); 238 | 239 | _get(Object.getPrototypeOf(TestComponent.prototype), 'constructor', this).apply(this, arguments); 240 | } 241 | 242 | _createClass(TestComponent, [{ 243 | key: 'render', 244 | value: function render() { 245 | return React.createElement( 246 | 'div', 247 | null, 248 | React.createElement(Header, this.props) 249 | ); 250 | } 251 | }]); 252 | 253 | return TestComponent; 254 | })(React.Component); 255 | 256 | var router = React.createElement( 257 | _reactRouter.Router, 258 | { history: createMemoryHistory() }, 259 | React.createElement( 260 | _reactRouter.Route, 261 | { name: 'app', component: App }, 262 | React.createElement(_reactRouter.Route, { name: 'landing', path: '/', component: TestComponent }), 263 | React.createElement(_reactRouter.Route, { name: 'detail', path: '/detail', component: TestComponent }) 264 | ) 265 | ); 266 | 267 | var div = undefined; 268 | beforeEach(function () { 269 | div = document.createElement('div'); 270 | }); 271 | afterEach(function () { 272 | _reactDom2['default'].unmountComponentAtNode(div); 273 | }); 274 | 275 | it('reverses', function (done) { 276 | _reactDom2['default'].render(router, div, function () { 277 | var homeLink = div.querySelectorAll('a')[0]; 278 | _assert2['default'].equal(homeLink.getAttribute('href'), '/'); 279 | _assert2['default'].equal(homeLink.innerHTML, 'Home'); 280 | done(); 281 | }); 282 | }); 283 | }); 284 | --------------------------------------------------------------------------------