feat: Virtual page redirect, breadcrumb & menu items
All checks were successful
Deploy WordPress and Nuxt / deploy (push) Successful in 1m5s

This commit is contained in:
2025-09-25 21:27:41 -04:00
parent 3f0d4dbb4e
commit e9c92840fc
12 changed files with 155 additions and 134 deletions

View File

@@ -71,7 +71,7 @@ Use GitHub-style checkboxes to mark task completion:
- [x] Configure GraphQL schema for ACF fields <!-- Completed: wpgraphql-acf plugin configured --> - [x] Configure GraphQL schema for ACF fields <!-- Completed: wpgraphql-acf plugin configured -->
- [x] Test GraphQL queries for all content types <!-- Completed: Basic .gql files created --> - [x] Test GraphQL queries for all content types <!-- Completed: Basic .gql files created -->
- [x] Set up GraphQL authentication and permissions <!-- Completed: JWT auth configured with includes/graphql/auth.php --> - [x] Set up GraphQL authentication and permissions <!-- Completed: JWT auth configured with includes/graphql/auth.php -->
- [ ] Customize MediaItem GraphQL type to include center (x/y) fields <!-- Priority: High - Image cropping and point-of-interest support --> - [x] Customize MediaItem GraphQL type to include center (x/y) fields <!-- Priority: High - Image cropping and point-of-interest support -->
--- ---
@@ -157,7 +157,7 @@ Use GitHub-style checkboxes to mark task completion:
### Content Features ### Content Features
- [x] Implement image uploads with point-of-interest cropping - [x] Implement image uploads with point-of-interest cropping
- [ ] Implement virtual pages (redirect to first child) - [x] Implement virtual pages (redirect to first child)
- [ ] Create automated URL redirect system - [ ] Create automated URL redirect system
- [ ] Build content search and filtering - [ ] Build content search and filtering
- [ ] Create content categorization system - [ ] Create content categorization system

View File

@@ -62,5 +62,5 @@
"graphql_types": "", "graphql_types": "",
"acfe_meta": "", "acfe_meta": "",
"acfe_note": "", "acfe_note": "",
"modified": 1757959232 "modified": 1758829149
} }

View File

