DEV/Node.js

[Node.js] Obsidian 파일 Tag 수정하기

9thxg 2024. 7. 7. 18:40

const Obsidian 파일 Tag 수정하기 = ( Param ) => {

💻 return Result;

// index.js
const readline = require("node:readline");
const { getFileList, modifyEachFile } = require("./file");

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
});

const folderPath = "폴더 경로";

const main = async () => {
    const tags = await new Promise((res, rej) => {
        rl.question(`필요한 태그 입력(쉼표구분):`, (tags) => {
            if (!tags) res(null);

            res(tags.split(",").map((it) => it.trim()));

            rl.close();
        });
    });

    if (!tags) {
        console.error("tag가 지정되지 않으면 진행할 수 없습니다!");
        process.exit();
    }

    const fileList = await getFileList(folderPath);

    fileList.forEach((it) => modifyEachFile(it, tags, folderPath));

    return;
};

main();
// file.js
const fs = require("fs");

const getFileList = (path) => {
    return new Promise((res, rej) => {
        fs.readdir(path, (err, fileList) => {
            if (err) {
                console.error("err", err);
                rej(err);
            }
            res(fileList);
        });
    });
};

const modifyEachFile = (fileName, tags, folderPath) => {
    return new Promise((res, rej) => {
        fs.readFile(folderPath + "/" + fileName, "utf8", (err, data) => {
            if (err) {
                console.error(err);
                rej(err);
            }

            // 정규식을 통해 --- 인 기호의 정보를 모두 가져온다.
            const matchSymbols = [...data.matchAll(/---/g)];

            let modifyData = "",
                propertyData = "";

            if (matchSymbols.length === 0) {
                propertyData += "tags:\n";
                tags.forEach((tag) => (propertyData += "  - " + tag + "\n"));

                modifyData = "---\n" + propertyData + "---\n" + data;
            } else {
                if (
                    matchSymbols[0].index !== 0 ||
                    (matchSymbols[0].index === 0 && matchSymbols.length === 1)
                ) {
                    // 상단 글 속성의 기호가 아닐 때
                    // 혹은 상단의 기호가 있지만 닫히지 않을 때
                    const errMsg = "Property 기호가 잘못되었습니다!";
                    console.error(errMsg);
                    rej(errMsg);
                }

                const splitedFile = data.split("---");

                propertyData = splitedFile[1];

                if (!splitedFile[1].includes("tags")) {
                    // tags 값 자체가 없을 때
                    propertyData += "tags:\n";
                    tags.forEach(
                        (tag) => (propertyData += "  - " + tag + "\n")
                    );
                } else {
                    tags.forEach((tag) => {
                        if (!splitedFile[1].includes(`  - ${tag}`)) {
                            propertyData += "  - " + tag + "\n";
                        }
                    });
                }

                modifyData = "---\n" + propertyData + "---\n";
                // modifyData = "---\n" + "---\n";
                for (let i = 2; i < splitedFile.length; i++) {
                    modifyData += splitedFile[i];
                }
            }

            fs.writeFile(folderPath + "/" + fileName, modifyData, (err) => {
                if (err) {
                    console.error(err);
                    rej(err);
                }
                res("Done");
            });
        });
    });
};

module.exports = { getFileList, modifyEachFile };

📝 console.log( history )

 문서들을 정리하기 위해 Obsidian을 사용 중이다. 이전에 노션에서 쓰다가 넘어온 터라 Property들이 제대로 지정되지 않아서 Graph View로 보았을 때 연결이 제대로 되어있지 않았다. 그래서 이번에 시간을 내어 쭉 정리했다.

 

 단일로 작성된 문서들은 직접 Property를 수정하였다. 문제는 일기와 같이 주기적으로 작성하는 문서들이 문제였다. 다행히 관심사 별로 폴더를 정리해 둔 터라 폴더 단위로 수정할 수 있었다. 그래도 문서의 양이 많아 직접 정리하기는 비효율적으로 보였고 node.js 코드를 통해 작성하여 수정했다.

 

 처음부터 여러 기능에 대해서 생각하지 않고 단순히 필요한 기능을 작성해 보고 하나씩 추가하기로 했다. 폴더의 파일 리스트를 읽고 해당 파일들에 접근하여 Property 부분을 수정하면 된다.

 

 fs 라이브러리의 함수를 통해 폴더의 파일 리스트를 읽고(readdir) 각 파일을 읽어 내용을 확인한 후(readFile) 내용을 수정하여 다시 파일에 적용(writeFile)했다.

 

 추가로 정규식을 통해 Property 기호인 '---'가 잘못 설정되어 있으면 진행하지 않도록 검증했다. tag값 수정이 필요해서 tag값을 readline 라이브러리를 통해 입력받아 처리하도록 했다.

 

/ /  Improvements

 일단 나만 사용하기 좋은 상태로 만들어 뒀지만 옵시디언 root 경로를 자동으로 잡아두고 사용자가 입력한 경로를 찾아 작업할 수 있도록 확장하는 것이 좋아 보인다.

 

 node에서는 cmd창에서 입력받고 선택하는 것이 어려워 보이지만 필요한 라이브러리를 찾아 태그뿐만 아니라 다른 Property 속성 혹은 반복해야 할 작업을 수행할 수 있도록 구현해야겠다.

}