preact-router
Advanced tools
Comparing version 1.1.0 to 1.2.0
@@ -1,3 +0,3 @@ | ||
(function(global,factory){if(typeof define === 'function' && define.amd){define(['exports','preact'],factory);}else if(typeof exports !== 'undefined'){factory(exports,require('preact'));}else {var mod={exports:{}};factory(mod.exports,global.preact);global.preactRouter = mod.exports;}})(this,function(exports,_preact){'use strict';exports.__esModule = 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;};exports.route = route;function _objectWithoutProperties(obj,keys){var target={};for(var i in obj) {if(keys.indexOf(i) >= 0)continue;if(!Object.prototype.hasOwnProperty.call(obj,i))continue;target[i] = obj[i];}return target;}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError('Cannot call a class as a function');}}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 routers=[];function route(url){var replace=arguments.length <= 1 || arguments[1] === undefined?false:arguments[1];if(typeof url !== 'string' && url.url){replace = url.replace;url = url.url;}if(history){if(replace === true){history.replaceState(null,null,url);}else {history.pushState(null,null,url);}}routeTo(url);}function routeTo(url){routers.forEach(function(router){return router.routeTo(url);});}function getCurrentUrl(){return '' + (location.pathname || '') + (location.search || '');}if(typeof addEventListener === 'function'){addEventListener('popstate',function(){return routeTo(getCurrentUrl());});}function handleLinkClick(e){route(this.getAttribute('href'));if(e.stopImmediatePropagation)e.stopImmediatePropagation();e.stopPropagation();e.preventDefault();return false;}var Link=function Link(_ref){var children=_ref.children;var props=_objectWithoutProperties(_ref,['children']);return _preact.h('a',_extends({},props,{onClick:handleLinkClick}),children);};exports.Link = Link;var Router=(function(_Component){_inherits(Router,_Component);function Router(){_classCallCheck(this,Router);_Component.apply(this,arguments);}Router.prototype.getInitialState = function getInitialState(){return {url:getCurrentUrl()};};Router.prototype.routeTo = function routeTo(url){this.setState({url:url});};Router.prototype.componentWillMount = function componentWillMount(){routers.push(this);};Router.prototype.componentWillUnmount = function componentWillUnmount(){routers.splice(routers.indexOf(this),1);};Router.prototype.render = function render(_ref2,_ref3){var children=_ref2.children;var onChange=_ref2.onChange;var url=_ref3.url;var active=children.filter(function(_ref4){var attributes=_ref4.attributes;var path=attributes.path,matches=exec(url,path);if(matches){attributes.url = url;attributes.matches = matches;for(var i in matches) {if(matches.hasOwnProperty(i)){attributes[i] = matches[i];}}return true;}});var previous=this.previousUrl;if(url !== previous){this.previousUrl = url;if(typeof onChange === 'function'){onChange({router:this,url:url,previous:previous,active:active,current:active[0]});}}return active[0] || null;};return Router;})(_preact.Component);exports.Router = Router;var Route=function Route(_ref5){var RoutedComponent=_ref5.component;var url=_ref5.url;var matches=_ref5.matches;return _preact.h(RoutedComponent,{url:url,matches:matches});};exports.Route = Route;function exec(url,route){var reg=/(?:\?([^#]*))?(#.*)?$/,c=url.match(reg),matches={};if(c && c[1]){var p=c[1].split('&');for(var i=0;i < p.length;i++) {var r=p[i].split('=');matches[decodeURIComponent(r[0])] = decodeURIComponent(r.slice(1).join('='));}}url = segmentize(url.replace(reg,''));route = segmentize(route);var max=Math.max(url.length,route.length);for(var i=0;i < max;i++) {if(route[i] && route[i].charAt(0) === ':'){matches[route[i].substring(1)] = decodeURIComponent(url[i] || '');}else {if(route[i] !== url[i]){return false;}}}return matches;}Router.route = route;Router.Route = Route;Router.Link = Link;exports['default'] = Router;var segmentize=function segmentize(url){return strip(url).split('/');};var strip=function strip(url){return url.replace(/(^\/+|\/+$)/g,'');};}); | ||
(function(global,factory){if(typeof define === 'function' && define.amd){define(['exports','preact','./util'],factory);}else if(typeof exports !== 'undefined'){factory(exports,require('preact'),require('./util'));}else {var mod={exports:{}};factory(mod.exports,global.preact,global.util);global.preactRouter = mod.exports;}})(this,function(exports,_preact,_util){'use strict';exports.__esModule = 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;};exports.route = route;function _objectWithoutProperties(obj,keys){var target={};for(var i in obj) {if(keys.indexOf(i) >= 0)continue;if(!Object.prototype.hasOwnProperty.call(obj,i))continue;target[i] = obj[i];}return target;}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError('Cannot call a class as a function');}}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 routers=[];var EMPTY={};function route(url){var replace=arguments.length <= 1 || arguments[1] === undefined?false:arguments[1];if(typeof url !== 'string' && url.url){replace = url.replace;url = url.url;}if(history){if(replace === true){history.replaceState(null,null,url);}else {history.pushState(null,null,url);}}routeTo(url);}function routeTo(url){routers.forEach(function(router){return router.routeTo(url);});}function getCurrentUrl(){var url=typeof location !== 'undefined'?location:EMPTY;return '' + (url.pathname || '') + (url.search || '');}if(typeof addEventListener === 'function'){addEventListener('popstate',function(){return routeTo(getCurrentUrl());});}function handleLinkClick(e){route(this.getAttribute('href'));if(e.stopImmediatePropagation)e.stopImmediatePropagation();e.stopPropagation();e.preventDefault();return false;}var Link=function Link(_ref){var children=_ref.children;var props=_objectWithoutProperties(_ref,['children']);return _preact.h('a',_extends({},props,{onClick:handleLinkClick}),children);};exports.Link = Link;var Router=(function(_Component){_inherits(Router,_Component);function Router(){_classCallCheck(this,Router);_Component.apply(this,arguments);}Router.prototype.getInitialState = function getInitialState(){return {url:getCurrentUrl()};};Router.prototype.routeTo = function routeTo(url){this.setState({url:url});};Router.prototype.componentWillMount = function componentWillMount(){routers.push(this);};Router.prototype.componentWillUnmount = function componentWillUnmount(){routers.splice(routers.indexOf(this),1);};Router.prototype.render = function render(_ref2,_ref3){var children=_ref2.children;var onChange=_ref2.onChange;var url=_ref3.url;var active=children.slice().sort(_util.pathRankSort).filter(function(_ref4){var attributes=_ref4.attributes;var path=attributes.path,matches=_util.exec(url,path,attributes);if(matches){attributes.url = url;attributes.matches = matches;for(var i in matches) {if(matches.hasOwnProperty(i)){attributes[i] = matches[i];}}return true;}});var previous=this.previousUrl;if(url !== previous){this.previousUrl = url;if(typeof onChange === 'function'){onChange({router:this,url:url,previous:previous,active:active,current:active[0]});}}return active[0] || null;};return Router;})(_preact.Component);exports.Router = Router;var Route=function Route(_ref5){var RoutedComponent=_ref5.component;var url=_ref5.url;var matches=_ref5.matches;return _preact.h(RoutedComponent,{url:url,matches:matches});};exports.Route = Route;Router.route = route;Router.Route = Route;Router.Link = Link;exports['default'] = Router;}); | ||
//# sourceMappingURL=preact-router.js.map |
{ | ||
"name": "preact-router", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "Connect your components up to that address bar.", | ||
@@ -28,15 +28,15 @@ "main": "dist/preact-router.js", | ||
"peerDependencies": { | ||
"preact": "^2.2.0" | ||
"preact": "^2.8.3" | ||
}, | ||
"devDependencies": { | ||
"babel": "^5.8.23", | ||
"babel-eslint": "^4.1.3", | ||
"chai": "^3.3.0", | ||
"babel-eslint": "^4.1.7", | ||
"chai": "^3.5.0", | ||
"eslint": "^1.7.1", | ||
"mkdirp": "^0.5.1", | ||
"mocha": "^2.3.3", | ||
"sinon": "^1.17.1", | ||
"sinon-chai": "^2.8.0", | ||
"preact": "^2.2.0" | ||
"mocha": "^2.4.5", | ||
"preact": "^2.8.3", | ||
"sinon": "^1.17.3", | ||
"sinon-chai": "^2.8.0" | ||
} | ||
} |
@@ -8,3 +8,5 @@ # preact-router | ||
`preact-router` provides a `<Router />` component that conditionally renders its children when the URL matches their `path`. It also includes a convenient `<Link />` component as a drop-in replacement for `<a />` wired up to the router. | ||
--- | ||
@@ -32,2 +34,20 @@ | ||
### Handling URLS | ||
:information_desk_person: Pages are just regular components that get mounted when you navigate to a certain URL. | ||
Any URL parameters get passed to the component as `props`. | ||
Defining what component(s) to load for a given URL is easy and declarative. | ||
You can even mix-and-match URL parameters and normal `props`. | ||
```js | ||
<Router> | ||
<A path="/" /> | ||
<B path="/b" id="42" /> | ||
<C path="/c/:id" /> | ||
</Router> | ||
``` | ||
--- | ||
@@ -34,0 +54,0 @@ |
import { h, Component } from 'preact'; | ||
import { exec, pathRankSort } from './util'; | ||
const routers = []; | ||
const EMPTY = {}; | ||
export function route(url, replace=false) { | ||
@@ -26,3 +29,4 @@ if (typeof url!=='string' && url.url) { | ||
function getCurrentUrl() { | ||
return `${location.pathname || ''}${location.search || ''}`; | ||
let url = typeof location!=='undefined' ? location : EMPTY; | ||
return `${url.pathname || ''}${url.search || ''}`; | ||
} | ||
@@ -67,5 +71,5 @@ | ||
render({ children, onChange }, { url }) { | ||
let active = children.filter( ({ attributes }) => { | ||
let active = children.slice().sort(pathRankSort).filter( ({ attributes }) => { | ||
let path = attributes.path, | ||
matches = exec(url, path); | ||
matches = exec(url, path, attributes); | ||
if (matches) { | ||
@@ -105,39 +109,3 @@ attributes.url = url; | ||
/* | ||
export class Route extends Component { | ||
render({ component:RoutedComponent, url, matches }) { | ||
return <RoutedComponent { ...{url, matches} } />; | ||
} | ||
} | ||
*/ | ||
function exec(url, route) { | ||
let reg = /(?:\?([^#]*))?(#.*)?$/, | ||
c = url.match(reg), | ||
matches = {}; | ||
if (c && c[1]) { | ||
let p = c[1].split('&'); | ||
for (let i=0; i<p.length; i++) { | ||
let r = p[i].split('='); | ||
matches[decodeURIComponent(r[0])] = decodeURIComponent(r.slice(1).join('=')); | ||
} | ||
} | ||
url = segmentize(url.replace(reg, '')); | ||
route = segmentize(route); | ||
let max = Math.max(url.length, route.length); | ||
for (let i=0; i<max; i++) { | ||
if (route[i] && route[i].charAt(0)===':') { | ||
matches[route[i].substring(1)] = decodeURIComponent(url[i] || ''); | ||
} | ||
else { | ||
if (route[i]!==url[i]) { | ||
return false; | ||
} | ||
} | ||
} | ||
return matches; | ||
} | ||
Router.route = route; | ||
@@ -147,6 +115,1 @@ Router.Route = Route; | ||
export default Router; | ||
let segmentize = url => strip(url).split('/'); | ||
let strip = url => url.replace(/(^\/+|\/+$)/g, ''); |
@@ -1,2 +0,2 @@ | ||
import { Router, Route, Link } from '../src'; | ||
import { Router, Link, route } from '../src'; | ||
import { h, Component } from 'preact'; | ||
@@ -7,9 +7,76 @@ import { expect, use } from 'chai'; | ||
use(sinonChai); | ||
/** @jsx h */ | ||
describe('preact-router', () => { | ||
describe('Not a Test', () => { | ||
it('should not be tested yet', () => { | ||
expect(1).to.equal(1); | ||
it('should export Router, Link and route', () => { | ||
expect(Router).to.be.a('function'); | ||
expect(Link).to.be.a('function'); | ||
expect(route).to.be.a('function'); | ||
}); | ||
describe('Router', () => { | ||
it('should filter children based on URL', () => { | ||
let router = new Router(); | ||
let children = [ | ||
<foo path="/" />, | ||
<foo path="/foo" />, | ||
<foo path="/foo/bar" /> | ||
]; | ||
expect( | ||
router.render({ children }, { url:'/foo' }) | ||
).to.equal(children[1]); | ||
expect( | ||
router.render({ children }, { url:'/' }) | ||
).to.equal(children[0]); | ||
expect( | ||
router.render({ children }, { url:'/foo/bar' }) | ||
).to.equal(children[2]); | ||
}); | ||
it('should support nested parameterized routes', () => { | ||
let router = new Router(); | ||
let children = [ | ||
<foo path="/foo" />, | ||
<foo path="/foo/:bar" />, | ||
<foo path="/foo/:bar/:baz" /> | ||
]; | ||
expect( | ||
router.render({ children }, { url:'/foo' }) | ||
).to.equal(children[0]); | ||
expect( | ||
router.render({ children }, { url:'/foo/bar' }) | ||
).to.equal(children[1]).and.have.deep.property('attributes.bar', 'bar'); | ||
expect( | ||
router.render({ children }, { url:'/foo/bar/baz' }) | ||
).equal(children[2]).and.have.deep.property('attributes') | ||
.which.contains.all.keys({ bar:'bar', baz:'baz' }); | ||
}); | ||
it('should support default routes', () => { | ||
let router = new Router(); | ||
let children = [ | ||
<foo default />, | ||
<foo path="/" />, | ||
<foo path="/foo" /> | ||
]; | ||
expect( | ||
router.render({ children }, { url:'/foo' }) | ||
).to.equal(children[2]); | ||
expect( | ||
router.render({ children }, { url:'/' }) | ||
).to.equal(children[1]); | ||
expect( | ||
router.render({ children }, { url:'/asdf/asdf' }) | ||
).to.equal(children[0]); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
21025
13
280
61
1