update
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
import { formatDate } from "~/utils/helper";
|
||||
interface Props {
|
||||
title?: string;
|
||||
image?: string;
|
||||
@@ -26,7 +25,7 @@ withDefaults(defineProps<Props>(), {
|
||||
<div
|
||||
class="flex items-center text-sm font-bold text-violet-600 dark:text-violet-400 bg-violet-500/10 px-3 py-1 rounded-full border border-violet-500/20">
|
||||
<LogoDate class="mr-2 w-4 h-4" />
|
||||
{{ formatDate(date) }}
|
||||
{{ date }}
|
||||
</div>
|
||||
<div class="flex items-center gap-2 flex-wrap">
|
||||
<template v-for="tag in tags" :key="tag">
|
||||
@@ -52,12 +51,12 @@ withDefaults(defineProps<Props>(), {
|
||||
|
||||
<div class="relative group max-w-4xl mx-auto mb-12">
|
||||
<div
|
||||
class="absolute inset-0 bg-gradient-to-tr from-violet-500/20 to-fuchsia-500/20 rounded-3xl blur-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-700"></div>
|
||||
class="absolute inset-0 bg-linear-to-tr from-violet-500/20 to-fuchsia-500/20 rounded-3xl blur-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-700"></div>
|
||||
<NuxtImg
|
||||
:src="image || ''"
|
||||
:alt="alt || ''"
|
||||
width="1200"
|
||||
class="relative rounded-3xl shadow-2xl w-full aspect-[21/9] object-cover border border-white/20 dark:border-white/5 transition-transform duration-700 group-hover:scale-[1.01]" />
|
||||
class="relative rounded-3xl shadow-2xl w-full aspect-21/9 object-cover border border-white/20 dark:border-white/5 transition-transform duration-700 group-hover:scale-[1.01]" />
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
@@ -2,10 +2,27 @@
|
||||
const { path } = useRoute();
|
||||
const articles = await queryCollection("content").path(path).first();
|
||||
|
||||
const links = articles?.body?.toc?.links || [];
|
||||
interface TocLink {
|
||||
id: string;
|
||||
text: string;
|
||||
children?: TocLink[];
|
||||
}
|
||||
|
||||
const links = (articles?.body?.toc?.links || []) as TocLink[];
|
||||
|
||||
const activeId = ref("");
|
||||
|
||||
const flattenLinks = (links: TocLink[]) => {
|
||||
let flat: TocLink[] = [];
|
||||
links.forEach((link) => {
|
||||
flat.push(link);
|
||||
if (link.children) {
|
||||
flat = flat.concat(flattenLinks(link.children));
|
||||
}
|
||||
});
|
||||
return flat;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
@@ -18,7 +35,7 @@ onMounted(() => {
|
||||
{ rootMargin: "-100px 0% -80% 0%" },
|
||||
);
|
||||
|
||||
links.forEach((link) => {
|
||||
flattenLinks(links).forEach((link) => {
|
||||
const el = document.getElementById(link.id);
|
||||
if (el) observer.observe(el);
|
||||
});
|
||||
@@ -37,18 +54,48 @@ onMounted(() => {
|
||||
Table Of Content
|
||||
</h3>
|
||||
<nav class="space-y-1">
|
||||
<NuxtLink
|
||||
v-for="link in links"
|
||||
:key="link.id"
|
||||
:to="`#${link.id}`"
|
||||
class="block text-sm py-1.5 px-3 rounded-xl transition-all duration-200"
|
||||
:class="[
|
||||
activeId === link.id
|
||||
? 'text-violet-600 dark:text-violet-400 bg-violet-500/10 font-bold translate-x-1'
|
||||
: 'text-zinc-600 dark:text-zinc-400 hover:text-violet-600 dark:hover:text-violet-400 hover:bg-violet-500/5',
|
||||
]">
|
||||
{{ link.text }}
|
||||
</NuxtLink>
|
||||
<template v-for="link in links" :key="link.id">
|
||||
<NuxtLink
|
||||
:to="`#${link.id}`"
|
||||
class="block text-sm py-1.5 px-3 rounded-xl transition-all duration-200"
|
||||
:class="[
|
||||
activeId === link.id
|
||||
? 'text-violet-600 dark:text-violet-400 bg-violet-500/10 font-bold translate-x-1'
|
||||
: 'text-zinc-600 dark:text-zinc-400 hover:text-violet-600 dark:hover:text-violet-400 hover:bg-violet-500/5',
|
||||
]">
|
||||
{{ link.text }}
|
||||
</NuxtLink>
|
||||
|
||||
<div v-if="link.children" class="ml-3 space-y-1">
|
||||
<template v-for="child in link.children" :key="child.id">
|
||||
<NuxtLink
|
||||
:to="`#${child.id}`"
|
||||
class="block text-xs py-1.5 px-3 rounded-xl transition-all duration-200"
|
||||
:class="[
|
||||
activeId === child.id
|
||||
? 'text-violet-600 dark:text-violet-400 bg-violet-500/10 font-bold translate-x-1'
|
||||
: 'text-zinc-500 dark:text-zinc-500 hover:text-violet-600 dark:hover:text-violet-400 hover:bg-violet-500/5',
|
||||
]">
|
||||
{{ child.text }}
|
||||
</NuxtLink>
|
||||
|
||||
<div v-if="child.children" class="ml-3 space-y-1">
|
||||
<NuxtLink
|
||||
v-for="grandchild in child.children"
|
||||
:key="grandchild.id"
|
||||
:to="`#${grandchild.id}`"
|
||||
class="block text-xs py-1.5 px-3 rounded-xl transition-all duration-200"
|
||||
:class="[
|
||||
activeId === grandchild.id
|
||||
? 'text-violet-600 dark:text-violet-400 bg-violet-500/10 font-bold translate-x-1'
|
||||
: 'text-zinc-400 dark:text-zinc-600 hover:text-violet-600 dark:hover:text-violet-400 hover:bg-violet-500/5',
|
||||
]">
|
||||
{{ grandchild.text }}
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
<script lang="ts" setup>
|
||||
interface Props {
|
||||
path: string;
|
||||
title: string;
|
||||
date: string;
|
||||
description: string;
|
||||
image: string;
|
||||
alt: string;
|
||||
ogImage: string;
|
||||
tags: Array<string>;
|
||||
published: boolean;
|
||||
path?: string;
|
||||
title?: string;
|
||||
date?: string;
|
||||
description?: string;
|
||||
image?: string;
|
||||
alt?: string;
|
||||
tags?: Array<string>;
|
||||
published?: boolean;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
|
||||
Reference in New Issue
Block a user