45 lines
1.5 KiB
JavaScript
45 lines
1.5 KiB
JavaScript
// Ported from nanohref 3.1.0 (MIT) — https://github.com/choojs/nanohref
|
|||
|
|
// Intercept same-origin anchor clicks for client-side navigation.
|
||
|
|
|
||
|
|
import { equal, notEqual } from './assert.js'
|
||
|
|
|
||
|
|
const safeExternalLink = /(noopener|noreferrer) (noopener|noreferrer)/
|
||
|
|
const protocolLink = /^[\w-_]+:/
|
||
|
|
|
||
|
|
export default function href (cb, root) {
|
||
|
|
notEqual(typeof window, 'undefined', 'nanohref: expected window to exist')
|
||
|
|
|
||
|
|
root = root || window.document
|
||
|
|
|
||
|
|
equal(typeof cb, 'function', 'nanohref: cb should be type function')
|
||
|
|
equal(typeof root, 'object', 'nanohref: root should be type object')
|
||
|
|
|
||
|
|
window.addEventListener('click', function (e) {
|
||
|
|
if ((e.button && e.button !== 0) ||
|
||
|
|
e.ctrlKey || e.metaKey || e.altKey || e.shiftKey ||
|
||
|
|
e.defaultPrevented) return
|
||
|
|
|
||
|
|
const anchor = (function traverse (node) {
|
||
|
|
if (!node || node === root) return
|
||
|
|
if (node.localName !== 'a' || node.href === undefined) {
|
||
|
|
return traverse(node.parentNode)
|
||
|
|
}
|
||
|
|
return node
|
||
|
|
})(e.target)
|
||
|
|
|
||
|
|
if (!anchor) return
|
||
|
|
|
||
|
|
if (window.location.protocol !== anchor.protocol ||
|
||
|
|
window.location.hostname !== anchor.hostname ||
|
||
|
|
window.location.port !== anchor.port ||
|
||
|
|
anchor.hasAttribute('data-nanohref-ignore') ||
|
||
|
|
anchor.hasAttribute('download') ||
|
||
|
|
(anchor.getAttribute('target') === '_blank' &&
|
||
|
|
safeExternalLink.test(anchor.getAttribute('rel'))) ||
|
||
|
|
protocolLink.test(anchor.getAttribute('href'))) return
|
||
|
|
|
||
|
|
e.preventDefault()
|
||
|
|
cb(anchor)
|
||
|
|
})
|
||
|
|
}
|