在您的 Hexo 博客项目中,您可能有大量的文章,每篇文章都可能定义了一个cover
字段来指定文章封面。随着时间的推移,您可能决定不再为文章设置封面,或者您想要使用随机图 API 来设置随机封面。这时候,手动编辑每个文件显然是不现实的。为了解决这个问题,您可以使用一个简单的 Node.js 脚本来自动化这个过程。
在这篇博客文章中,我将向您介绍一个为此目的而编写的 Node.js 脚本。这个脚本会遍历您的 Hexo 项目根目录下的source\_posts
文件夹,查找所有 Markdown 文件(.md
文件),并删除每个文件中的cover
字段后面的图片链接。
脚本功能概述
脚本的工作流程如下:
- 定位到 Hexo 项目根目录下的
source\_posts
文件夹。 - 遍历这个目录下的所有文件和子目录。
- 对于每个找到的 Markdown 文件,读取文件内容。
- 在文件内容中查找
cover
字段,并删除它后面的图片链接。 - 将修改后的内容写回到原文件中。
脚本细节分析
现在,我们来深入了解脚本的每个部分:
1. 导入 Node.js 模块
脚本首先导入了fs
(文件系统)和path
(路径操作)这两个 Node.js 核心模块,这是因为我们需要进行文件读写操作和路径操作。
const fs = require('fs');
const path = require('path');
2. 定义 _posts 目录的路径
接着,脚本定义了_posts
目录的路径,这个目录包含了所有的博客文章。
const postsDir = path.join(__dirname, 'source', '_posts');
3. 遍历目录的递归函数
脚本使用了一个名为walkDir
的递归函数来遍历指定目录下的所有文件和子目录。如果找到一个文件,并且它的扩展名是.md
,就会调用processMdFile
函数来处理这个 Markdown 文件。
function walkDir(dir, callback) {
fs.readdir(dir, (err, files) => {
if (err) {
console.error(`无法读取目录${dir}:`, err);
return;
}
files.forEach(file => {
const filePath = path.join(dir, file);
fs.stat(filePath, (err, stat) => {
if (err) {
console.error(`无法获取文件${file}的状态:`, err);
return;
}
if (stat.isDirectory()) {
walkDir(filePath, callback); // 递归遍历子目录
} else if (stat.isFile() && path.extname(file) === '.md') {
callback(filePath); // 找到.md文件,执行回调
}
});
});
});
}
4. 处理 Markdown 文件的函数
processMdFile
函数会读取 Markdown 文件,然后使用正则表达式查找和替换cover
字段。如果文件内容发生了变化,就会将新内容写回文件,并在控制台输出一个消息,说明文件已更新。
function processMdFile(filePath) {
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
console.error(`无法读取文件${filePath}:`, err);
return;
}
const modifiedData = data.replace(/(cover:).*/, '$1');
if (data !== modifiedData) {
fs.writeFile(filePath, modifiedData, 'utf8', (err) => {
if (err) {
console.error(`无法写入文件${filePath}:`, err);
return;
}
// 获取并输出相对于_posts目录的路径
const relativePath = path.relative(postsDir, filePath);
console.log(`已更新:“${relativePath}”`);
});
}
});
}
5. 开始执行脚本
最后,脚本调用walkDir
函数开始遍历_posts
目录,并为每个 Markdown 文件调用processMdFile
函数。
walkDir(postsDir, processMdFile);
完整脚本
const fs = require('fs');
const path = require('path');
// 定义_posts目录的路径
const postsDir = path.join(__dirname, 'source', '_posts');
// 递归函数来遍历目录
function walkDir(dir, callback) {
fs.readdir(dir, (err, files) => {
if (err) {
console.error(`无法读取目录${dir}:`, err);
return;
}
files.forEach(file => {
const filePath = path.join(dir, file);
fs.stat(filePath, (err, stat) => {
if (err) {
console.error(`无法获取文件${file}的状态:`, err);
return;
}
if (stat.isDirectory()) {
walkDir(filePath, callback); // 递归遍历子目录
} else if (stat.isFile() && path.extname(file) === '.md') {
callback(filePath); // 找到.md文件,执行回调
}
});
});
});
}
// 处理.md文件的函数
function processMdFile(filePath) {
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
console.error(`无法读取文件${filePath}:`, err);
return;
}
const modifiedData = data.replace(/(cover:).*/, '$1');
if (data !== modifiedData) {
fs.writeFile(filePath, modifiedData, 'utf8', (err) => {
if (err) {
console.error(`无法写入文件${filePath}:`, err);
return;
}
// 获取并输出相对于_posts目录的路径
const relativePath = path.relative(postsDir, filePath);
console.log(`已更新:“${relativePath}”`);
});
}
});
}
// 开始遍历_posts目录
walkDir(postsDir, processMdFile);
使用方法
要使用这个脚本,您需要将它保存为一个removeCover.js
文件,然后在您的 Hexo 项目根目录下通过以下命令运行它。
node removeCover.js
脚本会自动执行上述操作,批量删除所有 Markdown 文件中的cover
字段后面的图片链接。
🚨
请确保在运行此脚本之前备份您的文章,以防万一出现意外情况导致数据丢失。
通过使用这个脚本,您可以节省大量时间,自动化编辑 Markdown 文件的过程,让您可以更专注于创作内容,而不是重复的编辑工作。