Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
taga3s committed Dec 16, 2024
1 parent 29023a1 commit a836b93
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 194 deletions.
98 changes: 0 additions & 98 deletions app/packages/rehype-embedded-github-code/index.ts

This file was deleted.

62 changes: 0 additions & 62 deletions app/packages/rehype-embedded-github-code/util.ts

This file was deleted.

118 changes: 118 additions & 0 deletions app/packages/rehype-github-embed/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import type { Element, Root } from "hast";
import type { Plugin, Transformer } from "unified";
import { visit } from "unist-util-visit";
import {
type Lines,
buildRequestURL,
createCodeBlock,
createErrBlock,
extractCodeByLines,
extractRepoDataFromURL,
} from "./utils";

type Option = {
githubPAT: string;
};

const rehypeGithubEmbed: Plugin<Option[], Root> = (options): Transformer<Root> => {
const { githubPAT } = options;

const transform: Transformer<Root> = async (tree) => {
const githubEmbedPromises: Promise<void>[] = [];

const headers = {
Accept: "application/vnd.github+json",
Authorization: `Bearer ${githubPAT}`,
"X-GitHub-Api-Version": "2022-11-28",
};

visit(tree, "element", (node, index, parent) => {
const regex = new RegExp(
/https:\/\/github\.com\/[a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+\/blob\/[a-zA-Z0-9._-]+\/?[^\s]*/g,
);

if (
node.tagName !== "a" ||
node.children.length === 0 ||
node.children[0].type !== "text" ||
!regex.test(node.children[0].value)
) {
return;
}

if (index === undefined || parent === undefined) {
return;
}

if (parent.type === "mdxJsxFlowElement" || parent.type === "mdxJsxTextElement") {
return;
}

type Props = {
parent: Root | Element;
href: string;
owner: string;
repoName: string;
ref: string;
path: string;
lines: Lines | undefined;
};

const githubEmbedPromise = async ({ parent, owner, repoName, ref, href, path, lines }: Props): Promise<void> => {
const requestUrl = buildRequestURL(owner, repoName, ref, path);

try {
const response = await fetch(requestUrl, {
headers,
});
if (!response.ok) {
if (response.status === 404) {
const element = createErrBlock("404 Not Found");
parent.children[index] = element;
return;
}

throw new Error(`Failed to fetch code from GitHub: ${response.status}`);
}
const data = (await response.json()) as {
content: string;
};
const codeBase64 = data.content;
const code = extractCodeByLines(Buffer.from(codeBase64, "base64").toString("utf-8"), lines);

const title = `${repoName}/${path}${
lines
? `#${lines.startLine && lines.endLine ? `L${lines.startLine}-L${lines.endLine}` : `L${lines.startLine}`}`
: ""
}`;

const element = createCodeBlock(title, href, code);
parent.children[index] = element;
} catch (error) {
throw new Error("Failed to fetch code from GitHub", { cause: error });
}
};

const nodeHref = node.children[0].value;
const { repoName, owner, ref, path, lines } = extractRepoDataFromURL(nodeHref);

githubEmbedPromises.push(
githubEmbedPromise({
parent,
repoName,
owner,
href: nodeHref,
ref,
path,
lines,
}),
);
});

await Promise.all(githubEmbedPromises);
};

return transform;
};

export { rehypeGithubEmbed };
79 changes: 79 additions & 0 deletions app/packages/rehype-github-embed/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { h } from "hastscript";

const extractOwner = (pathname: string): string => {
const pathnameParts = pathname.split("/");
return pathnameParts[1];
};

const extractRepoName = (pathname: string): string => {
const pathnameParts = pathname.split("/");
return pathnameParts[2];
};

const extractFilePath = (pathname: string): string => {
const pathnameParts = pathname.split("/");
return pathnameParts.slice(5).join("/");
};

const extractRef = (pathname: string): string => {
const pathnameParts = pathname.split("/");
return pathnameParts[4];
};

export type Lines = {
startLine: number;
endLine?: number;
};

const extractLines = (hash: string): Lines | undefined => {
const matches = hash.match(/\d+/g);
if (!matches) return;

return matches[0] && matches[1]
? {
startLine: Number.parseInt(matches[0]),
endLine: Number.parseInt(matches[1]),
}
: { startLine: Number.parseInt(matches[0]) };
};

const extractRepoDataFromURL = (url: string) => {
const base = new URL(url);
return {
repoName: extractRepoName(base.pathname),
owner: extractOwner(base.pathname),
ref: extractRef(base.pathname),
path: extractFilePath(base.pathname),
lines: extractLines(base.hash),
};
};

const extractCodeByLines = (code: string, lines: Lines | undefined): string => {
if (!lines) return code;
const codeLines = code.split("\n");

if (lines.startLine && lines.endLine) {
return codeLines.slice(lines.startLine - 1, lines.endLine).join("\n");
}

return codeLines[lines.startLine - 1];
};

const buildRequestURL = (owner: string, repoName: string, ref: string, path: string): string => {
return `https://api.github.com/repos/${owner}/${repoName}/contents/${path}?ref=${ref}`;
};

const createCodeBlock = (title: string, href: string, code: string) => {
return h("div", [
h("span", { class: ["rehype-embedded-github-code-title"] }, [
h("a", { href: href }, [h(null, [{ type: "text", value: title }])]),
]),
h("pre", [h("code", [h(null, [{ type: "text", value: code }])])]),
]);
};

const createErrBlock = (message: string) => {
return h("div", [h("span", [h(null, [{ type: "text", value: message }])])]);
};

export { extractRepoDataFromURL, buildRequestURL, extractCodeByLines, createCodeBlock, createErrBlock };
30 changes: 0 additions & 30 deletions app/packages/remark-embedded-github-code/index.ts

This file was deleted.

1 change: 1 addition & 0 deletions app/routes/_renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export default jsxRenderer(({ children, title, description }) => {
{/* global css */}
<link rel="stylesheet" href="/static/markdown-styles.css" />
<link rel="stylesheet" href="/static/rehype-attention-block.css" />
<link rel="stylesheet" href="/static/rehype-embedded-github-code.css" />
<Style />

<Script src="/app/client.ts" async />
Expand Down
Loading

0 comments on commit a836b93

Please sign in to comment.