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 */
|
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 suffix = (mode !== 'all' ? `-${mode}` : '')
|
||||||
|
const componentName = resolveComponentName(fileName, prefixParts)
|
||||||
|
|
||||||
if (resolvedNames.has(componentName + suffix) || resolvedNames.has(componentName)) {
|
if (resolvedNames.has(componentName + suffix) || resolvedNames.has(componentName)) {
|
||||||
console.warn(`Two component files resolving to the same name \`${componentName}\`:\n` +
|
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
|
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 { resolve } from 'node:path'
|
||||||
import { expect, it, vi } from 'vitest'
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
import type { ComponentsDir } from 'nuxt/schema'
|
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 fixtureDir = resolve(__dirname, 'fixture')
|
||||||
const rFixture = (...p: string[]) => resolve(fixtureDir, ...p)
|
const rFixture = (...p: string[]) => resolve(fixtureDir, ...p)
|
||||||
@ -192,6 +192,19 @@ const expectedComponents = [
|
|||||||
preload: false,
|
preload: false,
|
||||||
priority: 1
|
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',
|
chunkName: 'components/some-glob',
|
||||||
export: 'default',
|
export: 'default',
|
||||||
@ -230,3 +243,25 @@ it('components:scanComponents', async () => {
|
|||||||
}
|
}
|
||||||
expect(scannedComponents).deep.eq(expectedComponents)
|
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