Repository: rrd108/vue-mess-detector (ts)

Issue:
self-closing-components incorrectly warns when an element is not alone on its line
**Describe the bug**
I have been getting warnings due to the `self-closing-components` rule on components that are empty and self-closing but are on the same line as another element.

**To Reproduce**
Here is a test case I wrote:

InsideComponent.vue
```vue
<script setup lang="ts">
  const fake = 'fake!';
</script>

<template>
  <div>{{ fake }}</div>
</template>

<style scoped>
</style>
```

VueMessTest.vue
```vue
<script setup lang="ts">
import InsideComponent from 'src/components/InsideComponent.vue';
</script>

<template>
  <a
    href="/path/to/link"
  ><InsideComponent /></a>
</template>

<style scoped>
</style>
```

Here's the command I ran and the output it gave me:
```sh
npx vue-mess-detector analyze --apply=selfClosingComponents ./src/components/VueMessTest.vue
```
```sh
Analyzing Vue, TS and JS files in ./src/components/VueMessTest.vue
👉 Using default configuration
      Project type: Vue
      Applying 0 rulesets: N/A
      Applying 1 individual rules: selfClosingComponents
      Ignoring 0 rules: N/A
      Excluding -
      Output level all
      Grouping by rule
      Sorting desc
Analyzing ./src/components/VueMessTest.vue...
Found 1 files

-  vue-strong ~ component is not self closing
   ./src/components/VueMessTest.vue
   👉 Components with no content should be self-closing. See: https://vue-mess-detector.webmania.cc/rules/vue-strong/self-closing-components.html
   line #8 <InsideComponent /></a> 🚨

Found 0 errors, and 1 warnings, 12 lines of code in 1 files
Code Health: [____________________________________________________________] 92%

Code health is OK: 92%
```

**Expected behavior**
This rule should not warn unless the element is not actually self-closing.

**Used version number of vue-mess-detector:**
```sh
$  npx vue-mess-detector -v
0.15.5
```

**Used version number of node & yarn:**
```sh
$  node -v
v22.0.0

$  npm -v
10.5.1
```


Pull request description:
fix: add new regex to handle nested self-closing (#391)
### Summary
Fix false positive for `selfClosingComponents` rule because of the self-closing component within nested html

### Description
- Added new regex to match valid self-closing components

This change should allowthe function to handle cases wherea self-closing component is nested inside another HTML tag

### Related Issues
Fixes #391 

### Type of Change
- [X] Bug fix (non-breaking change which fixes an issue)

### Screenshots (if applicable)
N/A

Patch:
diff --git a/src/rules/vue-strong/selfClosingComponents.ts b/src/rules/vue-strong/selfClosingComponents.ts
index d52dc1a..f50f135 100644
--- a/src/rules/vue-strong/selfClosingComponents.ts
+++ b/src/rules/vue-strong/selfClosingComponents.ts
@@ -1,6 +1,5 @@
 import type { SFCDescriptor } from '@vue/compiler-sfc'
 import type { FileCheckResult, Offense } from '../../types'
-
 import { charNotIn, createRegExp, letter, linefeed, maybe, oneOrMore, tab, wordChar } from 'magic-regexp'
 import getLineNumber from '../getLineNumber'
 
@@ -25,6 +24,17 @@ const checkSelfClosingComponents = (descriptor: SFCDescriptor | null, filePath:
     '>',
     ['g'],
   )
+
+  // New regex to match self-closing components
+  const regexValidSelfClosingComponent = createRegExp(
+    '<',
+    oneOrMore(letter.uppercase, wordChar),
+    maybe(linefeed, tab),
+    maybe(oneOrMore(charNotIn('>'))),
+    '/>',
+    ['g'],
+  )
+
   const matches = template?.content?.match(regexSelfClosingComponent)
 
   if (matches === null) {
@@ -32,6 +42,12 @@ const checkSelfClosingComponents = (descriptor: SFCDescriptor | null, filePath:
   }
 
   matches?.forEach((componentTag) => {
+    // Check if the component tag contains a valid self-closing component
+    const validSelfClosingMatches = componentTag.match(regexValidSelfClosingComponent)
+    if (validSelfClosingMatches) {
+      return // Skip this match as it contains a valid self-closing component
+    }
+
     const lineNumber = getLineNumber(descriptor.source, componentTag)
     const lastPart = componentTag.split('\n').at(-1)?.trim() || ''
     results.push({ filePath, message: `line #${lineNumber} <bg_warn>${lastPart}</bg_warn>` })


Test patch:
diff --git a/src/rules/vue-strong/selfClosingComponents.test.ts b/src/rules/vue-strong/selfClosingComponents.test.ts
index a1caade..b826969 100644
--- a/src/rules/vue-strong/selfClosingComponents.test.ts
+++ b/src/rules/vue-strong/selfClosingComponents.test.ts
@@ -20,6 +20,25 @@ describe('checkSelfClosingComponents', () => {
     expect(result).toStrictEqual([])
   })
 
+  it('should not report files with self-closing components', () => {
+    const template = `<template>
+      <a
+        href="/path/to/link"
+      ><InsideComponent /></a>
+    </template>`
+    const descriptor = {
+      source: template,
+      template: {
+        content: template,
+      },
+    } as SFCDescriptor
+    const fileName = 'self-close-component.vue'
+    checkSelfClosingComponents(descriptor, fileName)
+    const result = reportSelfClosingComponents()
+    expect(result.length).toBe(0)
+    expect(result).toStrictEqual([])
+  })
+
   it('should not report files where the components self close', () => {
     const template = `<template>
       <MyComponent />