@hyperframes/core 0.2.2 → 0.2.3-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"htmlBundler.d.ts","sourceRoot":"","sources":["../../src/compiler/htmlBundler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAe,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAgTvE,MAAM,WAAW,aAAa;IAC5B,oGAAoG;IACpG,kBAAkB,CAAC,EAAE,mBAAmB,CAAC;CAC1C;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,MAAM,CAAC,CA+PjB"}
1
+ {"version":3,"file":"htmlBundler.d.ts","sourceRoot":"","sources":["../../src/compiler/htmlBundler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAe,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AA+TvE,MAAM,WAAW,aAAa;IAC5B,oGAAoG;IACpG,kBAAkB,CAAC,EAAE,mBAAmB,CAAC;CAC1C;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,MAAM,CAAC,CAuSjB"}
@@ -1,10 +1,22 @@
1
1
  import { readFileSync, existsSync } from "fs";
2
2
  import { join, resolve, isAbsolute, sep } from "path";
3
- import * as cheerio from "cheerio";
3
+ import { parseHTML } from "linkedom";
4
4
  import { transformSync } from "esbuild";
5
5
  import { compileHtml } from "./htmlCompiler";
6
6
  import { rewriteAssetPaths, rewriteCssAssetUrls } from "./rewriteSubCompPaths";
7
7
  import { validateHyperframeHtmlContract } from "./staticGuard";
8
+ /**
9
+ * Parse an HTML string into a document. Fragments (without a full document
10
+ * structure) are wrapped in `<!DOCTYPE html><html><head></head><body>…</body></html>`
11
+ * so that linkedom places the content inside `document.body`.
12
+ */
13
+ function parseHTMLContent(html) {
14
+ const trimmed = html.trimStart().toLowerCase();
15
+ if (trimmed.startsWith("<!doctype") || trimmed.startsWith("<html")) {
16
+ return parseHTML(html).document;
17
+ }
18
+ return parseHTML(`<!DOCTYPE html><html><head></head><body>${html}</body></html>`).document;
19
+ }
8
20
  /** Resolve a relative path within projectDir, rejecting traversal outside it. */
9
21
  function safePath(projectDir, relativePath) {
10
22
  const resolved = resolve(projectDir, relativePath);
@@ -183,23 +195,25 @@ function rewriteCssUrlsWithInlinedAssets(cssText, projectDir) {
183
195
  return `url(${quote || ""}${maybeInlined}${quote || ""})`;
184
196
  });
185
197
  }
186
- function enforceCompositionPixelSizing($) {
187
- const compositionEls = $("[data-composition-id][data-width][data-height]").toArray();
198
+ function enforceCompositionPixelSizing(document) {
199
+ const compositionEls = [
200
+ ...document.querySelectorAll("[data-composition-id][data-width][data-height]"),
201
+ ];
188
202
  if (compositionEls.length === 0)
189
203
  return;
190
204
  const sizeMap = new Map();
191
205
  for (const el of compositionEls) {
192
- const compId = $(el).attr("data-composition-id");
193
- const w = Number($(el).attr("data-width"));
194
- const h = Number($(el).attr("data-height"));
206
+ const compId = el.getAttribute("data-composition-id");
207
+ const w = Number(el.getAttribute("data-width"));
208
+ const h = Number(el.getAttribute("data-height"));
195
209
  if (compId && Number.isFinite(w) && Number.isFinite(h) && w > 0 && h > 0) {
196
210
  sizeMap.set(compId, { w, h });
197
211
  }
198
212
  }
199
213
  if (sizeMap.size === 0)
200
214
  return;
201
- $("style").each((_, styleEl) => {
202
- let css = $(styleEl).html() || "";
215
+ for (const styleEl of document.querySelectorAll("style")) {
216
+ let css = styleEl.textContent || "";
203
217
  let modified = false;
204
218
  for (const [compId, { w, h }] of sizeMap) {
205
219
  const escaped = compId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -214,53 +228,53 @@ function enforceCompositionPixelSizing($) {
214
228
  });
215
229
  }
216
230
  if (modified)
217
- $(styleEl).text(css);
218
- });
231
+ styleEl.textContent = css;
232
+ }
219
233
  }
