diff --git a/src/main.js b/src/main.js index 8f1407c..f36525f 100644 --- a/src/main.js +++ b/src/main.js @@ -28,8 +28,8 @@ if(!sunes.length){const def=SUNE.create({name:'Default'});SUNE.setActive(def.id) const state=window.state={messages:[],busy:false,controller:null,currentThreadId:null,abortRequested:false,attachments:[],stream:{rid:null,bubble:null,meta:null,text:'',done:false}} const getModelShort=m=>{const mm=m||SUNE.model||'';return mm.includes('/')?mm.split('/').pop():mm} const resolveSuneSrc=src=>{if(!src)return null;if(src.startsWith('gh://')){const path=src.substring(5),parts=path.split('/');if(parts.length<3)return null;const[owner,repo,...filePathParts]=parts;return`https://raw.githubusercontent.com/${owner}/${repo}/main/${filePathParts.join('/')}`}return src} -const processSuneIncludes=async(html,depth=0)=>{if(depth>5)return'';if(!html)return'';const c=document.createElement('div');if(c.setHTMLUnsafe)c.setHTMLUnsafe(html);else c.innerHTML=html;for(const n of[...c.querySelectorAll('sune')]){if(n.hasAttribute('src')){if(n.hasAttribute('private')&&depth>0){n.remove();continue}const s=n.getAttribute('src'),u=resolveSuneSrc(s);if(!u){n.replaceWith(document.createComment(` Invalid src: ${esc(s)} `));continue}try{const r=await fetch(u);if(!r.ok)throw new Error(`HTTP ${r.status}`);const d=await r.json(),o=Array.isArray(d)?d[0]:d,h=[o?.settings?.extension_html||'',o?.settings?.html||''].join('\n');const res=await processSuneIncludes(h,depth+1);if(c.setHTMLUnsafe){const tmp=document.createElement('div');tmp.setHTMLUnsafe(res);n.replaceWith(...tmp.childNodes)}else{n.replaceWith(document.createRange().createContextualFragment(res))}}catch(e){n.replaceWith(document.createComment(` Fetch failed: ${esc(u)} `))}}else{if(c.setHTMLUnsafe){const tmp=document.createElement('div');tmp.setHTMLUnsafe(n.innerHTML);n.replaceWith(...tmp.childNodes)}else{n.replaceWith(document.createRange().createContextualFragment(n.innerHTML))}}}return c.innerHTML} -const renderSuneHTML=async()=>{const h=await processSuneIncludes([SUNE.extension_html,SUNE.html].map(x=>(x||'').trim()).join('\n')),c=el.suneHtml;c.innerHTML='';const t=h.trim();c.classList.toggle('hidden',!t);if(t){if(c.setHTMLUnsafe){c.setHTMLUnsafe(h);[...c.querySelectorAll('script')].forEach(s=>{const ns=document.createElement('script');[...s.attributes].forEach(a=>ns.setAttribute(a.name,a.value));ns.textContent=s.textContent;s.replaceWith(ns)})}else{c.appendChild(document.createRange().createContextualFragment(h))}window.Alpine?.initTree(c)}} +const processSuneIncludes=async(html,depth=0)=>{if(depth>5)return'';if(!html)return'';const c=document.createElement('div');c.innerHTML=html;for(const n of[...c.querySelectorAll('sune')]){if(n.hasAttribute('src')){if(n.hasAttribute('private')&&depth>0){n.remove();continue}const s=n.getAttribute('src'),u=resolveSuneSrc(s);if(!u){n.replaceWith(document.createComment(` Invalid src: ${esc(s)} `));continue}try{const r=await fetch(u);if(!r.ok)throw new Error(`HTTP ${r.status}`);const d=await r.json(),o=Array.isArray(d)?d[0]:d,h=[o?.settings?.extension_html||'',o?.settings?.html||''].join('\n');n.replaceWith(document.createRange().createContextualFragment(await processSuneIncludes(h,depth+1)))}catch(e){n.replaceWith(document.createComment(` Fetch failed: ${esc(u)} `))}}else{n.replaceWith(document.createRange().createContextualFragment(n.innerHTML))}}return c.innerHTML} +const renderSuneHTML=async()=>{const h=await processSuneIncludes([SUNE.extension_html,SUNE.html].map(x=>(x||'').trim()).join('\n')),c=el.suneHtml;c.innerHTML='';const t=h.trim();c.classList.toggle('hidden',!t);t&&(c.appendChild(document.createRange().createContextualFragment(h)),window.Alpine?.initTree(c))} const reflectActiveSune=async()=>{const a=SUNE.active;el.suneBtnTop.title=`Settings — ${a.name}`;el.suneBtnTop.innerHTML=a.avatar?``:'✺';el.footer.classList.toggle('hidden',!!a.settings.hide_composer);await renderSuneHTML();icons()} const suneRow=a=>`
` const renderSidebar=window.renderSidebar=()=>{const list=[...SUNE.list].sort((a,b)=>(b.pinned-a.pinned));el.suneList.innerHTML=list.map(suneRow).join('');icons()} @@ -155,3 +155,4 @@ const getActiveHtmlParts=()=>!el.htmlEditor.classList.contains('hidden')?[el.htm $(el.copyHTML).on('click',async()=>{try{await navigator.clipboard.writeText(getActiveHtmlParts()[0].textContent||'')}catch{}}) $(el.pasteHTML).on('click',async()=>{try{const t=await navigator.clipboard.readText();const[editor,jar]=getActiveHtmlParts();if(jar&&jar.updateCode)jar.updateCode(t);else if(editor)editor.textContent=t}catch{}}) Object.assign(window,{icons,haptic,clamp,num,int,gid,esc,positionPopover,sid,fmtSize,asDataURL,b64,makeSune,getModelShort,resolveSuneSrc,processSuneIncludes,renderSuneHTML,reflectActiveSune,suneRow,enhanceCodeBlocks,getSuneLabel,_createMessageRow,msgRow,partsToText,addSuneBubbleStreaming,clearChat,payloadWithSampling,setBtnStop,setBtnSend,localDemoReply,titleFrom,serializeThreadName,deserializeThreadName,ensureThreadOnFirstUser,generateTitleWithAI,threadRow,renderThreads,hideThreadPopover,showThreadPopover,hideSunePopover,showSunePopover,updateAttachBadge,toAttach,ensureJars,openSettings,closeSettings,showTab,dl,ts,kbUpdate,kbBind,activeMeta,init,showHtmlTab,showAccountTab,openAccountSettings,closeAccountSettings,getBubbleById,syncActiveThread,syncWhileBusy,onForeground,getActiveHtmlParts,imgToWebp,cacheStore,ghApi,parseGhUrl,pullThreads}); +