@adaas/are-html 0.0.22 → 0.0.23

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.
Files changed (129) hide show
  1. package/dist/browser/index.d.mts +176 -8
  2. package/dist/browser/index.mjs +661 -235
  3. package/dist/browser/index.mjs.map +1 -1
  4. package/dist/node/{AreBinding.attribute-doUvtOjc.d.mts → AreBinding.attribute-BWzEIw6H.d.mts} +45 -0
  5. package/dist/node/{AreBinding.attribute-Bm5LlOyE.d.ts → AreBinding.attribute-GpT-5Qmf.d.ts} +45 -0
  6. package/dist/node/attributes/AreBinding.attribute.d.mts +1 -1
  7. package/dist/node/attributes/AreBinding.attribute.d.ts +1 -1
  8. package/dist/node/attributes/AreDirective.attribute.d.mts +1 -1
  9. package/dist/node/attributes/AreDirective.attribute.d.ts +1 -1
  10. package/dist/node/attributes/AreEvent.attribute.d.mts +1 -1
  11. package/dist/node/attributes/AreEvent.attribute.d.ts +1 -1
  12. package/dist/node/attributes/AreStatic.attribute.d.mts +1 -1
  13. package/dist/node/attributes/AreStatic.attribute.d.ts +1 -1
  14. package/dist/node/directives/AreDirectiveFor.directive.d.mts +18 -1
  15. package/dist/node/directives/AreDirectiveFor.directive.d.ts +18 -1
  16. package/dist/node/directives/AreDirectiveFor.directive.js +57 -9
  17. package/dist/node/directives/AreDirectiveFor.directive.js.map +1 -1
  18. package/dist/node/directives/AreDirectiveFor.directive.mjs +57 -9
  19. package/dist/node/directives/AreDirectiveFor.directive.mjs.map +1 -1
  20. package/dist/node/directives/AreDirectiveIf.directive.d.mts +1 -1
  21. package/dist/node/directives/AreDirectiveIf.directive.d.ts +1 -1
  22. package/dist/node/directives/AreDirectiveShow.directive.d.mts +1 -1
  23. package/dist/node/directives/AreDirectiveShow.directive.d.ts +1 -1
  24. package/dist/node/engine/AreHTML.compiler.d.mts +1 -1
  25. package/dist/node/engine/AreHTML.compiler.d.ts +1 -1
  26. package/dist/node/engine/AreHTML.compiler.js +4 -0
  27. package/dist/node/engine/AreHTML.compiler.js.map +1 -1
  28. package/dist/node/engine/AreHTML.compiler.mjs +4 -0
  29. package/dist/node/engine/AreHTML.compiler.mjs.map +1 -1
  30. package/dist/node/engine/AreHTML.constants.d.mts +33 -1
  31. package/dist/node/engine/AreHTML.constants.d.ts +33 -1
  32. package/dist/node/engine/AreHTML.constants.js +166 -0
  33. package/dist/node/engine/AreHTML.constants.js.map +1 -1
  34. package/dist/node/engine/AreHTML.constants.mjs +165 -1
  35. package/dist/node/engine/AreHTML.constants.mjs.map +1 -1
  36. package/dist/node/engine/AreHTML.context.d.mts +66 -0
  37. package/dist/node/engine/AreHTML.context.d.ts +66 -0
  38. package/dist/node/engine/AreHTML.context.js +98 -0
  39. package/dist/node/engine/AreHTML.context.js.map +1 -1
  40. package/dist/node/engine/AreHTML.context.mjs +98 -0
  41. package/dist/node/engine/AreHTML.context.mjs.map +1 -1
  42. package/dist/node/engine/AreHTML.interpreter.d.mts +3 -0
  43. package/dist/node/engine/AreHTML.interpreter.d.ts +3 -0
  44. package/dist/node/engine/AreHTML.interpreter.js +66 -10
  45. package/dist/node/engine/AreHTML.interpreter.js.map +1 -1
  46. package/dist/node/engine/AreHTML.interpreter.mjs +66 -10
  47. package/dist/node/engine/AreHTML.interpreter.mjs.map +1 -1
  48. package/dist/node/engine/AreHTML.lifecycle.d.mts +1 -8
  49. package/dist/node/engine/AreHTML.lifecycle.d.ts +1 -8
  50. package/dist/node/engine/AreHTML.lifecycle.js +29 -44
  51. package/dist/node/engine/AreHTML.lifecycle.js.map +1 -1
  52. package/dist/node/engine/AreHTML.lifecycle.mjs +29 -44
  53. package/dist/node/engine/AreHTML.lifecycle.mjs.map +1 -1
  54. package/dist/node/engine/AreHTML.tokenizer.d.mts +1 -1
  55. package/dist/node/engine/AreHTML.tokenizer.d.ts +1 -1
  56. package/dist/node/engine/AreHTML.tokenizer.js +7 -1
  57. package/dist/node/engine/AreHTML.tokenizer.js.map +1 -1
  58. package/dist/node/engine/AreHTML.tokenizer.mjs +7 -1
  59. package/dist/node/engine/AreHTML.tokenizer.mjs.map +1 -1
  60. package/dist/node/engine/AreHTML.transformer.d.mts +1 -1
  61. package/dist/node/engine/AreHTML.transformer.d.ts +1 -1
  62. package/dist/node/index.d.mts +4 -3
  63. package/dist/node/index.d.ts +4 -3
  64. package/dist/node/index.js +7 -0
  65. package/dist/node/index.mjs +1 -0
  66. package/dist/node/instructions/AddStaticHTML.instruction.d.mts +8 -0
  67. package/dist/node/instructions/AddStaticHTML.instruction.d.ts +8 -0
  68. package/dist/node/instructions/AddStaticHTML.instruction.js +31 -0
  69. package/dist/node/instructions/AddStaticHTML.instruction.js.map +1 -0
  70. package/dist/node/instructions/AddStaticHTML.instruction.mjs +24 -0
  71. package/dist/node/instructions/AddStaticHTML.instruction.mjs.map +1 -0
  72. package/dist/node/instructions/AreHTML.instructions.constants.d.mts +1 -0
  73. package/dist/node/instructions/AreHTML.instructions.constants.d.ts +1 -0
  74. package/dist/node/instructions/AreHTML.instructions.constants.js +1 -0
  75. package/dist/node/instructions/AreHTML.instructions.constants.js.map +1 -1
  76. package/dist/node/instructions/AreHTML.instructions.constants.mjs +1 -0
  77. package/dist/node/instructions/AreHTML.instructions.constants.mjs.map +1 -1
  78. package/dist/node/instructions/AreHTML.instructions.types.d.mts +9 -1
  79. package/dist/node/instructions/AreHTML.instructions.types.d.ts +9 -1
  80. package/dist/node/lib/AreDirective/AreDirective.component.d.mts +1 -1
  81. package/dist/node/lib/AreDirective/AreDirective.component.d.ts +1 -1
  82. package/dist/node/lib/AreDirective/AreDirective.types.d.mts +1 -1
  83. package/dist/node/lib/AreDirective/AreDirective.types.d.ts +1 -1
  84. package/dist/node/lib/AreHTML/AreHTML.tokenizer.d.mts +1 -1
  85. package/dist/node/lib/AreHTML/AreHTML.tokenizer.d.ts +1 -1
  86. package/dist/node/lib/AreHTMLAttribute/AreHTML.attribute.d.mts +1 -1
  87. package/dist/node/lib/AreHTMLAttribute/AreHTML.attribute.d.ts +1 -1
  88. package/dist/node/lib/AreHTMLNode/AreHTMLNode.d.mts +1 -1
  89. package/dist/node/lib/AreHTMLNode/AreHTMLNode.d.ts +1 -1
  90. package/dist/node/lib/AreHTMLNode/AreHTMLNode.js +51 -0
  91. package/dist/node/lib/AreHTMLNode/AreHTMLNode.js.map +1 -1
  92. package/dist/node/lib/AreHTMLNode/AreHTMLNode.mjs +51 -0
  93. package/dist/node/lib/AreHTMLNode/AreHTMLNode.mjs.map +1 -1
  94. package/dist/node/lib/AreRoot/AreRoot.component.js.map +1 -1
  95. package/dist/node/lib/AreRoot/AreRoot.component.mjs.map +1 -1
  96. package/dist/node/nodes/AreComment.d.mts +1 -1
  97. package/dist/node/nodes/AreComment.d.ts +1 -1
  98. package/dist/node/nodes/AreComponent.d.mts +1 -1
  99. package/dist/node/nodes/AreComponent.d.ts +1 -1
  100. package/dist/node/nodes/AreInterpolation.d.mts +1 -1
  101. package/dist/node/nodes/AreInterpolation.d.ts +1 -1
  102. package/dist/node/nodes/AreRoot.d.mts +1 -1
  103. package/dist/node/nodes/AreRoot.d.ts +1 -1
  104. package/dist/node/nodes/AreText.d.mts +1 -1
  105. package/dist/node/nodes/AreText.d.ts +1 -1
  106. package/examples/dashboard/concept.ts +1 -1
  107. package/examples/dashboard/dist/index.html +1 -1
  108. package/examples/dashboard/dist/{mqh9ryml-xat335.js → mqiw5sqa-ypckmj.js} +403 -57
  109. package/examples/for-perf/dist/index.html +1 -1
  110. package/examples/for-perf/dist/{mqh9ryfo-6a8d0o.js → mqj1mpf2-z4aokv.js} +558 -117
  111. package/examples/for-perf/dist/{mqh9ryfq-4pf5cv.js → mqj1mpff-4fr7mw.js} +558 -117
  112. package/examples/signal-routing/dist/index.html +1 -1
  113. package/examples/signal-routing/dist/{mqh9ryc9-dkcbkx.js → mqiwo23h-bhcolu.js} +413 -60
  114. package/package.json +5 -5
  115. package/src/directives/AreDirectiveFor.directive.ts +99 -16
  116. package/src/engine/AreHTML.compiler.ts +13 -0
  117. package/src/engine/AreHTML.constants.ts +142 -0
  118. package/src/engine/AreHTML.context.ts +112 -0
  119. package/src/engine/AreHTML.interpreter.ts +114 -13
  120. package/src/engine/AreHTML.lifecycle.ts +81 -74
  121. package/src/engine/AreHTML.tokenizer.ts +30 -1
  122. package/src/index.ts +1 -0
  123. package/src/instructions/AddStaticHTML.instruction.ts +23 -0
  124. package/src/instructions/AreHTML.instructions.constants.ts +1 -0
  125. package/src/instructions/AreHTML.instructions.types.ts +9 -0
  126. package/src/lib/AreHTMLNode/AreHTMLNode.ts +74 -0
  127. package/src/lib/AreRoot/AreRoot.component.ts +3 -3
  128. package/tests/StaticIsland.test.ts +115 -0
  129. package/examples/for-perf/dist/mqh9ryde-m243t8.js +0 -15223
