Skip to content

Commit e8fe73c

Browse files
committed
feat: add example post
1 parent 6066c3f commit e8fe73c

File tree

7 files changed

+211
-26
lines changed

7 files changed

+211
-26
lines changed

.vitepress/theme/Layout.vue

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,58 @@
11
<script setup lang="ts">
2-
import { useData } from 'vitepress'
3-
import DefaultTheme from 'vitepress/theme'
4-
import { nextTick, provide } from 'vue'
2+
import { useData } from "vitepress";
3+
import DefaultTheme from "vitepress/theme";
4+
import { nextTick, provide } from "vue";
55
6-
const { isDark } = useData()
6+
const { isDark, page } = useData();
77
88
const enableTransitions = () =>
9-
'startViewTransition' in document &&
10-
window.matchMedia('(prefers-reduced-motion: no-preference)').matches
9+
"startViewTransition" in document &&
10+
window.matchMedia("(prefers-reduced-motion: no-preference)").matches;
1111
12-
provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
12+
provide("toggle-appearance", async ({ clientX: x, clientY: y }: MouseEvent) => {
1313
if (!enableTransitions()) {
14-
isDark.value = !isDark.value
15-
return
14+
isDark.value = !isDark.value;
15+
return;
1616
}
1717
18-
console.log('toggle-appearance', isDark.value)
18+
console.log("toggle-appearance", isDark.value);
1919
2020
const clipPath = [
2121
`circle(0px at ${x}px ${y}px)`,
2222
`circle(${Math.hypot(
2323
Math.max(x, innerWidth - x),
2424
Math.max(y, innerHeight - y)
25-
)}px at ${x}px ${y}px)`
26-
]
25+
)}px at ${x}px ${y}px)`,
26+
];
2727
2828
// @ts-expect-error
2929
await document.startViewTransition(async () => {
30-
isDark.value = !isDark.value
31-
await nextTick()
32-
}).ready
30+
isDark.value = !isDark.value;
31+
await nextTick();
32+
}).ready;
3333
3434
document.documentElement.animate(
3535
{ clipPath: isDark.value ? clipPath.reverse() : clipPath },
3636
{
3737
duration: 300,
38-
easing: 'ease-in',
39-
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`
38+
easing: "ease-in",
39+
pseudoElement: `::view-transition-${isDark.value ? "old" : "new"}(root)`,
4040
}
41-
)
42-
})
41+
);
42+
});
4343
</script>
4444

4545
<template>
46-
<DefaultTheme.Layout />
46+
<DefaultTheme.Layout>
47+
<template
48+
#doc-before
49+
v-if="
50+
page.filePath.startsWith('posts/') && page.filePath !== 'posts/index.md'
51+
"
52+
>
53+
<a class="back" href="/posts/"> ❮ &nbsp; 返回目录 </a>
54+
</template>
55+
</DefaultTheme.Layout>
4756
</template>
4857

4958
<style>
@@ -70,4 +79,18 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
7079
.VPSwitchAppearance .check {
7180
transform: none !important;
7281
}
73-
</style>
82+
83+
.back {
84+
display: inline-block;
85+
padding: 8px 16px;
86+
text-decoration: none;
87+
color: var(--vp-c-brand-1);
88+
font-size: 0.75rem;
89+
font-weight: 600;
90+
background-color: var(--vp-c-bg-soft);
91+
border-radius: 12px;
92+
margin-bottom: 12px;
93+
margin-top: -32px;
94+
margin-left: -5px;
95+
}
96+
</style>

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"private": true,
3+
"type": "module",
34
"scripts": {
45
"dev": "vitepress dev",
56
"build": "vitepress build",
@@ -8,5 +9,8 @@
89
"dependencies": {
910
"vitepress": "1.0.0-rc.36",
1011
"vue": "^3.4.10"
12+
},
13+
"devDependencies": {
14+
"@types/node": "^20.11.10"
1115
}
1216
}

pnpm-lock.yaml

Lines changed: 19 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