220
- function autoHealMissingCompositionIds($) {
234
+ function autoHealMissingCompositionIds(document) {
221
235
  const compositionIdRe = /data-composition-id=["']([^"']+)["']/gi;
222
236
  const referencedIds = new Set();
223
- $("style, script").each((_, el) => {
224
- const text = ($(el).html() || "").trim();
237
+ for (const el of document.querySelectorAll("style, script")) {
238
+ const text = (el.textContent || "").trim();
225
239
  if (!text)
226
- return;
240
+ continue;
227
241
  let match;
228
242
  while ((match = compositionIdRe.exec(text)) !== null) {
229
243
  const compId = (match[1] || "").trim();
230
244
  if (compId)
231
245
  referencedIds.add(compId);
232
246
  }
233
- });
247
+ }
234
248
  if (referencedIds.size === 0)
235
249
  return;
236
250
  const existingIds = new Set();
237
- $("[data-composition-id]").each((_, el) => {
238
- const id = ($(el).attr("data-composition-id") || "").trim();
251
+ for (const el of document.querySelectorAll("[data-composition-id]")) {
252
+ const id = (el.getAttribute("data-composition-id") || "").trim();
239
253
  if (id)
240
254
  existingIds.add(id);
241
- });
255
+ }
242
256
  for (const compId of referencedIds) {
243
257
  if (compId === "root" || existingIds.has(compId))
244
258
  continue;
245
259
  const candidates = [`${compId}-layer`, `${compId}-comp`, compId];
246
260
  for (const targetId of candidates) {
247
- const match = $(`#${targetId}`).first();
248
- if (match.length > 0 && !match.attr("data-composition-id")) {
249
- match.attr("data-composition-id", compId);
261
+ const found = document.getElementById(targetId);
262
+ if (found && !found.getAttribute("data-composition-id")) {
263
+ found.setAttribute("data-composition-id", compId);
250
264
  break;
251
265
  }
252
266
  }
253
267
  }
254
268
  }
255
- function coalesceHeadStylesAndBodyScripts($) {
256
- const headStyleEls = $("head style").toArray();
269
+ function coalesceHeadStylesAndBodyScripts(document) {
270
+ const headStyleEls = [...document.querySelectorAll("head style")];
257
271
  if (headStyleEls.length > 1) {
258
272
  const importRe = /@import\s+url\([^)]*\)\s*;|@import\s+["'][^"']+["']\s*;/gi;
259
273
  const imports = [];
260
274
  const cssParts = [];
261
275
  const seenImports = new Set();
262
276
  for (const el of headStyleEls) {
263
- const raw = ($(el).html() || "").trim();
277
+ const raw = (el.textContent || "").trim();
264
278
  if (!raw)
265
279
  continue;
266
280
  const nonImportCss = raw.replace(importRe, (match) => {
@@ -277,31 +291,31 @@ function coalesceHeadStylesAndBodyScripts($) {
277
291
  }
278
292
  const merged = [...imports, ...cssParts].join("\n\n").trim();
279
293
  if (merged) {
280
- $(headStyleEls[0]).text(merged);
294
+ headStyleEls[0].textContent = merged;
281
295
  for (let i = 1; i < headStyleEls.length; i++)
282
- $(headStyleEls[i]).remove();
296
+ headStyleEls[i].remove();
283
297
  }
284
298
  }
285
- const bodyInlineScripts = $("body script")
286
- .toArray()
287
- .filter((el) => {
288
- const src = ($(el).attr("src") || "").trim();
299
+ const bodyInlineScripts = [...document.querySelectorAll("body script")].filter((el) => {
300
+ const src = (el.getAttribute("src") || "").trim();
289
301
  if (src)
290
302
  return false;
291
- const type = ($(el).attr("type") || "").trim().toLowerCase();
303
+ const type = (el.getAttribute("type") || "").trim().toLowerCase();
292
304
  return !type || type === "text/javascript" || type === "application/javascript";
293
305
  });
294
306
  if (bodyInlineScripts.length > 0) {
295
307
  const mergedJs = bodyInlineScripts
296
- .map((el) => ($(el).html() || "").trim())
308
+ .map((el) => (el.textContent || "").trim())
297
309
  .filter(Boolean)
298
310
  .join("\n;\n")
299
311
  .trim();
300
312
  for (const el of bodyInlineScripts)
301
- $(el).remove();
313
+ el.remove();
302
314
  if (mergedJs) {
303
315
  const stripped = stripJsCommentsParserSafe(mergedJs);
304
- $("body").append(`<script>${stripped}</script>`);
316
+ const inlineScript = document.createElement("script");
317
+ inlineScript.textContent = stripped;
318
+ document.body.appendChild(inlineScript);
305
319
  }
306
320
  }
307
321
  }
@@ -336,91 +350,118 @@ export async function bundleToSingleHtml(projectDir, options) {
336
350
  console.warn(`[StaticGuard] Invalid HyperFrame contract: ${staticGuard.missingKeys.join("; ")}`);
337
351
  }
338
352
  const withInterceptor = injectInterceptor(compiled);
339
- const $ = cheerio.load(withInterceptor);
353
+ const { document } = parseHTML(withInterceptor);
340
354
  // Inline local CSS
341
355
  const localCssChunks = [];
342
356
  let cssAnchorPlaced = false;
343
- $('link[rel="stylesheet"]').each((_, el) => {
344
- const href = $(el).attr("href");
357
+ for (const el of [...document.querySelectorAll('link[rel="stylesheet"]')]) {
358
+ const href = el.getAttribute("href");
345
359
  if (!href || !isRelativeUrl(href))
346
- return;
360
+ continue;
347
361
  const cssPath = safePath(projectDir, href);
348
362
  const css = cssPath ? safeReadFile(cssPath) : null;
349
363
  if (css == null)
350
- return;
364
+ continue;
351
365
  localCssChunks.push(css);
352
366
  if (!cssAnchorPlaced) {
353
- $(el).replaceWith('<style data-hf-bundled-local-css="1"></style>');
367
+ const anchor = document.createElement("style");
368
+ anchor.setAttribute("data-hf-bundled-local-css", "1");
369
+ el.replaceWith(anchor);
354
370
  cssAnchorPlaced = true;
355
371
  }
356
372
  else {
357
- $(el).remove();
373
+ el.remove();
358
374
  }
359
- });
375
+ }
360
376
  if (localCssChunks.length > 0) {
361
- const $anchor = $('style[data-hf-bundled-local-css="1"]').first();
362
- if ($anchor.length)
363
- $anchor.removeAttr("data-hf-bundled-local-css").text(localCssChunks.join("\n\n"));
364
- else
365
- $("head").append(`<style>${localCssChunks.join("\n\n")}</style>`);
377
+ const anchor = document.querySelector('style[data-hf-bundled-local-css="1"]');
378
+ if (anchor) {
379
+ anchor.removeAttribute("data-hf-bundled-local-css");
380
+ anchor.textContent = localCssChunks.join("\n\n");
381
+ }
382
+ else {
383
+ const style = document.createElement("style");
384
+ style.textContent = localCssChunks.join("\n\n");
385
+ document.head.appendChild(style);
386
+ }
366
387
  }
367
388
  // Inline local JS
368
389
  const localJsChunks = [];
369
390
  let jsAnchorPlaced = false;
370
- $("script[src]").each((_, el) => {
371
- const src = $(el).attr("src");
391
+ for (const el of [...document.querySelectorAll("script[src]")]) {
392
+ const src = el.getAttribute("src");
372
393
  if (!src || !isRelativeUrl(src))
373
- return;
394
+ continue;
374
395
  const jsPath = safePath(projectDir, src);
375
396
  const js = jsPath ? safeReadFile(jsPath) : null;
376
397
  if (js == null)
377
- return;
398
+ continue;
378
399
  localJsChunks.push(js);
379
400
  if (!jsAnchorPlaced) {
380
- $(el).replaceWith('<script data-hf-bundled-local-js="1"></script>');
401
+ const anchor = document.createElement("script");
402
+ anchor.setAttribute("data-hf-bundled-local-js", "1");
403
+ el.replaceWith(anchor);
381
404
  jsAnchorPlaced = true;
382
405
  }
383
406
  else {
384
- $(el).remove();
407
+ el.remove();
385
408
  }
386
- });
409
+ }
387
410
  if (localJsChunks.length > 0) {
388
- const $anchor = $('script[data-hf-bundled-local-js="1"]').first();
389
- if ($anchor.length)
390
- $anchor.removeAttr("data-hf-bundled-local-js").text(localJsChunks.join("\n;\n"));
391
- else
392
- $("body").append(`<script>${localJsChunks.join("\n;\n")}</script>`);
411
+ const anchor = document.querySelector('script[data-hf-bundled-local-js="1"]');
412
+ if (anchor) {
413
+ anchor.removeAttribute("data-hf-bundled-local-js");
414
+ anchor.textContent = localJsChunks.join("\n;\n");
415
+ }
416
+ else {
417
+ const script = document.createElement("script");
418
+ script.textContent = localJsChunks.join("\n;\n");
419
+ document.body.appendChild(script);
420
+ }
393
421
  }
394
422
  // Inline sub-compositions
395
423
  const compStyleChunks = [];
396
424
  const compScriptChunks = [];
397
425
  const compExternalScriptSrcs = [];
398
- $("[data-composition-src]").each((_, hostEl) => {
399
- const src = $(hostEl).attr("data-composition-src");
426
+ for (const hostEl of [...document.querySelectorAll("[data-composition-src]")]) {
427
+ const src = hostEl.getAttribute("data-composition-src");
400
428
  if (!src || !isRelativeUrl(src))
401
- return;
429
+ continue;
402
430
  const compPath = safePath(projectDir, src);
403
431
  const compHtml = compPath ? safeReadFile(compPath) : null;
404
432
  if (compHtml == null) {
405
433
  console.warn(`[Bundler] Composition file not found: ${src}`);
406
- return;
434
+ continue;
407
435
  }
408
- const $comp = cheerio.load(compHtml);
409
- const compId = $(hostEl).attr("data-composition-id");
410
- const $contentRoot = $comp("template").first();
411
- const contentHtml = $contentRoot.length
412
- ? $contentRoot.html() || ""
413
- : $comp("body").html() || "";
414
- const $content = cheerio.load(contentHtml);
415
- const $innerRoot = compId
416
- ? $content(`[data-composition-id="${compId}"]`).first()
417
- : $content("[data-composition-id]").first();
418
- $content("style").each((_, s) => {
419
- compStyleChunks.push(rewriteCssAssetUrls($content(s).html() || "", src));
420
- $content(s).remove();
421
- });
422
- $content("script").each((_, s) => {
423
- const externalSrc = ($content(s).attr("src") || "").trim();
436
+ const compDoc = parseHTMLContent(compHtml);
437
+ const compId = hostEl.getAttribute("data-composition-id");
438
+ const contentRoot = compDoc.querySelector("template");
439
+ const contentHtml = contentRoot ? contentRoot.innerHTML || "" : compDoc.body.innerHTML || "";
440
+ const contentDoc = parseHTMLContent(contentHtml);
441
+ const innerRoot = compId
442
+ ? contentDoc.querySelector(`[data-composition-id="${compId}"]`)
443
+ : contentDoc.querySelector("[data-composition-id]");
444
+ // When a sub-composition is a full HTML document (no <template>), styles
445
+ // and scripts in <head> are not part of contentDoc (which only has body
446
+ // content). Extract them so backgrounds, positioning, fonts, and library
447
+ // scripts (e.g. GSAP CDN) are not silently dropped.
448
+ if (!contentRoot && compDoc.head) {
449
+ for (const s of [...compDoc.head.querySelectorAll("style")]) {
450
+ compStyleChunks.push(rewriteCssAssetUrls(s.textContent || "", src));
451
+ }
452
+ for (const s of [...compDoc.head.querySelectorAll("script")]) {
453
+ const externalSrc = (s.getAttribute("src") || "").trim();
454
+ if (externalSrc && !compExternalScriptSrcs.includes(externalSrc)) {
455
+ compExternalScriptSrcs.push(externalSrc);
456
+ }
457
+ }
458
+ }
459
+ for (const s of [...contentDoc.querySelectorAll("style")]) {
460
+ compStyleChunks.push(rewriteCssAssetUrls(s.textContent || "", src));
461
+ s.remove();
462
+ }
463
+ for (const s of [...contentDoc.querySelectorAll("script")]) {
464
+ const externalSrc = (s.getAttribute("src") || "").trim();
424
465
  if (externalSrc) {
425
466
  // External CDN/remote script — collect for deduped injection into the document.
426
467
  // Do NOT try to inline the content (external scripts have no innerHTML).
@@ -429,147 +470,157 @@ export async function bundleToSingleHtml(projectDir, options) {
429
470
  }
430
471
  }
431
472
  else {
432
- compScriptChunks.push(`(function(){ try { ${$content(s).html() || ""} } catch (_err) { console.error('[HyperFrames] composition script error:', _err); } })();`);
473
+ compScriptChunks.push(`(function(){ try { ${s.textContent || ""} } catch (_err) { console.error('[HyperFrames] composition script error:', _err); } })();`);
433
474
  }
434
- $content(s).remove();
435
- });
475
+ s.remove();
476
+ }
436
477
  // Rewrite relative asset paths before inlining so ../foo.svg from
437
478
  // compositions/ resolves correctly when the content moves to root.
438
- const $assetEls = $innerRoot.length
439
- ? $innerRoot.find("[src], [href]")
440
- : $content("[src], [href]");
441
- rewriteAssetPaths($assetEls.toArray(), src, (el, attr) => $content(el).attr(attr), (el, attr, val) => {
442
- $content(el).attr(attr, val);
479
+ const assetEls = innerRoot
480
+ ? innerRoot.querySelectorAll("[src], [href]")
481
+ : contentDoc.querySelectorAll("[src], [href]");
482
+ rewriteAssetPaths(assetEls, src, (el, attr) => el.getAttribute(attr), (el, attr, val) => {
483
+ el.setAttribute(attr, val);
443
484
  });
444
- if ($innerRoot.length) {
445
- const innerCompId = $innerRoot.attr("data-composition-id");
446
- const innerW = $innerRoot.attr("data-width");
447
- const innerH = $innerRoot.attr("data-height");
448
- if (innerCompId && !$(hostEl).attr("data-composition-id"))
449
- $(hostEl).attr("data-composition-id", innerCompId);
450
- if (innerW && !$(hostEl).attr("data-width"))
451
- $(hostEl).attr("data-width", innerW);
452
- if (innerH && !$(hostEl).attr("data-height"))
453
- $(hostEl).attr("data-height", innerH);
454
- $innerRoot.find("style, script").remove();
455
- $(hostEl).html($innerRoot.html() || "");
485
+ if (innerRoot) {
486
+ const innerCompId = innerRoot.getAttribute("data-composition-id");
487
+ const innerW = innerRoot.getAttribute("data-width");
488
+ const innerH = innerRoot.getAttribute("data-height");
489
+ if (innerCompId && !hostEl.getAttribute("data-composition-id"))
490
+ hostEl.setAttribute("data-composition-id", innerCompId);
491
+ if (innerW && !hostEl.getAttribute("data-width"))
492
+ hostEl.setAttribute("data-width", innerW);
493
+ if (innerH && !hostEl.getAttribute("data-height"))
494
+ hostEl.setAttribute("data-height", innerH);
495
+ for (const child of [...innerRoot.querySelectorAll("style, script")])
496
+ child.remove();
497
+ hostEl.innerHTML = innerRoot.innerHTML || "";
456
498
  }
457
499
  else {
458
- $content("style, script").remove();
459
- $(hostEl).html($content.html() || "");
500
+ for (const child of [...contentDoc.querySelectorAll("style, script")])
501
+ child.remove();
502
+ hostEl.innerHTML = contentDoc.body.innerHTML || "";
460
503
  }
461
- $(hostEl).removeAttr("data-composition-src");
462
- });
504
+ hostEl.removeAttribute("data-composition-src");
505
+ }
463
506
  // Inline template compositions: inject <template id="X-template"> content into
464
507
  // matching empty host elements with data-composition-id="X" (no data-composition-src)
465
- $("template[id]").each((_, templateEl) => {
466
- const templateId = $(templateEl).attr("id") || "";
508
+ for (const templateEl of [...document.querySelectorAll("template[id]")]) {
509
+ const templateId = templateEl.getAttribute("id") || "";
467
510
  const match = templateId.match(/^(.+)-template$/);
468
511
  if (!match)
469
- return;
512
+ continue;
470
513
  const compId = match[1];
471
514
  // Find the matching host element (must have data-composition-id, no data-composition-src,
472
- // and must NOT be inside a <template> element). In cheerio, elements inside <template>
473
- // have a detached parent chain (parents().length === 0), so we filter those out.
515
+ // and must NOT be inside a <template> element).
474
516
  const hostSelector = `[data-composition-id="${compId}"]:not([data-composition-src])`;
475
- const $candidates = $(hostSelector).filter((__, el) => $(el).parents().length > 0);
476
- const $host = $candidates.first();
477
- if ($host.length === 0)
478
- return;
479
- if ($host.children().length > 0)
480
- return; // already has content
517
+ // linkedom follows the DOM spec: querySelectorAll does not reach inside <template>
518
+ // content, so no isInsideTemplate filter is needed.
519
+ const host = document.querySelector(hostSelector);
520
+ if (!host)
521
+ continue;
522
+ if (host.children.length > 0)
523
+ continue; // already has content
481
524
  // Get template content and inject into host
482
- const templateHtml = $(templateEl).html() || "";
483
- const $inner = cheerio.load(templateHtml, { xml: false });
484
- const $innerRoot = $inner(`[data-composition-id="${compId}"]`).first();
485
- if ($innerRoot.length > 0) {
525
+ const templateHtml = templateEl.innerHTML || "";
526
+ const innerDoc = parseHTMLContent(templateHtml);
527
+ const innerRoot = innerDoc.querySelector(`[data-composition-id="${compId}"]`);
528
+ if (innerRoot) {
486
529
  // Hoist styles into the collected style chunks
487
- $innerRoot.find("style").each((__, styleEl) => {
488
- compStyleChunks.push($inner(styleEl).html() || "");
489
- $inner(styleEl).remove();
490
- });
530
+ for (const styleEl of [...innerRoot.querySelectorAll("style")]) {
531
+ compStyleChunks.push(styleEl.textContent || "");
532
+ styleEl.remove();
533
+ }
491
534
  // Hoist scripts into the collected script chunks
492
- $innerRoot.find("script").each((__, scriptEl) => {
493
- const externalSrc = ($inner(scriptEl).attr("src") || "").trim();
535
+ for (const scriptEl of [...innerRoot.querySelectorAll("script")]) {
536
+ const externalSrc = (scriptEl.getAttribute("src") || "").trim();
494
537
  if (externalSrc) {
495
538
  if (!compExternalScriptSrcs.includes(externalSrc)) {
496
539
  compExternalScriptSrcs.push(externalSrc);
497
540
  }
498
541
  }
499
542
  else {
500
- compScriptChunks.push(`(function(){ try { ${$inner(scriptEl).html() || ""} } catch (_err) { console.error('[HyperFrames] composition script error:', _err); } })();`);
543
+ compScriptChunks.push(`(function(){ try { ${scriptEl.textContent || ""} } catch (_err) { console.error('[HyperFrames] composition script error:', _err); } })();`);
501
544
  }
502
- $inner(scriptEl).remove();
503
- });
545
+ scriptEl.remove();
546
+ }
504
547
  // Copy dimension attributes from inner root to host if not already set
505
- const innerW = $innerRoot.attr("data-width");
506
- const innerH = $innerRoot.attr("data-height");
507
- if (innerW && !$host.attr("data-width"))
508
- $host.attr("data-width", innerW);
509
- if (innerH && !$host.attr("data-height"))
510
- $host.attr("data-height", innerH);
548
+ const innerW = innerRoot.getAttribute("data-width");
549
+ const innerH = innerRoot.getAttribute("data-height");
550
+ if (innerW && !host.getAttribute("data-width"))
551
+ host.setAttribute("data-width", innerW);
552
+ if (innerH && !host.getAttribute("data-height"))
553
+ host.setAttribute("data-height", innerH);
511
554
  // Set host content from inner root
512
- $host.html($innerRoot.html() || "");
555
+ host.innerHTML = innerRoot.innerHTML || "";
513
556
  }
514
557
  else {
515
558
  // No matching inner root — inject all template content directly
516
- $inner("style").each((__, styleEl) => {
517
- compStyleChunks.push($inner(styleEl).html() || "");
518
- $inner(styleEl).remove();
519
- });
520
- $inner("script").each((__, scriptEl) => {
521
- const externalSrc = ($inner(scriptEl).attr("src") || "").trim();
559
+ for (const styleEl of [...innerDoc.querySelectorAll("style")]) {
560
+ compStyleChunks.push(styleEl.textContent || "");
561
+ styleEl.remove();
562
+ }
563
+ for (const scriptEl of [...innerDoc.querySelectorAll("script")]) {
564
+ const externalSrc = (scriptEl.getAttribute("src") || "").trim();
522
565
  if (externalSrc) {
523
566
  if (!compExternalScriptSrcs.includes(externalSrc)) {
524
567
  compExternalScriptSrcs.push(externalSrc);
525
568
  }
526
569
  }
527
570
  else {
528
- compScriptChunks.push(`(function(){ try { ${$inner(scriptEl).html() || ""} } catch (_err) { console.error('[HyperFrames] composition script error:', _err); } })();`);
571
+ compScriptChunks.push(`(function(){ try { ${scriptEl.textContent || ""} } catch (_err) { console.error('[HyperFrames] composition script error:', _err); } })();`);
529
572
  }
530
- $inner(scriptEl).remove();
531
- });
532
- $host.html($inner.html() || "");
573
+ scriptEl.remove();
574
+ }
575
+ host.innerHTML = innerDoc.body.innerHTML || "";
533
576
  }
534
577
  // Remove the template element from the document
535
- $(templateEl).remove();
536
- });
578
+ templateEl.remove();
579
+ }
537
580
  // Inject external scripts from sub-compositions (e.g., Lottie CDN)
538
581
  // that aren't already present in the main document.
539
582
  for (const extSrc of compExternalScriptSrcs) {
540
- if (!$(`script[src="${extSrc}"]`).length) {
541
- $("body").append(`<script src="${extSrc}"></script>`);
583
+ if (!document.querySelector(`script[src="${extSrc}"]`)) {
584
+ const extScript = document.createElement("script");
585
+ extScript.setAttribute("src", extSrc);
586
+ document.body.appendChild(extScript);
542
587
  }
543
588
  }
544
- if (compStyleChunks.length)
545
- $("head").append(`<style>${compStyleChunks.join("\n\n")}</style>`);
546
- if (compScriptChunks.length)
547
- $("body").append(`<script>${compScriptChunks.join("\n;\n")}</script>`);
548
- enforceCompositionPixelSizing($);
549
- autoHealMissingCompositionIds($);
550
- coalesceHeadStylesAndBodyScripts($);
589
+ if (compStyleChunks.length) {
590
+ const style = document.createElement("style");
591
+ style.textContent = compStyleChunks.join("\n\n");
592
+ document.head.appendChild(style);
593
+ }
594
+ if (compScriptChunks.length) {
595
+ const compScript = document.createElement("script");
596
+ compScript.textContent = compScriptChunks.join("\n;\n");
597
+ document.body.appendChild(compScript);
598
+ }
599
+ enforceCompositionPixelSizing(document);
600
+ autoHealMissingCompositionIds(document);
601
+ coalesceHeadStylesAndBodyScripts(document);
551
602
  // Inline textual assets
552
- $("[src], [href], [poster], [xlink\\:href]").each((_, el) => {
603
+ for (const el of [...document.querySelectorAll("[src], [href], [poster], [xlink\\:href]")]) {
553
604
  for (const attr of ["src", "href", "poster", "xlink:href"]) {
554
- const value = $(el).attr(attr);
605
+ const value = el.getAttribute(attr);
555
606
  if (!value)
556
607
  continue;
557
608
  const inlined = maybeInlineRelativeAssetUrl(value, projectDir);
558
609
  if (inlined)
559
- $(el).attr(attr, inlined);
610
+ el.setAttribute(attr, inlined);
560
611
  }
561
- });
562
- $("[srcset]").each((_, el) => {
563
- const srcset = $(el).attr("srcset");
612
+ }
613
+ for (const el of [...document.querySelectorAll("[srcset]")]) {
614
+ const srcset = el.getAttribute("srcset");
564
615
  if (srcset)
565
- $(el).attr("srcset", rewriteSrcsetWithInlinedAssets(srcset, projectDir));
566
- });
567
- $("style").each((_, el) => {
568
- $(el).text(rewriteCssUrlsWithInlinedAssets($(el).html() || "", projectDir));
569
- });
570
- $("[style]").each((_, el) => {
571
- $(el).attr("style", rewriteCssUrlsWithInlinedAssets($(el).attr("style") || "", projectDir));
572
- });
573
- return $.html();
616
+ el.setAttribute("srcset", rewriteSrcsetWithInlinedAssets(srcset, projectDir));
617
+ }
618
+ for (const styleEl of document.querySelectorAll("style")) {
619
+ styleEl.textContent = rewriteCssUrlsWithInlinedAssets(styleEl.textContent || "", projectDir);
620
+ }
621
+ for (const el of [...document.querySelectorAll("[style]")]) {
622
+ el.setAttribute("style", rewriteCssUrlsWithInlinedAssets(el.getAttribute("style") || "", projectDir));
623
+ }
624
+ return document.toString();
574
625
  }
575
626
  //# sourceMappingURL=htmlBundler.js.map