代码优化
This commit is contained in:
parent
e4c5a6ffa9
commit
bf577d2905
17
README.MD
17
README.MD
|
|
@ -1,8 +1,15 @@
|
|||
# Evan Blog —— web前端技术博客
|
||||
|
||||
## 介绍
|
||||
## 简介
|
||||
|
||||
使用 [VuePress](https://v1.vuepress.vuejs.org/zh/guide/) 构建 SEO 友好的静态博客站。内置 `deploy.sh` 和 [GitHub Action](https://github.com/features/actions) 两种自动部署脚本,一键发布到 GitHub Pages。
|
||||
使用 [VuePress](https://v1.vuepress.vuejs.org/zh/guide/) 构建静态博客站。内置 `deploy.sh` 和 [GitHub Actions](https://github.com/features/actions) 两种自动部署脚本,一键发布到 GitHub Pages 或 国内访问速度更快的Coding Pages。还内置了自动百度链接推送,以及结合GitHub Actions[每天定时推送](https://github.com/xugaoyi/blog/blob/master/.github/workflows/baiduPush.yml)
|
||||
|
||||
* **简洁至上**
|
||||
* 继承了[VuePress](https://v1.vuepress.vuejs.org/zh/guide/) 简洁至上的特性,以 Markdown 为中心的项目结构,让你专注于写作
|
||||
* **高自动化**
|
||||
* 项目结合了各种自动化技术,[自动生成侧边栏](https://github.com/xugaoyi/blog/issues/113),自动部署,自动百度链接推送,每天定时百度链接推送
|
||||
* **SEO友好**
|
||||
* 让你的博客给更多人看到
|
||||
|
||||
|
||||
|
||||
|
|
@ -236,11 +243,7 @@ echo 'evanblogweb.com' > CNAME # // 域名替换成你的
|
|||
|
||||
|
||||
|
||||
## 提示
|
||||
|
||||
#### md文件的yaml代码
|
||||
|
||||
必须放在 md 文件在最上方才能生效
|
||||
## 其他
|
||||
|
||||
|
||||
#### 百度自动推送和统计
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ module.exports = {
|
|||
|
||||
"/01.前端/": [{"title":"JavaScript","collapsable":false,"children":[["01.JavaScript/01.JavaScript中的名词概念.md","JavaScript中的名词概念"],["01.JavaScript/02.数据类型转换.md","数据类型转换"],["01.JavaScript/03.ES5面向对象.md","ES5面向对象"],["01.JavaScript/04.ES6面向对象.md","ES6面向对象"],["01.JavaScript/05.new命令原理.md","new命令原理"],["01.JavaScript/06.多种数组去重性能对比.md","多种数组去重性能对比"]]}],
|
||||
|
||||
"/02.页面/": [{"title":"html-css","collapsable":false,"children":[["01.html-css/00.flex布局语法.md","flex布局语法"],["01.html-css/01.flex布局案例-基础.md","flex布局案例-基础"],["01.html-css/02.flex布局案例-骰子.md","flex布局案例-骰子"],["01.html-css/03.flex布局案例-网格布局.md","flex布局案例-网格布局"],["01.html-css/04.flex布局案例-圣杯布局.md","flex布局案例-圣杯布局"],["01.html-css/05.flex布局案例-输入框布局.md","flex布局案例-输入框布局"],["01.html-css/06.CSS3之transform过渡.md","CSS3之transform过渡"],["01.html-css/07.CSS3之animation动画.md","CSS3之animation动画"]]}],
|
||||
"/02.页面/": [{"title":"html-css","collapsable":false,"children":[["01.html-css/01.flex布局语法.md","flex布局语法"],["01.html-css/02.flex布局案例-基础.md","flex布局案例-基础"],["01.html-css/03.flex布局案例-骰子.md","flex布局案例-骰子"],["01.html-css/04.flex布局案例-圣杯布局.md","flex布局案例-圣杯布局"],["01.html-css/05.flex布局案例-网格布局.md","flex布局案例-网格布局"],["01.html-css/06.flex布局案例-输入框布局.md","flex布局案例-输入框布局"],["01.html-css/07.CSS3之transform过渡.md","CSS3之transform过渡"],["01.html-css/08.CSS3之animation动画.md","CSS3之animation动画"]]}],
|
||||
|
||||
"/03.技术杂谈/": [{"title":"技术杂谈","collapsable":false,"children":[["01.技术杂谈/01.Git使用手册.md","Git使用手册"],["01.技术杂谈/02.GitHub高级搜索技巧.md","GitHub高级搜索技巧"],["01.技术杂谈/03.Markdown使用教程.md","Markdown使用教程"],["01.技术杂谈/04.npm常用命令.md","npm常用命令"],["01.技术杂谈/05.yaml语言教程.md","yaml语言教程"],["01.技术杂谈/06.解决百度无法收录搭建在GitHub上的个人博客的问题.md","解决百度无法收录搭建在GitHub上的个人博客的问题"],["01.技术杂谈/07.使用Gitalk实现静态博客无后台评论系统.md","使用Gitalk实现静态博客无后台评论系统"]]}],
|
||||
"/03.技术杂谈/": [{"title":"技术","collapsable":false,"children":[["01.技术/01.Git使用手册.md","Git使用手册"],["01.技术/02.Markdown使用教程.md","Markdown使用教程"],["01.技术/03.npm常用命令.md","npm常用命令"],["01.技术/04.yaml语言教程.md","yaml语言教程"]]},{"title":"GitHub","collapsable":false,"children":[["02.GitHub/01.GitHub高级搜索技巧.md","GitHub高级搜索技巧"]]},{"title":"Nodejs","collapsable":false,"children":[["03.Nodejs/01.nodejs递归读取所有文件.md","nodejs递归读取所有文件"]]},{"title":"博客搭建","collapsable":false,"children":[["04.博客搭建/01.解决百度无法收录搭建在GitHub上的个人博客的问题.md","解决百度无法收录搭建在GitHub上的个人博客的问题"],["04.博客搭建/02.使用Gitalk实现静态博客无后台评论系统.md","使用Gitalk实现静态博客无后台评论系统"]]}],
|
||||
|
||||
"/04.其他/": [{"title":"学习","collapsable":false,"children":[["01.学习/01.学习网站.md","学习网站"],["01.学习/02.学习效率低,忘性很大怎么办?.md","学习效率低,忘性很大怎么办?"]]},{"title":"学习笔记","collapsable":false,"children":[["02.学习笔记/01.小程序笔记.md","小程序笔记"]]},{"title":"面试","collapsable":false,"children":[["03.面试/01.面试问题集锦.md","面试问题集锦"]]},["04.在线工具.md","在线工具"],["05.友情链接.md","友情链接"]],
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
title: nodejs递归读取所有文件
|
||||
date: 2019-12-26
|
||||
permalink: /pages/117708e0af7f0bd9
|
||||
---
|
||||
# nodejs递归读取所有文件
|
||||
```js
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
function readFileList(dir, filesList = []) {
|
||||
const files = fs.readdirSync(dir);
|
||||
console.log(files);
|
||||
files.forEach((item, index) => {
|
||||
var fullPath = path.join(dir, item);
|
||||
const stat = fs.statSync(fullPath);
|
||||
if (stat.isDirectory()) {
|
||||
readFileList(path.join(dir, item), filesList); //递归读取文件
|
||||
} else {
|
||||
filesList.push(fullPath);
|
||||
}
|
||||
});
|
||||
return filesList;
|
||||
}
|
||||
|
||||
var filesList = [];
|
||||
readFileList(__dirname,filesList);
|
||||
```
|
||||
|
||||
|
|
@ -7,15 +7,15 @@ tagline: web前端技术博客,积跬步以至千里,致敬每个爱学习
|
|||
features:
|
||||
- title: 前端
|
||||
details: JavaScript、ES6、vue框架等相关技术
|
||||
url: /web/JavaScript/01.JavaScript中的名词概念
|
||||
url: /pages/70d1485bb4e5754b/
|
||||
imgname: /img/web.png
|
||||
- title: 页面
|
||||
details: html(5)/css(3),前端页面相关技术
|
||||
url: /ui/00.flex布局语法
|
||||
url: /pages/0a83b083bdf257cb/
|
||||
imgname: /img/ui.png
|
||||
- title: 技术杂谈
|
||||
details: 技术文档、教程、技巧、学习笔记等
|
||||
url: /other/git
|
||||
url: /pages/9a7ee40fc232253e/
|
||||
imgname: /img/other.png
|
||||
footer: Copyright © 2019-present evanblog
|
||||
---
|
||||
|
|
@ -23,36 +23,37 @@ footer: Copyright © 2019-present evanblog
|
|||
## :earth_americas:前端
|
||||
|
||||
* JavaScript
|
||||
* [ES6面向对象](web/JavaScript/04.ES6面向对象)
|
||||
* [new命令原理](web/JavaScript/05.new命令原理)
|
||||
* [多种数组去重性能对比](web/JavaScript/06.多种数组去重性能对比)
|
||||
* [更多... 👉](web/JavaScript/01.JavaScript中的名词概念)
|
||||
* [ES6面向对象](/pages/1f4123be6f45abcd/)
|
||||
* [new命令原理](/pages/8143cc480faf9a11/)
|
||||
* [多种数组去重性能对比](/pages/e808fba1fa8fbab2/)
|
||||
* [更多... 👉](/pages/70d1485bb4e5754b/)
|
||||
|
||||
## 🎨 页面
|
||||
* HTML/CSS
|
||||
* [flex布局语法](ui/00.flex布局语法)
|
||||
* [flex布局案例-圣杯布局](ui/04.flex布局案例-圣杯布局)
|
||||
* [CSS3之animation动画](ui/07.CSS3之animation动画)
|
||||
* [更多... 👉](ui/00.flex布局语法)
|
||||
* [flex布局语法](/pages/0a83b083bdf257cb/)
|
||||
* [flex布局案例-圣杯布局](/pages/df9e7c7214fa5046/)
|
||||
* [CSS3之animation动画](/pages/c2c0432138f6e042/)
|
||||
* [更多... 👉](/pages/0a83b083bdf257cb/)
|
||||
|
||||
|
||||
|
||||
## :bulb:技术杂谈
|
||||
|
||||
* 技术
|
||||
* [Git使用文档](other/git)
|
||||
* [GitHub高级搜索技巧](other/github)
|
||||
* [Markdown使用教程](other/markdown)
|
||||
* [更多... 👉](other/git)
|
||||
* [Git使用手册](/pages/9a7ee40fc232253e/)
|
||||
* [GitHub高级搜索技巧](/pages/4c778760be26d8b3/)
|
||||
* [Markdown使用教程](/pages/ad247c4332211551/)
|
||||
* [解决百度无法收录搭建在GitHub上的静态博客的问题](/pages/41f87d890d0a02af/)
|
||||
* [使用Gitalk实现静态博客无后台评论系统](/pages/1da0bf9a988eafe5/)
|
||||
* [更多... 👉](/pages/9a7ee40fc232253e/)
|
||||
* 学习
|
||||
* [学习效果低,忘性很大怎么办?](other/LearningAndMemory)
|
||||
* [学习网站分享](other/study)
|
||||
* [学习网站分享](/pages/2e9ba3fa6e1ed0e9/)
|
||||
* [学习效果低,忘性很大怎么办?](/pages/839158575e5c4866/)
|
||||
* 面试
|
||||
* [面试问题集锦](other/interview)
|
||||
* [面试问题集锦](/pages/aea6571b7a8bae86/)
|
||||
* 其他
|
||||
* [在线工具](other/utils)
|
||||
* [在线工具](/pages/9c2232288caaa8ec/)
|
||||
* [关于本博客搭建](https://github.com/xugaoyi/evanblog)
|
||||
* [解决百度无法收录搭建在GitHub上的个人博客的问题](other/baidushoulu)
|
||||
|
||||
## :email: 联系
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
"name": "evanblog",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev": "node utils/frontmatter.js && node utils/sidebarAndNav.js && vuepress dev docs",
|
||||
"build": "node utils/frontmatter.js && node utils/sidebarAndNav.js && vuepress build docs",
|
||||
"dev": "node utils/frontmatter.js && node utils/sidebar.js && vuepress dev docs",
|
||||
"build": "node utils/frontmatter.js && node utils/sidebar.js && vuepress build docs",
|
||||
"deploy": "bash deploy.sh",
|
||||
"updateFM": "node utils/frontmatter.js -update"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
/**
|
||||
* 百度链接推送文件生成
|
||||
* 生成百度链接推送文件
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const MD5 = require('md5.js');
|
||||
|
||||
const { readFileList, docsRoot, PREFIX } = require('./frontmatter');
|
||||
const readFileList = require('./modules/readFileList');
|
||||
const urlsRoot = path.join(__dirname, '..', 'urls.txt'); // 百度链接推送文件
|
||||
|
||||
const DOMAIN = 'https://evanblogweb.com'
|
||||
|
|
@ -17,9 +16,9 @@ main();
|
|||
*/
|
||||
function main() {
|
||||
fs.writeFileSync(urlsRoot, DOMAIN)
|
||||
const files = readFileList(docsRoot); // 读取所有md文件
|
||||
const files = readFileList(); // 读取所有md文件数据
|
||||
files.forEach( file => {
|
||||
const link = `\r\n${DOMAIN}${PREFIX}${new MD5().update(file.name).digest('hex').substring(0,16)}/`;
|
||||
const link = `\r\n${DOMAIN}${file.permalink}/`;
|
||||
console.log(link);
|
||||
fs.appendFileSync(urlsRoot, link);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
/**
|
||||
* nodejs自动生成永久链接
|
||||
* 生成frontmatter (标题、日期、永久链接)
|
||||
*/
|
||||
const fs = require('fs'); // 文件模块
|
||||
const path = require('path'); // 路径模块
|
||||
const logger = require('tracer').colorConsole(); // 控制台工具(用于控制台打印信息包含时间、打印类型、文件及代码行号、对象、颜色)
|
||||
const MD5 = require('md5.js');
|
||||
const arg = process.argv.splice(2)[0]; // 获取命令行 传入参数
|
||||
|
||||
const docsRoot = path.join(__dirname, '..', 'docs'); // docs文件路径
|
||||
const PREFIX = '/pages/'; // 链接前缀
|
||||
const readFileList = require('./modules/readFileList');
|
||||
|
||||
main();
|
||||
|
||||
|
|
@ -16,7 +12,7 @@ main();
|
|||
* 主体函数
|
||||
*/
|
||||
function main() {
|
||||
const files = readFileList(docsRoot); // 读取所有md文件
|
||||
const files = readFileList(); // 读取所有md文件数据
|
||||
|
||||
files.forEach(file => {
|
||||
let dataStr = fs.readFileSync(file.filePath, 'utf8');// 读取每个md文件内容
|
||||
|
|
@ -48,8 +44,7 @@ function writeFrontMatter(file, dataStr) {
|
|||
const stat = fs.statSync(file.filePath);
|
||||
const date = stat.birthtime; // 创建时间
|
||||
const dateStr = `${date.getFullYear()}-${zero(date.getMonth()+1)}-${zero(date.getDate())}`;
|
||||
const permalink = `${PREFIX}${new MD5().update(file.name).digest('hex').substring(0,16)}`;
|
||||
const newData = `---\r\ntitle: ${file.name}\r\ndate: ${dateStr}\r\npermalink: ${permalink}\r\n---\r\n` + dataStr;
|
||||
const newData = `---\r\ntitle: ${file.name}\r\ndate: ${dateStr}\r\npermalink: ${file.permalink}\r\n---\r\n` + dataStr;
|
||||
fs.writeFileSync(file.filePath, newData); // 写入
|
||||
}
|
||||
|
||||
|
|
@ -57,53 +52,3 @@ function writeFrontMatter(file, dataStr) {
|
|||
function zero(d){
|
||||
return d.toString().padStart(2,'0')
|
||||
}
|
||||
|
||||
|
||||
// 读取所有md文件
|
||||
function readFileList(dir, filesList = []) {
|
||||
const files = fs.readdirSync(dir);
|
||||
files.forEach((item, index) => {
|
||||
let filePath = path.join(dir, item);
|
||||
const stat = fs.statSync(filePath);
|
||||
if (stat.isDirectory() && item !== '.vuepress') {
|
||||
readFileList(path.join(dir, item), filesList); //递归读取文件
|
||||
} else {
|
||||
if(path.basename(dir) !== 'docs'){ // 过滤docs目录级下的文件
|
||||
// 过滤非md文件
|
||||
let [, name, type] = path.basename(filePath).split('.');
|
||||
if(type === 'md'){
|
||||
filesList.push({
|
||||
name,
|
||||
filePath
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return filesList;
|
||||
}
|
||||
|
||||
// 抛出给baiduPush.js调用
|
||||
module.exports = {
|
||||
readFileList,
|
||||
docsRoot,
|
||||
PREFIX
|
||||
};
|
||||
|
||||
/**
|
||||
* 读取指定目录下的文件绝对路径
|
||||
* @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') { // 是否为文件夹目录,并排除.vuepress文件
|
||||
// result.push(file);
|
||||
// }
|
||||
// })
|
||||
// return result;
|
||||
// }
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
const {readdir, readFile, writeFile} = require('fs')
|
||||
// const {resolve} = require('path')
|
||||
|
||||
// const FOLDERPATH = './docs/article'
|
||||
const PathsIn = [
|
||||
'./docs/web/',
|
||||
'./docs/python/',
|
||||
'./docs/other/'
|
||||
]
|
||||
|
||||
function pReadFile(filepath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
readdir(filepath, (err, files) => {
|
||||
let filenames = []
|
||||
files.forEach(file => {
|
||||
if (file.toLowerCase() === 'readme.md') {
|
||||
file = ``
|
||||
} else {
|
||||
file = file.replace('.md', '')
|
||||
file = `${file}`
|
||||
}
|
||||
filenames.push(file)
|
||||
})
|
||||
|
||||
filenames.sort() // 排序
|
||||
resolve(filenames)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Promise.all([
|
||||
pReadFile(PathsIn[0]),
|
||||
pReadFile(PathsIn[1]),
|
||||
pReadFile(PathsIn[2])
|
||||
]).then(
|
||||
arr => {
|
||||
console.log(arr)
|
||||
var params = {
|
||||
'/web/': arr[0],
|
||||
'/python/': arr[1],
|
||||
'/other/': arr[2]
|
||||
}
|
||||
writeJson(params)
|
||||
},
|
||||
err => console.log(err)
|
||||
)
|
||||
|
||||
function writeJson(params) {
|
||||
//现将json文件读出来
|
||||
readFile('./docs/.vuepress/config/sidebar.json', function(err, data) {
|
||||
if (err) {
|
||||
return console.error(err)
|
||||
}
|
||||
var person = data.toString() //将二进制的数据转换为字符串
|
||||
|
||||
person = JSON.parse(person) //将字符串转换为json对象
|
||||
// person['/article_child/'] = params['/article_child/']
|
||||
for (let key in params) {
|
||||
person[key] = params[key]
|
||||
}
|
||||
console.log(person)
|
||||
var str = JSON.stringify(person) //因为nodejs的写入文件只认识字符串或者二进制数,所以把json对象转换成字符串重新写入json文件中
|
||||
writeFile('./docs/.vuepress/config/sidebar.json', str, function(err) {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
}
|
||||
console.log('----------新增成功-------------')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* 读取所有md文件数据
|
||||
*/
|
||||
const fs = require('fs'); // 文件模块
|
||||
const path = require('path'); // 路径模块
|
||||
const MD5 = require('md5.js');
|
||||
const docsRoot = path.join(__dirname, '..', '..', 'docs'); // docs文件路径
|
||||
|
||||
const PREFIX = '/pages/'; // 链接前缀
|
||||
|
||||
function readFileList(dir = docsRoot, filesList = []) {
|
||||
const files = fs.readdirSync(dir);
|
||||
files.forEach( (item, index) => {
|
||||
let filePath = path.join(dir, item);
|
||||
const stat = fs.statSync(filePath);
|
||||
if (stat.isDirectory() && item !== '.vuepress') {
|
||||
readFileList(path.join(dir, item), filesList); //递归读取文件
|
||||
} else {
|
||||
if(path.basename(dir) !== 'docs'){ // 过滤docs目录级下的文件
|
||||
let [order, name, type] = path.basename(filePath).split('.');
|
||||
order = parseInt(order, 10);
|
||||
if(type === 'md'){ // 过滤非md文件
|
||||
filesList.push({
|
||||
order,
|
||||
name,
|
||||
filePath,
|
||||
permalink: PREFIX + new MD5().update(name).digest('hex').substring(0,16) // 永久链接
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return filesList;
|
||||
}
|
||||
|
||||
module.exports = readFileList;
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 生成导航栏数据
|
||||
*/
|
||||
|
||||
// 思路:从sidebar.js中抽离一套获取目录文件结构树的代码,然后共用这块代码,对返回的数据做二次处理,分别产出侧边栏、导航栏、百度链接推送、首页内部链接数据。
|
||||
// 考虑:需要对导航和首页内链接做个性化处理,暂时不做自动化生成。
|
||||
|
||||
// const fs = require('fs');
|
||||
// const path = require('path');
|
||||
|
||||
// const readFileList = require('./modules/readFileList');
|
||||
// const navPath = path.join(__dirname, '..', 'docs', '.vuepress', 'config', 'nav-auto.js'); // 导航栏js文件要保存的路径
|
||||
|
||||
// main();
|
||||
|
||||
|
||||
|
||||
// /**
|
||||
// * 主体函数
|
||||
// */
|
||||
// function main() {
|
||||
// let navArr = [{text: '首页', link: '/'}];
|
||||
// const files = readFileList(); // 读取所有md文件数据
|
||||
// files.forEach( file => {
|
||||
// //if (file.order === 1) {
|
||||
// //console.log(file.filePath.split('\\'))
|
||||
// //}
|
||||
// })
|
||||
|
||||
// }
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* 生成侧边栏数据
|
||||
*/
|
||||
|
||||
const fs = require('fs'); // 文件模块
|
||||
const path = require('path'); // 路径模块
|
||||
const ejs = require('ejs'); // ejs模板引擎
|
||||
const logger = require('tracer').colorConsole(); // 控制台工具(用于控制台打印信息包含时间、打印类型、文件及代码行号、对象、颜色)
|
||||
|
||||
const docsRoot = path.join(__dirname, '..', 'docs'); // docs文件路径
|
||||
const sidebarPath = path.join(__dirname, '..', 'docs', '.vuepress', 'config', 'sidebar-auto.js'); // 侧边栏js文件要保存的路径
|
||||
|
||||
|
||||
// sidebar-auto.js代码模板
|
||||
const sidebarTemplate = `
|
||||
// 侧边栏自动生成
|
||||
module.exports = {
|
||||
<% for (let item of sidebarData) { %>
|
||||
"<%- item.path %>": <%- JSON.stringify(item.sidebarArr) %>,
|
||||
<% } %>
|
||||
}`;
|
||||
|
||||
main();
|
||||
|
||||
/**
|
||||
* 主体函数
|
||||
*/
|
||||
function main() {
|
||||
const sidebarData = [];
|
||||
|
||||
const tocs = readTocs(docsRoot); // 得到一个对路路径目录数组
|
||||
tocs.forEach(toc => { // toc为每个目录的绝对路径
|
||||
const sidebarArr = mapTocToSidebar(toc);
|
||||
if (!sidebarArr.length) {
|
||||
logger.warn(`该目录 "${toc}" 内部没有任何文件,将忽略生成对应侧边栏`);
|
||||
return;
|
||||
}
|
||||
sidebarData.push({
|
||||
path: `/${path.basename(toc)}/`, // basename返回绝对路径的文件名
|
||||
// name: path.basename(toc).replace(/ /g, '_'), // 替换空格
|
||||
sidebarArr
|
||||
})
|
||||
})
|
||||
|
||||
const sidebarDataTem = ejs.render(sidebarTemplate, { sidebarData });
|
||||
fs.writeFileSync(sidebarPath, sidebarDataTem); // 同步写入文件, 参数一:写入到的文件, 参数二:写入的数据
|
||||
logger.info('侧边栏生成成功!')
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取指定目录下的文件绝对路径
|
||||
* @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') { // 是否为文件夹目录,并排除.vuepress文件
|
||||
result.push(file);
|
||||
}
|
||||
})
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 将对应目录映射为对应的侧边栏配置
|
||||
* @param {String} root
|
||||
* @param {String} prefix
|
||||
*/
|
||||
function mapTocToSidebar(root, prefix){
|
||||
prefix = prefix || '';
|
||||
let sidebar = [];
|
||||
const files = fs.readdirSync(root); // 读取目录(文件和文件夹),返回数组
|
||||
files.forEach(filename => {
|
||||
const file = path.resolve(root, filename); // 方法:将路径或路径片段的序列解析为绝对路径
|
||||
const stat = fs.statSync(file); // 文件信息
|
||||
let [order, title, type] = filename.split('.');
|
||||
order = parseInt(order, 10);
|
||||
if (isNaN(order) || order < 0) {
|
||||
logger.error(`该文件 "${file}" 序号出错,请填写正确的序号,序号约定请查看:https://github.com/xugaoyi/blog/issues/113`);
|
||||
return;
|
||||
}
|
||||
if (sidebar[order]) { // sidebar数组的order位置的数据的布尔值
|
||||
logger.warn(`该文件 "${file}" 的序号在同一级别中有重复出现,将会被覆盖`);
|
||||
}
|
||||
if(stat.isDirectory()){ // 是否为文件夹目录
|
||||
sidebar[order] = {
|
||||
title,
|
||||
collapsable: false,
|
||||
children: mapTocToSidebar(file, prefix + filename + '/') // 子栏路径添加前缀
|
||||
}
|
||||
} else { // 是文件
|
||||
if (type !== 'md') {
|
||||
// 控制台错误信息
|
||||
logger.error(`该文件 "${file}" 非md文件,不支持非md文件类型`);
|
||||
return;
|
||||
}
|
||||
sidebar[order] = [prefix + filename, title]; // [<前缀加完整文件名>, <文件标题>]
|
||||
}
|
||||
})
|
||||
|
||||
sidebar = sidebar.filter(item => item !== null && item !== undefined);
|
||||
return sidebar;
|
||||
}
|
||||
|
|
@ -1,251 +0,0 @@
|
|||
/**
|
||||
* nodejs自动生成侧边栏与导航栏
|
||||
*/
|
||||
|
||||
const fs = require('fs'); // 文件模块
|
||||
const path = require('path'); // 路径模块
|
||||
const ejs = require('ejs'); // ejs模板引擎
|
||||
const logger = require('tracer').colorConsole(); // 控制台工具(用于控制台打印信息包含时间、打印类型、文件及代码行号、对象、颜色)
|
||||
|
||||
const docsRoot = path.join(__dirname, '..', 'docs'); // docs文件路径
|
||||
const sidebarPath = path.join(__dirname, '..', 'docs', '.vuepress', 'config', 'sidebar-auto.js'); // 侧边栏js文件要保存的路径
|
||||
const navPath = path.join(__dirname, '..', 'docs', '.vuepress', 'config', 'nav-auto.js'); // 导航栏js文件要保存的路径
|
||||
|
||||
// sidebar-auto.js代码模板
|
||||
const sidebarTemplate = `
|
||||
// 侧边栏自动生成
|
||||
module.exports = {
|
||||
<% for (let item of sidebarData) { %>
|
||||
"<%- item.path %>": <%- JSON.stringify(item.sidebarArr) %>,
|
||||
<% } %>
|
||||
}`;
|
||||
// nav-auto.js代码模板
|
||||
const navTemplate = `
|
||||
// 导航栏自动生成
|
||||
module.exports = {
|
||||
{text: '首页', link: '/'},
|
||||
<% for (let item of navData) { %>
|
||||
{
|
||||
text: '<%- item.name %>',
|
||||
<% if (item.navArr) {%>
|
||||
items: [
|
||||
<% for (let i of item.xx) { %>
|
||||
{text: '<%- i.name %>', link: <%- i.link %>},
|
||||
<% } %>
|
||||
]
|
||||
<% } else { %>
|
||||
link: <%- item.link %>
|
||||
<% } %>
|
||||
},
|
||||
<% } %>
|
||||
}`;
|
||||
|
||||
main();
|
||||
|
||||
/**
|
||||
* 主体函数
|
||||
*/
|
||||
function main() {
|
||||
const sidebarData = [];
|
||||
const navData = [];
|
||||
|
||||
const tocs = readTocs(docsRoot); // 得到一个对路路径目录数组
|
||||
tocs.forEach(toc => { // toc为每个目录的绝对路径
|
||||
const sidebarArr = mapTocToSidebar(toc);
|
||||
|
||||
//const navArr = mapTocToNav(toc);
|
||||
//console.log(navArr)
|
||||
|
||||
if (!sidebarArr.length) {
|
||||
logger.warn(`该目录 "${toc}" 内部没有任何文件,将忽略生成对应侧边栏`);
|
||||
return;
|
||||
}
|
||||
sidebarData.push({
|
||||
path: `/${path.basename(toc)}/`, // basename返回绝对路径的文件名
|
||||
// name: path.basename(toc).replace(/ /g, '_'), // 替换空格
|
||||
sidebarArr
|
||||
})
|
||||
})
|
||||
|
||||
const sidebarDataTem = ejs.render(sidebarTemplate, { sidebarData });
|
||||
fs.writeFileSync(sidebarPath, sidebarDataTem); // 同步写入文件, 参数一:写入到的文件, 参数二:写入的数据
|
||||
logger.info('侧边栏生成成功!')
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取指定目录下的文件绝对路径
|
||||
* @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') { // 是否为文件夹目录,并排除.vuepress文件
|
||||
result.push(file);
|
||||
}
|
||||
})
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 将对应目录映射为对应的侧边栏配置
|
||||
* @param {String} root
|
||||
* @param {String} prefix
|
||||
*/
|
||||
function mapTocToSidebar(root, prefix){
|
||||
prefix = prefix || '';
|
||||
let sidebar = [];
|
||||
const files = fs.readdirSync(root); // 读取目录(文件和文件夹),返回数组
|
||||
files.forEach(filename => {
|
||||
const file = path.resolve(root, filename); // 方法:将路径或路径片段的序列解析为绝对路径
|
||||
const stat = fs.statSync(file); // 文件信息
|
||||
let [order, title, type] = filename.split('.');
|
||||
order = parseInt(order, 10);
|
||||
if (isNaN(order) || order < 0) {
|
||||
logger.error(`该文件 "${file}" 序号出错,请填写正确的序号,序号约定请查看:https://github.com/xugaoyi/blog`);
|
||||
return;
|
||||
}
|
||||
if (sidebar[order]) { // sidebar数组的order位置的数据的布尔值
|
||||
logger.warn(`该文件 "${file}" 的序号在同一级别中有重复出现,将会被覆盖`);
|
||||
}
|
||||
if(stat.isDirectory()){ // 是否为文件夹目录
|
||||
sidebar[order] = {
|
||||
title,
|
||||
collapsable: false,
|
||||
children: mapTocToSidebar(file, prefix + filename + '/') // 子栏路径添加前缀
|
||||
}
|
||||
} else { // 是文件
|
||||
if (type !== 'md') {
|
||||
// 控制台错误信息
|
||||
logger.error(`该文件 "${file}" 非md文件,不支持非md文件类型`);
|
||||
return;
|
||||
}
|
||||
sidebar[order] = [prefix + filename, title]; // [<前缀加完整文件名>, <文件标题>]
|
||||
}
|
||||
})
|
||||
|
||||
sidebar = sidebar.filter(item => item !== null && item !== undefined);
|
||||
return sidebar;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将对应目录映射导航
|
||||
* @param {String} root
|
||||
*/
|
||||
function mapTocToNav(root){
|
||||
let nav = [];
|
||||
|
||||
const prefix = path.basename(root); // basename返回绝对路径的文件名
|
||||
|
||||
let [order , text] = prefix.split('.');
|
||||
|
||||
order = parseInt(order, 10);
|
||||
|
||||
if (nav[order]) {
|
||||
logger.warn(
|
||||
`该序号 "${order}" 在同一级别中有重复出现,将会被覆盖`
|
||||
);
|
||||
}
|
||||
|
||||
const files = fs.readdirSync(root); // 方法:读取目录,返回数组
|
||||
if (files.length === 1) { // 只有一级导航
|
||||
let link = ''
|
||||
|
||||
const file = path.resolve(root, files[0]); // 方法:将路径或路径片段的序列解析为绝对路径
|
||||
const stat = fs.statSync(file); // 文件信息
|
||||
|
||||
if (stat.isDirectory()) { // 文件夹
|
||||
|
||||
const files2 = fs.readdirSync(file);
|
||||
if (!files2.length) {
|
||||
logger.warn(`该目录 "${file}" 内部没有任何文件,将忽略生成对应导航`);
|
||||
return;
|
||||
}
|
||||
link = `/${prefix}/${files}/${files2[0]}`
|
||||
|
||||
} else { // 文件
|
||||
|
||||
const type = files[0].split('.')[2];
|
||||
if( type === 'md'){
|
||||
link = `/${prefix}/${files}`
|
||||
} else if (type === 'txt') { // 外部链接
|
||||
|
||||
} else { // 非md、txt文件
|
||||
logger.error(`该文件 "${file}" 非md或txt文件,不支持该文件类型`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nav[order] = {
|
||||
text,
|
||||
link
|
||||
}
|
||||
} else if (files.length > 1) { // 二级导航
|
||||
nav[order] = {
|
||||
text,
|
||||
items: twoNav(files,)
|
||||
}
|
||||
} else {
|
||||
logger.warn(`该目录 "${root}" 内部没有任何文件,将忽略生成对应导航`);
|
||||
}
|
||||
|
||||
return nav;
|
||||
}
|
||||
|
||||
// 获取二级导航数据
|
||||
function twoNav(files){
|
||||
var items = [];
|
||||
files.forEach(file => {
|
||||
console.log(file)
|
||||
let [order, text, type] = file.split('.');
|
||||
|
||||
order = parseInt(order, 10);
|
||||
|
||||
if (items[order]) {
|
||||
logger.warn(
|
||||
`该序号 "${order}" 在同一级别中有重复出现,将会被覆盖`
|
||||
);
|
||||
}
|
||||
|
||||
if (type === 'md') {
|
||||
items[order] = {
|
||||
text,
|
||||
link: '/04.其他/01.学习/01.学习网站'
|
||||
}
|
||||
} else if (type === 'txt') { // 外部链接文件
|
||||
|
||||
} else if (type === undefined) { // 文件夹
|
||||
items[order] = {
|
||||
text,
|
||||
link: '/04.其他/01.学习/01.学习网站'
|
||||
}
|
||||
} else { // 其他文件
|
||||
logger.error(`该文件 "${file}" 非md或txt文件,不支持该文件类型`);
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
// files.forEach(file => {
|
||||
// const file2 = path.resolve(root, file); // 方法:将路径或路径片段的序列解析为绝对路径
|
||||
// const stat = fs.statSync(file2); // 文件信息
|
||||
// if (stat.isDirectory()) { // 文件夹
|
||||
// console.log(mapTocToNav(path.resolve(root, file)))
|
||||
// } else {
|
||||
|
||||
// }
|
||||
// })
|
||||
|
||||
// items: [
|
||||
// {text: '学习', link: '/04.其他/01.学习/01.学习网站'},
|
||||
// {text: '学习笔记', link: '/04.其他/02.学习笔记/01.小程序笔记'},
|
||||
// {text: '面试', link: '/04.其他/03.面试/01.面试问题集锦'},
|
||||
// {text: '在线工具', link: '/04.其他/04.在线工具'},
|
||||
// {text: '友情链接', link: '/04.其他/05.友情链接'},
|
||||
// ]
|
||||
|
||||
return items;
|
||||
}
|
||||
Loading…
Reference in New Issue