Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: the article list is sorted by time in descending order by default. #2

Merged
merged 2 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,30 @@
## 规划

- [x] ✅ 文章标签以及标签页
- [ ] 🚧 脚手架工具
- [ ] 🚧 内置全局搜索
- [ ] 🚧 文章列表默认排序、手动排序、置顶
- [ ] 🚧 文章列表默认按照时间倒序排序
- [ ] 🚧 文章内容页顶部展示阅读时间、字数等信息
- [ ] ⌛ 侧边栏排序
- [ ] 🚧 文章列表手动根据frontmatter的sort字段排序, 优先级大于默认排序
- [ ] 🚧 文章列表置顶某个文章, 置顶后优先根据frontmatter的sort字段排序, 其次按照时间排序
- [ ] 🚧 侧边栏文章的排序
- [ ] ⌛ 文档站建设
- [ ] ⌛ 开源项目展示页, 展示项目卡片列表
- [ ] ⌛ 时间线页面
- [ ] ⌛ 文章评论
- [ ] ⌛ RSS 订阅
- [ ] ⌛ live2d
- [ ] ⌛ 友情链接页
- [ ] ⌛ AI文章摘要
- [ ] ⌛ AI聊天悬浮按钮
- [ ] ⌛ AI聊天

## 快速开始

> 待完善

## 案例

