@@ -37,22 +37,24 @@ export function resolveSitemapEntries(sitemap: SitemapDefinition, urls: SitemapU
3737 autoI18n,
3838 isI18nMapped,
3939 } = runtimeConfig
40- const filterPath = createPathFilter ( {
41- include : sitemap . include ,
42- exclude : sitemap . exclude ,
43- } , baseURL || '/' )
40+ const hasFilters = ! ! sitemap . include ?. length || ! ! sitemap . exclude ?. length
41+ const filterPath = hasFilters
42+ ? createPathFilter ( {
43+ include : sitemap . include ,
44+ exclude : sitemap . exclude ,
45+ } , baseURL || '/' )
46+ : undefined
4447 // 1. normalise
45- const _urls = urls . map ( ( _e ) => {
48+ const _urls : ResolvedSitemapUrl [ ] = [ ]
49+ for ( const _e of urls ) {
4650 const e = preNormalizeEntry ( _e , resolvers )
47- if ( ! e . loc || ! filterPath ( e . loc ) )
48- return false
49- return e
50- } ) . filter ( Boolean ) as ResolvedSitemapUrl [ ]
51+ if ( e . loc && ( ! filterPath || filterPath ( e . loc , e . _path ?. pathname ) ) )
52+ _urls . push ( e )
53+ }
5154
52- let validI18nUrlsForTransform : NormalizedI18n [ ] = [ ]
5355 const withoutPrefixPaths : Record < string , NormalizedI18n [ ] > = { }
5456 if ( autoI18n && autoI18n . strategy !== 'no_prefix' ) {
55- const localeCodes = autoI18n . locales . map ( l => l . code )
57+ const localeCodes = new Set ( autoI18n . locales . map ( l => l . code ) )
5658 // Create locale lookup Map for O(1) access
5759 const localeByCode = new Map ( autoI18n . locales . map ( l => [ l . code , l ] ) )
5860 // Pre-check strategy once
@@ -63,11 +65,14 @@ export function resolveSitemapEntries(sitemap: SitemapDefinition, urls: SitemapU
6365 // Cache frequently accessed values
6466 const defaultLocale = autoI18n . defaultLocale
6567 const hasPages = ! ! autoI18n . pages
68+ const sortedPageKeys = hasPages ? Object . keys ( autoI18n . pages ! ) . sort ( ( a , b ) => b . length - a . length ) : undefined
6669 const hasDifferentDomains = ! ! autoI18n . differentDomains
6770
68- validI18nUrlsForTransform = _urls . map ( ( _e , i ) => {
71+ const validI18nUrlsForTransform : NormalizedI18n [ ] = [ ]
72+ for ( let i = 0 ; i < _urls . length ; i ++ ) {
73+ const _e = _urls [ i ] !
6974 if ( _e . _abs )
70- return false
75+ continue
7176 const split = splitForLocales ( _e . _relativeLoc , localeCodes )
7277 let localeCode = split [ 0 ]
7378 const pathWithoutPrefix = split [ 1 ]
@@ -78,37 +83,33 @@ export function resolveSitemapEntries(sitemap: SitemapDefinition, urls: SitemapU
7883 // Use Map instead of find for O(1) lookup
7984 const locale = localeByCode . get ( localeCode )
8085 if ( ! locale )
81- return false
86+ continue
8287 e . _locale = locale
8388 e . _index = i
8489 e . _key = `${ e . _sitemap || '' } ${ e . _path ?. pathname || '/' } ${ e . _path ?. search || '' } `
8590 withoutPrefixPaths [ pathWithoutPrefix ] = withoutPrefixPaths [ pathWithoutPrefix ] || [ ]
8691 // need to make sure the locale doesn't already exist
8792 if ( ! withoutPrefixPaths [ pathWithoutPrefix ] . some ( e => e . _locale . code === locale . code ) )
8893 withoutPrefixPaths [ pathWithoutPrefix ] . push ( e )
89- return e
90- } ) . filter ( Boolean ) as NormalizedI18n [ ]
94+ validI18nUrlsForTransform . push ( e )
95+ }
9196
9297 for ( const e of validI18nUrlsForTransform ) {
9398 // let's try and find other urls that we can use for alternatives
9499 if ( ! e . _i18nTransform && ! e . alternatives ?. length ) {
95- const alternatives = ( withoutPrefixPaths [ e . _pathWithoutPrefix ] || [ ] )
96- . map ( ( u ) => {
97- const entries : AlternativeEntry [ ] = [ ]
98- if ( u . _locale . code === defaultLocale ) {
99- entries . push ( {
100- href : u . loc ,
101- hreflang : 'x-default' ,
102- } )
103- }
104- entries . push ( {
100+ const alternatives : AlternativeEntry [ ] = [ ]
101+ for ( const u of withoutPrefixPaths [ e . _pathWithoutPrefix ] || [ ] ) {
102+ if ( u . _locale . code === defaultLocale ) {
103+ alternatives . push ( {
105104 href : u . loc ,
106- hreflang : u . _locale . _hreflang || defaultLocale ,
105+ hreflang : 'x-default' ,
107106 } )
108- return entries
107+ }
108+ alternatives . push ( {
109+ href : u . loc ,
110+ hreflang : u . _locale . _hreflang || defaultLocale ,
109111 } )
110- . flat ( )
111- . filter ( Boolean ) as AlternativeEntry [ ]
112+ }
112113 if ( alternatives . length )
113114 e . alternatives = alternatives
114115 }
@@ -135,7 +136,7 @@ export function resolveSitemapEntries(sitemap: SitemapDefinition, urls: SitemapU
135136 }
136137 else {
137138 // Find page mapping with support for dynamic routes
138- const pageMatch = hasPages ? findPageMapping ( e . _pathWithoutPrefix , autoI18n . pages ! ) : null
139+ const pageMatch = hasPages ? findPageMapping ( e . _pathWithoutPrefix , autoI18n . pages ! , sortedPageKeys ) : null
139140 const pathSearch = e . _path ?. search || ''
140141 const pathWithoutPrefix = e . _pathWithoutPrefix
141142
@@ -191,7 +192,7 @@ export function resolveSitemapEntries(sitemap: SitemapDefinition, urls: SitemapU
191192 href = joinURL ( '/' , code , pathWithoutPrefix )
192193 }
193194
194- if ( ! filterPath ( href ) )
195+ if ( filterPath && ! filterPath ( href ) )
195196 continue
196197 alternatives . push ( {
197198 hreflang : locale . _hreflang ,
@@ -283,11 +284,18 @@ export async function buildResolvedSitemapUrls(
283284 const localeSitemapKeys = isI18nMapped && autoI18n ? autoI18n . locales . map ( l => l . _sitemap ) : [ ]
284285 if ( isMultiSitemap ) {
285286 const sitemapNames = Object . keys ( sitemaps ) . filter ( k => k !== 'index' )
287+ const validSitemapNames = new Set ( sitemapNames )
288+ if ( isI18nMapped ) {
289+ for ( const name of sitemapNames ) {
290+ const localeKey = resolveI18nSitemapLocaleKey ( name , localeSitemapKeys )
291+ if ( localeKey )
292+ validSitemapNames . add ( localeKey )
293+ }
294+ }
286295 // @ts -expect-error loose typing
287296 const warnedSitemaps = nitro ?. _sitemapWarnedSitemaps || new Set < string > ( )
288297 for ( const e of enhancedUrls ) {
289- const hasMatchingSitemap = typeof e . _sitemap === 'string'
290- && ( sitemapNames . includes ( e . _sitemap ) || ( isI18nMapped && sitemapNames . some ( name => resolveI18nSitemapLocaleKey ( name , localeSitemapKeys ) === e . _sitemap ) ) )
298+ const hasMatchingSitemap = typeof e . _sitemap === 'string' && validSitemapNames . has ( e . _sitemap )
291299 if ( typeof e . _sitemap === 'string' && ! hasMatchingSitemap ) {
292300 if ( ! warnedSitemaps . has ( e . _sitemap ) ) {
293301 warnedSitemaps . add ( e . _sitemap )
@@ -301,6 +309,7 @@ export async function buildResolvedSitemapUrls(
301309 }
302310 }
303311
312+ const matchedLocaleSitemap = isI18nMapped ? resolveI18nSitemapLocaleKey ( matchName , localeSitemapKeys ) : null
304313 const filteredUrls = enhancedUrls . filter ( ( e ) => {
305314 if ( e . _sitemap === false )
306315 return false
@@ -313,7 +322,7 @@ export async function buildResolvedSitemapUrls(
313322 // back to its locale key (longest match) so prefix-sharing locales don't collide,
314323 // e.g. a `zh` URL must not land in the `zh-Hant` sitemap.
315324 if ( isI18nMapped )
316- return e . _sitemap === resolveI18nSitemapLocaleKey ( matchName , localeSitemapKeys )
325+ return e . _sitemap === matchedLocaleSitemap
317326 return false
318327 }
319328 return true
0 commit comments