@ox-content/vite-plugin 2.70.0 → 2.72.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.
package/dist/github.cjs CHANGED
@@ -5,38 +5,32 @@ rehype_parse = require_chunk.__toESM(rehype_parse, 1);
5
5
  let rehype_stringify = require("rehype-stringify");
6
6
  rehype_stringify = require_chunk.__toESM(rehype_stringify, 1);
7
7
  let node_buffer = require("node:buffer");
8
- //#region src/plugins/github.ts
9
- /**
10
- * GitHub Plugin - Repository and source code embedding
11
- *
12
- * Transforms <GitHub> components into static repository and source code cards
13
- * by fetching data from GitHub API at build time.
14
- */
15
- var github_exports = /* @__PURE__ */ require_chunk.__exportAll({
16
- collectGitHubRepos: () => collectGitHubRepos,
17
- collectGitHubSources: () => collectGitHubSources,
18
- createGitHubPermalink: () => createGitHubPermalink,
19
- fetchGitHubSource: () => fetchGitHubSource,
20
- fetchRepoData: () => fetchRepoData,
21
- isSafeGitHubRepo: () => isSafeGitHubRepo,
22
- parseGitHubLineRange: () => parseGitHubLineRange,
23
- parseGitHubPermalink: () => parseGitHubPermalink,
24
- prefetchGitHubRepos: () => prefetchGitHubRepos,
25
- prefetchGitHubSources: () => prefetchGitHubSources,
26
- transformGitHub: () => transformGitHub
27
- });
28
- const defaultOptions = {
29
- token: "",
30
- cache: true,
31
- cacheTTL: 36e5,
32
- maxSourceBytes: 2e5,
33
- maxSourceLines: 120
34
- };
35
- const repoCache = /* @__PURE__ */ new Map();
36
- const sourceCache = /* @__PURE__ */ new Map();
8
+ //#region src/plugins/github/validation.ts
37
9
  const GITHUB_REPO_RE = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
