markdown文件中标题的序列号自动生成(非typora插件)

2023-11-16

非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;
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

markdown文件中标题的序列号自动生成(非typora插件) 的相关文章

随机推荐