mirror of
https://github.com/sune-org/store.git
synced 2026-01-14 00:27:59 +00:00
1 line
23 KiB
JSON
1 line
23 KiB
JSON
[{"id":"37uz2i8","name":"GitHub","pinned":true,"avatar":"","url":"gh://sune-org/store/github.sune","updatedAt":1757196496225,"settings":{"model":"openai/gpt-5-chat","temperature":"","top_p":"","top_k":"","frequency_penalty":"","presence_penalty":"","repetition_penalty":"","min_p":"","top_a":"","max_tokens":"","verbosity":"","reasoning_effort":"default","system_prompt":"","html":"<div id=\"ghRepoBrowserSune\" class=\"relative px-0 bg-white/80 backdrop-blur-xl rounded-lg border border-gray-200 shadow-sm font-sans overflow-hidden\">\n <!-- Background Blob -->\n <div class=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-96 h-96 bg-gradient-to-tr from-cyan-200 via-blue-300 to-purple-300 rounded-full opacity-30 filter blur-3xl -z-10\" aria-hidden=\"true\"></div>\n\n <!-- Header -->\n <div class=\"flex justify-between items-center mb-4\">\n <h2 id=\"viewTitle\" class=\"font-bold text-lg text-gray-800 transition-all\">GitHub Repositories</h2>\n <span class=\"text-xs text-gray-400\">v-0.7.1</span>\n </div>\n\n <!-- View: Repository List -->\n <div id=\"repoListView\" class=\"p-4\">\n <div id=\"repoList\" class=\"space-y-2 mb-3\"></div>\n <button id=\"addRepoBtn\" class=\"w-full flex items-center justify-center gap-2 px-4 py-2 text-xs text-gray-600 bg-gray-100 rounded-lg hover:bg-gray-200 active:scale-[0.98] transition-all\">\n <i data-lucide=\"plus\" class=\"h-4 w-4\"></i><span>Add Repository</span>\n </button>\n </div>\n\n <!-- View: Repository Browser -->\n <div id=\"repoBrowserView\" class=\"hidden\">\n <div class=\"flex items-center mb-3 -mt-2\">\n <button id=\"backBtn\" class=\"flex items-center gap-1.5 px-3 py-1 text-sm text-gray-600 rounded-lg hover:bg-gray-100 active:scale-[0.98] transition-all\">\n <i data-lucide=\"arrow-left\" class=\"h-4 w-4\"></i><span>Back</span>\n </button>\n </div>\n \n <div id=\"fileBrowserContainer\">\n <div id=\"breadcrumbs\" class=\"flex items-center gap-1.5 text-sm text-gray-500 mb-2 overflow-x-auto pb-2 -mr-4 pr-4\"></div>\n <div id=\"fileTree\" class=\"space-y-1 max-h-[60vh] overflow-y-auto border border-gray-200 rounded-lg p-2 bg-gray-50/50\"></div>\n </div>\n \n <div id=\"fileHistoryContainer\" class=\"hidden p-4\">\n <div id=\"fileHistoryHeader\" class=\"flex justify-between items-center text-sm font-medium text-gray-700 mb-2 truncate\">\n <span id=\"fileHistoryTitle\"></span>\n <button id=\"commitLatestBtn\" class=\"inline-flex items-center justify-center gap-1.5 h-8 px-3 shrink-0 rounded-lg bg-green-600 text-white shadow-sm hover:bg-green-700 active:scale-[0.98] transition text-xs font-medium\" title=\"Edit latest version and commit\">\n <i data-lucide=\"edit-3\" class=\"h-3 w-3\"></i><span>Commit</span>\n </button>\n </div>\n <div id=\"commitList\" class=\"space-y-2 max-h-[60vh] overflow-y-auto -mr-2 pr-2\"></div>\n </div>\n\n <!-- Container for the Editor Sune -->\n <div id=\"editorContainer\" class=\"hidden\">\n <!-- GitHub File Editor Sune v1.5.1 -->\n <div id=\"gh-editor-sune\" class=\"mx-0 border-b border-gray-200 bg-gray-50 flex flex-col rounded-lg shadow-inner overflow-hidden w-full max-h-[80vh]\">\n <!-- Editor View -->\n <div id=\"gh-editor-view\" class=\"flex flex-col\">\n <div class=\"flex items-center gap-3 px-3 sm:px-4 py-2 border-b border-gray-200 bg-white/80 backdrop-blur-sm shrink-0\">\n <button id=\"gh-back-btn\" class=\"p-1.5 -ml-1.5 rounded-md hover:bg-gray-200 text-gray-500 hover:text-gray-800 transition-colors\" title=\"Back to History\"><i data-lucide=\"arrow-left\" class=\"h-5 w-5 shrink-0\"></i></button>\n <input type=\"text\" id=\"ghPathInput\" placeholder=\"owner/repo/path/to/file.ext@branch\" class=\"flex-1 w-full bg-transparent border-none focus:ring-0 p-0 text-sm placeholder:text-gray-400\" readonly/>\n <button id=\"ghCommitBtn\" class=\"inline-flex items-center justify-center gap-1.5 h-8 px-3 shrink-0 rounded-lg bg-green-600 text-white shadow-sm hover:bg-green-700 active:scale-[0.98] transition text-sm font-medium\" title=\"Commit Changes\"><i data-lucide=\"check-circle\" class=\"h-4 w-4\"></i><span class=\"hidden sm:inline\">Commit</span></button>\n </div>\n <div id=\"ghSearchContainer\" class=\"hidden flex items-center gap-2 px-3 sm:px-4 py-1.5 border-b border-gray-200 bg-white shrink-0\">\n <i data-lucide=\"search\" class=\"h-4 w-4 text-gray-500 shrink-0\"></i>\n <input type=\"text\" id=\"ghSearchInput\" placeholder=\"Find\" class=\"flex-1 w-full bg-transparent border-none focus:ring-0 p-0 text-sm placeholder:text-gray-400\" />\n <span id=\"ghSearchCount\" class=\"text-xs text-gray-500 shrink-0 tabular-nums\">0/0</span>\n <div class=\"flex items-center\">\n <button id=\"ghSearchPrevBtn\" class=\"p-1 rounded-md hover:bg-gray-200 text-gray-500 hover:text-gray-800 transition-colors\"><i data-lucide=\"chevron-up\" class=\"h-5 w-5\"></i></button>\n <button id=\"ghSearchNextBtn\" class=\"p-1 rounded-md hover:bg-gray-200 text-gray-500 hover:text-gray-800 transition-colors\"><i data-lucide=\"chevron-down\" class=\"h-5 w-5\"></i></button>\n <button id=\"ghSearchCloseBtn\" class=\"p-1 rounded-md hover:bg-gray-200 text-gray-500 hover:text-gray-800 transition-colors\"><i data-lucide=\"x\" class=\"h-5 w-5\"></i></button>\n </div>\n </div>\n <div class=\"bg-white flex-1 relative\"><pre id=\"ghFileEditor\" class=\"w-full h-[65vh] p-3 overflow-auto font-mono text-[12px] leading-5 focus:outline-none [white-space:pre!important]\" contenteditable=\"plaintext-only\" spellcheck=\"false\"></pre></div>\n <div class=\"flex items-center justify-between gap-4 px-3 sm:px-4 py-1 border-t border-gray-200 bg-white/80 backdrop-blur-sm text-xs shrink-0\">\n <div class=\"flex items-center gap-1\">\n <button id=\"ghSearchBtn\" title=\"Search (Ctrl+F)\" class=\"p-1.5 rounded-md hover:bg-gray-200 text-gray-500 hover:text-gray-800 transition-colors\"><i data-lucide=\"search\" class=\"h-4 w-4\"></i></button>\n <button id=\"ghCopyBtn\" title=\"Copy\" class=\"p-1.5 rounded-md hover:bg-gray-200 text-gray-500 hover:text-gray-800 transition-colors\"><i data-lucide=\"copy\" class=\"h-4 w-4\"></i></button>\n </div>\n <div class=\"flex items-center gap-3 text-gray-500 truncate\">\n <span id=\"ghLangBadge\" class=\"font-medium\">Plain Text</span>\n <div id=\"ghStatus\" class=\"h-4 truncate\"></div>\n </div>\n <span class=\"text-gray-400\">v1.5.1</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<script>\n(async function() {\n const sune = document.getElementById('ghRepoBrowserSune');\n if (!sune || sune.dataset.initialized) return;\n sune.dataset.initialized = 'true';\n\n // --- BROWSER SUNE ---\n const SUNE_ID_B = window.SUNE?.id || 'gh-repo-browser-sune';\n const CACHE_KEY_B = `${SUNE_ID_B}_gh_repos`;\n let currentRepoInfo = {}, pathHistory = [], browserSubView = 'tree', currentFilePath = '';\n\n const viewTitle=sune.querySelector('#viewTitle'),repoListView=sune.querySelector('#repoListView'),repoBrowserView=sune.querySelector('#repoBrowserView'),repoList=sune.querySelector('#repoList'),addRepoBtn=sune.querySelector('#addRepoBtn'),backBtn=sune.querySelector('#backBtn'),fileBrowserContainer=sune.querySelector('#fileBrowserContainer'),fileHistoryContainer=sune.querySelector('#fileHistoryContainer'),editorContainer=sune.querySelector('#editorContainer'),breadcrumbs=sune.querySelector('#breadcrumbs'),fileTree=sune.querySelector('#fileTree'),fileHistoryHeader=sune.querySelector('#fileHistoryHeader'),fileHistoryTitle=sune.querySelector('#fileHistoryTitle'),commitLatestBtn=sune.querySelector('#commitLatestBtn'),commitList=sune.querySelector('#commitList');\n\n const parseRepoPath=p=>p?.match(/^([a-z\\d\\-_]+)\\/([a-z\\d\\-_.]+)(?:@([^\\/]+))?$/i)?.slice(1);\n const saveRepos=()=>localStorage.setItem(CACHE_KEY_B,JSON.stringify([...sune.querySelectorAll('.repo-path-input')].map(i=>i.value.trim())));\n const showView=v=>{repoListView.classList.toggle('hidden',v!=='list');repoBrowserView.classList.toggle('hidden',v!=='browser');if(v==='list'){viewTitle.textContent='GitHub Repositories';pathHistory=[];breadcrumbs.innerHTML='';fileTree.innerHTML='';showBrowserSubView('tree')}else{viewTitle.textContent=`${currentRepoInfo.owner}/${currentRepoInfo.repo}`}};\n const showBrowserSubView=v=>{browserSubView=v;fileBrowserContainer.classList.toggle('hidden',v!=='tree');fileHistoryContainer.classList.toggle('hidden',v!=='history');editorContainer.classList.toggle('hidden',v!=='editor');if(v==='tree'){commitList.innerHTML='';fileHistoryTitle.innerHTML=''}};\n const ghFetch=async u=>{const h={'Accept':'application/vnd.github.v3+json'};if(window.USER?.PAT)h['Authorization']=`token ${window.USER.PAT}`;const r=await fetch(u,{headers:h});if(!r.ok){const e=await r.json().catch(()=>({message:`API Error: ${r.status}`}));throw new Error(e.message||`API Err: ${r.status}`)};return r.json()};\n const fetchHistory=async(fPath,btn)=>{showBrowserSubView('history');currentFilePath=fPath;fileHistoryTitle.innerHTML=`<div class=\"flex items-center gap-2\"><svg class=\"animate-spin h-4 w-4\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"><circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle><path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path></svg> <span>Loading...</span></div>`;commitList.innerHTML='';try{const{owner,repo,branch}=currentRepoInfo;const commits=await ghFetch(`https://api.github.com/repos/${owner}/${repo}/commits?path=${encodeURIComponent(fPath)}&sha=${encodeURIComponent(branch)}`);fileHistoryTitle.innerHTML=`History for <b>${fPath.split('/').pop()}</b>`;if(!commits?.length)commitList.innerHTML=`<div class=\"text-xs text-center text-gray-500 p-3 bg-gray-50 rounded-md\">No commits found.</div>`;else commitList.innerHTML=commits.map(i=>{const m=i.commit,a=i.author||m.author,d=new Date(m.author.date).toLocaleString([],{dateStyle:'medium',timeStyle:'short'});return`<div class=\"p-3 border border-gray-200 rounded-lg bg-gray-50/50 hover:bg-white hover:shadow-md transition-all\"><p class=\"font-medium text-sm text-gray-800 truncate\">${m.message.split('\\n')[0]}</p><div class=\"flex flex-col sm:flex-row justify-between items-start sm:items-center mt-2 gap-2\"><div class=\"flex items-center gap-2 text-xs text-gray-500\">${a?.avatar_url?`<img src=\"${a.avatar_url}\" class=\"h-5 w-5 rounded-full\">`:''}<span class=\"font-medium\">${m.author.name}</span><span class=\"hidden md:inline\">•</span><span class=\"flex-shrink-0\">${d}</span></div><div class=\"flex items-center gap-2 self-end sm:self-center flex-shrink-0\"><button class=\"view-content-btn px-3 py-1 text-xs bg-white border border-gray-300 rounded-md shadow-sm hover:bg-gray-100 active:scale-95\" data-sha=\"${i.sha}\">View File</button></div></div></div>`}).join('')}catch(e){fileHistoryTitle.innerHTML=`Error loading history`;commitList.innerHTML=`<div class=\"text-xs text-center text-red-600 p-3 bg-red-50 rounded-md\">${e.message}</div>`}finally{btn?.classList.add('bg-blue-100','font-semibold')}};\n const renderBreadcrumbs=()=>{breadcrumbs.innerHTML=pathHistory.map((p,i)=>`<button class=\"breadcrumb-item inline-flex items-center gap-1.5 hover:text-blue-600 disabled:text-gray-800\" data-index=\"${i}\" ${i===pathHistory.length-1?'disabled':''}>${p.name==='root'?'<i data-lucide=\"git-branch\" class=\"h-4 w-4\"></i>':''}${p.name}${i<pathHistory.length-1?'<i data-lucide=\"chevron-right\" class=\"h-4 w-4 text-gray-400 -mr-1\"></i>':''}</button>`).join('');window.lucide?.createIcons()};\n const fetchAndRenderTree=async(sha,name)=>{showBrowserSubView('tree');if(name)pathHistory.push({name,sha});else pathHistory=[{name:'root',sha}];renderBreadcrumbs();fileTree.innerHTML='<div class=\"text-sm text-center p-4\">Loading...</div>';try{const{tree}=await ghFetch(`https://api.github.com/repos/${currentRepoInfo.owner}/${currentRepoInfo.repo}/git/trees/${sha}`);const s=tree.sort((a,b)=>{if(a.type===b.type)return a.path.localeCompare(b.path);return a.type==='tree'?-1:1});fileTree.innerHTML=s.map(i=>`<button class=\"file-item w-full flex items-center gap-2 p-2 text-left text-sm rounded-md hover:bg-gray-200\" data-path=\"${i.path}\" data-sha=\"${i.sha}\" data-type=\"${i.type}\"><i data-lucide=\"${i.type==='tree'?'folder':'file-text'}\" class=\"h-4 w-4 text-gray-500 shrink-0\"></i><span class=\"truncate\">${i.path.split('/').pop()}</span></button>`).join('')||'<div class=\"text-xs text-center text-gray-500 p-3\">Empty directory.</div>';window.lucide?.createIcons()}catch(e){alert(`Error fetching tree: ${e.message}`)}};\n const addRepoRow=p=>{const r=document.createElement('div');r.className='repo-row relative flex w-full items-center';r.innerHTML=`<i data-lucide=\"github\" class=\"pointer-events-none absolute left-3 top-1/2 z-10 h-4 w-4 -translate-y-1/2 text-gray-400\"></i><input type=\"text\" value=\"${p}\" placeholder=\"org/repo@branch\" class=\"repo-path-input w-full rounded-lg border py-2 pl-9 pr-32 text-sm outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/50\"><div class=\"absolute right-1.5 flex items-center gap-1\"><button class=\"browse-repo-btn flex items-center justify-center gap-2 rounded-md bg-blue-600 px-3 py-1.5 text-xs font-semibold text-white hover:bg-blue-700 active:scale-[0.98] disabled:bg-blue-400\">Browse</button><button class=\"remove-repo-btn flex items-center justify-center rounded-md p-1.5 text-red-500/80 hover:bg-red-500/10 hover:text-red-700\"><i data-lucide=\"x\" class=\"h-4 w-4\"></i></button></div>`;repoList.append(r);window.lucide?.createIcons()};\n const startRepoBrowse=async b=>{const i=b.closest('.repo-row').querySelector('.repo-path-input'),v=i.value.trim();if(!v)return;const p=parseRepoPath(v);if(!p){alert(\"Invalid format: org/repo@branch\");return}b.disabled=true;try{currentRepoInfo={owner:p[0],repo:p[1],branch:p[2]||null};if(!currentRepoInfo.branch){const r=await ghFetch(`https://api.github.com/repos/${currentRepoInfo.owner}/${currentRepoInfo.repo}`);currentRepoInfo.branch=r.default_branch;i.value=`${currentRepoInfo.owner}/${currentRepoInfo.repo}@${currentRepoInfo.branch}`;saveRepos()}const branchInfo=await ghFetch(`https://api.github.com/repos/${currentRepoInfo.owner}/${currentRepoInfo.repo}/branches/${currentRepoInfo.branch}`);showView('browser');await fetchAndRenderTree(branchInfo.commit.commit.tree.sha)}catch(e){alert(`Error: ${e.message}`);showView('list')}finally{b.disabled=false}};\n \n // --- EDITOR SUNE --- (Integrated)\n window.SUNE_GH_EDITOR = (() => {\n const getEl = id => sune.querySelector(`#${id}`);\n const [editorView,pathInput,commitBtn,fileEditorEl,searchBtn,copyBtn,statusEl,langBadge,searchContainer,searchInput,searchCount,searchPrevBtn,searchNextBtn,searchCloseBtn,ghBackBtn] = ['gh-editor-view','ghPathInput','ghCommitBtn','ghFileEditor','ghSearchBtn','ghCopyBtn','ghStatus','ghLangBadge','ghSearchContainer','ghSearchInput','ghSearchCount','ghSearchPrevBtn','ghSearchNextBtn','ghSearchCloseBtn','gh-back-btn'].map(getEl);\n const S = {o:null,r:null,p:null,b:null,sha:null,jar:null,t:null,l:null,search:{q:'',m:[],c:-1,oh:null}};\n const setStatus=(msg,isErr=false)=>{statusEl.textContent=msg||'';statusEl.className=`h-4 truncate ${isErr?'text-red-600':'text-gray-500'}`;if(!isErr&&msg)setTimeout(()=>statusEl.textContent===msg&&(statusEl.textContent=''),4e3);};\n const setLoading=(btn,loading)=>{btn.disabled=loading;const i=btn.querySelector('i');if(!i)return;if(loading){if(!i.dataset.og)i.dataset.og=i.dataset.lucide;i.dataset.lucide='loader-circle';i.classList.add('animate-spin')}else{if(i.dataset.og)i.dataset.lucide=i.dataset.og;i.classList.remove('animate-spin')}window.lucide?.createIcons()};\n const parsePath=i=>String(i).trim().match(/^([\\w.-]+)\\/([\\w.-]+)\\/(.+?)@([\\w.-]+)$/);\n const detectLang=p=>(p=String(p||'').toLowerCase(),{lang:/\\.html?$/.test(p)?'xml':/\\.m?js|cjs$/.test(p)?'javascript':/\\.json$/.test(p)?'json':/\\.css$/.test(p)?'css':/\\.md$/.test(p)?'markdown':'plaintext',label:/\\.html?$/.test(p)?'HTML':/\\.m?js|cjs$/.test(p)?'JavaScript':/\\.json$/.test(p)?'JSON':/\\.css$/.test(p)?'CSS':/\\.md$/.test(p)?'Markdown':'Plain Text'});\n const enc=s=>btoa(unescape(encodeURIComponent(s))),dec=b=>decodeURIComponent(escape(atob(b))),esc=s=>s.replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''})[c]);\n const openSearch=()=>{searchContainer.classList.replace('hidden','flex');searchInput.focus();searchInput.select();};\n const closeSearch=()=>{searchContainer.classList.replace('flex','hidden');if(S.search.oh)S.search.oh.classList.remove('ring-2','ring-orange-500');S.search.q='';searchInput.value='';S.jar.updateCode(S.jar.toString());S.search.m=[];S.search.c=-1;S.search.oh=null;};\n const fetchHandler = async (pathValue, sha) => {\n setStatus(); S.t = window.USER?.PAT||''; if (!S.t) return setStatus('Error: GitHub token not found.', true);\n const m = parsePath(pathValue); if (!m) return setStatus('Error: Invalid path. Use: owner/repo/path@branch', true);\n [,S.o,S.r,S.p,S.b] = m; const {lang,label} = detectLang(S.p); S.l = lang; langBadge.textContent = label;\n const ref = sha || S.b; const url = `https://api.github.com/repos/${S.o}/${S.r}/contents/${encodeURIComponent(S.p).replace(/%2F/g,'/')}?ref=${encodeURIComponent(ref)}`;\n setStatus('Fetching...'); S.jar.updateCode('Loading...');\n try {\n const r = await fetch(url,{headers:{'Authorization':`Bearer ${S.t}`,'Accept':'application/vnd.github.v3+json'}});\n const d = await r.json(); if (!r.ok) throw new Error(d.message || 'Failed to fetch file.'); if (d.type !== 'file') throw new Error('Path is not a file.');\n S.sha = d.sha; const content = dec(d.content || ''); S.jar.updateCode(content); pathInput.value = pathValue;\n setStatus(`Loaded ${sha?`@ ${sha.substring(0,7)}`:'latest'}.`);\n } catch (err) { setStatus(`Error: ${err.message}`, true); S.sha = null; S.jar.updateCode(`// Error: ${err.message}`); }\n };\n const commitHandler=async()=>{setStatus();const{o,r,p,b,sha,t,jar}=S;if(!t)return setStatus('Error: GitHub token not found.',true);if(!o||!sha)return setStatus('Error: Fetch a file first.',true);const msg=prompt(`Enter commit message for:\\n${p}`,`Update ${p.split('/').pop()||p}`);if(msg===null)return setStatus('Commit cancelled.');if(!msg.trim())return setStatus('Error: Commit message cannot be empty.',true);const newContent=jar.toString();const url=`https://api.github.com/repos/${o}/${r}/contents/${encodeURIComponent(p).replace(/%2F/g,'/')}`;setStatus('Committing...');setLoading(commitBtn,true);try{const res=await fetch(url,{method:'PUT',headers:{'Authorization':`Bearer ${t}`,'Accept':'application/vnd.github.v3+json','Content-Type':'application/json'},body:JSON.stringify({message:msg.trim(),content:enc(newContent),sha,branch:b})});const data=await res.json();if(!res.ok)throw new Error(data.message||'Failed to commit.');S.sha=data.content.sha;setStatus('Committed successfully!')}catch(err){setStatus(`Error: ${err.message}`,true)}finally{setLoading(commitBtn,false)}};\n const init = async () => {\n const { CodeJar: CJ } = await import('https://medv.io/codejar/codejar.js');\n const doHighlight=ed=>{const c=ed.textContent;if(S.search.q){ed.innerHTML=esc(c).replace(new RegExp(`(${S.search.q.replace(/[-/\\\\^$*+?.()|[\\]{}]/g,'\\\\$&')})`,'gi'),`<mark class=\"gh-search-match bg-yellow-200 rounded-sm\">$1</mark>`);S.search.m=[...ed.querySelectorAll('.gh-search-match')]}else if(window.hljs&&S.l&&hljs.getLanguage(S.l)){ed.innerHTML=hljs.highlight(c,{language:S.l,ignoreIllegals:true}).value}else{ed.textContent=c}};\n S.jar = CJ(fileEditorEl, doHighlight, { tab: ' ' });\n ghBackBtn.addEventListener('click', () => backBtn.click());\n commitBtn.addEventListener('click', commitHandler);\n copyBtn.addEventListener('click', () => navigator.clipboard.writeText(S.jar.toString()).then(()=>setStatus('Copied.')));\n searchBtn.addEventListener('click', openSearch);\n searchCloseBtn.addEventListener('click', closeSearch);\n };\n return { init, loadFile: fetchHandler };\n })();\n \n // --- BROWSER/EDITOR GLUE & INIT ---\n const init = async () => {\n await window.SUNE_GH_EDITOR.init();\n const cachedRepos = JSON.parse(localStorage.getItem(CACHE_KEY_B) || '[]');\n if (cachedRepos.length) cachedRepos.forEach(p => addRepoRow(p)); else addRepoRow('');\n sune.addEventListener('click', e => {\n const t = e.target;\n const browseBtn = t.closest('.browse-repo-btn'); if(browseBtn) return startRepoBrowse(browseBtn);\n const removeBtn = t.closest('.remove-repo-btn'); if(removeBtn) { removeBtn.closest('.repo-row').remove(); saveRepos(); if(repoList.childElementCount===0)addRepoRow(''); return; }\n if(t.closest('#addRepoBtn')) return addRepoRow('');\n if(t.closest('#backBtn')) { if(browserSubView==='editor')showBrowserSubView('history'); else if(browserSubView==='history')showBrowserSubView('tree'); else showView('list'); return; }\n const fileItem = t.closest('.file-item'); if(fileItem) { const {path,type}=fileItem.dataset; if(type==='tree')fetchAndRenderTree(fileItem.dataset.sha,path.split('/').pop()); else if(type==='blob')fetchHistory(path,fileItem); return; }\n const breadcrumbItem = t.closest('.breadcrumb-item:not([disabled])'); if(breadcrumbItem) { const i = parseInt(breadcrumbItem.dataset.index,10); pathHistory = pathHistory.slice(0,i+1); fetchAndRenderTree(pathHistory[i].sha); return; }\n const vContent = t.closest('.view-content-btn'); if(vContent) { const path = `${currentRepoInfo.owner}/${currentRepoInfo.repo}/${currentFilePath}@${currentRepoInfo.branch}`; window.SUNE_GH_EDITOR.loadFile(path, vContent.dataset.sha); showBrowserSubView('editor'); return; }\n if(t.closest('#commitLatestBtn')) { const path = `${currentRepoInfo.owner}/${currentRepoInfo.repo}/${currentFilePath}@${currentRepoInfo.branch}`; window.SUNE_GH_EDITOR.loadFile(path, null); showBrowserSubView('editor'); return; }\n });\n sune.addEventListener('input', e => { if(e.target.classList.contains('repo-path-input')) saveRepos(); });\n sune.addEventListener('keydown', e => { if(e.key==='Enter' && e.target.classList.contains('repo-path-input')) e.target.closest('.repo-row').querySelector('.browse-repo-btn')?.click(); });\n window.lucide?.createIcons();\n };\n init();\n})();\n</script>\n","extension_html":"<sune src='https://raw.githubusercontent.com/sune-org/store/refs/heads/main/sync.sune' private />"},"storage":{}}] |