babel-plugin-jsx-dom-expressions 0.32.10 → 0.32.17

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 +937 -845
  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) {
@@ -286,6 +297,9 @@ function isDynamic(path, { checkMember, checkTags, checkCallExpressions = true,
286
297
  let dynamic;
287
298
  path.traverse({
288
299
  Function(p) {
300
+ if (t__namespace.isObjectMethod(p.node) && p.node.computed) {
301
+ dynamic = isDynamic(p.get("key"), { checkMember, checkTags, checkCallExpressions, native });
302
+ }
289
303
  p.skip();
290
304
  },
291
305
  CallExpression(p) {
@@ -314,6 +328,7 @@ function getStaticExpression(path) {
314
328
  t__namespace.isJSXExpressionContainer(node) &&
315
329
  t__namespace.isJSXElement(path.parent) &&
316
330
  !isComponent(getTagName(path.parent)) &&
331
+ !t__namespace.isSequenceExpression(node.expression) &&
317
332
  (value = path.get("expression").evaluate().value) !== undefined &&
318
333
  ((type = typeof value) === "string" || type === "number") &&
319
334
  value
@@ -401,10 +416,7 @@ function transformCondition(path, inline, deep) {
401
416
  if (!t__namespace.isBinaryExpression(cond))
402
417
  cond = t__namespace.unaryExpression("!", t__namespace.unaryExpression("!", cond, true), true);
403
418
  id = inline
404
- ? t__namespace.callExpression(memo, [
405
- t__namespace.arrowFunctionExpression([], cond),
406
- t__namespace.booleanLiteral(true)
407
- ])
419
+ ? t__namespace.callExpression(memo, [t__namespace.arrowFunctionExpression([], cond), t__namespace.booleanLiteral(true)])
408
420
  : path.scope.generateUidIdentifier("_c$");
409
421
  expr.test = t__namespace.callExpression(id, []);
410
422
  if (t__namespace.isConditionalExpression(expr.consequent) || t__namespace.isLogicalExpression(expr.consequent)) {
@@ -430,10 +442,7 @@ function transformCondition(path, inline, deep) {
430
442
  if (!t__namespace.isBinaryExpression(cond))
431
443
  cond = t__namespace.unaryExpression("!", t__namespace.unaryExpression("!", cond, true), true);
432
444
  id = inline
433
- ? t__namespace.callExpression(memo, [
434
- t__namespace.arrowFunctionExpression([], cond),
435
- t__namespace.booleanLiteral(true)
436
- ])
445
+ ? t__namespace.callExpression(memo, [t__namespace.arrowFunctionExpression([], cond), t__namespace.booleanLiteral(true)])
437
446
  : path.scope.generateUidIdentifier("_c$");
438
447
  nextPath.node.left = t__namespace.callExpression(id, []);
439
448
  }
@@ -444,10 +453,7 @@ function transformCondition(path, inline, deep) {
444
453
  t__namespace.variableDeclarator(
445
454
  id,
446
455
  config.memoWrapper
447
- ? t__namespace.callExpression(memo, [
448
- t__namespace.arrowFunctionExpression([], cond),
449
- t__namespace.booleanLiteral(true)
450
- ])
456
+ ? t__namespace.callExpression(memo, [t__namespace.arrowFunctionExpression([], cond), t__namespace.booleanLiteral(true)])
451
457
  : t__namespace.arrowFunctionExpression([], cond)
452
458
  )
453
459
  ]),
@@ -515,744 +521,774 @@ function escapeHTML(s, attr) {
515
521
  return left < s.length ? out + s.substring(left) : out;
516
522
  }
517
523
 
518
- function transformElement$2(path, info) {
519
- let tagName = getTagName(path.node),
520
- config = getConfig(path),
521
- wrapSVG = info.topLevel && tagName != "svg" && SVGElements.has(tagName),
522
- voidTag = VoidElements.indexOf(tagName) > -1,
523
- results = {
524
- template: `<${tagName}`,
525
- decl: [],
526
- exprs: [],
527
- dynamics: [],
528
- postExprs: [],
529
- isSVG: wrapSVG,
530
- tagName
531
- };
532
- if (tagName === "html" && config.hydratable) results.skipTemplate = true;
533
- if (wrapSVG) results.template = "<svg>" + results.template;
534
- if (!info.skipId) results.id = path.scope.generateUidIdentifier("el$");
535
- transformAttributes$2(path, results);
536
- if (config.contextToCustomElements && (tagName === "slot" || tagName.indexOf("-") > -1)) {
537
- contextToCustomElement(path, results);
538
- }
539
- results.template += ">";
540
- if (!voidTag) {
541
- transformChildren$2(path, results, config);
542
- results.template += `</${tagName}>`;
543
- }
544
- if (info.topLevel && config.hydratable && results.hasHydratableEvent) {
545
- results.postExprs.push(
546
- t__namespace.expressionStatement(t__namespace.callExpression(registerImportMethod(path, "runHydrationEvents"), []))
547
- );
548
- }
549
- if (wrapSVG) results.template += "</svg>";
550
- return results;
551
- }
552
-
553
- function setAttr$2(path, elem, name, value, { isSVG, dynamic, prevId, isCE }) {
554
- // pull out namespace
555
- const config = getConfig(path);
556
- let parts, namespace;
557
- if ((parts = name.split(":")) && parts[1] && reservedNameSpaces.has(parts[0])) {
558
- name = parts[1];
559
- namespace = parts[0];
560
- }
561
-
562
- if (namespace === "style") {
563
- return t__namespace.callExpression(
564
- t__namespace.memberExpression(
565
- t__namespace.memberExpression(elem, t__namespace.identifier("style")),
566
- t__namespace.identifier("setProperty")
567
- ),
568
- [t__namespace.stringLiteral(name), value]
569
- );
570
- }
571
-
572
- if (namespace === "class") {
573
- return t__namespace.callExpression(
574
- t__namespace.memberExpression(
575
- t__namespace.memberExpression(elem, t__namespace.identifier("classList")),
576
- t__namespace.identifier("toggle")
577
- ),
578
- [t__namespace.stringLiteral(name), value]
579
- );
580
- }
581
-
582
- if (name === "style") {
583
- return t__namespace.callExpression(
584
- registerImportMethod(path, "style"),
585
- prevId ? [elem, value, prevId] : [elem, value]
586
- );
587
- }
588
-
589
- if (!isSVG && name === "class") {
590
- return t__namespace.assignmentExpression("=", t__namespace.memberExpression(elem, t__namespace.identifier("className")), value);
591
- }
592
-
593
- if (name === "classList") {
594
- return t__namespace.callExpression(
595
- registerImportMethod(path, "classList"),
596
- prevId ? [elem, value, prevId] : [elem, value]
597
- );
598
- }
599
-
600
- if (config.hydratable && name === "innerHTML") {
601
- return t__namespace.callExpression(
602
- registerImportMethod(path, "innerHTML"),
603
- [elem, value]
604
- );
605
- }
606
-
607
- if (dynamic && name === "textContent") {
608
- return t__namespace.assignmentExpression("=", t__namespace.memberExpression(elem, t__namespace.identifier("data")), value);
609
- }
610
-
611
- const isChildProp = ChildProperties.has(name);
612
- const isProp = Properties.has(name);
613
- const alias = PropAliases[name];
614
- if (namespace !== "attr" && (isChildProp || (!isSVG && isProp) || isCE || namespace === "prop")) {
615
- if (isCE && !isChildProp && !isProp && namespace !== "prop") name = toPropertyName(name);
616
- return t__namespace.assignmentExpression(
617
- "=",
618
- t__namespace.memberExpression(elem, t__namespace.identifier(alias || name)),
619
- value
620
- );
621
- }
622
-
623
- let isNameSpaced = name.indexOf(":") > -1;
624
- name = Aliases[name] || name;
625
- !isSVG && (name = name.toLowerCase());
626
- const ns = isNameSpaced && SVGNamespace[name.split(":")[0]];
627
- if (ns) {
628
- return t__namespace.callExpression(registerImportMethod(path, "setAttributeNS"), [
629
- elem,
630
- t__namespace.stringLiteral(ns),
631
- t__namespace.stringLiteral(name),
632
- value
633
- ]);
634
- } else {
635
- return t__namespace.callExpression(registerImportMethod(path, "setAttribute"), [elem, t__namespace.stringLiteral(name), value]);
636
- }
637
- }
638
-
639
- function detectResolvableEventHandler(attribute, handler) {
640
- while (t__namespace.isIdentifier(handler)) {
641
- const lookup = attribute.scope.getBinding(handler.name);
642
- if (lookup) {
643
- if (t__namespace.isVariableDeclarator(lookup.path.node)) {
644
- handler = lookup.path.node.init;
645
- } else if (t__namespace.isFunctionDeclaration(lookup.path.node)) {
646
- return true;
647
- } else return false;
648
- } else return false;
649
- }
650
- return t__namespace.isFunction(handler);
651
- }
652
-
653
- function transformAttributes$2(path, results) {
654
- let elem = results.id,
655
- hasHydratableEvent = false,
656
- children,
657
- attributes = path.get("openingElement").get("attributes");
658
- const tagName = getTagName(path.node),
659
- isSVG = SVGElements.has(tagName),
660
- isCE = tagName.includes("-"),
661
- hasChildren = path.node.children.length > 0,
662
- config = getConfig(path);
663
-
664
- // preprocess styles
665
- const styleAttribute = attributes.find(
666
- a =>
667
- a.node.name &&
668
- a.node.name.name === "style" &&
669
- t__namespace.isJSXExpressionContainer(a.node.value) &&
670
- t__namespace.isObjectExpression(a.node.value.expression) &&
671
- !a.node.value.expression.properties.some(p => t__namespace.isSpreadElement(p))
672
- );
673
- if (styleAttribute) {
674
- let i = 0,
675
- leading = styleAttribute.node.value.expression.leadingComments;
676
- styleAttribute.node.value.expression.properties.slice().forEach((p, index) => {
677
- if (!p.computed) {
678
- if (leading) p.value.leadingComments = leading;
679
- path
680
- .get("openingElement")
681
- .node.attributes.splice(
682
- styleAttribute.key + ++i,
683
- 0,
684
- t__namespace.JSXAttribute(
685
- t__namespace.JSXNamespacedName(
686
- t__namespace.JSXIdentifier("style"),
687
- t__namespace.JSXIdentifier(t__namespace.isIdentifier(p.key) ? p.key.name : p.key.value)
688
- ),
689
- t__namespace.JSXExpressionContainer(p.value)
690
- )
691
- );
692
- styleAttribute.node.value.expression.properties.splice(index - i - 1, 1);
693
- }
694
- });
695
- if (!styleAttribute.node.value.expression.properties.length)
696
- path.get("openingElement").node.attributes.splice(styleAttribute.key, 1);
697
- }
698
-
699
- // preprocess classList
700
- attributes = path.get("openingElement").get("attributes");
701
- const classListAttribute = attributes.find(
702
- a =>
703
- a.node.name &&
704
- a.node.name.name === "classList" &&
705
- t__namespace.isJSXExpressionContainer(a.node.value) &&
706
- t__namespace.isObjectExpression(a.node.value.expression) &&
707
- !a.node.value.expression.properties.some(
708
- p =>
709
- t__namespace.isSpreadElement(p) ||
710
- p.computed ||
711
- (t__namespace.isStringLiteral(p.key) && (p.key.value.includes(" ") || p.key.value.includes(":")))
712
- )
713
- );
714
- if (classListAttribute) {
715
- let i = 0,
716
- leading = classListAttribute.node.value.expression.leadingComments,
717
- classListProperties = classListAttribute.get("value").get("expression").get("properties");
718
- classListProperties.slice().forEach((propPath, index) => {
719
- const p = propPath.node;
720
- const { confident, value: computed } = propPath.get("value").evaluate();
721
- if (leading) p.value.leadingComments = leading;
722
- if (!confident) {
723
- path
724
- .get("openingElement")
725
- .node.attributes.splice(
726
- classListAttribute.key + ++i,
727
- 0,
728
- t__namespace.JSXAttribute(
729
- t__namespace.JSXNamespacedName(
730
- t__namespace.JSXIdentifier("class"),
731
- t__namespace.JSXIdentifier(t__namespace.isIdentifier(p.key) ? p.key.name : p.key.value)
732
- ),
733
- t__namespace.JSXExpressionContainer(p.value)
734
- )
735
- );
736
- } else if (computed) {
737
- path
738
- .get("openingElement")
739
- .node.attributes.splice(
740
- classListAttribute.key + ++i,
741
- 0,
742
- t__namespace.JSXAttribute(
743
- t__namespace.JSXIdentifier("class"),
744
- t__namespace.stringLiteral(t__namespace.isIdentifier(p.key) ? p.key.name : p.key.value)
745
- )
746
- );
747
- }
748
- classListProperties.splice(index - i - 1, 1);
749
- });
750
- if (!classListProperties.length)
751
- path.get("openingElement").node.attributes.splice(classListAttribute.key, 1);
752
- }
753
-
754
- // combine class properties
755
- attributes = path.get("openingElement").get("attributes");
756
- const classAttributes = attributes.filter(
757
- a => a.node.name && (a.node.name.name === "class" || a.node.name.name === "className")
758
- );
759
- if (classAttributes.length > 1) {
760
- const first = classAttributes[0].node,
761
- values = [],
762
- quasis = [t__namespace.TemplateElement({ raw: "" })];
763
- for (let i = 0; i < classAttributes.length; i++) {
764
- const attr = classAttributes[i].node,
765
- isLast = i === classAttributes.length - 1;
766
- if (!t__namespace.isJSXExpressionContainer(attr.value)) {
767
- const prev = quasis.pop();
768
- quasis.push(
769
- t__namespace.TemplateElement({
770
- raw: (prev ? prev.value.raw : "") + `${attr.value.value}` + (isLast ? "" : " ")
771
- })
772
- );
773
- } else {
774
- values.push(t__namespace.logicalExpression("||", attr.value.expression, t__namespace.stringLiteral("")));
775
- quasis.push(t__namespace.TemplateElement({ raw: isLast ? "" : " " }));
776
- }
777
- i && attributes.splice(attributes.indexOf(classAttributes[i]), 1);
778
- }
779
- if (values.length) first.value = t__namespace.JSXExpressionContainer(t__namespace.TemplateLiteral(quasis, values));
780
- else first.value = t__namespace.stringLiteral(quasis[0].value.raw);
781
- }
782
- path.get("openingElement").set(
783
- "attributes",
784
- attributes.map(a => a.node)
785
- );
786
-
787
- path
788
- .get("openingElement")
789
- .get("attributes")
790
- .forEach(attribute => {
791
- const node = attribute.node;
792
- if (t__namespace.isJSXSpreadAttribute(node)) {
793
- results.exprs.push(
794
- t__namespace.expressionStatement(
795
- t__namespace.callExpression(registerImportMethod(attribute, "spread"), [
796
- elem,
797
- isDynamic(attribute.get("argument"), {
798
- checkMember: true
799
- })
800
- ? t__namespace.isCallExpression(node.argument) && !node.argument.arguments.length
801
- ? node.argument.callee
802
- : t__namespace.arrowFunctionExpression([], node.argument)
803
- : node.argument,
804
- t__namespace.booleanLiteral(isSVG),
805
- t__namespace.booleanLiteral(hasChildren)
806
- ])
807
- )
808
- );
809
- //NOTE: can't be checked at compile time so add to compiled output
810
- hasHydratableEvent = true;
811
- return;
812
- }
813
-
814
- let value = node.value,
815
- key = t__namespace.isJSXNamespacedName(node.name)
816
- ? `${node.name.namespace.name}:${node.name.name.name}`
817
- : node.name.name,
818
- reservedNameSpace =
819
- t__namespace.isJSXNamespacedName(node.name) && reservedNameSpaces.has(node.name.namespace.name);
820
- if (t__namespace.isJSXExpressionContainer(value) && !key.startsWith("use:")) {
821
- const evaluated = attribute.get("value").get("expression").evaluate().value;
822
- let type;
823
- if (
824
- evaluated !== undefined &&
825
- ((type = typeof evaluated) === "string" || type === "number")
826
- ) {
827
- value = t__namespace.stringLiteral(String(evaluated));
828
- }
829
- }
830
- if (
831
- t__namespace.isJSXNamespacedName(node.name) &&
832
- reservedNameSpace &&
833
- !t__namespace.isJSXExpressionContainer(value)
834
- ) {
835
- node.value = value = t__namespace.JSXExpressionContainer(value || t__namespace.JSXEmptyExpression());
836
- }
837
- if (
838
- t__namespace.isJSXExpressionContainer(value) &&
839
- (reservedNameSpace ||
840
- !(t__namespace.isStringLiteral(value.expression) || t__namespace.isNumericLiteral(value.expression)))
841
- ) {
842
- if (key === "ref") {
843
- // Normalize expressions for non-null and type-as
844
- while (
845
- t__namespace.isTSNonNullExpression(value.expression) ||
846
- t__namespace.isTSAsExpression(value.expression)
847
- ) {
848
- value.expression = value.expression.expression;
849
- }
850
- let binding,
851
- isFunction =
852
- t__namespace.isIdentifier(value.expression) &&
853
- (binding = path.scope.getBinding(value.expression.name)) &&
854
- binding.kind === "const";
855
- if (!isFunction && t__namespace.isLVal(value.expression)) {
856
- const refIdentifier = path.scope.generateUidIdentifier("_ref$");
857
- results.exprs.unshift(
858
- t__namespace.variableDeclaration("const", [
859
- t__namespace.variableDeclarator(refIdentifier, value.expression)
860
- ]),
861
- t__namespace.expressionStatement(
862
- t__namespace.conditionalExpression(
863
- t__namespace.binaryExpression(
864
- "===",
865
- t__namespace.unaryExpression("typeof", refIdentifier),
866
- t__namespace.stringLiteral("function")
867
- ),
868
- t__namespace.callExpression(refIdentifier, [elem]),
869
- t__namespace.assignmentExpression("=", value.expression, elem)
870
- )
871
- )
872
- );
873
- } else if (isFunction || t__namespace.isFunction(value.expression)) {
874
- results.exprs.unshift(
875
- t__namespace.expressionStatement(t__namespace.callExpression(value.expression, [elem]))
876
- );
877
- } else if (t__namespace.isCallExpression(value.expression)) {
878
- const refIdentifier = path.scope.generateUidIdentifier("_ref$");
879
- results.exprs.unshift(
880
- t__namespace.variableDeclaration("const", [
881
- t__namespace.variableDeclarator(refIdentifier, value.expression)
882
- ]),
883
- t__namespace.expressionStatement(
884
- t__namespace.logicalExpression(
885
- "&&",
886
- t__namespace.binaryExpression(
887
- "===",
888
- t__namespace.unaryExpression("typeof", refIdentifier),
889
- t__namespace.stringLiteral("function")
890
- ),
891
- t__namespace.callExpression(refIdentifier, [elem])
892
- )
893
- )
894
- );
895
- }
896
- } else if (key.startsWith("use:")) {
897
- // Some trick to treat JSXIdentifier as Identifier
898
- node.name.name.type = 'Identifier';
899
- results.exprs.unshift(
900
- t__namespace.expressionStatement(
901
- t__namespace.callExpression(node.name.name, [
902
- elem,
903
- t__namespace.arrowFunctionExpression(
904
- [],
905
- t__namespace.isJSXEmptyExpression(value.expression)
906
- ? t__namespace.booleanLiteral(true)
907
- : value.expression
908
- )
909
- ])
910
- )
911
- );
912
- } else if (key === "children") {
913
- children = value;
914
- } else if (key.startsWith("on")) {
915
- const ev = toEventName(key);
916
- if (key.startsWith("on:") || key.startsWith("oncapture:")) {
917
- const listenerOptions = [t__namespace.stringLiteral(key.split(":")[1]), value.expression];
918
- results.exprs.push(
919
- t__namespace.expressionStatement(
920
- t__namespace.callExpression(
921
- t__namespace.memberExpression(elem, t__namespace.identifier("addEventListener")),
922
- key.startsWith("oncapture:")
923
- ? listenerOptions.concat(t__namespace.booleanLiteral(true))
924
- : listenerOptions
925
- )
926
- )
927
- );
928
- } else if (
929
- config.delegateEvents &&
930
- (DelegatedEvents.has(ev) || config.delegatedEvents.indexOf(ev) !== -1)
931
- ) {
932
- // can only hydrate delegated events
933
- hasHydratableEvent = true;
934
- const events =
935
- attribute.scope.getProgramParent().data.events ||
936
- (attribute.scope.getProgramParent().data.events = new Set());
937
- events.add(ev);
938
- let handler = value.expression;
939
- const resolveable = detectResolvableEventHandler(attribute, handler);
940
- if (t__namespace.isArrayExpression(handler)) {
941
- if (handler.elements.length > 1) {
942
- results.exprs.unshift(
943
- t__namespace.expressionStatement(
944
- t__namespace.assignmentExpression(
945
- "=",
946
- t__namespace.memberExpression(elem, t__namespace.identifier(`$$${ev}Data`)),
947
- handler.elements[1]
948
- )
949
- )
950
- );
951
- }
952
- handler = handler.elements[0];
953
- results.exprs.unshift(
954
- t__namespace.expressionStatement(
955
- t__namespace.assignmentExpression(
956
- "=",
957
- t__namespace.memberExpression(elem, t__namespace.identifier(`$$${ev}`)),
958
- handler
959
- )
960
- )
961
- );
962
- } else if (t__namespace.isFunction(handler) || resolveable) {
963
- results.exprs.unshift(
964
- t__namespace.expressionStatement(
965
- t__namespace.assignmentExpression(
966
- "=",
967
- t__namespace.memberExpression(elem, t__namespace.identifier(`$$${ev}`)),
968
- handler
969
- )
970
- )
971
- );
972
- } else {
973
- results.exprs.unshift(
974
- t__namespace.expressionStatement(
975
- t__namespace.callExpression(registerImportMethod(path, "addEventListener"), [
976
- elem,
977
- t__namespace.stringLiteral(ev),
978
- handler,
979
- t__namespace.booleanLiteral(true)
980
- ])
981
- )
982
- );
983
- }
984
- } else {
985
- let handler = value.expression;
986
- const resolveable = detectResolvableEventHandler(attribute, handler);
987
- if (t__namespace.isArrayExpression(handler)) {
988
- if (handler.elements.length > 1) {
989
- handler = t__namespace.arrowFunctionExpression(
990
- [t__namespace.identifier("e")],
991
- t__namespace.callExpression(handler.elements[0], [handler.elements[1], t__namespace.identifier("e")])
992
- );
993
- } else handler = handler.elements[0];
994
- results.exprs.unshift(
995
- t__namespace.expressionStatement(
996
- t__namespace.callExpression(t__namespace.memberExpression(elem, t__namespace.identifier("addEventListener")), [
997
- t__namespace.stringLiteral(ev),
998
- handler
999
- ])
1000
- )
1001
- );
1002
- } else if (t__namespace.isFunction(handler) || resolveable) {
1003
- results.exprs.unshift(
1004
- t__namespace.expressionStatement(
1005
- t__namespace.callExpression(t__namespace.memberExpression(elem, t__namespace.identifier("addEventListener")), [
1006
- t__namespace.stringLiteral(ev),
1007
- handler
1008
- ])
1009
- )
1010
- );
1011
- } else {
1012
- results.exprs.unshift(
1013
- t__namespace.expressionStatement(
1014
- t__namespace.callExpression(registerImportMethod(path, "addEventListener"), [
1015
- elem,
1016
- t__namespace.stringLiteral(ev),
1017
- handler
1018
- ])
1019
- )
1020
- );
1021
- }
1022
- }
1023
- } else if (
1024
- config.effectWrapper &&
1025
- isDynamic(attribute.get("value").get("expression"), {
1026
- checkMember: true
1027
- })
1028
- ) {
1029
- let nextElem = elem;
1030
- if (key === "textContent") {
1031
- nextElem = attribute.scope.generateUidIdentifier("el$");
1032
- children = t__namespace.JSXText(" ");
1033
- children.extra = { raw: " ", rawValue: " " };
1034
- results.decl.push(
1035
- t__namespace.variableDeclarator(nextElem, t__namespace.memberExpression(elem, t__namespace.identifier("firstChild")))
1036
- );
1037
- }
1038
- results.dynamics.push({ elem: nextElem, key, value: value.expression, isSVG, isCE });
1039
- } else {
1040
- results.exprs.push(
1041
- t__namespace.expressionStatement(setAttr$2(attribute, elem, key, value.expression, { isSVG, isCE }))
1042
- );
1043
- }
1044
- } else {
1045
- if (config.hydratable && key === "$ServerOnly") {
1046
- results.skipTemplate = true;
1047
- return;
1048
- }
1049
- if (t__namespace.isJSXExpressionContainer(value)) value = value.expression;
1050
- key = Aliases[key] || key;
1051
- if (value && ChildProperties.has(key)) {
1052
- results.exprs.push(
1053
- t__namespace.expressionStatement(setAttr$2(attribute, elem, key, value, { isSVG, isCE }))
1054
- );
1055
- } else {
1056
- !isSVG && (key = key.toLowerCase());
1057
- results.template += ` ${key}`;
1058
- results.template += value ? `="${escapeBackticks(value.value)}"` : "";
1059
- }
1060
- }
1061
- });
1062
- if (!hasChildren && children) {
1063
- path.node.children.push(children);
1064
- }
1065
-
1066
- results.hasHydratableEvent = results.hasHydratableEvent || hasHydratableEvent;
1067
- }
1068
-
1069
- function transformChildren$2(path, results, config) {
1070
- let tempPath = results.id && results.id.name,
1071
- tagName = getTagName(path.node),
1072
- nextPlaceholder,
1073
- i = 0;
1074
- const filteredChildren = filterChildren(path.get("children")),
1075
- childNodes = filteredChildren
1076
- .map(
1077
- (child, index) =>
1078
- transformNode(child, {
1079
- skipId: !results.id || !detectExpressions(filteredChildren, index, config)
1080
- })
1081
- // combine adjacent textNodes
1082
- )
1083
- .reduce((memo, child) => {
1084
- if (!child) return memo;
1085
- const i = memo.length;
1086
- if (child.text && i && memo[i - 1].text) {
1087
- memo[i - 1].template += child.template;
1088
- } else memo.push(child);
1089
- return memo;
1090
- }, []);
1091
-
1092
- childNodes.forEach((child, index) => {
1093
- if (!child) return;
1094
- results.template += child.template;
1095
- if (child.id) {
1096
- if (child.tagName === "head") return;
1097
- if (config.hydratable && tagName === "html") {
1098
- registerImportMethod(path, "getNextMatch");
1099
- }
1100
- const walk = t__namespace.memberExpression(
1101
- t__namespace.identifier(tempPath),
1102
- t__namespace.identifier(i === 0 ? "firstChild" : "nextSibling")
1103
- );
1104
- results.decl.push(
1105
- t__namespace.variableDeclarator(
1106
- child.id,
1107
- config.hydratable && tagName === "html"
1108
- ? t__namespace.callExpression(registerImportMethod(path, "getNextMatch"), [
1109
- walk,
1110
- t__namespace.stringLiteral(child.tagName)
1111
- ])
1112
- : walk
1113
- )
1114
- );
1115
- results.decl.push(...child.decl);
1116
- results.exprs.push(...child.exprs);
1117
- results.dynamics.push(...child.dynamics);
1118
- results.hasHydratableEvent = results.hasHydratableEvent || child.hasHydratableEvent;
1119
- tempPath = child.id.name;
1120
- nextPlaceholder = null;
1121
- i++;
1122
- } else if (child.exprs.length) {
1123
- const insert = registerImportMethod(path, "insert");
1124
- const multi = checkLength(filteredChildren),
1125
- markers = config.hydratable && multi;
1126
- // boxed by textNodes
1127
- if (markers || wrappedByText(childNodes, index)) {
1128
- let exprId, contentId;
1129
- if (markers) tempPath = createPlaceholder(path, results, tempPath, i++, "#")[0].name;
1130
- if (nextPlaceholder) {
1131
- exprId = nextPlaceholder;
1132
- } else {
1133
- [exprId, contentId] = createPlaceholder(path, results, tempPath, i++, markers ? "/" : "");
1134
- }
1135
- if (!markers) nextPlaceholder = exprId;
1136
- results.exprs.push(
1137
- t__namespace.expressionStatement(
1138
- t__namespace.callExpression(
1139
- insert,
1140
- contentId
1141
- ? [results.id, child.exprs[0], exprId, contentId]
1142
- : [results.id, child.exprs[0], exprId]
1143
- )
1144
- )
1145
- );
1146
- tempPath = exprId.name;
1147
- } else if (multi) {
1148
- results.exprs.push(
1149
- t__namespace.expressionStatement(
1150
- t__namespace.callExpression(insert, [
1151
- results.id,
1152
- child.exprs[0],
1153
- nextChild$1(childNodes, index) || t__namespace.nullLiteral()
1154
- ])
1155
- )
1156
- );
1157
- } else {
1158
- results.exprs.push(
1159
- t__namespace.expressionStatement(
1160
- t__namespace.callExpression(
1161
- insert,
1162
- [results.id, child.exprs[0]]
1163
- )
1164
- )
1165
- );
1166
- }
1167
- } else nextPlaceholder = null;
1168
- });
1169
- }
1170
-
1171
- function createPlaceholder(path, results, tempPath, i, char) {
1172
- const exprId = path.scope.generateUidIdentifier("el$"),
1173
- config = getConfig(path);
1174
- let contentId;
1175
- results.template += `<!${char}>`;
1176
- if (config.hydratable && char === "/") {
1177
- contentId = path.scope.generateUidIdentifier("co$");
1178
- results.decl.push(
1179
- t__namespace.variableDeclarator(
1180
- t__namespace.arrayPattern([exprId, contentId]),
1181
- t__namespace.callExpression(registerImportMethod(path, "getNextMarker"), [
1182
- t__namespace.memberExpression(t__namespace.identifier(tempPath), t__namespace.identifier("nextSibling"))
1183
- ])
1184
- )
1185
- );
1186
- } else
1187
- results.decl.push(
1188
- t__namespace.variableDeclarator(
1189
- exprId,
1190
- t__namespace.memberExpression(
1191
- t__namespace.identifier(tempPath),
1192
- t__namespace.identifier(i === 0 ? "firstChild" : "nextSibling")
1193
- )
1194
- )
1195
- );
1196
- return [exprId, contentId];
1197
- }
1198
-
1199
- function nextChild$1(children, index) {
1200
- return children[index + 1] && (children[index + 1].id || nextChild$1(children, index + 1));
1201
- }
1202
-
1203
- // reduce unnecessary refs
1204
- function detectExpressions(children, index, config) {
1205
- if (children[index - 1]) {
1206
- const node = children[index - 1].node;
1207
- if (
1208
- t__namespace.isJSXExpressionContainer(node) &&
1209
- !t__namespace.isJSXEmptyExpression(node.expression) &&
1210
- !getStaticExpression(children[index - 1])
1211
- )
1212
- return true;
1213
- let tagName;
1214
- if (t__namespace.isJSXElement(node) && (tagName = getTagName(node)) && isComponent(tagName)) return true;
1215
- }
1216
- for (let i = index; i < children.length; i++) {
1217
- const child = children[i].node;
1218
- if (t__namespace.isJSXExpressionContainer(child)) {
1219
- if (!t__namespace.isJSXEmptyExpression(child.expression) && !getStaticExpression(children[i]))
1220
- return true;
1221
- } else if (t__namespace.isJSXElement(child)) {
1222
- const tagName = getTagName(child);
1223
- if (isComponent(tagName)) return true;
1224
- if (config.contextToCustomElements && (tagName === "slot" || tagName.indexOf("-") > -1))
1225
- return true;
1226
- if (
1227
- child.openingElement.attributes.some(
1228
- attr =>
1229
- t__namespace.isJSXSpreadAttribute(attr) ||
1230
- ["textContent", "innerHTML", "innerText"].includes(attr.name.name) ||
1231
- (attr.name.namespace && attr.name.namespace.name === "use") ||
1232
- (t__namespace.isJSXExpressionContainer(attr.value) &&
1233
- !(
1234
- t__namespace.isStringLiteral(attr.value.expression) ||
1235
- t__namespace.isNumericLiteral(attr.value.expression)
1236
- ))
1237
- )
1238
- )
1239
- return true;
1240
- const nextChildren = filterChildren(children[i].get("children"));
1241
- if (nextChildren.length) if (detectExpressions(nextChildren, 0, config)) return true;
1242
- }
1243
- }
1244
- }
1245
-
1246
- function contextToCustomElement(path, results) {
1247
- results.exprs.push(
1248
- t__namespace.expressionStatement(
1249
- t__namespace.assignmentExpression(
1250
- "=",
1251
- t__namespace.memberExpression(results.id, t__namespace.identifier("_$owner")),
1252
- t__namespace.callExpression(registerImportMethod(path, "getOwner"), [])
1253
- )
1254
- )
1255
- );
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.assignmentExpression("=", t__namespace.memberExpression(elem, t__namespace.identifier("className")), 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
+ );
1256
1292
  }
1257
1293
 
1258
1294
  function createTemplate$2(path, result, wrap) {
@@ -1297,14 +1333,14 @@ function appendTemplates$1(path, templates) {
1297
1333
  template.id,
1298
1334
  t__namespace.addComment(
1299
1335
  t__namespace.callExpression(
1300
- registerImportMethod(path, "template"),
1336
+ registerImportMethod(path, "template", getRendererConfig(path, "dom").moduleName),
1301
1337
  [
1302
1338
  t__namespace.templateLiteral([t__namespace.templateElement(tmpl, true)], []),
1303
1339
  t__namespace.numericLiteral(template.elementCount)
1304
1340
  ].concat(template.isSVG ? t__namespace.booleanLiteral(template.isSVG) : [])
1305
1341
  ),
1306
- 'leading',
1307
- '#__PURE__'
1342
+ "leading",
1343
+ "#__PURE__"
1308
1344
  )
1309
1345
  );
1310
1346
  });
@@ -1328,14 +1364,18 @@ function registerTemplate(path, results) {
1328
1364
  id: templateId,
1329
1365
  template: results.template,
1330
1366
  elementCount: results.template.split("<").length - 1,
1331
- isSVG: results.isSVG
1367
+ isSVG: results.isSVG,
1368
+ renderer: "dom"
1332
1369
  });
1333
1370
  }
1334
1371
  }
1335
1372
  decl = t__namespace.variableDeclarator(
1336
1373
  results.id,
1337
1374
  hydratable
1338
- ? t__namespace.callExpression(registerImportMethod(path, "getNextElement"), templateId ? [templateId] : [])
1375
+ ? t__namespace.callExpression(
1376
+ registerImportMethod(path, "getNextElement", getRendererConfig(path, "dom").moduleName),
1377
+ templateId ? [templateId] : []
1378
+ )
1339
1379
  : t__namespace.callExpression(t__namespace.memberExpression(templateId, t__namespace.identifier("cloneNode")), [
1340
1380
  t__namespace.booleanLiteral(true)
1341
1381
  ])
@@ -1441,20 +1481,24 @@ function createTemplate$1(path, result) {
1441
1481
  }
1442
1482
 
1443
1483
  const templates =
1444
- path.scope.getProgramParent().data.templates ||
1445
- (path.scope.getProgramParent().data.templates = []);
1484
+ path.scope.getProgramParent().data.templates ||
1485
+ (path.scope.getProgramParent().data.templates = []);
1446
1486
  const found = templates.find(tmp => {
1447
- if (t__namespace.isArrayExpression(tmp[1]) && t__namespace.isArrayExpression(template)) {
1448
- return tmp[1].elements.every(
1487
+ if (t__namespace.isArrayExpression(tmp.template) && t__namespace.isArrayExpression(template)) {
1488
+ return tmp.template.elements.every(
1449
1489
  (el, i) => template.elements[i] && el.value === template.elements[i].value
1450
1490
  );
1451
1491
  }
1452
- return tmp[1].value === template.value;
1492
+ return tmp.template.value === template.value;
1453
1493
  });
1454
1494
  if (!found) {
1455
1495
  id = path.scope.generateUidIdentifier("tmpl$");
1456
- templates.push([id, template]);
1457
- } else id = found[0];
1496
+ templates.push({
1497
+ id,
1498
+ template,
1499
+ renderer: "ssr"
1500
+ });
1501
+ } else id = found.id;
1458
1502
 
1459
1503
  return t__namespace.callExpression(
1460
1504
  registerImportMethod(path, "ssr"),
@@ -1464,7 +1508,7 @@ function createTemplate$1(path, result) {
1464
1508
 
1465
1509
  function appendTemplates(path, templates) {
1466
1510
  const declarators = templates.map(template => {
1467
- return t__namespace.variableDeclarator(template[0], template[1]);
1511
+ return t__namespace.variableDeclarator(template.id, template.template);
1468
1512
  });
1469
1513
  path.node.body.unshift(t__namespace.variableDeclaration("const", declarators));
1470
1514
  }
@@ -1478,7 +1522,7 @@ function appendToTemplate(template, value) {
1478
1522
  if (array && array.length) template.push.apply(template, array);
1479
1523
  }
1480
1524
 
1481
- function transformElement$1(path, info) {
1525
+ function transformElement$2(path, info) {
1482
1526
  let tagName = getTagName(path.node),
1483
1527
  config = getConfig(path),
1484
1528
  voidTag = VoidElements.indexOf(tagName) > -1,
@@ -1488,8 +1532,10 @@ function transformElement$1(path, info) {
1488
1532
  decl: [],
1489
1533
  exprs: [],
1490
1534
  dynamics: [],
1491
- tagName
1535
+ tagName,
1536
+ renderer: "ssr"
1492
1537
  };
1538
+
1493
1539
  if (info.topLevel && config.hydratable) {
1494
1540
  results.template.push("");
1495
1541
  results.templateValues.push(
@@ -1883,7 +1929,7 @@ function transformChildren$1(path, results, { hydratable }) {
1883
1929
  });
1884
1930
  }
1885
1931
 
1886
- function transformElement(path, info) {
1932
+ function transformElement$1(path, info) {
1887
1933
  let tagName = getTagName(path.node),
1888
1934
  results = {
1889
1935
  id: path.scope.generateUidIdentifier("el$"),
@@ -1891,13 +1937,21 @@ function transformElement(path, info) {
1891
1937
  exprs: [],
1892
1938
  dynamics: [],
1893
1939
  postExprs: [],
1894
- tagName
1940
+ tagName,
1941
+ renderer: "universal"
1895
1942
  };
1896
1943
 
1897
1944
  results.decl.push(
1898
1945
  t__namespace.variableDeclarator(
1899
1946
  results.id,
1900
- t__namespace.callExpression(registerImportMethod(path, "createElement"), [t__namespace.stringLiteral(tagName)])
1947
+ t__namespace.callExpression(
1948
+ registerImportMethod(
1949
+ path,
1950
+ "createElement",
1951
+ getRendererConfig(path, "universal").moduleName
1952
+ ),
1953
+ [t__namespace.stringLiteral(tagName)]
1954
+ )
1901
1955
  )
1902
1956
  );
1903
1957
 
@@ -1921,17 +1975,24 @@ function transformAttributes(path, results) {
1921
1975
  if (t__namespace.isJSXSpreadAttribute(node)) {
1922
1976
  results.exprs.push(
1923
1977
  t__namespace.expressionStatement(
1924
- t__namespace.callExpression(registerImportMethod(attribute, "spread"), [
1925
- elem,
1926
- isDynamic(attribute.get("argument"), {
1927
- checkMember: true
1928
- })
1929
- ? t__namespace.isCallExpression(node.argument) && !node.argument.arguments.length
1930
- ? node.argument.callee
1931
- : t__namespace.arrowFunctionExpression([], node.argument)
1932
- : node.argument,
1933
- t__namespace.booleanLiteral(hasChildren)
1934
- ])
1978
+ t__namespace.callExpression(
1979
+ registerImportMethod(
1980
+ attribute,
1981
+ "spread",
1982
+ getRendererConfig(path, "universal").moduleName
1983
+ ),
1984
+ [
1985
+ elem,
1986
+ isDynamic(attribute.get("argument"), {
1987
+ checkMember: true
1988
+ })
1989
+ ? t__namespace.isCallExpression(node.argument) && !node.argument.arguments.length
1990
+ ? node.argument.callee
1991
+ : t__namespace.arrowFunctionExpression([], node.argument)
1992
+ : node.argument,
1993
+ t__namespace.booleanLiteral(hasChildren)
1994
+ ]
1995
+ )
1935
1996
  )
1936
1997
  );
1937
1998
  return;
@@ -2001,7 +2062,7 @@ function transformAttributes(path, results) {
2001
2062
  }
2002
2063
  } else if (key.startsWith("use:")) {
2003
2064
  // Some trick to treat JSXIdentifier as Identifier
2004
- node.name.name.type = 'Identifier';
2065
+ node.name.name.type = "Identifier";
2005
2066
  results.exprs.unshift(
2006
2067
  t__namespace.expressionStatement(
2007
2068
  t__namespace.callExpression(node.name.name, [
@@ -2041,7 +2102,7 @@ function transformAttributes(path, results) {
2041
2102
  function setAttr(path, elem, name, value, { prevId } = {}) {
2042
2103
  if (!value) value = t__namespace.booleanLiteral(true);
2043
2104
  return t__namespace.callExpression(
2044
- registerImportMethod(path, "setProp"),
2105
+ registerImportMethod(path, "setProp", getRendererConfig(path, "universal").moduleName),
2045
2106
  prevId ? [elem, t__namespace.stringLiteral(name), value, prevId] : [elem, t__namespace.stringLiteral(name), value]
2046
2107
  );
2047
2108
  }
@@ -2061,33 +2122,47 @@ function transformChildren(path, results) {
2061
2122
  const appends = [];
2062
2123
  childNodes.forEach((child, index) => {
2063
2124
  if (!child) return;
2125
+ if (child.tagName && child.renderer !== "universal") {
2126
+ throw new Error(`<${child.tagName}> is not supported in <${getTagName(path.node)}>.
2127
+ Wrap the usage with a component that would render this element, eg. Canvas`);
2128
+ }
2064
2129
  if (child.id) {
2065
- const insertNode = registerImportMethod(path, "insertNode");
2130
+ let insertNode = registerImportMethod(
2131
+ path,
2132
+ "insertNode",
2133
+ getRendererConfig(path, "universal").moduleName
2134
+ );
2066
2135
  let insert = child.id;
2067
2136
  if (child.text) {
2068
- const createTextNode = registerImportMethod(path, "createTextNode");
2137
+ let createTextNode = registerImportMethod(
2138
+ path,
2139
+ "createTextNode",
2140
+ getRendererConfig(path, "universal").moduleName
2141
+ );
2069
2142
  if (multi) {
2070
2143
  results.decl.push(
2071
2144
  t__namespace.variableDeclarator(
2072
2145
  child.id,
2073
2146
  t__namespace.callExpression(createTextNode, [
2074
- t__namespace.stringLiteral(htmlEntities.decode(child.template))
2147
+ t__namespace.templateLiteral([t__namespace.templateElement({ raw: child.template })], [])
2075
2148
  ])
2076
2149
  )
2077
2150
  );
2078
2151
  } else
2079
2152
  insert = t__namespace.callExpression(createTextNode, [
2080
- t__namespace.stringLiteral(htmlEntities.decode(child.template))
2153
+ t__namespace.templateLiteral([t__namespace.templateElement({ raw: child.template })], [])
2081
2154
  ]);
2082
2155
  }
2083
- appends.push(
2084
- t__namespace.expressionStatement(t__namespace.callExpression(insertNode, [results.id, insert]))
2085
- );
2156
+ appends.push(t__namespace.expressionStatement(t__namespace.callExpression(insertNode, [results.id, insert])));
2086
2157
  results.decl.push(...child.decl);
2087
2158
  results.exprs.push(...child.exprs);
2088
2159
  results.dynamics.push(...child.dynamics);
2089
2160
  } else if (child.exprs.length) {
2090
- const insert = registerImportMethod(path, "insert");
2161
+ let insert = registerImportMethod(
2162
+ path,
2163
+ "insert",
2164
+ getRendererConfig(path, "universal").moduleName
2165
+ );
2091
2166
  if (multi) {
2092
2167
  results.exprs.push(
2093
2168
  t__namespace.expressionStatement(
@@ -2100,9 +2175,7 @@ function transformChildren(path, results) {
2100
2175
  );
2101
2176
  } else {
2102
2177
  results.exprs.push(
2103
- t__namespace.expressionStatement(
2104
- t__namespace.callExpression(insert, [results.id, child.exprs[0]])
2105
- )
2178
+ t__namespace.expressionStatement(t__namespace.callExpression(insert, [results.id, child.exprs[0]]))
2106
2179
  );
2107
2180
  }
2108
2181
  }
@@ -2215,11 +2288,7 @@ function convertComponentIdentifier(node) {
2215
2288
  } else if (t__namespace.isJSXMemberExpression(node)) {
2216
2289
  const prop = convertComponentIdentifier(node.property);
2217
2290
  const computed = t__namespace.isStringLiteral(prop);
2218
- return t__namespace.memberExpression(
2219
- convertComponentIdentifier(node.object),
2220
- prop,
2221
- computed
2222
- );
2291
+ return t__namespace.memberExpression(convertComponentIdentifier(node.object), prop, computed);
2223
2292
  }
2224
2293
 
2225
2294
  return node;
@@ -2272,7 +2341,10 @@ function transformComponent(path) {
2272
2341
  isDynamic(attribute.get("argument"), {
2273
2342
  checkMember: true
2274
2343
  }) && (dynamicSpread = true)
2275
- ? t__namespace.isCallExpression(node.argument) && !node.argument.arguments.length
2344
+ ? t__namespace.isCallExpression(node.argument) &&
2345
+ !node.argument.arguments.length &&
2346
+ !t__namespace.isCallExpression(node.argument.callee) &&
2347
+ !t__namespace.isMemberExpression(node.argument.callee)
2276
2348
  ? node.argument.callee
2277
2349
  : t__namespace.arrowFunctionExpression([], node.argument)
2278
2350
  : node.argument
@@ -2416,13 +2488,7 @@ function transformComponent(path) {
2416
2488
  }
2417
2489
 
2418
2490
  function transformComponentChildren(children, config) {
2419
- const createTemplate$3 =
2420
- config.generate === "universal"
2421
- ? createTemplate
2422
- : config.generate === "ssr"
2423
- ? createTemplate$1
2424
- : createTemplate$2,
2425
- filteredChildren = filterChildren(children);
2491
+ const filteredChildren = filterChildren(children);
2426
2492
  if (!filteredChildren.length) return;
2427
2493
  let dynamic = false;
2428
2494
 
@@ -2436,7 +2502,7 @@ function transformComponentChildren(children, config) {
2436
2502
  componentChild: true
2437
2503
  });
2438
2504
  dynamic = dynamic || child.dynamic;
2439
- memo.push(createTemplate$3(path, child, filteredChildren.length > 1));
2505
+ memo.push(getCreateTemplate(config, path, child)(path, child, filteredChildren.length > 1));
2440
2506
  }
2441
2507
  return memo;
2442
2508
  }, []);
@@ -2464,20 +2530,14 @@ function transformComponentChildren(children, config) {
2464
2530
  }
2465
2531
 
2466
2532
  function transformFragmentChildren(children, results, config) {
2467
- const createTemplate$3 =
2468
- config.generate === "universal"
2469
- ? createTemplate
2470
- : config.generate === "ssr"
2471
- ? createTemplate$1
2472
- : createTemplate$2,
2473
- filteredChildren = filterChildren(children),
2533
+ const filteredChildren = filterChildren(children),
2474
2534
  childNodes = filteredChildren.reduce((memo, path) => {
2475
2535
  if (t__namespace.isJSXText(path.node)) {
2476
- const v = htmlEntities.decode(trimWhitespace(path.node.extra.raw));
2536
+ const v = htmlEntities.decode(trimWhitespace(path.node.extra.raw));
2477
2537
  if (v.length) memo.push(t__namespace.stringLiteral(v));
2478
2538
  } else {
2479
2539
  const child = transformNode(path, { topLevel: true, fragmentChild: true });
2480
- memo.push(createTemplate$3(path, child, true));
2540
+ memo.push(getCreateTemplate(config, path, child)(path, child, true));
2481
2541
  }
2482
2542
  return memo;
2483
2543
  }, []);
@@ -2495,12 +2555,9 @@ function transformJSX(path) {
2495
2555
  topLevel: true
2496
2556
  }
2497
2557
  );
2498
- const template =
2499
- config.generate === "universal"
2500
- ? createTemplate
2501
- : config.generate === "ssr"
2502
- ? createTemplate$1
2503
- : createTemplate$2;
2558
+
2559
+ const template = getCreateTemplate(config, path, result);
2560
+
2504
2561
  path.replaceWith(replace(template(path, result, false)));
2505
2562
  }
2506
2563
 
@@ -2529,17 +2586,10 @@ function transformNode(path, info = {}) {
2529
2586
  const node = path.node;
2530
2587
  let staticValue;
2531
2588
  if (t__namespace.isJSXElement(node)) {
2532
- let tagName = getTagName(node);
2533
- if (isComponent(tagName)) return transformComponent(path);
2534
- const element =
2535
- config.generate === "universal"
2536
- ? transformElement
2537
- : config.generate === "ssr"
2538
- ? transformElement$1
2539
- : transformElement$2;
2540
- return element(path, info);
2589
+ return transformElement(config, path, info);
2541
2590
  } else if (t__namespace.isJSXFragment(node)) {
2542
2591
  let results = { template: "", decl: [], exprs: [], dynamics: [] };
2592
+ // <><div /><Component /></>
2543
2593
  transformFragmentChildren(path.get("children"), results, config);
2544
2594
  return results;
2545
2595
  } else if (t__namespace.isJSXText(node) || (staticValue = getStaticExpression(path))) {
@@ -2551,7 +2601,7 @@ function transformNode(path, info = {}) {
2551
2601
  : trimWhitespace(node.extra.raw);
2552
2602
  if (!text.length) return null;
2553
2603
  const results = {
2554
- template: config.generate === "dom" ? escapeBackticks(text) : text,
2604
+ template: config.generate === "ssr" ? text : escapeBackticks(text),
2555
2605
  decl: [],
2556
2606
  exprs: [],
2557
2607
  dynamics: [],
@@ -2617,21 +2667,63 @@ function transformNode(path, info = {}) {
2617
2667
  }
2618
2668
  }
2619
2669
 
2670
+ function getCreateTemplate(config, path, result) {
2671
+ if ((result.tagName && result.renderer === "dom") || config.generate === "dom") {
2672
+ return createTemplate$2;
2673
+ }
2674
+
2675
+ if (result.renderer === "ssr" || config.generate === "ssr") {
2676
+ return createTemplate$1;
2677
+ }
2678
+
2679
+ return createTemplate;
2680
+ }
2681
+
2682
+ function transformElement(config, path, info = {}) {
2683
+ const node = path.node;
2684
+ let tagName = getTagName(node);
2685
+ // <Component ...></Component>
2686
+ if (isComponent(tagName)) return transformComponent(path);
2687
+
2688
+ // <div ...></div>
2689
+ // const element = getTransformElemet(config, path, tagName);
2690
+
2691
+ let tagRenderer;
2692
+ for (var renderer of config.renderers ?? []) {
2693
+ if (renderer.elements.indexOf(tagName) !== -1) {
2694
+ tagRenderer = renderer;
2695
+ break;
2696
+ }
2697
+ }
2698
+
2699
+ if (tagRenderer?.name === "dom" || getConfig(path).generate === "dom") {
2700
+ return transformElement$3(path, info);
2701
+ }
2702
+
2703
+ if (getConfig(path).generate === "ssr") {
2704
+ return transformElement$2(path, info);
2705
+ }
2706
+
2707
+ return transformElement$1(path);
2708
+ }
2709
+
2620
2710
  // add to the top/bottom of the module.
2621
2711
  var postprocess = path => {
2622
- const config = getConfig(path);
2623
2712
  if (path.scope.data.events) {
2624
2713
  path.node.body.push(
2625
2714
  t__namespace.expressionStatement(
2626
- t__namespace.callExpression(registerImportMethod(path, "delegateEvents"), [
2627
- t__namespace.arrayExpression(Array.from(path.scope.data.events).map(e => t__namespace.stringLiteral(e)))
2628
- ])
2715
+ t__namespace.callExpression(
2716
+ registerImportMethod(path, "delegateEvents", getRendererConfig(path, "dom").moduleName),
2717
+ [t__namespace.arrayExpression(Array.from(path.scope.data.events).map(e => t__namespace.stringLiteral(e)))]
2718
+ )
2629
2719
  )
2630
2720
  );
2631
2721
  }
2632
- if (path.scope.data.templates) {
2633
- const appendTemplates$2 = config.generate === "ssr" ? appendTemplates : appendTemplates$1;
2634
- appendTemplates$2(path, path.scope.data.templates);
2722
+ if (path.scope.data.templates?.length) {
2723
+ let domTemplates = path.scope.data.templates.filter(temp => temp.renderer === "dom");
2724
+ let ssrTemplates = path.scope.data.templates.filter(temp => temp.renderer === "ssr");
2725
+ domTemplates.length > 0 && appendTemplates$1(path, domTemplates);
2726
+ ssrTemplates.length > 0 && appendTemplates(path, ssrTemplates);
2635
2727
  }
2636
2728
  };
2637
2729