From ad36ab568fe1a37dc7c8fe932a23040f618fb2b3 Mon Sep 17 00:00:00 2001 From: seiya_tagami Date: Mon, 16 Dec 2024 13:18:56 +0900 Subject: [PATCH] refactor --- .../rehype-embedded-github-code/index.ts | 59 +++++++++++-------- .../rehype-embedded-github-code/utils.ts | 14 ++--- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/app/packages/rehype-embedded-github-code/index.ts b/app/packages/rehype-embedded-github-code/index.ts index d5b965c..a781a44 100644 --- a/app/packages/rehype-embedded-github-code/index.ts +++ b/app/packages/rehype-embedded-github-code/index.ts @@ -1,7 +1,7 @@ -import type { Root } from "hast"; +import type { Element, Root } from "hast"; import type { Plugin, Transformer } from "unified"; import { visit } from "unist-util-visit"; -import { buildRequestURL, createCodeBlock, extractCodeByLines, extractRepoDataFromURL } from "./utils"; +import { type Lines, buildRequestURL, createCodeBlock, extractCodeByLines, extractRepoDataFromURL } from "./utils"; type Option = { githubPAT: string; @@ -10,32 +10,44 @@ type Option = { const rehypeEmbeddedGithubCode: Plugin = (options): Transformer => { const { githubPAT } = options; - const headers = { - Accept: "application/vnd.github+json", - Authorization: `Bearer ${githubPAT}`, - "X-GitHub-Api-Version": "2022-11-28", - }; + const transform: Transformer = async (tree) => { + const regex = new RegExp( + /https:\/\/github\.com\/[a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+\/blob\/[a-zA-Z0-9._-]+\/?[^\s]*/g, + ); - const githubCodePromises: Promise[] = []; + const githubCodePromises: Promise[] = []; - const regex = new RegExp(/https:\/\/github\.com\/[a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+\/blob\/[a-zA-Z0-9._-]+\/?[^\s]*/g); + const headers = { + Accept: "application/vnd.github+json", + Authorization: `Bearer ${githubPAT}`, + "X-GitHub-Api-Version": "2022-11-28", + }; - const transform: Transformer = async (tree) => { visit(tree, "element", (node, index, parent) => { - if (node.tagName !== "a" || node.properties.href === undefined || !regex.test(String(node.properties.href))) { + if ( + node.tagName !== "a" || + node.properties.href === undefined || + typeof node.properties.href !== "string" || + !regex.test(node.properties.href) + ) { return; } + if (index === undefined || parent === undefined) { return; } - if (parent.type !== "root" && parent.type !== "element") { - return; - } - const githubCodePromise = async (): Promise => { - const { repoName, ref, path, lines } = extractRepoDataFromURL(String(node.properties.href)); - const requestUrl = buildRequestURL(repoName, ref, path); + type Props = { + node: Element; + href: string; + repoName: string; + ref: string; + path: string; + lines?: Lines; + }; + const githubCodePromise = async ({ repoName, ref, href, path, lines }: Props): Promise => { + const requestUrl = buildRequestURL(repoName, ref, path); try { const response = await fetch(requestUrl, { headers }); if (!response.ok) { @@ -45,18 +57,19 @@ const rehypeEmbeddedGithubCode: Plugin = (options): Transformer< const codeBase64 = content.content; const code = extractCodeByLines(Buffer.from(codeBase64, "base64").toString("utf-8"), lines); - const codeBlockElement = createCodeBlock( - `${repoName}/${path}${lines ? `#L${lines.startLine}-L${lines.endLine}` : ""}`, - String(node.properties.href), - code, - ); + const title = `${repoName}/${path}${lines ? `#L${lines.startLine}-L${lines.endLine}` : ""}`; + const codeBlockElement = createCodeBlock(title, href, code); parent.children[index] = codeBlockElement; } catch (error) { throw new Error("Failed to fetch code from GitHub", { cause: error }); } }; - githubCodePromises.push(githubCodePromise()); + + const nodeHref = node.properties.href; + const { repoName, ref, path, lines } = extractRepoDataFromURL(nodeHref); + + githubCodePromises.push(githubCodePromise({ node, repoName, href: nodeHref, ref, path, lines })); }); await Promise.all(githubCodePromises); diff --git a/app/packages/rehype-embedded-github-code/utils.ts b/app/packages/rehype-embedded-github-code/utils.ts index 851aaa6..a35c65e 100644 --- a/app/packages/rehype-embedded-github-code/utils.ts +++ b/app/packages/rehype-embedded-github-code/utils.ts @@ -17,12 +17,12 @@ const extractRef = (urlParts: string[]): string => { return urlParts[3]; }; -type LineNumbers = { +export type Lines = { startLine: number; endLine: number; }; -const extractLines = (urlParts: string[]): LineNumbers | undefined => { +const extractLines = (urlParts: string[]): Lines | undefined => { const result = urlParts.slice(4).join("/"); const hashIndex = result.indexOf("#"); if (hashIndex === -1) { @@ -48,16 +48,16 @@ const extractRepoDataFromURL = (url: string) => { }; }; -const buildRequestURL = (repo: string, ref: string, path: string): string => { - return `https://api.github.com/repos/${repo}/contents/${path}?ref=${ref}`; -}; - -const extractCodeByLines = (code: string, lines: LineNumbers | undefined): string => { +const extractCodeByLines = (code: string, lines: Lines | undefined): string => { if (!lines) return code; const codeLines = code.split("\n"); return codeLines.slice(lines.startLine - 1, lines.endLine).join("\n"); }; +const buildRequestURL = (repo: string, ref: string, path: string): string => { + return `https://api.github.com/repos/${repo}/contents/${path}?ref=${ref}`; +}; + const createCodeBlock = (title: string, href: string, code: string) => { return h("div", [ h("span", { class: ["rehype-embedded-github-code-title"] }, [