@@ -13,6 +13,6 @@
13
13
  <body>
14
14
  <are-root id="app"><app-shell></app-shell></are-root>
15
15
 
16
- <script type="module" src="./mqh9ryc9-dkcbkx.js"></script>
16
+ <script type="module" src="./mqiwo23h-bhcolu.js"></script>
17
17
  </body>
18
18
  </html>
@@ -2845,8 +2845,8 @@ var __decorateClass2 = /* @__PURE__ */ __name((decorators, target, key, kind) =>
2845
2845
  }, "__decorateClass");
2846
2846
  var __decorateParam2 = /* @__PURE__ */ __name((index, decorator) => (target, key) => decorator(target, key, index), "__decorateParam");
2847
2847
 
2848
- // node_modules/@adaas/a-frame/dist/browser/chunk-UWXOV5XO.mjs
2849
- var t = "0.1.15";
2848
+ // node_modules/@adaas/a-frame/dist/browser/chunk-VBGV4GJ5.mjs
2849
+ var t = "0.1.16";
2850
2850
 
2851
2851
  // node_modules/@adaas/a-frame/dist/browser/chunk-IKIN4MJV.mjs
2852
2852
  var h2 = Object.defineProperty;
@@ -2858,7 +2858,7 @@ var k2 = /* @__PURE__ */ __name((c3, a4, e, d4) => {
2858
2858
  }, "k");
