feat: UiProse prose component with link highjacking
This commit is contained in:
65
wp-content/themes/moonshine/app/composables/useProseLinks.ts
Normal file
65
wp-content/themes/moonshine/app/composables/useProseLinks.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user