@@ -1,5 +1,13 @@
fragment ThePage on Page { fragment ThePage on Page {
title title
template {
__typename
}
children {
nodes {
uri
}
}
groupPostPage { groupPostPage {
sections { sections {
...TheSection ...TheSection

View File

@@ -2,6 +2,11 @@
import type { ThePageFragment } from "#graphql-operations"; import type { ThePageFragment } from "#graphql-operations";
const props = defineProps<ThePageFragment>(); const props = defineProps<ThePageFragment>();
if (props.template?.__typename === "Template_VirtualPage") {
await navigateTo(props.children?.nodes[0]?.uri || "/");
}
useSeoMeta({ title: props.title }); useSeoMeta({ title: props.title });
</script> </script>

View File

@@ -1,7 +1,13 @@
export async function useSiteOptions() { export async function useSiteOptions() {
const { data } = await useAsyncGraphqlQuery("siteOptions", {}, { graphqlCaching: { client: true } }); const { data, error } = await useAsyncGraphqlQuery("siteOptions", {}, { graphqlCaching: { client: true } });
if (data.value?.errors?.length || !data.value?.data.siteOptions?.groupCcat) { if (error.value) {
throw createError({ statusCode: 500, message: "Erreur lors de la récupération des options du site" }); throw createError({ statusCode: 500, statusMessage: "Erreur interne", message: error.value.message });
}
if (data.value?.errors.length) {
throw createError({ statusCode: 500, statusMessage: "Erreur interne", message: data.value.errors.map((error) => error.message).join("\n") });
}
if (!data.value?.data.siteOptions?.groupCcat) {
throw createError({ statusCode: 500, statusMessage: "Erreur interne", message: "Options du site invalides." });
} }
return { ...data.value?.data.siteOptions?.groupCcat }; return { ...data.value?.data.siteOptions?.groupCcat };
} }

View File

@@ -5,6 +5,7 @@
// Core // Core
require_once __DIR__ . '/includes/core/sections.php'; require_once __DIR__ . '/includes/core/sections.php';
require_once __DIR__ . '/includes/core/theme-setup.php'; require_once __DIR__ . '/includes/core/theme-setup.php';
require_once __DIR__ . '/includes/core/virtual-page.php';
// Custom Post Types // Custom Post Types
require_once __DIR__ . '/includes/cpt/contributor.php'; require_once __DIR__ . '/includes/cpt/contributor.php';

View File

@@ -0,0 +1,18 @@
<?php
// Helper: Determine if page is a virtual page
function ccat_is_virtual_page( $page_id ) {
return get_post_meta( $page_id, '_wp_page_template', true ) === 'virtual.php';
}
// Replace menu item path with '#' for virtual pages
add_filter( 'graphql_resolve_field', 'ccat_virtual_page_menu_item_graphql_value', 10, 5 );
function ccat_virtual_page_menu_item_graphql_value( $result, $source, $args, $context, $info ) {
if ( $source instanceof \WPGraphQL\Model\MenuItem && $info->fieldName === 'path' ) {
$menu_item = wp_setup_nav_menu_item( get_post( $source->databaseId ) );
if ( $menu_item->object === 'page' && ccat_is_virtual_page( $menu_item->object_id ) ) {
return '#';
}
}
return $result;
}

View File

@@ -49,102 +49,77 @@ function ccat_register_breadcrumb_graphql_fields() {
// Helper: Get breadcrumbs for a given node // Helper: Get breadcrumbs for a given node
function ccat_get_breadcrumbs( $node ) { function ccat_get_breadcrumbs( $node ) {
$breadcrumbs = array();
if ( ! $node ) {
return $breadcrumbs;
}
if ( $node instanceof \WPGraphQL\Model\Post ) { if ( $node instanceof \WPGraphQL\Model\Post ) {
$post = get_post( $node->databaseId ); return ccat_get_post_breadcrumbs( $node->databaseId );
if ( $post ) {
$breadcrumbs = ccat_get_post_breadcrumbs( $post );
$breadcrumbs[] = array(
'label' => get_the_title( $post->ID ),
'to' => null,
);
} }
} elseif ( $node instanceof \WPGraphQL\Model\Term ) { if ( $node instanceof \WPGraphQL\Model\Term ) {
$term = get_term( $node->databaseId ); return ccat_get_term_breadcrumbs( $node->databaseId );
if ( $term && ! is_wp_error( $term ) ) {
$breadcrumbs = ccat_get_term_breadcrumbs( $term );
$breadcrumbs[] = array(
'label' => $term->name,
'to' => null,
);
} }
} return array();
return $breadcrumbs;
} }
// Helper: Get breadcrumbs for a given post // Helper: Get breadcrumbs for a given post ID
function ccat_get_post_breadcrumbs( WP_Post $post ) { function ccat_get_post_breadcrumbs( $post_id ) {
$breadcrumbs = array(); $breadcrumbs = array();
$is_front_page = get_option( 'show_on_front' ) === 'page' && (int) get_option( 'page_on_front' ) === $post->ID;
$is_front_page = get_option( 'show_on_front' ) === 'page' && (int) get_option( 'page_on_front' ) === $post_id;
if ( $is_front_page ) { if ( $is_front_page ) {
return $breadcrumbs; // No breadcrumbs for the front page return $breadcrumbs;
} else { }
$breadcrumbs[] = array( $breadcrumbs[] = array(
'label' => 'Accueil', 'label' => 'Accueil',
'to' => '/', 'to' => '/',
); );
}
$post_type = get_post_type( $post->ID );
switch ( $post_type ) {
case 'page':
$ancestors = get_post_ancestors( $post->ID );
if ( ! empty( $ancestors ) ) {
$ancestors = array_reverse( $ancestors );
foreach ( $ancestors as $ancestor_id ) {
$breadcrumbs[] = array(
'label' => get_the_title( $ancestor_id ),
'to' => str_replace( home_url(), '', get_permalink( $ancestor_id ) ),
);
}
}
break;
default: $post_type = get_post_type( $post_id );
if ( ! empty( $post_id = get_option( "page_for_$post_type" ) ) ) { $ancestor_ids = get_post_ancestors( $post_type === 'page' ? $post_id : get_option( "page_for_$post_type" ) );
// Get ancestors of the archive page $ancestor_ids = array_reverse( $ancestor_ids );
$ancestors = get_post_ancestors( $post_id ); foreach ( $ancestor_ids as $ancestor_id ) {
if ( ! empty( $ancestors ) ) {
$ancestors = array_reverse( $ancestors );
foreach ( $ancestors as $ancestor_id ) {
$breadcrumbs[] = array( $breadcrumbs[] = array(
'label' => get_the_title( $ancestor_id ), 'label' => get_the_title( $ancestor_id ),
'to' => str_replace( home_url(), '', get_permalink( $ancestor_id ) ), 'to' => ccat_is_virtual_page( $ancestor_id ) ? null : str_replace( home_url(), '', get_permalink( $ancestor_id ) ),
); );
} }
}
// Add the archive page itself
$breadcrumbs[] = array( $breadcrumbs[] = array(
'label' => get_the_title( $post_id ), 'label' => get_the_title( $post_id ),
'to' => str_replace( home_url(), '', get_permalink( $post_id ) ), 'to' => null,
); );
}
break;
}
return $breadcrumbs; return $breadcrumbs;
} }
// Helper: Get breadcrumbs for a given term // Helper: Get breadcrumbs for a given term ID
function ccat_get_term_breadcrumbs( WP_Term $term ) { function ccat_get_term_breadcrumbs( $term_id ) {
$breadcrumbs = array(); $breadcrumbs = array(
$taxonomy = $term->taxonomy; array(
if ( $term->parent ) { 'label' => 'Accueil',
$ancestors = get_ancestors( $term->term_id, $taxonomy ); 'to' => '/',
if ( ! empty( $ancestors ) ) { ),
$ancestors = array_reverse( $ancestors ); );
foreach ( $ancestors as $ancestor_id ) {
$ancestor_term = get_term( $ancestor_id, $taxonomy ); $term = get_term( $term_id );
if ( $ancestor_term && ! is_wp_error( $ancestor_term ) ) { if ( is_wp_error( $term ) || ! $term ) {
return $breadcrumbs;
}
$ancestor_ids = get_ancestors( $term->term_id, $term->taxonomy );
$ancestor_ids = array_reverse( $ancestor_ids );
foreach ( $ancestor_ids as $ancestor_id ) {
$ancestor_term = get_term( $ancestor_id, $term->taxonomy );
if ( is_wp_error( $ancestor_term ) || ! $ancestor_term ) {
continue;
}
$breadcrumbs[] = array( $breadcrumbs[] = array(
'label' => $ancestor_term->name, 'label' => $ancestor_term->name,
'to' => str_replace( home_url(), '', get_term_link( $ancestor_term ) ), 'to' => str_replace( home_url(), '', get_term_link( $ancestor_term ) ),
); );
} }
}
} $breadcrumbs[] = array(
} 'label' => $term->name,
'to' => null,
);
return $breadcrumbs; return $breadcrumbs;
} }

View File

@@ -39,7 +39,7 @@
"eslint": "^9.36.0", "eslint": "^9.36.0",
"typescript": "^5.9.2", "typescript": "^5.9.2",
"vue-tsc": "^3.0.8", "vue-tsc": "^3.0.8",
"wrangler": "^4.40.0" "wrangler": "^4.40.1"
}, },
"packageManager": "pnpm@10.15.0", "packageManager": "pnpm@10.15.0",
"pnpm": { "pnpm": {

View File

@@ -73,8 +73,8 @@ importers:
specifier: ^3.0.8 specifier: ^3.0.8
version: 3.0.8(typescript@5.9.2) version: 3.0.8(typescript@5.9.2)
wrangler: wrangler:
specifier: ^4.40.0 specifier: ^4.40.1
version: 4.40.0(@cloudflare/workers-types@4.20250924.0) version: 4.40.1(@cloudflare/workers-types@4.20250924.0)
packages: packages:
@@ -106,8 +106,8 @@ packages:
resolution: {integrity: sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==} resolution: {integrity: sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==}
engines: {node: '>=18'} engines: {node: '>=18'}
'@ai-sdk/vue@2.0.52': '@ai-sdk/vue@2.0.53':
resolution: {integrity: sha512-r2p+Z0DQNckgIyzUz7CzCJfGoOnwV8Z7HYYb0AuR3+maCqlpKQlovDDp3e171Z2WY+JBWof1UYSnOlcrWIrQig==} resolution: {integrity: sha512-IZ0a5oF82tjpfQbjWieTmuzNlovrH5xjunSaHdOcvNCVRSnJiiguHuf/NJXO2999OsfTRFRJO8KAbjogPltp7w==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
vue: ^3.3.4 vue: ^3.3.4
@@ -1009,8 +1009,8 @@ packages:
'@iconify-json/lucide@1.2.68': '@iconify-json/lucide@1.2.68':
resolution: {integrity: sha512-lR5xNJdn2CT0iR7lM25G4SewBO4G2hbr3fTWOc3AE9BspflEcneh02E3l9TBaCU/JOHozTJevWLrxBGypD7Tng==} resolution: {integrity: sha512-lR5xNJdn2CT0iR7lM25G4SewBO4G2hbr3fTWOc3AE9BspflEcneh02E3l9TBaCU/JOHozTJevWLrxBGypD7Tng==}
'@iconify/collections@1.0.597': '@iconify/collections@1.0.598':
resolution: {integrity: sha512-itoqOLcEmgoj+4I92R+PUAnSyhDWN7Ez1QjQvp08ww5EMVeAM5x3Zt3Snf1MS7R5SMM9rl3h7kPRY6+m6g4BwQ==} resolution: {integrity: sha512-Mm3gHh0gwgi2T6sYygmCF9A+QirG8E+yCFqLd2zjXNmacbQ4ng0bHTP9QRZqNh96ao4YxxyKAcZyedjW35Wevw==}
'@iconify/types@2.0.0': '@iconify/types@2.0.0':
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
@@ -2544,8 +2544,8 @@ packages:
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
engines: {node: '>=8'} engines: {node: '>=8'}
ai@5.0.52: ai@5.0.53:
resolution: {integrity: sha512-GLlRHjMlvN9+w7UYGxCpUQ8GgCRv5Z+JCprRH3Q8YbXJ/JyIc6EP9+YRUmQsyExX/qQsuehe7y/LLygarbSTOw==} resolution: {integrity: sha512-TIRelwDRczBS6vGLbJlskC1jLRKUT7DAYz+1DiHjJrgx1MnE2a5xQWv06koLHT+r0GImpkmqP77/n+Vbvea3aw==}
engines: {node: '>=18'} engines: {node: '>=18'}
peerDependencies: peerDependencies:
zod: ^3.25.76 || ^4 zod: ^3.25.76 || ^4
@@ -3267,8 +3267,8 @@ packages:
ee-first@1.1.1: ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
electron-to-chromium@1.5.223: electron-to-chromium@1.5.224:
resolution: {integrity: sha512-qKm55ic6nbEmagFlTFczML33rF90aU+WtrJ9MdTCThrcvDNdUHN4p6QfVN78U06ZmguqXIyMPyYhw2TrbDUwPQ==} resolution: {integrity: sha512-kWAoUu/bwzvnhpdZSIc6KUyvkI1rbRXMT0Eq8pKReyOyaPZcctMli+EgvcN1PAvwVc7Tdo4Fxi2PsLNDU05mdg==}
embla-carousel-auto-height@8.6.0: embla-carousel-auto-height@8.6.0:
resolution: {integrity: sha512-/HrJQOEM6aol/oF33gd2QlINcXy3e19fJWvHDuHWp2bpyTa+2dm9tVVJak30m2Qy6QyQ6Fc8DkImtv7pxWOJUQ==} resolution: {integrity: sha512-/HrJQOEM6aol/oF33gd2QlINcXy3e19fJWvHDuHWp2bpyTa+2dm9tVVJak30m2Qy6QyQ6Fc8DkImtv7pxWOJUQ==}
@@ -6157,8 +6157,8 @@ packages:
engines: {node: '>=16'} engines: {node: '>=16'}
hasBin: true hasBin: true
wrangler@4.40.0: wrangler@4.40.1:
resolution: {integrity: sha512-HCPNUz599h9emi6qjppn92kxS6E12QvD0A3K087CZFEysw6lO1saZUdJ8azk0LsYGYDnrkBs5TzUOEfpuccwWA==} resolution: {integrity: sha512-XQEHOW6g1zW2xnBq1dmhDbEiVBbPGh7mX1tQAUMqKETa61XXvxHCJSzVI3is5xuo9HzZ8ITzg4VnhB/91cg9DQ==}
engines: {node: '>=18.0.0'} engines: {node: '>=18.0.0'}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
@@ -6304,10 +6304,10 @@ snapshots:
dependencies: dependencies:
json-schema: 0.4.0 json-schema: 0.4.0
'@ai-sdk/vue@2.0.52(vue@3.5.22(typescript@5.9.2))(zod@4.1.11)': '@ai-sdk/vue@2.0.53(vue@3.5.22(typescript@5.9.2))(zod@4.1.11)':
dependencies: dependencies:
'@ai-sdk/provider-utils': 3.0.9(zod@4.1.11) '@ai-sdk/provider-utils': 3.0.9(zod@4.1.11)
ai: 5.0.52(zod@4.1.11) ai: 5.0.53(zod@4.1.11)
swrv: 1.1.0(vue@3.5.22(typescript@5.9.2)) swrv: 1.1.0(vue@3.5.22(typescript@5.9.2))
optionalDependencies: optionalDependencies:
vue: 3.5.22(typescript@5.9.2) vue: 3.5.22(typescript@5.9.2)
@@ -7354,7 +7354,7 @@ snapshots:
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
'@iconify/collections@1.0.597': '@iconify/collections@1.0.598':
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
@@ -7815,7 +7815,7 @@ snapshots:
'@nuxt/icon@2.0.0(magicast@0.3.5)(vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.2))': '@nuxt/icon@2.0.0(magicast@0.3.5)(vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.2))':
dependencies: dependencies:
'@iconify/collections': 1.0.597 '@iconify/collections': 1.0.598
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
'@iconify/utils': 3.0.2 '@iconify/utils': 3.0.2
'@iconify/vue': 5.0.0(vue@3.5.22(typescript@5.9.2)) '@iconify/vue': 5.0.0(vue@3.5.22(typescript@5.9.2))
@@ -7957,7 +7957,7 @@ snapshots:
'@nuxt/ui@4.0.0(@babel/parser@7.28.4)(@netlify/blobs@9.1.2)(change-case@5.4.4)(db0@0.3.2)(embla-carousel@8.6.0)(ioredis@5.8.0)(jwt-decode@4.0.0)(magicast@0.3.5)(typescript@5.9.2)(vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)(yaml@2.8.1))(vue-router@4.5.1(vue@3.5.22(typescript@5.9.2)))(vue@3.5.22(typescript@5.9.2))(zod@4.1.11)': '@nuxt/ui@4.0.0(@babel/parser@7.28.4)(@netlify/blobs@9.1.2)(change-case@5.4.4)(db0@0.3.2)(embla-carousel@8.6.0)(ioredis@5.8.0)(jwt-decode@4.0.0)(magicast@0.3.5)(typescript@5.9.2)(vite@7.1.7(@types/node@24.5.2)(jiti@2.6.0)(lightningcss@1.30.1)(terser@5.44.0)(yaml@2.8.1))(vue-router@4.5.1(vue@3.5.22(typescript@5.9.2)))(vue@3.5.22(typescript@5.9.2))(zod@4.1.11)':
dependencies: dependencies:
'@ai-sdk/vue': 2.0.52(vue@3.5.22(typescript@5.9.2))(zod@4.1.11) '@ai-sdk/vue': 2.0.53(vue@3.5.22(typescript@5.9.2))(zod@4.1.11)
'@iconify/vue': 5.0.0(vue@3.5.22(typescript@5.9.2)) '@iconify/vue': 5.0.0(vue@3.5.22(typescript@5.9.2))
'@internationalized/date': 3.9.0 '@internationalized/date': 3.9.0
'@internationalized/number': 3.6.5 '@internationalized/number': 3.6.5
@@ -9223,7 +9223,7 @@ snapshots:
clean-stack: 2.2.0 clean-stack: 2.2.0
indent-string: 4.0.0 indent-string: 4.0.0
ai@5.0.52(zod@4.1.11): ai@5.0.53(zod@4.1.11):
dependencies: dependencies:
'@ai-sdk/gateway': 1.0.29(zod@4.1.11) '@ai-sdk/gateway': 1.0.29(zod@4.1.11)
'@ai-sdk/provider': 2.0.0 '@ai-sdk/provider': 2.0.0
@@ -9407,7 +9407,7 @@ snapshots:
dependencies: dependencies:
baseline-browser-mapping: 2.8.7 baseline-browser-mapping: 2.8.7
caniuse-lite: 1.0.30001745 caniuse-lite: 1.0.30001745
electron-to-chromium: 1.5.223 electron-to-chromium: 1.5.224
node-releases: 2.0.21 node-releases: 2.0.21
update-browserslist-db: 1.1.3(browserslist@4.26.2) update-browserslist-db: 1.1.3(browserslist@4.26.2)
@@ -9481,7 +9481,7 @@ snapshots:
camel-case@4.1.2: camel-case@4.1.2:
dependencies: dependencies:
pascal-case: 3.1.2 pascal-case: 3.1.2
tslib: 2.6.3 tslib: 2.8.1
caniuse-api@3.0.0: caniuse-api@3.0.0:
dependencies: dependencies:
@@ -9495,7 +9495,7 @@ snapshots:
capital-case@1.0.4: capital-case@1.0.4:
dependencies: dependencies:
no-case: 3.0.4 no-case: 3.0.4
tslib: 2.6.3 tslib: 2.8.1
upper-case-first: 2.0.2 upper-case-first: 2.0.2
case-anything@3.1.2: {} case-anything@3.1.2: {}
@@ -9533,7 +9533,7 @@ snapshots:
path-case: 3.0.4 path-case: 3.0.4
sentence-case: 3.0.4 sentence-case: 3.0.4
snake-case: 3.0.4 snake-case: 3.0.4
tslib: 2.6.3 tslib: 2.8.1
change-case@5.4.4: {} change-case@5.4.4: {}
@@ -9658,7 +9658,7 @@ snapshots:
constant-case@3.0.4: constant-case@3.0.4:
dependencies: dependencies:
no-case: 3.0.4 no-case: 3.0.4
tslib: 2.6.3 tslib: 2.8.1
upper-case: 2.0.2 upper-case: 2.0.2
convert-source-map@2.0.0: {} convert-source-map@2.0.0: {}
@@ -9903,7 +9903,7 @@ snapshots:
dot-case@3.0.4: dot-case@3.0.4:
dependencies: dependencies:
no-case: 3.0.4 no-case: 3.0.4
tslib: 2.6.3 tslib: 2.8.1
dot-prop@9.0.0: dot-prop@9.0.0:
dependencies: dependencies:
@@ -9928,7 +9928,7 @@ snapshots:
ee-first@1.1.1: {} ee-first@1.1.1: {}
electron-to-chromium@1.5.223: {} electron-to-chromium@1.5.224: {}
embla-carousel-auto-height@8.6.0(embla-carousel@8.6.0): embla-carousel-auto-height@8.6.0(embla-carousel@8.6.0):
dependencies: dependencies:
@@ -10648,7 +10648,7 @@ snapshots:
header-case@2.0.4: header-case@2.0.4:
dependencies: dependencies:
capital-case: 1.0.4 capital-case: 1.0.4
tslib: 2.6.3 tslib: 2.8.1
hey-listen@1.0.8: {} hey-listen@1.0.8: {}
@@ -10852,7 +10852,7 @@ snapshots:
is-lower-case@2.0.2: is-lower-case@2.0.2:
dependencies: dependencies:
tslib: 2.6.3 tslib: 2.8.1
is-module@1.0.0: {} is-module@1.0.0: {}
@@ -10884,7 +10884,7 @@ snapshots:
is-upper-case@2.0.2: is-upper-case@2.0.2:
dependencies: dependencies:
tslib: 2.6.3 tslib: 2.8.1
is-what@4.1.16: {} is-what@4.1.16: {}
@@ -11130,11 +11130,11 @@ snapshots:
lower-case-first@2.0.2: lower-case-first@2.0.2:
dependencies: dependencies:
tslib: 2.6.3 tslib: 2.8.1
lower-case@2.0.2: lower-case@2.0.2:
dependencies: dependencies:
tslib: 2.6.3 tslib: 2.8.1
lru-cache@10.4.3: {} lru-cache@10.4.3: {}
@@ -11430,7 +11430,7 @@ snapshots:
no-case@3.0.4: no-case@3.0.4:
dependencies: dependencies:
lower-case: 2.0.2 lower-case: 2.0.2
tslib: 2.6.3 tslib: 2.8.1
node-abi@3.77.0: node-abi@3.77.0:
dependencies: dependencies:
@@ -11876,7 +11876,7 @@ snapshots:
param-case@3.0.4: param-case@3.0.4:
dependencies: dependencies:
dot-case: 3.0.4 dot-case: 3.0.4
tslib: 2.6.3 tslib: 2.8.1
parent-module@1.0.1: parent-module@1.0.1:
dependencies: dependencies:
@@ -11918,14 +11918,14 @@ snapshots:
pascal-case@3.1.2: pascal-case@3.1.2:
dependencies: dependencies:
no-case: 3.0.4 no-case: 3.0.4
tslib: 2.6.3 tslib: 2.8.1
path-browserify@1.0.1: {} path-browserify@1.0.1: {}
path-case@3.0.4: path-case@3.0.4:
dependencies: dependencies:
dot-case: 3.0.4 dot-case: 3.0.4
tslib: 2.6.3 tslib: 2.8.1
path-exists@4.0.0: {} path-exists@4.0.0: {}
@@ -12427,7 +12427,7 @@ snapshots:
sentence-case@3.0.4: sentence-case@3.0.4:
dependencies: dependencies:
no-case: 3.0.4 no-case: 3.0.4
tslib: 2.6.3 tslib: 2.8.1
upper-case-first: 2.0.2 upper-case-first: 2.0.2
serialize-javascript@6.0.2: serialize-javascript@6.0.2:
@@ -12596,7 +12596,7 @@ snapshots:
snake-case@3.0.4: snake-case@3.0.4:
dependencies: dependencies:
dot-case: 3.0.4 dot-case: 3.0.4
tslib: 2.6.3 tslib: 2.8.1
source-map-js@1.2.1: {} source-map-js@1.2.1: {}
@@ -12622,7 +12622,7 @@ snapshots:
sponge-case@1.0.1: sponge-case@1.0.1:
dependencies: dependencies:
tslib: 2.6.3 tslib: 2.8.1
stable-hash-x@0.2.0: {} stable-hash-x@0.2.0: {}
@@ -12741,7 +12741,7 @@ snapshots:
swap-case@2.0.2: swap-case@2.0.2:
dependencies: dependencies:
tslib: 2.6.3 tslib: 2.8.1
swrv@1.1.0(vue@3.5.22(typescript@5.9.2)): swrv@1.1.0(vue@3.5.22(typescript@5.9.2)):
dependencies: dependencies:
@@ -12842,7 +12842,7 @@ snapshots:
title-case@3.0.3: title-case@3.0.3:
dependencies: dependencies:
tslib: 2.6.3 tslib: 2.8.1
to-regex-range@5.0.1: to-regex-range@5.0.1:
dependencies: dependencies:
@@ -13097,11 +13097,11 @@ snapshots:
upper-case-first@2.0.2: upper-case-first@2.0.2:
dependencies: dependencies:
tslib: 2.6.3 tslib: 2.8.1
upper-case@2.0.2: upper-case@2.0.2:
dependencies: dependencies:
tslib: 2.6.3 tslib: 2.8.1
uqr@0.1.2: {} uqr@0.1.2: {}
@@ -13300,7 +13300,7 @@ snapshots:
'@cloudflare/workerd-linux-arm64': 1.20250924.0 '@cloudflare/workerd-linux-arm64': 1.20250924.0
'@cloudflare/workerd-windows-64': 1.20250924.0 '@cloudflare/workerd-windows-64': 1.20250924.0
wrangler@4.40.0(@cloudflare/workers-types@4.20250924.0): wrangler@4.40.1(@cloudflare/workers-types@4.20250924.0):
dependencies: dependencies:
'@cloudflare/kv-asset-handler': 0.4.0 '@cloudflare/kv-asset-handler': 0.4.0
'@cloudflare/unenv-preset': 2.7.4(unenv@2.0.0-rc.21)(workerd@1.20250924.0) '@cloudflare/unenv-preset': 2.7.4(unenv@2.0.0-rc.21)(workerd@1.20250924.0)

View File

@@ -24891,6 +24891,12 @@ type TemplateToTemplateConnectionPageInfo implements PageInfo & TemplateConnecti
startCursor: String startCursor: String
} }
"""The template assigned to the node"""
type Template_VirtualPage implements ContentTemplate {
"""The name of the template"""
templateName: String
}
""" """
Base interface for taxonomy terms such as categories and tags. Terms are used to organize and classify content. Base interface for taxonomy terms such as categories and tags. Terms are used to organize and classify content.
""" """

View File

@@ -0,0 +1,2 @@
<?php
/** Template Name: Virtual Page */