非typora插件,在指定路径下新增文件,调整文件的标题序号。
/**
* :: java -cp md-auto-num-1.0.jar com.emulate.AutoGenerateNum
* :: 正式的标题中不能有空格
* :: 路径1:需要自动生成标题序号的md文件路径
* :: 路径2:转换后的文件路径,不涉及是默认:D:\mdFilePath,若和路径1一致,转D:\temp
* java -Dfile.encoding=utf-8 -jar md-auto-num-1.0.jar D:\markdown\程序学习 D:\temp
* pause
*
*/
package com.emulate;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AutoGenerateNum {
public static void main(String[] args) {
if (args == null || args.length == 0) {
throw new RuntimeException("未指定需要自动生成标题序号的文件路径");
}
// 文件夹下的md文件解析
String mdFilePath = args[0];
String newPath;
try {
newPath = args[1];
} catch (Exception e) {
newPath = "D:\\mdFilePath";
}
read_writer(mdFilePath, newPath);
}
private static void read_writer(String mdFilePath, String newPath) {
if (newPath.equals(mdFilePath)) {
newPath = "D:\\temp";
}
File folder = new File(mdFilePath);
if (folder.isDirectory()) {
List<File> files = getFolderAllMdFile(folder);
for (File file : files) {
write_parse_copy(file, newPath, mdFilePath);
}
}
}
private static List<File> getFolderAllMdFile(File folder) {
List<File> fileList = new ArrayList<>();
for (File file : Objects.requireNonNull(folder.listFiles())) {
if (file.isDirectory()) {
fileList.addAll(getFolderAllMdFile(file));
} else if (file.getName().endsWith(".md")) {
fileList.add(file);
}
}
return fileList;
}
private static void write_parse_copy(File inputFile, String newPath, String mdFilePath) {
String copyPath = newPath + "\\" + inputFile.getPath().substring(mdFilePath.length() + 1);
copyPath = copyPath.substring(0, copyPath.length() - inputFile.getName().length() - 1);
System.out.println(copyPath);
File dirs = new File(copyPath);
if (!dirs.exists()) {
dirs.mkdirs();
}
File outputFile = new File(copyPath + "\\" + inputFile.getName());
try {
outputFile.createNewFile();
} catch (Exception exception) {
throw new RuntimeException(exception.getMessage(), exception);
}
Integer[] titleNumber = new Integer[]{0, 0, 0, 0, 0, 0};
try (BufferedReader reader = new BufferedReader(new FileReader(inputFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) {
String line;
int headerLevel = 0;
int maxLevel = 0;
int trueCount = 0;
while ((line = reader.readLine()) != null) {
// TODO 其余需要排除的中间逻辑结构,业务执行过程中继续完善
// 排除注释中的#
if (line.startsWith("<!--") || line.contains("<!--")) {
trueCount++;
}
if (line.startsWith("-->") || line.contains("-->")) {
trueCount--;
}
// 排除```中的设计
// 部分注释中带注释的逻辑调整
if (line.startsWith("```") && line.trim().length() > countHeaderLevel(line.trim(), '`')) {
trueCount++;
}
if (line.startsWith("```") && line.trim().length() == countHeaderLevel(line.trim(), '`')) {
trueCount--;
}
// 验证当前行是否是标题栏,标题和#中间带有空格,并且6级标题之内
if (line.startsWith("#") && line.trim().indexOf(" ") <= 6 && trueCount == 0) {
headerLevel = countHeaderLevel(line);
// 排除###标题1,无空格标识的数据,正常的标题,中间含空格### 标题1
if (line.charAt(headerLevel) == ' ') {
if (maxLevel == 0) {
maxLevel = headerLevel;
}
titleNumber[headerLevel - maxLevel] = titleNumber[headerLevel - maxLevel] + 1;
for (int i = headerLevel - maxLevel + 1; i < titleNumber.length; i++) {
titleNumber[i] = 0;
}
// 配置标题
StringBuilder title = new StringBuilder();
for (int i = 0; i <= headerLevel - maxLevel; i++) {
title.append(titleNumber[i]).append(".");
}
title.deleteCharAt(title.length() - 1);
title.append(" ");
System.out.println("需要处理的标题:" + line);
{
// 考虑序号和标题合并在一起:
// 表示标题序号已存在,数据转换:
String splitLine = line.trim();
String[] data = splitLine.split(" ");
// 已有标题的改造声明:标准的 ### 1.1.2.3 标题
if (data.length == 3) {
boolean numberFirst = firstNumberRegularExpressionValidation(data[data.length - 1]);
if (numberFirst) {
// 截取正常的逻辑标题并赋值
data[data.length - 1] = subTitle(data[data.length - 1]);
}
line = line.substring(0, data[0].length()) + " " + line.substring(2 + data[0].length() + data[1].length());
System.out.println("删除已有标题:" + line);
}
// 已有标题的改造声明:非标准的 ### 1.1.2.3 标题 保留最前和最后的
if (data.length > 3) {
boolean numberFirst = firstNumberRegularExpressionValidation(data[data.length - 1]);
if (numberFirst) {
data[data.length - 1] = subTitle(data[data.length - 1]);
}
int lengthCount = 0;
for (String arr : data) {
lengthCount = lengthCount + arr.length() + 1;
}
lengthCount = lengthCount - data[data.length - 1].length() - 1;
line = line.substring(0, data[0].length()) + " " + line.substring(lengthCount);
System.out.println("待非标准的已有标题:" + line);
}
if (data.length == 2) {
boolean numberFirst = firstNumberRegularExpressionValidation(data[data.length - 1]);
if (numberFirst) {
data[data.length - 1] = subTitle(data[data.length - 1]);
}
line = line.substring(0, data[0].length()) + " " + data[data.length - 1];
System.out.println("无序号标题:" + line);
}
}
line = line.trim().substring(0, headerLevel + 1) + title + line.trim().substring(headerLevel + 1);
System.out.println("处理后的标题源码:" + line);
}
}
writer.write(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static String subTitle(String datum) {
if (datum.startsWith(".") || firstNumberRegularExpressionValidation(datum)) {
datum = subTitle(datum.substring(1));
}
return datum;
}
public static boolean firstNumberRegularExpressionValidation(String input) {
Pattern pattern = Pattern.compile("^(\\d+)(.*)");
Matcher matcher = pattern.matcher(input.charAt(0) + "");
return matcher.matches();
}
private static int countHeaderLevel(String line) {
int level = 0;
try {
while (line.charAt(level) == '#') {
level++;
}
} catch (Exception e) {
// System.out.println("部分数据校验的逻辑处理,不考虑," + e.getMessage());
}
return level;
}
private static int countHeaderLevel(String line, char key) {
int level = 0;
try {
while (line.charAt(level) == key) {
level++;
}
} catch (Exception e) {
// System.out.println("部分数据校验的逻辑处理,不考虑," + e.getMessage());
}
return level;
}
}