71 lines
1.8 KiB
TypeScript
71 lines
1.8 KiB
TypeScript
export function useProseLinks(refContent: Ref<HTMLElement | null>) {
|
|
const router = useRouter();
|
|
const { url } = useSiteConfig();
|
|
const siteUrl = new URL(url);
|
|
|
|
// Determine if the href is internal
|
|
const isInternal = (href: string) => {
|
|
if (!href) return false;
|
|
if (href.startsWith("/")) return true;
|
|
if (href.startsWith("#")) return false;
|
|
try {
|
|
const hrefUrl = new URL(href);
|
|
return hrefUrl.hostname === siteUrl.hostname;
|
|
} catch {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// Convert href to relative path
|
|
const convertToRelative = (href: string) => {
|
|
if (href.startsWith("/")) return href;
|
|
try {
|
|
const hrefUrl = new URL(href);
|
|
if (hrefUrl.hostname === siteUrl.hostname) {
|
|
return hrefUrl.pathname + hrefUrl.search + hrefUrl.hash;
|
|
}
|
|
} catch {
|
|
// Invalid URL
|
|
}
|
|
return href;
|
|
};
|
|
|
|
// Highjack click events to use router for internal links
|
|
const handleClick = (e: MouseEvent) => {
|
|
const target = e.target as HTMLElement;
|
|
const link = target.closest("a");
|
|
if (!link) return;
|
|
const href = link.getAttribute("href");
|
|
if (!href) return;
|
|
if (
|
|
e.metaKey ||
|
|
e.ctrlKey ||
|
|
e.shiftKey ||
|
|
e.altKey ||
|
|
link.target === "_blank" ||
|
|
link.hasAttribute("download")
|
|
) {
|
|
return;
|
|
}
|
|
if (isInternal(href)) {
|
|
e.preventDefault();
|
|
const path = convertToRelative(href);
|
|
router.push(path);
|
|
}
|
|
};
|
|
|
|
// Attach and detach event listeners
|
|
onMounted(() => {
|
|
const element = unref(refContent);
|
|
if (element) {
|
|
element.addEventListener("click", handleClick);
|
|
}
|
|
});
|
|
onBeforeUnmount(() => {
|
|
const element = unref(refContent);
|
|
if (element) {
|
|
element.removeEventListener("click", handleClick);
|
|
}
|
|
});
|
|
}
|