From a5aacf8201cbf403dde72c729752ed71656035f6 Mon Sep 17 00:00:00 2001 From: multipleof4 Date: Thu, 19 Mar 2026 15:51:31 -0700 Subject: [PATCH] Feat: Extract Sune HTML processing logic --- src/sune-html.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/sune-html.js diff --git a/src/sune-html.js b/src/sune-html.js new file mode 100644 index 0000000..d15d56b --- /dev/null +++ b/src/sune-html.js @@ -0,0 +1,54 @@ +import { el } from './dom.js'; +import { esc } from './utils.js'; + +export 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; +}; + +export 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; +}; + +export const renderSuneHTML = async () => { + const SUNE = window.SUNE; + const h = await processSuneIncludes([SUNE.extension_html, SUNE.html].map(x => (x || '').trim()).join('\n')); + const 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)); +};