PageSourceSearch

https://smalldocs.org/public/sdocs-html-components.js?v=0ef0401827

js smalldocs.org collected 2026-09-29 16:36:37 UTC 25,087 bytes, 633 lines download raw bytes

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.