This commit is contained in:
HugoRCD
2025-05-06 14:09:34 +02:00
parent 9589a7ffcf
commit 64d574ba6e
5 changed files with 251 additions and 56 deletions

View File

@@ -1,36 +1,22 @@
<script setup lang="ts">
import type { ContentNavigationItem } from '@nuxt/content'
import { findPageBreadcrumb, mapContentNavigation } from '#ui-pro/utils/content'
import { kebabCase } from 'scule'
const route = useRoute()
const { data: page } = await useAsyncData(route.path, () =>
queryCollection('blog').path(route.path).first()
)
if (!page.value) throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
const { data: surround } = await useAsyncData(`${route.path}-surround`, () =>
queryCollectionItemSurroundings('blog', route.path, {
fields: ['description']
})
)
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation', ref([]))
const blogNavigation = computed(() => navigation.value.find(item => item.path === '/blog')?.children || [])
const breadcrumb = computed(() => mapContentNavigation(findPageBreadcrumb(blogNavigation?.value, page.value)).map(({ icon, ...link }) => link))
if (page.value.image) {
defineOgImage({ url: page.value.image })
} else {
defineOgImageComponent('Blog', {
headline: breadcrumb.value.map(item => item.label).join(' > ')
}, {
fonts: ['Geist:400', 'Geist:600']
const [{ data: page }, { data: surround }] = await Promise.all([
useAsyncData(kebabCase(route.path), () => queryCollection('blog').path(route.path).first()),
useAsyncData(`${kebabCase(route.path)}-surround`, () => {
return queryCollectionItemSurroundings('blog', route.path, {
fields: ['description']
}).order('date', 'DESC')
})
])
if (!page.value) {
throw createError({ statusCode: 404, statusMessage: 'Article not found', fatal: true })
}
const title = page.value?.seo?.title || page.value?.title
const description = page.value?.seo?.description || page.value?.description
const title = page.value.seo?.title || page.value.title
const description = page.value.seo?.description || page.value.description
useSeoMeta({
title,
@@ -39,9 +25,17 @@ useSeoMeta({
ogTitle: title
})
const articleLink = computed(() => `${window?.location}`)
if (page.value.image) {
defineOgImage({ url: page.value.image })
} else {
defineOgImageComponent('Docs', {
headline: 'Blog',
title,
description
})
}
const formatDate = (dateString: Date) => {
const formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
@@ -94,16 +88,9 @@ const formatDate = (dateString: Date) => {
:value="page"
/>
<div class="flex items-center justify-end gap-2 text-sm text-muted">
<UButton
size="sm"
variant="link"
color="neutral"
label="Copy link"
@click="copyToClipboard(articleLink, 'Article link copied to clipboard')"
/>
</div>
<UContentSurround :surround />
<USeparator v-if="surround?.length" />
<UContentSurround :surround="surround" />
</UPageBody>
</UPage>
</UContainer>

View File

@@ -26,7 +26,7 @@ useSeoMeta({
<UPageHero :links="page.links" :ui="{ container: 'relative' }">
<LazyStarsBg />
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-default inset-0 mx-4 sm:mx-6 lg:mx-8" />
<div aria-hidden="true" class="absolute z-[-1] border-x border-default inset-0 mx-4 sm:mx-6 lg:mx-8" />
<template #title>
<MDC :value="page.title" unwrap="p" cache-key="pro-templates-hero-title" />
@@ -37,28 +37,36 @@ useSeoMeta({
</template>
</UPageHero>
<UPageBody class="mt-0 lg:border-t border-default">
<UPageBody class="!my-0 !py-0 border-y border-default">
<UContainer>
<UBlogPosts orientation="vertical" class="!gap-0">
<UBlogPost
v-for="(article, index) in posts"
<div
v-for="article in posts"
:key="article.path"
:to="article.path"
:title="article.title"
:description="article.description"
:image="{
src: article.image,
width: (index === 0 ? 672 : 437),
height: (index === 0 ? 378 : 246),
alt: `${article.title} image`
}"
:authors="article.authors?.map(author => ({ ...author, avatar: { ...author.avatar, alt: `${author.name} avatar` } }))"
:badge="{ label: article.category, color: 'primary', variant: 'subtle' }"
orientation="horizontal"
class="ring-0 border border-t-0 border-default rounded-none"
/>
class="group"
>
<UBlogPost
:to="article.path"
:title="article.title"
:description="article.description"
:image="{
src: article.image,
width: 437,
height: 246,
alt: `${article.title} image`
}"
:authors="article.authors?.map(author => ({ ...author, avatar: { ...author.avatar, alt: `${author.name} avatar` } }))"
:badge="{ label: article.category, color: 'primary', variant: 'subtle' }"
orientation="horizontal"
class="ring-0 border group-first:border-t-0 group-last:border-b-0 border-default rounded-none"
/>
<div class="h-6 bg-muted/50 group-last:hidden border-x border-default" />
</div>
</UBlogPosts>
</UContainer>
</UPageBody>
<UContainer class="relative h-24">
<div aria-hidden="true" class="absolute z-[-1] border-x border-default inset-0 mx-4 sm:mx-6 lg:mx-8" />
</UContainer>
</div>
</template>