mirror of
https://github.com/sune-org/store.git
synced 2026-09-18 12:25:43 +00:00
1 line
17 KiB
JSON
1 line
17 KiB
JSON
[{"id":"e1yibwd","name":"Marketplace","pinned":false,"avatar":"data:image/webp;base64,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","url":"gh://sune-org/store/marketplace.sune","updatedAt":1788220441102,"settings":{"model":"","temperature":"","top_p":"","top_k":"","frequency_penalty":"","repetition_penalty":"","min_p":"","top_a":"","verbosity":"","reasoning_effort":"default","system_prompt":"","html":"<!--\nSune: Marketplace\nVersion: 2.5.6\nDescription: Discover and install sunes from a configurable catalog URL.\n-->\n<section id=\"suneMarketplace\" class=\"p-3 sm:p-5 bg-slate-50 not-prose max-w-4xl mx-auto rounded-2xl border border-slate-200 my-2\" style=\"max-height:80vh;overflow-y:auto;\">\n <header id=\"mpHeader\" class=\"mb-4 pb-3 border-b border-slate-200 flex items-center justify-between\">\n <div class=\"flex items-center gap-2\">\n <div class=\"h-8 w-8 rounded-xl bg-slate-900 text-white flex items-center justify-center\">\n <i data-lucide=\"store\" class=\"h-4 w-4\"></i>\n </div>\n <div>\n <div class=\"flex items-center gap-1.5\">\n <h1 class=\"text-base font-bold text-slate-800 leading-none\">Sune Store</h1>\n <span class=\"text-[10px] font-mono px-1.5 py-0.5 rounded bg-slate-200 text-slate-600 leading-none\">v2.5.6</span>\n </div>\n <p class=\"text-[11px] text-slate-400 mt-0.5\">Explore modules & extensions</p>\n </div>\n </div>\n <button id=\"mpRefresh\" class=\"h-8 px-2.5 rounded-lg bg-white border border-slate-200 text-slate-700 text-xs font-medium hover:bg-slate-100 active:scale-[.98] transition flex items-center gap-1 shadow-sm\" title=\"Refresh catalog\">\n <i data-lucide=\"refresh-cw\" class=\"h-3.5 w-3.5 text-slate-500\"></i>\n <span class=\"hidden sm:inline\">Refresh</span>\n </button>\n </header>\n\n <div id=\"mpNav\" class=\"mb-3\"></div>\n <div id=\"mpContent\" class=\"min-h-[120px]\">\n <div class=\"flex justify-center items-center py-12\">\n <div class=\"animate-spin rounded-full h-8 w-8 border-2 border-slate-400 border-t-transparent\"></div>\n </div>\n </div>\n\n <footer class=\"mt-6 pt-4 border-t border-slate-200\">\n <div class=\"text-center bg-white p-4 rounded-xl border border-slate-200 shadow-sm\">\n <div class=\"flex items-center justify-center gap-1.5\">\n <i data-lucide=\"git-pull-request-arrow\" class=\"h-4 w-4 text-slate-600\"></i>\n <h3 class=\"text-xs font-semibold text-slate-800\">Contribute your Sune</h3>\n </div>\n <p class=\"mt-1 text-[11px] text-slate-500 max-w-sm mx-auto\">\n Publish your sune to the community via pull request in\n <a href=\"https://github.com/sune-org/store\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"font-medium text-sky-600 hover:underline\">sune-org/store</a>.\n </p>\n </div>\n </footer>\n</section>\n\n<script>\n(()=>{\n/* =========================================================\n EDIT CATALOG URL HERE\n ========================================================= */\nconst CATALOG_URL = 'https://raw.githack.com/sune-org/store/main/catalog.json';\n\nconst $ = s => document.querySelector(s);\nconst ico = () => window.lucide?.createIcons();\nconst esc = s => String(s ?? '').replace(/[&<>\"]/g, m => ({ '&':'&','<':'<','>':'>','\"':'"' }[m]));\nconst TTL = 3e5; // 5 min cache TTL\n\nconst root = $(\"#suneMarketplace\"), nav = $(\"#mpNav\"), content = $(\"#mpContent\"), refreshBtn = $(\"#mpRefresh\");\nif (!root) return;\n\nlet catalogData = [], currentView = 'main';\n\n/* Helpers */\nconst b64url2b64 = s => { let x = (s || '').replace(/-/g, '+').replace(/_/g, '/'); while (x && x.length % 4) x += '='; return x; };\nconst sniff = b => b.startsWith('iVBOR') ? 'image/png' : (b.startsWith('/9j/') ? 'image/jpeg' : (b.startsWith('UklGR') ? 'image/webp' : (b.startsWith('R0lGOD') ? 'image/gif' : 'application/octet-stream')));\nconst avatarSrc = v => { if (!v || v.length < 10) return ''; if (/^data:/.test(v)) return v; const b64 = b64url2b64(v), mime = sniff(b64); return `data:${mime};base64,${b64}`; };\nconst ghRaw = u => { try { if (!u || !u.startsWith('gh://')) return u; const s = u.slice(5), [hd, ...rest] = s.split('/'), [ur, br] = hd.split('@'), [user, repo] = ur.split('/'); return `https://raw.githack.com/${user}/${repo}/${br}/${rest.join('/')}`; } catch { return u; } };\nconst ghUrlFromRaw = u => { try { const r = new URL(u); if (!['raw.githubusercontent.com','raw.githack.com'].includes(r.hostname)) return ''; const [,u1,r1,b,...p] = r.pathname.split('/'); return `gh://${u1}/${r1}@${b}/${p.join('/')}`; } catch { return ''; } };\nconst T = s => (s || '').replace(/\\.sune$/, '').replace(/[-_]/g, ' ').replace(/\\b\\w/g, m => m.toUpperCase());\nconst installed = () => new Set((window.SUNE?.list || []).map(x => x?.id).filter(Boolean));\n\n/* UI Builders */\nconst btn = (it, ins) => ins \n ? `<button class=\"mt-3 w-full px-3 py-1.5 text-xs font-medium rounded-lg bg-slate-100 text-slate-400 cursor-default flex items-center justify-center gap-1\" disabled><i data-lucide=\"check-circle\" class=\"h-3.5 w-3.5\"></i><span>Installed</span></button>`\n : `<button class=\"mpInstall mt-3 w-full px-3 py-1.5 text-xs font-medium rounded-lg bg-slate-900 text-white hover:bg-slate-800 active:scale-[.98] transition flex items-center justify-center gap-1 shadow-sm\" data-id=\"${esc(it.id||'')}\" data-raw=\"${esc(it.raw||'')}\"><i data-lucide=\"download\" class=\"h-3.5 w-3.5\"></i><span>Install</span></button>`;\n\nconst card = (it, ins) => {\n const src = avatarSrc(it.avatar);\n return `<article class=\"bg-white border border-slate-200 rounded-xl shadow-sm p-3 flex flex-col justify-between\">\n <div>\n <div class=\"flex items-center gap-2.5\">\n ${src ? `<img alt=\"\" src=\"${src}\" loading=\"lazy\" class=\"h-8 w-8 rounded-lg object-cover bg-slate-100 border border-slate-200 shrink-0\">` : `<div class=\"h-8 w-8 rounded-lg bg-slate-100 border border-slate-200 text-slate-400 flex items-center justify-center shrink-0\"><i data-lucide=\"box\" class=\"h-4 w-4\"></i></div>`}\n <div class=\"min-w-0 flex-1\">\n <h3 class=\"text-xs font-bold text-slate-800 truncate\">${esc(T(it.name))}</h3>\n <p class=\"text-[10px] text-slate-400 truncate\">${esc(it.description || 'Utility sune.')}</p>\n </div>\n </div>\n <div class=\"mt-2 text-[9px] text-slate-400 truncate font-mono\">${esc(it.id || '')}</div>\n </div>\n ${btn(it, ins)}\n </article>`;\n};\n\nconst folderCard = f => `<button class=\"mpFolder w-full text-left p-3 bg-white border border-slate-200 rounded-xl shadow-sm hover:bg-slate-50 transition flex items-center gap-2.5\" data-folder=\"${esc(f.folder)}\">\n <div class=\"h-8 w-8 rounded-lg bg-slate-100 text-slate-600 flex items-center justify-center shrink-0\"><i data-lucide=\"folder\" class=\"h-4 w-4\"></i></div>\n <div class=\"flex-1 min-w-0\">\n <div class=\"text-xs font-semibold text-slate-800\">${esc(T(f.folder))}</div>\n <div class=\"text-[10px] text-slate-400\">${f.sunes.length} sune${f.sunes.length === 1 ? '' : 's'}</div>\n </div>\n <i data-lucide=\"chevron-right\" class=\"h-4 w-4 text-slate-400\"></i>\n</button>`;\n\nconst render = () => {\n nav.innerHTML = '';\n const ids = installed();\n if (currentView === 'main') {\n const folders = catalogData.filter(f => f.folder !== '.').sort((a, b) => a.folder.localeCompare(b.folder));\n const rootSunes = (catalogData.find(f => f.folder === '.')?.sunes || []);\n let foldersHtml = folders.length ? `<div class=\"grid gap-2 grid-cols-1 sm:grid-cols-2\">${folders.map(folderCard).join('')}</div>` : '';\n let sunesHtml = rootSunes.length ? `<div class=\"grid gap-2.5 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\">${rootSunes.map(s => card(s, s.id ? ids.has(s.id) : false)).join('')}</div>` : '';\n let html = foldersHtml + (foldersHtml && sunesHtml ? '<div class=\"my-3\"></div>' : '') + sunesHtml;\n content.innerHTML = html || `<div class=\"text-center py-8 text-xs text-slate-400\">No sunes found.</div>`;\n } else {\n const folder = catalogData.find(f => f.folder === currentView);\n nav.innerHTML = `<button class=\"mpBack inline-flex items-center gap-1 px-2.5 py-1 text-xs font-medium rounded-lg bg-slate-200 text-slate-700 hover:bg-slate-300 transition\"><i data-lucide=\"arrow-left\" class=\"h-3 w-3\"></i>Back</button>`;\n content.innerHTML = folder ? `<div class=\"grid gap-2.5 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3\">${folder.sunes.map(s => card(s, s.id ? ids.has(s.id) : false)).join('')}</div>` : `<div class=\"text-center py-8 text-xs text-slate-400\">Folder not found.</div>`;\n }\n ico();\n};\n\n/* Cache & Fetch */\nconst loadCat = () => window.SUNE?.storage?.get ? window.SUNE.storage.get('catalog_cache', null) : null;\nconst saveCat = d => window.SUNE?.storage?.set && window.SUNE.storage.set('catalog_cache', { t: Date.now(), items: d });\n\nconst fetchCatalog = async () => {\n const U = ghRaw(CATALOG_URL);\n const r = await fetch(U, { cache: 'no-store' });\n if (!r.ok) throw new Error(`Catalog fetch failed: ${r.status}`);\n const raw = await r.json();\n if (!Array.isArray(raw)) throw new Error('Invalid catalog format.');\n const items = raw.filter(f => f && f.folder && f.sunes?.length > 0);\n saveCat(items);\n return items;\n};\n\nconst boot = async (force = false) => {\n try {\n const cache = loadCat();\n catalogData = (!force && cache?.items && Date.now() - (cache.t || 0) < TTL) ? cache.items : await fetchCatalog();\n currentView = 'main';\n render();\n } catch (e) {\n content.innerHTML = `<div class=\"text-center py-8 bg-red-50 text-red-600 text-xs rounded-xl p-3\"><p class=\"font-semibold\">Unable to load Marketplace</p><p class=\"mt-1 opacity-80\">${esc(e?.message || e)}</p></div>`;\n } finally {\n ico();\n }\n};\n\nrefreshBtn?.addEventListener('click', e => { e.preventDefault(); boot(true); });\n\nroot.addEventListener('click', async e => {\n const installBtn = e.target.closest('.mpInstall'), folderBtn = e.target.closest('.mpFolder'), backBtn = e.target.closest('.mpBack');\n if (backBtn) { currentView = 'main'; render(); return; }\n if (folderBtn) { currentView = folderBtn.dataset.folder || 'main'; render(); return; }\n if (!installBtn) return;\n\n const rawUrl = installBtn.dataset.raw;\n try {\n if (!rawUrl) throw new Error('Missing URL');\n installBtn.disabled = true;\n installBtn.innerHTML = `<i data-lucide=\"loader\" class=\"h-3.5 w-3.5 animate-spin\"></i><span>Installing...</span>`;\n ico();\n\n const githackUrl = ghRaw(rawUrl);\n const arr = await (await fetch(githackUrl)).json();\n if (!Array.isArray(arr) || !arr.length) throw new Error('Corrupt file');\n\n let upd = 0;\n for (const s of arr) {\n if (!s?.id) continue;\n s.url = s.url || ghUrlFromRaw(githackUrl);\n const ex = (window.SUNE?.list || []).find(x => x.id === s.id);\n if (!ex) window.SUNE.create(s);\n else if (+s.updatedAt > +ex.updatedAt) { Object.assign(ex, s); upd++; }\n }\n if (upd > 0) window.SUNE?.save?.();\n window.renderSidebar?.();\n installBtn.outerHTML = `<button class=\"mt-3 w-full px-3 py-1.5 text-xs font-medium rounded-lg bg-slate-100 text-slate-400 cursor-default flex items-center justify-center gap-1\" disabled><i data-lucide=\"check-circle\" class=\"h-3.5 w-3.5\"></i><span>Installed</span></button>`;\n ico();\n } catch (err) {\n installBtn.disabled = false;\n installBtn.innerHTML = `<i data-lucide=\"alert-triangle\" class=\"h-3.5 w-3.5\"></i><span>Retry</span>`;\n ico();\n }\n});\n\nboot();\n})();\n</script>\n","extension_html":"<sune src='https://raw.githubusercontent.com/sune-org/store/refs/heads/main/sync.sune' private></sune>","hide_composer":true,"include_thoughts":false,"img_output":false,"aspect_ratio":"1:1","image_size":"1K","ignore_master_prompt":false,"presence_penalty":"0","max_tokens":""}}] |