babel-plugin-jsx-dom-expressions 0.32.11 → 0.33.0

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 (2) hide show
  1. package/index.js +956 -863
  2. package/package.json +4 -4
package/index.js CHANGED
@@ -223,18 +223,29 @@ function getConfig(path) {
223
223
  return path.hub.file.metadata.config;
224
224
  }
225
225
 
226
- function registerImportMethod(path, name) {
226
+ const getRendererConfig = (path, renderer) => {
227
+ const config = getConfig(path);
228
+ return config?.renderers?.find(r => r.name === renderer) ?? config;
229
+ };
230
+
231
+ function registerImportMethod(path, name, moduleName) {
227
232
  const imports =
228
233
  path.scope.getProgramParent().data.imports ||
229
- (path.scope.getProgramParent().data.imports = new Set());
230
- const identifier = t__namespace.identifier(`_$${name}`);
231
- if (!imports.has(name)) {
232
- helperModuleImports.addNamed(path, name, getConfig(path).moduleName, {
234
+ (path.scope.getProgramParent().data.imports = new Map());
235
+ moduleName = moduleName || getConfig(path).moduleName;
236
+ if (!imports.has(`${moduleName}:${name}`)) {
237
+ let id = helperModuleImports.addNamed(path, name, moduleName, {
233
238
  nameHint: `_$${name}`
234
239
  });
235
- imports.add(name);
240
+ imports.set(`${moduleName}:${name}`, id);
241
+ return id;
242
+ } else {
243
+ let iden = imports.get(`${moduleName}:${name}`);
244
+ // the cloning is required to play well with babel-preset-env which is
245
+ // transpiling import as we add them and using the same identifier causes
246
+ // problems with the multiple identifiers of the same thing
247
+ return t__namespace.cloneDeep(iden);
236
248
  }
237
- return identifier;
238
249
  }
239
250
 
240
251
  function jsxElementNameToString(node) {
@@ -317,6 +328,7 @@ function getStaticExpression(path) {
317
328
  t__namespace.isJSXExpressionContainer(node) &&
318
329
  t__namespace.isJSXElement(path.parent) &&
319
330
  !isComponent(getTagName(path.parent)) &&
331
+ !t__namespace.isSequenceExpression(node.expression) &&
320
332
  (value = path.get("expression").evaluate().value) !== undefined &&
321
333
  ((type = typeof value) === "string" || type === "number") &&
322
334
  value
@@ -404,10 +416,7 @@ function transformCondition(path, inline, deep) {
404
416
  if (!t__namespace.isBinaryExpression(cond))
405
417
  cond = t__namespace.unaryExpression("!", t__namespace.unaryExpression("!", cond, true), true);
406
418
  id = inline
407
- ? t__namespace.callExpression(memo, [
408
- t__namespace.arrowFunctionExpression([], cond),
409
- t__namespace.booleanLiteral(true)
410
- ])
419
+ ? t__namespace.callExpression(memo, [t__namespace.arrowFunctionExpression([], cond), t__namespace.booleanLiteral(true)])
411
420
  : path.scope.generateUidIdentifier("_c$");
412
421
  expr.test = t__namespace.callExpression(id, []);
413
422
  if (t__namespace.isConditionalExpression(expr.consequent) || t__namespace.isLogicalExpression(expr.consequent)) {
@@ -433,10 +442,7 @@ function transformCondition(path, inline, deep) {
433
442
  if (!t__namespace.isBinaryExpression(cond))
434
443
  cond = t__namespace.unaryExpression("!", t__namespace.unaryExpression("!", cond, true), true);
435
444
  id = inline
436
- ? t__namespace.callExpression(memo, [
437
- t__namespace.arrowFunctionExpression([], cond),
438
- t__namespace.booleanLiteral(true)
439
- ])
445
+ ? t__namespace.callExpression(memo, [t__namespace.arrowFunctionExpression([], cond), t__namespace.booleanLiteral(true)])
440
446
  : path.scope.generateUidIdentifier("_c$");
441
447
  nextPath.node.left = t__namespace.callExpression(id, []);
442
448
  }
@@ -447,10 +453,7 @@ function transformCondition(path, inline, deep) {
447
453
  t__namespace.variableDeclarator(
448
454
  id,
449
455
  config.memoWrapper
450
- ? t__namespace.callExpression(memo, [
451
- t__namespace.arrowFunctionExpression([], cond),
452
- t__namespace.booleanLiteral(true)
453
- ])
456
+ ? t__namespace.callExpression(memo, [t__namespace.arrowFunctionExpression([], cond), t__namespace.booleanLiteral(true)])
454
457
  : t__namespace.arrowFunctionExpression([], cond)
455
458
  )
456
459
  ]),
@@ -518,744 +521,774 @@ function escapeHTML(s, attr) {
518
521
  return left < s.length ? out + s.substring(left) : out;
519
522
  }
520
523
 
521
- function transformElement$2(path, info) {
522
- let tagName = getTagName(path.node),
523
- config = getConfig(path),
524
- wrapSVG = info.topLevel && tagName != "svg" && SVGElements.has(tagName),
525
- voidTag = VoidElements.indexOf(tagName) > -1,
526
- results = {
527
- template: `<${tagName}`,
528
- decl: [],
529
- exprs: [],
530
- dynamics: [],
531
- postExprs: [],
532
- isSVG: wrapSVG,
533
- tagName
534
- };
535
- if (tagName === "html" && config.hydratable) results.skipTemplate = true;
536
- if (wrapSVG) results.template = "<svg>" + results.template;
537
- if (!info.skipId) results.id = path.scope.generateUidIdentifier("el$");
538
- transformAttributes$2(path, results);
539
- if (config.contextToCustomElements && (tagName === "slot" || tagName.indexOf("-") > -1)) {
540
- contextToCustomElement(path, results);
541
- }
542
- results.template += ">";
543
- if (!voidTag) {
544
- transformChildren$2(path, results, config);
545
- results.template += `</${tagName}>`;
546
- }
547
- if (info.topLevel && config.hydratable && results.hasHydratableEvent) {
548
- results.postExprs.push(
549
- t__namespace.expressionStatement(t__namespace.callExpression(registerImportMethod(path, "runHydrationEvents"), []))
550
- );
551
- }
552
- if (wrapSVG) results.template += "</svg>";
553
- return results;
554
- }
555
-
556
- function setAttr$2(path, elem, name, value, { isSVG, dynamic, prevId, isCE }) {
557
- // pull out namespace
558
- const config = getConfig(path);
559
- let parts, namespace;
560
- if ((parts = name.split(":")) && parts[1] && reservedNameSpaces.has(parts[0])) {
561
- name = parts[1];
562
- namespace = parts[0];
563
- }
564
-
565
- if (namespace === "style") {
566
- return t__namespace.callExpression(
567
- t__namespace.memberExpression(
568
- t__namespace.memberExpression(elem, t__namespace.identifier("style")),
569
- t__namespace.identifier("setProperty")
570
- ),
571
- [t__namespace.stringLiteral(name), value]
572
- );
573
- }
574
-
575
- if (namespace === "class") {
576
- return t__namespace.callExpression(
577
- t__namespace.memberExpression(
578
- t__namespace.memberExpression(elem, t__namespace.identifier("classList")),
579
- t__namespace.identifier("toggle")
580
- ),
581
- [t__namespace.stringLiteral(name), value]
582
- );
583
- }
584
-
585
- if (name === "style") {
586
- return t__namespace.callExpression(
587
- registerImportMethod(path, "style"),
588
- prevId ? [elem, value, prevId] : [elem, value]
589
- );
590
- }
591
-
592
- if (!isSVG && name === "class") {
593
- return t__namespace.assignmentExpression("=", t__namespace.memberExpression(elem, t__namespace.identifier("className")), value);
594
- }
595
-
596
- if (name === "classList") {
597
- return t__namespace.callExpression(
598
- registerImportMethod(path, "classList"),
599
- prevId ? [elem, value, prevId] : [elem, value]
600
- );
601
- }
602
-
603
- if (config.hydratable && name === "innerHTML") {
604
- return t__namespace.callExpression(
605
- registerImportMethod(path, "innerHTML"),
606
- [elem, value]
607
- );
608
- }
609
-
610
- if (dynamic && name === "textContent") {
611
- return t__namespace.assignmentExpression("=", t__namespace.memberExpression(elem, t__namespace.identifier("data")), value);
612
- }
613
-
614
- const isChildProp = ChildProperties.has(name);
615
- const isProp = Properties.has(name);
616
- const alias = PropAliases[name];
617
- if (namespace !== "attr" && (isChildProp || (!isSVG && isProp) || isCE || namespace === "prop")) {
618
- if (isCE && !isChildProp && !isProp && namespace !== "prop") name = toPropertyName(name);
619
- return t__namespace.assignmentExpression(
620
- "=",
621
- t__namespace.memberExpression(elem, t__namespace.identifier(alias || name)),
622
- value
623
- );
624
- }
625
-
626
- let isNameSpaced = name.indexOf(":") > -1;
627
- name = Aliases[name] || name;
628
- !isSVG && (name = name.toLowerCase());
629
- const ns = isNameSpaced && SVGNamespace[name.split(":")[0]];
630
- if (ns) {
631
- return t__namespace.callExpression(registerImportMethod(path, "setAttributeNS"), [
632
- elem,
633
- t__namespace.stringLiteral(ns),
634
- t__namespace.stringLiteral(name),
635
- value
636
- ]);
637
- } else {
638
- return t__namespace.callExpression(registerImportMethod(path, "setAttribute"), [elem, t__namespace.stringLiteral(name), value]);
639
- }
640
- }
641
-
642
- function detectResolvableEventHandler(attribute, handler) {
643
- while (t__namespace.isIdentifier(handler)) {
644
- const lookup = attribute.scope.getBinding(handler.name);
645
- if (lookup) {
646
- if (t__namespace.isVariableDeclarator(lookup.path.node)) {
647
- handler = lookup.path.node.init;
648
- } else if (t__namespace.isFunctionDeclaration(lookup.path.node)) {
649
- return true;
650
- } else return false;
651
- } else return false;
652
- }
653
- return t__namespace.isFunction(handler);
654
- }
655
-
656
- function transformAttributes$2(path, results) {
657
- let elem = results.id,
658
- hasHydratableEvent = false,
659
- children,
660
- attributes = path.get("openingElement").get("attributes");
661
- const tagName = getTagName(path.node),
662
- isSVG = SVGElements.has(tagName),
663
- isCE = tagName.includes("-"),
664
- hasChildren = path.node.children.length > 0,
665
- config = getConfig(path);
666
-
667
- // preprocess styles
668
- const styleAttribute = attributes.find(
669
- a =>
670
- a.node.name &&
671
- a.node.name.name === "style" &&
672
- t__namespace.isJSXExpressionContainer(a.node.value) &&
673
- t__namespace.isObjectExpression(a.node.value.expression) &&
674
- !a.node.value.expression.properties.some(p => t__namespace.isSpreadElement(p))
675
- );
676
- if (styleAttribute) {
677
- let i = 0,
678
- leading = styleAttribute.node.value.expression.leadingComments;
679
- styleAttribute.node.value.expression.properties.slice().forEach((p, index) => {
680
- if (!p.computed) {
681
- if (leading) p.value.leadingComments = leading;
682
- path
683
- .get("openingElement")
684
- .node.attributes.splice(
685
- styleAttribute.key + ++i,
686
- 0,
687
- t__namespace.JSXAttribute(
688
- t__namespace.JSXNamespacedName(
689
- t__namespace.JSXIdentifier("style"),
690
- t__namespace.JSXIdentifier(t__namespace.isIdentifier(p.key) ? p.key.name : p.key.value)
691
- ),
692
- t__namespace.JSXExpressionContainer(p.value)
693
- )
694
- );
695
- styleAttribute.node.value.expression.properties.splice(index - i - 1, 1);
696
- }
697
- });
698
- if (!styleAttribute.node.value.expression.properties.length)
699
- path.get("openingElement").node.attributes.splice(styleAttribute.key, 1);
700
- }
701
-
702
- // preprocess classList
703
- attributes = path.get("openingElement").get("attributes");
704
- const classListAttribute = attributes.find(
705
- a =>
706
- a.node.name &&
707
- a.node.name.name === "classList" &&
708
- t__namespace.isJSXExpressionContainer(a.node.value) &&
709
- t__namespace.isObjectExpression(a.node.value.expression) &&
710
- !a.node.value.expression.properties.some(
711
- p =>
712
- t__namespace.isSpreadElement(p) ||
713
- p.computed ||
714
- (t__namespace.isStringLiteral(p.key) && (p.key.value.includes(" ") || p.key.value.includes(":")))
715
- )
716
- );
717
- if (classListAttribute) {
718
- let i = 0,
719
- leading = classListAttribute.node.value.expression.leadingComments,
720
- classListProperties = classListAttribute.get("value").get("expression").get("properties");
721
- classListProperties.slice().forEach((propPath, index) => {
722
- const p = propPath.node;
723
- const { confident, value: computed } = propPath.get("value").evaluate();
724
- if (leading) p.value.leadingComments = leading;
725
- if (!confident) {
726
- path
727
- .get("openingElement")
728
- .node.attributes.splice(
729
- classListAttribute.key + ++i,
730
- 0,
731
- t__namespace.JSXAttribute(
732
- t__namespace.JSXNamespacedName(
733
- t__namespace.JSXIdentifier("class"),
734
- t__namespace.JSXIdentifier(t__namespace.isIdentifier(p.key) ? p.key.name : p.key.value)
735
- ),
736
- t__namespace.JSXExpressionContainer(p.value)
737
- )
738
- );
739
- } else if (computed) {
740
- path
741
- .get("openingElement")
742
- .node.attributes.splice(
743
- classListAttribute.key + ++i,
744
- 0,
745
- t__namespace.JSXAttribute(
746
- t__namespace.JSXIdentifier("class"),
747
- t__namespace.stringLiteral(t__namespace.isIdentifier(p.key) ? p.key.name : p.key.value)
748
- )
749
- );
750
- }
751
- classListProperties.splice(index - i - 1, 1);
752
- });
753
- if (!classListProperties.length)
754
- path.get("openingElement").node.attributes.splice(classListAttribute.key, 1);
755
- }
756
-
757
- // combine class properties
758
- attributes = path.get("openingElement").get("attributes");
759
- const classAttributes = attributes.filter(
760
- a => a.node.name && (a.node.name.name === "class" || a.node.name.name === "className")
761
- );
762
- if (classAttributes.length > 1) {
763
- const first = classAttributes[0].node,
764
- values = [],
765
- quasis = [t__namespace.TemplateElement({ raw: "" })];
766
- for (let i = 0; i < classAttributes.length; i++) {
767
- const attr = classAttributes[i].node,
768
- isLast = i === classAttributes.length - 1;
769
- if (!t__namespace.isJSXExpressionContainer(attr.value)) {
770
- const prev = quasis.pop();
771
- quasis.push(
772
- t__namespace.TemplateElement({
773
- raw: (prev ? prev.value.raw : "") + `${attr.value.value}` + (isLast ? "" : " ")
774
- })
775
- );
776
- } else {
777
- values.push(t__namespace.logicalExpression("||", attr.value.expression, t__namespace.stringLiteral("")));
778
- quasis.push(t__namespace.TemplateElement({ raw: isLast ? "" : " " }));
779
- }
780
- i && attributes.splice(attributes.indexOf(classAttributes[i]), 1);
781
- }
782
- if (values.length) first.value = t__namespace.JSXExpressionContainer(t__namespace.TemplateLiteral(quasis, values));
783
- else first.value = t__namespace.stringLiteral(quasis[0].value.raw);
784
- }
785
- path.get("openingElement").set(
786
- "attributes",
787
- attributes.map(a => a.node)
788
- );
789
-
790
- path
791
- .get("openingElement")
792
- .get("attributes")
793
- .forEach(attribute => {
794
- const node = attribute.node;
795
- if (t__namespace.isJSXSpreadAttribute(node)) {
796
- results.exprs.push(
797
- t__namespace.expressionStatement(
798
- t__namespace.callExpression(registerImportMethod(attribute, "spread"), [
799
- elem,
800
- isDynamic(attribute.get("argument"), {
801
- checkMember: true
802
- })
803
- ? t__namespace.isCallExpression(node.argument) && !node.argument.arguments.length
804
- ? node.argument.callee
805
- : t__namespace.arrowFunctionExpression([], node.argument)
806
- : node.argument,
807
- t__namespace.booleanLiteral(isSVG),
808
- t__namespace.booleanLiteral(hasChildren)
809
- ])
810
- )
811
- );
812
- //NOTE: can't be checked at compile time so add to compiled output
813
- hasHydratableEvent = true;
814
- return;
815
- }
816
-
817
- let value = node.value,
818
- key = t__namespace.isJSXNamespacedName(node.name)
819
- ? `${node.name.namespace.name}:${node.name.name.name}`
820
- : node.name.name,
821
- reservedNameSpace =
822
- t__namespace.isJSXNamespacedName(node.name) && reservedNameSpaces.has(node.name.namespace.name);
823
- if (t__namespace.isJSXExpressionContainer(value) && !key.startsWith("use:")) {
824
- const evaluated = attribute.get("value").get("expression").evaluate().value;
825
- let type;
826
- if (
827
- evaluated !== undefined &&
828
- ((type = typeof evaluated) === "string" || type === "number")
829
- ) {
830
- value = t__namespace.stringLiteral(String(evaluated));
831
- }
832
- }
833
- if (
834
- t__namespace.isJSXNamespacedName(node.name) &&
835
- reservedNameSpace &&
836
- !t__namespace.isJSXExpressionContainer(value)
837
- ) {
838
- node.value = value = t__namespace.JSXExpressionContainer(value || t__namespace.JSXEmptyExpression());
839
- }
840
- if (
841
- t__namespace.isJSXExpressionContainer(value) &&
842
- (reservedNameSpace ||
843
- !(t__namespace.isStringLiteral(value.expression) || t__namespace.isNumericLiteral(value.expression)))
844
- ) {
845
- if (key === "ref") {
846
- // Normalize expressions for non-null and type-as
847
- while (
848
- t__namespace.isTSNonNullExpression(value.expression) ||
849
- t__namespace.isTSAsExpression(value.expression)
850
- ) {
851
- value.expression = value.expression.expression;
852
- }
853
- let binding,
854
- isFunction =
855
- t__namespace.isIdentifier(value.expression) &&
856
- (binding = path.scope.getBinding(value.expression.name)) &&
857
- binding.kind === "const";
858
- if (!isFunction && t__namespace.isLVal(value.expression)) {
859
- const refIdentifier = path.scope.generateUidIdentifier("_ref$");
860
- results.exprs.unshift(
861
- t__namespace.variableDeclaration("const", [
862
- t__namespace.variableDeclarator(refIdentifier, value.expression)
863
- ]),
864
- t__namespace.expressionStatement(
865
- t__namespace.conditionalExpression(
866
- t__namespace.binaryExpression(
867
- "===",
868
- t__namespace.unaryExpression("typeof", refIdentifier),
869
- t__namespace.stringLiteral("function")
870
- ),
871
- t__namespace.callExpression(refIdentifier, [elem]),
872
- t__namespace.assignmentExpression("=", value.expression, elem)
873
- )
874
- )
875
- );
876
- } else if (isFunction || t__namespace.isFunction(value.expression)) {
877
- results.exprs.unshift(
878
- t__namespace.expressionStatement(t__namespace.callExpression(value.expression, [elem]))
879
- );
880
- } else if (t__namespace.isCallExpression(value.expression)) {
881
- const refIdentifier = path.scope.generateUidIdentifier("_ref$");
882
- results.exprs.unshift(
883
- t__namespace.variableDeclaration("const", [
884
- t__namespace.variableDeclarator(refIdentifier, value.expression)
885
- ]),
886
- t__namespace.expressionStatement(
887
- t__namespace.logicalExpression(
888
- "&&",
889
- t__namespace.binaryExpression(
890
- "===",
891
- t__namespace.unaryExpression("typeof", refIdentifier),
892
- t__namespace.stringLiteral("function")
893
- ),
894
- t__namespace.callExpression(refIdentifier, [elem])
895
- )
896
- )
897
- );
898
- }
899
- } else if (key.startsWith("use:")) {
900
- // Some trick to treat JSXIdentifier as Identifier
901
- node.name.name.type = 'Identifier';
902
- results.exprs.unshift(
903
- t__namespace.expressionStatement(
904
- t__namespace.callExpression(node.name.name, [
905
- elem,
906
- t__namespace.arrowFunctionExpression(
907
- [],
908
- t__namespace.isJSXEmptyExpression(value.expression)
909
- ? t__namespace.booleanLiteral(true)
910
- : value.expression
911
- )
912
- ])
913
- )
914
- );
915
- } else if (key === "children") {
916
- children = value;
917
- } else if (key.startsWith("on")) {
918
- const ev = toEventName(key);
919
- if (key.startsWith("on:") || key.startsWith("oncapture:")) {
920
- const listenerOptions = [t__namespace.stringLiteral(key.split(":")[1]), value.expression];
921
- results.exprs.push(
922
- t__namespace.expressionStatement(
923
- t__namespace.callExpression(
924
- t__namespace.memberExpression(elem, t__namespace.identifier("addEventListener")),
925
- key.startsWith("oncapture:")
926
- ? listenerOptions.concat(t__namespace.booleanLiteral(true))
927
- : listenerOptions
928
- )
929
- )
930
- );
931
- } else if (
932
- config.delegateEvents &&
933
- (DelegatedEvents.has(ev) || config.delegatedEvents.indexOf(ev) !== -1)
934
- ) {
935
- // can only hydrate delegated events
936
- hasHydratableEvent = true;
937
- const events =
938
- attribute.scope.getProgramParent().data.events ||
939
- (attribute.scope.getProgramParent().data.events = new Set());
940
- events.add(ev);
941
- let handler = value.expression;
942
- const resolveable = detectResolvableEventHandler(attribute, handler);
943
- if (t__namespace.isArrayExpression(handler)) {
944
- if (handler.elements.length > 1) {
945
- results.exprs.unshift(
946
- t__namespace.expressionStatement(
947
- t__namespace.assignmentExpression(
948
- "=",
949
- t__namespace.memberExpression(elem, t__namespace.identifier(`$$${ev}Data`)),
950
- handler.elements[1]
951
- )
952
- )
953
- );
954
- }
955
- handler = handler.elements[0];
956
- results.exprs.unshift(
957
- t__namespace.expressionStatement(
958
- t__namespace.assignmentExpression(
959
- "=",
960
- t__namespace.memberExpression(elem, t__namespace.identifier(`$$${ev}`)),
961
- handler
962
- )
963
- )
964
- );
965
- } else if (t__namespace.isFunction(handler) || resolveable) {
966
- results.exprs.unshift(
967
- t__namespace.expressionStatement(
968
- t__namespace.assignmentExpression(
969
- "=",
970
- t__namespace.memberExpression(elem, t__namespace.identifier(`$$${ev}`)),
971
- handler
972
- )
973
- )
974
- );
975
- } else {
976
- results.exprs.unshift(
977
- t__namespace.expressionStatement(
978
- t__namespace.callExpression(registerImportMethod(path, "addEventListener"), [
979
- elem,
980
- t__namespace.stringLiteral(ev),
981
- handler,
982
- t__namespace.booleanLiteral(true)
983
- ])
984
- )
985
- );
986
- }
987
- } else {
988
- let handler = value.expression;
989
- const resolveable = detectResolvableEventHandler(attribute, handler);
990
- if (t__namespace.isArrayExpression(handler)) {
991
- if (handler.elements.length > 1) {
992
- handler = t__namespace.arrowFunctionExpression(
993
- [t__namespace.identifier("e")],
994
- t__namespace.callExpression(handler.elements[0], [handler.elements[1], t__namespace.identifier("e")])
995
- );
996
- } else handler = handler.elements[0];
997
- results.exprs.unshift(
998
- t__namespace.expressionStatement(
999
- t__namespace.callExpression(t__namespace.memberExpression(elem, t__namespace.identifier("addEventListener")), [
1000
- t__namespace.stringLiteral(ev),
1001
- handler
1002
- ])
1003
- )
1004
- );
1005
- } else if (t__namespace.isFunction(handler) || resolveable) {
1006
- results.exprs.unshift(
1007
- t__namespace.expressionStatement(
1008
- t__namespace.callExpression(t__namespace.memberExpression(elem, t__namespace.identifier("addEventListener")), [
1009
- t__namespace.stringLiteral(ev),
1010
- handler
1011
- ])
1012
- )
1013
- );
1014
- } else {
1015
- results.exprs.unshift(
1016
- t__namespace.expressionStatement(
1017
- t__namespace.callExpression(registerImportMethod(path, "addEventListener"), [
1018
- elem,
1019
- t__namespace.stringLiteral(ev),
1020
- handler
1021
- ])
1022
- )
1023
- );
1024
- }
1025
- }
1026
- } else if (
1027
- config.effectWrapper &&
1028
- isDynamic(attribute.get("value").get("expression"), {
1029
- checkMember: true
1030
- })
1031
- ) {
1032
- let nextElem = elem;
1033
- if (key === "textContent") {
1034
- nextElem = attribute.scope.generateUidIdentifier("el$");
1035
- children = t__namespace.JSXText(" ");
1036
- children.extra = { raw: " ", rawValue: " " };
1037
- results.decl.push(
1038
- t__namespace.variableDeclarator(nextElem, t__namespace.memberExpression(elem, t__namespace.identifier("firstChild")))
1039
- );
1040
- }
1041
- results.dynamics.push({ elem: nextElem, key, value: value.expression, isSVG, isCE });
1042
- } else {
1043
- results.exprs.push(
1044
- t__namespace.expressionStatement(setAttr$2(attribute, elem, key, value.expression, { isSVG, isCE }))
1045
- );
1046
- }
1047
- } else {
1048
- if (config.hydratable && key === "$ServerOnly") {
1049
- results.skipTemplate = true;
1050
- return;
1051
- }
1052
- if (t__namespace.isJSXExpressionContainer(value)) value = value.expression;
1053
- key = Aliases[key] || key;
1054
- if (value && ChildProperties.has(key)) {
1055
- results.exprs.push(
1056
- t__namespace.expressionStatement(setAttr$2(attribute, elem, key, value, { isSVG, isCE }))
1057
- );
1058
- } else {
1059
- !isSVG && (key = key.toLowerCase());
1060
- results.template += ` ${key}`;
1061
- results.template += value ? `="${escapeBackticks(value.value)}"` : "";
1062
- }
1063
- }
1064
- });
1065
- if (!hasChildren && children) {
1066
- path.node.children.push(children);
1067
- }
1068
-
1069
- results.hasHydratableEvent = results.hasHydratableEvent || hasHydratableEvent;
1070
- }
1071
-
1072
- function transformChildren$2(path, results, config) {
1073
- let tempPath = results.id && results.id.name,
1074
- tagName = getTagName(path.node),
1075
- nextPlaceholder,
1076
- i = 0;
1077
- const filteredChildren = filterChildren(path.get("children")),
1078
- childNodes = filteredChildren
1079
- .map(
1080
- (child, index) =>
1081
- transformNode(child, {
1082
- skipId: !results.id || !detectExpressions(filteredChildren, index, config)
1083
- })
1084
- // combine adjacent textNodes
1085
- )
1086
- .reduce((memo, child) => {
1087
- if (!child) return memo;
1088
- const i = memo.length;
1089
- if (child.text && i && memo[i - 1].text) {
1090
- memo[i - 1].template += child.template;
1091
- } else memo.push(child);
1092
- return memo;
1093
- }, []);
1094
-
1095
- childNodes.forEach((child, index) => {
1096
- if (!child) return;
1097
- results.template += child.template;
1098
- if (child.id) {
1099
- if (child.tagName === "head") return;
1100
- if (config.hydratable && tagName === "html") {
1101
- registerImportMethod(path, "getNextMatch");
1102
- }
1103
- const walk = t__namespace.memberExpression(
1104
- t__namespace.identifier(tempPath),
1105
- t__namespace.identifier(i === 0 ? "firstChild" : "nextSibling")
1106
- );
1107
- results.decl.push(
1108
- t__namespace.variableDeclarator(
1109
- child.id,
1110
- config.hydratable && tagName === "html"
1111
- ? t__namespace.callExpression(registerImportMethod(path, "getNextMatch"), [
1112
- walk,
1113
- t__namespace.stringLiteral(child.tagName)
1114
- ])
1115
- : walk
1116
- )
1117
- );
1118
- results.decl.push(...child.decl);
1119
- results.exprs.push(...child.exprs);
1120
- results.dynamics.push(...child.dynamics);
1121
- results.hasHydratableEvent = results.hasHydratableEvent || child.hasHydratableEvent;
1122
- tempPath = child.id.name;
1123
- nextPlaceholder = null;
1124
- i++;
1125
- } else if (child.exprs.length) {
1126
- const insert = registerImportMethod(path, "insert");
1127
- const multi = checkLength(filteredChildren),
1128
- markers = config.hydratable && multi;
1129
- // boxed by textNodes
1130
- if (markers || wrappedByText(childNodes, index)) {
1131
- let exprId, contentId;
1132
- if (markers) tempPath = createPlaceholder(path, results, tempPath, i++, "#")[0].name;
1133
- if (nextPlaceholder) {
1134
- exprId = nextPlaceholder;
1135
- } else {
1136
- [exprId, contentId] = createPlaceholder(path, results, tempPath, i++, markers ? "/" : "");
1137
- }
1138
- if (!markers) nextPlaceholder = exprId;
1139
- results.exprs.push(
1140
- t__namespace.expressionStatement(
1141
- t__namespace.callExpression(
1142
- insert,
1143
- contentId
1144
- ? [results.id, child.exprs[0], exprId, contentId]
1145
- : [results.id, child.exprs[0], exprId]
1146
- )
1147
- )
1148
- );
1149
- tempPath = exprId.name;
1150
- } else if (multi) {
1151
- results.exprs.push(
1152
- t__namespace.expressionStatement(
1153
- t__namespace.callExpression(insert, [
1154
- results.id,
1155
- child.exprs[0],
1156
- nextChild$1(childNodes, index) || t__namespace.nullLiteral()
1157
- ])
1158
- )
1159
- );
1160
- } else {
1161
- results.exprs.push(
1162
- t__namespace.expressionStatement(
1163
- t__namespace.callExpression(
1164
- insert,
1165
- [results.id, child.exprs[0]]
1166
- )
1167
- )
1168
- );
1169
- }
1170
- } else nextPlaceholder = null;
1171
- });
1172
- }
1173
-
1174
- function createPlaceholder(path, results, tempPath, i, char) {
1175
- const exprId = path.scope.generateUidIdentifier("el$"),
1176
- config = getConfig(path);
1177
- let contentId;
1178
- results.template += `<!${char}>`;
1179
- if (config.hydratable && char === "/") {
1180
- contentId = path.scope.generateUidIdentifier("co$");
1181
- results.decl.push(
1182
- t__namespace.variableDeclarator(
1183
- t__namespace.arrayPattern([exprId, contentId]),
1184
- t__namespace.callExpression(registerImportMethod(path, "getNextMarker"), [
1185
- t__namespace.memberExpression(t__namespace.identifier(tempPath), t__namespace.identifier("nextSibling"))
1186
- ])
1187
- )
1188
- );
1189
- } else
1190
- results.decl.push(
1191
- t__namespace.variableDeclarator(
1192
- exprId,
1193
- t__namespace.memberExpression(
1194
- t__namespace.identifier(tempPath),
1195
- t__namespace.identifier(i === 0 ? "firstChild" : "nextSibling")
1196
- )
1197
- )
1198
- );
1199
- return [exprId, contentId];
1200
- }
1201
-
1202
- function nextChild$1(children, index) {
1203
- return children[index + 1] && (children[index + 1].id || nextChild$1(children, index + 1));
1204
- }
1205
-
1206
- // reduce unnecessary refs
1207
- function detectExpressions(children, index, config) {
1208
- if (children[index - 1]) {
1209
- const node = children[index - 1].node;
1210
- if (
1211
- t__namespace.isJSXExpressionContainer(node) &&
1212
- !t__namespace.isJSXEmptyExpression(node.expression) &&
1213
- !getStaticExpression(children[index - 1])
1214
- )
1215
- return true;
1216
- let tagName;
1217
- if (t__namespace.isJSXElement(node) && (tagName = getTagName(node)) && isComponent(tagName)) return true;
1218
- }
1219
- for (let i = index; i < children.length; i++) {
1220
- const child = children[i].node;
1221
- if (t__namespace.isJSXExpressionContainer(child)) {
1222
- if (!t__namespace.isJSXEmptyExpression(child.expression) && !getStaticExpression(children[i]))
1223
- return true;
1224
- } else if (t__namespace.isJSXElement(child)) {
1225
- const tagName = getTagName(child);
1226
- if (isComponent(tagName)) return true;
1227
- if (config.contextToCustomElements && (tagName === "slot" || tagName.indexOf("-") > -1))
1228
- return true;
1229
- if (
1230
- child.openingElement.attributes.some(
1231
- attr =>
1232
- t__namespace.isJSXSpreadAttribute(attr) ||
1233
- ["textContent", "innerHTML", "innerText"].includes(attr.name.name) ||
1234
- (attr.name.namespace && attr.name.namespace.name === "use") ||
1235
- (t__namespace.isJSXExpressionContainer(attr.value) &&
1236
- !(
1237
- t__namespace.isStringLiteral(attr.value.expression) ||
1238
- t__namespace.isNumericLiteral(attr.value.expression)
1239
- ))
1240
- )
1241
- )
1242
- return true;
1243
- const nextChildren = filterChildren(children[i].get("children"));
1244
- if (nextChildren.length) if (detectExpressions(nextChildren, 0, config)) return true;
1245
- }
1246
- }
1247
- }
1248
-
1249
- function contextToCustomElement(path, results) {
1250
- results.exprs.push(
1251
- t__namespace.expressionStatement(
1252
- t__namespace.assignmentExpression(
1253
- "=",
1254
- t__namespace.memberExpression(results.id, t__namespace.identifier("_$owner")),
1255
- t__namespace.callExpression(registerImportMethod(path, "getOwner"), [])
1256
- )
1257
- )
1258
- );
524
+ function transformElement$3(path, info) {
525
+ let tagName = getTagName(path.node),
526
+ config = getConfig(path),
527
+ wrapSVG = info.topLevel && tagName != "svg" && SVGElements.has(tagName),
528
+ voidTag = VoidElements.indexOf(tagName) > -1,
529
+ results = {
530
+ template: `<${tagName}`,
531
+ decl: [],
532
+ exprs: [],
533
+ dynamics: [],
534
+ postExprs: [],
535
+ isSVG: wrapSVG,
536
+ tagName,
537
+ renderer: "dom"
538
+ };
539
+ if (tagName === "html" && config.hydratable) results.skipTemplate = true;
540
+ if (wrapSVG) results.template = "<svg>" + results.template;
541
+ if (!info.skipId) results.id = path.scope.generateUidIdentifier("el$");
542
+ transformAttributes$2(path, results);
543
+ if (config.contextToCustomElements && (tagName === "slot" || tagName.indexOf("-") > -1)) {
544
+ contextToCustomElement(path, results);
545
+ }
546
+ results.template += ">";
547
+ if (!voidTag) {
548
+ transformChildren$2(path, results, config);
549
+ results.template += `</${tagName}>`;
550
+ }
551
+ if (info.topLevel && config.hydratable && results.hasHydratableEvent) {
552
+ let runHydrationEvents = registerImportMethod(
553
+ path,
554
+ "runHydrationEvents",
555
+ getRendererConfig(path, "dom").moduleName
556
+ );
557
+ results.postExprs.push(t__namespace.expressionStatement(t__namespace.callExpression(runHydrationEvents, [])));
558
+ }
559
+ if (wrapSVG) results.template += "</svg>";
560
+ return results;
561
+ }
562
+
563
+ function setAttr$2(path, elem, name, value, { isSVG, dynamic, prevId, isCE }) {
564
+ // pull out namespace
565
+ const config = getConfig(path);
566
+ let parts, namespace;
567
+ if ((parts = name.split(":")) && parts[1] && reservedNameSpaces.has(parts[0])) {
568
+ name = parts[1];
569
+ namespace = parts[0];
570
+ }
571
+
572
+ if (namespace === "style") {
573
+ return t__namespace.callExpression(
574
+ t__namespace.memberExpression(
575
+ t__namespace.memberExpression(elem, t__namespace.identifier("style")),
576
+ t__namespace.identifier("setProperty")
577
+ ),
578
+ [t__namespace.stringLiteral(name), value]
579
+ );
580
+ }
581
+
582
+ if (namespace === "class") {
583
+ return t__namespace.callExpression(
584
+ t__namespace.memberExpression(
585
+ t__namespace.memberExpression(elem, t__namespace.identifier("classList")),
586
+ t__namespace.identifier("toggle")
587
+ ),
588
+ [t__namespace.stringLiteral(name), value]
589
+ );
590
+ }
591
+
592
+ if (name === "style") {
593
+ return t__namespace.callExpression(registerImportMethod(path, "style", getRendererConfig(path, "dom").moduleName), prevId ? [elem, value, prevId] : [elem, value]);
594
+ }
595
+
596
+ if (!isSVG && name === "class") {
597
+ return t__namespace.callExpression(registerImportMethod(path, "className", getRendererConfig(path, "dom").moduleName), [elem, value]);
598
+ }
599
+
600
+ if (name === "classList") {
601
+ return t__namespace.callExpression(registerImportMethod(
602
+ path,
603
+ "classList",
604
+ getRendererConfig(path, "dom").moduleName
605
+ ), prevId ? [elem, value, prevId] : [elem, value]);
606
+ }
607
+
608
+ if (config.hydratable && name === "innerHTML") {
609
+ return t__namespace.callExpression(
610
+ registerImportMethod(path, "innerHTML"),
611
+ [elem, value]
612
+ );
613
+ }
614
+
615
+ if (dynamic && name === "textContent") {
616
+ return t__namespace.assignmentExpression("=", t__namespace.memberExpression(elem, t__namespace.identifier("data")), value);
617
+ }
618
+
619
+ const isChildProp = ChildProperties.has(name);
620
+ const isProp = Properties.has(name);
621
+ const alias = PropAliases[name];
622
+ if (namespace !== "attr" && (isChildProp || (!isSVG && isProp) || isCE || namespace === "prop")) {
623
+ if (isCE && !isChildProp && !isProp && namespace !== "prop") name = toPropertyName(name);
624
+ return t__namespace.assignmentExpression(
625
+ "=",
626
+ t__namespace.memberExpression(elem, t__namespace.identifier(alias || name)),
627
+ value
628
+ );
629
+ }
630
+
631
+ let isNameSpaced = name.indexOf(":") > -1;
632
+ name = Aliases[name] || name;
633
+ !isSVG && (name = name.toLowerCase());
634
+ const ns = isNameSpaced && SVGNamespace[name.split(":")[0]];
635
+ if (ns) {
636
+ return t__namespace.callExpression(registerImportMethod(
637
+ path,
638
+ "setAttributeNS",
639
+ getRendererConfig(path, "dom").moduleName
640
+ ), [
641
+ elem,
642
+ t__namespace.stringLiteral(ns),
643
+ t__namespace.stringLiteral(name),
644
+ value
645
+ ]);
646
+ } else {
647
+ return t__namespace.callExpression(registerImportMethod(
648
+ path,
649
+ "setAttribute",
650
+ getRendererConfig(path, "dom").moduleName
651
+ ), [elem, t__namespace.stringLiteral(name), value]);
652
+ }
653
+ }
654
+
655
+ function detectResolvableEventHandler(attribute, handler) {
656
+ while (t__namespace.isIdentifier(handler)) {
657
+ const lookup = attribute.scope.getBinding(handler.name);
658
+ if (lookup) {
659
+ if (t__namespace.isVariableDeclarator(lookup.path.node)) {
660
+ handler = lookup.path.node.init;
661
+ } else if (t__namespace.isFunctionDeclaration(lookup.path.node)) {
662
+ return true;
663
+ } else return false;
664
+ } else return false;
665
+ }
666
+ return t__namespace.isFunction(handler);
667
+ }
668
+
669
+ function transformAttributes$2(path, results) {
670
+ let elem = results.id,
671
+ hasHydratableEvent = false,
672
+ children,
673
+ attributes = path.get("openingElement").get("attributes");
674
+ const tagName = getTagName(path.node),
675
+ isSVG = SVGElements.has(tagName),
676
+ isCE = tagName.includes("-"),
677
+ hasChildren = path.node.children.length > 0,
678
+ config = getConfig(path);
679
+
680
+ // preprocess styles
681
+ const styleAttribute = attributes.find(
682
+ a =>
683
+ a.node.name &&
684
+ a.node.name.name === "style" &&
685
+ t__namespace.isJSXExpressionContainer(a.node.value) &&
686
+ t__namespace.isObjectExpression(a.node.value.expression) &&
687
+ !a.node.value.expression.properties.some(p => t__namespace.isSpreadElement(p))
688
+ );
689
+ if (styleAttribute) {
690
+ let i = 0,
691
+ leading = styleAttribute.node.value.expression.leadingComments;
692
+ styleAttribute.node.value.expression.properties.slice().forEach((p, index) => {
693
+ if (!p.computed) {
694
+ if (leading) p.value.leadingComments = leading;
695
+ path
696
+ .get("openingElement")
697
+ .node.attributes.splice(
698
+ styleAttribute.key + ++i,
699
+ 0,
700
+ t__namespace.JSXAttribute(
701
+ t__namespace.JSXNamespacedName(
702
+ t__namespace.JSXIdentifier("style"),
703
+ t__namespace.JSXIdentifier(t__namespace.isIdentifier(p.key) ? p.key.name : p.key.value)
704
+ ),
705
+ t__namespace.JSXExpressionContainer(p.value)
706
+ )
707
+ );
708
+ styleAttribute.node.value.expression.properties.splice(index - i - 1, 1);
709
+ }
710
+ });
711
+ if (!styleAttribute.node.value.expression.properties.length)
712
+ path.get("openingElement").node.attributes.splice(styleAttribute.key, 1);
713
+ }
714
+
715
+ // preprocess classList
716
+ attributes = path.get("openingElement").get("attributes");
717
+ const classListAttribute = attributes.find(
718
+ a =>
719
+ a.node.name &&
720
+ a.node.name.name === "classList" &&
721
+ t__namespace.isJSXExpressionContainer(a.node.value) &&
722
+ t__namespace.isObjectExpression(a.node.value.expression) &&
723
+ !a.node.value.expression.properties.some(
724
+ p =>
725
+ t__namespace.isSpreadElement(p) ||
726
+ p.computed ||
727
+ (t__namespace.isStringLiteral(p.key) && (p.key.value.includes(" ") || p.key.value.includes(":")))
728
+ )
729
+ );
730
+ if (classListAttribute) {
731
+ let i = 0,
732
+ leading = classListAttribute.node.value.expression.leadingComments,
733
+ classListProperties = classListAttribute.get("value").get("expression").get("properties");
734
+ classListProperties.slice().forEach((propPath, index) => {
735
+ const p = propPath.node;
736
+ const { confident, value: computed } = propPath.get("value").evaluate();
737
+ if (leading) p.value.leadingComments = leading;
738
+ if (!confident) {
739
+ path
740
+ .get("openingElement")
741
+ .node.attributes.splice(
742
+ classListAttribute.key + ++i,
743
+ 0,
744
+ t__namespace.JSXAttribute(
745
+ t__namespace.JSXNamespacedName(
746
+ t__namespace.JSXIdentifier("class"),
747
+ t__namespace.JSXIdentifier(t__namespace.isIdentifier(p.key) ? p.key.name : p.key.value)
748
+ ),
749
+ t__namespace.JSXExpressionContainer(p.value)
750
+ )
751
+ );
752
+ } else if (computed) {
753
+ path
754
+ .get("openingElement")
755
+ .node.attributes.splice(
756
+ classListAttribute.key + ++i,
757
+ 0,
758
+ t__namespace.JSXAttribute(
759
+ t__namespace.JSXIdentifier("class"),
760
+ t__namespace.stringLiteral(t__namespace.isIdentifier(p.key) ? p.key.name : p.key.value)
761
+ )
762
+ );
763
+ }
764
+ classListProperties.splice(index - i - 1, 1);
765
+ });
766
+ if (!classListProperties.length)
767
+ path.get("openingElement").node.attributes.splice(classListAttribute.key, 1);
768
+ }
769
+
770
+ // combine class properties
771
+ attributes = path.get("openingElement").get("attributes");
772
+ const classAttributes = attributes.filter(
773
+ a => a.node.name && (a.node.name.name === "class" || a.node.name.name === "className")
774
+ );
775
+ if (classAttributes.length > 1) {
776
+ const first = classAttributes[0].node,
777
+ values = [],
778
+ quasis = [t__namespace.TemplateElement({ raw: "" })];
779
+ for (let i = 0; i < classAttributes.length; i++) {
780
+ const attr = classAttributes[i].node,
781
+ isLast = i === classAttributes.length - 1;
782
+ if (!t__namespace.isJSXExpressionContainer(attr.value)) {
783
+ const prev = quasis.pop();
784
+ quasis.push(
785
+ t__namespace.TemplateElement({
786
+ raw: (prev ? prev.value.raw : "") + `${attr.value.value}` + (isLast ? "" : " ")
787
+ })
788
+ );
789
+ } else {
790
+ values.push(t__namespace.logicalExpression("||", attr.value.expression, t__namespace.stringLiteral("")));
791
+ quasis.push(t__namespace.TemplateElement({ raw: isLast ? "" : " " }));
792
+ }
793
+ i && attributes.splice(attributes.indexOf(classAttributes[i]), 1);
794
+ }
795
+ if (values.length) first.value = t__namespace.JSXExpressionContainer(t__namespace.TemplateLiteral(quasis, values));
796
+ else first.value = t__namespace.stringLiteral(quasis[0].value.raw);
797
+ }
798
+ path.get("openingElement").set(
799
+ "attributes",
800
+ attributes.map(a => a.node)
801
+ );
802
+
803
+ path
804
+ .get("openingElement")
805
+ .get("attributes")
806
+ .forEach(attribute => {
807
+ const node = attribute.node;
808
+ if (t__namespace.isJSXSpreadAttribute(node)) {
809
+ results.exprs.push(
810
+ t__namespace.expressionStatement(
811
+ t__namespace.callExpression(registerImportMethod(
812
+ attribute,
813
+ "spread",
814
+ getRendererConfig(path, "dom").moduleName
815
+ ), [
816
+ elem,
817
+ isDynamic(attribute.get("argument"), {
818
+ checkMember: true
819
+ })
820
+ ? t__namespace.isCallExpression(node.argument) && !node.argument.arguments.length
821
+ ? node.argument.callee
822
+ : t__namespace.arrowFunctionExpression([], node.argument)
823
+ : node.argument,
824
+ t__namespace.booleanLiteral(isSVG),
825
+ t__namespace.booleanLiteral(hasChildren)
826
+ ])
827
+ )
828
+ );
829
+ //NOTE: can't be checked at compile time so add to compiled output
830
+ hasHydratableEvent = true;
831
+ return;
832
+ }
833
+
834
+ let value = node.value,
835
+ key = t__namespace.isJSXNamespacedName(node.name)
836
+ ? `${node.name.namespace.name}:${node.name.name.name}`
837
+ : node.name.name,
838
+ reservedNameSpace =
839
+ t__namespace.isJSXNamespacedName(node.name) && reservedNameSpaces.has(node.name.namespace.name);
840
+ if (t__namespace.isJSXExpressionContainer(value) && !key.startsWith("use:")) {
841
+ const evaluated = attribute.get("value").get("expression").evaluate().value;
842
+ let type;
843
+ if (
844
+ evaluated !== undefined &&
845
+ ((type = typeof evaluated) === "string" || type === "number")
846
+ ) {
847
+ value = t__namespace.stringLiteral(String(evaluated));
848
+ }
849
+ }
850
+ if (
851
+ t__namespace.isJSXNamespacedName(node.name) &&
852
+ reservedNameSpace &&
853
+ !t__namespace.isJSXExpressionContainer(value)
854
+ ) {
855
+ node.value = value = t__namespace.JSXExpressionContainer(value || t__namespace.JSXEmptyExpression());
856
+ }
857
+ if (
858
+ t__namespace.isJSXExpressionContainer(value) &&
859
+ (reservedNameSpace ||
860
+ !(t__namespace.isStringLiteral(value.expression) || t__namespace.isNumericLiteral(value.expression)))
861
+ ) {
862
+ if (key === "ref") {
863
+ // Normalize expressions for non-null and type-as
864
+ while (
865
+ t__namespace.isTSNonNullExpression(value.expression) ||
866
+ t__namespace.isTSAsExpression(value.expression)
867
+ ) {
868
+ value.expression = value.expression.expression;
869
+ }
870
+ let binding,
871
+ isFunction =
872
+ t__namespace.isIdentifier(value.expression) &&
873
+ (binding = path.scope.getBinding(value.expression.name)) &&
874
+ binding.kind === "const";
875
+ if (!isFunction && t__namespace.isLVal(value.expression)) {
876
+ const refIdentifier = path.scope.generateUidIdentifier("_ref$");
877
+ results.exprs.unshift(
878
+ t__namespace.variableDeclaration("const", [
879
+ t__namespace.variableDeclarator(refIdentifier, value.expression)
880
+ ]),
881
+ t__namespace.expressionStatement(
882
+ t__namespace.conditionalExpression(
883
+ t__namespace.binaryExpression(
884
+ "===",
885
+ t__namespace.unaryExpression("typeof", refIdentifier),
886
+ t__namespace.stringLiteral("function")
887
+ ),
888
+ t__namespace.callExpression(refIdentifier, [elem]),
889
+ t__namespace.assignmentExpression("=", value.expression, elem)
890
+ )
891
+ )
892
+ );
893
+ } else if (isFunction || t__namespace.isFunction(value.expression)) {
894
+ results.exprs.unshift(
895
+ t__namespace.expressionStatement(t__namespace.callExpression(value.expression, [elem]))
896
+ );
897
+ } else if (t__namespace.isCallExpression(value.expression)) {
898
+ const refIdentifier = path.scope.generateUidIdentifier("_ref$");
899
+ results.exprs.unshift(
900
+ t__namespace.variableDeclaration("const", [
901
+ t__namespace.variableDeclarator(refIdentifier, value.expression)
902
+ ]),
903
+ t__namespace.expressionStatement(
904
+ t__namespace.logicalExpression(
905
+ "&&",
906
+ t__namespace.binaryExpression(
907
+ "===",
908
+ t__namespace.unaryExpression("typeof", refIdentifier),
909
+ t__namespace.stringLiteral("function")
910
+ ),
911
+ t__namespace.callExpression(refIdentifier, [elem])
912
+ )
913
+ )
914
+ );
915
+ }
916
+ } else if (key.startsWith("use:")) {
917
+ // Some trick to treat JSXIdentifier as Identifier
918
+ node.name.name.type = 'Identifier';
919
+ results.exprs.unshift(
920
+ t__namespace.expressionStatement(
921
+ t__namespace.callExpression(node.name.name, [
922
+ elem,
923
+ t__namespace.arrowFunctionExpression(
924
+ [],
925
+ t__namespace.isJSXEmptyExpression(value.expression)
926
+ ? t__namespace.booleanLiteral(true)
927
+ : value.expression
928
+ )
929
+ ])
930
+ )
931
+ );
932
+ } else if (key === "children") {
933
+ children = value;
934
+ } else if (key.startsWith("on")) {
935
+ const ev = toEventName(key);
936
+ if (key.startsWith("on:") || key.startsWith("oncapture:")) {
937
+ const listenerOptions = [t__namespace.stringLiteral(key.split(":")[1]), value.expression];
938
+ results.exprs.push(
939
+ t__namespace.expressionStatement(
940
+ t__namespace.callExpression(
941
+ t__namespace.memberExpression(elem, t__namespace.identifier("addEventListener")),
942
+ key.startsWith("oncapture:")
943
+ ? listenerOptions.concat(t__namespace.booleanLiteral(true))
944
+ : listenerOptions
945
+ )
946
+ )
947
+ );
948
+ } else if (
949
+ config.delegateEvents &&
950
+ (DelegatedEvents.has(ev) || config.delegatedEvents.indexOf(ev) !== -1)
951
+ ) {
952
+ // can only hydrate delegated events
953
+ hasHydratableEvent = true;
954
+ const events =
955
+ attribute.scope.getProgramParent().data.events ||
956
+ (attribute.scope.getProgramParent().data.events = new Set());
957
+ events.add(ev);
958
+ let handler = value.expression;
959
+ const resolveable = detectResolvableEventHandler(attribute, handler);
960
+ if (t__namespace.isArrayExpression(handler)) {
961
+ if (handler.elements.length > 1) {
962
+ results.exprs.unshift(
963
+ t__namespace.expressionStatement(
964
+ t__namespace.assignmentExpression(
965
+ "=",
966
+ t__namespace.memberExpression(elem, t__namespace.identifier(`$$${ev}Data`)),
967
+ handler.elements[1]
968
+ )
969
+ )
970
+ );
971
+ }
972
+ handler = handler.elements[0];
973
+ results.exprs.unshift(
974
+ t__namespace.expressionStatement(
975
+ t__namespace.assignmentExpression(
976
+ "=",
977
+ t__namespace.memberExpression(elem, t__namespace.identifier(`$$${ev}`)),
978
+ handler
979
+ )
980
+ )
981
+ );
982
+ } else if (t__namespace.isFunction(handler) || resolveable) {
983
+ results.exprs.unshift(
984
+ t__namespace.expressionStatement(
985
+ t__namespace.assignmentExpression(
986
+ "=",
987
+ t__namespace.memberExpression(elem, t__namespace.identifier(`$$${ev}`)),
988
+ handler
989
+ )
990
+ )
991
+ );
992
+ } else {
993
+ results.exprs.unshift(
994
+ t__namespace.expressionStatement(
995
+ t__namespace.callExpression(registerImportMethod(
996
+ path,
997
+ "addEventListener",
998
+ getRendererConfig(path, "dom").moduleName
999
+ ), [
1000
+ elem,
1001
+ t__namespace.stringLiteral(ev),
1002
+ handler,
1003
+ t__namespace.booleanLiteral(true)
1004
+ ])
1005
+ )
1006
+ );
1007
+ }
1008
+ } else {
1009
+ let handler = value.expression;
1010
+ const resolveable = detectResolvableEventHandler(attribute, handler);
1011
+ if (t__namespace.isArrayExpression(handler)) {
1012
+ if (handler.elements.length > 1) {
1013
+ handler = t__namespace.arrowFunctionExpression(
1014
+ [t__namespace.identifier("e")],
1015
+ t__namespace.callExpression(handler.elements[0], [handler.elements[1], t__namespace.identifier("e")])
1016
+ );
1017
+ } else handler = handler.elements[0];
1018
+ results.exprs.unshift(
1019
+ t__namespace.expressionStatement(
1020
+ t__namespace.callExpression(t__namespace.memberExpression(elem, t__namespace.identifier("addEventListener")), [
1021
+ t__namespace.stringLiteral(ev),
1022
+ handler
1023
+ ])
1024
+ )
1025
+ );
1026
+ } else if (t__namespace.isFunction(handler) || resolveable) {
1027
+ results.exprs.unshift(
1028
+ t__namespace.expressionStatement(
1029
+ t__namespace.callExpression(t__namespace.memberExpression(elem, t__namespace.identifier("addEventListener")), [
1030
+ t__namespace.stringLiteral(ev),
1031
+ handler
1032
+ ])
1033
+ )
1034
+ );
1035
+ } else {
1036
+ results.exprs.unshift(
1037
+ t__namespace.expressionStatement(
1038
+ t__namespace.callExpression(registerImportMethod(
1039
+ path,
1040
+ "addEventListener",
1041
+ getRendererConfig(path, "dom").moduleName
1042
+ ), [elem, t__namespace.stringLiteral(ev), handler])
1043
+ )
1044
+ );
1045
+ }
1046
+ }
1047
+ } else if (
1048
+ config.effectWrapper &&
1049
+ isDynamic(attribute.get("value").get("expression"), {
1050
+ checkMember: true
1051
+ })
1052
+ ) {
1053
+ let nextElem = elem;
1054
+ if (key === "textContent") {
1055
+ nextElem = attribute.scope.generateUidIdentifier("el$");
1056
+ children = t__namespace.JSXText(" ");
1057
+ children.extra = { raw: " ", rawValue: " " };
1058
+ results.decl.push(
1059
+ t__namespace.variableDeclarator(nextElem, t__namespace.memberExpression(elem, t__namespace.identifier("firstChild")))
1060
+ );
1061
+ }
1062
+ results.dynamics.push({ elem: nextElem, key, value: value.expression, isSVG, isCE });
1063
+ } else {
1064
+ results.exprs.push(
1065
+ t__namespace.expressionStatement(setAttr$2(attribute, elem, key, value.expression, { isSVG, isCE }))
1066
+ );
1067
+ }
1068
+ } else {
1069
+ if (config.hydratable && key === "$ServerOnly") {
1070
+ results.skipTemplate = true;
1071
+ return;
1072
+ }
1073
+ if (t__namespace.isJSXExpressionContainer(value)) value = value.expression;
1074
+ key = Aliases[key] || key;
1075
+ if (value && ChildProperties.has(key)) {
1076
+ results.exprs.push(
1077
+ t__namespace.expressionStatement(setAttr$2(attribute, elem, key, value, { isSVG, isCE }))
1078
+ );
1079
+ } else {
1080
+ !isSVG && (key = key.toLowerCase());
1081
+ results.template += ` ${key}`;
1082
+ results.template += value ? `="${escapeBackticks(value.value)}"` : "";
1083
+ }
1084
+ }
1085
+ });
1086
+ if (!hasChildren && children) {
1087
+ path.node.children.push(children);
1088
+ }
1089
+
1090
+ results.hasHydratableEvent = results.hasHydratableEvent || hasHydratableEvent;
1091
+ }
1092
+
1093
+ function transformChildren$2(path, results, config) {
1094
+ let tempPath = results.id && results.id.name,
1095
+ tagName = getTagName(path.node),
1096
+ nextPlaceholder,
1097
+ i = 0;
1098
+ const filteredChildren = filterChildren(path.get("children")),
1099
+ childNodes = filteredChildren
1100
+ .map(
1101
+ (child, index) =>
1102
+ transformNode(child, {
1103
+ skipId: !results.id || !detectExpressions(filteredChildren, index, config)
1104
+ })
1105
+ // combine adjacent textNodes
1106
+ )
1107
+ .reduce((memo, child) => {
1108
+ if (!child) return memo;
1109
+ const i = memo.length;
1110
+ if (child.text && i && memo[i - 1].text) {
1111
+ memo[i - 1].template += child.template;
1112
+ } else memo.push(child);
1113
+ return memo;
1114
+ }, []);
1115
+
1116
+ childNodes.forEach((child, index) => {
1117
+ if (!child) return;
1118
+ if (child.tagName && child.renderer !== "dom") {
1119
+ throw new Error(`<${child.tagName}> is not supported in <${tagName}>.
1120
+ Wrap the usage with a component that would render this element, eg. Canvas`);
1121
+ }
1122
+
1123
+ results.template += child.template;
1124
+ if (child.id) {
1125
+ if (child.tagName === "head") return;
1126
+
1127
+ let getNextMatch;
1128
+ if (config.hydratable && tagName === "html") {
1129
+ getNextMatch = registerImportMethod(
1130
+ path,
1131
+ "getNextMatch",
1132
+ getRendererConfig(path, "dom").moduleName
1133
+ );
1134
+ }
1135
+ const walk = t__namespace.memberExpression(
1136
+ t__namespace.identifier(tempPath),
1137
+ t__namespace.identifier(i === 0 ? "firstChild" : "nextSibling")
1138
+ );
1139
+ results.decl.push(
1140
+ t__namespace.variableDeclarator(
1141
+ child.id,
1142
+ config.hydratable && tagName === "html"
1143
+ ? t__namespace.callExpression(getNextMatch, [walk, t__namespace.stringLiteral(child.tagName)])
1144
+ : walk
1145
+ )
1146
+ );
1147
+ results.decl.push(...child.decl);
1148
+ results.exprs.push(...child.exprs);
1149
+ results.dynamics.push(...child.dynamics);
1150
+ results.hasHydratableEvent = results.hasHydratableEvent || child.hasHydratableEvent;
1151
+ tempPath = child.id.name;
1152
+ nextPlaceholder = null;
1153
+ i++;
1154
+ } else if (child.exprs.length) {
1155
+ let insert = registerImportMethod(path, "insert", getRendererConfig(path, "dom").moduleName);
1156
+ const multi = checkLength(filteredChildren),
1157
+ markers = config.hydratable && multi;
1158
+ // boxed by textNodes
1159
+ if (markers || wrappedByText(childNodes, index)) {
1160
+ let exprId, contentId;
1161
+ if (markers) tempPath = createPlaceholder(path, results, tempPath, i++, "#")[0].name;
1162
+ if (nextPlaceholder) {
1163
+ exprId = nextPlaceholder;
1164
+ } else {
1165
+ [exprId, contentId] = createPlaceholder(path, results, tempPath, i++, markers ? "/" : "");
1166
+ }
1167
+ if (!markers) nextPlaceholder = exprId;
1168
+ results.exprs.push(
1169
+ t__namespace.expressionStatement(
1170
+ t__namespace.callExpression(
1171
+ insert,
1172
+ contentId
1173
+ ? [results.id, child.exprs[0], exprId, contentId]
1174
+ : [results.id, child.exprs[0], exprId]
1175
+ )
1176
+ )
1177
+ );
1178
+ tempPath = exprId.name;
1179
+ } else if (multi) {
1180
+ results.exprs.push(
1181
+ t__namespace.expressionStatement(
1182
+ t__namespace.callExpression(insert, [
1183
+ results.id,
1184
+ child.exprs[0],
1185
+ nextChild$1(childNodes, index) || t__namespace.nullLiteral()
1186
+ ])
1187
+ )
1188
+ );
1189
+ } else {
1190
+ results.exprs.push(
1191
+ t__namespace.expressionStatement(
1192
+ t__namespace.callExpression(
1193
+ insert,
1194
+ [results.id, child.exprs[0]]
1195
+ )
1196
+ )
1197
+ );
1198
+ }
1199
+ } else nextPlaceholder = null;
1200
+ });
1201
+ }
1202
+
1203
+ function createPlaceholder(path, results, tempPath, i, char) {
1204
+ const exprId = path.scope.generateUidIdentifier("el$"),
1205
+ config = getConfig(path);
1206
+ let contentId;
1207
+ results.template += `<!${char}>`;
1208
+ if (config.hydratable && char === "/") {
1209
+ contentId = path.scope.generateUidIdentifier("co$");
1210
+ results.decl.push(
1211
+ t__namespace.variableDeclarator(
1212
+ t__namespace.arrayPattern([exprId, contentId]),
1213
+ t__namespace.callExpression(
1214
+ registerImportMethod(path, "getNextMarker", getRendererConfig(path, "dom").moduleName),
1215
+ [t__namespace.memberExpression(t__namespace.identifier(tempPath), t__namespace.identifier("nextSibling"))]
1216
+ )
1217
+ )
1218
+ );
1219
+ } else
1220
+ results.decl.push(
1221
+ t__namespace.variableDeclarator(
1222
+ exprId,
1223
+ t__namespace.memberExpression(
1224
+ t__namespace.identifier(tempPath),
1225
+ t__namespace.identifier(i === 0 ? "firstChild" : "nextSibling")
1226
+ )
1227
+ )
1228
+ );
1229
+ return [exprId, contentId];
1230
+ }
1231
+
1232
+ function nextChild$1(children, index) {
1233
+ return children[index + 1] && (children[index + 1].id || nextChild$1(children, index + 1));
1234
+ }
1235
+
1236
+ // reduce unnecessary refs
1237
+ function detectExpressions(children, index, config) {
1238
+ if (children[index - 1]) {
1239
+ const node = children[index - 1].node;
1240
+ if (
1241
+ t__namespace.isJSXExpressionContainer(node) &&
1242
+ !t__namespace.isJSXEmptyExpression(node.expression) &&
1243
+ !getStaticExpression(children[index - 1])
1244
+ )
1245
+ return true;
1246
+ let tagName;
1247
+ if (t__namespace.isJSXElement(node) && (tagName = getTagName(node)) && isComponent(tagName)) return true;
1248
+ }
1249
+ for (let i = index; i < children.length; i++) {
1250
+ const child = children[i].node;
1251
+ if (t__namespace.isJSXExpressionContainer(child)) {
1252
+ if (!t__namespace.isJSXEmptyExpression(child.expression) && !getStaticExpression(children[i]))
1253
+ return true;
1254
+ } else if (t__namespace.isJSXElement(child)) {
1255
+ const tagName = getTagName(child);
1256
+ if (isComponent(tagName)) return true;
1257
+ if (config.contextToCustomElements && (tagName === "slot" || tagName.indexOf("-") > -1))
1258
+ return true;
1259
+ if (
1260
+ child.openingElement.attributes.some(
1261
+ attr =>
1262
+ t__namespace.isJSXSpreadAttribute(attr) ||
1263
+ ["textContent", "innerHTML", "innerText"].includes(attr.name.name) ||
1264
+ (attr.name.namespace && attr.name.namespace.name === "use") ||
1265
+ (t__namespace.isJSXExpressionContainer(attr.value) &&
1266
+ !(
1267
+ t__namespace.isStringLiteral(attr.value.expression) ||
1268
+ t__namespace.isNumericLiteral(attr.value.expression)
1269
+ ))
1270
+ )
1271
+ )
1272
+ return true;
1273
+ const nextChildren = filterChildren(children[i].get("children"));
1274
+ if (nextChildren.length) if (detectExpressions(nextChildren, 0, config)) return true;
1275
+ }
1276
+ }
1277
+ }
1278
+
1279
+ function contextToCustomElement(path, results) {
1280
+ results.exprs.push(
1281
+ t__namespace.expressionStatement(
1282
+ t__namespace.assignmentExpression(
1283
+ "=",
1284
+ t__namespace.memberExpression(results.id, t__namespace.identifier("_$owner")),
1285
+ t__namespace.callExpression(
1286
+ registerImportMethod(path, "getOwner", getRendererConfig(path, "dom").moduleName),
1287
+ []
1288
+ )
1289
+ )
1290
+ )
1291
+ );
1259
1292
  }
1260
1293
 
1261
1294
  function createTemplate$2(path, result, wrap) {
@@ -1300,14 +1333,14 @@ function appendTemplates$1(path, templates) {
1300
1333
  template.id,
1301
1334
  t__namespace.addComment(
1302
1335
  t__namespace.callExpression(
1303
- registerImportMethod(path, "template"),
1336
+ registerImportMethod(path, "template", getRendererConfig(path, "dom").moduleName),
1304
1337
  [
1305
1338
  t__namespace.templateLiteral([t__namespace.templateElement(tmpl, true)], []),
1306
1339
  t__namespace.numericLiteral(template.elementCount)
1307
1340
  ].concat(template.isSVG ? t__namespace.booleanLiteral(template.isSVG) : [])
1308
1341
  ),
1309
- 'leading',
1310
- '#__PURE__'
1342
+ "leading",
1343
+ "#__PURE__"
1311
1344
  )
1312
1345
  );
1313
1346
  });
@@ -1331,14 +1364,18 @@ function registerTemplate(path, results) {
1331
1364
  id: templateId,
1332
1365
  template: results.template,
1333
1366
  elementCount: results.template.split("<").length - 1,
1334
- isSVG: results.isSVG
1367
+ isSVG: results.isSVG,
1368
+ renderer: "dom"
1335
1369
  });
1336
1370
  }
1337
1371
  }
1338
1372
  decl = t__namespace.variableDeclarator(
1339
1373
  results.id,
1340
1374
  hydratable
1341
- ? t__namespace.callExpression(registerImportMethod(path, "getNextElement"), templateId ? [templateId] : [])
1375
+ ? t__namespace.callExpression(
1376
+ registerImportMethod(path, "getNextElement", getRendererConfig(path, "dom").moduleName),
1377
+ templateId ? [templateId] : []
1378
+ )
1342
1379
  : t__namespace.callExpression(t__namespace.memberExpression(templateId, t__namespace.identifier("cloneNode")), [
1343
1380
  t__namespace.booleanLiteral(true)
1344
1381
  ])
@@ -1444,20 +1481,24 @@ function createTemplate$1(path, result) {
1444
1481
  }
1445
1482
 
1446
1483
  const templates =
1447
- path.scope.getProgramParent().data.templates ||
1448
- (path.scope.getProgramParent().data.templates = []);
1484
+ path.scope.getProgramParent().data.templates ||
1485
+ (path.scope.getProgramParent().data.templates = []);
1449
1486
  const found = templates.find(tmp => {
1450
- if (t__namespace.isArrayExpression(tmp[1]) && t__namespace.isArrayExpression(template)) {
1451
- return tmp[1].elements.every(
1487
+ if (t__namespace.isArrayExpression(tmp.template) && t__namespace.isArrayExpression(template)) {
1488
+ return tmp.template.elements.every(
1452
1489
  (el, i) => template.elements[i] && el.value === template.elements[i].value
1453
1490
  );
1454
1491
  }
1455
- return tmp[1].value === template.value;
1492
+ return tmp.template.value === template.value;
1456
1493
  });
1457
1494
  if (!found) {
1458
1495
  id = path.scope.generateUidIdentifier("tmpl$");
1459
- templates.push([id, template]);
1460
- } else id = found[0];
1496
+ templates.push({
1497
+ id,
1498
+ template,
1499
+ renderer: "ssr"
1500
+ });
1501
+ } else id = found.id;
1461
1502
 
1462
1503
  return t__namespace.callExpression(
1463
1504
  registerImportMethod(path, "ssr"),
@@ -1467,7 +1508,7 @@ function createTemplate$1(path, result) {
1467
1508
 
1468
1509
  function appendTemplates(path, templates) {
1469
1510
  const declarators = templates.map(template => {
1470
- return t__namespace.variableDeclarator(template[0], template[1]);
1511
+ return t__namespace.variableDeclarator(template.id, template.template);
1471
1512
  });
1472
1513
  path.node.body.unshift(t__namespace.variableDeclaration("const", declarators));
1473
1514
  }
@@ -1481,7 +1522,7 @@ function appendToTemplate(template, value) {
1481
1522
  if (array && array.length) template.push.apply(template, array);
1482
1523
  }
1483
1524
 
1484
- function transformElement$1(path, info) {
1525
+ function transformElement$2(path, info) {
1485
1526
  let tagName = getTagName(path.node),
1486
1527
  config = getConfig(path),
1487
1528
  voidTag = VoidElements.indexOf(tagName) > -1,
@@ -1491,8 +1532,10 @@ function transformElement$1(path, info) {
1491
1532
  decl: [],
1492
1533
  exprs: [],
1493
1534
  dynamics: [],
1494
- tagName
1535
+ tagName,
1536
+ renderer: "ssr"
1495
1537
  };
1538
+
1496
1539
  if (info.topLevel && config.hydratable) {
1497
1540
  results.template.push("");
1498
1541
  results.templateValues.push(
@@ -1514,7 +1557,7 @@ function toAttribute(key, isSVG) {
1514
1557
  return key;
1515
1558
  }
1516
1559
 
1517
- function setAttr$1(results, name, value, isSVG) {
1560
+ function setAttr$1(attribute, results, name, value, isSVG) {
1518
1561
  // strip out namespaces for now, everything at this point is an attribute
1519
1562
  let parts;
1520
1563
  if ((parts = name.split(":")) && parts[1] && reservedNameSpaces.has(parts[0])) {
@@ -1522,9 +1565,18 @@ function setAttr$1(results, name, value, isSVG) {
1522
1565
  }
1523
1566
 
1524
1567
  name = toAttribute(name, isSVG);
1525
- appendToTemplate(results.template, ` ${name}="`);
1526
- results.template.push(`"`);
1527
- results.templateValues.push(value);
1568
+ const attr = t__namespace.callExpression(registerImportMethod(attribute, "ssrAttribute"), [
1569
+ t__namespace.stringLiteral(name),
1570
+ value,
1571
+ t__namespace.booleanLiteral(false)
1572
+ ]);
1573
+ if (results.template[results.template.length - 1].length) {
1574
+ results.template.push("");
1575
+ results.templateValues.push(attr);
1576
+ } else {
1577
+ const last = results.templateValues.length - 1;
1578
+ results.templateValues[last] = t__namespace.binaryExpression("+", results.templateValues[last], attr);
1579
+ }
1528
1580
  }
1529
1581
 
1530
1582
  function escapeExpression(path, expression, attr) {
@@ -1711,23 +1763,15 @@ function transformAttributes$1(path, results) {
1711
1763
  children = value;
1712
1764
  if (key === "innerHTML") path.doNotEscape = true;
1713
1765
  } else {
1714
- let dynamic = false,
1715
- doEscape = true;
1716
- if (
1717
- isDynamic(attribute.get("value").get("expression"), {
1718
- checkMember: true,
1719
- native: true
1720
- })
1721
- )
1722
- dynamic = true;
1723
-
1766
+ let doEscape = true;
1724
1767
  if (BooleanAttributes.has(key)) {
1725
1768
  results.template.push("");
1726
- const fn = t__namespace.callExpression(registerImportMethod(attribute, "ssrBoolean"), [
1769
+ const fn = t__namespace.callExpression(registerImportMethod(attribute, "ssrAttribute"), [
1727
1770
  t__namespace.stringLiteral(key),
1728
- value.expression
1771
+ value.expression,
1772
+ t__namespace.booleanLiteral(true)
1729
1773
  ]);
1730
- results.templateValues.push(dynamic ? t__namespace.arrowFunctionExpression([], fn) : fn);
1774
+ results.templateValues.push(fn);
1731
1775
  return;
1732
1776
  }
1733
1777
  if (key === "style") {
@@ -1786,13 +1830,15 @@ function transformAttributes$1(path, results) {
1786
1830
  key = "class";
1787
1831
  doEscape = false;
1788
1832
  }
1789
- if (dynamic)
1790
- value.expression = t__namespace.arrowFunctionExpression(
1791
- [],
1792
- doEscape ? escapeExpression(path, value.expression, true) : value.expression
1793
- );
1794
- else if (doEscape) value.expression = escapeExpression(path, value.expression, true);
1795
- setAttr$1(results, key, value.expression, isSVG);
1833
+ if (doEscape)
1834
+ value.expression = escapeExpression(path, value.expression, true);
1835
+
1836
+ if (!doEscape || t__namespace.isLiteral(value.expression) || t__namespace.isBinaryExpression(value.expression)) {
1837
+ key = toAttribute(key, isSVG);
1838
+ appendToTemplate(results.template, ` ${key}="`);
1839
+ results.template.push(`"`);
1840
+ results.templateValues.push(value.expression);
1841
+ } else setAttr$1(attribute, results, key, value.expression, isSVG);
1796
1842
  }
1797
1843
  } else {
1798
1844
  if (key === "$ServerOnly") return;
@@ -1886,7 +1932,7 @@ function transformChildren$1(path, results, { hydratable }) {
1886
1932
  });
1887
1933
  }
1888
1934
 
1889
- function transformElement(path, info) {
1935
+ function transformElement$1(path, info) {
1890
1936
  let tagName = getTagName(path.node),
1891
1937
  results = {
1892
1938
  id: path.scope.generateUidIdentifier("el$"),
@@ -1894,13 +1940,21 @@ function transformElement(path, info) {
1894
1940
  exprs: [],
1895
1941
  dynamics: [],
1896
1942
  postExprs: [],
1897
- tagName
1943
+ tagName,
1944
+ renderer: "universal"
1898
1945
  };
1899
1946
 
1900
1947
  results.decl.push(
1901
1948
  t__namespace.variableDeclarator(
1902
1949
  results.id,
1903
- t__namespace.callExpression(registerImportMethod(path, "createElement"), [t__namespace.stringLiteral(tagName)])
1950
+ t__namespace.callExpression(
1951
+ registerImportMethod(
1952
+ path,
1953
+ "createElement",
1954
+ getRendererConfig(path, "universal").moduleName
1955
+ ),
1956
+ [t__namespace.stringLiteral(tagName)]
1957
+ )
1904
1958
  )
1905
1959
  );
1906
1960
 
@@ -1924,17 +1978,24 @@ function transformAttributes(path, results) {
1924
1978
  if (t__namespace.isJSXSpreadAttribute(node)) {
1925
1979
  results.exprs.push(
1926
1980
  t__namespace.expressionStatement(
1927
- t__namespace.callExpression(registerImportMethod(attribute, "spread"), [
1928
- elem,
1929
- isDynamic(attribute.get("argument"), {
1930
- checkMember: true
1931
- })
1932
- ? t__namespace.isCallExpression(node.argument) && !node.argument.arguments.length
1933
- ? node.argument.callee
1934
- : t__namespace.arrowFunctionExpression([], node.argument)
1935
- : node.argument,
1936
- t__namespace.booleanLiteral(hasChildren)
1937
- ])
1981
+ t__namespace.callExpression(
1982
+ registerImportMethod(
1983
+ attribute,
1984
+ "spread",
1985
+ getRendererConfig(path, "universal").moduleName
1986
+ ),
1987
+ [
1988
+ elem,
1989
+ isDynamic(attribute.get("argument"), {
1990
+ checkMember: true
1991
+ })
1992
+ ? t__namespace.isCallExpression(node.argument) && !node.argument.arguments.length
1993
+ ? node.argument.callee
1994
+ : t__namespace.arrowFunctionExpression([], node.argument)
1995
+ : node.argument,
1996
+ t__namespace.booleanLiteral(hasChildren)
1997
+ ]
1998
+ )
1938
1999
  )
1939
2000
  );
1940
2001
  return;
@@ -2004,7 +2065,7 @@ function transformAttributes(path, results) {
2004
2065
  }
2005
2066
  } else if (key.startsWith("use:")) {
2006
2067
  // Some trick to treat JSXIdentifier as Identifier
2007
- node.name.name.type = 'Identifier';
2068
+ node.name.name.type = "Identifier";
2008
2069
  results.exprs.unshift(
2009
2070
  t__namespace.expressionStatement(
2010
2071
  t__namespace.callExpression(node.name.name, [
@@ -2044,7 +2105,7 @@ function transformAttributes(path, results) {
2044
2105
  function setAttr(path, elem, name, value, { prevId } = {}) {
2045
2106
  if (!value) value = t__namespace.booleanLiteral(true);
2046
2107
  return t__namespace.callExpression(
2047
- registerImportMethod(path, "setProp"),
2108
+ registerImportMethod(path, "setProp", getRendererConfig(path, "universal").moduleName),
2048
2109
  prevId ? [elem, t__namespace.stringLiteral(name), value, prevId] : [elem, t__namespace.stringLiteral(name), value]
2049
2110
  );
2050
2111
  }
@@ -2064,33 +2125,47 @@ function transformChildren(path, results) {
2064
2125
  const appends = [];
2065
2126
  childNodes.forEach((child, index) => {
2066
2127
  if (!child) return;
2128
+ if (child.tagName && child.renderer !== "universal") {
2129
+ throw new Error(`<${child.tagName}> is not supported in <${getTagName(path.node)}>.
2130
+ Wrap the usage with a component that would render this element, eg. Canvas`);
2131
+ }
2067
2132
  if (child.id) {
2068
- const insertNode = registerImportMethod(path, "insertNode");
2133
+ let insertNode = registerImportMethod(
2134
+ path,
2135
+ "insertNode",
2136
+ getRendererConfig(path, "universal").moduleName
2137
+ );
2069
2138
  let insert = child.id;
2070
2139
  if (child.text) {
2071
- const createTextNode = registerImportMethod(path, "createTextNode");
2140
+ let createTextNode = registerImportMethod(
2141
+ path,
2142
+ "createTextNode",
2143
+ getRendererConfig(path, "universal").moduleName
2144
+ );
2072
2145
  if (multi) {
2073
2146
  results.decl.push(
2074
2147
  t__namespace.variableDeclarator(
2075
2148
  child.id,
2076
2149
  t__namespace.callExpression(createTextNode, [
2077
- t__namespace.stringLiteral(htmlEntities.decode(child.template))
2150
+ t__namespace.templateLiteral([t__namespace.templateElement({ raw: child.template })], [])
2078
2151
  ])
2079
2152
  )
2080
2153
  );
2081
2154
  } else
2082
2155
  insert = t__namespace.callExpression(createTextNode, [
2083
- t__namespace.stringLiteral(htmlEntities.decode(child.template))
2156
+ t__namespace.templateLiteral([t__namespace.templateElement({ raw: child.template })], [])
2084
2157
  ]);
2085
2158
  }
2086
- appends.push(
2087
- t__namespace.expressionStatement(t__namespace.callExpression(insertNode, [results.id, insert]))
2088
- );
2159
+ appends.push(t__namespace.expressionStatement(t__namespace.callExpression(insertNode, [results.id, insert])));
2089
2160
  results.decl.push(...child.decl);
2090
2161
  results.exprs.push(...child.exprs);
2091
2162
  results.dynamics.push(...child.dynamics);
2092
2163
  } else if (child.exprs.length) {
2093
- const insert = registerImportMethod(path, "insert");
2164
+ let insert = registerImportMethod(
2165
+ path,
2166
+ "insert",
2167
+ getRendererConfig(path, "universal").moduleName
2168
+ );
2094
2169
  if (multi) {
2095
2170
  results.exprs.push(
2096
2171
  t__namespace.expressionStatement(
@@ -2103,9 +2178,7 @@ function transformChildren(path, results) {
2103
2178
  );
2104
2179
  } else {
2105
2180
  results.exprs.push(
2106
- t__namespace.expressionStatement(
2107
- t__namespace.callExpression(insert, [results.id, child.exprs[0]])
2108
- )
2181
+ t__namespace.expressionStatement(t__namespace.callExpression(insert, [results.id, child.exprs[0]]))
2109
2182
  );
2110
2183
  }
2111
2184
  }
@@ -2418,13 +2491,7 @@ function transformComponent(path) {
2418
2491
  }
2419
2492
 
2420
2493
  function transformComponentChildren(children, config) {
2421
- const createTemplate$3 =
2422
- config.generate === "universal"
2423
- ? createTemplate
2424
- : config.generate === "ssr"
2425
- ? createTemplate$1
2426
- : createTemplate$2,
2427
- filteredChildren = filterChildren(children);
2494
+ const filteredChildren = filterChildren(children);
2428
2495
  if (!filteredChildren.length) return;
2429
2496
  let dynamic = false;
2430
2497
 
@@ -2438,7 +2505,7 @@ function transformComponentChildren(children, config) {
2438
2505
  componentChild: true
2439
2506
  });
2440
2507
  dynamic = dynamic || child.dynamic;
2441
- memo.push(createTemplate$3(path, child, filteredChildren.length > 1));
2508
+ memo.push(getCreateTemplate(config, path, child)(path, child, filteredChildren.length > 1));
2442
2509
  }
2443
2510
  return memo;
2444
2511
  }, []);
@@ -2466,20 +2533,14 @@ function transformComponentChildren(children, config) {
2466
2533
  }
2467
2534
 
2468
2535
  function transformFragmentChildren(children, results, config) {
2469
- const createTemplate$3 =
2470
- config.generate === "universal"
2471
- ? createTemplate
2472
- : config.generate === "ssr"
2473
- ? createTemplate$1
2474
- : createTemplate$2,
2475
- filteredChildren = filterChildren(children),
2536
+ const filteredChildren = filterChildren(children),
2476
2537
  childNodes = filteredChildren.reduce((memo, path) => {
2477
2538
  if (t__namespace.isJSXText(path.node)) {
2478
- const v = htmlEntities.decode(trimWhitespace(path.node.extra.raw));
2539
+ const v = htmlEntities.decode(trimWhitespace(path.node.extra.raw));
2479
2540
  if (v.length) memo.push(t__namespace.stringLiteral(v));
2480
2541
  } else {
2481
2542
  const child = transformNode(path, { topLevel: true, fragmentChild: true });
2482
- memo.push(createTemplate$3(path, child, true));
2543
+ memo.push(getCreateTemplate(config, path, child)(path, child, true));
2483
2544
  }
2484
2545
  return memo;
2485
2546
  }, []);
@@ -2497,12 +2558,9 @@ function transformJSX(path) {
2497
2558
  topLevel: true
2498
2559
  }
2499
2560
  );
2500
- const template =
2501
- config.generate === "universal"
2502
- ? createTemplate
2503
- : config.generate === "ssr"
2504
- ? createTemplate$1
2505
- : createTemplate$2;
2561
+
2562
+ const template = getCreateTemplate(config, path, result);
2563
+
2506
2564
  path.replaceWith(replace(template(path, result, false)));
2507
2565
  }
2508
2566
 
@@ -2531,17 +2589,10 @@ function transformNode(path, info = {}) {
2531
2589
  const node = path.node;
2532
2590
  let staticValue;
2533
2591
  if (t__namespace.isJSXElement(node)) {
2534
- let tagName = getTagName(node);
2535
- if (isComponent(tagName)) return transformComponent(path);
2536
- const element =
2537
- config.generate === "universal"
2538
- ? transformElement
2539
- : config.generate === "ssr"
2540
- ? transformElement$1
2541
- : transformElement$2;
2542
- return element(path, info);
2592
+ return transformElement(config, path, info);
2543
2593
  } else if (t__namespace.isJSXFragment(node)) {
2544
2594
  let results = { template: "", decl: [], exprs: [], dynamics: [] };
2595
+ // <><div /><Component /></>
2545
2596
  transformFragmentChildren(path.get("children"), results, config);
2546
2597
  return results;
2547
2598
  } else if (t__namespace.isJSXText(node) || (staticValue = getStaticExpression(path))) {
@@ -2553,7 +2604,7 @@ function transformNode(path, info = {}) {
2553
2604
  : trimWhitespace(node.extra.raw);
2554
2605
  if (!text.length) return null;
2555
2606
  const results = {
2556
- template: config.generate === "dom" ? escapeBackticks(text) : text,
2607
+ template: config.generate === "ssr" ? text : escapeBackticks(text),
2557
2608
  decl: [],
2558
2609
  exprs: [],
2559
2610
  dynamics: [],
@@ -2619,21 +2670,63 @@ function transformNode(path, info = {}) {
2619
2670
  }
2620
2671
  }
2621
2672
 
2673
+ function getCreateTemplate(config, path, result) {
2674
+ if ((result.tagName && result.renderer === "dom") || config.generate === "dom") {
2675
+ return createTemplate$2;
2676
+ }
2677
+
2678
+ if (result.renderer === "ssr" || config.generate === "ssr") {
2679
+ return createTemplate$1;
2680
+ }
2681
+
2682
+ return createTemplate;
2683
+ }
2684
+
2685
+ function transformElement(config, path, info = {}) {
2686
+ const node = path.node;
2687
+ let tagName = getTagName(node);
2688
+ // <Component ...></Component>
2689
+ if (isComponent(tagName)) return transformComponent(path);
2690
+
2691
+ // <div ...></div>
2692
+ // const element = getTransformElemet(config, path, tagName);
2693
+
2694
+ let tagRenderer;
2695
+ for (var renderer of config.renderers ?? []) {
2696
+ if (renderer.elements.indexOf(tagName) !== -1) {
2697
+ tagRenderer = renderer;
2698
+ break;
2699
+ }
2700
+ }
2701
+
2702
+ if (tagRenderer?.name === "dom" || getConfig(path).generate === "dom") {
2703
+ return transformElement$3(path, info);
2704
+ }
2705
+
2706
+ if (getConfig(path).generate === "ssr") {
2707
+ return transformElement$2(path, info);
2708
+ }
2709
+
2710
+ return transformElement$1(path);
2711
+ }
2712
+
2622
2713
  // add to the top/bottom of the module.
2623
2714
  var postprocess = path => {
2624
- const config = getConfig(path);
2625
2715
  if (path.scope.data.events) {
2626
2716
  path.node.body.push(
2627
2717
  t__namespace.expressionStatement(
2628
- t__namespace.callExpression(registerImportMethod(path, "delegateEvents"), [
2629
- t__namespace.arrayExpression(Array.from(path.scope.data.events).map(e => t__namespace.stringLiteral(e)))
2630
- ])
2718
+ t__namespace.callExpression(
2719
+ registerImportMethod(path, "delegateEvents", getRendererConfig(path, "dom").moduleName),
2720
+ [t__namespace.arrayExpression(Array.from(path.scope.data.events).map(e => t__namespace.stringLiteral(e)))]
2721
+ )
2631
2722
  )
2632
2723
  );
2633
2724
  }
2634
- if (path.scope.data.templates) {
2635
- const appendTemplates$2 = config.generate === "ssr" ? appendTemplates : appendTemplates$1;
2636
- appendTemplates$2(path, path.scope.data.templates);
2725
+ if (path.scope.data.templates?.length) {
2726
+ let domTemplates = path.scope.data.templates.filter(temp => temp.renderer === "dom");
2727
+ let ssrTemplates = path.scope.data.templates.filter(temp => temp.renderer === "ssr");
2728
+ domTemplates.length > 0 && appendTemplates$1(path, domTemplates);
2729
+ ssrTemplates.length > 0 && appendTemplates(path, ssrTemplates);
2637
2730
  }
2638
2731
  };
2639
2732