|
|
@ -71,10 +71,43 @@ export function createRouter(
|
|
|
|
go
|
|
|
|
go
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function go(href: string = inBrowser ? location.href : '/') {
|
|
|
|
async function go(
|
|
|
|
|
|
|
|
href: string = inBrowser ? location.href : '/',
|
|
|
|
|
|
|
|
cause: Element | null = null
|
|
|
|
|
|
|
|
) {
|
|
|
|
href = normalizeHref(href)
|
|
|
|
href = normalizeHref(href)
|
|
|
|
|
|
|
|
let loc: string | null = null
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (inBrowser) {
|
|
|
|
|
|
|
|
loc = normalizeHref(location.href)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const { pathname, search, hash } = new URL(href, fakeHost)
|
|
|
|
|
|
|
|
const currentLoc = new URL(loc, fakeHost)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
|
|
pathname === currentLoc.pathname &&
|
|
|
|
|
|
|
|
search === currentLoc.search &&
|
|
|
|
|
|
|
|
hash !== currentLoc.hash
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
history.pushState({}, '', href)
|
|
|
|
|
|
|
|
window.dispatchEvent(
|
|
|
|
|
|
|
|
new HashChangeEvent('hashchange', {
|
|
|
|
|
|
|
|
oldURL: currentLoc.href,
|
|
|
|
|
|
|
|
newURL: href
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
if (hash) {
|
|
|
|
|
|
|
|
scrollTo(cause, hash, cause?.classList.contains('header-anchor'))
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
window.scrollTo(0, 0)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ((await router.onBeforeRouteChange?.(href)) === false) return
|
|
|
|
if ((await router.onBeforeRouteChange?.(href)) === false) return
|
|
|
|
if (inBrowser && href !== normalizeHref(location.href)) {
|
|
|
|
if (loc !== null && href !== loc) {
|
|
|
|
// save scroll position before changing url
|
|
|
|
// save scroll position before changing url
|
|
|
|
history.replaceState({ scrollPosition: window.scrollY }, '')
|
|
|
|
history.replaceState({ scrollPosition: window.scrollY }, '')
|
|
|
|
history.pushState({}, '', href)
|
|
|
|
history.pushState({}, '', href)
|
|
|
@ -125,20 +158,10 @@ export function createRouter(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (targetLoc.hash && !scrollPosition) {
|
|
|
|
if (targetLoc.hash && !scrollPosition) {
|
|
|
|
let target: HTMLElement | null = null
|
|
|
|
scrollTo(null, targetLoc.hash)
|
|
|
|
try {
|
|
|
|
} else {
|
|
|
|
target = document.getElementById(
|
|
|
|
window.scrollTo(0, scrollPosition)
|
|
|
|
decodeURIComponent(targetLoc.hash).slice(1)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
|
|
console.warn(e)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target) {
|
|
|
|
|
|
|
|
scrollTo(target, targetLoc.hash)
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
window.scrollTo(0, scrollPosition)
|
|
|
|
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -210,39 +233,12 @@ export function createRouter(
|
|
|
|
(link instanceof SVGAElement ? link.getAttribute('xlink:href') : null)
|
|
|
|
(link instanceof SVGAElement ? link.getAttribute('xlink:href') : null)
|
|
|
|
if (linkHref == null) return
|
|
|
|
if (linkHref == null) return
|
|
|
|
|
|
|
|
|
|
|
|
const { href, origin, pathname, hash, search } = new URL(
|
|
|
|
const { href, origin, pathname } = new URL(linkHref, link.baseURI)
|
|
|
|
linkHref,
|
|
|
|
const currentLoc = new URL(location.href) // copy to keep old data
|
|
|
|
link.baseURI
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
const currentUrl = new URL(location.href) // copy to keep old data
|
|
|
|
|
|
|
|
// only intercept inbound html links
|
|
|
|
// only intercept inbound html links
|
|
|
|
if (origin === currentUrl.origin && treatAsHtml(pathname)) {
|
|
|
|
if (origin === currentLoc.origin && treatAsHtml(pathname)) {
|
|
|
|
e.preventDefault()
|
|
|
|
e.preventDefault()
|
|
|
|
if (
|
|
|
|
go(href, link)
|
|
|
|
pathname === currentUrl.pathname &&
|
|
|
|
|
|
|
|
search === currentUrl.search
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
// scroll between hash anchors in the same page
|
|
|
|
|
|
|
|
// avoid duplicate history entries when the hash is same
|
|
|
|
|
|
|
|
if (hash !== currentUrl.hash) {
|
|
|
|
|
|
|
|
history.pushState({}, '', href)
|
|
|
|
|
|
|
|
// still emit the event so we can listen to it in themes
|
|
|
|
|
|
|
|
window.dispatchEvent(
|
|
|
|
|
|
|
|
new HashChangeEvent('hashchange', {
|
|
|
|
|
|
|
|
oldURL: currentUrl.href,
|
|
|
|
|
|
|
|
newURL: href
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hash) {
|
|
|
|
|
|
|
|
// use smooth scroll when clicking on header anchor links
|
|
|
|
|
|
|
|
scrollTo(link, hash, link.classList.contains('header-anchor'))
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
window.scrollTo(0, 0)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
go(href)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{ capture: true }
|
|
|
|
{ capture: true }
|
|
|
@ -277,12 +273,12 @@ export function useRoute(): Route {
|
|
|
|
return useRouter().route
|
|
|
|
return useRouter().route
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function scrollTo(el: Element, hash: string, smooth = false) {
|
|
|
|
export function scrollTo(from: Element | null, hash: string, smooth = false) {
|
|
|
|
let target: Element | null = null
|
|
|
|
let target: Element | null = null
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
target = el.classList.contains('header-anchor')
|
|
|
|
target = from?.classList.contains('header-anchor')
|
|
|
|
? el
|
|
|
|
? from
|
|
|
|
: document.getElementById(decodeURIComponent(hash).slice(1))
|
|
|
|
: document.getElementById(decodeURIComponent(hash).slice(1))
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
console.warn(e)
|
|
|
|
console.warn(e)
|
|
|
|