posts/TOC.vue

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<script setup lang="ts">
2+
/// <reference types="vitepress/client" />
3+
import { data as posts } from "./posts.data";
4+
5+
function renderDate(dateN: number) {
6+
const date = dateN.toString();
7+
return `${date.slice(0, 4)}-${date.slice(4, 6)}-${date.slice(6, 8)}`;
8+
}
9+
</script>
10+
11+
<template>
12+
<h1>Posts</h1>
13+
<ul class="posts">
14+
<li class="post" v-for="post in posts" :key="post.url">
15+
<a class="link" :href="post.url">
16+
<div class="date">{{ renderDate(post.frontmatter.date) }}</div>
17+
<div class="title">{{ post.frontmatter.title }}</div>
18+
<div class="excerpt" v-html="post.frontmatter.description" />
19+
<div class="authors" v-if="post.frontmatter.authors">
20+
<img
21+
v-for="author in post.frontmatter.authors"
22+
:key="author"
23+
:src="`https://www.github.com/${author}.png`"
24+
/>
25+
</div>
26+
</a>
27+
</li>
28+
</ul>
29+
</template>
30+
31+
<style scoped>
32+
.posts {
33+
list-style: none;
34+
padding: 0;
35+
36+
display: flex;
37+
flex-direction: column;
38+
gap: 1rem;
39+
}
40+
.post {
41+
display: flex;
42+
border-radius: 12px;
43+
background-color: var(--vp-c-bg-soft);
44+
transition: cubic-bezier(0.075, 0.82, 0.165, 1);
45+
transition-duration: .7s;
46+
transition-property: all;
47+
box-shadow: 0 18px 56px rgba(0, 0, 0, 0.16), 0 4px 12px rgba(0, 0, 0, 0.16);
48+
}
49+
.post:hover {
50+
background-color: var(--vp-c-gray-3);
51+
box-shadow: 0 18px 56px rgba(0, 0, 0, 0.16), 6px 12px 12px -2px var(--vp-c-brand-1);
52+
}
53+
.post .date {
54+
font-size: 0.75rem;
55+
font-weight: 600;
56+
color: var(--vp-c-text-2);
57+
margin-left: 1px;
58+
}
59+
.post .link {
60+
position: relative;
61+
display: flex;
62+
padding: 24px 32px;
63+
flex-direction: column;
64+
width: 100%;
65+
text-decoration: none;
66+
color: var(--vp-c-text-1);
67+
height: 128px;
68+
}
69+
.post .title {
70+
font-size: 1.5rem;
71+
font-weight: 600;
72+
}
73+
.post .excerpt {
74+
max-width: 70%;
75+
font-size: 1rem;
76+
line-height: 1.5;
77+
font-weight: 400;
78+
margin-top: 8px;
79+
color: var(--vp-c-text-2);
80+
white-space: nowrap;
81+
text-overflow: ellipsis;
82+
overflow: hidden;
83+
}
84+
.post .authors {
85+
position: absolute;
86+
right: 32px;
87+
bottom: 16px;
88+
display: flex;
89+
min-width: 32px;
90+
}
91+
.post .authors img {
92+
margin-left: -0.5rem;
93+
width: 32px;
94+
height: 32px;
95+
border-radius: 50%;
96+
}
97+
</style>

posts/example/index.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
title: Example Post
3+
description: This is an example post.
4+
authors:
5+
- kermanx
6+
- zecyel
7+
- 7086cmd
8+
date: 20240130
9+
---
10+
11+
# Example Post
12+
13+
This is an example post.
14+
15+
```ts
16+
console.log('Hello, world!')
17+
```

posts/index.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
page: true
3+
title: Posts
4+
sidebar: false
5+
returnToTop: false
6+
---
7+
8+
<script>
9+
import { defineAsyncComponent } from 'vue'
10+
import TOC from './TOC.vue'
11+
12+
export default {
13+
components: {
14+
TOC
15+
}
16+
}
17+
</script>
18+
19+
<TOC />

posts/posts.data.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { ContentData, createContentLoader } from "vitepress";
2+
3+
export declare const data: ContentData[];
4+
5+
export default createContentLoader("posts/*/index.md", {
6+
transform(rawData) {
7+
return rawData.sort((a, b) => {
8+
return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date);
9+
});
10+
},
11+
});

0 commit comments

Comments
 (0)