Appearance
如何获取所有的md文档,并获取它们的类型、标签、时间等
获取所有md文档
在写md文档时,我们的frontmatter
里应该都包含了该文档基本信息,如分类、标签、创建时间、作者、标题等。如:
我们可以通过读取md文件,然后解析frontmatter
,即可获取所有的文章列表、标签、分类。
1. 获取所有md文件
想要获取md文件的frontmatter,我们就得解析文件,通过nodejs
提供的fs
模块来递归的处理所提供的文件夹。
在根目录新建一个readMD.js
。引入fs
模块,并提供一个根路径。
const fs = require('fs')
function readAll(parentPath) {
const files = fs.readdirSync(parentPath)
}
readAll('./docs/write')
现在files
就是./docs/write
下所有的文件以及文件夹,我们通过遍历它,判断如果是文件则解析frontmatter
,如果是文件夹则递归处理。
2. 解析文件获取frontmatter
javascript
const fs = require('fs')
const path = require('path')
const yaml = require('js-yaml')
const out = []
let re = /---(.*?)---/sg
function readAll(parentPath) {
const files = fs.readdirSync(parentPath)
files.map(item => {
let tempPath = path.join(parentPath, item); //当前文件或文件夹的路径
let stats = fs.statSync(tempPath); //判断是文件还是文件夹
if (stats.isDirectory()) { //文件夹递归处理
readAll(tempPath);
} else {
const content = fs.readFileSync(tempPath, 'utf8') //获取文件内容
let s = re.exec(content) //通过正则获取frontmatter的内容
re.lastIndex = 0 // 这里如果不操作,在后面正则判断时会有问题,当时在这里卡了很久
if (s) {
let docs = yaml.load(s[1]) // 通过yaml转换成对象
docs.link = '/littlear'+tempPath.slice(4, -3) // 这里是为了文章列表的跳转
out.push(docs);
}
}
})
}
readAll('./docs/write')
3. 存储所有数据
现在out
中就是所有的文档信息了,可以直接将它导出,在需要用的地方引入,或者直接将它输入到一个文件中,这里我选择了后者。我新建了一个docs/.vitepress/components/docs.json
文件来存储所有的文章信息
javascript
const filePath = 'docs/.vitepress/components/docs.json';
fs.writeFileSync(
filePath,
JSON.stringify(out),
{
encoding: 'utf8',
}
);
格式化数据
可以在/docs/.vitepress/componentes
下新建一个useDocs.js
文件,对之前获取到的数据进行格式化,以便页面中更好的使用。
javascript
import docData from './docs.json'
export function useDocs() {
// 时间倒序显示
docData.sort((a, b) => new Date(b.date) - new Date(a.date))
const categories = {} //所有的文章分类
const tags = new Set() //所有的文章标签
let docNum = 0, tagNum = 0 //文章总数、标签总数
docData.map(item => {
docNum++
if (item.categories) {
item.categories.map(c => {
if (!categories[c]) {
categories[c] = 0
}
categories[c]++
})
}
if (item.tags) {
item.tags.map(c => {
tags.add(c)
})
}
})
tagNum = tags.size
return {
/**
* docData: 包含所有的文章信息
* categories: 所有分类
* tags: 所有标签
* docNum: 文章总数
* tagNum: 标签总数
*/
docData, categories, tags, docNum, tagNum
}
}
之后就能直接在想用的地方直接引入即可,如要按列表展示文章
<script setup>
import { useDocs } from './useDocs.js'
const { docData } = useDocs() //获取所有文章信息遍历即可
</script>
<template>
<a v-for="item in docData" :key="item.title" :href="item.link" class="docs">
<div class="docs-title">{{ item.title }}</div>
<div class="docs-footer">
<span class="docs-info">✍️{{ item.author }}</span>
<span class="docs-info">🕐{{ item.date }}</span>
<span>
🔗
<span class="docs-info docs-tag" v-for="tag in item.tags" :key="tag">{{ tag }}</span>
</span>
</div>
</a>
</template>