- [hacxy.cn](https://hacxy.cn)

## License

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"dev": "pnpm -F vitepress-theme-mild run dev",
"build": "pnpm -F vitepress-theme-mild run build",
"release": "pnpm -F vitepress-theme-mild run release",
"demo:dev": "pnpm -F demo run dev",
"demo:dev": "pnpm build && pnpm -F demo run dev",
"demo:build": "pnpm -F demo run build",
"demo:preview": "pnpm -F demo run preview",
"prepare": "simple-git-hooks",
Expand Down
3 changes: 2 additions & 1 deletion packages/demo/docs/src/demo2.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
---
date: 2024-12-25 17:25:00
category: 服务器
tags:
- demo
---

# demo2

测试时间
可以在 Markdown 文件、主题中的 \*.vue 组件、样式和普通的 .css 文件中引用静态资源,可以使用绝对路径 (基于项目根目录) 或者相对路径 (基于文件系统)。后者类似于 Vite、Vue CLI 或者 webpack 的 file-loader 的行为。

常见的图像,媒体和字体文件会被自动检测并视作资源。
Expand Down
1 change: 1 addition & 0 deletions packages/demo/docs/src/demo4.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ tags:
---
# demo4

这是demo4 测试时间
可以在 Markdown 文件、主题中的 \*.vue 组件、样式和普通的 .css 文件中引用静态资源,可以使用绝对路径 (基于项目根目录) 或者相对路径 (基于文件系统)。后者类似于 Vite、Vue CLI 或者 webpack 的 file-loader 的行为。

常见的图像,媒体和字体文件会被自动检测并视作资源。
Expand Down
21 changes: 8 additions & 13 deletions packages/theme/src/components/ArticlesList.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { ArticlesData } from '../datas/articles.data.js';
import { useUrlSearchParams } from '@vueuse/core';
import { NEllipsis, NPagination } from 'naive-ui';
import { NPagination, NTime } from 'naive-ui';
import { useRouter } from 'vitepress';
import { computed, ref, watch, watchEffect } from 'vue';
import { useArticleData } from '../hooks/useArticleData.js';
Expand Down Expand Up @@ -83,13 +83,15 @@ watch(currentPage, () => {
<a> {{ article?.title }}</a>
</div>
</div>
<n-ellipsis class="describe" :tooltip="{ show: false }">
<div class="describe">
{{ article.description }}
</n-ellipsis>
</div>
<div class="post-info">
<div class="text">
<icon-calendar />
<span>{{ article.date }}</span>
<span>
<n-time :time="article.date" format="yyyy-MM-dd" />
</span>
</div>
<div class="text">
<icon-words />
Expand Down Expand Up @@ -200,7 +202,8 @@ watch(currentPage, () => {
font-weight: 500;
margin: 0.1rem 0;
}
:deep(.n-ellipsis) {

.describe {
font-size: 0.9375rem;
overflow: hidden;
color: var(--vp-c-text-2);
Expand Down Expand Up @@ -249,13 +252,5 @@ watch(currentPage, () => {
overflow: hidden;
width: 17rem;
}
.describe {
font-size: 0.9375rem;
display: -webkit-box;
-webkit-box-orient: vertical;
line-clamp: 3;
overflow: hidden;
margin: 0.5rem 0 1rem;
}
}
</style>
56 changes: 15 additions & 41 deletions packages/theme/src/datas/articles.data.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,34 @@
import matter from 'gray-matter';
import { readingTime } from 'reading-time-estimator';
import { NOT_ARTICLE_LAYOUTS } from '../constants';
import { getTextDescription } from '../utils/common';
import { createArticlesListLoader } from '../utils/node/articles';
import { formatDate } from '../utils/node/date';

function getTextDescription(text: string, count = 100) {
const finalText = text
// 首个标题
?.replace(/^(#+)(.*)/m, '')
// 除去标题
?.replace(/#/g, '')
// 除去图片
?.replace(/!\[.*?\]\(.*?\)/g, '')
// 除去链接
?.replace(/\[(.*?)\]\(.*?\)/g, '$1')
// 除去加粗
?.replace(/\*\*(.*?)\*\*/g, '$1')
?.split('\n')
?.filter(v => !!v)
?.join('\n')
?.replace(/>(.*)/, '')
?.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
?.trim()
?.slice(0, count);

return `${finalText}...`;
export interface ArticlesData {
title: string
path: string
description: string
date: number
tags: string[]
words: number
minutes: number
category: string
}

export default createArticlesListLoader({
includeSrc: true,
render: true,
excerpt: true,
transform(rawData) {
const data = rawData.filter(item => !NOT_ARTICLE_LAYOUTS.includes(item.frontmatter.layout)).map(item => {
const data = rawData.filter(item => !NOT_ARTICLE_LAYOUTS.includes(item.frontmatter.layout)).sort((a, b) => b.frontmatter.date - a.frontmatter.date).map(item => {
const content = matter(item.src || '').content;
const { words, minutes } = readingTime(content, 200);
const match = content.match(/^(#+)\s+(.+)/m);
const title = match?.[2] || '';
const description = getTextDescription(content);
let { date, ...frontmatter } = item.frontmatter;
if (date) {
date = formatDate(item.frontmatter.date);
}
else {
date = item.fileModifiedTime; // 文件最后修改时间(兜底)
let { date, description = content, ...frontmatter } = item.frontmatter;

if (description?.length > 100) {
description = getTextDescription(description);
}
return {
path: item.url,
Expand All @@ -60,15 +44,5 @@ export default createArticlesListLoader({
}
});

export interface ArticlesData {
title: string
path: string
description: string
date: string
tags: string[]
words: number
minutes: number
category: string
}
declare const data: ArticlesData[];
export { data };
25 changes: 25 additions & 0 deletions packages/theme/src/utils/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export function getTextDescription(text: string, count = 100) {
if (!text)
return;
const finalText = text
// 首个标题
?.replace(/^(#+)(.*)/m, '')
// 除去标题
?.replace(/#/g, '')
// 除去图片
?.replace(/!\[.*?\]\(.*?\)/g, '')
// 除去链接
?.replace(/\[(.*?)\]\(.*?\)/g, '$1')
// 除去加粗
?.replace(/\*\*(.*?)\*\*/g, '$1')
?.split('\n')
?.filter(v => !!v)
?.join('\n')
?.replace(/>(.*)/, '')
?.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
?.trim()
?.slice(0, count);

return `${finalText}...`;
}
16 changes: 11 additions & 5 deletions packages/theme/src/utils/node/articles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fs from 'fs-extra';
import matter from 'gray-matter';
import { glob, type GlobOptions } from 'tinyglobby';
import { createMarkdownRenderer, type SiteConfig } from 'vitepress';
import { formatDate } from './date';
import { dateToUnixTimestamp } from './date';
import { getPattern, normalizePath } from './path';

export interface ContentData {
Expand All @@ -12,7 +12,7 @@ export interface ContentData {
html: string | undefined
frontmatter: Record<string, any>
excerpt: string | undefined
fileModifiedTime: string
// fileModifiedTime: number
}
export interface ContentOptions<T = ContentData[]> {
/**
Expand Down Expand Up @@ -127,21 +127,27 @@ export function createArticlesListLoader<T = ContentData[]>(
? { excerpt_separator: renderExcerpt as any }
: { excerpt: renderExcerpt as any }
);
// const lastEditTime = await getLastCommitDate(file);

if (frontmatter.date) {
frontmatter.date = dateToUnixTimestamp(frontmatter.date);
}
else {
frontmatter.date = timestamp;
}
const url
= `/${
normalizePath(path.relative(config.srcDir, file))
.replace(/(^|\/)index\.md$/, '$1')
.replace(/\.md$/, config.cleanUrls ? '' : '.html')}`;
// eslint-disable-next-line no-undefined
const html = render ? md.render(src) : undefined;
const fileModifiedTime = formatDate(timestamp);
// const fileModifiedTime = timestamp;
const renderedExcerpt = renderExcerpt
? excerpt && md.render(excerpt)
// eslint-disable-next-line no-undefined
: undefined;
const data: ContentData = {
fileModifiedTime,
// fileModifiedTime,
// eslint-disable-next-line no-undefined
src: includeSrc ? src : undefined,
html,
Expand Down
8 changes: 8 additions & 0 deletions packages/theme/src/utils/node/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,11 @@ export function formatDate(date: number | Date | string) {
// 返回格式化后的日期字符串
return `${year}-${month}-${day}`;
}

export function dateToUnixTimestamp(date: Date) {
// 检查输入是否为 Date 对象
if (!(date instanceof Date)) {
throw new TypeError('Input must be a Date object');
}
return new Date(date.toLocaleString('en-US', { timeZone: 'UTC' })).getTime();
}
Loading