Diy万能博客模板js脚本【静态博客】
· 阅读需 7 分钟
静态博客工具,一般都使用Markdown
文件。那么Front-Matter
这些重复的内容就可以使用工具来生成,大部分静态博客工具都支持插件来生成博客文件。
比如:hexo 的 new 命令:
$ hexo new [layout] <title>
新建一篇文章。 如果没有设置 layout
的话,默认使用 _config.yml 中的 default_layout
参数代替。 Use the layout draft
to create a draft. 如果标题包含空格的话,请使用引号括起来。
选项 | 描述 |
---|---|
-p , --path | 文章的路径。 自定义文章的路径。 |
-r , --replace | 如果存在的话,替换当前的文章。 |
-s , --slug | 文章别名。 自定义文章的 URL。 |
只要在nodejs环境下,就可以通过脚本来完整这件事。无论用的是哪种的构建工具。
脚本的执行流程:
- 接收用户参数,用来创建哪类模板;
- 根据已有模版,填充模版中的内容,然后创建markdown文件。
所以我们需要一些操作markdown的相关工具:gray-matter 、日期工具、id工具等。
新建脚本文件
newBlog-test.js
首先接收用户参数
// 执行自定义命令
const runNpmScript = async () => {
const userInput = await getUserInput();
const scriptName = userInput.toLowerCase().replace('命令', 'command');
switch (scriptName) {
case '1':
console.log('命令1');
break;
case '2':
console.log('命令2');
break;
default:
console.log('无效的命令');
}
};
// 入口
runNpmScript();
执行脚本:
请选择一个模板^_^:(1:默认;2:电影):1
命令1
读取并修改模板文件
从指定位置加载模板文件。
这里我们需要从指定的模板文件夹位置读取到模板文件,然后再自定义替换里面的内容。
假设我们的模板文件在目录 blog/template
下
模板内容:
---
draft: true
slug: draft
title: XXX
authors: [lichlaughing]
tags:
- 生活日常
- 软件工具
- 技术笔记
keywords: [blog]
image: https://via.placeholder.com/1920x1080
description: XXX
---
测试 1234
操作脚本:
// 默认模板
const newBlog_default = () => {
const blogDir = 'blog';
const templateFilePath = path.join(__dirname, 'blog/template/template_default.md');
const targetPath = path.join(__dirname, blogDir + '/' + dayjs().format('YYYY/MM'));
const targetFilePath = targetPath + '/' + dayjs().format('YYYY-MM-DD') + '-XXX.md';
// 检查目录是否存在
fs.access(targetPath, fs.constants.F_OK, err => {
if (err) {
// 目录不存在
fs.mkdir(targetPath, { recursive: true }, err => {
if (err) {
console.error('创建目录时发生错误:', err);
} else {
console.log('目录创建成功:', targetPath);
}
});
} else {
// 目录存在
console.log('目录已存在', targetPath);
}
});
// 读取源文件
fs.readFile(templateFilePath, 'utf8', (err, fileContents) => {
if (err) {
console.error('读取模板时发生错误:', templateFilePath, err);
return;
}
// 解析front matter
const { data: frontMatter, content } = matter(fileContents);
const slug = nanoid(12);
frontMatter.slug = slug;
frontMatter.date = nowDateStr;
frontMatter.image = '/img/cover/' + dayjs().format('YYYY') + '/' + slug + '-cover.webp';
// 重新组合文件内容和更新后的front matter
const newFileContent = matter.stringify(content, frontMatter);
fs.writeFile(targetFilePath, newFileContent, 'utf8', err => {
if (err) {
console.error('模板读取写入失败:', err);
return;
}
console.log('模板读取并写入成功^_^');
});
});
};
自定义命令
最后把读取命令和操作模板串起来就行了。
/**
* 根据模板新建博客
*/
const fs = require('fs');
const path = require('path');
const dayjs = require('dayjs');
const matter = require('gray-matter');
const { nanoid } = require('nanoid');
const nowDateStr = dayjs().format('YYYY-MM-DD HH:mm:ss');
// 接收用户输入
const getUserInput = () => {
return new Promise(resolve => {
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
readline.question('请选择一个模板^_^:(1:默认;2:电影):', input => {
readline.close();
resolve(input.trim());
});
});
};
// 执行自定义命令
const runNpmScript = async () => {
const userInput = await getUserInput();
const scriptName = userInput.toLowerCase().replace('命令', 'command');
switch (scriptName) {
case '1':
newBlog_default();
break;
case '2':
newBlog_moive();
console.log('命令2');
break;
default:
console.log('无效的命令');
}
};
// 默认模板
const newBlog_default = () => {
const blogDir = 'blog';
const templateFilePath = path.join(__dirname, 'blog/template/template_default.md');
const targetPath = path.join(__dirname, blogDir + '/' + dayjs().format('YYYY/MM'));
const targetFilePath = targetPath + '/' + dayjs().format('YYYY-MM-DD') + '-XXX.md';
// 检查目录是否存在
fs.access(targetPath, fs.constants.F_OK, err => {
if (err) {
// 目录不存在
fs.mkdir(targetPath, { recursive: true }, err => {
if (err) {
console.error('创建目录时发生错误:', err);
} else {
console.log('目录创建成功:', targetPath);
}
});
} else {
// 目录存在
console.log('目录已存在', targetPath);
}
});
// 读取源文件
fs.readFile(templateFilePath, 'utf8', (err, fileContents) => {
if (err) {
console.error('读取模板时发生错误:', templateFilePath, err);
return;
}
// 解析front matter
const { data: frontMatter, content } = matter(fileContents);
const slug = nanoid(12);
frontMatter.slug = slug;
frontMatter.date = nowDateStr;
frontMatter.image = '/img/cover/' + dayjs().format('YYYY') + '/' + slug + '-cover.webp';
// 重新组合文件内容和更新后的front matter
const newFileContent = matter.stringify(content, frontMatter);
fs.writeFile(targetFilePath, newFileContent, 'utf8', err => {
if (err) {
console.error('模板读取写入失败:', err);
return;
}
console.log('模板读取并写入成功^_^');
});
});
};
// 电影模板
const newBlog_moive = () => {
const blogDir = 'blog';
const templateFilePath = path.join(__dirname, 'blog/template/template_moive.md');
const targetPath = path.join(__dirname, blogDir + '/' + dayjs().format('YYYY/MM'));
const targetFilePath = targetPath + '/' + dayjs().format('YYYY-MM-DD') + '-电影-XXX.md';
// 检查目录是否存在
fs.access(targetPath, fs.constants.F_OK, err => {
if (err) {
// 目录不存在
fs.mkdir(targetPath, { recursive: true }, err => {
if (err) {
console.error('创建目录时发生错误:', err);
} else {
console.log('目录创建成功:', targetPath);
}
});
} else {
// 目录存在
console.log('目录已存在', targetPath);
}
});
// 读取源文件
fs.readFile(templateFilePath, 'utf8', (err, fileContents) => {
if (err) {
console.error('读取模板时发生错误:', templateFilePath, err);
return;
}
// 解析front matter
const { data: frontMatter, content } = matter(fileContents);
frontMatter.slug = nanoid(12);
frontMatter.date = nowDateStr;
// 重新组合文件内容和更新后的front matter
const newFileContent = matter.stringify(content, frontMatter);
fs.writeFile(targetFilePath, newFileContent, 'utf8', err => {
if (err) {
console.error('模板读取写入失败:', err);
return;
}
console.log('模板读取并写入成功^_^');
});
});
};
// 入口
runNpmScript();
在 package.json
中注册命令:
{
"scripts": {
"nblog": "node newBlog-test.js",
},
}
执行命令:
npm run nblog
请选择一个模板^_^:(1:默认;2:算法;3:工具;4:阅读):
小结
依赖的组件:
- fs
- path
- dayjs
- nanoid
- gray-matter