1// sdocs-html-components.js - canonical runnable HTML component reader. 2// 3// A fenced `sdoc-app` block contains one complete HTML document. The source 4// runs in its own sandboxed iframe, both inline and in the fullscreen gallery. 5// The iframe deliberately has no same-origin capability, so the component is 6// a standalone browser context rather than another part of the reader DOM. 7(function (exports) { 8 'use strict'; 9 10 var EXPAND_SVG = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>'; 11 var PREVIOUS_SVG = '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 18-6-6 6-6"/></svg>'; 12 var NEXT_SVG = '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 18 6-6-6-6"/></svg>'; 13 var CLOSE_SVG = '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg>'; 14 var SANDBOX = 'allow-scripts allow-forms allow-modals allow-downloads allow-popups'; 15 var READY_TIMEOUT_MS = 15000; 16 var DESIGN_TOKEN_SOURCES = { 17 '--sdoc-app-background': ['--md-bg', '--sdocs-background'], 18 '--sdoc-app-surface': ['--md-code-bg', '--md-block-bg', '--sdocs-code-background'], 19 '--sdoc-app-color': ['--md-color', '--sdocs-text-color'], 20 '--sdoc-app-heading-color': ['--md-h-color', '--md-color', '--sdocs-text-color'], 21 '--sdoc-app-muted-color': ['--md-muted', '--sdocs-muted-color', '--text-2'], 22 '--sdoc-app-accent-color': ['--md-link-color', '--sdocs-accent'], 23 '--sdoc-app-border-color': ['--sdocs-border-color', '--md-hr-border', '--border'], 24 '--sdoc-app-font-family': ['--md-font-family', '--sdocs-font-family'], 25 '--sdoc-app-heading-font-family': ['--md-h-font-family', '--sdocs-heading-font-family', '--md-font-family'], 26 '--sdoc-app-code-font-family': ['--md-code-font', '--sdocs-code-font-family'], 27 '--sdoc-app-font-size': ['--md-base-size', '--sdocs-font-size'], 28 '--sdoc-app-line-height': ['--md-line-height', '--sdocs-line-height'], 29 '--sdoc-app-heading-scale': ['--md-h-scale', '--sdocs-heading-scale'], 30 '--sdoc-app-h1-size': ['--md-h1-size', '--sdocs-h1-size'], 31 '--sdoc-app-h2-size': ['--md-h2-size', '--sdocs-h2-size'], 32 '--sdoc-app-h3-size': ['--md-h3-size', '--sdocs-h3-size'], 33 '--sdoc-app-h1-weight': ['--md-h1-weight', '--sdocs-h1-weight'], 34 '--sdoc-app-h2-weight': ['--md-h2-weight', '--sdocs-h2-weight'], 35 '--sdoc-app-h3-weight': ['--md-h3-weight', '--sdocs-h3-weight'], 36 '--sdoc-app-radius': ['--sdocs-radius', '--radius-md'], 37 '--sdoc-app-block-spacing': ['--md-block-gap', '--sdocs-paragraph-spacing'], 38 '--sdoc-app-padding': ['--sdocs-app-padding'], 39 }; 40 var DESIGN_DEFAULTS = { 41 '--sdoc-app-background': '#ffffff', 42 '--sdoc-app-surface': '#f4f1ed', 43 '--sdoc-app-color': '#1c1917', 44 '--sdoc-app-heading-color': '#1c1917', 45 '--sdoc-app-muted-color': '#6b6560', 46 '--sdoc-app-accent-color': '#2563eb', 47 '--sdoc-app-border-color': '#ded9d3', 48 '--sdoc-app-font-family': 'Inter, ui-sans-serif, system-ui, sans-serif', 49 '--sdoc-app-heading-font-family': 'Inter, ui-sans-serif, system-ui, sans-serif', 50 '--sdoc-app-code-font-family': 'ui-monospace, Menlo, monospace', 51 '--sdoc-app-font-size': '16px', 52 '--sdoc-app-line-height': '1.6', 53 '--sdoc-app-heading-scale': '1', 54 '--sdoc-app-h1-size': '2.1em', 55 '--sdoc-app-h2-size': '1.55em', 56 '--sdoc-app-h3-size': '1.2em', 57 '--sdoc-app-h1-weight': '700', 58 '--sdoc-app-h2-weight': '600', 59 '--sdoc-app-h3-weight': '600', 60 '--sdoc-app-radius': '8px', 61 '--sdoc-app-block-spacing': '1.1em',
62 '--sdoc-app-padding': 'clamp(16px, 4vw, 32px)', 63 }; 64 65 function deferred() { 66 var resolve; 67 var promise = new Promise(function (yes) { resolve = yes; }); 68 return { promise: promise, resolve: resolve }; 69 } 70 71 function randomToken(win) { 72 if (win.crypto && typeof win.crypto.randomUUID === 'function') { 73 return win.crypto.randomUUID(); 74 } 75 var bytes = new Uint32Array(4); 76 win.crypto.getRandomValues(bytes); 77 return Array.prototype.map.call(bytes, function (value) { 78 return value.toString(36); 79 }).join(''); 80 } 81 82 function titleFromSource(win, source, index) { 83 try { 84 var parsed = new win.DOMParser().parseFromString(String(source || ''), 'text/html'); 85 var title = (parsed.title || '').replace(/\s+/g, ' ').trim(); 86 if (title) return title.slice(0, 160); 87 var heading = parsed.querySelector('h1'); 88 if (heading && heading.textContent.trim()) { 89 return heading.textContent.replace(/\s+/g, ' ').trim().slice(0, 160); 90 } 91 } catch (_) {} 92 return 'Interactive component ' + (index + 1); 93 } 94 95 function createButton(doc, className, label) { 96 var button = doc.createElement('button'); 97 button.type = 'button'; 98 button.className = className; 99 button.setAttribute('aria-label', label); 100 button.title = label; 101 return button; 102 } 103 104 function firstStyleValue(style, names, fallback) { 105 for (var i = 0; i < names.length; i += 1) { 106 var value = style.getPropertyValue(names[i]).trim(); 107 if (value) return value; 108 } 109 return fallback; 110 } 111 112 function colorLuminance(win, value) { 113 try { 114 if (win.CSS && typeof win.CSS.supports === 'function' 115 && !win.CSS.supports('color', String(value || ''))) return null; 116 var canvas = win.document.createElement('canvas'); 117 canvas.width = 1; 118 canvas.height = 1; 119 var context = canvas.getContext('2d', { willReadFrequently: true }); 120 if (!context) return null; 121 context.clearRect(0, 0, 1, 1); 122 context.fillStyle = '#000000'; 123 context.fillStyle = String(value || ''); 124 context.fillRect(0, 0, 1, 1); 125 var pixel = context.getImageData(0, 0, 1, 1).data; 126 if (!pixel[3]) return null; 127 var alpha = pixel[3] / 255; 128 var red = pixel[0] * alpha + 255 * (1 - alpha); 129 var green = pixel[1] * alpha + 255 * (1 - alpha); 130 var blue = pixel[2] * alpha + 255 * (1 - alpha); 131 return red * 0.2126 + green * 0.7152 + blue * 0.0722; 132 } catch (_) { 133 return null; 134 } 135 } 136 137 function colorScheme(win, source, style, background) { 138 var luminance = colorLuminance(win, background); 139 if (luminance !== null) return luminance < 128 ? 'dark' : 'light'; 140 var themed = source && source.closest ? source.closest('[data-theme]') : null; 141 var named = themed && themed.getAttribute('data-theme'); 142 if (named === 'dark' || named === 'light') return named; 143 if (style.colorScheme === 'dark') return 'dark'; 144 return 'light'; 145 } 146 147 function readDesignTokens(win, source) { 148 var result = {}; 149 var style = source && win.getComputedStyle ? win.getComputedStyle(source) : null; 150 Object.keys(DESIGN_TOKEN_SOURCES).forEach(function (name) { 151 result[name] = style 152 ? firstStyleValue(style, DESIGN_TOKEN_SOURCES[name], DESIGN_DEFAULTS[name]) 153 : DESIGN_DEFAULTS[name]; 154 }); 155 if (style) { 156 if (!firstStyleValue(style, DESIGN_TOKEN_SOURCES['--sdoc-app-font-family'], '')) { 157 result['--sdoc-app-font-family'] = style.fontFamily || DESIGN_DEFAULTS['--sdoc-app-font-family']; 158 } 159 if (!firstStyleValue(style, DESIGN_TOKEN_SOURCES['--sdoc-app-font-size'], '')) { 160 result['--sdoc-app-font-size'] = style.fontSize || DESIGN_DEFAULTS['--sdoc-app-font-size']; 161 } 162 if (!firstStyleValue(style, DESIGN_TOKEN_SOURCES['--sdoc-app-line-height'], '')) { 163 result['--sdoc-app-line-height'] = style.lineHeight || DESIGN_DEFAULTS['--sdoc-app-line-height']; 164 } 165 } 166 result['--sdoc-app-color-scheme'] = colorScheme( 167 win, 168 source, 169 style || {}, 170 result['--sdoc-app-background'] 171 ); 172 return result; 173 } 174 175 function create(options) { 176 options = options || {}; 177 var win = options.window || window; 178 var doc = options.document || win.document; 179 var entries = []; 180 var framesByToken = new Map();
181 var overlay = null; 182 var destroyed = false; 183 var styleRoot = null; 184 var styleObserver = null; 185 var styleRefreshFrame = 0; 186 var colorSchemeMedia = win.matchMedia ? win.matchMedia('(prefers-color-scheme: dark)') : null; 187 188 function setHTML(node, html) { 189 if (options.setHTML) options.setHTML(node, String(html)); 190 else node.innerHTML = html; 191 } 192 193 function controls(name) { 194 var configured = typeof options.controls === 'function' ? options.controls() : options.controls; 195 return !configured || configured[name] !== false; 196 } 197 198 function button(className, label, icon) { 199 var result = createButton(doc, className, label); 200 setHTML(result, icon); 201 return result; 202 } 203 204 function isActive() { 205 return !destroyed && (!options.isActive || options.isActive()); 206 } 207 208 function runnerUrl(token) { 209 var configured = typeof options.runnerUrl === 'function' 210 ? options.runnerUrl(token) 211 : options.runnerUrl; 212 var url = new URL(configured || '/sdoc-app-runner', win.location.href); 213 url.searchParams.set('token', token); 214 return url.href; 215 } 216 217 function designSource() { 218 var configured = typeof options.styleSource === 'function' 219 ? options.styleSource() 220 : options.styleSource; 221 return configured || styleRoot || doc.documentElement; 222 } 223 224 function currentDesign() { 225 if (typeof options.designTokens === 'function') return options.designTokens(designSource()); 226 if (options.designTokens) return options.designTokens; 227 return readDesignTokens(win, designSource()); 228 } 229 230 function sendDesign(record) { 231 if (!record || !record.sent || !record.frame.contentWindow) return; 232 record.frame.contentWindow.postMessage({ 233 type: 'sdocs-app-design', 234 token: record.token, 235 design: currentDesign(), 236 }, '*'); 237 } 238 239 function refreshDesign() { 240 styleRefreshFrame = 0; 241 if (!isActive()) return; 242 framesByToken.forEach(sendDesign); 243 } 244 245 function scheduleDesignRefresh() { 246 if (styleRefreshFrame || destroyed) return; 247 styleRefreshFrame = win.requestAnimationFrame(refreshDesign); 248 } 249 250 function watchDesign(source) { 251 if (styleObserver) styleObserver.disconnect(); 252 if (!win.MutationObserver || !source) return; 253 styleObserver = new win.MutationObserver(scheduleDesignRefresh); 254 var node = source; 255 while (node && node.nodeType === 1) { 256 styleObserver.observe(node, { 257 attributes: true, 258 attributeFilter: ['class', 'style', 'data-theme'], 259 }); 260 node = node.parentElement; 261 } 262 } 263 264 win.addEventListener('resize', scheduleDesignRefresh); 265 if (colorSchemeMedia && colorSchemeMedia.addEventListener) { 266 colorSchemeMedia.addEventListener('change', scheduleDesignRefresh); 267 } 268 269 function removeFrame(frame) { 270 if (!frame) return; 271 var token = frame.dataset.sdocsAppToken; 272 if (token) framesByToken.delete(token); 273 frame.remove(); 274 } 275 276 function settleEntry(entry, status) { 277 if (!entry || entry.settled) return; 278 entry.settled = true; 279 win.clearTimeout(entry.readyTimer); 280 entry.ready.resolve({ status: status, index: entry.index }); 281 } 282 283 function showFailure(entry, message) { 284 if (!entry || !entry.host) return; 285 if (entry.status) { 286 entry.status.textContent = message; 287 entry.status.hidden = false; 288 } 289 if (!entry.failure) { 290 var details = doc.createElement('details'); 291 details.className = 'sdoc-app-failure-source'; 292 var summary = doc.createElement('summary'); 293 summary.textContent = 'View component source'; 294 var pre = doc.createElement('pre'); 295 var code = doc.createElement('code'); 296 code.className = 'language-html'; 297 code.textContent = entry.source; 298 pre.appendChild(code); 299 details.append(summary, pre); 300 entry.host.appendChild(details); 301 entry.failure = details; 302 } 303 settleEntry(entry, 'error'); 304 } 305 306 function createFrame(entry, mode) { 307 var token = randomToken(win); 308 var frame = doc.createElement('iframe'); 309 frame.className = 'sdoc-app-frame sdoc-app-frame-' + mode; 310 frame.dataset.sdocsAppToken = token; 311 frame.dataset.sdocsAppIndex = String(entry.index); 312 frame.title = entry.title; 313 frame.setAttribute('sandbox', SANDBOX); 314 frame.setAttribute('allow', 'clipboard-read; clipboard-write; fullscreen'); 315 frame.setAttribute('loading', 'eager'); 316 frame.src = runnerUrl(token); 317 framesByToken.set(token, { 318 token: token, 319 frame: frame, 320 entry: entry, 321 mode: mode, 322 sent: false, 323 lastInlineHeight: 480, 324 }); 325 frame.addEventListener('error', function () { 326 showFailure(entry, 'This component could not start.'); 327 }, { once: true }); 328 return frame; 329 } 330 331 function receive(event) { 332 var message = event.data; 333 if (!message || typeof message !== 'object' || !message.token) return; 334 var record = framesByToken.get(message.token); 335 if (!record || event.source !== record.frame.contentWindow || !isActive()) return; 336 if (message.type === 'sdocs-app-ready') { 337 if (record.sent) return; 338 record.sent = true; 339 record.frame.contentWindow.postMessage({ 340 type: 'sdocs-app-load', 341 token: record.token, 342 source: record.entry.source, 343 design: currentDesign(), 344 }, '*'); 345 return; 346 } 347 if (message.type === 'sdocs-app-size' && record.mode === 'inline') { 348 var height = Math.round(Number(message.height)); 349 if (!Number.isFinite(height)) return; 350 height = Math.max(0, height); 351 record.lastInlineHeight = height; 352 record.frame.style.height = height + 'px'; 353 return; 354 } 355 if (message.type === 'sdocs-app-mounted' && record.entry.status) { 356 record.entry.status.hidden = true; 357 sendDesign(record); 358 settleEntry(record.entry, 'mounted'); 359 } 360 } 361 362 win.addEventListener('message', receive); 363 364 function clearInline(status) {
365 entries.forEach(function (entry) { 366 settleEntry(entry, status || 'replaced'); 367 if (entry.frame) removeFrame(entry.frame); 368 }); 369 entries = []; 370 } 371 372 function cleanupOverlay(record) { 373 if (!record || record.cleaned) return; 374 record.cleaned = true; 375 win.removeEventListener('keydown', record.onKeydown); 376 restoreInlineFrame(record.entry); 377 if (overlay === record) overlay = null; 378 } 379 380 function frameRecord(entry) { 381 return entry && entry.frame 382 ? framesByToken.get(entry.frame.dataset.sdocsAppToken) 383 : null; 384 } 385 386 function restoreInlineFrame(entry) { 387 if (!entry || !entry.frame || !entry.host || !entry.host.isConnected) return; 388 var record = frameRecord(entry); 389 if (record) record.mode = 'inline'; 390 if (typeof entry.frame.hidePopover === 'function') { 391 try { entry.frame.hidePopover(); } catch (_) {} 392 } 393 entry.frame.removeAttribute('popover'); 394 entry.frame.classList.remove('sdoc-app-frame-fullscreen'); 395 entry.frame.classList.add('sdoc-app-frame-inline'); 396 entry.frame.style.height = ((record && record.lastInlineHeight) || 480) + 'px'; 397 entry.host.classList.remove('sdoc-app-expanded'); 398 if (entry.placeholder) entry.placeholder.hidden = true; 399 } 400 401 function moveFrameToOverlay(entry) { 402 var record = frameRecord(entry); 403 if (record) record.mode = 'fullscreen'; 404 entry.frame.classList.remove('sdoc-app-frame-inline'); 405 entry.frame.classList.add('sdoc-app-frame-fullscreen'); 406 entry.frame.style.height = ''; 407 if (typeof entry.frame.showPopover === 'function') { 408 entry.frame.setAttribute('popover', 'manual'); 409 entry.frame.showPopover(); 410 } 411 entry.host.classList.add('sdoc-app-expanded'); 412 if (entry.placeholder) entry.placeholder.hidden = false; 413 } 414 415 function defaultMountSurface(surface, setup) { 416 var previousBodyOverflow = doc.body.style.overflow; 417 var previousRootOverflow = doc.documentElement.style.overflow; 418 doc.body.appendChild(surface); 419 doc.body.classList.add('sdoc-app-focus-open'); 420 doc.documentElement.style.overflow = 'hidden'; 421 return { 422 close: function (reason) { 423 setup.beforeClose(reason || 'user'); 424 surface.remove(); 425 doc.body.classList.remove('sdoc-app-focus-open'); 426 doc.body.style.overflow = previousBodyOverflow; 427 doc.documentElement.style.overflow = previousRootOverflow; 428 if (setup.returnFocus && setup.returnFocus.isConnected) setup.returnFocus.focus(); 429 }, 430 }; 431 } 432 433 function renderOverlayEntry(record, index) { 434 if (!record || !entries.length) return; 435 var total = entries.length; 436 var nextIndex = Math.max(0, Math.min(total - 1, index)); 437 var entry = entries[nextIndex]; 438 restoreInlineFrame(record.entry); 439 record.index = nextIndex; 440 record.entry = entry; 441 record.title.textContent = entry.title; 442 record.counter.textContent = (nextIndex + 1) + ' / ' + total; 443 record.previous.disabled = nextIndex === 0; 444 record.next.disabled = nextIndex === total - 1; 445 record.previous.hidden = total < 2; 446 record.next.hidden = total < 2; 447 record.counter.hidden = total < 2; 448 moveFrameToOverlay(entry); 449 } 450 451 function closeFullscreen(reason) { 452 var record = overlay; 453 if (!record) return; 454 if (record.lease && typeof record.lease.close === 'function') { 455 record.lease.close(reason || 'user'); 456 } else { 457 cleanupOverlay(record); 458 record.surface.remove(); 459 } 460 } 461 462 function openFullscreen(index, returnFocus) { 463 if (!entries.length || !isActive()) return; 464 closeFullscreen('superseded'); 465 466 var surface = doc.createElement('div'); 467 surface.className = 'sdoc-app-focus'; 468 surface.dataset.sdocsSdkVersion = options.sdkVersion || 'app'; 469 surface.setAttribute('role', 'dialog'); 470 surface.setAttribute('aria-modal', 'true'); 471 surface.setAttribute('aria-label', 'Interactive components'); 472 var bar = doc.createElement('div'); 473 bar.className = 'sdoc-app-focus-bar'; 474 var brand = doc.createElement('span'); 475 brand.className = 'sdoc-app-focus-brand'; 476 brand.textContent = 'SmallDocs'; 477 var title = doc.createElement('span'); 478 title.className = 'sdoc-app-focus-title'; 479 var actions = doc.createElement('div'); 480 actions.className = 'sdoc-app-focus-actions'; 481 var previous = button('sdoc-app-focus-button', 'Previous component', PREVIOUS_SVG); 482 var counter = doc.createElement('span'); 483 counter.className = 'sdoc-app-focus-counter'; 484 var next = button('sdoc-app-focus-button', 'Next component', NEXT_SVG); 485 var close = button('sdoc-app-focus-button', 'Close fullscreen', CLOSE_SVG); 486 var stage = doc.createElement('div'); 487 stage.className = 'sdoc-app-focus-stage'; 488 actions.append(previous, counter, next, close); 489 bar.append(brand, title, actions); 490 surface.append(bar, stage); 491 492 var record = { 493 surface: surface, 494 stage: stage, 495 title: title, 496 previous: previous, 497 counter: counter, 498 next: next, 499 close: close, 500 entry: null, 501 index: 0, 502 returnFocus: returnFocus || doc.activeElement, 503 lease: null,
504 cleaned: false, 505 onKeydown: null, 506 }; 507 overlay = record; 508 previous.addEventListener('click', function () { renderOverlayEntry(record, record.index - 1); }); 509 next.addEventListener('click', function () { renderOverlayEntry(record, record.index + 1); }); 510 close.addEventListener('click', function () { closeFullscreen('user'); }); 511 record.onKeydown = function (event) { 512 if (overlay !== record) return; 513 if (event.key === 'ArrowLeft' && !record.previous.disabled) { 514 event.preventDefault(); 515 renderOverlayEntry(record, record.index - 1); 516 } else if (event.key === 'ArrowRight' && !record.next.disabled) { 517 event.preventDefault(); 518 renderOverlayEntry(record, record.index + 1); 519 } else if (event.key === 'Escape' && !options.mountSurface) { 520 event.preventDefault(); 521 closeFullscreen('user'); 522 } 523 }; 524 win.addEventListener('keydown', record.onKeydown); 525 526 var mount = options.mountSurface || defaultMountSurface; 527 record.lease = mount(surface, { 528 initialFocus: close, 529 returnFocus: record.returnFocus, 530 beforeClose: function () { cleanupOverlay(record); }, 531 }); 532 renderOverlayEntry(record, index || 0); 533 close.focus(); 534 } 535 536 function mountInline(code, index) { 537 var pre = code.closest('pre'); 538 if (!pre) return null; 539 var target = pre.closest('.pre-wrapper') || pre; 540 var source = code.textContent || ''; 541 var entry = { 542 index: index, 543 source: source, 544 title: titleFromSource(win, source, index), 545 frame: null, 546 status: null, 547 host: null, 548 placeholder: null, 549 failure: null, 550 settled: false, 551 ready: deferred(), 552 readyTimer: null, 553 }; 554 var host = doc.createElement('section'); 555 host.className = 'sdoc-app'; 556 host.dataset.sdocsAppIndex = String(index); 557 host.dataset.sdocsSdkVersion = options.sdkVersion || 'app'; 558 var bar = doc.createElement('div'); 559 bar.className = 'sdoc-app-bar'; 560 var title = doc.createElement('span'); 561 title.className = 'sdoc-app-title'; 562 title.textContent = entry.title; 563 var expand = null; 564 if (controls('fullscreen')) { 565 expand = button('sdoc-app-expand', 'Open ' + entry.title + ' in fullscreen', EXPAND_SVG); 566 expand.addEventListener('click', function () { openFullscreen(entry.index, expand); }); 567 } 568 var status = doc.createElement('span'); 569 status.className = 'sdoc-app-status'; 570 status.textContent = 'Loading component...'; 571 entry.status = status; 572 entry.host = host; 573 var placeholder = doc.createElement('div'); 574 placeholder.className = 'sdoc-app-placeholder'; 575 placeholder.textContent = 'This component is open in fullscreen.'; 576 placeholder.hidden = true; 577 entry.placeholder = placeholder; 578 bar.appendChild(title); 579 if (expand) bar.appendChild(expand); 580 entry.frame = createFrame(entry, 'inline'); 581 host.append(bar, entry.frame, status, placeholder); 582 target.replaceWith(host); 583 entry.readyTimer = win.setTimeout(function () { 584 showFailure(entry, 'This component did not finish starting.'); 585 }, READY_TIMEOUT_MS); 586 return entry; 587 } 588 589 function process(root) { 590 if (!isActive() || !root) return { apps: [], ready: Promise.resolve([]) }; 591 closeFullscreen('rerender'); 592 clearInline('replaced'); 593 styleRoot = root; 594 watchDesign(designSource()); 595 var blocks = Array.from(root.querySelectorAll('pre > code.language-sdoc-app')); 596 entries = blocks.map(mountInline).filter(Boolean); 597 return { 598 apps: entries.slice(), 599 ready: Promise.all(entries.map(function (entry) { return entry.ready.promise; })), 600 }; 601 } 602 603 function destroy(reason) { 604 if (destroyed) return; 605 closeFullscreen(reason || 'destroy'); 606 clearInline(reason || 'destroyed'); 607 destroyed = true; 608 if (styleObserver) styleObserver.disconnect(); 609 if (styleRefreshFrame) win.cancelAnimationFrame(styleRefreshFrame); 610 win.removeEventListener('resize', scheduleDesignRefresh); 611 if (colorSchemeMedia && colorSchemeMedia.removeEventListener) { 612 colorSchemeMedia.removeEventListener('change', scheduleDesignRefresh); 613 } 614 win.removeEventListener('message', receive);
615 framesByToken.forEach(function (record) { record.frame.remove(); }); 616 framesByToken.clear(); 617 } 618 619 return { 620 process: process, 621 open: openFullscreen, 622 close: closeFullscreen, 623 destroy: destroy, 624 entries: function () { return entries.slice(); }, 625 }; 626 } 627 628 exports.SANDBOX = SANDBOX; 629 exports.DESIGN_DEFAULTS = DESIGN_DEFAULTS; 630 exports.readDesignTokens = readDesignTokens; 631 exports.titleFromSource = titleFromSource; 632 exports.create = create; 633})(typeof module !== 'undefined' && module.exports ? module.exports : (window.SDocHtmlComponents = {}));
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.