mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
fix(nuxt): ensure all dir parts are present in component name (#20779)
This commit is contained in:
parent
1f30cf18e3
commit
ce84c9b44f
@ -72,24 +72,8 @@ export async function scanComponents (dirs: ComponentsDir[], srcDir: string): Pr
|
||||
fileName = dir.pathPrefix === false ? basename(dirname(filePath)) : '' /* inherits from path */
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of fileName parts splitted by case, / or -
|
||||
*
|
||||
* @example third-component -> ['third', 'component']
|
||||
* @example AwesomeComponent -> ['Awesome', 'Component']
|
||||
*/
|
||||
const fileNameParts = splitByCase(fileName)
|
||||
|
||||
const componentNameParts: string[] = []
|
||||
|
||||
while (prefixParts.length &&
|
||||
(prefixParts[0] || '').toLowerCase() !== (fileNameParts[0] || '').toLowerCase()
|
||||
) {
|
||||
componentNameParts.push(prefixParts.shift()!)
|
||||
}
|
||||
|
||||
const componentName = pascalCase(componentNameParts) + pascalCase(fileNameParts)
|
||||
const suffix = (mode !== 'all' ? `-${mode}` : '')
|
||||
const componentName = resolveComponentName(fileName, prefixParts)
|
||||
|
||||
if (resolvedNames.has(componentName + suffix) || resolvedNames.has(componentName)) {
|
||||
console.warn(`Two component files resolving to the same name \`${componentName}\`:\n` +
|
||||
@ -137,3 +121,30 @@ export async function scanComponents (dirs: ComponentsDir[], srcDir: string): Pr
|
||||
|
||||
return components
|
||||
}
|
||||
|
||||
export function resolveComponentName (fileName: string, prefixParts: string[]) {
|
||||
/**
|
||||
* Array of fileName parts splitted by case, / or -
|
||||
*
|
||||
* @example third-component -> ['third', 'component']
|
||||
* @example AwesomeComponent -> ['Awesome', 'Component']
|
||||
*/
|
||||
const fileNameParts = splitByCase(fileName)
|
||||
const fileNamePartsContent = fileNameParts.join('').toLowerCase()
|
||||
const componentNameParts: string[] = [...prefixParts]
|
||||
let index = prefixParts.length - 1
|
||||
const matchedSuffix:string[] = []
|
||||
while (index >= 0) {
|
||||
matchedSuffix.unshift((prefixParts[index] || '').toLowerCase())
|
||||
if (fileNamePartsContent.startsWith(matchedSuffix.join('')) ||
|
||||
// e.g Item/Item/Item.vue -> Item
|
||||
(prefixParts[index].toLowerCase() === fileNamePartsContent &&
|
||||
prefixParts[index + 1] &&
|
||||
prefixParts[index] === prefixParts[index + 1])) {
|
||||
componentNameParts.length = index
|
||||
}
|
||||
index--
|
||||
}
|
||||
|
||||
return pascalCase(componentNameParts) + pascalCase(fileNameParts)
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
This is Same name component!
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
</script>
|
@ -1,8 +1,8 @@
|
||||
import { resolve } from 'node:path'
|
||||
import { expect, it, vi } from 'vitest'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import type { ComponentsDir } from 'nuxt/schema'
|
||||
|
||||
import { scanComponents } from '../src/components/scan'
|
||||
import { resolveComponentName, scanComponents } from '../src/components/scan'
|
||||
|
||||
const fixtureDir = resolve(__dirname, 'fixture')
|
||||
const rFixture = (...p: string[]) => resolve(fixtureDir, ...p)
|
||||
@ -192,6 +192,19 @@ const expectedComponents = [
|
||||
preload: false,
|
||||
priority: 1
|
||||
},
|
||||
{
|
||||
chunkName: 'components/same-name-same',
|
||||
export: 'default',
|
||||
global: undefined,
|
||||
island: undefined,
|
||||
kebabName: 'same-name-same',
|
||||
mode: 'all',
|
||||
pascalName: 'SameNameSame',
|
||||
prefetch: false,
|
||||
preload: false,
|
||||
priority: 1,
|
||||
shortPath: 'components/same-name/same/Same.vue'
|
||||
},
|
||||
{
|
||||
chunkName: 'components/some-glob',
|
||||
export: 'default',
|
||||
@ -230,3 +243,25 @@ it('components:scanComponents', async () => {
|
||||
}
|
||||
expect(scannedComponents).deep.eq(expectedComponents)
|
||||
})
|
||||
|
||||
const tests: Array<[string, string[], string]> = [
|
||||
['WithClientOnlySetup', ['Client'], 'ClientWithClientOnlySetup'],
|
||||
['ItemHolderItem', ['Item', 'Holder', 'Item'], 'ItemHolderItem'],
|
||||
['Item', ['Item'], 'Item'],
|
||||
['Item', ['Item', 'Item'], 'Item'],
|
||||
['ItemTest', ['Item', 'Test'], 'ItemTest'],
|
||||
['ThingItemTest', ['Item', 'Thing'], 'ItemThingItemTest'],
|
||||
['Item', ['Thing', 'Item'], 'ThingItem'],
|
||||
['Item', ['Item', 'Holder', 'Item'], 'ItemHolderItem'],
|
||||
['ItemHolder', ['Item', 'Holder', 'Item'], 'ItemHolderItemHolder'],
|
||||
['ThingItemTest', ['Item', 'Thing', 'Foo'], 'ItemThingFooThingItemTest'],
|
||||
['ItemIn', ['Item', 'Holder', 'Item', 'In'], 'ItemHolderItemIn'],
|
||||
['Item', ['Item', 'Holder', 'Test'], 'ItemHolderTestItem'],
|
||||
['ItemHolderItem', ['Item', 'Holder', 'Item', 'Holder'], 'ItemHolderItemHolderItem']
|
||||
]
|
||||
|
||||
describe('components:resolveComponentName', () => {
|
||||
it.each(tests)('resolves %s with prefix parts %s and filename %s', (fileName, prefixParts: string[], result) => {
|
||||
expect(resolveComponentName(fileName, prefixParts)).toBe(result)
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user