如何用Node.js实现给Markdown文件标题加数字序号?

2024-07-31 21:34:03 浏览数 (3)

目录

  • 前言
  • 需求分析
  • 实现步骤
    • 读取Markdown文件
    • 解析并确定最高标题级别
    • 解析并处理每一行
    • 维护标题级别的计数器
    • 构造新的标题行
    • 写回文件
  • 实现代码
  • 代码解析
    • 读取Markdown文件
    • 分割文件内容为行
    • 确定最高标题级别
    • 初始化计数器数组
    • 处理每一行
    • 写回文件
  • 结语

前言

你好,我是喵喵侠。作为一名技术创作者,Markdown我每次写文章都会用到,它可以很方便的帮助我书写文章,让我专注于内容,不需要刻意注重排版。

当一篇文章的目录过多时,往往分不清最终显示的标题,到底是几级标题,以及这些标题是怎么样的层级和排序。

今天我将为你带来一个Markdown加序号的实现方法,看完你立马就能用上。

需求分析

我们这里用Node.js做演示,首先肯定是要读取到md文件内容,找出里面所有的标题,然后在每个标题的后面,添加合适的序号。

这里还需要追加限定条件:

如果最高层级的标题是一级标题#,那么得到的结果是# 1.

如果最高层级的标题是二级标题##,那么得到的结果是## 1.

依次类推……

那么怎么实现这样的操作呢,来看下面的实现步骤吧。

实现步骤

读取Markdown文件

从文件系统读取Markdown文件的内容。

解析并确定最高标题级别

遍历文件内容,确定最高标题级别。

解析并处理每一行

根据最高标题级别,逐行检查是否为标题行,更新计数器。

维护标题级别的计数器

使用一个数组记录每个级别标题的当前计数,并根据标题级别进行更新。

构造新的标题行

根据计数器的值构造新的标题行,添加相应的序号。

写回文件

将处理后的内容重新写回文件。

实现代码

废话不多数,直接上代码!

代码语言:javascript复制
const fs = require('fs');
const path = require('path');

// 读取Markdown文件
const filePath = path.join(__dirname, 'your-file.md');
let fileContent = fs.readFileSync(filePath, 'utf8');

// 分割文件内容为行
let lines = fileContent.split('n');

// 确定最高标题级别
let highestHeadingLevel = 6; // 初始化为最大标题级别
lines.forEach(line => {
  if (line.startsWith('#')) {
    const headingLevel = line.split(' ')[0].length;
    if (headingLevel < highestHeadingLevel) {
      highestHeadingLevel = headingLevel;
    }
  }
});

// 初始化计数器数组,根据最高标题级别决定长度
let headingCounters = Array(6 - highestHeadingLevel   1).fill(0);

// 处理每一行
lines = lines.map(line => {
  if (line.startsWith('#')) {
    const headingLevel = line.split(' ')[0].length;
    if (headingLevel >= highestHeadingLevel) {
      const index = headingLevel - highestHeadingLevel;
      headingCounters[index]  = 1; // 当前级别计数加1

      // 将当前级别以下的计数器归零
      for (let i = index   1; i < headingCounters.length; i  ) {
        headingCounters[i] = 0;
      }

      // 生成序号前缀
      const headingNumber = headingCounters.slice(0, index   1).join('.');

      // 重构标题行
      line = line.replace(/^# /, match => `${match} ${headingNumber}.`);
    }
  }
  return line;
});

// 写回Markdown文件
fileContent = lines.join('n');
fs.writeFileSync(filePath, fileContent, 'utf8');

console.log('标题已添加序号');

代码解析

乍一看上面代码,可能读不太明白,这里做一个解析。

读取Markdown文件

读取Markdown文件的内容。

代码语言:javascript复制
const filePath = path.join(__dirname, 'your-file.md');
let fileContent = fs.readFileSync(filePath, 'utf8');

分割文件内容为行

将文件内容按行分割成一个数组。

代码语言:javascript复制
let lines = fileContent.split('n');

确定最高标题级别

遍历每一行,确定文件中最高的标题级别(例如,最高标题级别是#还是##)。

代码语言:javascript复制
let highestHeadingLevel = 6;
lines.forEach(line => {
  if (line.startsWith('#')) {
    const headingLevel = line.split(' ')[0].length;
    if (headingLevel < highestHeadingLevel) {
      highestHeadingLevel = headingLevel;
    }
  }
});

初始化计数器数组

根据最高标题级别,初始化计数器数组。

代码语言:javascript复制
let headingCounters = Array(6 - highestHeadingLevel   1).fill(0);

处理每一行

根据标题级别更新计数器,重构标题行。

代码语言:javascript复制
lines = lines.map(line => {
  if (line.startsWith('#')) {
    const headingLevel = line.split(' ')[0].length;
    if (headingLevel >= highestHeadingLevel) {
      const index = headingLevel - highestHeadingLevel;
      headingCounters[index]  = 1;

      for (let i = index   1; i < headingCounters.length; i  ) {
        headingCounters[i] = 0;
      }

      const headingNumber = headingCounters.slice(0, index   1).join('.');
      line = line.replace(/^# /, match => `${match} ${headingNumber}.`);
    }
  }
  return line;
});

写回文件

将处理后的内容写回Markdown文件。

代码语言:javascript复制
fileContent = lines.join('n');
fs.writeFileSync(filePath, fileContent, 'utf8');

结语

本文的代码脚本,会读取Markdown文件,解析并处理每一行标题,根据最高标题级别生成序号,并将处理后的内容写回文件,从而实现标题序号的自动添加。这个代码可以满足基本的使用,还有一些可以优化的点,比方说执行脚本可以输入文件路径、排除部分大标题(比如目录)的序号等等,也可以根据个人需要,改写成网页版本。如果你也喜欢用Markdown写作,不妨试一试吧。

0 人点赞