feat: AcfProse
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
fragment AcfProse on GroupAbstractProse_Fields {
|
||||
content
|
||||
}
|
||||
12
wp-content/themes/headless/app/components/acf/AcfProse.vue
Normal file
12
wp-content/themes/headless/app/components/acf/AcfProse.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import type { AcfProseFragment } from "#graphql/types";
|
||||
|
||||
defineProps<{ prose: AcfProseFragment }>();
|
||||
|
||||
const refContent = useTemplateRef("refContent");
|
||||
useProseLinks(refContent);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="refContent" class="prose" v-html="prose.content" />
|
||||
</template>
|
||||
@@ -1,5 +1,7 @@
|
||||
fragment SectionProse on GroupAbstractBuilderSectionsProseLayout {
|
||||
content
|
||||
prose @nonNull {
|
||||
...AcfProse
|
||||
}
|
||||
layout: layoutSettings @nonNull {
|
||||
...AcfLayout
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ defineProps<{ section: SectionProseFragment }>();
|
||||
|
||||
<template>
|
||||
<AcfLayout :layout="section.layout">
|
||||
<div class="prose" v-html="section.content"></div>
|
||||
<AcfProse :prose="section.prose" />
|
||||
</AcfLayout>
|
||||
</template>
|
||||
|
||||
70
wp-content/themes/headless/app/composables/useProseLinks.ts
Normal file
70
wp-content/themes/headless/app/composables/useProseLinks.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
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 = (event: MouseEvent) => {
|
||||
const target = event.target as HTMLElement;
|
||||
const link = target.closest("a");
|
||||
if (!link) return;
|
||||
const href = link.getAttribute("href");
|
||||
if (!href) return;
|
||||
if (
|
||||
event.metaKey ||
|
||||
event.ctrlKey ||
|
||||
event.shiftKey ||
|
||||
event.altKey ||
|
||||
link.target === "_blank" ||
|
||||
link.hasAttribute("download")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (isInternal(href)) {
|
||||
event.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