@ox-content/vite-plugin 0.4.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"github2.cjs","names":["rehypeParse","rehypeStringify"],"sources":["../src/plugins/github.ts"],"sourcesContent":["/**\n * GitHub Plugin - Repository card embedding\n *\n * Transforms <GitHub> components into static repository cards\n * by fetching data from GitHub API at build time.\n */\n\nimport { unified } from \"unified\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeStringify from \"rehype-stringify\";\nimport type { Root, Element } from \"hast\";\n\nexport interface GitHubRepoData {\n name: string;\n full_name: string;\n description: string | null;\n html_url: string;\n stargazers_count: number;\n forks_count: number;\n language: string | null;\n owner: {\n login: string;\n avatar_url: string;\n };\n}\n\nexport interface GitHubOptions {\n /** GitHub API token for higher rate limits. */\n token?: string;\n /** Cache fetched data. Default: true */\n cache?: boolean;\n /** Cache TTL in milliseconds. Default: 3600000 (1 hour) */\n cacheTTL?: number;\n}\n\nconst defaultOptions: Required<GitHubOptions> = {\n token: \"\",\n cache: true,\n cacheTTL: 3600000,\n};\n\n// Simple in-memory cache\nconst repoCache = new Map<string, { data: GitHubRepoData; timestamp: number }>();\n\n/**\n * Get element attribute value.\n */\nfunction getAttribute(el: Element, name: string): string | undefined {\n const value = el.properties?.[name];\n if (typeof value === \"string\") return value;\n if (Array.isArray(value)) return value.join(\" \");\n return undefined;\n}\n\n/**\n * Format number with K/M suffix.\n */\nfunction formatNumber(num: number): string {\n if (num >= 1000000) {\n return `${(num / 1000000).toFixed(1)}M`;\n }\n if (num >= 1000) {\n return `${(num / 1000).toFixed(1)}k`;\n }\n return String(num);\n}\n\n/**\n * Fetch repository data from GitHub API.\n */\nexport async function fetchRepoData(repo: string, options: Required<GitHubOptions>): Promise<GitHubRepoData | null> {\n // Check cache\n if (options.cache) {\n const cached = repoCache.get(repo);\n if (cached && Date.now() - cached.timestamp < options.cacheTTL) {\n return cached.data;\n }\n }\n\n try {\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github.v3+json\",\n \"User-Agent\": \"ox-content-github-plugin\",\n };\n\n if (options.token) {\n headers.Authorization = `Bearer ${options.token}`;\n }\n\n const response = await fetch(`https://api.github.com/repos/${repo}`, { headers });\n\n if (!response.ok) {\n console.warn(`Failed to fetch GitHub repo ${repo}: ${response.status}`);\n return null;\n }\n\n const data = (await response.json()) as GitHubRepoData;\n\n // Cache the result\n if (options.cache) {\n repoCache.set(repo, { data, timestamp: Date.now() });\n }\n\n return data;\n } catch (error) {\n console.warn(`Error fetching GitHub repo ${repo}:`, error);\n return null;\n }\n}\n\n/**\n * Create GitHub card element from repo data.\n */\nfunction createGitHubCard(repoData: GitHubRepoData): Element {\n const statsChildren: Element[\"children\"] = [];\n\n // Language\n if (repoData.language) {\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-language\"] },\n children: [\n {\n type: \"element\",\n tagName: \"span\",\n properties: {\n className: [\"ox-github-language-color\"],\n \"data-lang\": repoData.language.toLowerCase(),\n },\n children: [],\n },\n { type: \"text\", value: repoData.language },\n ],\n });\n }\n\n // Stars\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-stat\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z\",\n },\n children: [],\n },\n ],\n },\n { type: \"text\", value: formatNumber(repoData.stargazers_count) },\n ],\n });\n\n // Forks\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-stat\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z\",\n },\n children: [],\n },\n ],\n },\n { type: \"text\", value: formatNumber(repoData.forks_count) },\n ],\n });\n\n return {\n type: \"element\",\n tagName: \"a\",\n properties: {\n className: [\"ox-github-card\"],\n href: repoData.html_url,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n children: [\n // Header\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-header\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n className: [\"ox-github-icon\"],\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z\",\n },\n children: [],\n },\n ],\n },\n {\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-repo\"] },\n children: [{ type: \"text\", value: repoData.full_name }],\n },\n ],\n },\n // Description\n ...(repoData.description\n ? [\n {\n type: \"element\" as const,\n tagName: \"p\",\n properties: { className: [\"ox-github-description\"] },\n children: [{ type: \"text\" as const, value: repoData.description }],\n },\n ]\n : []),\n // Stats\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-stats\"] },\n children: statsChildren,\n },\n ],\n };\n}\n\n/**\n * Create fallback element when repo data is unavailable.\n */\nfunction createFallbackCard(repo: string): Element {\n return {\n type: \"element\",\n tagName: \"a\",\n properties: {\n className: [\"ox-github-card\", \"error\"],\n href: `https://github.com/${repo}`,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-header\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n className: [\"ox-github-icon\"],\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z\",\n },\n children: [],\n },\n ],\n },\n {\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-repo\"] },\n children: [{ type: \"text\", value: repo }],\n },\n ],\n },\n ],\n };\n}\n\n/**\n * Collect all GitHub repos from HTML for pre-fetching.\n */\nexport async function collectGitHubRepos(html: string): Promise<string[]> {\n const repos: string[] = [];\n const repoPattern = /<github[^>]*\\s+repo=[\"']([^\"']+)[\"']/gi;\n\n let match;\n while ((match = repoPattern.exec(html)) !== null) {\n repos.push(match[1]);\n }\n\n return repos;\n}\n\n/**\n * Pre-fetch all GitHub repos data.\n */\nexport async function prefetchGitHubRepos(\n repos: string[],\n options?: GitHubOptions,\n): Promise<Map<string, GitHubRepoData | null>> {\n const mergedOptions = { ...defaultOptions, ...options };\n const results = new Map<string, GitHubRepoData | null>();\n\n await Promise.all(\n repos.map(async (repo) => {\n const data = await fetchRepoData(repo, mergedOptions);\n results.set(repo, data);\n }),\n );\n\n return results;\n}\n\n/**\n * Rehype plugin to transform GitHub components.\n */\nfunction rehypeGitHub(repoDataMap: Map<string, GitHubRepoData | null>) {\n return (tree: Root) => {\n const visit = (node: Root | Element) => {\n if (\"children\" in node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n\n if (child.type === \"element\") {\n // Check for <GitHub> component\n if (child.tagName.toLowerCase() === \"github\") {\n const repo = getAttribute(child, \"repo\");\n\n if (repo) {\n const repoData = repoDataMap.get(repo);\n const cardElement = repoData ? createGitHubCard(repoData) : createFallbackCard(repo);\n node.children[i] = cardElement;\n }\n } else {\n visit(child);\n }\n }\n }\n }\n };\n\n visit(tree);\n };\n}\n\n/**\n * Transform GitHub components in HTML.\n */\nexport async function transformGitHub(\n html: string,\n repoDataMap?: Map<string, GitHubRepoData | null>,\n options?: GitHubOptions,\n): Promise<string> {\n // If no pre-fetched data, collect and fetch\n let dataMap = repoDataMap;\n if (!dataMap) {\n const repos = await collectGitHubRepos(html);\n dataMap = await prefetchGitHubRepos(repos, options);\n }\n\n const result = await unified()\n .use(rehypeParse, { fragment: true })\n .use(rehypeGitHub, dataMap)\n .use(rehypeStringify)\n .process(html);\n\n return String(result);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"github2.cjs","names":["rehypeParse","rehypeStringify"],"sources":["../src/plugins/github.ts"],"sourcesContent":["/**\n * GitHub Plugin - Repository card embedding\n *\n * Transforms <GitHub> components into static repository cards\n * by fetching data from GitHub API at build time.\n */\n\nimport { unified } from \"unified\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeStringify from \"rehype-stringify\";\nimport type { Root, Element } from \"hast\";\n\nexport interface GitHubRepoData {\n name: string;\n full_name: string;\n description: string | null;\n html_url: string;\n stargazers_count: number;\n forks_count: number;\n language: string | null;\n owner: {\n login: string;\n avatar_url: string;\n };\n}\n\nexport interface GitHubOptions {\n /** GitHub API token for higher rate limits. */\n token?: string;\n /** Cache fetched data. Default: true */\n cache?: boolean;\n /** Cache TTL in milliseconds. Default: 3600000 (1 hour) */\n cacheTTL?: number;\n}\n\nconst defaultOptions: Required<GitHubOptions> = {\n token: \"\",\n cache: true,\n cacheTTL: 3600000,\n};\n\n// Simple in-memory cache\nconst repoCache = new Map<string, { data: GitHubRepoData; timestamp: number }>();\n\n/**\n * Get element attribute value.\n */\nfunction getAttribute(el: Element, name: string): string | undefined {\n const value = el.properties?.[name];\n if (typeof value === \"string\") return value;\n if (Array.isArray(value)) return value.join(\" \");\n return undefined;\n}\n\n/**\n * Format number with K/M suffix.\n */\nfunction formatNumber(num: number): string {\n if (num >= 1000000) {\n return `${(num / 1000000).toFixed(1)}M`;\n }\n if (num >= 1000) {\n return `${(num / 1000).toFixed(1)}k`;\n }\n return String(num);\n}\n\n/**\n * Fetch repository data from GitHub API.\n */\nexport async function fetchRepoData(\n repo: string,\n options: Required<GitHubOptions>,\n): Promise<GitHubRepoData | null> {\n // Check cache\n if (options.cache) {\n const cached = repoCache.get(repo);\n if (cached && Date.now() - cached.timestamp < options.cacheTTL) {\n return cached.data;\n }\n }\n\n try {\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github.v3+json\",\n \"User-Agent\": \"ox-content-github-plugin\",\n };\n\n if (options.token) {\n headers.Authorization = `Bearer ${options.token}`;\n }\n\n const response = await fetch(`https://api.github.com/repos/${repo}`, { headers });\n\n if (!response.ok) {\n console.warn(`Failed to fetch GitHub repo ${repo}: ${response.status}`);\n return null;\n }\n\n const data = (await response.json()) as GitHubRepoData;\n\n // Cache the result\n if (options.cache) {\n repoCache.set(repo, { data, timestamp: Date.now() });\n }\n\n return data;\n } catch (error) {\n console.warn(`Error fetching GitHub repo ${repo}:`, error);\n return null;\n }\n}\n\n/**\n * Create GitHub card element from repo data.\n */\nfunction createGitHubCard(repoData: GitHubRepoData): Element {\n const statsChildren: Element[\"children\"] = [];\n\n // Language\n if (repoData.language) {\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-language\"] },\n children: [\n {\n type: \"element\",\n tagName: \"span\",\n properties: {\n className: [\"ox-github-language-color\"],\n \"data-lang\": repoData.language.toLowerCase(),\n },\n children: [],\n },\n { type: \"text\", value: repoData.language },\n ],\n });\n }\n\n // Stars\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-stat\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z\",\n },\n children: [],\n },\n ],\n },\n { type: \"text\", value: formatNumber(repoData.stargazers_count) },\n ],\n });\n\n // Forks\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-stat\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z\",\n },\n children: [],\n },\n ],\n },\n { type: \"text\", value: formatNumber(repoData.forks_count) },\n ],\n });\n\n return {\n type: \"element\",\n tagName: \"a\",\n properties: {\n className: [\"ox-github-card\"],\n href: repoData.html_url,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n children: [\n // Header\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-header\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n className: [\"ox-github-icon\"],\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z\",\n },\n children: [],\n },\n ],\n },\n {\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-repo\"] },\n children: [{ type: \"text\", value: repoData.full_name }],\n },\n ],\n },\n // Description\n ...(repoData.description\n ? [\n {\n type: \"element\" as const,\n tagName: \"p\",\n properties: { className: [\"ox-github-description\"] },\n children: [{ type: \"text\" as const, value: repoData.description }],\n },\n ]\n : []),\n // Stats\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-stats\"] },\n children: statsChildren,\n },\n ],\n };\n}\n\n/**\n * Create fallback element when repo data is unavailable.\n */\nfunction createFallbackCard(repo: string): Element {\n return {\n type: \"element\",\n tagName: \"a\",\n properties: {\n className: [\"ox-github-card\", \"error\"],\n href: `https://github.com/${repo}`,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-header\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n className: [\"ox-github-icon\"],\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z\",\n },\n children: [],\n },\n ],\n },\n {\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-repo\"] },\n children: [{ type: \"text\", value: repo }],\n },\n ],\n },\n ],\n };\n}\n\n/**\n * Collect all GitHub repos from HTML for pre-fetching.\n */\nexport async function collectGitHubRepos(html: string): Promise<string[]> {\n const repos: string[] = [];\n const repoPattern = /<github[^>]*\\s+repo=[\"']([^\"']+)[\"']/gi;\n\n let match;\n while ((match = repoPattern.exec(html)) !== null) {\n repos.push(match[1]);\n }\n\n return repos;\n}\n\n/**\n * Pre-fetch all GitHub repos data.\n */\nexport async function prefetchGitHubRepos(\n repos: string[],\n options?: GitHubOptions,\n): Promise<Map<string, GitHubRepoData | null>> {\n const mergedOptions = { ...defaultOptions, ...options };\n const results = new Map<string, GitHubRepoData | null>();\n\n await Promise.all(\n repos.map(async (repo) => {\n const data = await fetchRepoData(repo, mergedOptions);\n results.set(repo, data);\n }),\n );\n\n return results;\n}\n\n/**\n * Rehype plugin to transform GitHub components.\n */\nfunction rehypeGitHub(repoDataMap: Map<string, GitHubRepoData | null>) {\n return (tree: Root) => {\n const visit = (node: Root | Element) => {\n if (\"children\" in node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n\n if (child.type === \"element\") {\n // Check for <GitHub> component\n if (child.tagName.toLowerCase() === \"github\") {\n const repo = getAttribute(child, \"repo\");\n\n if (repo) {\n const repoData = repoDataMap.get(repo);\n const cardElement = repoData\n ? createGitHubCard(repoData)\n : createFallbackCard(repo);\n node.children[i] = cardElement;\n }\n } else {\n visit(child);\n }\n }\n }\n }\n };\n\n visit(tree);\n };\n}\n\n/**\n * Transform GitHub components in HTML.\n */\nexport async function transformGitHub(\n html: string,\n repoDataMap?: Map<string, GitHubRepoData | null>,\n options?: GitHubOptions,\n): Promise<string> {\n // If no pre-fetched data, collect and fetch\n let dataMap = repoDataMap;\n if (!dataMap) {\n const repos = await collectGitHubRepos(html);\n dataMap = await prefetchGitHubRepos(repos, options);\n }\n\n const result = await unified()\n .use(rehypeParse, { fragment: true })\n .use(rehypeGitHub, dataMap)\n .use(rehypeStringify)\n .process(html);\n\n return String(result);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"github2.js","names":[],"sources":["../src/plugins/github.ts"],"sourcesContent":["/**\n * GitHub Plugin - Repository card embedding\n *\n * Transforms <GitHub> components into static repository cards\n * by fetching data from GitHub API at build time.\n */\n\nimport { unified } from \"unified\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeStringify from \"rehype-stringify\";\nimport type { Root, Element } from \"hast\";\n\nexport interface GitHubRepoData {\n name: string;\n full_name: string;\n description: string | null;\n html_url: string;\n stargazers_count: number;\n forks_count: number;\n language: string | null;\n owner: {\n login: string;\n avatar_url: string;\n };\n}\n\nexport interface GitHubOptions {\n /** GitHub API token for higher rate limits. */\n token?: string;\n /** Cache fetched data. Default: true */\n cache?: boolean;\n /** Cache TTL in milliseconds. Default: 3600000 (1 hour) */\n cacheTTL?: number;\n}\n\nconst defaultOptions: Required<GitHubOptions> = {\n token: \"\",\n cache: true,\n cacheTTL: 3600000,\n};\n\n// Simple in-memory cache\nconst repoCache = new Map<string, { data: GitHubRepoData; timestamp: number }>();\n\n/**\n * Get element attribute value.\n */\nfunction getAttribute(el: Element, name: string): string | undefined {\n const value = el.properties?.[name];\n if (typeof value === \"string\") return value;\n if (Array.isArray(value)) return value.join(\" \");\n return undefined;\n}\n\n/**\n * Format number with K/M suffix.\n */\nfunction formatNumber(num: number): string {\n if (num >= 1000000) {\n return `${(num / 1000000).toFixed(1)}M`;\n }\n if (num >= 1000) {\n return `${(num / 1000).toFixed(1)}k`;\n }\n return String(num);\n}\n\n/**\n * Fetch repository data from GitHub API.\n */\nexport async function fetchRepoData(repo: string, options: Required<GitHubOptions>): Promise<GitHubRepoData | null> {\n // Check cache\n if (options.cache) {\n const cached = repoCache.get(repo);\n if (cached && Date.now() - cached.timestamp < options.cacheTTL) {\n return cached.data;\n }\n }\n\n try {\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github.v3+json\",\n \"User-Agent\": \"ox-content-github-plugin\",\n };\n\n if (options.token) {\n headers.Authorization = `Bearer ${options.token}`;\n }\n\n const response = await fetch(`https://api.github.com/repos/${repo}`, { headers });\n\n if (!response.ok) {\n console.warn(`Failed to fetch GitHub repo ${repo}: ${response.status}`);\n return null;\n }\n\n const data = (await response.json()) as GitHubRepoData;\n\n // Cache the result\n if (options.cache) {\n repoCache.set(repo, { data, timestamp: Date.now() });\n }\n\n return data;\n } catch (error) {\n console.warn(`Error fetching GitHub repo ${repo}:`, error);\n return null;\n }\n}\n\n/**\n * Create GitHub card element from repo data.\n */\nfunction createGitHubCard(repoData: GitHubRepoData): Element {\n const statsChildren: Element[\"children\"] = [];\n\n // Language\n if (repoData.language) {\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-language\"] },\n children: [\n {\n type: \"element\",\n tagName: \"span\",\n properties: {\n className: [\"ox-github-language-color\"],\n \"data-lang\": repoData.language.toLowerCase(),\n },\n children: [],\n },\n { type: \"text\", value: repoData.language },\n ],\n });\n }\n\n // Stars\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-stat\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z\",\n },\n children: [],\n },\n ],\n },\n { type: \"text\", value: formatNumber(repoData.stargazers_count) },\n ],\n });\n\n // Forks\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-stat\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z\",\n },\n children: [],\n },\n ],\n },\n { type: \"text\", value: formatNumber(repoData.forks_count) },\n ],\n });\n\n return {\n type: \"element\",\n tagName: \"a\",\n properties: {\n className: [\"ox-github-card\"],\n href: repoData.html_url,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n children: [\n // Header\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-header\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n className: [\"ox-github-icon\"],\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z\",\n },\n children: [],\n },\n ],\n },\n {\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-repo\"] },\n children: [{ type: \"text\", value: repoData.full_name }],\n },\n ],\n },\n // Description\n ...(repoData.description\n ? [\n {\n type: \"element\" as const,\n tagName: \"p\",\n properties: { className: [\"ox-github-description\"] },\n children: [{ type: \"text\" as const, value: repoData.description }],\n },\n ]\n : []),\n // Stats\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-stats\"] },\n children: statsChildren,\n },\n ],\n };\n}\n\n/**\n * Create fallback element when repo data is unavailable.\n */\nfunction createFallbackCard(repo: string): Element {\n return {\n type: \"element\",\n tagName: \"a\",\n properties: {\n className: [\"ox-github-card\", \"error\"],\n href: `https://github.com/${repo}`,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-header\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n className: [\"ox-github-icon\"],\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z\",\n },\n children: [],\n },\n ],\n },\n {\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-repo\"] },\n children: [{ type: \"text\", value: repo }],\n },\n ],\n },\n ],\n };\n}\n\n/**\n * Collect all GitHub repos from HTML for pre-fetching.\n */\nexport async function collectGitHubRepos(html: string): Promise<string[]> {\n const repos: string[] = [];\n const repoPattern = /<github[^>]*\\s+repo=[\"']([^\"']+)[\"']/gi;\n\n let match;\n while ((match = repoPattern.exec(html)) !== null) {\n repos.push(match[1]);\n }\n\n return repos;\n}\n\n/**\n * Pre-fetch all GitHub repos data.\n */\nexport async function prefetchGitHubRepos(\n repos: string[],\n options?: GitHubOptions,\n): Promise<Map<string, GitHubRepoData | null>> {\n const mergedOptions = { ...defaultOptions, ...options };\n const results = new Map<string, GitHubRepoData | null>();\n\n await Promise.all(\n repos.map(async (repo) => {\n const data = await fetchRepoData(repo, mergedOptions);\n results.set(repo, data);\n }),\n );\n\n return results;\n}\n\n/**\n * Rehype plugin to transform GitHub components.\n */\nfunction rehypeGitHub(repoDataMap: Map<string, GitHubRepoData | null>) {\n return (tree: Root) => {\n const visit = (node: Root | Element) => {\n if (\"children\" in node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n\n if (child.type === \"element\") {\n // Check for <GitHub> component\n if (child.tagName.toLowerCase() === \"github\") {\n const repo = getAttribute(child, \"repo\");\n\n if (repo) {\n const repoData = repoDataMap.get(repo);\n const cardElement = repoData ? createGitHubCard(repoData) : createFallbackCard(repo);\n node.children[i] = cardElement;\n }\n } else {\n visit(child);\n }\n }\n }\n }\n };\n\n visit(tree);\n };\n}\n\n/**\n * Transform GitHub components in HTML.\n */\nexport async function transformGitHub(\n html: string,\n repoDataMap?: Map<string, GitHubRepoData | null>,\n options?: GitHubOptions,\n): Promise<string> {\n // If no pre-fetched data, collect and fetch\n let dataMap = repoDataMap;\n if (!dataMap) {\n const repos = await collectGitHubRepos(html);\n dataMap = await prefetchGitHubRepos(repos, options);\n }\n\n const result = await unified()\n .use(rehypeParse, { fragment: true })\n .use(rehypeGitHub, dataMap)\n .use(rehypeStringify)\n .process(html);\n\n return String(result);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"github2.js","names":[],"sources":["../src/plugins/github.ts"],"sourcesContent":["/**\n * GitHub Plugin - Repository card embedding\n *\n * Transforms <GitHub> components into static repository cards\n * by fetching data from GitHub API at build time.\n */\n\nimport { unified } from \"unified\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeStringify from \"rehype-stringify\";\nimport type { Root, Element } from \"hast\";\n\nexport interface GitHubRepoData {\n name: string;\n full_name: string;\n description: string | null;\n html_url: string;\n stargazers_count: number;\n forks_count: number;\n language: string | null;\n owner: {\n login: string;\n avatar_url: string;\n };\n}\n\nexport interface GitHubOptions {\n /** GitHub API token for higher rate limits. */\n token?: string;\n /** Cache fetched data. Default: true */\n cache?: boolean;\n /** Cache TTL in milliseconds. Default: 3600000 (1 hour) */\n cacheTTL?: number;\n}\n\nconst defaultOptions: Required<GitHubOptions> = {\n token: \"\",\n cache: true,\n cacheTTL: 3600000,\n};\n\n// Simple in-memory cache\nconst repoCache = new Map<string, { data: GitHubRepoData; timestamp: number }>();\n\n/**\n * Get element attribute value.\n */\nfunction getAttribute(el: Element, name: string): string | undefined {\n const value = el.properties?.[name];\n if (typeof value === \"string\") return value;\n if (Array.isArray(value)) return value.join(\" \");\n return undefined;\n}\n\n/**\n * Format number with K/M suffix.\n */\nfunction formatNumber(num: number): string {\n if (num >= 1000000) {\n return `${(num / 1000000).toFixed(1)}M`;\n }\n if (num >= 1000) {\n return `${(num / 1000).toFixed(1)}k`;\n }\n return String(num);\n}\n\n/**\n * Fetch repository data from GitHub API.\n */\nexport async function fetchRepoData(\n repo: string,\n options: Required<GitHubOptions>,\n): Promise<GitHubRepoData | null> {\n // Check cache\n if (options.cache) {\n const cached = repoCache.get(repo);\n if (cached && Date.now() - cached.timestamp < options.cacheTTL) {\n return cached.data;\n }\n }\n\n try {\n const headers: Record<string, string> = {\n Accept: \"application/vnd.github.v3+json\",\n \"User-Agent\": \"ox-content-github-plugin\",\n };\n\n if (options.token) {\n headers.Authorization = `Bearer ${options.token}`;\n }\n\n const response = await fetch(`https://api.github.com/repos/${repo}`, { headers });\n\n if (!response.ok) {\n console.warn(`Failed to fetch GitHub repo ${repo}: ${response.status}`);\n return null;\n }\n\n const data = (await response.json()) as GitHubRepoData;\n\n // Cache the result\n if (options.cache) {\n repoCache.set(repo, { data, timestamp: Date.now() });\n }\n\n return data;\n } catch (error) {\n console.warn(`Error fetching GitHub repo ${repo}:`, error);\n return null;\n }\n}\n\n/**\n * Create GitHub card element from repo data.\n */\nfunction createGitHubCard(repoData: GitHubRepoData): Element {\n const statsChildren: Element[\"children\"] = [];\n\n // Language\n if (repoData.language) {\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-language\"] },\n children: [\n {\n type: \"element\",\n tagName: \"span\",\n properties: {\n className: [\"ox-github-language-color\"],\n \"data-lang\": repoData.language.toLowerCase(),\n },\n children: [],\n },\n { type: \"text\", value: repoData.language },\n ],\n });\n }\n\n // Stars\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-stat\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25Z\",\n },\n children: [],\n },\n ],\n },\n { type: \"text\", value: formatNumber(repoData.stargazers_count) },\n ],\n });\n\n // Forks\n statsChildren.push({\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-stat\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M5 5.372v.878c0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75v-.878a2.25 2.25 0 1 1 1.5 0v.878a2.25 2.25 0 0 1-2.25 2.25h-1.5v2.128a2.251 2.251 0 1 1-1.5 0V8.5h-1.5A2.25 2.25 0 0 1 3.5 6.25v-.878a2.25 2.25 0 1 1 1.5 0ZM5 3.25a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Zm6.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm-3 8.75a.75.75 0 1 0-1.5 0 .75.75 0 0 0 1.5 0Z\",\n },\n children: [],\n },\n ],\n },\n { type: \"text\", value: formatNumber(repoData.forks_count) },\n ],\n });\n\n return {\n type: \"element\",\n tagName: \"a\",\n properties: {\n className: [\"ox-github-card\"],\n href: repoData.html_url,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n children: [\n // Header\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-header\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n className: [\"ox-github-icon\"],\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z\",\n },\n children: [],\n },\n ],\n },\n {\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-repo\"] },\n children: [{ type: \"text\", value: repoData.full_name }],\n },\n ],\n },\n // Description\n ...(repoData.description\n ? [\n {\n type: \"element\" as const,\n tagName: \"p\",\n properties: { className: [\"ox-github-description\"] },\n children: [{ type: \"text\" as const, value: repoData.description }],\n },\n ]\n : []),\n // Stats\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-stats\"] },\n children: statsChildren,\n },\n ],\n };\n}\n\n/**\n * Create fallback element when repo data is unavailable.\n */\nfunction createFallbackCard(repo: string): Element {\n return {\n type: \"element\",\n tagName: \"a\",\n properties: {\n className: [\"ox-github-card\", \"error\"],\n href: `https://github.com/${repo}`,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-github-header\"] },\n children: [\n {\n type: \"element\",\n tagName: \"svg\",\n properties: {\n className: [\"ox-github-icon\"],\n viewBox: \"0 0 16 16\",\n fill: \"currentColor\",\n },\n children: [\n {\n type: \"element\",\n tagName: \"path\",\n properties: {\n d: \"M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z\",\n },\n children: [],\n },\n ],\n },\n {\n type: \"element\",\n tagName: \"span\",\n properties: { className: [\"ox-github-repo\"] },\n children: [{ type: \"text\", value: repo }],\n },\n ],\n },\n ],\n };\n}\n\n/**\n * Collect all GitHub repos from HTML for pre-fetching.\n */\nexport async function collectGitHubRepos(html: string): Promise<string[]> {\n const repos: string[] = [];\n const repoPattern = /<github[^>]*\\s+repo=[\"']([^\"']+)[\"']/gi;\n\n let match;\n while ((match = repoPattern.exec(html)) !== null) {\n repos.push(match[1]);\n }\n\n return repos;\n}\n\n/**\n * Pre-fetch all GitHub repos data.\n */\nexport async function prefetchGitHubRepos(\n repos: string[],\n options?: GitHubOptions,\n): Promise<Map<string, GitHubRepoData | null>> {\n const mergedOptions = { ...defaultOptions, ...options };\n const results = new Map<string, GitHubRepoData | null>();\n\n await Promise.all(\n repos.map(async (repo) => {\n const data = await fetchRepoData(repo, mergedOptions);\n results.set(repo, data);\n }),\n );\n\n return results;\n}\n\n/**\n * Rehype plugin to transform GitHub components.\n */\nfunction rehypeGitHub(repoDataMap: Map<string, GitHubRepoData | null>) {\n return (tree: Root) => {\n const visit = (node: Root | Element) => {\n if (\"children\" in node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n\n if (child.type === \"element\") {\n // Check for <GitHub> component\n if (child.tagName.toLowerCase() === \"github\") {\n const repo = getAttribute(child, \"repo\");\n\n if (repo) {\n const repoData = repoDataMap.get(repo);\n const cardElement = repoData\n ? createGitHubCard(repoData)\n : createFallbackCard(repo);\n node.children[i] = cardElement;\n }\n } else {\n visit(child);\n }\n }\n }\n }\n };\n\n visit(tree);\n };\n}\n\n/**\n * Transform GitHub components in HTML.\n */\nexport async function transformGitHub(\n html: string,\n repoDataMap?: Map<string, GitHubRepoData | null>,\n options?: GitHubOptions,\n): Promise<string> {\n // If no pre-fetched data, collect and fetch\n let dataMap = repoDataMap;\n if (!dataMap) {\n const repos = await collectGitHubRepos(html);\n dataMap = await prefetchGitHubRepos(repos, options);\n }\n\n const result = await unified()\n .use(rehypeParse, { fragment: true })\n .use(rehypeGitHub, dataMap)\n .use(rehypeStringify)\n .process(html);\n\n return String(result);\n}\n"],"mappings":"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"}