Skip to content

Commit

Permalink
feat: sitemapsPathPrefix config (#325)
Browse files Browse the repository at this point in the history
  • Loading branch information
harlan-zw authored Jul 26, 2024
1 parent f340d8a commit 4b94c3d
Show file tree
Hide file tree
Showing 18 changed files with 52 additions and 38 deletions.
10 changes: 6 additions & 4 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
hasNuxtModuleCompatibility,
useLogger,
} from '@nuxt/kit'
import { withBase, withLeadingSlash, withoutLeadingSlash, withoutTrailingSlash } from 'ufo'
import { joinURL, withBase, withLeadingSlash, withoutLeadingSlash, withoutTrailingSlash } from 'ufo'
import { installNuxtSiteConfig } from 'nuxt-site-config-kit'
import type { NuxtI18nOptions } from '@nuxtjs/i18n'
import { defu } from 'defu'
Expand Down Expand Up @@ -63,6 +63,7 @@ export default defineNuxtModule<ModuleOptions>({
dynamicUrlsApiEndpoint: '/api/_sitemap-urls',
urls: [],
sortEntries: true,
sitemapsPathPrefix: '/__sitemap__/',
xsl: '/__sitemap__/style.xsl',
xslTips: true,
strictNuxtContentPaths: false,
Expand Down Expand Up @@ -320,8 +321,8 @@ declare module 'vue-router' {
nuxt.options.nitro.routeRules['/sitemap_index.xml'] = routeRules
if (typeof config.sitemaps === 'object') {
for (const k in config.sitemaps) {
nuxt.options.nitro.routeRules[`/sitemap/${k}.xml`] = routeRules
nuxt.options.nitro.routeRules[`/${k}-sitemap.xml`] = { redirect: `/sitemap/${k}.xml` }
nuxt.options.nitro.routeRules[joinURL(config.sitemapsPathPrefix, `/${k}.xml`)] = routeRules
nuxt.options.nitro.routeRules[`/${k}-sitemap.xml`] = { redirect: joinURL(config.sitemapsPathPrefix, `${k}.xml`) }
}
}
else {
Expand Down Expand Up @@ -400,7 +401,7 @@ declare module 'vue-router' {
middleware: false,
})
addServerHandler({
route: `/sitemap/**:sitemap`,
route: joinURL(config.sitemapsPathPrefix, `/**:sitemap`),
handler: resolve('./runtime/nitro/routes/sitemap/[sitemap].xml'),
lazy: true,
middleware: false,
Expand Down Expand Up @@ -514,6 +515,7 @@ declare module 'vue-router' {
// needed for nuxt/content integration and prerendering
discoverImages: config.discoverImages,
discoverVideos: config.discoverVideos,
sitemapsPathPrefix: config.sitemapsPathPrefix,

/* @nuxt/content */
isNuxtContentDocumentDriven,
Expand Down
5 changes: 3 additions & 2 deletions src/runtime/nitro/routes/sitemap/[sitemap].xml.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { createError, defineEventHandler, getRouterParam } from 'h3'
import { withoutLeadingSlash, withoutTrailingSlash } from 'ufo'
import { useSimpleSitemapRuntimeConfig } from '../../utils'
import { createSitemap } from '../../sitemap/nitro'

export default defineEventHandler(async (e) => {
const runtimeConfig = useSimpleSitemapRuntimeConfig(e)
const { sitemaps } = runtimeConfig

const sitemapName = (getRouterParam(e, 'sitemap') || e.path)?.replace('.xml', '')
.replace('/sitemap/', '')
const sitemapName = withoutLeadingSlash(withoutTrailingSlash((getRouterParam(e, 'sitemap') || e.path)?.replace('.xml', '')
.replace(runtimeConfig.sitemapsPathPrefix, '')))
// check if sitemapName can be cast to a number safely
const isChunking = typeof sitemaps.chunks !== 'undefined' && !Number.isNaN(Number(sitemapName))
if (!sitemapName || (!(sitemapName in sitemaps) && !isChunking)) {
Expand Down
3 changes: 2 additions & 1 deletion src/runtime/nitro/routes/sitemap_index.xml.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { appendHeader, defineEventHandler, setHeader } from 'h3'
import { joinURL } from 'ufo'
import { useSimpleSitemapRuntimeConfig } from '../utils'
import { buildSitemapIndex, urlsToIndexXml } from '../sitemap/builder/sitemap-index'
import type { SitemapOutputHookCtx } from '../../types'
Expand All @@ -18,7 +19,7 @@ export default defineEventHandler(async (e) => {
e,
'x-nitro-prerender',
sitemaps.filter(entry => !!entry._sitemapName)
.map(entry => encodeURIComponent(`/sitemap/${entry._sitemapName}.xml`)).join(', '),
.map(entry => encodeURIComponent(joinURL(runtimeConfig.sitemapsPathPrefix, `/${entry._sitemapName}.xml`))).join(', '),
)
}

Expand Down
4 changes: 3 additions & 1 deletion src/runtime/nitro/sitemap/builder/sitemap-index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defu } from 'defu'
import { joinURL } from 'ufo'
import type {
ModuleRuntimeConfig,
NitroUrlResolvers,
Expand All @@ -22,6 +23,7 @@ export async function buildSitemapIndex(resolvers: NitroUrlResolvers, runtimeCon
autoI18n,
isI18nMapped,
sortEntries,
sitemapsPathPrefix,
} = runtimeConfig

if (!sitemaps)
Expand Down Expand Up @@ -64,7 +66,7 @@ export async function buildSitemapIndex(resolvers: NitroUrlResolvers, runtimeCon
const sitemap = chunks[name]
const entry: SitemapIndexEntry = {
_sitemapName: name,
sitemap: resolvers.canonicalUrlResolver(`sitemap/${name}.xml`),
sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix, `/${name}.xml`)),
}
let lastmod = sitemap.urls
.filter(a => !!a?.lastmod)
Expand Down
8 changes: 7 additions & 1 deletion src/runtime/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ export interface ModuleOptions extends SitemapDefinition {
* @default false
*/
sitemaps?: boolean | MultiSitemapsInput
/**
* The path prefix for the sitemaps.
*
* @default /__sitemap__/
*/
sitemapsPathPrefix: string
/**
* Sitemaps to append to the sitemap index.
*
Expand Down Expand Up @@ -200,7 +206,7 @@ export interface AutoI18nConfig {
strategy: 'prefix' | 'prefix_except_default' | 'prefix_and_default' | 'no_prefix'
}

export interface ModuleRuntimeConfig extends Pick<ModuleOptions, 'cacheMaxAgeSeconds' | 'sitemapName' | 'excludeAppSources' | 'sortEntries' | 'defaultSitemapsChunkSize' | 'xslColumns' | 'xslTips' | 'debug' | 'discoverImages' | 'discoverVideos' | 'autoLastmod' | 'xsl' | 'credits' > {
export interface ModuleRuntimeConfig extends Pick<ModuleOptions, 'sitemapsPathPrefix' | 'cacheMaxAgeSeconds' | 'sitemapName' | 'excludeAppSources' | 'sortEntries' | 'defaultSitemapsChunkSize' | 'xslColumns' | 'xslTips' | 'debug' | 'discoverImages' | 'discoverVideos' | 'autoLastmod' | 'xsl' | 'credits' > {
version: string
isNuxtContentDocumentDriven: boolean
sitemaps: { index?: Pick<SitemapDefinition, 'sitemapName' | '_route'> & { sitemaps: SitemapIndexEntry[] } } & Record<string, Omit<SitemapDefinition, 'urls'> & { _hasSourceChunk?: boolean }>
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/i18n/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ export default defineNuxtConfig({
},
],
},

compatibilityDate: '2024-07-22',
})
10 changes: 5 additions & 5 deletions test/integration/chunks/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ describe('multi chunks', () => {
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://nuxtseo.com/sitemap/0.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/0.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/1.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/1.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/2.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/2.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/3.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/3.xml</loc>
</sitemap>
</sitemapindex>"
`)
const sitemap0 = await $fetch('/sitemap/0.xml')
const sitemap0 = await $fetch('/__sitemap__/0.xml')
expect(sitemap0).toMatchInlineSnapshot(`
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
<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">
Expand Down
10 changes: 5 additions & 5 deletions test/integration/chunks/generate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ describe('generate', () => {
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://nuxtseo.com/sitemap/0.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/0.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/1.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/1.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/2.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/2.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/3.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/3.xml</loc>
</sitemap>
</sitemapindex>"
`)
const sitemapEn = (await readFile(resolve(rootDir, '.output/public/sitemap/0.xml'), 'utf-8')).replace(/lastmod>(.*?)</g, 'lastmod><')
const sitemapEn = (await readFile(resolve(rootDir, '.output/public/__sitemap__/0.xml'), 'utf-8')).replace(/lastmod>(.*?)</g, 'lastmod><')
expect(sitemapEn).toMatchInlineSnapshot(`
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
<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">
Expand Down
8 changes: 4 additions & 4 deletions test/integration/i18n/domains.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,18 @@ describe('i18n domains', () => {
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://nuxtseo.com/sitemap/en-US.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/en-US.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/es-ES.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/es-ES.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/fr-FR.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/fr-FR.xml</loc>
</sitemap>
</sitemapindex>"
`)

const fr = await $fetch('/sitemap/fr-FR.xml')
const fr = await $fetch('/__sitemap__/fr-FR.xml')
expect(fr).toMatchInlineSnapshot(`
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
<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">
Expand Down
2 changes: 1 addition & 1 deletion test/integration/i18n/dynamic-urls.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ await setup({
})
describe('i18n dynamic urls', () => {
it('basic', async () => {
let sitemap = await $fetch('/sitemap/en-US.xml')
let sitemap = await $fetch('/__sitemap__/en-US.xml')

// strip lastmod
sitemap = sitemap.replace(/<lastmod>.*<\/lastmod>/g, '')
Expand Down
2 changes: 1 addition & 1 deletion test/integration/i18n/filtering-include.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ await setup({
})
describe('i18n filtering with include', () => {
it('basic', async () => {
const sitemap = await $fetch('/sitemap/main.xml')
const sitemap = await $fetch('/__sitemap__/main.xml')

expect(sitemap).toMatchInlineSnapshot(`
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
Expand Down
2 changes: 1 addition & 1 deletion test/integration/i18n/filtering-regexp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ await setup({
})
describe('i18n filtering with regexp', () => {
it('basic', async () => {
let sitemap = await $fetch('/sitemap/en-US.xml')
let sitemap = await $fetch('/__sitemap__/en-US.xml')

// strip lastmod
sitemap = sitemap.replace(/<lastmod>.*<\/lastmod>/g, '')
Expand Down
2 changes: 1 addition & 1 deletion test/integration/i18n/filtering.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ await setup({
})
describe('i18n filtering', () => {
it('basic', async () => {
let sitemap = await $fetch('/sitemap/en-US.xml')
let sitemap = await $fetch('/__sitemap__/en-US.xml')

// strip lastmod
sitemap = sitemap.replace(/<lastmod>.*<\/lastmod>/g, '')
Expand Down
8 changes: 4 additions & 4 deletions test/integration/i18n/generate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ describe('generate', () => {
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://nuxtseo.com/sitemap/en-US.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/en-US.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/es-ES.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/es-ES.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/fr-FR.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/fr-FR.xml</loc>
</sitemap>
</sitemapindex>"
`)
const sitemapEn = (await readFile(resolve(rootDir, '.output/public/sitemap/en-US.xml'), 'utf-8')).replace(/lastmod>(.*?)</g, 'lastmod><')
const sitemapEn = (await readFile(resolve(rootDir, '.output/public/__sitemap__/en-US.xml'), 'utf-8')).replace(/lastmod>(.*?)</g, 'lastmod><')
expect(sitemapEn).toMatchInlineSnapshot(`
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
<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">
Expand Down
8 changes: 4 additions & 4 deletions test/integration/i18n/pages-multi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,17 @@ describe('i18n pages multi', () => {
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://nuxtseo.com/sitemap/en-US.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/en-US.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/es-ES.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/es-ES.xml</loc>
</sitemap>
<sitemap>
<loc>https://nuxtseo.com/sitemap/fr-FR.xml</loc>
<loc>https://nuxtseo.com/__sitemap__/fr-FR.xml</loc>
</sitemap>
</sitemapindex>"
`)
const fr = await $fetch('/sitemap/fr-FR.xml')
const fr = await $fetch('/__sitemap__/fr-FR.xml')
expect(fr).toMatchInlineSnapshot(`
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
<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">
Expand Down
2 changes: 1 addition & 1 deletion test/integration/multi/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ await setup({
})
describe('mutli defaults', () => {
it('basic', async () => {
let sitemap = await $fetch('/sitemap/foo.xml')
let sitemap = await $fetch('/__sitemap__/foo.xml')
// remove lastmods before tresting
sitemap = sitemap.replace(/lastmod>(.*?)</g, 'lastmod><')
// basic test to make sure we get a valid response
Expand Down
2 changes: 1 addition & 1 deletion test/integration/multi/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ await setup({
})
describe('multi endpoints', () => {
it('basic', async () => {
let sitemap = await $fetch('/sitemap/foo.xml')
let sitemap = await $fetch('/__sitemap__/foo.xml')
// remove lastmods before tresting
sitemap = sitemap.replace(/lastmod>(.*?)</g, 'lastmod><')
// basic test to make sure we get a valid response
Expand Down
2 changes: 1 addition & 1 deletion test/integration/multi/filtering.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ await setup({
})
describe('multi filtering', () => {
it('basic', async () => {
let sitemap = await $fetch('/sitemap/foo.xml')
let sitemap = await $fetch('/__sitemap__/foo.xml')

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

0 comments on commit 4b94c3d

Please sign in to comment.