Skip to content

Commit

Permalink
Merge pull request #16 from samzong/file-traverser
Browse files Browse the repository at this point in the history
redesgin filewalker
  • Loading branch information
samzong authored Dec 29, 2024
2 parents dac402a + bfea354 commit cec96ec
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 115 deletions.
62 changes: 16 additions & 46 deletions .vitepress/utils/archives.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,30 @@
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { BasePost, walkFiles, extractDateFromFilename } from './fileWalker'

interface Post {
title: string
date: string
url: string
}
interface Post extends BasePost {}

interface ArchiveData {
[year: string]: Post[]
}

// 从文件名中提取日期
function extractDateFromFilename(filename: string): string | null {
const match = filename.match(/^(\d{4}-\d{2}-\d{2})/)
return match ? match[1] : null
}

export function generateArchives(): ArchiveData {
const posts: Post[] = []
const contentDir = path.resolve(__dirname, '../../blog')

function findMarkdownFiles(dir: string) {
const files = fs.readdirSync(dir)

files.forEach(file => {
const filePath = path.join(dir, file)
const stat = fs.statSync(filePath)

if (stat.isDirectory()) {
findMarkdownFiles(filePath)
} else if (path.extname(file) === '.md') {
// 从文件名中提取日期
const dateFromFilename = extractDateFromFilename(file)

// 如果文件名没有日期前缀,跳过这个文件
if (!dateFromFilename) return

const content = fs.readFileSync(filePath, 'utf-8')
const { data } = matter(content)
const url = '/' + path.relative(path.resolve(__dirname, '../..'), filePath).replace(/\.md$/, '')

const post = {
title: data.title || file.replace(/^\d{4}-\d{2}-\d{2}-/, '').replace(/\.md$/, ''),
date: dateFromFilename,
url
}

posts.push(post)
const posts = walkFiles<Post>({
contentDir,
fileFilter: (file) => !!extractDateFromFilename(file),
processFile: (filePath, content, { data }) => {
const dateFromFilename = extractDateFromFilename(path.basename(filePath))
if (!dateFromFilename) return null

return {
title: data.title || path.basename(filePath).replace(/^\d{4}-\d{2}-\d{2}-/, '').replace(/\.md$/, ''),
date: dateFromFilename,
url: '/' + path.relative(path.resolve(__dirname, '../..'), filePath).replace(/\.md$/, '')
}
})
}

findMarkdownFiles(contentDir)

}
})

// 按日期排序(从新到旧)
posts.sort((a, b) => b.date.localeCompare(a.date))

Expand Down
66 changes: 66 additions & 0 deletions .vitepress/utils/fileWalker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'

export interface BasePost {
title: string
date: string
url: string
}

export interface FileProcessorOptions {
contentDir: string
fileFilter?: (file: string) => boolean
processFile: (filePath: string, content: string, matter: matter.GrayMatterFile<string>) => any
}

export function walkFiles<T>({ contentDir, fileFilter, processFile }: FileProcessorOptions): T[] {
const results: T[] = []

function walk(dir: string) {
const files = fs.readdirSync(dir)

files.forEach(file => {
const filePath = path.join(dir, file)
const stat = fs.statSync(filePath)

if (stat.isDirectory()) {
walk(filePath)
} else if (path.extname(file) === '.md') {
if (fileFilter && !fileFilter(file)) {
return
}

const content = fs.readFileSync(filePath, 'utf-8')
const matterResult = matter(content)
const result = processFile(filePath, content, matterResult)

if (result) {
results.push(result)
}
}
})
}

walk(contentDir)
return results
}

// 辅助函数:从文件名中提取日期
export function extractDateFromFilename(filename: string): string | null {
const match = filename.match(/^(\d{4}-\d{2}-\d{2})/)
return match ? match[1] : null
}

// 辅助函数:格式化日期
export function formatDate(date: string | Date): string {
if (typeof date === 'string') {
date = new Date(date)
}
return date.toISOString().split('T')[0]
}

// 辅助函数:生成URL
export function generateUrl(filePath: string, baseDir: string): string {
return '/' + path.relative(path.resolve(baseDir), filePath).replace(/\.md$/, '')
}
124 changes: 55 additions & 69 deletions .vitepress/utils/tags.ts
Original file line number Diff line number Diff line change
@@ -1,77 +1,63 @@
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import fs from "fs";
import path from "path";
import { BasePost, walkFiles, formatDate } from "./fileWalker";

interface Post {
title: string
date: string
url: string
tags: string[]
interface Post extends BasePost {
tags: string[];
}

interface TagData {
[key: string]: Post[]
}

// 格式化日期函数
function formatDate(date: string | Date): string {
if (typeof date === 'string') {
// 如果是ISO格式的字符串,先转换为Date对象
date = new Date(date)
}
return date.toISOString().split('T')[0]
[key: string]: Post[];
}

export function generateTags(): TagData {
const posts: Post[] = []
const contentDir = path.resolve(__dirname, '../../blog')
const tags: TagData = {}

function findMarkdownFiles(dir: string) {
const files = fs.readdirSync(dir)

files.forEach(file => {
const filePath = path.join(dir, file)
const stat = fs.statSync(filePath)

if (stat.isDirectory()) {
findMarkdownFiles(filePath)
} else if (path.extname(file) === '.md') {
const content = fs.readFileSync(filePath, 'utf-8')
const { data } = matter(content)

if (data.tags && Array.isArray(data.tags)) {
const url = '/' + path.relative(path.resolve(__dirname, '../..'), filePath).replace(/\.md$/, '')
const post = {
title: data.title || file.replace(/\.md$/, ''),
date: formatDate(data.date || stat.birthtime),
url,
tags: data.tags
}

posts.push(post)

data.tags.forEach((tag: string) => {
if (!tags[tag]) {
tags[tag] = []
}
tags[tag].push(post)
})
}
const contentDir = path.resolve(__dirname, "../../blog");
const tags: TagData = {};

const posts = walkFiles<Post>({
contentDir,
processFile: (filePath, content, { data }) => {
if (!data.tags || !Array.isArray(data.tags)) {
return null;
}
})
}

findMarkdownFiles(contentDir)

Object.keys(tags).forEach(tag => {
tags[tag].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
})

const sortedTags: TagData = {}
Object.keys(tags).sort().forEach(tag => {
sortedTags[tag] = tags[tag]
})

return sortedTags
}

const post = {
title: data.title || path.basename(filePath).replace(/\.md$/, ""),
date: formatDate(data.date || fs.statSync(filePath).birthtime),
url:
"/" +
path
.relative(path.resolve(__dirname, "../.."), filePath)
.replace(/\.md$/, ""),
tags: data.tags,
};

// 将文章添加到对应的标签集合中
data.tags.forEach((tag: string) => {
if (!tags[tag]) {
tags[tag] = [];
}
tags[tag].push(post);
});

return post;
},
});

// 对每个标签下的文章按日期排序
Object.keys(tags).forEach((tag) => {
tags[tag].sort(
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
);
});

// 对标签进行字母顺序排序
const sortedTags: TagData = {};
Object.keys(tags)
.sort()
.forEach((tag) => {
sortedTags[tag] = tags[tag];
});

return sortedTags;
}

0 comments on commit cec96ec

Please sign in to comment.