1// /src/containers/types/stickies/exporter.js 2// Creates a framework-agnostic snapshot of a stickies container: { html, css, js } 3// Also provides Preview + Full-screen helpers. 4// NOTE: This file is complete (your uploaded version was truncated). [1](https://thesmartcone-my.sharepoint.com/personal/jason_thesmartcone_com/Documents/Microsoft%20Copilot%20Chat%20Files/login.html) 5 6export function exportBundle(containerEl) { 7 const body = containerEl.querySelector(".shell-tb"); 8 const stickies = Array.from(body.querySelectorAll(":scope > .comp.sticky")); 9 10 const htmlChildren = stickies.map((n) => { 11 const w = n.offsetWidth || parseFloat(n.style.width) || 220; 12 const h = n.offsetHeight || parseFloat(n.style.height) || 180; 13 const l = n.offsetLeft ?? parseFloat(n.style.left) ?? 0; 14 const t = n.offsetTop ?? parseFloat(n.style.top) ?? 0; 15 16 const bg = getComputedStyle(n).backgroundColor || "#fef08a"; 17 const title = n.querySelector(".title-st")?.textContent || ""; 18 const text = n.querySelector(".body-st")?.textContent || ""; 19 const done = n.dataset.done === "true"; 20 const assignee = n.querySelector(".assignee-st")?.value || ""; 21 const due = n.querySelector(".date-st")?.value || ""; 22 23 return ` 24<div class="note${done ? " done" : ""}" style="left:${Math.round(l)}px;top:${Math.round(t)}px;width:${Math.round(w)}px;min-height:${Math.round(h)}px;background:${escapeAttr(bg)}"> 25 <div class="note-title">${escapeHTML(title)}</div> 26 <div class="note-body">${escapeHTML(text)}</div> 27 <div class="note-meta"> 28 ${assignee ? `<div class="note-assignee">ð¤ ${escapeHTML(assignee)}</div>` : ""} 29 ${due ? `<div class="note-due">ð ${escapeHTML(due)}</div>` : ""} 30 ${done ? `<div class="note-badge">DONE</div>` : ""} 31 </div> 32</div>`.trim(); 33 }).join("\n"); 34 35 const html = ` 36<div class="notes-board"> 37${htmlChildren} 38</div>`.trim(); 39 40 const css = ` 41:root { color-scheme: light; } 42body { margin:0; font-family:system-ui, -apple-system, Segoe UI, Roboto, sans-serif; } 43.notes-board{ 44 position:relative; 45 width:100%; 46 min-height:100vh; 47 background:#fafafa; 48 overflow:auto; 49} 50.note{ 51 position:absolute; 52 box-sizing:border-box; 53 border:1px solid rgba(0,0,0,.06); 54 border-radius:10px; 55 padding:10px; 56 color:#0f172a; 57 box-shadow:0 10px 25px rgba(0,0,0,.15), inset 0 1px 0 rgba(255,255,255,.4); 58 transform: rotate(-0.35deg); 59} 60.note.done{ opacity:.9; } 61.note-title{ 62 font:700 14px/1.2 system-ui, -apple-system, Segoe UI, Roboto, sans-serif; 63 margin-bottom:6px; 64} 65.note-body{ 66 font:13px/1.4 system-ui, -apple-system, Segoe UI, Roboto, sans-serif; 67 white-space:pre-wrap; 68 word-break:break-word; 69} 70.note-meta{ 71 margin-top:8px; 72 display:flex; 73 gap:10px; 74 align-items:center; 75 color:#334155; 76 font:600 11px system-ui, -apple-system, Segoe UI, Roboto, sans-serif; 77} 78.note-badge{ 79 margin-left:auto; 80 font:700 10px system-ui, -apple-system, Segoe UI, Roboto, sans-serif; 81 color:#10b981; 82} 83`.trim(); 84 85 const js = ``; 86 87 return { html, css, js }; 88} 89 90export function openPreviewModal(bundle, title = "Stickies Preview") { 91 const { html, css, js } = bundle ?? { html: "", css: "", js: "" }; 92 93 const back = document.createElement("div"); 94 back.style.cssText = 95 "position:fixed;inset:0;background:rgba(17,24,39,.68);z-index:9999;display:flex;align-items:center;justify-content:center;"; 96 97 const card = document.createElement("div"); 98 card.style.cssText = 99 "width:min(1200px,92vw);height:min(800px,86vh);background:#0b1220;border:1px solid #1f2937;border-radius:12px;overflow:hidden;box-shadow:0 25px 60px rgba(0,0,0,.35);display:grid;grid-template-rows:44px 1fr;"; 100 101 const bar = document.createElement("div"); 102 bar.style.cssText = 103 "display:flex;align-items:center;justify-content:space-between;padding:8px 10px;background:#0f172a;color:#e5e7eb;border-bottom:1px solid #1e293b;font:600 12px system-ui;"; 104 bar.textContent = title; 105 106 const actions = document.createElement("div"); 107 const btnOpen = Object.assign(document.createElement("button"), { textContent: "Open in Tab" }); 108 const btnClose = Object.assign(document.createElement("button"), { textContent: "Close" }); 109 [btnOpen, btnClose].forEach((b) => { 110 b.style.cssText = 111 "background:#111827;color:#e5e7eb;border:1px solid #374151;border-radius:7px;padding:6px 10px;cursor:pointer;font:600 12px system-ui;margin-left:6px;"; 112 }); 113 actions.append(btnOpen, btnClose); 114 bar.append(actions); 115 116 const iframe = document.createElement("iframe"); 117 iframe.style.cssText = "width:100%;height:100%;border:0;background:#fff"; 118 iframe.setAttribute("sandbox", "allow-scripts allow-modals allow-popups"); 119 120 card.append(bar, iframe); 121 back.appendChild(card); 122 document.body.appendChild(back); 123 124 const close = () => back.remove(); 125 btnClose.addEventListener("click", close); 126 back.addEventListener("click", (e) => { if (e.target === back) close(); }); 127 128 const doc = ` 129<!doctype html> 130<html> 131<head> 132<meta charset="utf-8"/> 133<meta name="viewport" content="width=device-width,initial-scale=1"/> 134<style>${css}</style> 135</head> 136<body> 137${html} 138<script>${js}</script> 139</body> 140</html>`; 141 142 iframe.srcdoc = doc; 143 144 btnOpen.addEventListener("click", () => { 145 const w = window.open("", "_blank"); 146 if (!w) return; 147 w.document.open(); 148 w.document.write(doc); 149 w.document.close(); 150 }); 151} 152 153export function openFullscreen(bundle) { 154 // For now, fullscreen uses the same modal but with a different title. 155 // (You can extend this later if you want a true fullscreen overlay.) 156 openPreviewModal(bundle, "Stickies Full Screen"); 157} 158 159function escapeHTML(s) { 160 return String(s ?? "").replace(/[&<>"']/g, (c) => ({ 161 "&": "&", 162 "<": "<", 163 ">": ">", 164 '"': """, 165 "'": "'", 166 })[c]); 167} 168 169function escapeAttr(s) { 170 // Keep it simple: remove quotes to avoid breaking style="" 171 return String(s ?? "").replace(/["']/g, ""); 172}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.