@ox-content/vite-plugin 2.69.0 → 2.71.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.mjs CHANGED
@@ -1,2 +1,622 @@
1
- import { d as transformGitHub } from "./github2.mjs";
2
- export { transformGitHub };
1
+ import { unified } from "unified";
2
+ import rehypeParse from "rehype-parse";
3
+ import rehypeStringify from "rehype-stringify";
4
+ import { Buffer } from "node:buffer";
5
+ //#region src/plugins/github/validation.ts
6
+ const GITHUB_REPO_RE = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
7
+ function hasControlChar(value) {
8
+ for (let index = 0; index < value.length; index++) {
9
+ const code = value.charCodeAt(index);
10
+ if (code <= 31 || code === 127) return true;
11
+ }
12
+ return false;
13
+ }
14
+ function isSafeGitHubRepo(repo) {
15
+ return GITHUB_REPO_RE.test(repo) && !repo.split("/").some((part) => part === "." || part === "..");
16
+ }
17
+ function isSafeGitHubRef(ref) {
18
+ return Boolean(ref) && !hasControlChar(ref) && !hasUnsafePathSegment(ref);
19
+ }
20
+ function isSafeGitHubPath(path) {
21
+ return Boolean(path) && !hasControlChar(path) && !hasUnsafePathSegment(path);
22
+ }
23
+ function hasUnsafePathSegment(value) {
24
+ return value.split("/").some((part) => !part || part === "." || part === ".." || part.includes("\\"));
25
+ }
26
+ function encodePath(path) {
27
+ return path.split("/").map(encodeURIComponent).join("/");
28
+ }
29
+ //#endregion
30
+ //#region src/plugins/github/source.ts
31
+ const EXTENSION_LANGUAGE_MAP = new Map([
32
+ ["cjs", "javascript"],
33
+ ["css", "css"],
34
+ ["go", "go"],
35
+ ["html", "html"],
36
+ ["js", "javascript"],
37
+ ["json", "json"],
38
+ ["jsx", "jsx"],
39
+ ["md", "markdown"],
40
+ ["mdx", "mdx"],
41
+ ["mjs", "javascript"],
42
+ ["py", "python"],
43
+ ["rb", "ruby"],
44
+ ["rs", "rust"],
45
+ ["sh", "shell"],
46
+ ["svelte", "svelte"],
47
+ ["toml", "toml"],
48
+ ["ts", "typescript"],
49
+ ["tsx", "tsx"],
50
+ ["vue", "vue"],
51
+ ["yaml", "yaml"],
52
+ ["yml", "yaml"]
53
+ ]);
54
+ function sourceKey(source) {
55
+ return `${source.repo}@${source.ref}:${source.path}`;
56
+ }
57
+ function formatLineRange(lines) {
58
+ return lines.start === lines.end ? `L${lines.start}` : `L${lines.start}-L${lines.end}`;
59
+ }
60
+ function parseGitHubLineRange(value) {
61
+ if (!value) return void 0;
62
+ const match = value.trim().match(/^#?L?(\d+)(?:-L?(\d+))?$/i);
63
+ if (!match) return void 0;
64
+ const start = Number.parseInt(match[1], 10);
65
+ const end = match[2] ? Number.parseInt(match[2], 10) : start;
66
+ if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 1 || end < start) return;
67
+ return {
68
+ start,
69
+ end
70
+ };
71
+ }
72
+ function createGitHubPermalink(source) {
73
+ const fragment = source.lines ? `#${formatLineRange(source.lines)}` : "";
74
+ return `https://github.com/${source.repo}/blob/${encodeURIComponent(source.ref)}/${encodePath(source.path)}${fragment}`;
75
+ }
76
+ function parseGitHubPermalink(value) {
77
+ let url;
78
+ try {
79
+ url = new URL(value);
80
+ } catch {
81
+ return null;
82
+ }
83
+ if (url.protocol !== "https:" || url.hostname !== "github.com") return null;
84
+ let parts;
85
+ try {
86
+ parts = url.pathname.split("/").filter(Boolean).map((part) => decodeURIComponent(part));
87
+ } catch {
88
+ return null;
89
+ }
90
+ if (parts.length < 5 || parts[2] !== "blob") return null;
91
+ const repo = `${parts[0]}/${parts[1]}`;
92
+ const ref = parts[3];
93
+ const path = parts.slice(4).join("/");
94
+ if (!isSafeGitHubRepo(repo) || !isSafeGitHubRef(ref) || !isSafeGitHubPath(path)) return null;
95
+ const source = {
96
+ repo,
97
+ ref,
98
+ path,
99
+ lines: parseGitHubLineRange(url.hash)
100
+ };
101
+ return {
102
+ ...source,
103
+ permalink: createGitHubPermalink(source)
104
+ };
105
+ }
106
+ function inferLanguage(path) {
107
+ const fileName = path.split("/").at(-1)?.toLowerCase() ?? "";
108
+ if (fileName === "dockerfile") return "dockerfile";
109
+ if (fileName === "makefile") return "makefile";
110
+ const extension = fileName.includes(".") ? fileName.split(".").at(-1) : void 0;
111
+ return extension ? EXTENSION_LANGUAGE_MAP.get(extension) ?? extension : null;
112
+ }
113
+ //#endregion
114
+ //#region src/plugins/github/types.ts
115
+ const defaultOptions = {
116
+ token: "",
117
+ cache: true,
118
+ cacheTTL: 36e5,
119
+ maxSourceBytes: 2e5,
120
+ maxSourceLines: 120
121
+ };
122
+ //#endregion
123
+ //#region src/plugins/github/api.ts
124
+ const repoCache = /* @__PURE__ */ new Map();
125
+ const sourceCache = /* @__PURE__ */ new Map();
126
+ function githubHeaders(options) {
127
+ const headers = {
128
+ Accept: "application/vnd.github.v3+json",
129
+ "User-Agent": "ox-content-github-plugin"
130
+ };
131
+ if (options.token) headers.Authorization = `Bearer ${options.token}`;
132
+ return headers;
133
+ }
134
+ /**
135
+ * Fetch repository data from GitHub API.
136
+ */
137
+ async function fetchRepoData(repo, options) {
138
+ if (!isSafeGitHubRepo(repo)) return null;
139
+ if (options.cache) {
140
+ const cached = repoCache.get(repo);
141
+ if (cached && Date.now() - cached.timestamp < options.cacheTTL) return cached.data;
142
+ }
143
+ try {
144
+ const response = await fetch(`https://api.github.com/repos/${repo}`, { headers: githubHeaders(options) });
145
+ if (!response.ok) {
146
+ console.warn(`Failed to fetch GitHub repo ${repo}: ${response.status}`);
147
+ return null;
148
+ }
149
+ const data = await response.json();
150
+ if (options.cache) repoCache.set(repo, {
151
+ data,
152
+ timestamp: Date.now()
153
+ });
154
+ return data;
155
+ } catch (error) {
156
+ console.warn(`Error fetching GitHub repo ${repo}:`, error);
157
+ return null;
158
+ }
159
+ }
160
+ /**
161
+ * Fetch source file data from GitHub API.
162
+ */
163
+ async function fetchGitHubSource(source, options) {
164
+ if (!isSafeGitHubRepo(source.repo) || !isSafeGitHubRef(source.ref) || !isSafeGitHubPath(source.path)) return null;
165
+ const key = sourceKey(source);
166
+ if (options.cache) {
167
+ const cached = sourceCache.get(key);
168
+ if (cached && Date.now() - cached.timestamp < options.cacheTTL) return cached.data;
169
+ }
170
+ try {
171
+ const apiUrl = `https://api.github.com/repos/${source.repo}/contents/${encodePath(source.path)}?ref=${encodeURIComponent(source.ref)}`;
172
+ const response = await fetch(apiUrl, { headers: githubHeaders(options) });
173
+ if (!response.ok) {
174
+ console.warn(`Failed to fetch GitHub source ${source.permalink}: ${response.status}`);
175
+ return null;
176
+ }
177
+ const data = await response.json();
178
+ if (data.type !== "file" || data.encoding !== "base64" || !data.content || (data.size ?? 0) > options.maxSourceBytes) return null;
179
+ const content = Buffer.from(data.content.replace(/\s/g, ""), "base64").toString("utf8");
180
+ if (Buffer.byteLength(content) > options.maxSourceBytes) return null;
181
+ const sourceData = {
182
+ repo: source.repo,
183
+ ref: source.ref,
184
+ path: source.path,
185
+ permalink: source.permalink,
186
+ content,
187
+ size: data.size ?? Buffer.byteLength(content),
188
+ html_url: data.html_url ?? source.permalink,
189
+ language: inferLanguage(source.path)
190
+ };
191
+ if (options.cache) sourceCache.set(key, {
192
+ data: sourceData,
193
+ timestamp: Date.now()
194
+ });
195
+ return sourceData;
196
+ } catch (error) {
197
+ console.warn(`Error fetching GitHub source ${source.permalink}:`, error);
198
+ return null;
199
+ }
200
+ }
201
+ /**
202
+ * Pre-fetch all GitHub repos data.
203
+ */
204
+ async function prefetchGitHubRepos(repos, options) {
205
+ const mergedOptions = {
206
+ ...defaultOptions,
207
+ ...options
208
+ };
209
+ const results = /* @__PURE__ */ new Map();
210
+ await Promise.all(Array.from(new Set(repos)).map(async (repo) => {
211
+ const data = await fetchRepoData(repo, mergedOptions);
212
+ results.set(repo, data);
213
+ }));
214
+ return results;
215
+ }
216
+ /**
217
+ * Pre-fetch all GitHub source files.
218
+ */
219
+ async function prefetchGitHubSources(sources, options) {
220
+ const mergedOptions = {
221
+ ...defaultOptions,
222
+ ...options
223
+ };
224
+ const results = /* @__PURE__ */ new Map();
225
+ const uniqueSources = Array.from(new Map(sources.map((source) => [sourceKey(source), source])).values());
226
+ await Promise.all(uniqueSources.map(async (source) => {
227
+ const data = await fetchGitHubSource(source, mergedOptions);
228
+ results.set(sourceKey(source), data);
229
+ }));
230
+ return results;
231
+ }
232
+ //#endregion
233
+ //#region src/plugins/github/attributes.ts
234
+ const GITHUB_COMPONENT_RE = /<github\b([^>]*)>/gi;
235
+ const ATTRIBUTE_RE = /([:\w-]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'>/]+)))?/g;
236
+ /**
237
+ * Collect all GitHub repos from HTML for pre-fetching.
238
+ */
239
+ async function collectGitHubRepos(html) {
240
+ const repos = [];
241
+ GITHUB_COMPONENT_RE.lastIndex = 0;
242
+ let match;
243
+ while ((match = GITHUB_COMPONENT_RE.exec(html)) !== null) {
244
+ const attrs = parseAttributes(match[1]);
245
+ if (attrs.path || attrs.file || attrs.permalink || attrs.url || attrs.href) continue;
246
+ const repo = attrs.repo;
247
+ if (repo && isSafeGitHubRepo(repo)) repos.push(repo);
248
+ }
249
+ return repos;
250
+ }
251
+ /**
252
+ * Collect all GitHub source references from HTML for pre-fetching.
253
+ */
254
+ async function collectGitHubSources(html) {
255
+ const sources = [];
256
+ GITHUB_COMPONENT_RE.lastIndex = 0;
257
+ let match;
258
+ while ((match = GITHUB_COMPONENT_RE.exec(html)) !== null) {
259
+ const source = sourceRefFromAttributes(parseAttributes(match[1]));
260
+ if (source) sources.push(source);
261
+ }
262
+ return sources;
263
+ }
264
+ function parseAttributes(raw) {
265
+ const attrs = {};
266
+ ATTRIBUTE_RE.lastIndex = 0;
267
+ let match;
268
+ while ((match = ATTRIBUTE_RE.exec(raw)) !== null) attrs[match[1].toLowerCase()] = match[2] ?? match[3] ?? match[4] ?? "";
269
+ return attrs;
270
+ }
271
+ function attributesFromElement(el) {
272
+ const attrs = {};
273
+ for (const name of [
274
+ "permalink",
275
+ "url",
276
+ "href",
277
+ "repo",
278
+ "path",
279
+ "file",
280
+ "ref",
281
+ "sha",
282
+ "branch",
283
+ "loc",
284
+ "lines",
285
+ "line"
286
+ ]) {
287
+ const value = getAttribute(el, name);
288
+ if (value !== void 0) attrs[name] = value;
289
+ }
290
+ return attrs;
291
+ }
292
+ function getAttribute(el, name) {
293
+ const value = el.properties?.[name];
294
+ if (typeof value === "string") return value;
295
+ if (Array.isArray(value)) return value.join(" ");
296
+ }
297
+ function sourceRefFromAttributes(attrs) {
298
+ const permalink = attrs.permalink ?? attrs.url ?? attrs.href;
299
+ if (permalink) return parseGitHubPermalink(permalink);
300
+ const repo = attrs.repo;
301
+ const path = attrs.path ?? attrs.file;
302
+ if (!repo || !path || !isSafeGitHubRepo(repo) || !isSafeGitHubPath(path)) return null;
303
+ const ref = attrs.ref ?? attrs.sha ?? attrs.branch ?? "main";
304
+ if (!isSafeGitHubRef(ref)) return null;
305
+ const source = {
306
+ repo,
307
+ ref,
308
+ path,
309
+ lines: parseGitHubLineRange(attrs.loc ?? attrs.lines ?? attrs.line)
310
+ };
311
+ return {
312
+ ...source,
313
+ permalink: createGitHubPermalink(source)
314
+ };
315
+ }
316
+ //#endregion
317
+ //#region src/plugins/github/fallback-card.ts
318
+ /**
319
+ * Create fallback element when repo data is unavailable.
320
+ */
321
+ function createFallbackCard(repo) {
322
+ return {
323
+ type: "element",
324
+ tagName: "a",
325
+ properties: {
326
+ className: ["ox-github-card", "error"],
327
+ href: isSafeGitHubRepo(repo) ? `https://github.com/${repo}` : "#",
328
+ target: "_blank",
329
+ rel: "noopener noreferrer"
330
+ },
331
+ children: [{
332
+ type: "element",
333
+ tagName: "div",
334
+ properties: { className: ["ox-github-header"] },
335
+ children: [{
336
+ type: "element",
337
+ tagName: "svg",
338
+ properties: {
339
+ className: ["ox-github-icon"],
340
+ viewBox: "0 0 16 16",
341
+ fill: "currentColor"
342
+ },
343
+ children: [{
344
+ type: "element",
345
+ tagName: "path",
346
+ 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" },
347
+ children: []
348
+ }]
349
+ }, {
350
+ type: "element",
351
+ tagName: "span",
352
+ properties: { className: ["ox-github-repo"] },
353
+ children: [{
354
+ type: "text",
355
+ value: repo
356
+ }]
357
+ }]
358
+ }]
359
+ };
360
+ }
361
+ //#endregion
362
+ //#region src/plugins/github/repo-card.ts
363
+ function formatNumber(num) {
364
+ if (num >= 1e6) return `${(num / 1e6).toFixed(1)}M`;
365
+ if (num >= 1e3) return `${(num / 1e3).toFixed(1)}k`;
366
+ return String(num);
367
+ }
368
+ function iconPath(d) {
369
+ return {
370
+ type: "element",
371
+ tagName: "svg",
372
+ properties: {
373
+ viewBox: "0 0 16 16",
374
+ fill: "currentColor"
375
+ },
376
+ children: [{
377
+ type: "element",
378
+ tagName: "path",
379
+ properties: { d },
380
+ children: []
381
+ }]
382
+ };
383
+ }
384
+ function createStatsChildren(repoData) {
385
+ const statsChildren = [];
386
+ if (repoData.language) statsChildren.push({
387
+ type: "element",
388
+ tagName: "span",
389
+ properties: { className: ["ox-github-language"] },
390
+ children: [{
391
+ type: "element",
392
+ tagName: "span",
393
+ properties: {
394
+ className: ["ox-github-language-color"],
395
+ "data-lang": repoData.language.toLowerCase()
396
+ },
397
+ children: []
398
+ }, {
399
+ type: "text",
400
+ value: repoData.language
401
+ }]
402
+ });
403
+ statsChildren.push({
404
+ type: "element",
405
+ tagName: "span",
406
+ properties: { className: ["ox-github-stat"] },
407
+ 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"), {
408
+ type: "text",
409
+ value: formatNumber(repoData.stargazers_count)
410
+ }]
411
+ });
412
+ statsChildren.push({
413
+ type: "element",
414
+ tagName: "span",
415
+ properties: { className: ["ox-github-stat"] },
416
+ 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"), {
417
+ type: "text",
418
+ value: formatNumber(repoData.forks_count)
419
+ }]
420
+ });
421
+ return statsChildren;
422
+ }
423
+ /**
424
+ * Create GitHub card element from repo data.
425
+ */
426
+ function createGitHubCard(repoData) {
427
+ return {
428
+ type: "element",
429
+ tagName: "a",
430
+ properties: {
431
+ className: ["ox-github-card"],
432
+ href: repoData.html_url,
433
+ target: "_blank",
434
+ rel: "noopener noreferrer"
435
+ },
436
+ children: [
437
+ {
438
+ type: "element",
439
+ tagName: "div",
440
+ properties: { className: ["ox-github-header"] },
441
+ children: [{
442
+ ...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"),
443
+ properties: {
444
+ className: ["ox-github-icon"],
445
+ viewBox: "0 0 16 16",
446
+ fill: "currentColor"
447
+ }
448
+ }, {
449
+ type: "element",
450
+ tagName: "span",
451
+ properties: { className: ["ox-github-repo"] },
452
+ children: [{
453
+ type: "text",
454
+ value: repoData.full_name
455
+ }]
456
+ }]
457
+ },
458
+ ...repoData.description ? [{
459
+ type: "element",
460
+ tagName: "p",
461
+ properties: { className: ["ox-github-description"] },
462
+ children: [{
463
+ type: "text",
464
+ value: repoData.description
465
+ }]
466
+ }] : [],
467
+ {
468
+ type: "element",
469
+ tagName: "div",
470
+ properties: { className: ["ox-github-stats"] },
471
+ children: createStatsChildren(repoData)
472
+ }
473
+ ]
474
+ };
475
+ }
476
+ //#endregion
477
+ //#region src/plugins/github/source-card.ts
478
+ function normalizeSourceLines(content) {
479
+ const lines = content.replace(/\r\n?/g, "\n").split("\n");
480
+ if (lines.length > 1 && lines.at(-1) === "") lines.pop();
481
+ return lines.length > 0 ? lines : [""];
482
+ }
483
+ function createGitHubSourceCard(source, lines, options) {
484
+ const allLines = normalizeSourceLines(source.content);
485
+ const start = Math.min(lines?.start ?? 1, allLines.length);
486
+ const end = lines ? Math.min(lines.end, allLines.length) : Math.min(allLines.length, options.maxSourceLines);
487
+ const selectedLines = allLines.slice(start - 1, end);
488
+ const lineRange = {
489
+ start,
490
+ end
491
+ };
492
+ const loc = selectedLines.length;
493
+ const rangeLabel = formatLineRange(lineRange);
494
+ const locLabel = !lines && end < allLines.length ? `${rangeLabel} of ${allLines.length} LOC` : `${rangeLabel} - ${loc} LOC`;
495
+ const languageClass = source.language ? [`language-${source.language}`] : [];
496
+ return {
497
+ type: "element",
498
+ tagName: "figure",
499
+ properties: {
500
+ className: ["ox-github-code"],
501
+ "data-loc": String(loc),
502
+ "data-source": source.permalink
503
+ },
504
+ children: [{
505
+ type: "element",
506
+ tagName: "figcaption",
507
+ properties: { className: ["ox-github-code-header"] },
508
+ children: [{
509
+ type: "element",
510
+ tagName: "a",
511
+ properties: {
512
+ className: ["ox-github-code-title"],
513
+ href: source.permalink,
514
+ target: "_blank",
515
+ rel: "noopener noreferrer"
516
+ },
517
+ children: [{
518
+ type: "text",
519
+ value: `${source.repo}/${source.path}`
520
+ }]
521
+ }, {
522
+ type: "element",
523
+ tagName: "span",
524
+ properties: { className: ["ox-github-code-loc"] },
525
+ children: [{
526
+ type: "text",
527
+ value: locLabel
528
+ }]
529
+ }]
530
+ }, {
531
+ type: "element",
532
+ tagName: "pre",
533
+ properties: {
534
+ className: ["ox-github-code-block", ...languageClass],
535
+ ...source.language ? { "data-language": source.language } : {}
536
+ },
537
+ children: [{
538
+ type: "element",
539
+ tagName: "code",
540
+ properties: { className: languageClass },
541
+ children: selectedLines.map((line, index) => {
542
+ const lineNumber = start + index;
543
+ return {
544
+ type: "element",
545
+ tagName: "span",
546
+ properties: {
547
+ className: ["line", "ox-github-code-line"],
548
+ "data-line": String(lineNumber)
549
+ },
550
+ children: [{
551
+ type: "element",
552
+ tagName: "span",
553
+ properties: { className: ["ox-github-code-line-number"] },
554
+ children: [{
555
+ type: "text",
556
+ value: String(lineNumber)
557
+ }]
558
+ }, {
559
+ type: "element",
560
+ tagName: "span",
561
+ properties: { className: ["ox-github-code-line-content"] },
562
+ children: [{
563
+ type: "text",
564
+ value: line || " "
565
+ }]
566
+ }]
567
+ };
568
+ })
569
+ }]
570
+ }]
571
+ };
572
+ }
573
+ //#endregion
574
+ //#region src/plugins/github/transform.ts
575
+ /**
576
+ * Rehype plugin to transform GitHub components.
577
+ */
578
+ function rehypeGitHub(repoDataMap, sourceDataMap, options) {
579
+ return (tree) => {
580
+ const visit = (node) => {
581
+ if ("children" in node) for (let i = 0; i < node.children.length; i++) {
582
+ const child = node.children[i];
583
+ if (child.type !== "element") continue;
584
+ if (child.tagName.toLowerCase() !== "github") {
585
+ visit(child);
586
+ continue;
587
+ }
588
+ const attrs = attributesFromElement(child);
589
+ const source = sourceRefFromAttributes(attrs);
590
+ if (source) {
591
+ const sourceData = sourceDataMap.get(sourceKey(source));
592
+ node.children[i] = sourceData ? createGitHubSourceCard(sourceData, source.lines, options) : createFallbackCard(source.permalink);
593
+ continue;
594
+ }
595
+ const repo = attrs.repo;
596
+ if (repo) {
597
+ const repoData = repoDataMap.get(repo);
598
+ node.children[i] = repoData ? createGitHubCard(repoData) : createFallbackCard(repo);
599
+ }
600
+ }
601
+ };
602
+ visit(tree);
603
+ };
604
+ }
605
+ /**
606
+ * Transform GitHub components in HTML.
607
+ */
608
+ async function transformGitHub(html, repoDataMap, options) {
609
+ const mergedOptions = {
610
+ ...defaultOptions,
611
+ ...options
612
+ };
613
+ let dataMap = repoDataMap;
614
+ if (!dataMap) dataMap = await prefetchGitHubRepos(await collectGitHubRepos(html), mergedOptions);
615
+ const sourceDataMap = await prefetchGitHubSources(await collectGitHubSources(html), mergedOptions);
616
+ const result = await unified().use(rehypeParse, { fragment: true }).use(rehypeGitHub, dataMap, sourceDataMap, mergedOptions).use(rehypeStringify).process(html);
617
+ return String(result);
618
+ }
619
+ //#endregion
620
+ export { fetchRepoData as a, createGitHubPermalink as c, isSafeGitHubRepo as d, fetchGitHubSource as i, parseGitHubLineRange as l, collectGitHubRepos as n, prefetchGitHubRepos as o, collectGitHubSources as r, prefetchGitHubSources as s, transformGitHub as t, parseGitHubPermalink as u };
621
+
622
+ //# sourceMappingURL=github.mjs.map