Typora 博文标题自动编号
1、Why?
1.1、Typora标题自动编号
- 修改 base.user.css 中的 css 代码可达到如下效果,看着还不错

1.2、博文效果
- 修改 base.user.css 中的 css 代码只能实现 Typora 中的视觉效果,并不是真正在标题中添加了序号

2、Let’s Do it
2.1、目标
- 编写 Java 脚本,读取 MD 文件的内容,并在每个标题之前添加标题序号
2.2、代码
- 大致思路:
- 每一级标题都有自己的计数器,由于一级标题不参与编号,从二级标题开始算起,Typora 最多支持六级标题,我们用一个长度为 5 的一维数组代表 2~6 级标题计数器
- 每读取一行,便判断此行是否为标题行,如果是标题行,则为当前标题添加标题序号
- 标题计数器初始默认值为 0 ,每次用的时候便执行 += 1 操作
public class TitleAutoNumbering {
public static void main(String[] args) {
String destMdFilePath;
if (args == null || args.length == 0) {
destMdFilePath = "C:\\Users\\Heygo\\Desktop\\Typora + PicGo + Aliyun OSS + CSDN.md";
} else {
destMdFilePath = args[0];
}
doTitleAutoNumbering(destMdFilePath);
}
private static void doTitleAutoNumbering(String destMdFilePath) {
String mdFileContent = getAutoTitledMdContent(destMdFilePath);
SaveMdContentToFile(destMdFilePath, mdFileContent);
}
private static String getAutoTitledMdContent(String destMdFilePath) {
Boolean isMdFile = destMdFilePath.endsWith(".md");
if (!isMdFile) {
return "";
}
Integer[] titleNumber = new Integer[]{0, 0, 0, 0, 0};
StringBuilder sb = new StringBuilder();
String curLine;
try (
FileReader fr = new FileReader(destMdFilePath);
BufferedReader br = new BufferedReader(fr);
) {
while ((curLine = br.readLine()) != null) {
Integer curTitleLevel = calcTitleLevel(curLine);
if (curTitleLevel != -1) {
curLine = insertTitleNumber(curLine, titleNumber);
RecalcTitleCounter(curTitleLevel, titleNumber);
}
sb.append(curLine + "\r\n");
}
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
private static Integer calcTitleLevel(String curLine) {
boolean isTitle = curLine.startsWith("##");
if (!isTitle) {
return -1;
}
Integer titleLevel = curLine.indexOf(" ");
return titleLevel;
}
private static void RecalcTitleCounter(Integer titleLevel, Integer[] titleNumber) {
Integer startIndex = titleLevel - 1;
for (int i = startIndex; i < titleNumber.length; i++) {
titleNumber[i] = 0;
}
}
private static String insertTitleNumber(String curLine, Integer[] titleNumber) {
Integer titleLevel = curLine.indexOf(" ");
String titleLevelStr = curLine.substring(0, titleLevel);
String titleContent = curLine.substring(titleLevel + 1);
titleContent = RemovePreviousTitleNumber(titleContent);
Integer titleIndex = titleLevel - 2;
titleNumber[titleIndex] += 1;
String titleNumberStr = "";
switch (titleLevel) {
case 2:
titleNumberStr = titleNumber[0].toString();
break;
case 3:
titleNumberStr = titleNumber[0].toString() + "." + titleNumber[1];
break;
case 4:
titleNumberStr = titleNumber[0].toString() + "." + titleNumber[1] + "." + titleNumber[2];
break;
case 5:
titleNumberStr = titleNumber[3].toString();
break;
case 6:
titleNumberStr = titleNumber[4].toString() + " ) ";
break;
}
titleNumberStr += "、";
titleContent = titleNumberStr + titleContent;
System.out.println("已增加标题序号:" + titleContent);
curLine = titleLevelStr + " " + titleContent;
return curLine;
}
private static String RemovePreviousTitleNumber(String titleContent) {
Integer index = titleContent.indexOf("、");
if (index > 0 && index < 6) {
return titleContent.substring(index + 1);
} else {
return titleContent;
}
}
public static void SaveMdContentToFile(String destMdFilePath, String mdFileContent) {
if (mdFileContent == null || mdFileContent == "") {
return;
}
try (FileWriter fw = new FileWriter(destMdFilePath)) {
fw.write(mdFileContent);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.3、效果
