Add Table of Contents (TOC) to article pages
This commit is contained in:
@@ -1,11 +1,12 @@
|
|||||||
---
|
---
|
||||||
title: "My First Blog Post"
|
title: "My First Blog Post"
|
||||||
description: "This is a test article."
|
description: "This is a test article."
|
||||||
|
navigation: true
|
||||||
---
|
---
|
||||||
|
|
||||||
# Hello World
|
## Hello World
|
||||||
|
|
||||||
This is a test article.
|
Foobarbazbuz.
|
||||||
|
|
||||||
## Component Rendering
|
## Component Rendering
|
||||||
|
|
||||||
|
|||||||
@@ -18,26 +18,6 @@ body {
|
|||||||
/* Main content */
|
/* Main content */
|
||||||
/*----------------------------------------*/
|
/*----------------------------------------*/
|
||||||
|
|
||||||
.container {
|
|
||||||
margin: 56px auto 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
position: relative;
|
|
||||||
min-height: calc(100vh - 104px - .5rem);
|
|
||||||
padding: 20px 20px 50px 20px;
|
|
||||||
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
color: #818080 !important;
|
color: #818080 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Footer */
|
|
||||||
/*----------------------------------------*/
|
|
||||||
|
|
||||||
footer {
|
|
||||||
text-align: center;
|
|
||||||
color: #909090;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<template>
|
||||||
|
<aside v-if="toc" class="position-fixed toc shadow">
|
||||||
|
<h5 class="text-center">{{ toc.title }}</h5>
|
||||||
|
<ul class="font-smaller mb-0">
|
||||||
|
<li>
|
||||||
|
<a href="#">Overview</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ArticlesTableOfContentsLink :links="toc.links" :first="true" class="font-smaller mb-0" />
|
||||||
|
</aside>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.toc {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1450px) {
|
||||||
|
.toc {
|
||||||
|
display: block;
|
||||||
|
width: calc((100vw - 960px) / 2 - 35px);
|
||||||
|
max-width: 300px;
|
||||||
|
top: 56px;
|
||||||
|
left: calc(100vw - (100vw - 960px) / 2 + 12px);
|
||||||
|
padding: 20px 5px 20px 0;
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-smaller {
|
||||||
|
font-size: .8125rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { Toc } from "@nuxtjs/mdc";
|
||||||
|
|
||||||
|
defineProps<{ toc?: Toc }>();
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<ul>
|
||||||
|
<template v-for="link in links" :key="link.id">
|
||||||
|
<li>
|
||||||
|
<a :href="'#' + link.id">{{ link.text }}</a>
|
||||||
|
</li>
|
||||||
|
<template v-if="link.children && link.children?.length > 0">
|
||||||
|
<ArticlesTableOfContentsLink :links="link.children" :first="false" />
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { TocLink } from "@nuxtjs/mdc";
|
||||||
|
|
||||||
|
defineProps<{ links: TocLink[] }>();
|
||||||
|
</script>
|
||||||
@@ -6,6 +6,13 @@
|
|||||||
</footer>
|
</footer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
footer {
|
||||||
|
text-align: center;
|
||||||
|
color: #909090;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const year = new Date().getFullYear();
|
const year: number = new Date().getFullYear();
|
||||||
</script>
|
</script>
|
||||||
@@ -12,3 +12,67 @@
|
|||||||
</div>
|
</div>
|
||||||
<ToggleColorMode />
|
<ToggleColorMode />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container {
|
||||||
|
margin: 56px auto 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
min-height: calc(100vh - 104px - .5rem);
|
||||||
|
padding: 20px 20px 50px 20px;
|
||||||
|
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 576px) {
|
||||||
|
|
||||||
|
.container,
|
||||||
|
.container-sm {
|
||||||
|
max-width: 540px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
|
||||||
|
.container,
|
||||||
|
.container-md,
|
||||||
|
.container-sm {
|
||||||
|
max-width: 630px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
|
||||||
|
.container,
|
||||||
|
.container-lg,
|
||||||
|
.container-md,
|
||||||
|
.container-sm {
|
||||||
|
max-width: 720px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
|
||||||
|
.container,
|
||||||
|
.container-lg,
|
||||||
|
.container-md,
|
||||||
|
.container-sm,
|
||||||
|
.container-xl {
|
||||||
|
max-width: 960px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1400px) {
|
||||||
|
|
||||||
|
.container,
|
||||||
|
.container-lg,
|
||||||
|
.container-md,
|
||||||
|
.container-sm,
|
||||||
|
.container-xl,
|
||||||
|
.container-xxl {
|
||||||
|
max-width: 960px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<template v-if="article">
|
<template v-if="article">
|
||||||
|
<ArticlesTableOfContents v-if="article.navigation" :toc="article.body.toc" />
|
||||||
|
|
||||||
<h1>{{ article.title }}</h1>
|
<h1>{{ article.title }}</h1>
|
||||||
<p>{{ article.description }}</p>
|
<p>{{ article.description }}</p>
|
||||||
<ContentRenderer :value="article" />
|
<ContentRenderer :value="article" />
|
||||||
@@ -59,9 +61,11 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { ContentCollectionItem } from "@nuxt/content";
|
||||||
|
|
||||||
const { params } = useRoute();
|
const { params } = useRoute();
|
||||||
|
|
||||||
const { data: article } = await useAsyncData(
|
const { data: article } = await useAsyncData<ContentCollectionItem | null>(
|
||||||
`article-${params.slug}`,
|
`article-${params.slug}`,
|
||||||
() => queryCollection("content").path("/articles/" + params.slug).first()
|
() => queryCollection("content").path("/articles/" + params.slug).first()
|
||||||
);
|
);
|
||||||
@@ -70,6 +74,4 @@ useSeoMeta({
|
|||||||
title: article.value?.title,
|
title: article.value?.title,
|
||||||
description: article.value?.description
|
description: article.value?.description
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(article);
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user