@tsrx/prettier-plugin 0.3.68 → 0.3.69

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.
package/README.md CHANGED
@@ -3,6 +3,5 @@
3
3
  [![npm version](https://img.shields.io/npm/v/%40tsrx%2Fprettier-plugin?logo=npm)](https://www.npmjs.com/package/@tsrx/prettier-plugin)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/%40tsrx%2Fprettier-plugin?logo=npm&label=downloads)](https://www.npmjs.com/package/@tsrx/prettier-plugin)
5
5
 
6
- A Prettier plugin for formatting [Ripple](https://github.com/Ripple-TS/ripple)
7
- component files, with `.tsrx` as the default extension and continued `.tsrx`
8
- support.
6
+ A Prettier plugin for formatting [TSRX](https://tsrx.dev) files, with `.tsrx` as
7
+ the default extension.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsrx/prettier-plugin",
3
- "version": "0.3.68",
3
+ "version": "0.3.69",
4
4
  "description": "Ripple plugin for Prettier",
5
5
  "type": "module",
6
6
  "module": "src/index.js",
@@ -27,7 +27,7 @@
27
27
  "prettier": "^3.8.3"
28
28
  },
29
29
  "dependencies": {
30
- "@tsrx/core": "0.1.16"
30
+ "@tsrx/core": "0.1.17"
31
31
  },
32
32
  "files": [
33
33
  "src/"
package/src/index.js CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  /** @typedef {Partial<Pick<ParserOptions, 'singleQuote' | 'jsxSingleQuote' | 'semi' | 'trailingComma' | 'useTabs' | 'tabWidth' | 'singleAttributePerLine' | 'bracketSameLine' | 'bracketSpacing' | 'arrowParens' | 'originalText' | 'printWidth'>> & { locStart: (node: AST.NodeWithLocation) => number, locEnd: (node: AST.NodeWithLocation) => number }} RippleFormatOptions */
18
18
 
19
- /** @typedef {{ isInAttribute?: boolean, isInArray?: boolean, allowInlineObject?: boolean, isConditionalTest?: boolean, isNestedConditional?: boolean, suppressLeadingComments?: boolean, suppressExpressionLeadingComments?: boolean, isInlineContext?: boolean, isStatement?: boolean, isLogicalAndOr?: boolean, allowShorthandProperty?: boolean, isFirstChild?: boolean, skipComponentLabel?: boolean, noBreakInside?: boolean, expandLastArg?: boolean, preferInlineSimpleUnionType?: boolean }} PrintArgs */
19
+ /** @typedef {{ isInAttribute?: boolean, isInArray?: boolean, allowInlineObject?: boolean, isConditionalTest?: boolean, isNestedConditional?: boolean, suppressLeadingComments?: boolean, suppressExpressionLeadingComments?: boolean, isInlineContext?: boolean, isStatement?: boolean, isLogicalAndOr?: boolean, allowShorthandProperty?: boolean, isFirstChild?: boolean, noBreakInside?: boolean, expandLastArg?: boolean, preferInlineSimpleUnionType?: boolean }} PrintArgs */
20
20
 
21
21
  import { parseModule } from '@tsrx/core';
22
22
  import { doc } from 'prettier';
@@ -244,7 +244,7 @@ function hasComment(node) {
244
244
  }
245
245
 
246
246
  /**
247
- * @param {AST.FunctionDeclaration | AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.Component} node - The function node
247
+ * @param {AST.FunctionDeclaration | AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction} node - The function node
248
248
  * @returns {Array<AST.Pattern | AST.Parameter>} - Array of parameter patterns
249
249
  */
250
250
  function getFunctionParameters(node) {
@@ -261,12 +261,12 @@ function getFunctionParameters(node) {
261
261
  /**
262
262
  * Iterate over function parameters with path callbacks.
263
263
  * TypeScript/Ripple functions can have additional `this` and `rest` parameters.
264
- * @param {AstPath<AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.FunctionDeclaration | AST.Component>} path - The function path
265
- * @param {(paramPath: AstPath<AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.FunctionDeclaration | AST.Component>, index: number) => void} iteratee - Callback for each parameter
264
+ * @param {AstPath<AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.FunctionDeclaration>} path - The function path
265
+ * @param {(paramPath: AstPath<AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.FunctionDeclaration>, index: number) => void} iteratee - Callback for each parameter
266
266
  * @returns {void}
267
267
  */
268
268
  function iterateFunctionParametersPath(path, iteratee) {
269
- /** @type {AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.FunctionDeclaration | AST.Component} */
269
+ /** @type {AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.FunctionDeclaration} */
270
270
  const node = path.node;
271
271
  let index = 0;
272
272
  /** @type {(paramPath: AstPath) => void} */
@@ -615,7 +615,7 @@ function isNextLineEmpty(node, options) {
615
615
 
616
616
  /**
617
617
  * Check if a function has a rest parameter
618
- * @param {AST.FunctionDeclaration | AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.Component} node - The function node
618
+ * @param {AST.FunctionDeclaration | AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction} node - The function node
619
619
  * @returns {boolean}
620
620
  */
621
621
  function hasRestParameter(node) {
@@ -764,11 +764,10 @@ function printRippleNode(node, path, options, print, args) {
764
764
  const suppressExpressionLeadingComments = args && args.suppressExpressionLeadingComments;
765
765
  const parentNode = /** @type {AST.Node | null} */ (path.getParentNode());
766
766
 
767
- // For TSRXExpression, Text, and Html nodes, don't add leading comments here - they should be handled
767
+ // For TSRXExpression and Text nodes, don't add leading comments here - they should be handled
768
768
  // as separate children within elements, not as part of the expression.
769
769
  const shouldSkipLeadingComments =
770
- parentNode?.type === 'Element' &&
771
- (node.type === 'TSRXExpression' || node.type === 'Text' || node.type === 'Html');
770
+ parentNode?.type === 'Element' && (node.type === 'TSRXExpression' || node.type === 'Text');
772
771
 
773
772
  // Handle leading comments
774
773
  if (node.leadingComments && !shouldSkipLeadingComments && !suppressLeadingComments) {
@@ -884,10 +883,6 @@ function printRippleNode(node, path, options, print, args) {
884
883
  nodeContent = printImportDeclaration(node, path, options, print);
885
884
  break;
886
885
 
887
- case 'Component':
888
- nodeContent = printComponent(node, path, options, print, innerCommentParts, args);
889
- break;
890
-
891
886
  case 'ExportNamedDeclaration':
892
887
  nodeContent = printExportNamedDeclaration(node, path, options, print);
893
888
  break;
@@ -1477,11 +1472,6 @@ function printRippleNode(node, path, options, print, args) {
1477
1472
  break;
1478
1473
  }
1479
1474
 
1480
- case 'Style': {
1481
- nodeContent = ['style ', path.call(print, 'value')];
1482
- break;
1483
- }
1484
-
1485
1475
  case 'StyleSheet': {
1486
1476
  // StyleSheet nodes inside <style> elements. When CSS is empty/whitespace-only,
1487
1477
  // return empty string so the element collapses to <style></style>.
@@ -1695,14 +1685,6 @@ function printRippleNode(node, path, options, print, args) {
1695
1685
  }
1696
1686
  break;
1697
1687
  }
1698
- case 'RefAttribute':
1699
- nodeContent = ['{ref ', path.call(print, 'argument'), '}'];
1700
- break;
1701
-
1702
- case 'RefExpression':
1703
- nodeContent = ['ref ', path.call(print, 'argument')];
1704
- break;
1705
-
1706
1688
  case 'SpreadAttribute': {
1707
1689
  /** @type {Doc[]} */
1708
1690
  const parts = ['{...', path.call(print, 'argument'), '}'];
@@ -1763,7 +1745,7 @@ function printRippleNode(node, path, options, print, args) {
1763
1745
 
1764
1746
  case 'TSModuleBlock':
1765
1747
  case 'BlockStatement': {
1766
- // Apply the same block formatting pattern as component bodies
1748
+ // Apply the same block formatting pattern throughout TSRX.
1767
1749
  if (!node.body || node.body.length === 0) {
1768
1750
  // Handle innerComments for empty blocks
1769
1751
  if (innerCommentParts.length > 0) {
@@ -2322,15 +2304,7 @@ function printRippleNode(node, path, options, print, args) {
2322
2304
  const expressionDoc = suppressExpressionLeadingComments
2323
2305
  ? path.call((exprPath) => print(exprPath, { suppressLeadingComments: true }), 'expression')
2324
2306
  : path.call(print, 'expression');
2325
- nodeContent = ['{text ', expressionDoc, '}'];
2326
- break;
2327
- }
2328
-
2329
- case 'Html': {
2330
- const expressionDoc = suppressExpressionLeadingComments
2331
- ? path.call((exprPath) => print(exprPath, { suppressLeadingComments: true }), 'expression')
2332
- : path.call(print, 'expression');
2333
- nodeContent = ['{html ', expressionDoc, '}'];
2307
+ nodeContent = ['{', expressionDoc, '}'];
2334
2308
  break;
2335
2309
  }
2336
2310
 
@@ -2539,173 +2513,6 @@ function printExportNamedDeclaration(node, path, options, print) {
2539
2513
  return 'export';
2540
2514
  }
2541
2515
 
2542
- /**
2543
- * Print a Ripple component declaration
2544
- * @param {AST.Component} node - The component node
2545
- * @param {AstPath<AST.Component>} path - The AST path
2546
- * @param {RippleFormatOptions} options - Prettier options
2547
- * @param {PrintFn} print - Print callback
2548
- * @param {Doc[]} [innerCommentParts=[]] - Inner comment docs
2549
- * @param {{ skipComponentLabel?: boolean }} [args] - Additional args
2550
- * @returns {Doc[]}
2551
- */
2552
- function printComponent(
2553
- node,
2554
- path,
2555
- options,
2556
- print,
2557
- innerCommentParts = [],
2558
- args = { skipComponentLabel: false },
2559
- ) {
2560
- // Use arrays instead of string concatenation
2561
- /** @type {Doc[]} */
2562
- const signatureParts = args.skipComponentLabel
2563
- ? []
2564
- : node.id
2565
- ? ['component ', node.id.name]
2566
- : ['component'];
2567
-
2568
- // Add TypeScript generics if present
2569
- if (node.typeParameters) {
2570
- const typeParams = path.call(print, 'typeParameters');
2571
- if (Array.isArray(typeParams)) {
2572
- signatureParts.push(...typeParams);
2573
- } else {
2574
- signatureParts.push(typeParams);
2575
- }
2576
- }
2577
-
2578
- // Print parameters using shared function
2579
- const paramsPart = printFunctionParameters(path, options, print);
2580
- signatureParts.push(group(paramsPart)); // Build body content using the same pattern as BlockStatement
2581
- /** @type {Doc[]} */
2582
- const statements = [];
2583
-
2584
- for (let i = 0; i < node.body.length; i++) {
2585
- const statement = path.call(print, 'body', i);
2586
- statements.push(statement);
2587
-
2588
- // Handle blank lines between statements
2589
- if (i < node.body.length - 1) {
2590
- const currentStmt = node.body[i];
2591
- const nextStmt = node.body[i + 1];
2592
-
2593
- // Use shouldAddBlankLine to determine spacing
2594
- if (shouldAddBlankLine(currentStmt, nextStmt)) {
2595
- statements.push(hardline, hardline); // Blank line = two hardlines
2596
- } else {
2597
- statements.push(hardline); // Normal line break
2598
- }
2599
- }
2600
- }
2601
-
2602
- // Process statements to add them to contentParts
2603
- /** @type {Doc[]} */
2604
- const contentParts = [];
2605
- if (statements.length > 0) {
2606
- contentParts.push(statements);
2607
- }
2608
-
2609
- const isArrowComponent = node.metadata?.arrow === true && !node.id && !args.skipComponentLabel;
2610
-
2611
- // Use Prettier's standard block statement pattern
2612
- /** @type {Doc[]} */
2613
- const parts = [signatureParts, isArrowComponent ? ' => {' : ' {'];
2614
-
2615
- if (statements.length > 0) {
2616
- // Build content manually with proper spacing
2617
- /** @type {Doc[]} */
2618
- let contentParts = [];
2619
-
2620
- // Add statements
2621
- if (statements.length > 0) {
2622
- // The statements array contains statements separated by line breaks
2623
- // We need to use join to properly handle the line breaks
2624
- contentParts.push(statements);
2625
- }
2626
-
2627
- // Join content parts
2628
- /** @type {Doc[] | ''} */
2629
- const joinedContent = contentParts.length > 0 ? contentParts : '';
2630
-
2631
- // Apply component-level indentation
2632
- const indentedContent = joinedContent ? indent([hardline, joinedContent]) : indent([hardline]);
2633
-
2634
- // Add the body and closing brace
2635
- parts.push(indentedContent, hardline, '}');
2636
- } else {
2637
- // Empty component body - check for inner comments or trailing comments on id
2638
- // When a component body is empty with only comments, the parser attaches them
2639
- // as trailingComments on the id node (component name)
2640
- /** @type {{ doc: Doc, hasBlankLineBefore: boolean }[]} */
2641
- const commentDocs = [];
2642
-
2643
- // Check innerComments first (standard case for empty blocks)
2644
- if (innerCommentParts.length > 0) {
2645
- for (const part of innerCommentParts) {
2646
- commentDocs.push({ doc: part, hasBlankLineBefore: false });
2647
- }
2648
- }
2649
-
2650
- // Check for trailing comments on the id (component name)
2651
- // These are comments that appear inside an empty component body
2652
- if (node.id && node.id.trailingComments && node.id.trailingComments.length > 0) {
2653
- const comments = node.id.trailingComments;
2654
-
2655
- for (let i = 0; i < comments.length; i++) {
2656
- const comment = comments[i];
2657
- const prevComment = i > 0 ? comments[i - 1] : null;
2658
-
2659
- // Check if there's a blank line before this comment
2660
- const hasBlankLineBefore =
2661
- !!prevComment && getBlankLinesBetweenNodes(prevComment, comment) > 0;
2662
-
2663
- /** @type {Doc | undefined} */
2664
- let commentDoc;
2665
- if (comment.type === 'Line') {
2666
- commentDoc = '//' + comment.value;
2667
- } else if (comment.type === 'Block') {
2668
- commentDoc = '/*' + comment.value + '*/';
2669
- }
2670
-
2671
- if (commentDoc !== undefined) {
2672
- commentDocs.push({ doc: commentDoc, hasBlankLineBefore });
2673
- }
2674
- }
2675
- }
2676
-
2677
- if (commentDocs.length > 0) {
2678
- // Build the content with proper spacing
2679
- /** @type {Doc[]} */
2680
- const contentParts = [];
2681
- for (let i = 0; i < commentDocs.length; i++) {
2682
- const { doc, hasBlankLineBefore } = commentDocs[i];
2683
-
2684
- if (i > 0) {
2685
- // Add blank line if needed (two hardlines = one blank line)
2686
- if (hasBlankLineBefore) {
2687
- contentParts.push(hardline);
2688
- contentParts.push(hardline);
2689
- } else {
2690
- contentParts.push(hardline);
2691
- }
2692
- }
2693
-
2694
- contentParts.push(doc);
2695
- }
2696
-
2697
- return [
2698
- signatureParts,
2699
- isArrowComponent ? ' => ' : ' ',
2700
- group(['{', indent([hardline, contentParts]), hardline, '}']),
2701
- ];
2702
- }
2703
-
2704
- parts[1] = isArrowComponent ? ' => {}' : ' {}';
2705
- }
2706
- return parts;
2707
- }
2708
-
2709
2516
  /**
2710
2517
  * Print a variable declaration
2711
2518
  * @param {AST.VariableDeclaration} node - The variable declaration node
@@ -2922,7 +2729,7 @@ function printExportDefaultDeclaration(node, path, options, print) {
2922
2729
 
2923
2730
  /**
2924
2731
  * Check if the only function parameter should be hugged (no extra parens)
2925
- * @param {AST.FunctionDeclaration | AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.Component} node - The function node
2732
+ * @param {AST.FunctionDeclaration | AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction} node - The function node
2926
2733
  * @returns {boolean}
2927
2734
  */
2928
2735
  function shouldHugTheOnlyFunctionParameter(node) {
@@ -2946,7 +2753,7 @@ function shouldHugTheOnlyFunctionParameter(node) {
2946
2753
 
2947
2754
  /**
2948
2755
  * Print function parameters with proper formatting
2949
- * @param {AstPath<AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.FunctionDeclaration | AST.Component>} path - The function path
2756
+ * @param {AstPath<AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction | AST.FunctionDeclaration>} path - The function path
2950
2757
  * @param {RippleFormatOptions} options - Prettier options
2951
2758
  * @param {PrintFn} print - Print callback
2952
2759
  * @returns {Doc[]}
@@ -5029,8 +4836,6 @@ function printProperty(node, path, options, print) {
5029
4836
  return path.call(print, 'key');
5030
4837
  }
5031
4838
 
5032
- const is_component = /** @type {AST.TSRXProperty} */ (node).value?.type === 'Component';
5033
-
5034
4839
  // Handle getter/setter methods
5035
4840
  if (node.kind === 'get' || node.kind === 'set') {
5036
4841
  const methodParts = [];
@@ -5063,7 +4868,7 @@ function printProperty(node, path, options, print) {
5063
4868
  }
5064
4869
 
5065
4870
  // Handle method shorthand: increment() {} instead of increment: function() {}
5066
- if (node.method && (node.value.type === 'FunctionExpression' || is_component)) {
4871
+ if (node.method && node.value.type === 'FunctionExpression') {
5067
4872
  const methodParts = [];
5068
4873
  const funcValue = /** @type {AST.FunctionExpression} */ (node.value);
5069
4874
 
@@ -5072,10 +4877,6 @@ function printProperty(node, path, options, print) {
5072
4877
  methodParts.push('async ');
5073
4878
  }
5074
4879
 
5075
- if (is_component) {
5076
- methodParts.push('component ');
5077
- }
5078
-
5079
4880
  if (funcValue.generator) {
5080
4881
  methodParts.push('*');
5081
4882
  }
@@ -5087,13 +4888,6 @@ function printProperty(node, path, options, print) {
5087
4888
  methodParts.push(path.call(print, 'value', 'typeParameters'));
5088
4889
  }
5089
4890
 
5090
- if (is_component) {
5091
- methodParts.push(
5092
- path.call((childPath) => print(childPath, { skipComponentLabel: true }), 'value'),
5093
- );
5094
- return methodParts;
5095
- }
5096
-
5097
4891
  // Print parameters by calling into the value path
5098
4892
  const paramsPart = path.call(
5099
4893
  (valuePath) =>
@@ -5687,8 +5481,8 @@ function shouldInlineSingleChild(parentNode, firstChild, childDoc) {
5687
5481
  return false;
5688
5482
  }
5689
5483
 
5690
- // Always inline Html and Text nodes — they are explicit text/raw-markup child forms.
5691
- if (firstChild.type === 'Text' || firstChild.type === 'Html') {
5484
+ // Always inline Text nodes — they are explicit text child forms.
5485
+ if (firstChild.type === 'Text') {
5692
5486
  return true;
5693
5487
  }
5694
5488
 
@@ -5847,8 +5641,7 @@ function printTsx(node, path, options, print) {
5847
5641
  }
5848
5642
 
5849
5643
  /**
5850
- * Print a Tsrx node - renders native TSRX template children inside
5851
- * <tsrx>...</tsrx>.
5644
+ * Print a Tsrx node - renders native TSRX template children inside a fragment.
5852
5645
  * @param {AST.Tsrx} node - The Tsrx node
5853
5646
  * @param {AstPath<AST.Tsrx>} path - The AST path
5854
5647
  * @param {RippleFormatOptions} options - Prettier options
@@ -5856,8 +5649,8 @@ function printTsx(node, path, options, print) {
5856
5649
  * @returns {Doc}
5857
5650
  */
5858
5651
  function printTsrx(node, path, options, print) {
5859
- const tagName = '<tsrx>';
5860
- const closingTagName = '</tsrx>';
5652
+ const tagName = '<>';
5653
+ const closingTagName = '</>';
5861
5654
  const hasChildren = Array.isArray(node.children) && node.children.length > 0;
5862
5655
 
5863
5656
  if (!hasChildren) {
@@ -5883,6 +5676,13 @@ function printTsrx(node, path, options, print) {
5883
5676
  return [tagName, closingTagName];
5884
5677
  }
5885
5678
 
5679
+ if (
5680
+ printedChildren.length === 1 &&
5681
+ ['Element', 'Text', 'TSRXExpression'].includes(node.children[0]?.type)
5682
+ ) {
5683
+ return group([tagName, indent([softline, printedChildren[0]]), softline, closingTagName]);
5684
+ }
5685
+
5886
5686
  return group([
5887
5687
  tagName,
5888
5688
  indent([hardline, join(hardline, printedChildren)]),
@@ -6378,7 +6178,7 @@ function printElement(element, path, options, print) {
6378
6178
  const openingEnd = /** @type {AST.NodeWithLocation} */ (node.openingElement).end;
6379
6179
  for (const child of node.children) {
6380
6180
  if (
6381
- (child.type === 'TSRXExpression' || child.type === 'Text' || child.type === 'Html') &&
6181
+ (child.type === 'TSRXExpression' || child.type === 'Text') &&
6382
6182
  Array.isArray(child.leadingComments)
6383
6183
  ) {
6384
6184
  for (const comment of child.leadingComments) {
@@ -6567,10 +6367,7 @@ function printElement(element, path, options, print) {
6567
6367
  }
6568
6368
  }
6569
6369
 
6570
- const isTextLikeChild =
6571
- currentChild.type === 'TSRXExpression' ||
6572
- currentChild.type === 'Text' ||
6573
- currentChild.type === 'Html';
6370
+ const isTextLikeChild = currentChild.type === 'TSRXExpression' || currentChild.type === 'Text';
6574
6371
  const hasTextLeadingComments =
6575
6372
  shouldLiftTextLevelComments &&
6576
6373
  isTextLikeChild &&
@@ -6683,18 +6480,16 @@ function printElement(element, path, options, print) {
6683
6480
  ? nextChild.leadingComments[0]
6684
6481
  : nextChild;
6685
6482
  const whitespaceLinesCount = getBlankLinesBetweenNodes(currentChild, whitespaceTarget);
6686
- const isTextOrHtmlChild =
6483
+ const isTextOrExpressionChild =
6687
6484
  currentChild.type === 'TSRXExpression' ||
6688
6485
  currentChild.type === 'Text' ||
6689
- currentChild.type === 'Html' ||
6690
6486
  nextChild.type === 'TSRXExpression' ||
6691
- nextChild.type === 'Text' ||
6692
- nextChild.type === 'Html';
6487
+ nextChild.type === 'Text';
6693
6488
 
6694
6489
  if (whitespaceLinesCount > 0) {
6695
6490
  finalChildren.push(hardline);
6696
6491
  finalChildren.push(hardline);
6697
- } else if (!isTextOrHtmlChild && shouldAddBlankLine(currentChild, nextChild)) {
6492
+ } else if (!isTextOrExpressionChild && shouldAddBlankLine(currentChild, nextChild)) {
6698
6493
  finalChildren.push(hardline);
6699
6494
  finalChildren.push(hardline);
6700
6495
  } else {
@@ -6741,10 +6536,7 @@ function printElement(element, path, options, print) {
6741
6536
  const closingTag = ['</', tagName, '>'];
6742
6537
  let elementOutput;
6743
6538
 
6744
- const hasComponentChild =
6745
- node.children && node.children.some((child) => child.type === 'Component');
6746
-
6747
- if (finalChildren.length === 1 && !hasComponentChild) {
6539
+ if (finalChildren.length === 1) {
6748
6540
  const child = finalChildren[0];
6749
6541
  const firstChild = node.children[0];
6750
6542
  const isNonSelfClosingElement =