feat: Initial SEO integration
This commit is contained in:
20
wp-content/themes/moonshine/app/composables/useNodeSeo.ts
Normal file
20
wp-content/themes/moonshine/app/composables/useNodeSeo.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { NodeByUriQueryResult, NodeSeoFragment } from "#graphql/operations";
|
||||
|
||||
export function useNodeSeo(node: NodeByUriQueryResult["nodeByUri"]) {
|
||||
// Check if node has SEO data
|
||||
if (!node || !("seo" in node) || !node.seo) {
|
||||
return;
|
||||
}
|
||||
const { seo } = node as NodeSeoFragment;
|
||||
|
||||
useSeoMeta({
|
||||
title: seo?.title || undefined,
|
||||
description: seo?.description || undefined,
|
||||
robots: (seo?.robots || []).join(", "),
|
||||
ogTitle: seo?.openGraph?.title || undefined,
|
||||
ogDescription: seo?.openGraph?.description || undefined,
|
||||
ogImage: seo?.openGraph?.image?.url || undefined,
|
||||
ogUrl: seo?.canonicalUrl || undefined,
|
||||
twitterCard: "summary_large_image",
|
||||
});
|
||||
}
|
||||
@@ -1,8 +1,27 @@
|
||||
fragment NodeSeo on NodeWithRankMathSeo {
|
||||
seo {
|
||||
title
|
||||
description
|
||||
robots
|
||||
canonicalUrl
|
||||
openGraph {
|
||||
title
|
||||
description
|
||||
image {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query NodeByUri($uri: String!) {
|
||||
nodeByUri(uri: $uri) {
|
||||
__typename
|
||||
... on Page {
|
||||
... NodePage
|
||||
}
|
||||
... on NodeWithRankMathSeo {
|
||||
... NodeSeo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
// Resolve Node component from URI
|
||||
const { path: uri } = useRoute();
|
||||
const { data } = await useAsyncGraphQLQuery("NodeByUri", { uri });
|
||||
|
||||
// Resolve and validate Node component
|
||||
if (!data.value.nodeByUri) {
|
||||
throw createError({ statusCode: 404, message: `La page demandée est introuvable: ${uri}`, fatal: true });
|
||||
}
|
||||
@@ -10,10 +9,13 @@ const componentName = `Node${data.value.nodeByUri.__typename}`;
|
||||
if (!useNuxtApp().vueApp.component(componentName)) {
|
||||
throw createError({ statusCode: 404, message: `La page demandée ne peut pas être affichée correctement: ${componentName}`, fatal: true });
|
||||
}
|
||||
|
||||
useNodeSeo(data.value.nodeByUri);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="data.nodeByUri" id="page-node-from-uri">
|
||||
<Component :is="componentName" v-bind="data.nodeByUri" />
|
||||
<pre>{{ data.nodeByUri }}</pre>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -20,13 +20,14 @@ function moonshine_after_setup_theme() {
|
||||
// Bypass headless home URL for specific cases
|
||||
add_filter( 'home_url', 'moonshine_bypass_home_url', 10, 4 );
|
||||
function moonshine_bypass_home_url( $url, $path, $orig_scheme, $blog_id ) {
|
||||
$excluded_patterns = array(
|
||||
'#/wp-json(/|$)#i',
|
||||
);
|
||||
foreach ( $excluded_patterns as $pattern ) {
|
||||
if ( preg_match( $pattern, $url ) ) {
|
||||
return get_site_url( $blog_id, $path, $orig_scheme );
|
||||
}
|
||||
$excluded_patterns = array(
|
||||
'#/wp-json(/|$)#i', // WP REST API
|
||||
'#\.(xsl|xml)$#i', // Sitemap and XSLT files
|
||||
);
|
||||
foreach ( $excluded_patterns as $pattern ) {
|
||||
if ( preg_match( $pattern, $url ) ) {
|
||||
return get_site_url( $blog_id, $path, $orig_scheme );
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
@@ -56,8 +56,6 @@ export default defineNuxtConfig({
|
||||
},
|
||||
},
|
||||
|
||||
sitemap: {
|
||||
zeroRuntime: true,
|
||||
},
|
||||
sitemap: false,
|
||||
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user