目录
- 前言
- 需求分析
- 实现步骤
- 读取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');
确定最高标题级别
遍历每一行,确定文件中最高的标题级别(例如,最高标题级别是#
还是##
)。
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写作,不妨试一试吧。