在Excalidraw中列出某笔记所有二级Heading

继续发一下,之前生成的canvas的id是数字,正常的应该是字符串,这里重新发下代码,另外发现 Obsidian-canvas-minimap (github.com)这个插件特别好用,可以生成缩略图并点击跳转:

PixPin_2024-03-04_17-23-28

另外我设置了参数在QuickAdd里面,不同等级的标题的卡片颜色会变化:
image

QuickAdd Macro脚本
const path = require('path');
const fs = require('fs');
// 获取笔记的基本路径
const file = app.workspace.getActiveFile();
const fileFullPath = app.vault.adapter.getFullPath(file.path);

module.exports = {
    entry: async (QuickAdd, settings, params) => {
        // 可调节的参数
        // 大纲等级
        const level = Number(settings["level"]);
        // 卡片参数
        const width = Number(settings["width"]);
        const height = Number(settings["height"]);
        // 卡片间隔
        const space = Number(settings["space"]);
        // 每行卡片的数量限制
        const limit = Number(settings["limit"]);
        // 基于库的相对路径的Canvas
        const canvasPath = settings["canvasPath"];

        const canvasData = {
            nodes: [],
            edges: []
        };
        if (file.extension === 'md') {
            console.log("开始获取二级标题");
            const { heads, counts } = getHeadings(fileFullPath, level);
            console.log(heads);

            let x = 0;
            let y = 0;
            let n = 1;
            let nodes = [];
            const length = heads.length;

            for (let i = 1; i <= length; i++) {
                const node = {
                    id: "",
                    type: "file",
                    file: file.path,
                    subpath: "",
                    x: 0,
                    y: 0,
                    width: width,
                    height: height,
                };

                node.subpath = heads[i - 1];
                node.id = String(i);
                node.x = x;
                node.y = y;
                node.color = String(counts[i - 1]-1)
                console.log([heads[i - 1], x, y]);

                x += width + space;
                if (i >= limit * n) {
                    y += height + space;
                    x = 0;
                    n = n + 1;
                }
                console.log([heads[i - 1], node.x, y]);

                nodes.push(node);
            }
            canvasData.nodes = nodes;
            console.log(canvasData);
            const canvasFile = app.vault.getAbstractFileByPath(canvasPath);
            const canvasJson = JSON.stringify(canvasData, null, 2);
            if (canvasFile) {
                app.vault.modify(canvasFile, canvasJson);
                app.workspace.activeLeaf.openFile(canvasFile);
            } else {
                canvasFile = app.vault.create(canvasPath, canvasJson);
                app.workspace.activeLeaf.openFile(canvasFile);
            }

            // 尝试重新加载缩略图
            setTimeout(() => {
                try {
                    app.commands.executeCommandById("canvas-minimap:reload");
                } catch (error) {
                    console.log(error);
                }
            }, 1000);


        } else if (file.extension === 'canvas') {
            fs.readFile(fileFullPath, 'utf8', (err, data) => {
                if (err) throw err;
                const canvasData = JSON.parse(data);
                // 获取nodes中的object.file
                canvasData.nodes;
                const mdFilePath = canvasData.nodes[0].file;
                app.workspace.activeLeaf.openFile(app.vault.getAbstractFileByPath(mdFilePath));
            });

        }

    },
    settings: {
        name: "Convert md to canvas",
        author: "熊猫别熬夜",
        options: {
            "canvasPath": {
                type: "text",
                defaultValue: "MdToCanvas.canvas",
                placeholder: "相对路径",
                description: "设置Canvas路径,可以嵌套子文件夹",
            },
            "level": {
                type: "dropdown",
                defaultValue: 2,
                options: [2, 3, 4, 5, 6],
                description: "设置平铺的大纲等级,每个等级对应不同颜色",
            },
            "width": {
                type: "text",
                defaultValue: "1080",
                placeholder: "卡片参数",
                description: "卡片宽度",

            },
            "height": {
                type: "text",
                defaultValue: "1000",
                placeholder: "卡片参数",
                description: "卡片高度",
            },

            "limit": {
                type: "text",
                defaultValue: "3",
                placeholder: "每行卡片数量",
                description: "每行卡片数量",
            },
            "space": {
                type: "text",
                defaultValue: "250",
                placeholder: "卡片间隔",
                description: "卡片之间的间隔",

            },
        }
    }

};


function getHeadings(fileFullPath, level) {
    // 读取文件内容
    const fileContent = fs.readFileSync(fileFullPath, 'utf-8');
    // 使用正则表达式提取指定级别的标题
    const regex = new RegExp(`^#{2,${level}}\\s(.+)`, 'gm');
    const heads = [];
    let head;
    let counts = [];

    while ((head = regex.exec(fileContent)) !== null) {
        heads.push("#" + head[1]);
        counts.push(head[0].match(/#/g).length);
    }
    return { heads, counts };
}

1 个赞