mjz update

This commit is contained in:
mjz
2023-05-28 18:15:33 +08:00
parent 9b75e60571
commit ed6e2d81fb
243 changed files with 11730 additions and 6 deletions

View File

@@ -0,0 +1,185 @@
const fs = require('fs'); // 文件模块
const path = require('path'); // 路径模块
const chalk = require('chalk') // 命令行打印美化
const matter = require('gray-matter'); // front matter解析器
const log = console.log
let catalogueData = {}; // 目录页数据
/**
* 生成侧边栏数据
* @param {String} sourceDir .md文件所在源目录(一般是docs目录)
* @param {Boolean} collapsable 是否可折叠
*/
function createSidebarData(sourceDir, collapsable) {
const sidebarData = {};
const tocs = readTocs(sourceDir);
tocs.forEach(toc => { // toc是每个目录的绝对路径
if (toc.substr(-6) === '_posts') { // 碎片化文章
// 注释说明:碎片化文章不需要生成结构化侧边栏 2020.05.01
// const sidebarArr = mapTocToPostSidebar(toc);
// sidebarData[`/${path.basename(toc)}/`] = sidebarArr
} else {
const sidebarObj = mapTocToSidebar(toc, collapsable);
if (!sidebarObj.sidebar.length) {
log(chalk.yellow(`warning: 该目录 "${toc}" 内部没有任何文件或文件序号出错,将忽略生成对应侧边栏`))
return;
}
sidebarData[`/${path.basename(toc)}/`] = sidebarObj.sidebar
sidebarData.catalogue = sidebarObj.catalogueData
}
})
return sidebarData
}
module.exports = createSidebarData;
/**
* 读取指定目录下的文件绝对路径
* @param {String} root 指定的目录
*/
function readTocs(root) {
const result = [];
const files = fs.readdirSync(root); // 读取目录,返回数组成员是root底下所有的目录名 (包含文件夹和文件)
files.forEach(name => {
const file = path.resolve(root, name); // 将路径或路径片段的序列解析为绝对路径
if (fs.statSync(file).isDirectory() && name !== '.vuepress' && name !== '@pages') { // 是否为文件夹目录,并排除.vuepress文件夹
result.push(file);
}
})
return result;
}
/**
* 将碎片化文章目录(_posts)映射为对应的侧边栏配置数据
* @param {String} root
*/
function mapTocToPostSidebar(root) {
let postSidebar = [] // 碎片化文章数据
const files = fs.readdirSync(root); // 读取目录(文件和文件夹),返回数组
files.forEach(filename => {
const file = path.resolve(root, filename); // 方法:将路径或路径片段的序列解析为绝对路径
const stat = fs.statSync(file); // 文件信息
const fileNameArr = filename.split('.');
if (fileNameArr.length > 2) {
log(chalk.yellow(`warning: 该文件 "${file}" 在_posts文件夹中不应有序号且文件名中间不应有'.'`))
return
}
if (stat.isDirectory()) { // 是文件夹目录
// log(chalk.yellow(`warning: 该目录 "${file}" 内文件无法生成侧边栏_posts文件夹里面不能有二级目录。`))
return
}
let [title, type] = filename.split('.');
if (type !== 'md') {
log(chalk.yellow(`warning: 该文件 "${file}" 非.md格式文件不支持该文件类型`))
return;
}
const contentStr = fs.readFileSync(file, 'utf8') // 读取md文件内容返回字符串
const { data } = matter(contentStr, {}) // 解析出front matter数据
const { permalink = '', titleTag = '' } = data || {}
if (data.title) {
title = data.title
}
const item = [filename, title, permalink]
if (titleTag) {
item.push(titleTag)
}
postSidebar.push(item); // [<路径>, <标题>, <永久链接>, <?标题标签>]
})
return postSidebar
}
/**
* 将目录映射为对应的侧边栏配置数据
* @param {String} root
* @param {Boolean} collapsable
* @param {String} prefix
*/
function mapTocToSidebar(root, collapsable, prefix = '') {
let sidebar = []; // 结构化文章侧边栏数据
const files = fs.readdirSync(root); // 读取目录(文件和文件夹),返回数组
files.forEach(filename => {
const file = path.resolve(root, filename); // 方法:将路径或路径片段的序列解析为绝对路径
const stat = fs.statSync(file); // 文件信息
if (filename === '.DS_Store') { // 过滤.DS_Store文件
return
}
// let [order, title, type] = filename.split('.');
const fileNameArr = filename.split('.')
const isDir = stat.isDirectory()
let order = '', title = '', type = '';
if (fileNameArr.length === 2) {
order = fileNameArr[0];
title = fileNameArr[1];
} else {
const firstDotIndex = filename.indexOf('.');
const lastDotIndex = filename.lastIndexOf('.');
order = filename.substring(0, firstDotIndex);
type = filename.substring(lastDotIndex + 1);
if (isDir) {
title = filename.substring(firstDotIndex + 1);
} else {
title = filename.substring(firstDotIndex + 1, lastDotIndex);
}
}
order = parseInt(order, 10);
if (isNaN(order) || order < 0) {
log(chalk.yellow(`warning: 该文件 "${file}" 序号出错,请填写正确的序号`))
return;
}
if (sidebar[order]) { // 判断序号是否已经存在
log(chalk.yellow(`warning: 该文件 "${file}" 的序号在同一级别中重复出现,将会被覆盖`))
}
if (isDir) { // 是文件夹目录
sidebar[order] = {
title,
collapsable, // 是否可折叠默认true
children: mapTocToSidebar(file, collapsable, prefix + filename + '/').sidebar // 子栏路径添加前缀
}
} else { // 是文件
if (type !== 'md') {
log(chalk.yellow(`warning: 该文件 "${file}" 非.md格式文件不支持该文件类型`))
return;
}
const contentStr = fs.readFileSync(file, 'utf8') // 读取md文件内容返回字符串
const { data } = matter(contentStr, {}) // 解析出front matter数据
const { permalink = '', titleTag = '' } = data || {}
// 目录页对应的永久链接,用于给面包屑提供链接
const { pageComponent } = data
if (pageComponent && pageComponent.name === "Catalogue") {
catalogueData[title] = permalink
}
if (data.title) {
title = data.title
}
const item = [prefix + filename, title, permalink]
if (titleTag) item.push(titleTag)
sidebar[order] = item; // [<路径>, <标题>, <永久链接>, <?标题标签>]
}
})
sidebar = sidebar.filter(item => item !== null && item !== undefined);
return {
sidebar,
catalogueData
};
}