Repository: ony3000/prettier-plugin-classnames (ts)

Issue:
Class names of elements inside empty JSX tags do not wrap
## Dependency information

- prettier@3.4.0
- @trivago/prettier-plugin-sort-imports@4.2.1
- prettier-plugin-brace-style@0.7.1
- prettier-plugin-classnames@0.7.5
- prettier-plugin-merge@0.7.2
- prettier-plugin-tailwindcss@0.6.11

## Prettier configuration

```json
{
  "singleQuote": true,
  "trailingComma": "all",
  "singleAttributePerLine": true,
  "plugins": [
    "@trivago/prettier-plugin-sort-imports",
    "prettier-plugin-tailwindcss",
    "prettier-plugin-classnames",
    "prettier-plugin-brace-style",
    "prettier-plugin-merge"
  ],
  "importOrder": [
    "^(.*)\\.css$",
    "<THIRD_PARTY_MODULES>",
    "^@/(.*)$",
    "^\\.(.*)$"
  ],
  "importOrderSeparation": true,
  "endingPosition": "absolute-with-indent",
  "experimentalOptimization": true,
  "braceStyle": "stroustrup"
}
```

## Steps to reproduce

Turn on the `experimentalOptimization` option and try formatting the following components:

```tsx
function Foo() {
  return (
    <>
      <div className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24 lg:px-20 lg:py-24">
        content
      </div>
    </>
  );
}
```

## The current behavior

```tsx
function Foo() {
  return (
    <>
      <div className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24 lg:px-20 lg:py-24">
        content
      </div>
    </>
  );
}
```

## The expected behavior

```tsx
function Foo() {
  return (
    <>
      <div
        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
          sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
      >
        content
      </div>
    </>
  );
}
```

Pull request description:
Fix line wrapping inside empty JSX tags
This PR closes #90.

Patch:
diff --git a/src/packages/core-parts/finder.ts b/src/packages/core-parts/finder.ts
index f9f1cf9..55ae1a7 100644
--- a/src/packages/core-parts/finder.ts
+++ b/src/packages/core-parts/finder.ts
@@ -173,6 +173,10 @@ export function findTargetClassNameNodes(ast: any, options: ResolvedOptions): Cl
           recursiveProps = ['openingElement', 'children'];
           break;
         }
