在您的 Hexo 博客项目中,您可能有大量的文章,每篇文章都可能定义了一个cover字段来指定文章封面。随着时间的推移,您可能决定不再为文章设置封面,或者您想要使用随机图 API 来设置随机封面。这时候,手动编辑每个文件显然是不现实的。为了解决这个问题,您可以使用一个简单的 Node.js 脚本来自动化这个过程。

在这篇博客文章中,我将向您介绍一个为此目的而编写的 Node.js 脚本。这个脚本会遍历您的 Hexo 项目根目录下的source\_posts文件夹,查找所有 Markdown 文件(.md文件),并删除每个文件中的cover字段后面的图片链接。

脚本功能概述

脚本的工作流程如下:

  1. 定位到 Hexo 项目根目录下的source\_posts文件夹。

  2. 遍历这个目录下的所有文件和子目录。

  3. 对于每个找到的 Markdown 文件,读取文件内容。

  4. 在文件内容中查找cover字段,并删除它后面的图片链接。

  5. 将修改后的内容写回到原文件中。

脚本细节分析

现在,我们来深入了解脚本的每个部分:

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 文件的过程,让您可以更专注于创作内容,而不是重复的编辑工作。