Skip to content

Commit 4b94c3d

Browse files
authoredJul 26, 2024··
feat: sitemapsPathPrefix config (#325)
1 parent f340d8a commit 4b94c3d

18 files changed

+52
-38
lines changed
 

‎src/module.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
hasNuxtModuleCompatibility,
1212
useLogger,
1313
} from '@nuxt/kit'
14-
import { withBase, withLeadingSlash, withoutLeadingSlash, withoutTrailingSlash } from 'ufo'
14+
import { joinURL, withBase, withLeadingSlash, withoutLeadingSlash, withoutTrailingSlash } from 'ufo'
1515
import { installNuxtSiteConfig } from 'nuxt-site-config-kit'
1616
import type { NuxtI18nOptions } from '@nuxtjs/i18n'
1717
import { defu } from 'defu'
@@ -63,6 +63,7 @@ export default defineNuxtModule<ModuleOptions>({
6363
dynamicUrlsApiEndpoint: '/api/_sitemap-urls',
6464
urls: [],
6565
sortEntries: true,
66+
sitemapsPathPrefix: '/__sitemap__/',
6667
xsl: '/__sitemap__/style.xsl',
6768
xslTips: true,
6869
strictNuxtContentPaths: false,
@@ -320,8 +321,8 @@ declare module 'vue-router' {
320321
nuxt.options.nitro.routeRules['/sitemap_index.xml'] = routeRules
321322
if (typeof config.sitemaps === 'object') {
322323
for (const k in config.sitemaps) {
323-
nuxt.options.nitro.routeRules[`/sitemap/${k}.xml`] = routeRules
324-
nuxt.options.nitro.routeRules[`/${k}-sitemap.xml`] = { redirect: `/sitemap/${k}.xml` }
324+
nuxt.options.nitro.routeRules[joinURL(config.sitemapsPathPrefix, `/${k}.xml`)] = routeRules
325+
nuxt.options.nitro.routeRules[`/${k}-sitemap.xml`] = { redirect: joinURL(config.sitemapsPathPrefix, `${k}.xml`) }
325326
}
326327
}
327328
else {
@@ -400,7 +401,7 @@ declare module 'vue-router' {
400401
middleware: false,
401402
})
402403
addServerHandler({
403-
route: `/sitemap/**:sitemap`,
404+
route: joinURL(config.sitemapsPathPrefix, `/**:sitemap`),
404405
handler: resolve('./runtime/nitro/routes/sitemap/[sitemap].xml'),
405406
lazy: true,
406407
middleware: false,
@@ -514,6 +515,7 @@ declare module 'vue-router' {
514515
// needed for nuxt/content integration and prerendering
515516
discoverImages: config.discoverImages,
516517
discoverVideos: config.discoverVideos,
518+
sitemapsPathPrefix: config.sitemapsPathPrefix,
517519

518520
/* @nuxt/content */
519521
isNuxtContentDocumentDriven,

‎src/runtime/nitro/routes/sitemap/[sitemap].xml.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { createError, defineEventHandler, getRouterParam } from 'h3'
2+
import { withoutLeadingSlash, withoutTrailingSlash } from 'ufo'
23
import { useSimpleSitemapRuntimeConfig } from '../../utils'
34
import { createSitemap } from '../../sitemap/nitro'
45

56
export default defineEventHandler(async (e) => {
67
const runtimeConfig = useSimpleSitemapRuntimeConfig(e)
78
const { sitemaps } = runtimeConfig
89

9-
const sitemapName = (getRouterParam(e, 'sitemap') || e.path)?.replace('.xml', '')
10-
.replace('/sitemap/', '')
10+
const sitemapName = withoutLeadingSlash(withoutTrailingSlash((getRouterParam(e, 'sitemap') || e.path)?.replace('.xml', '')
11+
.replace(runtimeConfig.sitemapsPathPrefix, '')))
1112
// check if sitemapName can be cast to a number safely
1213
const isChunking = typeof sitemaps.chunks !== 'undefined' && !Number.isNaN(Number(sitemapName))
1314
if (!sitemapName || (!(sitemapName in sitemaps) && !isChunking)) {

‎src/runtime/nitro/routes/sitemap_index.xml.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { appendHeader, defineEventHandler, setHeader } from 'h3'
2+
import { joinURL } from 'ufo'
23
import { useSimpleSitemapRuntimeConfig } from '../utils'
34
import { buildSitemapIndex, urlsToIndexXml } from '../sitemap/builder/sitemap-index'
45
import type { SitemapOutputHookCtx } from '../../types'
@@ -18,7 +19,7 @@ export default defineEventHandler(async (e) => {
1819
e,
1920
'x-nitro-prerender',
2021
sitemaps.filter(entry => !!entry._sitemapName)
21-
.map(entry => encodeURIComponent(`/sitemap/${entry._sitemapName}.xml`)).join(', '),
22+
.map(entry => encodeURIComponent(joinURL(runtimeConfig.sitemapsPathPrefix, `/${entry._sitemapName}.xml`))).join(', '),
2223
)
2324
}
2425

‎src/runtime/nitro/sitemap/builder/sitemap-index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { defu } from 'defu'
2+
import { joinURL } from 'ufo'
23
import type {
34
ModuleRuntimeConfig,
45
NitroUrlResolvers,
@@ -22,6 +23,7 @@ export async function buildSitemapIndex(resolvers: NitroUrlResolvers, runtimeCon
2223
autoI18n,
2324
isI18nMapped,
2425
sortEntries,
26+
sitemapsPathPrefix,
2527
} = runtimeConfig
2628

2729
if (!sitemaps)
@@ -64,7 +66,7 @@ export async function buildSitemapIndex(resolvers: NitroUrlResolvers, runtimeCon
6466
const sitemap = chunks[name]
6567
const entry: SitemapIndexEntry = {
6668
_sitemapName: name,
67-
sitemap: resolvers.canonicalUrlResolver(`sitemap/${name}.xml`),
69+
sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix, `/${name}.xml`)),
6870
}
6971
let lastmod = sitemap.urls
7072
.filter(a => !!a?.lastmod)

‎src/runtime/types.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ export interface ModuleOptions extends SitemapDefinition {
4444
* @default false
4545
*/
4646
sitemaps?: boolean | MultiSitemapsInput
47+
/**
48+
* The path prefix for the sitemaps.
49+
*
50+
* @default /__sitemap__/
51+
*/
52+
sitemapsPathPrefix: string
4753
/**
4854
* Sitemaps to append to the sitemap index.
4955
*
@@ -200,7 +206,7 @@ export interface AutoI18nConfig {
200206
strategy: 'prefix' | 'prefix_except_default' | 'prefix_and_default' | 'no_prefix'
201207
}
202208

203-
export interface ModuleRuntimeConfig extends Pick<ModuleOptions, 'cacheMaxAgeSeconds' | 'sitemapName' | 'excludeAppSources' | 'sortEntries' | 'defaultSitemapsChunkSize' | 'xslColumns' | 'xslTips' | 'debug' | 'discoverImages' | 'discoverVideos' | 'autoLastmod' | 'xsl' | 'credits' > {
209+
export interface ModuleRuntimeConfig extends Pick<ModuleOptions, 'sitemapsPathPrefix' | 'cacheMaxAgeSeconds' | 'sitemapName' | 'excludeAppSources' | 'sortEntries' | 'defaultSitemapsChunkSize' | 'xslColumns' | 'xslTips' | 'debug' | 'discoverImages' | 'discoverVideos' | 'autoLastmod' | 'xsl' | 'credits' > {
204210
version: string
205211
isNuxtContentDocumentDriven: boolean
206212
sitemaps: { index?: Pick<SitemapDefinition, 'sitemapName' | '_route'> & { sitemaps: SitemapIndexEntry[] } } & Record<string, Omit<SitemapDefinition, 'urls'> & { _hasSourceChunk?: boolean }>

‎test/fixtures/i18n/nuxt.config.ts

+2
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,6 @@ export default defineNuxtConfig({
4141
},
4242
],
4343
},
44+
45+
compatibilityDate: '2024-07-22',
4446
})

‎test/integration/chunks/default.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ describe('multi chunks', () => {
1717
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
1818
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
1919
<sitemap>
20-
<loc>https://nuxtseo.com/sitemap/0.xml</loc>
20+
<loc>https://nuxtseo.com/__sitemap__/0.xml</loc>
2121
</sitemap>
2222
<sitemap>
23-
<loc>https://nuxtseo.com/sitemap/1.xml</loc>
23+
<loc>https://nuxtseo.com/__sitemap__/1.xml</loc>
2424
</sitemap>
2525
<sitemap>
26-
<loc>https://nuxtseo.com/sitemap/2.xml</loc>
26+
<loc>https://nuxtseo.com/__sitemap__/2.xml</loc>
2727
</sitemap>
2828
<sitemap>
29-
<loc>https://nuxtseo.com/sitemap/3.xml</loc>
29+
<loc>https://nuxtseo.com/__sitemap__/3.xml</loc>
3030
</sitemap>
3131
</sitemapindex>"
3232
`)
33-
const sitemap0 = await $fetch('/sitemap/0.xml')
33+
const sitemap0 = await $fetch('/__sitemap__/0.xml')
3434
expect(sitemap0).toMatchInlineSnapshot(`
3535
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
3636
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

‎test/integration/chunks/generate.test.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,20 @@ describe('generate', () => {
2727
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
2828
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
2929
<sitemap>
30-
<loc>https://nuxtseo.com/sitemap/0.xml</loc>
30+
<loc>https://nuxtseo.com/__sitemap__/0.xml</loc>
3131
</sitemap>
3232
<sitemap>
33-
<loc>https://nuxtseo.com/sitemap/1.xml</loc>
33+
<loc>https://nuxtseo.com/__sitemap__/1.xml</loc>
3434
</sitemap>
3535
<sitemap>
36-
<loc>https://nuxtseo.com/sitemap/2.xml</loc>
36+
<loc>https://nuxtseo.com/__sitemap__/2.xml</loc>
3737
</sitemap>
3838
<sitemap>
39-
<loc>https://nuxtseo.com/sitemap/3.xml</loc>
39+
<loc>https://nuxtseo.com/__sitemap__/3.xml</loc>
4040
</sitemap>
4141
</sitemapindex>"
4242
`)
43-
const sitemapEn = (await readFile(resolve(rootDir, '.output/public/sitemap/0.xml'), 'utf-8')).replace(/lastmod>(.*?)</g, 'lastmod><')
43+
const sitemapEn = (await readFile(resolve(rootDir, '.output/public/__sitemap__/0.xml'), 'utf-8')).replace(/lastmod>(.*?)</g, 'lastmod><')
4444
expect(sitemapEn).toMatchInlineSnapshot(`
4545
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
4646
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

‎test/integration/i18n/domains.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,18 @@ describe('i18n domains', () => {
4141
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
4242
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
4343
<sitemap>
44-
<loc>https://nuxtseo.com/sitemap/en-US.xml</loc>
44+
<loc>https://nuxtseo.com/__sitemap__/en-US.xml</loc>
4545
</sitemap>
4646
<sitemap>
47-
<loc>https://nuxtseo.com/sitemap/es-ES.xml</loc>
47+
<loc>https://nuxtseo.com/__sitemap__/es-ES.xml</loc>
4848
</sitemap>
4949
<sitemap>
50-
<loc>https://nuxtseo.com/sitemap/fr-FR.xml</loc>
50+
<loc>https://nuxtseo.com/__sitemap__/fr-FR.xml</loc>
5151
</sitemap>
5252
</sitemapindex>"
5353
`)
5454

55-
const fr = await $fetch('/sitemap/fr-FR.xml')
55+
const fr = await $fetch('/__sitemap__/fr-FR.xml')
5656
expect(fr).toMatchInlineSnapshot(`
5757
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
5858
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

‎test/integration/i18n/dynamic-urls.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ await setup({
2424
})
2525
describe('i18n dynamic urls', () => {
2626
it('basic', async () => {
27-
let sitemap = await $fetch('/sitemap/en-US.xml')
27+
let sitemap = await $fetch('/__sitemap__/en-US.xml')
2828

2929
// strip lastmod
3030
sitemap = sitemap.replace(/<lastmod>.*<\/lastmod>/g, '')

‎test/integration/i18n/filtering-include.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ await setup({
1919
})
2020
describe('i18n filtering with include', () => {
2121
it('basic', async () => {
22-
const sitemap = await $fetch('/sitemap/main.xml')
22+
const sitemap = await $fetch('/__sitemap__/main.xml')
2323

2424
expect(sitemap).toMatchInlineSnapshot(`
2525
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>

‎test/integration/i18n/filtering-regexp.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ await setup({
2121
})
2222
describe('i18n filtering with regexp', () => {
2323
it('basic', async () => {
24-
let sitemap = await $fetch('/sitemap/en-US.xml')
24+
let sitemap = await $fetch('/__sitemap__/en-US.xml')
2525

2626
// strip lastmod
2727
sitemap = sitemap.replace(/<lastmod>.*<\/lastmod>/g, '')

‎test/integration/i18n/filtering.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ await setup({
1616
})
1717
describe('i18n filtering', () => {
1818
it('basic', async () => {
19-
let sitemap = await $fetch('/sitemap/en-US.xml')
19+
let sitemap = await $fetch('/__sitemap__/en-US.xml')
2020

2121
// strip lastmod
2222
sitemap = sitemap.replace(/<lastmod>.*<\/lastmod>/g, '')

‎test/integration/i18n/generate.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@ describe('generate', () => {
2727
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
2828
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
2929
<sitemap>
30-
<loc>https://nuxtseo.com/sitemap/en-US.xml</loc>
30+
<loc>https://nuxtseo.com/__sitemap__/en-US.xml</loc>
3131
</sitemap>
3232
<sitemap>
33-
<loc>https://nuxtseo.com/sitemap/es-ES.xml</loc>
33+
<loc>https://nuxtseo.com/__sitemap__/es-ES.xml</loc>
3434
</sitemap>
3535
<sitemap>
36-
<loc>https://nuxtseo.com/sitemap/fr-FR.xml</loc>
36+
<loc>https://nuxtseo.com/__sitemap__/fr-FR.xml</loc>
3737
</sitemap>
3838
</sitemapindex>"
3939
`)
40-
const sitemapEn = (await readFile(resolve(rootDir, '.output/public/sitemap/en-US.xml'), 'utf-8')).replace(/lastmod>(.*?)</g, 'lastmod><')
40+
const sitemapEn = (await readFile(resolve(rootDir, '.output/public/__sitemap__/en-US.xml'), 'utf-8')).replace(/lastmod>(.*?)</g, 'lastmod><')
4141
expect(sitemapEn).toMatchInlineSnapshot(`
4242
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
4343
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

‎test/integration/i18n/pages-multi.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,17 @@ describe('i18n pages multi', () => {
6363
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
6464
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
6565
<sitemap>
66-
<loc>https://nuxtseo.com/sitemap/en-US.xml</loc>
66+
<loc>https://nuxtseo.com/__sitemap__/en-US.xml</loc>
6767
</sitemap>
6868
<sitemap>
69-
<loc>https://nuxtseo.com/sitemap/es-ES.xml</loc>
69+
<loc>https://nuxtseo.com/__sitemap__/es-ES.xml</loc>
7070
</sitemap>
7171
<sitemap>
72-
<loc>https://nuxtseo.com/sitemap/fr-FR.xml</loc>
72+
<loc>https://nuxtseo.com/__sitemap__/fr-FR.xml</loc>
7373
</sitemap>
7474
</sitemapindex>"
7575
`)
76-
const fr = await $fetch('/sitemap/fr-FR.xml')
76+
const fr = await $fetch('/__sitemap__/fr-FR.xml')
7777
expect(fr).toMatchInlineSnapshot(`
7878
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
7979
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

‎test/integration/multi/defaults.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ await setup({
3636
})
3737
describe('mutli defaults', () => {
3838
it('basic', async () => {
39-
let sitemap = await $fetch('/sitemap/foo.xml')
39+
let sitemap = await $fetch('/__sitemap__/foo.xml')
4040
// remove lastmods before tresting
4141
sitemap = sitemap.replace(/lastmod>(.*?)</g, 'lastmod><')
4242
// basic test to make sure we get a valid response

‎test/integration/multi/endpoints.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ await setup({
2525
})
2626
describe('multi endpoints', () => {
2727
it('basic', async () => {
28-
let sitemap = await $fetch('/sitemap/foo.xml')
28+
let sitemap = await $fetch('/__sitemap__/foo.xml')
2929
// remove lastmods before tresting
3030
sitemap = sitemap.replace(/lastmod>(.*?)</g, 'lastmod><')
3131
// basic test to make sure we get a valid response

‎test/integration/multi/filtering.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ await setup({
3636
})
3737
describe('multi filtering', () => {
3838
it('basic', async () => {
39-
let sitemap = await $fetch('/sitemap/foo.xml')
39+
let sitemap = await $fetch('/__sitemap__/foo.xml')
4040

4141
// strip lastmod
4242
sitemap = sitemap.replace(/<lastmod>.*<\/lastmod>/g, '')

0 commit comments

Comments
 (0)
Please sign in to comment.