[obsidian] 교보문고 책 link로 책 template 입력

fuzzy·2024년 6월 20일

etc

목록 보기
2/2
post-thumbnail

tr_get_kyobobook_info.js

  • tr_get_kyobobook_info.js 파일은 vault 안에 따로 scripts 폴더를 만드시고 해당 폴더 안에 넣어두시면 됩니다.
    그래야 클라우드든 뭐든 동기화 할떄 script 파일이 같이 넘어가서 다른 환경에서도 동작해요
async function get_kyoBoBook_info(tp, url = "", title_section = true, cover_section = true, toc_section = true) {
  function convertToYAML(obj, indent = 0) {
    let yamlStr = "";
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        let value = obj[key];
        let indentStr = " ".repeat(indent);
        if (typeof value === "object" && !Array.isArray(value)) {
          yamlStr += `${indentStr}${key}:\n${convertToYAML(value, indent + 2)}`;
        } else if (Array.isArray(value)) {
          yamlStr += `${indentStr}${key}:\n`;
          value.forEach((item) => {
            yamlStr += `${" ".repeat(indent + 2)}- ${item}\n`;
          });
        } else {
          yamlStr += `${indentStr}${key}: ${value}\n`;
        }
      }
    }
    return yamlStr;
  }

  if (!url) {
    url = tp.frontmatter["url"];
  }

  if (!url) {
    let modal = new tp.obsidian.Modal(app);
    modal.titleEl.setText("⚠ 에러 - frontmatter에 url을 넣으세요.");
    modal.contentEl.setText("url:" + url);
    modal.open();
    return;
  }

  let response;
  try {
    response = await request({ url: url });
  } catch (e) {
    console.error("에러 발생 - request", e);
    alert("에러 발생 - request\n\n" + e + "\n\n옵시디언을 다시 시작해 보세요.");
    return;
  }

  const parser = new DOMParser();
  const doc = parser.parseFromString(response, "text/html");

  const title = doc.querySelector("#contents h1 span.prod_title").innerText.trim();

  const authors_element = doc.querySelector("#contents .author");
  const names_temp = Array.from(authors_element.querySelectorAll("a")).map((a) => a.textContent.trim());
  const author = names_temp[0];

  const cover = doc.head.querySelector("meta[property='og:image']")?.content || "";
  const category = doc.body.querySelectorAll("ol.breadcrumb_list li.breadcrumb_item")[2]?.innerText.trim() || "";

  let publish_date, book_pages, isbn;

  Array.from(doc.body.querySelectorAll(".product_detail_area.basic_info tr")).forEach((tr) => {
    const key = tr.firstElementChild.innerText.trim();
    const value = tr.children[1].innerText.trim();
    if (key === "발행(출시)일자") {
      publish_date = value.replace(/\s{2,}/g, " ");
    } else if (key === "쪽수") {
      book_pages = value;
    } else if (key === "ISBN") {
      isbn = value;
    }
  });

  let toc = doc.body.querySelector(".book_contents_list li")?.innerHTML.trim().replace(/<br>/g, "  \n") || "";
  if (toc) {
    toc = toc.replace(/^(\d+[.장]?\s)/gm, "### $1");
  }

  async function get_filename_new(folder, fname) {
    const file_exist = await tp.file.exists(`${folder}/${fname}.md`);
    if (file_exist) {
      const match = fname.match(/ \((\d+)\)$/);
      fname = fname.replace(/ \(\d+\)$/, "") + ` (${match ? parseInt(match[1]) + 1 : 1})`;
      fname = await get_filename_new(folder, fname);
    }
    return fname;
  }

  const filename_old = tp.file.title;
  let filename_new = `📚 ${title} - ${author}`.replace(/[\\/:\*\?"<>\|]/g, "");
  if (!filename_old.startsWith(filename_new)) {
    filename_new = await get_filename_new(tp.file.folder(true), filename_new);
    await tp.file.rename(filename_new);
  }

  const path = tp.obsidian.normalizePath(tp.file.path(true));
  const tFile = app.vault.getAbstractFileByPath(path);

  let tR = "";
  await app.fileManager.processFrontMatter(tFile, (fm) => {
    const addIfNotEmpty = (key, value, type = "string") => {
      if (value) {
        fm[key] = type === "number" ? Number(value) : value;
      }
    };

    addIfNotEmpty("authors", author);
    addIfNotEmpty("category", category);
    addIfNotEmpty("publish date", publish_date);
    addIfNotEmpty("pages", book_pages);
    addIfNotEmpty("isbn", isbn, "number");
    addIfNotEmpty("cover", cover);

    const title_old = tp.frontmatter["title"] || "";
    const title_new = `${title} - ${author}`;

    const aliases = tp.frontmatter["aliases"] || [];
    const alias = title_new;
    let aliases_changed = false;

    if (!aliases.includes(alias)) {
      aliases.push(alias);
      aliases_changed = true;
    }

    if (title_old && title_old !== "Untitled" && title_old !== title_new && !aliases.includes(title_old)) {
      aliases.push(title_old);
      aliases_changed = true;
    }

    if (aliases_changed) fm["aliases"] = aliases;

    // YAML 형태의 frontmatter 내용을 문자열로 변환하여 tR에 추가
    tR += `---\n${convertToYAML(fm)}---\n`;

    if (title_section && title) tR += `# ${title}\n`;
    if (cover_section && cover) tR += `## 표지\n![cover](${cover})\n`;
    if (toc_section && toc) tR += `## 목차\n${toc}\n`;
  });

  return tR;
}

module.exports = get_kyoBoBook_info;

note에 복붙할 script
let url = "내가 review할 책 링크(교보문고 링크)" 로 수정하시면 됩니다.

<%_*
//url: 교보문고 도서 url, 
let url = "https://product.kyobobook.co.kr/detail/S000212321676"; 

let title_section = false; // 본문에 책 제목 (true / false)
let cover_section = false; // 본문에 커버이미지 (true / false)
let toc_section = true; // 본문에 목차 (true / false)

// Script 실행
tR = await tp.user.tr_get_kyobobook_info(tp, url, title_section, cover_section, toc_section);
-%>
profile
java, c++, react, back-end / full stack, game, security

0개의 댓글