新增字数和预计阅读时间、文档两端对齐,优化作者信息显示逻辑 (#411)

Co-authored-by: BeiyanYunyi <14120445+BeiyanYunyi@users.noreply.github.com>
pull/414/head
Lee 2024-09-12 19:30:33 +08:00 committed by GitHub
parent 7240ee2332
commit b634077a02
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 98 additions and 12 deletions

View File

@ -158,3 +158,7 @@
border-radius: 8px !important;
}
/* 文档两端对齐 */
.vp-doc {
text-align: justify;
}

View File

@ -2,7 +2,7 @@
"name": "rle-wiki",
"type": "module",
"version": "1.0.0",
"packageManager": "pnpm@9.9.0",
"packageManager": "pnpm@9.10.0+sha512.73a29afa36a0d092ece5271de5177ecbf8318d454ecd701343131b8ebc0c1a91c487da46ab77c8e596d6acf1461e3594ced4becedf8921b074fbd8653ed7051c",
"description": "RLE 指北",
"license": "CC-BY-SA-4.0",
"scripts": {

View File

@ -1,18 +1,26 @@
<script setup lang="ts">
import { useData } from 'vitepress'
import { computed, onMounted, ref, watchEffect } from 'vue'
import ReadingTime from './ReadingTime.vue' // ReadingTime
// VitePress
const { frontmatter, page, theme, lang } = useData()
//
const date = computed(
() => new Date(frontmatter.value.lastUpdated ?? page.value.lastUpdated),
)
// ISO
const isoDatetime = computed(() => date.value.toISOString())
//
const datetime = ref('')
// Avoid hydration errors
// hydration
onMounted(() => {
watchEffect(() => {
// 使 API
datetime.value = new Intl.DateTimeFormat(
theme.value.lastUpdated?.formatOptions?.forceLocale ? lang.value : undefined,
theme.value.lastUpdated?.formatOptions ?? {
@ -23,15 +31,22 @@ onMounted(() => {
})
})
//
const authors = computed(() => {
let author = (frontmatter.value?.author ?? []) as string[]
if (!Array.isArray(author))
author = [author]
return author
})
if (!author.length)
author = []
return [...author, '匿名']
//
const displayAuthors = computed(() => {
if (authors.value.length === 0) {
return '匿名'
}
else {
return `${authors.value.join(', ')}`
}
})
</script>
@ -40,11 +55,7 @@ const authors = computed(() => {
<div class="inline-flex items-center gap-1">
<span class="i-octicon:person" />
<span>作者:</span>
<span class="space-x-2">
<span v-for="(author, index) in authors" :key="index">
{{ author }}
</span>
</span>
<span>{{ displayAuthors }}</span>
</div>
<div class="inline-flex items-center gap-1">
@ -52,5 +63,8 @@ const authors = computed(() => {
<span>{{ theme.lastUpdated?.text || 'Last updated' }}:</span>
<time :datetime="isoDatetime">{{ datetime }}</time>
</div>
<ClientOnly>
<ReadingTime /> <!-- 添加 ReadingTime 组件 -->
</ClientOnly>
</div>
</template>

View File

@ -0,0 +1,66 @@
<script setup lang="ts">
import { useRoute } from 'vitepress'
import { nextTick, ref, watch } from 'vue'
//
const route = useRoute()
//
const wordCount = ref(0)
const readingTime = ref(0)
const componentKey = ref(0) // key
const isLoaded = ref(false) //
//
function calculateReadingTime(content: string) {
const wordsPerMinute = 500 // 500
// 77
const wordCountOffset = 77
const chineseText = content.replace(/<[^>]*>|[^\u4E00-\u9FA5]/g, '') // HTML
const wordCount = chineseText.length - wordCountOffset //
const readingTime = Math.ceil(wordCount / wordsPerMinute) //
return { wordCount, readingTime }
}
//
function updateReadingTime() {
const contentElement = document.querySelector('.VPContent') // DOM
if (contentElement) {
const content = contentElement.textContent || '' //
const { wordCount: wc, readingTime: rt } = calculateReadingTime(content)
wordCount.value = wc
readingTime.value = rt
}
}
//
function initialize() {
isLoaded.value = false //
componentKey.value += 1
nextTick().then(() => {
updateReadingTime()
isLoaded.value = true //
})
}
//
watch(
route,
() => {
initialize()
},
{ immediate: true },
)
</script>
<template>
<div v-if="isLoaded" :key="componentKey">
<p>字数: {{ wordCount }} &nbsp; 预计阅读时间: {{ readingTime }} 分钟</p>
</div>
</template>
<style scoped>
/* 这里可以添加样式 */
</style>

View File

@ -5,6 +5,7 @@ import ArticlesMenu from './ArticlesMenu.vue'
import CopyrightInfo from './CopyrightInfo.vue'
import HomeContent from './HomeContent.vue'
import PageInfo from './PageInfo.vue'
import ReadingTime from './ReadingTime.vue'
export {
@ -14,5 +15,6 @@ export {
ArticlesMenu,
CopyrightInfo,
HomeContent,
PageInfo
PageInfo,
ReadingTime
}