+        case 'JSXFragment': {
+          recursiveProps = ['children'];
+          break;
+        }
         case 'JSXOpeningElement': {
           recursiveProps = ['attributes'];
           break;
@@ -1933,6 +1937,7 @@ export function findTargetClassNameNodesForAstro(
           recursiveProps = ['attributes', 'children'];
           break;
         }
+        case 'fragment':
         case 'root': {
           recursiveProps = ['children'];
           break;


Test patch:
diff --git a/tests/v2-test/astro/issue-90/__snapshots__/absolute.test.ts.snap b/tests/v2-test/astro/issue-90/__snapshots__/absolute.test.ts.snap
new file mode 100644
index 0000000..d7b01d2
--- /dev/null
+++ b/tests/v2-test/astro/issue-90/__snapshots__/absolute.test.ts.snap
@@ -0,0 +1,19 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------|
+printWidth=80 (in snapshot)
+<div>
+  <div>
+    <>
+      <div
+        class="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  </div>
+</div>
+"
+`;
diff --git a/tests/v2-test/astro/issue-90/__snapshots__/ideal.test.ts.snap b/tests/v2-test/astro/issue-90/__snapshots__/ideal.test.ts.snap
new file mode 100644
index 0000000..ad622d6
--- /dev/null
+++ b/tests/v2-test/astro/issue-90/__snapshots__/ideal.test.ts.snap
@@ -0,0 +1,19 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------|
+printWidth=80 (in snapshot)
+<div>
+  <div>
+    <>
+      <div
+        class="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+          sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  </div>
+</div>
+"
+`;
diff --git a/tests/v2-test/astro/issue-90/__snapshots__/relative.test.ts.snap b/tests/v2-test/astro/issue-90/__snapshots__/relative.test.ts.snap
new file mode 100644
index 0000000..589a5ba
--- /dev/null
+++ b/tests/v2-test/astro/issue-90/__snapshots__/relative.test.ts.snap
@@ -0,0 +1,19 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------|
+printWidth=80 (in snapshot)
+<div>
+  <div>
+    <>
+      <div
+        class="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24
+          lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  </div>
+</div>
+"
+`;
diff --git a/tests/v2-test/astro/issue-90/absolute.test.ts b/tests/v2-test/astro/issue-90/absolute.test.ts
new file mode 100644
index 0000000..0b1b786
--- /dev/null
+++ b/tests/v2-test/astro/issue-90/absolute.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: ['prettier-plugin-astro', thisPlugin],
+  parser: 'astro',
+  endingPosition: 'absolute',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v2-test/astro/issue-90/fixtures.ts b/tests/v2-test/astro/issue-90/fixtures.ts
new file mode 100644
index 0000000..4b53e57
--- /dev/null
+++ b/tests/v2-test/astro/issue-90/fixtures.ts
@@ -0,0 +1,22 @@
+import type { Fixture } from 'test-settings';
+
+export const fixtures: Omit<Fixture, 'output'>[] = [
+  {
+    name: '(1) Empty JSX tags should also behave the same as named tags.',
+    input: `
+//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+<div>
+  <div>
+    <>
+      <div class="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24 lg:px-20 lg:py-24">
+        content
+      </div>
+    </>
+  </div>
+</div>
+`,
+    options: {
+      experimentalOptimization: true,
+    },
+  },
+];
diff --git a/tests/v2-test/astro/issue-90/ideal.test.ts b/tests/v2-test/astro/issue-90/ideal.test.ts
new file mode 100644
index 0000000..38dd286
--- /dev/null
+++ b/tests/v2-test/astro/issue-90/ideal.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: ['prettier-plugin-astro', thisPlugin],
+  parser: 'astro',
+  endingPosition: 'absolute-with-indent',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v2-test/astro/issue-90/relative.test.ts b/tests/v2-test/astro/issue-90/relative.test.ts
new file mode 100644
index 0000000..4b09e55
--- /dev/null
+++ b/tests/v2-test/astro/issue-90/relative.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: ['prettier-plugin-astro', thisPlugin],
+  parser: 'astro',
+  endingPosition: 'relative',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v2-test/babel/issue-90/__snapshots__/absolute.test.ts.snap b/tests/v2-test/babel/issue-90/__snapshots__/absolute.test.ts.snap
new file mode 100644
index 0000000..42283b8
--- /dev/null
+++ b/tests/v2-test/babel/issue-90/__snapshots__/absolute.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v2-test/babel/issue-90/__snapshots__/ideal.test.ts.snap b/tests/v2-test/babel/issue-90/__snapshots__/ideal.test.ts.snap
new file mode 100644
index 0000000..b79ad43
--- /dev/null
+++ b/tests/v2-test/babel/issue-90/__snapshots__/ideal.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+          sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v2-test/babel/issue-90/__snapshots__/relative.test.ts.snap b/tests/v2-test/babel/issue-90/__snapshots__/relative.test.ts.snap
new file mode 100644
index 0000000..a2b8c85
--- /dev/null
+++ b/tests/v2-test/babel/issue-90/__snapshots__/relative.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24
+          lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v2-test/babel/issue-90/absolute.test.ts b/tests/v2-test/babel/issue-90/absolute.test.ts
new file mode 100644
index 0000000..847f81f
--- /dev/null
+++ b/tests/v2-test/babel/issue-90/absolute.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'babel',
+  endingPosition: 'absolute',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v2-test/babel/issue-90/fixtures.ts b/tests/v2-test/babel/issue-90/fixtures.ts
new file mode 100644
index 0000000..1c08e23
--- /dev/null
+++ b/tests/v2-test/babel/issue-90/fixtures.ts
@@ -0,0 +1,22 @@
+import type { Fixture } from 'test-settings';
+
+export const fixtures: Omit<Fixture, 'output'>[] = [
+  {
+    name: '(1) Empty JSX tags should also behave the same as named tags.',
+    input: `
+//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24 lg:px-20 lg:py-24">
+        content
+      </div>
+    </>
+  );
+}
+`,
+    options: {
+      experimentalOptimization: true,
+    },
+  },
+];
diff --git a/tests/v2-test/babel/issue-90/ideal.test.ts b/tests/v2-test/babel/issue-90/ideal.test.ts
new file mode 100644
index 0000000..c15a81a
--- /dev/null
+++ b/tests/v2-test/babel/issue-90/ideal.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'babel',
+  endingPosition: 'absolute-with-indent',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v2-test/babel/issue-90/relative.test.ts b/tests/v2-test/babel/issue-90/relative.test.ts
new file mode 100644
index 0000000..91646ba
--- /dev/null
+++ b/tests/v2-test/babel/issue-90/relative.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'babel',
+  endingPosition: 'relative',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v2-test/typescript/issue-90/__snapshots__/absolute.test.ts.snap b/tests/v2-test/typescript/issue-90/__snapshots__/absolute.test.ts.snap
new file mode 100644
index 0000000..42283b8
--- /dev/null
+++ b/tests/v2-test/typescript/issue-90/__snapshots__/absolute.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v2-test/typescript/issue-90/__snapshots__/ideal.test.ts.snap b/tests/v2-test/typescript/issue-90/__snapshots__/ideal.test.ts.snap
new file mode 100644
index 0000000..b79ad43
--- /dev/null
+++ b/tests/v2-test/typescript/issue-90/__snapshots__/ideal.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+          sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v2-test/typescript/issue-90/__snapshots__/relative.test.ts.snap b/tests/v2-test/typescript/issue-90/__snapshots__/relative.test.ts.snap
new file mode 100644
index 0000000..a2b8c85
--- /dev/null
+++ b/tests/v2-test/typescript/issue-90/__snapshots__/relative.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24
+          lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v2-test/typescript/issue-90/absolute.test.ts b/tests/v2-test/typescript/issue-90/absolute.test.ts
new file mode 100644
index 0000000..6c0c91a
--- /dev/null
+++ b/tests/v2-test/typescript/issue-90/absolute.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'typescript',
+  endingPosition: 'absolute',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v2-test/typescript/issue-90/fixtures.ts b/tests/v2-test/typescript/issue-90/fixtures.ts
new file mode 100644
index 0000000..1c08e23
--- /dev/null
+++ b/tests/v2-test/typescript/issue-90/fixtures.ts
@@ -0,0 +1,22 @@
+import type { Fixture } from 'test-settings';
+
+export const fixtures: Omit<Fixture, 'output'>[] = [
+  {
+    name: '(1) Empty JSX tags should also behave the same as named tags.',
+    input: `
+//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24 lg:px-20 lg:py-24">
+        content
+      </div>
+    </>
+  );
+}
+`,
+    options: {
+      experimentalOptimization: true,
+    },
+  },
+];
diff --git a/tests/v2-test/typescript/issue-90/ideal.test.ts b/tests/v2-test/typescript/issue-90/ideal.test.ts
new file mode 100644
index 0000000..e08742e
--- /dev/null
+++ b/tests/v2-test/typescript/issue-90/ideal.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'typescript',
+  endingPosition: 'absolute-with-indent',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v2-test/typescript/issue-90/relative.test.ts b/tests/v2-test/typescript/issue-90/relative.test.ts
new file mode 100644
index 0000000..305e9fb
--- /dev/null
+++ b/tests/v2-test/typescript/issue-90/relative.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'typescript',
+  endingPosition: 'relative',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v3-test/astro/issue-90/__snapshots__/absolute.test.ts.snap b/tests/v3-test/astro/issue-90/__snapshots__/absolute.test.ts.snap
new file mode 100644
index 0000000..d7b01d2
--- /dev/null
+++ b/tests/v3-test/astro/issue-90/__snapshots__/absolute.test.ts.snap
@@ -0,0 +1,19 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------|
+printWidth=80 (in snapshot)
+<div>
+  <div>
+    <>
+      <div
+        class="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  </div>
+</div>
+"
+`;
diff --git a/tests/v3-test/astro/issue-90/__snapshots__/ideal.test.ts.snap b/tests/v3-test/astro/issue-90/__snapshots__/ideal.test.ts.snap
new file mode 100644
index 0000000..ad622d6
--- /dev/null
+++ b/tests/v3-test/astro/issue-90/__snapshots__/ideal.test.ts.snap
@@ -0,0 +1,19 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------|
+printWidth=80 (in snapshot)
+<div>
+  <div>
+    <>
+      <div
+        class="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+          sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  </div>
+</div>
+"
+`;
diff --git a/tests/v3-test/astro/issue-90/__snapshots__/relative.test.ts.snap b/tests/v3-test/astro/issue-90/__snapshots__/relative.test.ts.snap
new file mode 100644
index 0000000..589a5ba
--- /dev/null
+++ b/tests/v3-test/astro/issue-90/__snapshots__/relative.test.ts.snap
@@ -0,0 +1,19 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------|
+printWidth=80 (in snapshot)
+<div>
+  <div>
+    <>
+      <div
+        class="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24
+          lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  </div>
+</div>
+"
+`;
diff --git a/tests/v3-test/astro/issue-90/absolute.test.ts b/tests/v3-test/astro/issue-90/absolute.test.ts
new file mode 100644
index 0000000..0b1b786
--- /dev/null
+++ b/tests/v3-test/astro/issue-90/absolute.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: ['prettier-plugin-astro', thisPlugin],
+  parser: 'astro',
+  endingPosition: 'absolute',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v3-test/astro/issue-90/fixtures.ts b/tests/v3-test/astro/issue-90/fixtures.ts
new file mode 100644
index 0000000..4b53e57
--- /dev/null
+++ b/tests/v3-test/astro/issue-90/fixtures.ts
@@ -0,0 +1,22 @@
+import type { Fixture } from 'test-settings';
+
+export const fixtures: Omit<Fixture, 'output'>[] = [
+  {
+    name: '(1) Empty JSX tags should also behave the same as named tags.',
+    input: `
+//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+<div>
+  <div>
+    <>
+      <div class="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24 lg:px-20 lg:py-24">
+        content
+      </div>
+    </>
+  </div>
+</div>
+`,
+    options: {
+      experimentalOptimization: true,
+    },
+  },
+];
diff --git a/tests/v3-test/astro/issue-90/ideal.test.ts b/tests/v3-test/astro/issue-90/ideal.test.ts
new file mode 100644
index 0000000..38dd286
--- /dev/null
+++ b/tests/v3-test/astro/issue-90/ideal.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: ['prettier-plugin-astro', thisPlugin],
+  parser: 'astro',
+  endingPosition: 'absolute-with-indent',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v3-test/astro/issue-90/relative.test.ts b/tests/v3-test/astro/issue-90/relative.test.ts
new file mode 100644
index 0000000..4b09e55
--- /dev/null
+++ b/tests/v3-test/astro/issue-90/relative.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: ['prettier-plugin-astro', thisPlugin],
+  parser: 'astro',
+  endingPosition: 'relative',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v3-test/babel/issue-90/__snapshots__/absolute.test.ts.snap b/tests/v3-test/babel/issue-90/__snapshots__/absolute.test.ts.snap
new file mode 100644
index 0000000..42283b8
--- /dev/null
+++ b/tests/v3-test/babel/issue-90/__snapshots__/absolute.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v3-test/babel/issue-90/__snapshots__/ideal.test.ts.snap b/tests/v3-test/babel/issue-90/__snapshots__/ideal.test.ts.snap
new file mode 100644
index 0000000..b79ad43
--- /dev/null
+++ b/tests/v3-test/babel/issue-90/__snapshots__/ideal.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+          sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v3-test/babel/issue-90/__snapshots__/relative.test.ts.snap b/tests/v3-test/babel/issue-90/__snapshots__/relative.test.ts.snap
new file mode 100644
index 0000000..a2b8c85
--- /dev/null
+++ b/tests/v3-test/babel/issue-90/__snapshots__/relative.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24
+          lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v3-test/babel/issue-90/absolute.test.ts b/tests/v3-test/babel/issue-90/absolute.test.ts
new file mode 100644
index 0000000..847f81f
--- /dev/null
+++ b/tests/v3-test/babel/issue-90/absolute.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'babel',
+  endingPosition: 'absolute',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v3-test/babel/issue-90/fixtures.ts b/tests/v3-test/babel/issue-90/fixtures.ts
new file mode 100644
index 0000000..1c08e23
--- /dev/null
+++ b/tests/v3-test/babel/issue-90/fixtures.ts
@@ -0,0 +1,22 @@
+import type { Fixture } from 'test-settings';
+
+export const fixtures: Omit<Fixture, 'output'>[] = [
+  {
+    name: '(1) Empty JSX tags should also behave the same as named tags.',
+    input: `
+//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24 lg:px-20 lg:py-24">
+        content
+      </div>
+    </>
+  );
+}
+`,
+    options: {
+      experimentalOptimization: true,
+    },
+  },
+];
diff --git a/tests/v3-test/babel/issue-90/ideal.test.ts b/tests/v3-test/babel/issue-90/ideal.test.ts
new file mode 100644
index 0000000..c15a81a
--- /dev/null
+++ b/tests/v3-test/babel/issue-90/ideal.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'babel',
+  endingPosition: 'absolute-with-indent',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v3-test/babel/issue-90/relative.test.ts b/tests/v3-test/babel/issue-90/relative.test.ts
new file mode 100644
index 0000000..91646ba
--- /dev/null
+++ b/tests/v3-test/babel/issue-90/relative.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'babel',
+  endingPosition: 'relative',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v3-test/typescript/issue-90/__snapshots__/absolute.test.ts.snap b/tests/v3-test/typescript/issue-90/__snapshots__/absolute.test.ts.snap
new file mode 100644
index 0000000..42283b8
--- /dev/null
+++ b/tests/v3-test/typescript/issue-90/__snapshots__/absolute.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v3-test/typescript/issue-90/__snapshots__/ideal.test.ts.snap b/tests/v3-test/typescript/issue-90/__snapshots__/ideal.test.ts.snap
new file mode 100644
index 0000000..b79ad43
--- /dev/null
+++ b/tests/v3-test/typescript/issue-90/__snapshots__/ideal.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12
+          sm:py-16 lg:gap-24 lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v3-test/typescript/issue-90/__snapshots__/relative.test.ts.snap b/tests/v3-test/typescript/issue-90/__snapshots__/relative.test.ts.snap
new file mode 100644
index 0000000..a2b8c85
--- /dev/null
+++ b/tests/v3-test/typescript/issue-90/__snapshots__/relative.test.ts.snap
@@ -0,0 +1,18 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`'(1) Empty JSX tags should also behave the same as named tags.' > expectation 1`] = `
+"//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div
+        className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24
+          lg:px-20 lg:py-24"
+      >
+        content
+      </div>
+    </>
+  );
+}
+"
+`;
diff --git a/tests/v3-test/typescript/issue-90/absolute.test.ts b/tests/v3-test/typescript/issue-90/absolute.test.ts
new file mode 100644
index 0000000..6c0c91a
--- /dev/null
+++ b/tests/v3-test/typescript/issue-90/absolute.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'typescript',
+  endingPosition: 'absolute',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v3-test/typescript/issue-90/fixtures.ts b/tests/v3-test/typescript/issue-90/fixtures.ts
new file mode 100644
index 0000000..1c08e23
--- /dev/null
+++ b/tests/v3-test/typescript/issue-90/fixtures.ts
@@ -0,0 +1,22 @@
+import type { Fixture } from 'test-settings';
+
+export const fixtures: Omit<Fixture, 'output'>[] = [
+  {
+    name: '(1) Empty JSX tags should also behave the same as named tags.',
+    input: `
+//-----------------------------------------------------------------------------| printWidth=80 (in snapshot)
+function Foo() {
+  return (
+    <>
+      <div className="flex min-h-screen flex-col gap-8 px-5 py-8 sm:gap-16 sm:px-12 sm:py-16 lg:gap-24 lg:px-20 lg:py-24">
+        content
+      </div>
+    </>
+  );
+}
+`,
+    options: {
+      experimentalOptimization: true,
+    },
+  },
+];
diff --git a/tests/v3-test/typescript/issue-90/ideal.test.ts b/tests/v3-test/typescript/issue-90/ideal.test.ts
new file mode 100644
index 0000000..e08742e
--- /dev/null
+++ b/tests/v3-test/typescript/issue-90/ideal.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'typescript',
+  endingPosition: 'absolute-with-indent',
+};
+
+testSnapshotEach(fixtures, options);
diff --git a/tests/v3-test/typescript/issue-90/relative.test.ts b/tests/v3-test/typescript/issue-90/relative.test.ts
new file mode 100644
index 0000000..305e9fb
--- /dev/null
+++ b/tests/v3-test/typescript/issue-90/relative.test.ts
@@ -0,0 +1,13 @@
+import { baseOptions } from 'test-settings';
+
+import { thisPlugin, testSnapshotEach } from '../../adaptor';
+import { fixtures } from './fixtures';
+
+const options = {
+  ...baseOptions,
+  plugins: [thisPlugin],
+  parser: 'typescript',
+  endingPosition: 'relative',
+};
+
+testSnapshotEach(fixtures, options);