From 0e684379ea05c7cea098612d620f01be70954b89 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 17 Apr 2017 20:18:47 -0400 Subject: [PATCH] A working relative links implementation (with test) that only accounts for links in a document (not `route("./foo")`). See #138. --- src/index.js | 27 +++++++++------------------ test/dom.js | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/index.js b/src/index.js index 868b190c..8b796f7b 100644 --- a/src/index.js +++ b/src/index.js @@ -79,17 +79,11 @@ function routeTo(url) { function routeFromLink(node) { - // only valid elements - if (!node || !node.getAttribute) return; - - let href = node.getAttribute('href'), - target = node.getAttribute('target'); - - // ignore links with targets and non-path URLs - if (!href || !href.match(/^\//g) || (target && !target.match(/^_?self$/i))) return; + // ignore invalid & external links: + if (!node || node.protocol!==location.protocol || node.host!==location.host || (node.target && !node.target.match(/^_?self$/i))) return; // attempt to route, if no match simply cede control to browser - return route(href); + return route(node.pathname + node.search + node.hash); } @@ -117,12 +111,9 @@ function delegateLinkHandler(e) { let t = e.target; do { - if (String(t.nodeName).toUpperCase()==='A' && t.getAttribute('href') && isPreactElement(t)) { - if (t.hasAttribute('native')) return; + if (String(t.nodeName).toUpperCase()==='A' && t.pathname && isPreactElement(t) && !t.hasAttribute('native') && routeFromLink(t)) { // if link is handled by the router, prevent browser defaults - if (routeFromLink(t)) { - return prevent(e); - } + return prevent(e); } } while ((t=t.parentNode)); } @@ -131,13 +122,13 @@ function delegateLinkHandler(e) { let eventListenersInitialized = false; function initEventListeners() { - if (eventListenersInitialized){ - return; - } + if (eventListenersInitialized) return; if (typeof addEventListener==='function') { if (!customHistory) { - addEventListener('popstate', () => routeTo(getCurrentUrl())); + addEventListener('popstate', () => { + routeTo(getCurrentUrl()); + }); } addEventListener('click', delegateLinkHandler); } diff --git a/test/dom.js b/test/dom.js index 5687a832..c55312dc 100644 --- a/test/dom.js +++ b/test/dom.js @@ -170,6 +170,22 @@ describe('dom', () => { route('/foo'); expect(routerRef.base.outerHTML).to.eql('

bar is

'); }); + + it('should support relative links', () => { + class A { + render() { + return go; + } + } + history.replaceState(null, null, '/foo/one'); + mount( + + + + ); + scratch.querySelector('a').click(); + expect(location.pathname).to.equal('/foo/two'); + }); }); describe('preact-router/match', () => {