38
- const GITHUB_COMPONENT_RE = /<github\b([^>]*)>/gi;
39
- const ATTRIBUTE_RE = /([:\w-]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>/]+)))?/g;
10
+ function hasControlChar(value) {
11
+ for (let index = 0; index < value.length; index++) {
12
+ const code = value.charCodeAt(index);
13
+ if (code <= 31 || code === 127) return true;
14
+ }
15
+ return false;
16
+ }
17
+ function isSafeGitHubRepo(repo) {
18
+ return GITHUB_REPO_RE.test(repo) && !repo.split("/").some((part) => part === "." || part === "..");
19
+ }
20
+ function isSafeGitHubRef(ref) {
21
+ return Boolean(ref) && !hasControlChar(ref) && !hasUnsafePathSegment(ref);
22
+ }
23
+ function isSafeGitHubPath(path) {
24
+ return Boolean(path) && !hasControlChar(path) && !hasUnsafePathSegment(path);
25
+ }
26
+ function hasUnsafePathSegment(value) {
27
+ return value.split("/").some((part) => !part || part === "." || part === ".." || part.includes("\\"));
28
+ }
29
+ function encodePath(path) {
30
+ return path.split("/").map(encodeURIComponent).join("/");
31
+ }
32
+ //#endregion
33
+ //#region src/plugins/github/source.ts
40
34
  const EXTENSION_LANGUAGE_MAP = new Map([
41
35
  ["cjs", "javascript"],
42
36
  ["css", "css"],
@@ -60,28 +54,6 @@ const EXTENSION_LANGUAGE_MAP = new Map([
60
54
  ["yaml", "yaml"],
61
55
  ["yml", "yaml"]
62
56
  ]);
63
- function hasControlChar(value) {
64
- for (let index = 0; index < value.length; index++) {
65
- const code = value.charCodeAt(index);
66
- if (code <= 31 || code === 127) return true;
67
- }
68
- return false;
69
- }
70
- function isSafeGitHubRepo(repo) {
71
- return GITHUB_REPO_RE.test(repo) && !repo.split("/").some((part) => part === "." || part === "..");
72
- }
73
- function isSafeGitHubRef(ref) {
74
- return Boolean(ref) && !hasControlChar(ref) && !hasUnsafePathSegment(ref);
75
- }
76
- function isSafeGitHubPath(path) {
77
- return Boolean(path) && !hasControlChar(path) && !hasUnsafePathSegment(path);
78
- }
79
- function hasUnsafePathSegment(value) {
80
- return value.split("/").some((part) => !part || part === "." || part === ".." || part.includes("\\"));
81
- }
82
- function encodePath(path) {
83
- return path.split("/").map(encodeURIComponent).join("/");
84
- }
85
57
  function sourceKey(source) {
86
58
  return `${source.repo}@${source.ref}:${source.path}`;
87
59
  }
@@ -134,21 +106,33 @@ function parseGitHubPermalink(value) {
134
106
  permalink: createGitHubPermalink(source)
135
107
  };
136
108
  }
137
- /**
138
- * Get element attribute value.
139
- */
140
- function getAttribute(el, name) {
141
- const value = el.properties?.[name];
142
- if (typeof value === "string") return value;
143
- if (Array.isArray(value)) return value.join(" ");
109
+ function inferLanguage(path) {
110
+ const fileName = path.split("/").at(-1)?.toLowerCase() ?? "";
111
+ if (fileName === "dockerfile") return "dockerfile";
112
+ if (fileName === "makefile") return "makefile";
113
+ const extension = fileName.includes(".") ? fileName.split(".").at(-1) : void 0;
114
+ return extension ? EXTENSION_LANGUAGE_MAP.get(extension) ?? extension : null;
144
115
  }
145
- /**
146
- * Format number with K/M suffix.
147
- */
148
- function formatNumber(num) {
149
- if (num >= 1e6) return `${(num / 1e6).toFixed(1)}M`;
150
- if (num >= 1e3) return `${(num / 1e3).toFixed(1)}k`;
151
- return String(num);
116
+ //#endregion
117
+ //#region src/plugins/github/types.ts
118
+ const defaultOptions = {
119
+ token: "",
120
+ cache: true,
121
+ cacheTTL: 36e5,
122
+ maxSourceBytes: 2e5,
123
+ maxSourceLines: 120
124
+ };
125
+ //#endregion
126
+ //#region src/plugins/github/api.ts
127
+ const repoCache = /* @__PURE__ */ new Map();
128
+ const sourceCache = /* @__PURE__ */ new Map();
129
+ function githubHeaders(options) {
130
+ const headers = {
131
+ Accept: "application/vnd.github.v3+json",
132
+ "User-Agent": "ox-content-github-plugin"
133
+ };
134
+ if (options.token) headers.Authorization = `Bearer ${options.token}`;
135
+ return headers;
152
136
  }
153
137
  /**
154
138
  * Fetch repository data from GitHub API.
@@ -160,12 +144,7 @@ async function fetchRepoData(repo, options) {
160
144
  if (cached && Date.now() - cached.timestamp < options.cacheTTL) return cached.data;
161
145
  }
162
146
  try {
163
- const headers = {
164
- Accept: "application/vnd.github.v3+json",
165
- "User-Agent": "ox-content-github-plugin"
166
- };
167
- if (options.token) headers.Authorization = `Bearer ${options.token}`;
168
- const response = await fetch(`https://api.github.com/repos/${repo}`, { headers });
147
+ const response = await fetch(`https://api.github.com/repos/${repo}`, { headers: githubHeaders(options) });
169
148
  if (!response.ok) {
170
149
  console.warn(`Failed to fetch GitHub repo ${repo}: ${response.status}`);
171
150
  return null;
@@ -192,13 +171,8 @@ async function fetchGitHubSource(source, options) {
192
171
  if (cached && Date.now() - cached.timestamp < options.cacheTTL) return cached.data;
193
172
  }
194
173
  try {
195
- const headers = {
196
- Accept: "application/vnd.github.v3+json",
197
- "User-Agent": "ox-content-github-plugin"
198
- };
199
- if (options.token) headers.Authorization = `Bearer ${options.token}`;
200
174
  const apiUrl = `https://api.github.com/repos/${source.repo}/contents/${encodePath(source.path)}?ref=${encodeURIComponent(source.ref)}`;
201
- const response = await fetch(apiUrl, { headers });
175
+ const response = await fetch(apiUrl, { headers: githubHeaders(options) });
202
176
  if (!response.ok) {
203
177
  console.warn(`Failed to fetch GitHub source ${source.permalink}: ${response.status}`);
204
178
  return null;
@@ -228,9 +202,189 @@ async function fetchGitHubSource(source, options) {
228
202
  }
229
203
  }
230
204
  /**
231
- * Create GitHub card element from repo data.
205
+ * Pre-fetch all GitHub repos data.
232
206
  */
233
- function createGitHubCard(repoData) {
207
+ async function prefetchGitHubRepos(repos, options) {
208
+ const mergedOptions = {
209
+ ...defaultOptions,
210
+ ...options
211
+ };
212
+ const results = /* @__PURE__ */ new Map();
213
+ await Promise.all(Array.from(new Set(repos)).map(async (repo) => {
214
+ const data = await fetchRepoData(repo, mergedOptions);
215
+ results.set(repo, data);
216
+ }));
217
+ return results;
218
+ }
219
+ /**
220
+ * Pre-fetch all GitHub source files.
221
+ */
222
+ async function prefetchGitHubSources(sources, options) {
223
+ const mergedOptions = {
224
+ ...defaultOptions,
225
+ ...options
226
+ };
227
+ const results = /* @__PURE__ */ new Map();
228
+ const uniqueSources = Array.from(new Map(sources.map((source) => [sourceKey(source), source])).values());
229
+ await Promise.all(uniqueSources.map(async (source) => {
230
+ const data = await fetchGitHubSource(source, mergedOptions);
231
+ results.set(sourceKey(source), data);
232
+ }));
233
+ return results;
234
+ }
235
+ //#endregion
236
+ //#region src/plugins/github/attributes.ts
237
+ const GITHUB_COMPONENT_RE = /<github\b([^>]*)>/gi;
238
+ const ATTRIBUTE_RE = /([:\w-]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>/]+)))?/g;
239
+ /**
240
+ * Collect all GitHub repos from HTML for pre-fetching.
241
+ */
242
+ async function collectGitHubRepos(html) {
243
+ const repos = [];
244
+ GITHUB_COMPONENT_RE.lastIndex = 0;
245
+ let match;
246
+ while ((match = GITHUB_COMPONENT_RE.exec(html)) !== null) {
247
+ const attrs = parseAttributes(match[1]);
248
+ if (attrs.path || attrs.file || attrs.permalink || attrs.url || attrs.href) continue;
249
+ const repo = attrs.repo;
250
+ if (repo && isSafeGitHubRepo(repo)) repos.push(repo);
251
+ }
252
+ return repos;
253
+ }
254
+ /**
255
+ * Collect all GitHub source references from HTML for pre-fetching.
256
+ */
257
+ async function collectGitHubSources(html) {
258
+ const sources = [];
259
+ GITHUB_COMPONENT_RE.lastIndex = 0;
260
+ let match;
261
+ while ((match = GITHUB_COMPONENT_RE.exec(html)) !== null) {
262
+ const source = sourceRefFromAttributes(parseAttributes(match[1]));
263
+ if (source) sources.push(source);
264
+ }
265
+ return sources;
266
+ }
267
+ function parseAttributes(raw) {
268
+ const attrs = {};
269
+ ATTRIBUTE_RE.lastIndex = 0;
270
+ let match;
271
+ while ((match = ATTRIBUTE_RE.exec(raw)) !== null) attrs[match[1].toLowerCase()] = match[2] ?? match[3] ?? match[4] ?? "";
272
+ return attrs;
273
+ }
274
+ function attributesFromElement(el) {
275
+ const attrs = {};
276
+ for (const name of [
277
+ "permalink",
278
+ "url",
279
+ "href",
280
+ "repo",
281
+ "path",
282
+ "file",
283
+ "ref",
284
+ "sha",
285
+ "branch",
286
+ "loc",
287
+ "lines",
288
+ "line"
289
+ ]) {
290
+ const value = getAttribute(el, name);
291
+ if (value !== void 0) attrs[name] = value;
292
+ }
293
+ return attrs;
294
+ }
295
+ function getAttribute(el, name) {
296
+ const value = el.properties?.[name];
297
+ if (typeof value === "string") return value;
298
+ if (Array.isArray(value)) return value.join(" ");
299
+ }
300
+ function sourceRefFromAttributes(attrs) {
301
+ const permalink = attrs.permalink ?? attrs.url ?? attrs.href;
302
+ if (permalink) return parseGitHubPermalink(permalink);
303
+ const repo = attrs.repo;
304
+ const path = attrs.path ?? attrs.file;
305
+ if (!repo || !path || !isSafeGitHubRepo(repo) || !isSafeGitHubPath(path)) return null;
306
+ const ref = attrs.ref ?? attrs.sha ?? attrs.branch ?? "main";
307
+ if (!isSafeGitHubRef(ref)) return null;
308
+ const source = {
309
+ repo,
310
+ ref,
311
+ path,
312
+ lines: parseGitHubLineRange(attrs.loc ?? attrs.lines ?? attrs.line)
313
+ };
314
+ return {
315
+ ...source,
316
+ permalink: createGitHubPermalink(source)
317
+ };
318
+ }
319
+ //#endregion
320
+ //#region src/plugins/github/fallback-card.ts
321
+ /**
322
+ * Create fallback element when repo data is unavailable.
323
+ */
324
+ function createFallbackCard(repo) {
325
+ return {
326
+ type: "element",
327
+ tagName: "a",
328
+ properties: {
329
+ className: ["ox-github-card", "error"],
330
+ href: isSafeGitHubRepo(repo) ? `https://github.com/${repo}` : "#",
331
+ target: "_blank",
332
+ rel: "noopener noreferrer"
333
+ },
334
+ children: [{
335
+ type: "element",
336
+ tagName: "div",
337
+ properties: { className: ["ox-github-header"] },
338
+ children: [{
339
+ type: "element",
340
+ tagName: "svg",
341
+ properties: {
342
+ className: ["ox-github-icon"],
343
+ viewBox: "0 0 16 16",
344
+ fill: "currentColor"
345
+ },
346
+ children: [{
347
+ type: "element",
348
+ tagName: "path",
349
+ properties: { 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" },
350
+ children: []
351
+ }]
352
+ }, {
353
+ type: "element",
354
+ tagName: "span",
355
+ properties: { className: ["ox-github-repo"] },
356
+ children: [{
357
+ type: "text",
358
+ value: repo
359
+ }]
360
+ }]
361
+ }]
362
+ };
363
+ }
364
+ //#endregion
365
+ //#region src/plugins/github/repo-card.ts
366
+ function formatNumber(num) {
367
+ if (num >= 1e6) return `${(num / 1e6).toFixed(1)}M`;
368
+ if (num >= 1e3) return `${(num / 1e3).toFixed(1)}k`;
369
+ return String(num);
370
+ }
371
+ function iconPath(d) {
372
+ return {
373
+ type: "element",
374
+ tagName: "svg",
375
+ properties: {
376
+ viewBox: "0 0 16 16",
377
+ fill: "currentColor"
378
+ },
379
+ children: [{
380
+ type: "element",
381
+ tagName: "path",
382
+ properties: { d },
383
+ children: []
384
+ }]
385
+ };
386
+ }
387
+ function createStatsChildren(repoData) {
234
388
  const statsChildren = [];
235
389
  if (repoData.language) statsChildren.push({
236
390
  type: "element",
@@ -253,20 +407,7 @@ function createGitHubCard(repoData) {
253
407
  type: "element",
254
408
  tagName: "span",
255
409
  properties: { className: ["ox-github-stat"] },
256
- children: [{
257
- type: "element",
258
- tagName: "svg",
259
- properties: {
260
- viewBox: "0 0 16 16",
261
- fill: "currentColor"
262
- },
263
- children: [{
264
- type: "element",
265
- tagName: "path",
266
- properties: { 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" },
267
- children: []
268
- }]
269
- }, {
410
+ children: [iconPath("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"), {
270
411
  type: "text",
271
412
  value: formatNumber(repoData.stargazers_count)
272
413
  }]
@@ -275,24 +416,17 @@ function createGitHubCard(repoData) {
275
416
  type: "element",
276
417
  tagName: "span",
277
418
  properties: { className: ["ox-github-stat"] },
278
- children: [{
279
- type: "element",
280
- tagName: "svg",
281
- properties: {
282
- viewBox: "0 0 16 16",
283
- fill: "currentColor"
284
- },
285
- children: [{
286
- type: "element",
287
- tagName: "path",
288
- properties: { 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" },
289
- children: []
290
- }]
291
- }, {
419
+ children: [iconPath("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"), {
292
420
  type: "text",
293
421
  value: formatNumber(repoData.forks_count)
294
422
  }]
295
423
  });
424
+ return statsChildren;
425
+ }
426
+ /**
427
+ * Create GitHub card element from repo data.
428
+ */
429
+ function createGitHubCard(repoData) {
296
430
  return {
297
431
  type: "element",
298
432
  tagName: "a",
@@ -308,19 +442,12 @@ function createGitHubCard(repoData) {
308
442
  tagName: "div",
309
443
  properties: { className: ["ox-github-header"] },
310
444
  children: [{
311
- type: "element",
312
- tagName: "svg",
445
+ ...iconPath("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"),
313
446
  properties: {
314
447
  className: ["ox-github-icon"],
315
448
  viewBox: "0 0 16 16",
316
449
  fill: "currentColor"
317
- },
318
- children: [{
319
- type: "element",
320
- tagName: "path",
321
- properties: { 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" },
322
- children: []
323
- }]
450
+ }
324
451
  }, {
325
452
  type: "element",
326
453
  tagName: "span",
@@ -344,61 +471,13 @@ function createGitHubCard(repoData) {
344
471
  type: "element",
345
472
  tagName: "div",
346
473
  properties: { className: ["ox-github-stats"] },
347
- children: statsChildren
474
+ children: createStatsChildren(repoData)
348
475
  }
349
476
  ]
350
477
  };
351
478
  }
352
- /**
353
- * Create fallback element when repo data is unavailable.
354
- */
355
- function createFallbackCard(repo) {
356
- return {
357
- type: "element",
358
- tagName: "a",
359
- properties: {
360
- className: ["ox-github-card", "error"],
361
- href: isSafeGitHubRepo(repo) ? `https://github.com/${repo}` : "#",
362
- target: "_blank",
363
- rel: "noopener noreferrer"
364
- },
365
- children: [{
366
- type: "element",
367
- tagName: "div",
368
- properties: { className: ["ox-github-header"] },
369
- children: [{
370
- type: "element",
371
- tagName: "svg",
372
- properties: {
373
- className: ["ox-github-icon"],
374
- viewBox: "0 0 16 16",
375
- fill: "currentColor"
376
- },
377
- children: [{
378
- type: "element",
379
- tagName: "path",
380
- properties: { 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" },
381
- children: []
382
- }]
383
- }, {
384
- type: "element",
385
- tagName: "span",
386
- properties: { className: ["ox-github-repo"] },
387
- children: [{
388
- type: "text",
389
- value: repo
390
- }]
391
- }]
392
- }]
393
- };
394
- }
395
- function inferLanguage(path) {
396
- const fileName = path.split("/").at(-1)?.toLowerCase() ?? "";
397
- if (fileName === "dockerfile") return "dockerfile";
398
- if (fileName === "makefile") return "makefile";
399
- const extension = fileName.includes(".") ? fileName.split(".").at(-1) : void 0;
400
- return extension ? EXTENSION_LANGUAGE_MAP.get(extension) ?? extension : null;
401
- }
479
+ //#endregion
480
+ //#region src/plugins/github/source-card.ts
402
481
  function normalizeSourceLines(content) {
403
482
  const lines = content.replace(/\r\n?/g, "\n").split("\n");
404
483
  if (lines.length > 1 && lines.at(-1) === "") lines.pop();
@@ -494,112 +573,8 @@ function createGitHubSourceCard(source, lines, options) {
494
573
  }]
495
574
  };
496
575
  }
497
- /**
498
- * Collect all GitHub repos from HTML for pre-fetching.
499
- */
500
- async function collectGitHubRepos(html) {
501
- const repos = [];
502
- GITHUB_COMPONENT_RE.lastIndex = 0;
503
- let match;
504
- while ((match = GITHUB_COMPONENT_RE.exec(html)) !== null) {
505
- const attrs = parseAttributes(match[1]);
506
- if (attrs.path || attrs.file || attrs.permalink || attrs.url || attrs.href) continue;
507
- const repo = attrs.repo;
508
- if (repo && isSafeGitHubRepo(repo)) repos.push(repo);
509
- }
510
- return repos;
511
- }
512
- /**
513
- * Collect all GitHub source references from HTML for pre-fetching.
514
- */
515
- async function collectGitHubSources(html) {
516
- const sources = [];
517
- GITHUB_COMPONENT_RE.lastIndex = 0;
518
- let match;
519
- while ((match = GITHUB_COMPONENT_RE.exec(html)) !== null) {
520
- const source = sourceRefFromAttributes(parseAttributes(match[1]));
521
- if (source) sources.push(source);
522
- }
523
- return sources;
524
- }
525
- function parseAttributes(raw) {
526
- const attrs = {};
527
- ATTRIBUTE_RE.lastIndex = 0;
528
- let match;
529
- while ((match = ATTRIBUTE_RE.exec(raw)) !== null) attrs[match[1].toLowerCase()] = match[2] ?? match[3] ?? match[4] ?? "";
530
- return attrs;
531
- }
532
- function attributesFromElement(el) {
533
- const attrs = {};
534
- for (const name of [
535
- "permalink",
536
- "url",
537
- "href",
538
- "repo",
539
- "path",
540
- "file",
541
- "ref",
542
- "sha",
543
- "branch",
544
- "loc",
545
- "lines",
546
- "line"
547
- ]) {
548
- const value = getAttribute(el, name);
549
- if (value !== void 0) attrs[name] = value;
550
- }
551
- return attrs;
552
- }
553
- function sourceRefFromAttributes(attrs) {
554
- const permalink = attrs.permalink ?? attrs.url ?? attrs.href;
555
- if (permalink) return parseGitHubPermalink(permalink);
556
- const repo = attrs.repo;
557
- const path = attrs.path ?? attrs.file;
558
- if (!repo || !path || !isSafeGitHubRepo(repo) || !isSafeGitHubPath(path)) return null;
559
- const ref = attrs.ref ?? attrs.sha ?? attrs.branch ?? "main";
560
- if (!isSafeGitHubRef(ref)) return null;
561
- const source = {
562
- repo,
563
- ref,
564
- path,
565
- lines: parseGitHubLineRange(attrs.loc ?? attrs.lines ?? attrs.line)
566
- };
567
- return {
568
- ...source,
569
- permalink: createGitHubPermalink(source)
570
- };
571
- }
572
- /**
573
- * Pre-fetch all GitHub repos data.
574
- */
575
- async function prefetchGitHubRepos(repos, options) {
576
- const mergedOptions = {
577
- ...defaultOptions,
578
- ...options
579
- };
580
- const results = /* @__PURE__ */ new Map();
581
- await Promise.all(Array.from(new Set(repos)).map(async (repo) => {
582
- const data = await fetchRepoData(repo, mergedOptions);
583
- results.set(repo, data);
584
- }));
585
- return results;
586
- }
587
- /**
588
- * Pre-fetch all GitHub source files.
589
- */
590
- async function prefetchGitHubSources(sources, options) {
591
- const mergedOptions = {
592
- ...defaultOptions,
593
- ...options
594
- };
595
- const results = /* @__PURE__ */ new Map();
596
- const uniqueSources = Array.from(new Map(sources.map((source) => [sourceKey(source), source])).values());
597
- await Promise.all(uniqueSources.map(async (source) => {
598
- const data = await fetchGitHubSource(source, mergedOptions);
599
- results.set(sourceKey(source), data);
600
- }));
601
- return results;
602
- }
576
+ //#endregion
577
+ //#region src/plugins/github/transform.ts
603
578
  /**
604
579
  * Rehype plugin to transform GitHub components.
605
580
  */
@@ -608,21 +583,23 @@ function rehypeGitHub(repoDataMap, sourceDataMap, options) {
608
583
  const visit = (node) => {
609
584
  if ("children" in node) for (let i = 0; i < node.children.length; i++) {
610
585
  const child = node.children[i];
611
- if (child.type === "element") if (child.tagName.toLowerCase() === "github") {
612
- const attrs = attributesFromElement(child);
613
- const source = sourceRefFromAttributes(attrs);
614
- if (source) {
615
- const sourceData = sourceDataMap.get(sourceKey(source));
616
- node.children[i] = sourceData ? createGitHubSourceCard(sourceData, source.lines, options) : createFallbackCard(source.permalink);
617
- continue;
618
- }
619
- const repo = attrs.repo;
620
- if (repo) {
621
- const repoData = repoDataMap.get(repo);
622
- const cardElement = repoData ? createGitHubCard(repoData) : createFallbackCard(repo);
623
- node.children[i] = cardElement;
624
- }
625
- } else visit(child);
586
+ if (child.type !== "element") continue;
587
+ if (child.tagName.toLowerCase() !== "github") {
588
+ visit(child);
589
+ continue;
590
+ }
591
+ const attrs = attributesFromElement(child);
592
+ const source = sourceRefFromAttributes(attrs);
593
+ if (source) {
594
+ const sourceData = sourceDataMap.get(sourceKey(source));
595
+ node.children[i] = sourceData ? createGitHubSourceCard(sourceData, source.lines, options) : createFallbackCard(source.permalink);
596
+ continue;
597
+ }
598
+ const repo = attrs.repo;
599
+ if (repo) {
600
+ const repoData = repoDataMap.get(repo);
601
+ node.children[i] = repoData ? createGitHubCard(repoData) : createFallbackCard(repo);
602
+ }
626
603
  }
627
604
  };
628
605
  visit(tree);
@@ -643,6 +620,9 @@ async function transformGitHub(html, repoDataMap, options) {
643
620
  return String(result);
644
621
  }
645
622
  //#endregion
623
+ //#region src/plugins/github.ts
624
+ var github_exports = /* @__PURE__ */ require_chunk.__exportAll({ transformGitHub: () => transformGitHub });
625
+ //#endregion
646
626
  Object.defineProperty(exports, "collectGitHubRepos", {
647
627
  enumerable: true,
648
628
  get: function() {