@plateerlab/xgen-gallery 0.1.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/index.mjs ADDED
@@ -0,0 +1,534 @@
1
+ // src/XgenGallery.tsx
2
+ import { useEffect, useState, useCallback } from "react";
3
+
4
+ // src/api.ts
5
+ var API = "https://api.github.com";
6
+ function headers(token) {
7
+ const h = { Accept: "application/vnd.github.v3+json" };
8
+ if (token) h.Authorization = `Bearer ${token}`;
9
+ return h;
10
+ }
11
+ async function fetchRepos(org, token) {
12
+ try {
13
+ const res = await fetch(`${API}/orgs/${org}/repos?per_page=100&sort=updated`, {
14
+ headers: headers(token)
15
+ });
16
+ if (!res.ok) return [];
17
+ return res.json();
18
+ } catch {
19
+ return [];
20
+ }
21
+ }
22
+ async function fetchReadme(org, repo, token) {
23
+ try {
24
+ const res = await fetch(`${API}/repos/${org}/${repo}/readme`, {
25
+ headers: { ...headers(token), Accept: "application/vnd.github.v3.raw" }
26
+ });
27
+ if (!res.ok) return null;
28
+ return res.text();
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+ async function fetchDemoSnippets(org, repo, readme, token) {
34
+ for (const path of [".xgen-gallery/demo.json", "demo.json"]) {
35
+ try {
36
+ const res = await fetch(`${API}/repos/${org}/${repo}/contents/${path}`, {
37
+ headers: { ...headers(token), Accept: "application/vnd.github.v3.raw" }
38
+ });
39
+ if (!res.ok) continue;
40
+ const data = await res.json();
41
+ if (data.snippets?.length) return data.snippets;
42
+ } catch {
43
+ continue;
44
+ }
45
+ }
46
+ try {
47
+ const res = await fetch(`${API}/repos/${org}/${repo}/contents/examples`, {
48
+ headers: headers(token)
49
+ });
50
+ if (res.ok) {
51
+ const files = await res.json();
52
+ const pyFiles = files.filter((f) => f.name.endsWith(".py")).slice(0, 5);
53
+ const snippets = [];
54
+ for (const f of pyFiles) {
55
+ try {
56
+ const r = await fetch(f.download_url);
57
+ if (r.ok) {
58
+ const code = await r.text();
59
+ snippets.push({ label: f.name.replace(/\.py$/, "").replace(/[_-]/g, " "), code: code.trim() });
60
+ }
61
+ } catch {
62
+ continue;
63
+ }
64
+ }
65
+ if (snippets.length) return snippets;
66
+ }
67
+ } catch {
68
+ }
69
+ let md = readme;
70
+ if (!md) md = await fetchReadme(org, repo, token);
71
+ if (md) {
72
+ const blocks = extractPythonBlocks(md);
73
+ if (blocks.length) return blocks;
74
+ }
75
+ return [];
76
+ }
77
+ function extractPythonBlocks(readme) {
78
+ const snippets = [];
79
+ const lines = readme.split("\n");
80
+ let i = 0;
81
+ while (i < lines.length) {
82
+ if (/^```(?:python|py)\s*$/i.test(lines[i].trim())) {
83
+ let label = "";
84
+ for (let j = i - 1; j >= Math.max(0, i - 5); j--) {
85
+ const prev = lines[j].trim();
86
+ if (/^#{1,4}\s+/.test(prev)) {
87
+ label = prev.replace(/^#+\s+/, "");
88
+ break;
89
+ }
90
+ if (prev && !label) label = prev;
91
+ }
92
+ const codeLines = [];
93
+ i++;
94
+ while (i < lines.length && !lines[i].trim().startsWith("```")) {
95
+ codeLines.push(lines[i]);
96
+ i++;
97
+ }
98
+ const code = codeLines.join("\n").trim();
99
+ if (code && code.split("\n").length >= 2 && !code.startsWith("pip ") && !code.startsWith("$ pip")) {
100
+ snippets.push({ label: label || `Example ${snippets.length + 1}`, code });
101
+ }
102
+ }
103
+ i++;
104
+ }
105
+ return snippets;
106
+ }
107
+
108
+ // src/styles.ts
109
+ var themes = {
110
+ dark: {
111
+ bg: "#0a0a0f",
112
+ bgCard: "#12121a",
113
+ bgCardHover: "#1a1a25",
114
+ border: "#1e1e2e",
115
+ text: "#e8e8f0",
116
+ textSecondary: "#a0a0b8",
117
+ textMuted: "#6b6b80",
118
+ accent: "#6c63ff",
119
+ accentLight: "#8b83ff",
120
+ accentGlow: "rgba(108,99,255,0.15)"
121
+ },
122
+ light: {
123
+ bg: "#f8f9fa",
124
+ bgCard: "#ffffff",
125
+ bgCardHover: "#f0f0f5",
126
+ border: "#e0e0e8",
127
+ text: "#1a1a2e",
128
+ textSecondary: "#4a4a5a",
129
+ textMuted: "#8a8a9a",
130
+ accent: "#5b52e0",
131
+ accentLight: "#5b52e0",
132
+ accentGlow: "rgba(91,82,224,0.1)"
133
+ }
134
+ };
135
+ var LANG_COLORS = {
136
+ Python: "#3572A5",
137
+ TypeScript: "#3178c6",
138
+ JavaScript: "#f1e05a",
139
+ Rust: "#dea584",
140
+ HTML: "#e34c26",
141
+ CSS: "#563d7c",
142
+ Go: "#00ADD8",
143
+ Shell: "#89e051",
144
+ Java: "#b07219",
145
+ "C++": "#f34b7d",
146
+ C: "#555555",
147
+ Ruby: "#701516"
148
+ };
149
+
150
+ // src/ReadmeView.tsx
151
+ import ReactMarkdown from "react-markdown";
152
+ import remarkGfm from "remark-gfm";
153
+ import rehypeRaw from "rehype-raw";
154
+ import { jsx, jsxs } from "react/jsx-runtime";
155
+ function ReadmeView({
156
+ org,
157
+ repoName,
158
+ content,
159
+ t
160
+ }) {
161
+ if (!content) {
162
+ return /* @__PURE__ */ jsx("div", { style: { textAlign: "center", padding: 40, color: t.textMuted }, children: "README not found" });
163
+ }
164
+ return /* @__PURE__ */ jsxs("div", { className: "xgen-markdown", style: { color: t.text, lineHeight: 1.7, fontSize: 14 }, children: [
165
+ /* @__PURE__ */ jsx("style", { children: markdownStyles(t) }),
166
+ /* @__PURE__ */ jsx(
167
+ ReactMarkdown,
168
+ {
169
+ remarkPlugins: [remarkGfm],
170
+ rehypePlugins: [rehypeRaw],
171
+ components: {
172
+ img: ({ src, alt, ...props }) => {
173
+ let resolved = src;
174
+ if (typeof src === "string" && !src.startsWith("http")) {
175
+ resolved = `https://raw.githubusercontent.com/${org}/${repoName}/main/${src}`;
176
+ }
177
+ return /* @__PURE__ */ jsx("img", { src: resolved, alt: alt || "", style: { maxWidth: "100%" }, ...props });
178
+ },
179
+ a: ({ href, children, ...props }) => /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noopener noreferrer", style: { color: t.accentLight }, ...props, children }),
180
+ code: ({ children, className, ...props }) => {
181
+ const isBlock = className?.includes("language-");
182
+ if (isBlock) {
183
+ return /* @__PURE__ */ jsx(
184
+ "code",
185
+ {
186
+ style: {
187
+ display: "block",
188
+ background: t.bg,
189
+ padding: 16,
190
+ borderRadius: 8,
191
+ overflow: "auto",
192
+ fontSize: 13,
193
+ lineHeight: 1.6
194
+ },
195
+ ...props,
196
+ children
197
+ }
198
+ );
199
+ }
200
+ return /* @__PURE__ */ jsx("code", { style: { background: t.accentGlow, padding: "2px 6px", borderRadius: 4, fontSize: 13 }, ...props, children });
201
+ }
202
+ },
203
+ children: content
204
+ }
205
+ )
206
+ ] });
207
+ }
208
+ function markdownStyles(t) {
209
+ return `
210
+ .xgen-markdown h1, .xgen-markdown h2, .xgen-markdown h3 { color: ${t.text}; margin: 1.2em 0 0.5em; }
211
+ .xgen-markdown h1 { font-size: 1.8em; border-bottom: 1px solid ${t.border}; padding-bottom: 8px; }
212
+ .xgen-markdown h2 { font-size: 1.4em; border-bottom: 1px solid ${t.border}; padding-bottom: 6px; }
213
+ .xgen-markdown h3 { font-size: 1.15em; }
214
+ .xgen-markdown p { margin: 0.8em 0; }
215
+ .xgen-markdown ul, .xgen-markdown ol { padding-left: 24px; }
216
+ .xgen-markdown li { margin: 4px 0; }
217
+ .xgen-markdown pre { background: ${t.bg}; border: 1px solid ${t.border}; border-radius: 8px; padding: 16px; overflow: auto; margin: 12px 0; }
218
+ .xgen-markdown blockquote { border-left: 3px solid ${t.accent}; padding-left: 12px; color: ${t.textSecondary}; margin: 12px 0; }
219
+ .xgen-markdown table { border-collapse: collapse; width: 100%; margin: 12px 0; }
220
+ .xgen-markdown th, .xgen-markdown td { border: 1px solid ${t.border}; padding: 8px 12px; text-align: left; }
221
+ .xgen-markdown th { background: ${t.bgCard}; font-weight: 600; }
222
+ .xgen-markdown hr { border: none; border-top: 1px solid ${t.border}; margin: 16px 0; }
223
+ `;
224
+ }
225
+
226
+ // src/XgenGallery.tsx
227
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
228
+ function XgenGallery({ org, token, theme: themeName = "dark", limit, onRepoClick }) {
229
+ const t = themes[themeName];
230
+ const [repos, setRepos] = useState([]);
231
+ const [loading, setLoading] = useState(true);
232
+ const [search, setSearch] = useState("");
233
+ const [lang, setLang] = useState(null);
234
+ const [view, setView] = useState({ type: "list" });
235
+ useEffect(() => {
236
+ fetchRepos(org, token).then((data) => {
237
+ setRepos(limit ? data.slice(0, limit) : data);
238
+ setLoading(false);
239
+ });
240
+ }, [org, token, limit]);
241
+ const languages = [...new Set(repos.map((r) => r.language).filter(Boolean))];
242
+ const filtered = repos.filter((r) => {
243
+ if (lang && r.language !== lang) return false;
244
+ if (search) {
245
+ const q = search.toLowerCase();
246
+ return r.name.toLowerCase().includes(q) || (r.description || "").toLowerCase().includes(q);
247
+ }
248
+ return true;
249
+ });
250
+ const handleCardClick = useCallback((repo) => {
251
+ if (onRepoClick) {
252
+ onRepoClick(repo);
253
+ } else {
254
+ setView({ type: "detail", repo });
255
+ }
256
+ }, [onRepoClick]);
257
+ if (view.type === "detail") {
258
+ return /* @__PURE__ */ jsx2(RepoDetail, { org, repo: view.repo, token, t, onBack: () => setView({ type: "list" }) });
259
+ }
260
+ return /* @__PURE__ */ jsxs2("div", { style: { background: t.bg, color: t.text, fontFamily: "system-ui, -apple-system, sans-serif", padding: 24 }, children: [
261
+ /* @__PURE__ */ jsxs2("div", { style: { marginBottom: 24 }, children: [
262
+ /* @__PURE__ */ jsx2("h2", { style: { fontSize: 24, fontWeight: 700, margin: 0 }, children: org }),
263
+ /* @__PURE__ */ jsxs2("p", { style: { color: t.textMuted, fontSize: 14, margin: "4px 0 0" }, children: [
264
+ repos.length,
265
+ " repositories"
266
+ ] })
267
+ ] }),
268
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 16 }, children: [
269
+ /* @__PURE__ */ jsx2(
270
+ "input",
271
+ {
272
+ type: "text",
273
+ placeholder: "Search...",
274
+ value: search,
275
+ onChange: (e) => setSearch(e.target.value),
276
+ style: {
277
+ background: t.bgCard,
278
+ border: `1px solid ${t.border}`,
279
+ borderRadius: 8,
280
+ padding: "8px 12px",
281
+ color: t.text,
282
+ fontSize: 14,
283
+ outline: "none",
284
+ flex: "1 1 200px"
285
+ }
286
+ }
287
+ ),
288
+ /* @__PURE__ */ jsx2(
289
+ "button",
290
+ {
291
+ onClick: () => setLang(null),
292
+ style: {
293
+ padding: "6px 12px",
294
+ borderRadius: 8,
295
+ fontSize: 12,
296
+ fontWeight: 500,
297
+ cursor: "pointer",
298
+ background: !lang ? t.accent : "transparent",
299
+ color: !lang ? "#fff" : t.textMuted,
300
+ border: `1px solid ${!lang ? t.accent : t.border}`
301
+ },
302
+ children: "All"
303
+ }
304
+ ),
305
+ languages.map((l) => /* @__PURE__ */ jsx2(
306
+ "button",
307
+ {
308
+ onClick: () => setLang(lang === l ? null : l),
309
+ style: {
310
+ padding: "6px 12px",
311
+ borderRadius: 8,
312
+ fontSize: 12,
313
+ fontWeight: 500,
314
+ cursor: "pointer",
315
+ background: lang === l ? t.accent : "transparent",
316
+ color: lang === l ? "#fff" : t.textMuted,
317
+ border: `1px solid ${lang === l ? t.accent : t.border}`
318
+ },
319
+ children: l
320
+ },
321
+ l
322
+ ))
323
+ ] }),
324
+ loading ? /* @__PURE__ */ jsx2("div", { style: { textAlign: "center", padding: 60, color: t.textMuted }, children: "Loading..." }) : /* @__PURE__ */ jsx2("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(300px, 1fr))", gap: 16 }, children: filtered.map((repo) => /* @__PURE__ */ jsx2(RepoCard, { repo, t, onClick: () => handleCardClick(repo) }, repo.name)) }),
325
+ !loading && filtered.length === 0 && /* @__PURE__ */ jsx2("div", { style: { textAlign: "center", padding: 60, color: t.textMuted }, children: "No results" })
326
+ ] });
327
+ }
328
+ function RepoCard({ repo, t, onClick }) {
329
+ const [hover, setHover] = useState(false);
330
+ const langColor = repo.language ? LANG_COLORS[repo.language] || "#888" : null;
331
+ const date = new Date(repo.updated_at).toLocaleDateString("ko-KR", { year: "numeric", month: "short", day: "numeric" });
332
+ return /* @__PURE__ */ jsxs2(
333
+ "div",
334
+ {
335
+ onClick,
336
+ onMouseEnter: () => setHover(true),
337
+ onMouseLeave: () => setHover(false),
338
+ style: {
339
+ background: hover ? t.bgCardHover : t.bgCard,
340
+ border: `1px solid ${hover ? t.accent : t.border}`,
341
+ borderRadius: 12,
342
+ padding: 20,
343
+ cursor: "pointer",
344
+ transform: hover ? "translateY(-2px)" : "none",
345
+ boxShadow: hover ? `0 0 20px ${t.accentGlow}` : "none",
346
+ transition: "all 0.2s"
347
+ },
348
+ children: [
349
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 8 }, children: [
350
+ /* @__PURE__ */ jsx2("span", { style: { fontSize: 16, fontWeight: 600, color: t.accentLight }, children: repo.name }),
351
+ /* @__PURE__ */ jsx2(
352
+ "button",
353
+ {
354
+ onClick: (e) => {
355
+ e.stopPropagation();
356
+ window.open(repo.html_url, "_blank");
357
+ },
358
+ style: {
359
+ fontSize: 11,
360
+ padding: "2px 8px",
361
+ borderRadius: 6,
362
+ cursor: "pointer",
363
+ border: `1px solid ${t.border}`,
364
+ background: "transparent",
365
+ color: t.textMuted
366
+ },
367
+ children: "GitHub \u2192"
368
+ }
369
+ )
370
+ ] }),
371
+ /* @__PURE__ */ jsx2("p", { style: { fontSize: 13, color: t.textSecondary, margin: "0 0 12px", lineHeight: 1.5, minHeight: 40 }, children: repo.description || "No description" }),
372
+ /* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: 12, fontSize: 12, color: t.textMuted }, children: [
373
+ langColor && /* @__PURE__ */ jsxs2("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
374
+ /* @__PURE__ */ jsx2("span", { style: { width: 10, height: 10, borderRadius: "50%", background: langColor, display: "inline-block" } }),
375
+ repo.language
376
+ ] }),
377
+ repo.stargazers_count > 0 && /* @__PURE__ */ jsxs2("span", { children: [
378
+ "\u2605 ",
379
+ repo.stargazers_count
380
+ ] }),
381
+ repo.forks_count > 0 && /* @__PURE__ */ jsxs2("span", { children: [
382
+ "Fork ",
383
+ repo.forks_count
384
+ ] }),
385
+ /* @__PURE__ */ jsx2("span", { children: date })
386
+ ] })
387
+ ]
388
+ }
389
+ );
390
+ }
391
+ function RepoDetail({ org, repo, token, t, onBack }) {
392
+ const [tab, setTab] = useState("readme");
393
+ const [readme, setReadme] = useState(null);
394
+ const [snippets, setSnippets] = useState([]);
395
+ const [loading, setLoading] = useState(true);
396
+ useEffect(() => {
397
+ Promise.all([
398
+ fetchReadme(org, repo.name, token),
399
+ fetchDemoSnippets(org, repo.name, void 0, token)
400
+ ]).then(([md, s]) => {
401
+ setReadme(md);
402
+ setSnippets(s);
403
+ setLoading(false);
404
+ });
405
+ }, [org, repo.name, token]);
406
+ return /* @__PURE__ */ jsxs2("div", { style: { background: t.bg, color: t.text, fontFamily: "system-ui, -apple-system, sans-serif", padding: 24 }, children: [
407
+ /* @__PURE__ */ jsx2(
408
+ "button",
409
+ {
410
+ onClick: onBack,
411
+ style: {
412
+ background: "transparent",
413
+ border: "none",
414
+ color: t.accentLight,
415
+ cursor: "pointer",
416
+ fontSize: 14,
417
+ padding: 0,
418
+ marginBottom: 16
419
+ },
420
+ children: "\u2190 Back"
421
+ }
422
+ ),
423
+ /* @__PURE__ */ jsx2("div", { style: { background: t.bgCard, border: `1px solid ${t.border}`, borderRadius: 12, padding: 24, marginBottom: 16 }, children: /* @__PURE__ */ jsxs2("div", { style: { display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: 16 }, children: [
424
+ /* @__PURE__ */ jsxs2("div", { children: [
425
+ /* @__PURE__ */ jsx2("h1", { style: { fontSize: 22, fontWeight: 700, margin: 0 }, children: repo.name }),
426
+ /* @__PURE__ */ jsx2("p", { style: { color: t.textSecondary, fontSize: 14, margin: "8px 0" }, children: repo.description || "No description" })
427
+ ] }),
428
+ /* @__PURE__ */ jsx2(
429
+ "a",
430
+ {
431
+ href: repo.html_url,
432
+ target: "_blank",
433
+ rel: "noopener noreferrer",
434
+ style: {
435
+ display: "inline-flex",
436
+ alignItems: "center",
437
+ gap: 8,
438
+ padding: "8px 16px",
439
+ borderRadius: 8,
440
+ fontSize: 14,
441
+ fontWeight: 500,
442
+ background: t.accent,
443
+ color: "#fff",
444
+ textDecoration: "none",
445
+ height: "fit-content"
446
+ },
447
+ children: "View on GitHub"
448
+ }
449
+ )
450
+ ] }) }),
451
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", gap: 4, borderBottom: `1px solid ${t.border}`, marginBottom: 16 }, children: ["readme", ...snippets.length > 0 ? ["demo"] : []].map((key) => /* @__PURE__ */ jsx2(
452
+ "button",
453
+ {
454
+ onClick: () => setTab(key),
455
+ style: {
456
+ padding: "10px 16px",
457
+ fontSize: 14,
458
+ fontWeight: 500,
459
+ cursor: "pointer",
460
+ background: "transparent",
461
+ border: "none",
462
+ color: tab === key ? t.accentLight : t.textMuted,
463
+ borderBottom: tab === key ? `2px solid ${t.accent}` : "2px solid transparent"
464
+ },
465
+ children: key === "readme" ? "README" : "Demo"
466
+ },
467
+ key
468
+ )) }),
469
+ /* @__PURE__ */ jsx2("div", { style: { background: t.bgCard, border: `1px solid ${t.border}`, borderRadius: 12, padding: 24 }, children: loading ? /* @__PURE__ */ jsx2("div", { style: { textAlign: "center", padding: 40, color: t.textMuted }, children: "Loading..." }) : tab === "readme" ? /* @__PURE__ */ jsx2(ReadmeView, { org, repoName: repo.name, content: readme, t }) : /* @__PURE__ */ jsx2(DemoView, { snippets, t }) })
470
+ ] });
471
+ }
472
+ function DemoView({ snippets, t }) {
473
+ const [idx, setIdx] = useState(0);
474
+ const snippet = snippets[idx];
475
+ if (!snippet) return null;
476
+ return /* @__PURE__ */ jsxs2("div", { children: [
477
+ snippets.length > 1 && /* @__PURE__ */ jsx2("div", { style: { display: "flex", gap: 6, marginBottom: 12, flexWrap: "wrap" }, children: snippets.map((s, i) => /* @__PURE__ */ jsx2(
478
+ "button",
479
+ {
480
+ onClick: () => setIdx(i),
481
+ style: {
482
+ padding: "4px 12px",
483
+ borderRadius: 99,
484
+ fontSize: 12,
485
+ cursor: "pointer",
486
+ background: i === idx ? t.accentGlow : "transparent",
487
+ color: i === idx ? t.accentLight : t.textMuted,
488
+ border: `1px solid ${i === idx ? t.accent : t.border}`
489
+ },
490
+ children: s.label
491
+ },
492
+ i
493
+ )) }),
494
+ /* @__PURE__ */ jsx2(
495
+ "pre",
496
+ {
497
+ style: {
498
+ background: t.bg,
499
+ border: `1px solid ${t.border}`,
500
+ borderRadius: 8,
501
+ padding: 16,
502
+ fontSize: 13,
503
+ lineHeight: 1.6,
504
+ overflow: "auto",
505
+ color: t.textSecondary,
506
+ margin: 0
507
+ },
508
+ children: /* @__PURE__ */ jsx2("code", { children: snippet.code })
509
+ }
510
+ ),
511
+ snippet.expectedOutput && /* @__PURE__ */ jsxs2("div", { style: { marginTop: 12 }, children: [
512
+ /* @__PURE__ */ jsx2("span", { style: { fontSize: 12, color: t.textMuted }, children: "Expected Output:" }),
513
+ /* @__PURE__ */ jsx2(
514
+ "pre",
515
+ {
516
+ style: {
517
+ background: t.bg,
518
+ border: `1px solid ${t.border}`,
519
+ borderRadius: 8,
520
+ padding: 12,
521
+ fontSize: 12,
522
+ color: t.textMuted,
523
+ margin: "4px 0 0"
524
+ },
525
+ children: snippet.expectedOutput
526
+ }
527
+ )
528
+ ] })
529
+ ] });
530
+ }
531
+ export {
532
+ XgenGallery
533
+ };
534
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/XgenGallery.tsx","../src/api.ts","../src/styles.ts","../src/ReadmeView.tsx"],"sourcesContent":["import { useEffect, useState, useCallback } from \"react\";\r\nimport type { Repo, GalleryProps, DemoSnippet } from \"./types\";\r\nimport { fetchRepos, fetchReadme, fetchDemoSnippets } from \"./api\";\r\nimport { themes, LANG_COLORS, Theme } from \"./styles\";\r\nimport { ReadmeView } from \"./ReadmeView\";\r\n\r\ntype View = { type: \"list\" } | { type: \"detail\"; repo: Repo };\r\n\r\nexport function XgenGallery({ org, token, theme: themeName = \"dark\", limit, onRepoClick }: GalleryProps) {\r\n const t = themes[themeName];\r\n const [repos, setRepos] = useState<Repo[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n const [search, setSearch] = useState(\"\");\r\n const [lang, setLang] = useState<string | null>(null);\r\n const [view, setView] = useState<View>({ type: \"list\" });\r\n\r\n useEffect(() => {\r\n fetchRepos(org, token).then((data) => {\r\n setRepos(limit ? data.slice(0, limit) : data);\r\n setLoading(false);\r\n });\r\n }, [org, token, limit]);\r\n\r\n const languages = [...new Set(repos.map((r) => r.language).filter(Boolean))] as string[];\r\n\r\n const filtered = repos.filter((r) => {\r\n if (lang && r.language !== lang) return false;\r\n if (search) {\r\n const q = search.toLowerCase();\r\n return r.name.toLowerCase().includes(q) || (r.description || \"\").toLowerCase().includes(q);\r\n }\r\n return true;\r\n });\r\n\r\n const handleCardClick = useCallback((repo: Repo) => {\r\n if (onRepoClick) {\r\n onRepoClick(repo);\r\n } else {\r\n setView({ type: \"detail\", repo });\r\n }\r\n }, [onRepoClick]);\r\n\r\n if (view.type === \"detail\") {\r\n return <RepoDetail org={org} repo={view.repo} token={token} t={t} onBack={() => setView({ type: \"list\" })} />;\r\n }\r\n\r\n return (\r\n <div style={{ background: t.bg, color: t.text, fontFamily: \"system-ui, -apple-system, sans-serif\", padding: 24 }}>\r\n {/* Header */}\r\n <div style={{ marginBottom: 24 }}>\r\n <h2 style={{ fontSize: 24, fontWeight: 700, margin: 0 }}>{org}</h2>\r\n <p style={{ color: t.textMuted, fontSize: 14, margin: \"4px 0 0\" }}>\r\n {repos.length} repositories\r\n </p>\r\n </div>\r\n\r\n {/* Search + Filter */}\r\n <div style={{ display: \"flex\", gap: 8, flexWrap: \"wrap\", marginBottom: 16 }}>\r\n <input\r\n type=\"text\"\r\n placeholder=\"Search...\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n style={{\r\n background: t.bgCard, border: `1px solid ${t.border}`, borderRadius: 8,\r\n padding: \"8px 12px\", color: t.text, fontSize: 14, outline: \"none\", flex: \"1 1 200px\",\r\n }}\r\n />\r\n <button\r\n onClick={() => setLang(null)}\r\n style={{\r\n padding: \"6px 12px\", borderRadius: 8, fontSize: 12, fontWeight: 500, cursor: \"pointer\",\r\n background: !lang ? t.accent : \"transparent\",\r\n color: !lang ? \"#fff\" : t.textMuted,\r\n border: `1px solid ${!lang ? t.accent : t.border}`,\r\n }}\r\n >\r\n All\r\n </button>\r\n {languages.map((l) => (\r\n <button\r\n key={l}\r\n onClick={() => setLang(lang === l ? null : l)}\r\n style={{\r\n padding: \"6px 12px\", borderRadius: 8, fontSize: 12, fontWeight: 500, cursor: \"pointer\",\r\n background: lang === l ? t.accent : \"transparent\",\r\n color: lang === l ? \"#fff\" : t.textMuted,\r\n border: `1px solid ${lang === l ? t.accent : t.border}`,\r\n }}\r\n >\r\n {l}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Grid */}\r\n {loading ? (\r\n <div style={{ textAlign: \"center\", padding: 60, color: t.textMuted }}>Loading...</div>\r\n ) : (\r\n <div style={{ display: \"grid\", gridTemplateColumns: \"repeat(auto-fill, minmax(300px, 1fr))\", gap: 16 }}>\r\n {filtered.map((repo) => (\r\n <RepoCard key={repo.name} repo={repo} t={t} onClick={() => handleCardClick(repo)} />\r\n ))}\r\n </div>\r\n )}\r\n {!loading && filtered.length === 0 && (\r\n <div style={{ textAlign: \"center\", padding: 60, color: t.textMuted }}>No results</div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n/* ---------- RepoCard ---------- */\r\n\r\nfunction RepoCard({ repo, t, onClick }: { repo: Repo; t: Theme; onClick: () => void }) {\r\n const [hover, setHover] = useState(false);\r\n const langColor = repo.language ? LANG_COLORS[repo.language] || \"#888\" : null;\r\n const date = new Date(repo.updated_at).toLocaleDateString(\"ko-KR\", { year: \"numeric\", month: \"short\", day: \"numeric\" });\r\n\r\n return (\r\n <div\r\n onClick={onClick}\r\n onMouseEnter={() => setHover(true)}\r\n onMouseLeave={() => setHover(false)}\r\n style={{\r\n background: hover ? t.bgCardHover : t.bgCard,\r\n border: `1px solid ${hover ? t.accent : t.border}`,\r\n borderRadius: 12, padding: 20, cursor: \"pointer\",\r\n transform: hover ? \"translateY(-2px)\" : \"none\",\r\n boxShadow: hover ? `0 0 20px ${t.accentGlow}` : \"none\",\r\n transition: \"all 0.2s\",\r\n }}\r\n >\r\n <div style={{ display: \"flex\", justifyContent: \"space-between\", marginBottom: 8 }}>\r\n <span style={{ fontSize: 16, fontWeight: 600, color: t.accentLight }}>{repo.name}</span>\r\n <button\r\n onClick={(e) => { e.stopPropagation(); window.open(repo.html_url, \"_blank\"); }}\r\n style={{\r\n fontSize: 11, padding: \"2px 8px\", borderRadius: 6, cursor: \"pointer\",\r\n border: `1px solid ${t.border}`, background: \"transparent\", color: t.textMuted,\r\n }}\r\n >\r\n GitHub →\r\n </button>\r\n </div>\r\n <p style={{ fontSize: 13, color: t.textSecondary, margin: \"0 0 12px\", lineHeight: 1.5, minHeight: 40 }}>\r\n {repo.description || \"No description\"}\r\n </p>\r\n <div style={{ display: \"flex\", gap: 12, fontSize: 12, color: t.textMuted }}>\r\n {langColor && (\r\n <span style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\r\n <span style={{ width: 10, height: 10, borderRadius: \"50%\", background: langColor, display: \"inline-block\" }} />\r\n {repo.language}\r\n </span>\r\n )}\r\n {repo.stargazers_count > 0 && <span>★ {repo.stargazers_count}</span>}\r\n {repo.forks_count > 0 && <span>Fork {repo.forks_count}</span>}\r\n <span>{date}</span>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n/* ---------- RepoDetail ---------- */\r\n\r\nfunction RepoDetail({ org, repo, token, t, onBack }: { org: string; repo: Repo; token?: string; t: Theme; onBack: () => void }) {\r\n const [tab, setTab] = useState<\"readme\" | \"demo\">(\"readme\");\r\n const [readme, setReadme] = useState<string | null>(null);\r\n const [snippets, setSnippets] = useState<DemoSnippet[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n Promise.all([\r\n fetchReadme(org, repo.name, token),\r\n fetchDemoSnippets(org, repo.name, undefined, token),\r\n ]).then(([md, s]) => {\r\n setReadme(md);\r\n setSnippets(s);\r\n setLoading(false);\r\n });\r\n }, [org, repo.name, token]);\r\n\r\n return (\r\n <div style={{ background: t.bg, color: t.text, fontFamily: \"system-ui, -apple-system, sans-serif\", padding: 24 }}>\r\n {/* Back */}\r\n <button\r\n onClick={onBack}\r\n style={{\r\n background: \"transparent\", border: \"none\", color: t.accentLight,\r\n cursor: \"pointer\", fontSize: 14, padding: 0, marginBottom: 16,\r\n }}\r\n >\r\n ← Back\r\n </button>\r\n\r\n {/* Header */}\r\n <div style={{ background: t.bgCard, border: `1px solid ${t.border}`, borderRadius: 12, padding: 24, marginBottom: 16 }}>\r\n <div style={{ display: \"flex\", justifyContent: \"space-between\", flexWrap: \"wrap\", gap: 16 }}>\r\n <div>\r\n <h1 style={{ fontSize: 22, fontWeight: 700, margin: 0 }}>{repo.name}</h1>\r\n <p style={{ color: t.textSecondary, fontSize: 14, margin: \"8px 0\" }}>{repo.description || \"No description\"}</p>\r\n </div>\r\n <a\r\n href={repo.html_url}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n style={{\r\n display: \"inline-flex\", alignItems: \"center\", gap: 8,\r\n padding: \"8px 16px\", borderRadius: 8, fontSize: 14, fontWeight: 500,\r\n background: t.accent, color: \"#fff\", textDecoration: \"none\",\r\n height: \"fit-content\",\r\n }}\r\n >\r\n View on GitHub\r\n </a>\r\n </div>\r\n </div>\r\n\r\n {/* Tabs */}\r\n <div style={{ display: \"flex\", gap: 4, borderBottom: `1px solid ${t.border}`, marginBottom: 16 }}>\r\n {([\"readme\", ...(snippets.length > 0 ? [\"demo\"] : [])] as const).map((key) => (\r\n <button\r\n key={key}\r\n onClick={() => setTab(key as typeof tab)}\r\n style={{\r\n padding: \"10px 16px\", fontSize: 14, fontWeight: 500, cursor: \"pointer\",\r\n background: \"transparent\", border: \"none\",\r\n color: tab === key ? t.accentLight : t.textMuted,\r\n borderBottom: tab === key ? `2px solid ${t.accent}` : \"2px solid transparent\",\r\n }}\r\n >\r\n {key === \"readme\" ? \"README\" : \"Demo\"}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n {/* Content */}\r\n <div style={{ background: t.bgCard, border: `1px solid ${t.border}`, borderRadius: 12, padding: 24 }}>\r\n {loading ? (\r\n <div style={{ textAlign: \"center\", padding: 40, color: t.textMuted }}>Loading...</div>\r\n ) : tab === \"readme\" ? (\r\n <ReadmeView org={org} repoName={repo.name} content={readme} t={t} />\r\n ) : (\r\n <DemoView snippets={snippets} t={t} />\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n/* ---------- DemoView ---------- */\r\n\r\nfunction DemoView({ snippets, t }: { snippets: DemoSnippet[]; t: Theme }) {\r\n const [idx, setIdx] = useState(0);\r\n const snippet = snippets[idx];\r\n\r\n if (!snippet) return null;\r\n\r\n return (\r\n <div>\r\n {snippets.length > 1 && (\r\n <div style={{ display: \"flex\", gap: 6, marginBottom: 12, flexWrap: \"wrap\" }}>\r\n {snippets.map((s, i) => (\r\n <button\r\n key={i}\r\n onClick={() => setIdx(i)}\r\n style={{\r\n padding: \"4px 12px\", borderRadius: 99, fontSize: 12, cursor: \"pointer\",\r\n background: i === idx ? t.accentGlow : \"transparent\",\r\n color: i === idx ? t.accentLight : t.textMuted,\r\n border: `1px solid ${i === idx ? t.accent : t.border}`,\r\n }}\r\n >\r\n {s.label}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n <pre\r\n style={{\r\n background: t.bg, border: `1px solid ${t.border}`, borderRadius: 8,\r\n padding: 16, fontSize: 13, lineHeight: 1.6, overflow: \"auto\",\r\n color: t.textSecondary, margin: 0,\r\n }}\r\n >\r\n <code>{snippet.code}</code>\r\n </pre>\r\n {snippet.expectedOutput && (\r\n <div style={{ marginTop: 12 }}>\r\n <span style={{ fontSize: 12, color: t.textMuted }}>Expected Output:</span>\r\n <pre\r\n style={{\r\n background: t.bg, border: `1px solid ${t.border}`, borderRadius: 8,\r\n padding: 12, fontSize: 12, color: t.textMuted, margin: \"4px 0 0\",\r\n }}\r\n >\r\n {snippet.expectedOutput}\r\n </pre>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n","import type { Repo, DemoSnippet } from \"./types\";\r\n\r\nconst API = \"https://api.github.com\";\r\n\r\nfunction headers(token?: string): HeadersInit {\r\n const h: Record<string, string> = { Accept: \"application/vnd.github.v3+json\" };\r\n if (token) h.Authorization = `Bearer ${token}`;\r\n return h;\r\n}\r\n\r\nexport async function fetchRepos(org: string, token?: string): Promise<Repo[]> {\r\n try {\r\n const res = await fetch(`${API}/orgs/${org}/repos?per_page=100&sort=updated`, {\r\n headers: headers(token),\r\n });\r\n if (!res.ok) return [];\r\n return res.json();\r\n } catch {\r\n return [];\r\n }\r\n}\r\n\r\nexport async function fetchReadme(org: string, repo: string, token?: string): Promise<string | null> {\r\n try {\r\n const res = await fetch(`${API}/repos/${org}/${repo}/readme`, {\r\n headers: { ...headers(token), Accept: \"application/vnd.github.v3.raw\" },\r\n });\r\n if (!res.ok) return null;\r\n return res.text();\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nexport async function fetchDemoSnippets(\r\n org: string,\r\n repo: string,\r\n readme?: string | null,\r\n token?: string,\r\n): Promise<DemoSnippet[]> {\r\n // 1. demo.json\r\n for (const path of [\".xgen-gallery/demo.json\", \"demo.json\"]) {\r\n try {\r\n const res = await fetch(`${API}/repos/${org}/${repo}/contents/${path}`, {\r\n headers: { ...headers(token), Accept: \"application/vnd.github.v3.raw\" },\r\n });\r\n if (!res.ok) continue;\r\n const data = await res.json();\r\n if (data.snippets?.length) return data.snippets;\r\n } catch {\r\n continue;\r\n }\r\n }\r\n\r\n // 2. examples/\r\n try {\r\n const res = await fetch(`${API}/repos/${org}/${repo}/contents/examples`, {\r\n headers: headers(token),\r\n });\r\n if (res.ok) {\r\n const files: { name: string; download_url: string }[] = await res.json();\r\n const pyFiles = files.filter((f) => f.name.endsWith(\".py\")).slice(0, 5);\r\n const snippets: DemoSnippet[] = [];\r\n for (const f of pyFiles) {\r\n try {\r\n const r = await fetch(f.download_url);\r\n if (r.ok) {\r\n const code = await r.text();\r\n snippets.push({ label: f.name.replace(/\\.py$/, \"\").replace(/[_-]/g, \" \"), code: code.trim() });\r\n }\r\n } catch { continue; }\r\n }\r\n if (snippets.length) return snippets;\r\n }\r\n } catch { /* ignore */ }\r\n\r\n // 3. README python blocks\r\n let md = readme;\r\n if (!md) md = await fetchReadme(org, repo, token);\r\n if (md) {\r\n const blocks = extractPythonBlocks(md);\r\n if (blocks.length) return blocks;\r\n }\r\n\r\n return [];\r\n}\r\n\r\nfunction extractPythonBlocks(readme: string): DemoSnippet[] {\r\n const snippets: DemoSnippet[] = [];\r\n const lines = readme.split(\"\\n\");\r\n let i = 0;\r\n while (i < lines.length) {\r\n if (/^```(?:python|py)\\s*$/i.test(lines[i].trim())) {\r\n let label = \"\";\r\n for (let j = i - 1; j >= Math.max(0, i - 5); j--) {\r\n const prev = lines[j].trim();\r\n if (/^#{1,4}\\s+/.test(prev)) { label = prev.replace(/^#+\\s+/, \"\"); break; }\r\n if (prev && !label) label = prev;\r\n }\r\n const codeLines: string[] = [];\r\n i++;\r\n while (i < lines.length && !lines[i].trim().startsWith(\"```\")) { codeLines.push(lines[i]); i++; }\r\n const code = codeLines.join(\"\\n\").trim();\r\n if (code && code.split(\"\\n\").length >= 2 && !code.startsWith(\"pip \") && !code.startsWith(\"$ pip\")) {\r\n snippets.push({ label: label || `Example ${snippets.length + 1}`, code });\r\n }\r\n }\r\n i++;\r\n }\r\n return snippets;\r\n}\r\n","export const themes = {\r\n dark: {\r\n bg: \"#0a0a0f\",\r\n bgCard: \"#12121a\",\r\n bgCardHover: \"#1a1a25\",\r\n border: \"#1e1e2e\",\r\n text: \"#e8e8f0\",\r\n textSecondary: \"#a0a0b8\",\r\n textMuted: \"#6b6b80\",\r\n accent: \"#6c63ff\",\r\n accentLight: \"#8b83ff\",\r\n accentGlow: \"rgba(108,99,255,0.15)\",\r\n },\r\n light: {\r\n bg: \"#f8f9fa\",\r\n bgCard: \"#ffffff\",\r\n bgCardHover: \"#f0f0f5\",\r\n border: \"#e0e0e8\",\r\n text: \"#1a1a2e\",\r\n textSecondary: \"#4a4a5a\",\r\n textMuted: \"#8a8a9a\",\r\n accent: \"#5b52e0\",\r\n accentLight: \"#5b52e0\",\r\n accentGlow: \"rgba(91,82,224,0.1)\",\r\n },\r\n};\r\n\r\nexport type Theme = {\r\n bg: string; bgCard: string; bgCardHover: string; border: string;\r\n text: string; textSecondary: string; textMuted: string;\r\n accent: string; accentLight: string; accentGlow: string;\r\n};\r\n\r\nexport const LANG_COLORS: Record<string, string> = {\r\n Python: \"#3572A5\",\r\n TypeScript: \"#3178c6\",\r\n JavaScript: \"#f1e05a\",\r\n Rust: \"#dea584\",\r\n HTML: \"#e34c26\",\r\n CSS: \"#563d7c\",\r\n Go: \"#00ADD8\",\r\n Shell: \"#89e051\",\r\n Java: \"#b07219\",\r\n \"C++\": \"#f34b7d\",\r\n C: \"#555555\",\r\n Ruby: \"#701516\",\r\n};\r\n","import ReactMarkdown from \"react-markdown\";\r\nimport remarkGfm from \"remark-gfm\";\r\nimport rehypeRaw from \"rehype-raw\";\r\nimport type { Theme } from \"./styles\";\r\n\r\nexport function ReadmeView({\r\n org,\r\n repoName,\r\n content,\r\n t,\r\n}: {\r\n org: string;\r\n repoName: string;\r\n content: string | null;\r\n t: Theme;\r\n}) {\r\n if (!content) {\r\n return <div style={{ textAlign: \"center\", padding: 40, color: t.textMuted }}>README not found</div>;\r\n }\r\n\r\n return (\r\n <div className=\"xgen-markdown\" style={{ color: t.text, lineHeight: 1.7, fontSize: 14 }}>\r\n <style>{markdownStyles(t)}</style>\r\n <ReactMarkdown\r\n remarkPlugins={[remarkGfm]}\r\n rehypePlugins={[rehypeRaw]}\r\n components={{\r\n img: ({ src, alt, ...props }) => {\r\n let resolved = src;\r\n if (typeof src === \"string\" && !src.startsWith(\"http\")) {\r\n resolved = `https://raw.githubusercontent.com/${org}/${repoName}/main/${src}`;\r\n }\r\n return <img src={resolved} alt={alt || \"\"} style={{ maxWidth: \"100%\" }} {...props} />;\r\n },\r\n a: ({ href, children, ...props }) => (\r\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\" style={{ color: t.accentLight }} {...props}>\r\n {children}\r\n </a>\r\n ),\r\n code: ({ children, className, ...props }) => {\r\n const isBlock = className?.includes(\"language-\");\r\n if (isBlock) {\r\n return (\r\n <code\r\n style={{\r\n display: \"block\", background: t.bg, padding: 16, borderRadius: 8,\r\n overflow: \"auto\", fontSize: 13, lineHeight: 1.6,\r\n }}\r\n {...props}\r\n >\r\n {children}\r\n </code>\r\n );\r\n }\r\n return (\r\n <code style={{ background: t.accentGlow, padding: \"2px 6px\", borderRadius: 4, fontSize: 13 }} {...props}>\r\n {children}\r\n </code>\r\n );\r\n },\r\n }}\r\n >\r\n {content}\r\n </ReactMarkdown>\r\n </div>\r\n );\r\n}\r\n\r\nfunction markdownStyles(t: Theme): string {\r\n return `\r\n .xgen-markdown h1, .xgen-markdown h2, .xgen-markdown h3 { color: ${t.text}; margin: 1.2em 0 0.5em; }\r\n .xgen-markdown h1 { font-size: 1.8em; border-bottom: 1px solid ${t.border}; padding-bottom: 8px; }\r\n .xgen-markdown h2 { font-size: 1.4em; border-bottom: 1px solid ${t.border}; padding-bottom: 6px; }\r\n .xgen-markdown h3 { font-size: 1.15em; }\r\n .xgen-markdown p { margin: 0.8em 0; }\r\n .xgen-markdown ul, .xgen-markdown ol { padding-left: 24px; }\r\n .xgen-markdown li { margin: 4px 0; }\r\n .xgen-markdown pre { background: ${t.bg}; border: 1px solid ${t.border}; border-radius: 8px; padding: 16px; overflow: auto; margin: 12px 0; }\r\n .xgen-markdown blockquote { border-left: 3px solid ${t.accent}; padding-left: 12px; color: ${t.textSecondary}; margin: 12px 0; }\r\n .xgen-markdown table { border-collapse: collapse; width: 100%; margin: 12px 0; }\r\n .xgen-markdown th, .xgen-markdown td { border: 1px solid ${t.border}; padding: 8px 12px; text-align: left; }\r\n .xgen-markdown th { background: ${t.bgCard}; font-weight: 600; }\r\n .xgen-markdown hr { border: none; border-top: 1px solid ${t.border}; margin: 16px 0; }\r\n `;\r\n}\r\n"],"mappings":"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","names":["jsx","jsxs"]}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@plateerlab/xgen-gallery",
3
+ "version": "0.1.0",
4
+ "description": "React component to showcase GitHub organization repositories",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": ["dist"],
16
+ "scripts": {
17
+ "build": "tsup",
18
+ "prepublishOnly": "npm run build"
19
+ },
20
+ "peerDependencies": {
21
+ "react": ">=18",
22
+ "react-dom": ">=18"
23
+ },
24
+ "dependencies": {
25
+ "react-markdown": "^10.1.0",
26
+ "rehype-raw": "^7.0.0",
27
+ "remark-gfm": "^4.0.1"
28
+ },
29
+ "devDependencies": {
30
+ "@types/react": "^19",
31
+ "@types/react-dom": "^19",
32
+ "react": "19.2.4",
33
+ "react-dom": "19.2.4",
34
+ "tsup": "^8",
35
+ "typescript": "^5"
36
+ },
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/PlateerLab/xgen-gallery.git"
41
+ },
42
+ "keywords": ["react", "github", "gallery", "plateerlab", "xgen"]
43
+ }