2859
2859
  var l = /* @__PURE__ */ __name((c3, a4) => (e, d4) => a4(e, d4, c3), "l");
2860
2860
 
2861
- // node_modules/@adaas/a-frame/dist/browser/chunk-PTHJM2MP.mjs
2861
+ // node_modules/@adaas/a-frame/dist/browser/chunk-6K7VISNV.mjs
2862
2862
  var _a39;
2863
2863
  var _2 = (_a39 = class extends H {
2864
2864
  get A_FRAME_TOKEN() {
@@ -3468,7 +3468,7 @@ var n3 = (_a48 = class extends D {
3468
3468
  j2(n3, "A_FrameDefinition");
3469
3469
  var h3 = n3;
3470
3470
 
3471
- // node_modules/@adaas/a-frame/dist/browser/chunk-FYZWOISU.mjs
3471
+ // node_modules/@adaas/a-frame/dist/browser/chunk-3ROGJ3YE.mjs
3472
3472
  var _a49;
3473
3473
  var z2 = (_a49 = class extends H {
3474
3474
  constructor() {
@@ -4439,7 +4439,7 @@ var a3 = (_a64 = class extends D {
4439
4439
  j2(a3, "A_FrameSchema");
4440
4440
  var s2 = a3;
4441
4441
 
4442
- // node_modules/@adaas/a-frame/dist/browser/chunk-PIH5MHMV.mjs
4442
+ // node_modules/@adaas/a-frame/dist/browser/chunk-4KUCX5R6.mjs
4443
4443
  var d3 = { Request: "_A_FRAME_REQUEST", Socket: "_A_FRAME_SOCKET", Stream: "_A_FRAME_STREAM", Send: "_A_FRAME_SEND" };
4444
4444
  var _a65;
4445
4445
  var J2 = (_a65 = class extends H {
@@ -5008,7 +5008,7 @@ var l3 = (_a76 = class extends O {
5008
5008
  j2(l3, "A_FrameChannel"), k2([N.Extend({ name: r4.Embed, scope: [h3] }), l(0, Yt(te)), l(1, Yt(f3))], l3.prototype, "embedDefinition", 1), k2([N.Extend({ name: m3.Embed, scope: [w2] }), l(0, Yt(te)), l(1, Yt(f3))], l3.prototype, "embedNamespace", 1), k2([N.Extend({ name: r5.Embed, scope: [_4] }), l(0, Yt(te)), l(1, Yt(f3))], l3.prototype, "embedSegment", 1), k2([N.Extend({ name: D3.Generate, scope: [O3] }), l(0, Yt(te)), l(1, Yt(v4))], l3.prototype, "generateDynamicStructure", 1), k2([N.Extend({ name: D3.Patch, scope: [O3] }), l(0, Yt(te)), l(1, Yt(v4))], l3.prototype, "patchDynamicStructure", 1), k2([N.Extend({ name: C4.Generate, scope: [P3] }), l(0, Yt(te)), l(1, Yt(w5))], l3.prototype, "generateDynamicFeature", 1), k2([N.Extend({ name: C4.Patch, scope: [P3] }), l(0, Yt(te)), l(1, Yt(w5))], l3.prototype, "patchDynamicFeature", 1), k2([N.Extend({ name: F3.Generate, scope: [w4] }), l(0, Yt(te)), l(1, Yt(f2))], l3.prototype, "generateDynamicContent", 1), k2([N.Extend({ name: F3.Patch, scope: [w4] }), l(0, Yt(te)), l(1, Yt(f2))], l3.prototype, "patchDynamicContent", 1), k2([N.Extend({ name: n4.Generate, scope: [m4] }), l(0, Yt(te)), l(1, Yt(f3))], l3.prototype, "generateCompletion", 1), k2([N.Extend({ name: r6.Extract, scope: [s2] }), l(0, Yt(te)), l(1, Yt(f3))], l3.prototype, "extractSchema", 1), k2([N.Extend({ name: r6.ExtractMultiple, scope: [s2] }), l(0, Yt(te)), l(1, Yt(f3))], l3.prototype, "extractSchemaMultiple", 1);
5009
5009
  var Fe2 = l3;
5010
5010
 
5011
- // node_modules/@adaas/a-frame/dist/browser/chunk-2O3HAEYW.mjs
5011
+ // node_modules/@adaas/a-frame/dist/browser/chunk-P6WICUUU.mjs
5012
5012
  var _a77;
5013
5013
  var r7 = (_a77 = class extends Fe2 {
5014
5014
  async request(e, a4) {
@@ -12286,6 +12286,7 @@ var AreHTMLInstructions = {
12286
12286
  AddListener: "_AreHTML_AddListener",
12287
12287
  AddInterpolation: "_AreHTML_AddInterpolation",
12288
12288
  AddComment: "_AreHTML_AddComment",
12289
+ AddStaticHTML: "_AreHTML_AddStaticHTML",
12289
12290
  HideElement: "_AreHTML_HideElement"
12290
12291
  };
12291
12292
 
@@ -12895,6 +12896,24 @@ AddListenerInstruction = __decorateClass([
12895
12896
  })
12896
12897
  ], AddListenerInstruction);
12897
12898
 
12899
+ // src/instructions/AddStaticHTML.instruction.ts
12900
+ var AddStaticHTMLInstruction = class extends AreMutation {
12901
+ constructor(parent, props) {
12902
+ if ("aseid" in props) {
12903
+ super(props);
12904
+ } else {
12905
+ super(AreHTMLInstructions.AddStaticHTML, parent, props);
12906
+ }
12907
+ }
12908
+ };
12909
+ __name(AddStaticHTMLInstruction, "AddStaticHTMLInstruction");
12910
+ AddStaticHTMLInstruction = __decorateClass([
12911
+ R4.Define({
12912
+ namespace: "a-are-html",
12913
+ description: 'Materialises a fully static subtree (a "static island") onto its parent element in a single pass via browser-parsed innerHTML / a cached <template> clone. Apply injects the markup; revert clears it. Decodes HTML entities (e.g. &nbsp;) for free.'
12914
+ })
12915
+ ], AddStaticHTMLInstruction);
12916
+
12898
12917
  // src/instructions/AddStyle.instruction.ts
12899
12918
  var AddStyleInstruction = class extends AreMutation {
12900
12919
  constructor(parent, props) {
@@ -12957,6 +12976,27 @@ var AreHTMLNode = class extends AreNode {
12957
12976
  get tag() {
12958
12977
  return this.aseid.entity;
12959
12978
  }
12979
+ /**
12980
+ * The verbatim inner markup captured when this node was identified as a
12981
+ * static island, or `undefined` for ordinary (per-node) nodes.
12982
+ */
12983
+ get staticInnerHTML() {
12984
+ return this._staticInnerHTML;
12985
+ }
12986
+ /**
12987
+ * Whether this node is a static-island root (see `_staticInnerHTML`).
12988
+ */
12989
+ get isStaticIsland() {
12990
+ return this._staticInnerHTML !== void 0;
12991
+ }
12992
+ /**
12993
+ * Marks this node as a static-island root, capturing the verbatim inner
12994
+ * markup to be materialised in one shot by the interpreter. Called by the
12995
+ * tokenizer when the node's inner content is detected to be fully static.
12996
+ */
12997
+ markStatic(innerHTML) {
12998
+ this._staticInnerHTML = innerHTML;
12999
+ }
12960
13000
  /**
12961
13001
  * The static attributes defined for the node, which are typically used to represent static properties or characteristics of the node that do not change based on the context or state. These attributes are usually defined in the template and are not reactive.
12962
13002
  *
@@ -13280,6 +13320,171 @@ function toDOMString(value) {
13280
13320
  }
13281
13321
  }
13282
13322
  __name(toDOMString, "toDOMString");
13323
+ var STANDARD_HTML_TAGS = /* @__PURE__ */ new Set([
13324
+ // root / sections
13325
+ "html",
13326
+ "body",
13327
+ "header",
13328
+ "footer",
13329
+ "main",
13330
+ "nav",
13331
+ "section",
13332
+ "article",
13333
+ "aside",
13334
+ "address",
13335
+ "hgroup",
13336
+ // headings
13337
+ "h1",
13338
+ "h2",
13339
+ "h3",
13340
+ "h4",
13341
+ "h5",
13342
+ "h6",
13343
+ // grouping
13344
+ "div",
13345
+ "p",
13346
+ "span",
13347
+ "pre",
13348
+ "blockquote",
13349
+ "figure",
13350
+ "figcaption",
13351
+ "hr",
13352
+ "br",
13353
+ "wbr",
13354
+ // lists
13355
+ "ul",
13356
+ "ol",
13357
+ "li",
13358
+ "dl",
13359
+ "dt",
13360
+ "dd",
13361
+ "menu",
13362
+ // text-level / phrasing
13363
+ "a",
13364
+ "b",
13365
+ "i",
13366
+ "u",
13367
+ "s",
13368
+ "em",
13369
+ "strong",
13370
+ "small",
13371
+ "mark",
13372
+ "abbr",
13373
+ "cite",
13374
+ "q",
13375
+ "code",
13376
+ "kbd",
13377
+ "samp",
13378
+ "var",
13379
+ "sub",
13380
+ "sup",
13381
+ "time",
13382
+ "data",
13383
+ "dfn",
13384
+ "bdi",
13385
+ "bdo",
13386
+ "ruby",
13387
+ "rt",
13388
+ "rp",
13389
+ "del",
13390
+ "ins",
13391
+ // media / embedded (no special namespace handling needed)
13392
+ "img",
13393
+ "picture",
13394
+ "source",
13395
+ "figure",
13396
+ "audio",
13397
+ "video",
13398
+ "track",
13399
+ // tables
13400
+ "table",
13401
+ "caption",
13402
+ "colgroup",
13403
+ "col",
13404
+ "thead",
13405
+ "tbody",
13406
+ "tfoot",
13407
+ "tr",
13408
+ "th",
13409
+ "td",
13410
+ // forms (display only — these still render fine from innerHTML)
13411
+ "label",
13412
+ "fieldset",
13413
+ "legend",
13414
+ "datalist",
13415
+ "option",
13416
+ "optgroup",
13417
+ "output",
13418
+ "progress",
13419
+ "meter",
13420
+ // interactive
13421
+ "details",
13422
+ "summary",
13423
+ "dialog"
13424
+ ]);
13425
+ function isStaticMarkup(inner) {
13426
+ if (!inner) return false;
13427
+ if (inner.indexOf("{{") !== -1) return false;
13428
+ const n6 = inner.length;
13429
+ let i6 = 0;
13430
+ while (i6 < n6) {
13431
+ const lt = inner.indexOf("<", i6);
13432
+ if (lt === -1) break;
13433
+ if (inner.startsWith("<!--", lt)) {
13434
+ const end = inner.indexOf("-->", lt + 4);
13435
+ if (end === -1) return false;
13436
+ i6 = end + 3;
13437
+ continue;
13438
+ }
13439
+ if (inner[lt + 1] === "/" || inner[lt + 1] === "!" || inner[lt + 1] === "?") {
13440
+ const gt2 = inner.indexOf(">", lt);
13441
+ if (gt2 === -1) return false;
13442
+ i6 = gt2 + 1;
13443
+ continue;
13444
+ }
13445
+ const nameMatch = /^<([a-zA-Z][a-zA-Z0-9-]*)/.exec(inner.slice(lt));
13446
+ if (!nameMatch) {
13447
+ i6 = lt + 1;
13448
+ continue;
13449
+ }
13450
+ const tag = nameMatch[1].toLowerCase();
13451
+ if (tag.indexOf("-") !== -1 || !STANDARD_HTML_TAGS.has(tag)) return false;
13452
+ let j5 = lt + nameMatch[0].length;
13453
+ let inSingle = false;
13454
+ let inDouble = false;
13455
+ let atNameBoundary = true;
13456
+ let tagEnd = -1;
13457
+ while (j5 < n6) {
13458
+ const ch = inner[j5];
13459
+ if (inDouble) {
13460
+ if (ch === '"') inDouble = false;
13461
+ } else if (inSingle) {
13462
+ if (ch === "'") inSingle = false;
13463
+ } else if (ch === '"') {
13464
+ inDouble = true;
13465
+ atNameBoundary = false;
13466
+ } else if (ch === "'") {
13467
+ inSingle = true;
13468
+ atNameBoundary = false;
13469
+ } else if (ch === ">") {
13470
+ tagEnd = j5;
13471
+ break;
13472
+ } else if (ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "/") {
13473
+ atNameBoundary = true;
13474
+ } else {
13475
+ if (atNameBoundary && (ch === "$" || ch === ":" || ch === "@")) {
13476
+ return false;
13477
+ }
13478
+ atNameBoundary = false;
13479
+ }
13480
+ j5++;
13481
+ }
13482
+ if (tagEnd === -1) return false;
13483
+ i6 = tagEnd + 1;
13484
+ }
13485
+ return true;
13486
+ }
13487
+ __name(isStaticMarkup, "isStaticMarkup");
13283
13488
 
13284
13489
  // src/engine/AreHTML.context.ts
13285
13490
  var AreHTMLEngineContext = class extends AreContext {
@@ -13323,11 +13528,109 @@ var AreHTMLEngineContext = class extends AreContext {
13323
13528
  */
13324
13529
  elementListeners: /* @__PURE__ */ new WeakMap()
13325
13530
  };
13531
+ /**
13532
+ * Parsed-fragment cache for static islands (see AddStaticHTMLInstruction).
13533
+ *
13534
+ * Keyed by `hostTag\u0000markup`, each entry holds a `DocumentFragment` whose
13535
+ * children were parsed by the browser exactly once — in the *correct element
13536
+ * context* (the host tag), so table fragments (`<tr>`, `<td>`, …) and other
13537
+ * context-sensitive content parse correctly. Repeated static islands with
13538
+ * identical markup (e.g. list rows, reused components) clone the pre-parsed
13539
+ * fragment instead of re-parsing the HTML string on every mount — turning an
13540
+ * O(parse) operation into an O(clone) one.
13541
+ */
13542
+ this._staticFragmentCache = /* @__PURE__ */ new Map();
13543
+ /**
13544
+ * Live-DOM attachments deferred while a mount pass is batching.
13545
+ *
13546
+ * A freshly-mounted subtree is built inside a *detached* root element, so
13547
+ * every descendant `appendChild`/`insertBefore` happens off-document and
13548
+ * triggers zero layout/paint invalidation. The single mutation that actually
13549
+ * connects the built subtree to the live document is deferred and collected
13550
+ * here, then flushed once when the batch closes — collapsing O(nodes) reflows
13551
+ * into O(1) per mount root.
13552
+ */
13553
+ this._pendingAttachments = [];
13554
+ /**
13555
+ * Depth of the currently open batching scopes. Re-entrant so that nested
13556
+ * `beginBatch`/`endBatch` pairs flush exactly once, when the outermost scope
13557
+ * closes.
13558
+ */
13559
+ this._batchDepth = 0;
13326
13560
  this._container = props.container;
13327
13561
  }
13328
13562
  get container() {
13329
13563
  return this._container;
13330
13564
  }
13565
+ /**
13566
+ * `true` while a synchronous mount pass is batching live-DOM attachments.
13567
+ * Interpreter handlers consult this to decide whether to attach an element
13568
+ * immediately or hand the attachment to {@link deferAttach}.
13569
+ */
13570
+ get isBatching() {
13571
+ return this._batchDepth > 0;
13572
+ }
13573
+ /**
13574
+ * Opens a batching scope. Re-entrant: only the outermost matching
13575
+ * {@link endBatch} flushes the deferred attachments, so a single mount pass
13576
+ * connects its built subtree to the live DOM exactly once.
13577
+ */
13578
+ beginBatch() {
13579
+ this._batchDepth++;
13580
+ }
13581
+ /**
13582
+ * Registers a live-DOM attachment to run when the current batch flushes. If
13583
+ * no batch is active the attachment runs immediately, preserving the original
13584
+ * synchronous behaviour for updates that mount outside a batch.
13585
+ *
13586
+ * @param attach the DOM mutation that connects a built subtree to the document
13587
+ */
13588
+ deferAttach(attach) {
13589
+ if (this._batchDepth > 0) {
13590
+ this._pendingAttachments.push(attach);
13591
+ } else {
13592
+ attach();
13593
+ }
13594
+ }
13595
+ /**
13596
+ * Closes a batching scope. When the outermost scope closes, every deferred
13597
+ * attachment runs in registration (document) order, connecting the built
13598
+ * subtrees to the live DOM in a single pass.
13599
+ */
13600
+ endBatch() {
13601
+ if (this._batchDepth === 0) return;
13602
+ this._batchDepth--;
13603
+ if (this._batchDepth > 0) return;
13604
+ const pending = this._pendingAttachments;
13605
+ this._pendingAttachments = [];
13606
+ for (let i6 = 0; i6 < pending.length; i6++) {
13607
+ pending[i6]();
13608
+ }
13609
+ }
13610
+ /**
13611
+ * Returns a `DocumentFragment` containing the parsed form of `html`, parsed
13612
+ * once in the context of `hostTag` (so context-sensitive content such as
13613
+ * table rows/cells parses correctly) and cached thereafter. Callers should
13614
+ * `cloneNode(true)` the returned fragment rather than mutating it, so the
13615
+ * cache stays reusable.
13616
+ *
13617
+ * @param hostTag the tag name of the element the markup will be injected into
13618
+ * @param html verbatim static-island inner markup
13619
+ */
13620
+ getStaticFragment(hostTag, html) {
13621
+ const key = `${hostTag}\0${html}`;
13622
+ let fragment = this._staticFragmentCache.get(key);
13623
+ if (!fragment) {
13624
+ const container = this._container.createElement(hostTag);
13625
+ container.innerHTML = html;
13626
+ fragment = this._container.createDocumentFragment();
13627
+ while (container.firstChild) {
13628
+ fragment.appendChild(container.firstChild);
13629
+ }
13630
+ this._staticFragmentCache.set(key, fragment);
13631
+ }
13632
+ return fragment;
13633
+ }
13331
13634
  getNodeElement(node) {
13332
13635
  if (typeof node === "string") {
13333
13636
  return this.index.nodeToHostElements.get(node);
@@ -13463,6 +13766,9 @@ AreHTMLEngineContext = __decorateClass([
13463
13766
  var AreHTMLCompiler = class extends AreCompiler {
13464
13767
  compileHTMLNode(node, scene, logger, ...args) {
13465
13768
  super.compile(node, scene, logger, ...args);
13769
+ if (node.isStaticIsland && scene.host) {
13770
+ scene.plan(new AddStaticHTMLInstruction(scene.host, { html: node.staticInnerHTML }));
13771
+ }
13466
13772
  if (node.styles?.styles) {
13467
13773
  const host = scene.host;
13468
13774
  if (host) {
@@ -13660,12 +13966,15 @@ var AreHTMLInterpreter = class extends AreInterpreter {
13660
13966
  });
13661
13967
  }
13662
13968
  const element = isSVG ? context.container.createElementNS(SVG_NAMESPACE, tag) : context.container.createElement(tag);
13663
- if (mountPoint.nodeType === Node.ELEMENT_NODE) {
13664
- mountPoint.appendChild(element);
13665
- } else {
13969
+ context.setInstructionElement(declaration, element);
13970
+ const attach = mountPoint.nodeType === Node.ELEMENT_NODE ? () => mountPoint.appendChild(element) : () => {
13666
13971
  mountPoint.parentNode?.insertBefore(element, mountPoint);
13972
+ };
13973
+ if (context.isBatching && mountPoint.isConnected) {
13974
+ context.deferAttach(attach);
13975
+ } else {
13976
+ attach();
13667
13977
  }
13668
- context.setInstructionElement(declaration, element);
13669
13978
  } else {
13670
13979
  const mountPoint = context.container.getElementById(node.id);
13671
13980
  if (!mountPoint) {
@@ -13675,8 +13984,15 @@ var AreHTMLInterpreter = class extends AreInterpreter {
13675
13984
  });
13676
13985
  }
13677
13986
  const element = isSVG ? context.container.createElementNS(SVG_NAMESPACE, tag) : context.container.createElement(tag);
13678
- mountPoint.parentNode?.replaceChild(element, mountPoint);
13679
13987
  context.setInstructionElement(declaration, element);
13988
+ const attach = /* @__PURE__ */ __name(() => {
13989
+ mountPoint.parentNode?.replaceChild(element, mountPoint);
13990
+ }, "attach");
13991
+ if (context.isBatching && mountPoint.isConnected) {
13992
+ context.deferAttach(attach);
13993
+ } else {
13994
+ attach();
13995
+ }
13680
13996
  }
13681
13997
  logger?.debug("green", `Element ${node.aseid.toString()} added to Context:`);
13682
13998
  } catch (error) {
@@ -13686,7 +14002,7 @@ var AreHTMLInterpreter = class extends AreInterpreter {
13686
14002
  }
13687
14003
  removeElement(declaration, context) {
13688
14004
  const element = context.getElementByInstruction(declaration);
13689
- if (element && element.parentNode) {
14005
+ if (element && element.parentNode && element.isConnected) {
13690
14006
  element.parentNode.removeChild(element);
13691
14007
  }
13692
14008
  context.removeInstructionElement(declaration);
@@ -13789,7 +14105,7 @@ var AreHTMLInterpreter = class extends AreInterpreter {
13789
14105
  const element = context.getElementByInstruction(mutation.parent);
13790
14106
  if (!element) return;
13791
14107
  const { name } = mutation.payload;
13792
- if (name && element.nodeType === Node.ELEMENT_NODE) {
14108
+ if (name && element.nodeType === Node.ELEMENT_NODE && element.isConnected) {
13793
14109
  const colonIdx = name.indexOf(":");
13794
14110
  if (colonIdx > 0) {
13795
14111
  const ns = SVG_ATTRIBUTE_NS[name.slice(0, colonIdx)];
@@ -13816,6 +14132,7 @@ var AreHTMLInterpreter = class extends AreInterpreter {
13816
14132
  showElement(mutation, context) {
13817
14133
  const element = context.getElementByInstruction(mutation.parent);
13818
14134
  if (!element || element.nodeType !== Node.ELEMENT_NODE) return;
14135
+ if (!element.isConnected) return;
13819
14136
  const el = element;
13820
14137
  el.style.display = mutation.payload?.display ?? mutation.cache ?? "";
13821
14138
  }
@@ -13910,7 +14227,9 @@ var AreHTMLInterpreter = class extends AreInterpreter {
13910
14227
  const { event: eventName } = parseEventName(name);
13911
14228
  const listener = mutation.payload._callback;
13912
14229
  if (listener) {
13913
- element.removeEventListener(eventName, listener);
14230
+ if (element.isConnected) {
14231
+ element.removeEventListener(eventName, listener);
14232
+ }
13914
14233
  context.removeListener(element, name, listener);
13915
14234
  mutation.payload._callback = void 0;
13916
14235
  }
@@ -13948,9 +14267,32 @@ var AreHTMLInterpreter = class extends AreInterpreter {
13948
14267
  removeText(declaration, context) {
13949
14268
  const element = context.getElementByInstruction(declaration);
13950
14269
  if (!element) return;
13951
- element.parentNode?.removeChild(element);
14270
+ if (element.isConnected) {
14271
+ element.parentNode?.removeChild(element);
14272
+ }
13952
14273
  context.removeInstructionElement(declaration);
13953
14274
  }
14275
+ addStaticHTML(mutation, context, logger) {
14276
+ const element = context.getElementByInstruction(mutation.parent);
14277
+ if (!element || element.nodeType !== Node.ELEMENT_NODE) {
14278
+ throw new AreInterpreterError({
14279
+ title: "Element Not Found",
14280
+ description: `Could not find a DOM element associated with the instruction ASEID "${mutation.parent}". Ensure the host element is rendered before materialising its static island.`
14281
+ });
14282
+ }
14283
+ const el = element;
14284
+ const { html } = mutation.payload;
14285
+ el.textContent = "";
14286
+ const fragment = context.getStaticFragment(el.tagName.toLowerCase(), html);
14287
+ el.appendChild(fragment.cloneNode(true));
14288
+ logger?.debug("green", `Static island materialised onto <${(mutation.owner.parent ?? mutation.owner)?.aseid?.toString?.()}>`);
14289
+ }
14290
+ removeStaticHTML(mutation, context) {
14291
+ const element = context.getElementByInstruction(mutation.parent);
14292
+ if (element && element.nodeType === Node.ELEMENT_NODE && element.isConnected) {
14293
+ element.textContent = "";
14294
+ }
14295
+ }
13954
14296
  addComment(declaration, context, store, syntax, directiveContext, logger) {
13955
14297
  const node = declaration.owner.parent;
13956
14298
  const { content, evaluate } = declaration.payload;
@@ -13984,7 +14326,9 @@ var AreHTMLInterpreter = class extends AreInterpreter {
13984
14326
  removeComment(declaration, context) {
13985
14327
  const element = context.getElementByInstruction(declaration);
13986
14328
  if (!element) return;
13987
- element.parentNode?.removeChild(element);
14329
+ if (element.isConnected) {
14330
+ element.parentNode?.removeChild(element);
14331
+ }
13988
14332
  context.removeInstructionElement(declaration);
13989
14333
  }
13990
14334
  addStyle(mutation, context, logger) {
@@ -14129,6 +14473,24 @@ __decorateClass([
14129
14473
  __decorateParam(0, Yt(te)),
14130
14474
  __decorateParam(1, Yt(AreHTMLEngineContext))
14131
14475
  ], AreHTMLInterpreter.prototype, "removeText", 1);
14476
+ __decorateClass([
14477
+ R4.Define({
14478
+ description: "Inject a static island's inner markup onto its host element in one pass via a cached, browser-parsed <template> clone. Decodes HTML entities natively."
14479
+ }),
14480
+ AreInterpreter.Apply(AreHTMLInstructions.AddStaticHTML),
14481
+ AreInterpreter.Update(AreHTMLInstructions.AddStaticHTML),
14482
+ __decorateParam(0, Yt(te)),
14483
+ __decorateParam(1, Yt(AreHTMLEngineContext)),
14484
+ __decorateParam(2, Yt(A_Logger))
14485
+ ], AreHTMLInterpreter.prototype, "addStaticHTML", 1);
14486
+ __decorateClass([
14487
+ R4.Define({
14488
+ description: "Clear a static island's injected markup from its host element on revert."
14489
+ }),
14490
+ AreInterpreter.Revert(AreHTMLInstructions.AddStaticHTML),
14491
+ __decorateParam(0, Yt(te)),
14492
+ __decorateParam(1, Yt(AreHTMLEngineContext))
14493
+ ], AreHTMLInterpreter.prototype, "removeStaticHTML", 1);
14132
14494
  __decorateClass([
14133
14495
  R4.Define({
14134
14496
  description: "Add a comment node to the DOM based on the provided declaration instruction."
@@ -14182,7 +14544,12 @@ var AreHTMLTokenizer = class extends AreTokenizer {
14182
14544
  this.ATTR_PATTERN = /([$:@]?[\w.-]+(?::[\w.-]+)?)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/"'=]+)))?/g;
14183
14545
  }
14184
14546
  tokenize(node, context, logger) {
14185
- super.tokenize(node, context, logger);
14547
+ const isStaticIsland = node instanceof AreComponentNode && !!node.content && isStaticMarkup(node.content);
14548
+ if (isStaticIsland) {
14549
+ node.markStatic(node.content);
14550
+ } else {
14551
+ super.tokenize(node, context, logger);
14552
+ }
14186
14553
  context.startPerformance("attributeExtraction");
14187
14554
  const attributes = this.extractAttributes(node.markup);
14188
14555
  for (const attr of attributes) {
@@ -14262,46 +14629,39 @@ var AreHTMLLifecycle = class extends AreLifecycle {
14262
14629
  mount(node, scene, logger, ...args) {
14263
14630
  logger?.debug(`[Mount] Component Trigger for <${node.aseid.entity}> with aseid :{${node.aseid.toString()}}`);
14264
14631
  if (scene.isInactive) return;
14265
- node.interpret();
14266
- const stack = [];
14267
- for (let i6 = node.children.length - 1; i6 >= 0; i6--) {
14268
- stack.push({ node: node.children[i6], entered: false });
14269
- }
14270
- const step = /* @__PURE__ */ __name(() => {
14271
- const frame = stack[stack.length - 1];
14272
- const current = frame.node;
14273
- if (frame.entered) {
14274
- stack.pop();
14275
- current.call(AreNodeFeatures.onAfterMount, current.scope);
14276
- return;
14277
- }
14278
- frame.entered = true;
14279
- current.call(AreNodeFeatures.onBeforeMount, current.scope);
14280
- if (!current.scene.isInactive) {
14281
- current.interpret();
14282
- for (let i6 = current.children.length - 1; i6 >= 0; i6--) {
14283
- stack.push({ node: current.children[i6], entered: false });
14284
- }
14632
+ const context = node.scope.resolve(AreHTMLEngineContext);
14633
+ context?.beginBatch();
14634
+ const afterMountQueue = [];
14635
+ try {
14636
+ node.interpret();
14637
+ const stack = [];
14638
+ for (let i6 = node.children.length - 1; i6 >= 0; i6--) {
14639
+ stack.push({ node: node.children[i6], entered: false });
14285
14640
  }
14286
- }, "step");
14287
- const drive = /* @__PURE__ */ __name(() => {
14288
- const start = AreSchedulerHelper.now();
14289
14641
  while (stack.length > 0) {
14290
- step();
14291
- if (stack.length > 0 && AreSchedulerHelper.now() - start >= AreHTMLLifecycle.MOUNT_BUDGET_MS) {
14292
- return new Promise((resolve, reject) => {
14293
- AreSchedulerHelper.scheduleMacrotask(() => {
14294
- try {
14295
- resolve(drive());
14296
- } catch (error) {
14297
- reject(error);
14298
- }
14299
- });
14300
- });
14642
+ const frame = stack[stack.length - 1];
14643
+ const current = frame.node;
14644
+ if (frame.entered) {
14645
+ stack.pop();
14646
+ afterMountQueue.push(current);
14647
+ continue;
14648
+ }
14649
+ frame.entered = true;
14650
+ current.call(AreNodeFeatures.onBeforeMount, current.scope);
14651
+ if (!current.scene.isInactive) {
14652
+ current.interpret();
14653
+ for (let i6 = current.children.length - 1; i6 >= 0; i6--) {
14654
+ stack.push({ node: current.children[i6], entered: false });
14655
+ }
14301
14656
  }
14302
14657
  }
14303
- }, "drive");
14304
- return drive();
14658
+ } finally {
14659
+ context?.endBatch();
14660
+ }
14661
+ for (let i6 = 0; i6 < afterMountQueue.length; i6++) {
14662
+ const mounted = afterMountQueue[i6];
14663
+ mounted.call(AreNodeFeatures.onAfterMount, mounted.scope);
14664
+ }
14305
14665
  }
14306
14666
  updateDirectiveAttribute(directive, scope, feature, logger, ...args) {
14307
14667
  if (directive.component) {
@@ -14312,13 +14672,6 @@ var AreHTMLLifecycle = class extends AreLifecycle {
14312
14672
  }
14313
14673
  };
14314
14674
  __name(AreHTMLLifecycle, "AreHTMLLifecycle");
14315
- /**
14316
- * Per-chunk time budget (ms) for the time-sliced initial mount walk. While
14317
- * mounting a large subtree we keep applying nodes until this much wall-clock
14318
- * time has elapsed, then yield to the browser so it can paint and process
14319
- * input before the next chunk. ~16ms targets a single animation frame.
14320
- */
14321
- AreHTMLLifecycle.MOUNT_BUDGET_MS = 16;
14322
14675
  __decorateClass([
14323
14676
  AreLifecycle.Init(AreComponentNode),
14324
14677
  __decorateParam(0, Yt(te)),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaas/are-html",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "description": "A-Concept Rendering Engine (ARE) is a powerful rendering engine designed to work seamlessly with the A-Concept framework. This library provides an HTML engine implementation of ARE, enabling developers to create dynamic and interactive user interfaces for web applications using standard HTML syntax.",
5
5
  "keywords": [
6
6
  "a-concept",
@@ -84,15 +84,15 @@
84
84
  },
85
85
  "peerDependencies": {
86
86
  "@adaas/a-concept": "^0.3.29",
87
- "@adaas/a-frame": "^0.1.17",
87
+ "@adaas/a-frame": "^0.1.18",
88
88
  "@adaas/a-utils": "^0.3.34",
89
- "@adaas/are": "^0.0.23"
89
+ "@adaas/are": "^0.0.24"
90
90
  },
91
91
  "devDependencies": {
92
92
  "@adaas/a-concept": "^0.3.29",
93
- "@adaas/a-frame": "^0.1.17",
93
+ "@adaas/a-frame": "^0.1.18",
94
94
  "@adaas/a-utils": "^0.3.34",
95
- "@adaas/are": "^0.0.23",
95
+ "@adaas/are": "^0.0.24",
96
96
  "@types/chai": "^4.3.14",
97
97
  "@types/jest": "^29.5.12",
98
98
  "@types/mocha": "^10.0.6",