marko 4.28.0 → 4.28.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -480,6 +480,7 @@ class CustomTag extends HtmlElement {
480
480
  let tagVar = codegen.addStaticVar(tagVarName, loadTag);
481
481
 
482
482
  renderTagNode = this.generateRenderTagCode(codegen, tagVar, [inputProps, builder.identifierOut()]);
483
+ renderTagNode._isTagCall = true;
483
484
  } else {
484
485
  if (rendererRequirePath) {
485
486
  codegen.pushMeta("tags", rendererRequirePath, true);
@@ -516,8 +517,10 @@ class CustomTag extends HtmlElement {
516
517
 
517
518
  if (isNestedTag) {
518
519
  renderTagNode = builder.functionCall(tagVar, tagArgs);
520
+ renderTagNode._isNestedTagCall = true;
519
521
  } else {
520
522
  renderTagNode = this.generateRenderTagCode(codegen, tagVar, tagArgs);
523
+ renderTagNode._isTagCall = true;
521
524
  }
522
525
  }
523
526
 
@@ -533,10 +536,22 @@ class CustomTag extends HtmlElement {
533
536
  let renderBodyFunction;
534
537
 
535
538
  if (hasBody) {
536
- if (this._mergedRenderBodyStart !== undefined) {
537
- const mergedRenderBody = builder.renderBodyFunction(body.slice(this._mergedRenderBodyStart));
538
- body = body.slice(0, this._mergedRenderBodyStart);
539
- body.push(builder.returnStatement(mergedRenderBody));
539
+ if (this._hasDynamicNestedTags) {
540
+ const renderBody = [];
541
+ const newBody = [];
542
+
543
+ for (const child of body) {
544
+ if (hasHTML(child, context)) {
545
+ renderBody.push(child);
546
+ } else {
547
+ newBody.push(child);
548
+ }
549
+ }
550
+
551
+ if (renderBody.length) {
552
+ newBody.push(builder.returnStatement(builder.renderBodyFunction(renderBody)));
553
+ body = newBody;
554
+ }
540
555
  }
541
556
 
542
557
  if (tagDef.bodyFunction) {
@@ -625,27 +640,7 @@ class CustomTag extends HtmlElement {
625
640
  return null;
626
641
  } else {
627
642
  this._isDirectlyNestedTag = false;
628
-
629
- if (!parentCustomTag._hasDynamicNestedTags) {
630
- parentCustomTag._hasDynamicNestedTags = true;
631
-
632
- let nextBodyContent = parentCustomTag.firstChild;
633
- let i = 0;
634
-
635
- do {
636
- if (nextBodyContent.type === "Text" || nextBodyContent.type === "Scriptlet" || (nextBodyContent.type === "HtmlElement" || nextBodyContent.type === "CustomTag") && !(nextBodyContent.tagDef && (nextBodyContent.tagDef.isNestedTag || nextBodyContent.tagDef.codeGeneratorModulePath))) {
637
- parentCustomTag._mergedRenderBodyStart = i;
638
- break;
639
- }
640
-
641
- nextBodyContent = nextBodyContent.nextSibling;
642
- i++;
643
- } while (nextBodyContent);
644
-
645
- if (!i) {
646
- context.addError(parentCustomTag, "Render body content must come after any dynamic nested attribute tags.");
647
- }
648
- }
643
+ parentCustomTag._hasDynamicNestedTags = true;
649
644
  }
650
645
  }
651
646
 
@@ -660,4 +655,21 @@ class CustomTag extends HtmlElement {
660
655
  }
661
656
  }
662
657
 
658
+ function hasHTML(node, context) {
659
+ let hasHTML = false;
660
+ const walker = context.createWalker({
661
+ enter(node) {
662
+ if (node.type === "Html" || node.type === "TextVDOM" || node._isTagCall) {
663
+ hasHTML = true;
664
+ walker.stop();
665
+ } else if (node._isNestedTagCall) {
666
+ walker.skip();
667
+ }
668
+ }
669
+ });
670
+
671
+ walker.walk(node);
672
+ return hasHTML;
673
+ }
674
+
663
675
  module.exports = CustomTag;
@@ -219,8 +219,12 @@ function morphdom(fromNode, toNode, host, componentsContext) {
219
219
  if (!curToNodeChild.ae_) {
220
220
  // We just skip over the fromNode if it is preserved
221
221
 
222
- if (compareNodeNames(curToNodeChild, curVFromNodeChild)) {
223
- morphEl(curFromNodeChild, curVFromNodeChild, curToNodeChild, parentComponent);
222
+ if (curVFromNodeChild && curToNodeType === curVFromNodeChild.bX_ && (curToNodeType !== ELEMENT_NODE || compareNodeNames(curToNodeChild, curVFromNodeChild))) {
223
+ if (curToNodeType === ELEMENT_NODE) {
224
+ morphEl(curFromNodeChild, curVFromNodeChild, curToNodeChild, parentComponent);
225
+ } else {
226
+ morphChildren(curFromNodeChild, curToNodeChild, parentComponent);
227
+ }
224
228
  } else {
225
229
  // Remove the old node
226
230
  detachNode(curFromNodeChild, fromNode, ownerComponent);
@@ -300,7 +304,7 @@ function morphdom(fromNode, toNode, host, componentsContext) {
300
304
  if (!curToNodeChild.ae_) {
301
305
  curVFromNodeChild = vElementByDOMNode.get(matchingFromEl);
302
306
 
303
- if (compareNodeNames(curVFromNodeChild, curToNodeChild)) {
307
+ if (curVFromNodeChild && curToNodeType === curVFromNodeChild.bX_ && (curToNodeType !== ELEMENT_NODE || compareNodeNames(curVFromNodeChild, curToNodeChild))) {
304
308
  if (fromNextSibling === matchingFromEl) {
305
309
  // Single element removal:
306
310
  // A <-> A
@@ -348,7 +352,11 @@ function morphdom(fromNode, toNode, host, componentsContext) {
348
352
  }
349
353
  }
350
354
 
351
- morphEl(matchingFromEl, curVFromNodeChild, curToNodeChild, parentComponent);
355
+ if (curToNodeType === ELEMENT_NODE) {
356
+ morphEl(matchingFromEl, curVFromNodeChild, curToNodeChild, parentComponent);
357
+ } else {
358
+ morphChildren(matchingFromEl, curToNodeChild, parentComponent);
359
+ }
352
360
  } else {
353
361
  insertVirtualNodeBefore(curToNodeChild, curToNodeKey, curFromNodeChild, fromNode, ownerComponent, parentComponent);
354
362
  detachNode(matchingFromEl, fromNode, ownerComponent);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marko",
3
- "version": "4.28.0",
3
+ "version": "4.28.1",
4
4
  "license": "MIT",
5
5
  "description": "UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.",
6
6
  "dependencies": {
@@ -560,6 +560,7 @@ class CustomTag extends HtmlElement {
560
560
  inputProps,
561
561
  builder.identifierOut(),
562
562
  ]);
563
+ renderTagNode._isTagCall = true;
563
564
  } else {
564
565
  if (rendererRequirePath) {
565
566
  codegen.pushMeta("tags", rendererRequirePath, true);
@@ -623,8 +624,10 @@ class CustomTag extends HtmlElement {
623
624
 
624
625
  if (isNestedTag) {
625
626
  renderTagNode = builder.functionCall(tagVar, tagArgs);
627
+ renderTagNode._isNestedTagCall = true
626
628
  } else {
627
629
  renderTagNode = this.generateRenderTagCode(codegen, tagVar, tagArgs);
630
+ renderTagNode._isTagCall = true;
628
631
  }
629
632
  }
630
633
 
@@ -640,12 +643,22 @@ class CustomTag extends HtmlElement {
640
643
  let renderBodyFunction;
641
644
 
642
645
  if (hasBody) {
643
- if (this._mergedRenderBodyStart !== undefined) {
644
- const mergedRenderBody = builder.renderBodyFunction(
645
- body.slice(this._mergedRenderBodyStart)
646
- );
647
- body = body.slice(0, this._mergedRenderBodyStart);
648
- body.push(builder.returnStatement(mergedRenderBody));
646
+ if (this._hasDynamicNestedTags) {
647
+ const renderBody = [];
648
+ const newBody = [];
649
+
650
+ for (const child of body) {
651
+ if (hasHTML(child, context)) {
652
+ renderBody.push(child);
653
+ } else {
654
+ newBody.push(child);
655
+ }
656
+ }
657
+
658
+ if (renderBody.length) {
659
+ newBody.push(builder.returnStatement(builder.renderBodyFunction(renderBody)));
660
+ body = newBody;
661
+ }
649
662
  }
650
663
 
651
664
  if (tagDef.bodyFunction) {
@@ -756,40 +769,7 @@ class CustomTag extends HtmlElement {
756
769
  return null;
757
770
  } else {
758
771
  this._isDirectlyNestedTag = false;
759
-
760
- if (!parentCustomTag._hasDynamicNestedTags) {
761
- parentCustomTag._hasDynamicNestedTags = true;
762
-
763
- let nextBodyContent = parentCustomTag.firstChild;
764
- let i = 0;
765
-
766
- do {
767
- if (
768
- nextBodyContent.type === "Text" ||
769
- nextBodyContent.type === "Scriptlet" ||
770
- ((nextBodyContent.type === "HtmlElement" ||
771
- nextBodyContent.type === "CustomTag") &&
772
- !(
773
- nextBodyContent.tagDef &&
774
- (nextBodyContent.tagDef.isNestedTag ||
775
- nextBodyContent.tagDef.codeGeneratorModulePath)
776
- ))
777
- ) {
778
- parentCustomTag._mergedRenderBodyStart = i;
779
- break;
780
- }
781
-
782
- nextBodyContent = nextBodyContent.nextSibling;
783
- i++;
784
- } while (nextBodyContent);
785
-
786
- if (!i) {
787
- context.addError(
788
- parentCustomTag,
789
- "Render body content must come after any dynamic nested attribute tags."
790
- );
791
- }
792
- }
772
+ parentCustomTag._hasDynamicNestedTags = true;
793
773
  }
794
774
  }
795
775
 
@@ -812,4 +792,21 @@ class CustomTag extends HtmlElement {
812
792
  }
813
793
  }
814
794
 
795
+ function hasHTML(node, context) {
796
+ let hasHTML = false;
797
+ const walker = context.createWalker({
798
+ enter(node) {
799
+ if (node.type === "Html" || node.type === "TextVDOM" || node._isTagCall) {
800
+ hasHTML = true;
801
+ walker.stop();
802
+ } else if (node._isNestedTagCall) {
803
+ walker.skip();
804
+ }
805
+ },
806
+ });
807
+
808
+ walker.walk(node);
809
+ return hasHTML;
810
+ }
811
+
815
812
  module.exports = CustomTag;
@@ -281,13 +281,26 @@ function morphdom(fromNode, toNode, host, componentsContext) {
281
281
  if (!curToNodeChild.___preserve) {
282
282
  // We just skip over the fromNode if it is preserved
283
283
 
284
- if (compareNodeNames(curToNodeChild, curVFromNodeChild)) {
285
- morphEl(
286
- curFromNodeChild,
287
- curVFromNodeChild,
288
- curToNodeChild,
289
- parentComponent
290
- );
284
+ if (
285
+ curVFromNodeChild &&
286
+ curToNodeType === curVFromNodeChild.___nodeType &&
287
+ (curToNodeType !== ELEMENT_NODE ||
288
+ compareNodeNames(curToNodeChild, curVFromNodeChild))
289
+ ) {
290
+ if (curToNodeType === ELEMENT_NODE) {
291
+ morphEl(
292
+ curFromNodeChild,
293
+ curVFromNodeChild,
294
+ curToNodeChild,
295
+ parentComponent,
296
+ );
297
+ } else {
298
+ morphChildren(
299
+ curFromNodeChild,
300
+ curToNodeChild,
301
+ parentComponent,
302
+ );
303
+ }
291
304
  } else {
292
305
  // Remove the old node
293
306
  detachNode(curFromNodeChild, fromNode, ownerComponent);
@@ -404,7 +417,12 @@ function morphdom(fromNode, toNode, host, componentsContext) {
404
417
  if (!curToNodeChild.___preserve) {
405
418
  curVFromNodeChild = vElementByDOMNode.get(matchingFromEl);
406
419
 
407
- if (compareNodeNames(curVFromNodeChild, curToNodeChild)) {
420
+ if (
421
+ curVFromNodeChild &&
422
+ curToNodeType === curVFromNodeChild.___nodeType &&
423
+ (curToNodeType !== ELEMENT_NODE ||
424
+ compareNodeNames(curVFromNodeChild, curToNodeChild))
425
+ ) {
408
426
  if (fromNextSibling === matchingFromEl) {
409
427
  // Single element removal:
410
428
  // A <-> A
@@ -455,12 +473,21 @@ function morphdom(fromNode, toNode, host, componentsContext) {
455
473
  }
456
474
  }
457
475
 
458
- morphEl(
459
- matchingFromEl,
460
- curVFromNodeChild,
461
- curToNodeChild,
462
- parentComponent
463
- );
476
+ if (curToNodeType === ELEMENT_NODE) {
477
+ morphEl(
478
+ matchingFromEl,
479
+ curVFromNodeChild,
480
+ curToNodeChild,
481
+ parentComponent
482
+ );
483
+ } else {
484
+ morphChildren(
485
+ matchingFromEl,
486
+ curToNodeChild,
487
+ parentComponent,
488
+ );
489
+ }
490
+
464
491
  } else {
465
492
  insertVirtualNodeBefore(
466
493
  curToNodeChild,