You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vitepress/lib/app/composables/router.js

76 lines
1.7 KiB

import { reactive, provide } from 'vue'
/**
* @type {import('vue').InjectionKey<{ path: string, scrollPosition: number }>}
*/
export const RouteSymbol = Symbol()
export function useRouter() {
const loc = location
const route = reactive({
path: loc.pathname,
scrollPosition: window.scrollY
})
window.addEventListener(
'click',
/**
* @param {*} e
*/
(e) => {
if (e.target.tagName === 'A') {
const { href, target } = e.target
const url = new URL(href)
if (
target !== `_blank` &&
url.protocol === loc.protocol &&
url.hostname === loc.hostname
) {
if (url.pathname === loc.pathname) {
// smooth scroll bewteen hash anchors in the same page
if (url.hash !== loc.hash) {
e.preventDefault()
window.scrollTo({
left: 0,
top: e.target.offsetTop,
behavior: 'smooth'
})
}
} else {
e.preventDefault()
// save scroll position before changing url
saveScrollPosition()
history.pushState(null, '', href)
route.path = loc.pathname
route.scrollPosition = 0
}
}
}
},
{ capture: true }
)
window.addEventListener(
'popstate',
/**
* @param {*} e
*/
(e) => {
route.path = location.pathname
route.scrollPosition = (e.state && e.state.scrollPosition) || 0
}
)
provide(RouteSymbol, route)
}
function saveScrollPosition() {
history.replaceState(
{
scrollPosition: window.scrollY
},
document.title,
''
)
}