Skip to content

Commit 579f70e

Browse files
authoredJan 17, 2025··
feat: Nuxt Content v3 (#398)
1 parent c37be55 commit 579f70e

32 files changed

+1789
-112
lines changed
 

‎docs/content/2.guides/5.content.md

+58-28
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,37 @@ title: Nuxt Content
33
description: How to use the Nuxt Sitemap module with Nuxt Content.
44
---
55

6-
Nuxt Sitemap integrates with Nuxt Content out of the box.
6+
## Introduction
77

8-
It comes with automatic configuration when using document driven mode.
9-
Otherwise, you can opt in on each markdown file or set up your own [app source](/docs/sitemap/getting-started/data-sources).
8+
Nuxt Sitemap comes with an integration for Nuxt Content that allows you to configure your sitemap entry straight from your markdown directly.
109

11-
## Setup
10+
## Setup Nuxt Content v3
1211

13-
### Document Driven Mode
12+
In Nuxt Content v3 we need to use the `asSitemapCollection()`{lang="ts"} function to augment any collections
13+
to be able to use the `sitemap` frontmatter key.
1414

15-
When using `documentDriven` mode, all paths will be automatically added to the sitemap.
15+
```ts [content.config.ts]
16+
import { defineCollection, defineContentConfig, z } from '@nuxt/content'
17+
import { asSitemapCollection } from '@nuxtjs/sitemap'
18+
19+
export default defineContentConfig({
20+
collections: {
21+
content: defineCollection(
22+
// adds the robots frontmatter key to the collection
23+
asSitemapCollection({
24+
type: 'page',
25+
source: '**/*.md',
26+
}),
27+
),
28+
},
29+
})
30+
```
31+
32+
33+
## Setup Nuxt Content v2
34+
35+
In Nuxt Content v2 markdown files require either [Document Driven Mode](https://content.nuxt.com/document-driven/introduction), a `path` key to be set
36+
in the frontmatter or the `strictNuxtContentPaths` option to be enabled.
1637

1738
```ts [nuxt.config.ts]
1839
export default defineNuxtConfig({
@@ -34,26 +55,9 @@ export default defineNuxtConfig({
3455
})
3556
```
3657

37-
### Markdown opt in
38-
39-
If you want to add markdown pages to your sitemap without any extra config, you can use the `sitemap` key on
40-
your frontmatter. You must provide a `loc` value, or the page must have a `path`.
41-
42-
```md
43-
---
44-
sitemap:
45-
loc: /my-page
46-
lastmod: 2021-01-01
47-
changefreq: monthly
48-
priority: 0.8
49-
---
50-
51-
# My Page
52-
```
53-
54-
### Nuxt Content App Source
58+
### Advanced: Nuxt Content App Source
5559

56-
If you'd like to set up a more automated Nuxt Content integration and your not using Document Driven mode, you can add content to the sitemap as you would with [Dynamic URLs](/docs/sitemap/guides/dynamic-urls).
60+
If you'd like to set up a more automated Nuxt Content integration and you're not using Document Driven mode, you can add content to the sitemap as you would with [Dynamic URLs](/docs/sitemap/guides/dynamic-urls).
5761

5862
An example of what this might look like is below, customize to your own needs.
5963

@@ -86,8 +90,34 @@ export default defineNuxtConfig({
8690
})
8791
```
8892

89-
## Guides
93+
## Usage
9094

91-
### Opt out from Sitemap
95+
### Frontmatter `sitemap`
9296

93-
You can also disable the content from being used by passing in `sitemap: false` or `robots: false`.
97+
Use the `sitemap` key in your frontmatter to add a page to your sitemap.
98+
99+
You can provide any data that you would normally provide in the sitemap configuration.
100+
101+
```md
102+
---
103+
sitemap:
104+
loc: /my-page
105+
lastmod: 2021-01-01
106+
changefreq: monthly
107+
priority: 0.8
108+
---
109+
110+
# My Page
111+
```
112+
113+
### Exclude from Sitemap
114+
115+
If you'd like to exclude a page from the sitemap, you can set `sitemap: false` in the frontmatter or `robots: false`
116+
if you'd like to exclude it from search engines.
117+
118+
```md
119+
---
120+
sitemap: false
121+
robots: false
122+
---
123+
```

‎package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@
6464
"ufo": "^1.5.4"
6565
},
6666
"devDependencies": {
67-
"@nuxt/content": "^2.13.4",
67+
"@nuxt/content": "3.0.0-alpha.9",
68+
"@nuxt/content-v2": "npm:@nuxt/content@2.13.4",
6869
"@nuxt/eslint-config": "^0.7.5",
6970
"@nuxt/module-builder": "0.8.4",
7071
"@nuxt/test-utils": "^3.15.4",
@@ -89,7 +90,8 @@
8990
"h3",
9091
"std-env",
9192
"nitropack",
92-
"consola"
93+
"consola",
94+
"@nuxt/content"
9395
]
9496
}
9597
}

‎pnpm-lock.yaml

+1,336-49
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pnpm-workspace.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
packages:
22
- client
3+
- test/fixtures/**
4+
- playground

‎src/content.ts

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { z } from '@nuxt/content'
2+
3+
const sitemap = z.object({
4+
loc: z.string().optional(),
5+
lastmod: z.date().optional(),
6+
changefreq: z.union([z.literal('always'), z.literal('hourly'), z.literal('daily'), z.literal('weekly'), z.literal('monthly'), z.literal('yearly'), z.literal('never')]).optional(),
7+
priority: z.number().optional(),
8+
images: z.array(z.object({
9+
loc: z.string(),
10+
caption: z.string().optional(),
11+
geo_location: z.string().optional(),
12+
title: z.string().optional(),
13+
license: z.string().optional(),
14+
})).optional(),
15+
videos: z.array(z.object({
16+
content_loc: z.string(),
17+
player_loc: z.string().optional(),
18+
duration: z.string().optional(),
19+
expiration_date: z.date().optional(),
20+
rating: z.number().optional(),
21+
view_count: z.number().optional(),
22+
publication_date: z.date().optional(),
23+
family_friendly: z.boolean().optional(),
24+
tag: z.string().optional(),
25+
category: z.string().optional(),
26+
restriction: z.object({
27+
relationship: z.literal('allow').optional(),
28+
value: z.string().optional(),
29+
}).optional(),
30+
gallery_loc: z.string().optional(),
31+
price: z.string().optional(),
32+
requires_subscription: z.boolean().optional(),
33+
uploader: z.string().optional(),
34+
})).optional(),
35+
}).optional()
36+
37+
export function asSitemapCollection(collection: any) {
38+
if (collection.type !== 'page') {
39+
return
40+
}
41+
if (!collection.schema) {
42+
collection.schema = z.object({
43+
sitemap,
44+
})
45+
}
46+
else {
47+
collection.schema = collection.schema.extend({
48+
sitemap,
49+
})
50+
}
51+
collection._integrations = collection._integrations || []
52+
collection._integrations.push('sitemap')
53+
return collection
54+
}

‎src/module.ts

+113-30
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@ import {
77
defineNuxtModule,
88
getNuxtModuleVersion,
99
hasNuxtModule,
10-
hasNuxtModuleCompatibility,
10+
hasNuxtModuleCompatibility, resolveModule,
1111
useLogger,
1212
} from '@nuxt/kit'
1313
import { joinURL, withBase, withLeadingSlash, withoutLeadingSlash, withoutTrailingSlash } from 'ufo'
1414
import { installNuxtSiteConfig } from 'nuxt-site-config/kit'
1515
import { defu } from 'defu'
1616
import type { NitroRouteConfig } from 'nitropack'
1717
import { readPackageJSON } from 'pkg-types'
18+
import { dirname } from 'pathe'
19+
import type { FileAfterParseHook } from '@nuxt/content'
20+
import type { UseSeoMetaInput } from '@unhead/schema'
1821
import type {
1922
AppSourceContext,
2023
AutoI18nConfig,
@@ -24,7 +27,7 @@ import type {
2427
SitemapSourceBase,
2528
SitemapSourceInput,
2629
SitemapSourceResolved,
27-
ModuleOptions as _ModuleOptions, FilterInput, I18nIntegrationOptions,
30+
ModuleOptions as _ModuleOptions, FilterInput, I18nIntegrationOptions, SitemapUrl,
2831
} from './runtime/types'
2932
import { convertNuxtPagesToSitemapEntries, generateExtraRoutesFromNuxtConfig, resolveUrls } from './util/nuxtSitemap'
3033
import { createNitroPromise, createPagesPromise, extendTypes, getNuxtModuleOptions, resolveNitroPreset } from './util/kit'
@@ -41,6 +44,8 @@ import { normalizeFilters } from './util/filter'
4144
// eslint-disable-next-line
4245
export interface ModuleOptions extends _ModuleOptions {}
4346

47+
export * from './content'
48+
4449
export default defineNuxtModule<ModuleOptions>({
4550
meta: {
4651
name: '@nuxtjs/sitemap',
@@ -352,34 +357,112 @@ declare module 'vue-router' {
352357

353358
// @ts-expect-error untyped
354359
const isNuxtContentDocumentDriven = (!!nuxt.options.content?.documentDriven || config.strictNuxtContentPaths)
355-
if (hasNuxtModule('@nuxt/content')) {
356-
if (await hasNuxtModuleCompatibility('@nuxt/content', '^3')) {
357-
logger.warn('Nuxt Sitemap does not work with Nuxt Content v3 yet, the integration will be disabled.')
358-
}
359-
else {
360-
addServerPlugin(resolve('./runtime/server/plugins/nuxt-content'))
361-
addServerHandler({
362-
route: '/__sitemap__/nuxt-content-urls.json',
363-
handler: resolve('./runtime/server/routes/__sitemap__/nuxt-content-urls'),
364-
})
365-
const tips: string[] = []
366-
// @ts-expect-error untyped
367-
if (nuxt.options.content?.documentDriven)
368-
tips.push('Enabled because you\'re using `@nuxt/content` with `documentDriven: true`.')
369-
else if (config.strictNuxtContentPaths)
370-
tips.push('Enabled because you\'ve set `config.strictNuxtContentPaths: true`.')
371-
else
372-
tips.push('You can provide a `sitemap` key in your markdown frontmatter to configure specific URLs. Make sure you include a `loc`.')
360+
const usingNuxtContent = hasNuxtModule('@nuxt/content')
361+
const isNuxtContentV3 = usingNuxtContent && await hasNuxtModuleCompatibility('@nuxt/content', '^3')
362+
const nuxtV3Collections = new Set<string>()
363+
const isNuxtContentV2 = usingNuxtContent && await hasNuxtModuleCompatibility('@nuxt/content', '^2')
364+
if (isNuxtContentV3) {
365+
// TODO this is a hack until content gives us an alias
366+
nuxt.options.alias['#sitemap/content-v3-nitro-path'] = resolve(dirname(resolveModule('@nuxt/content')), 'runtime/nitro')
367+
// @ts-expect-error runtime type
368+
nuxt.hooks.hook('content:file:afterParse', (ctx: FileAfterParseHook) => {
369+
const content = ctx.content as {
370+
body: { value: [string, Record<string, any>][] }
371+
sitemap?: Partial<SitemapUrl>
372+
path: string
373+
seo: UseSeoMetaInput
374+
updatedAt?: string
375+
}
376+
nuxtV3Collections.add(ctx.collection.name)
377+
if (!('sitemap' in ctx.collection.fields)) {
378+
return
379+
}
380+
// add any top level images
381+
const images: SitemapUrl['images'] = []
382+
if (config.discoverImages) {
383+
images.push(...(content.body.value
384+
?.filter(c =>
385+
['image', 'img', 'nuxtimg', 'nuxt-img'].includes(c[0]),
386+
)
387+
.map(c => ({ loc: c[1].src })) || []),
388+
)
389+
}
373390

374-
appGlobalSources.push({
375-
context: {
376-
name: '@nuxt/content:urls',
377-
description: 'Generated from your markdown files.',
378-
tips,
379-
},
380-
fetch: '/__sitemap__/nuxt-content-urls.json',
381-
})
391+
// add any top level videos
392+
const videos: SitemapUrl['videos'] = []
393+
if (config.discoverVideos) {
394+
// TODO
395+
// videos.push(...(content.body.value
396+
// .filter(c => c[0] === 'video' && c[1]?.src)
397+
// .map(c => ({
398+
// content_loc: c[1].src
399+
// })) || []),
400+
// )
401+
}
402+
403+
const sitemapConfig = typeof content.sitemap === 'object' ? content.sitemap : {}
404+
const lastmod = content.seo?.articleModifiedTime || content.updatedAt
405+
const defaults: Partial<SitemapUrl> = {
406+
loc: content.path,
407+
}
408+
if (images.length > 0)
409+
defaults.images = images
410+
if (videos.length > 0)
411+
defaults.videos = videos
412+
if (lastmod)
413+
defaults.lastmod = lastmod
414+
const definition = defu(sitemapConfig, defaults) as Partial<SitemapUrl>
415+
if (!definition.loc) {
416+
// user hasn't provided a loc... lets fallback to a relative path
417+
if (content.path && content.path && content.path.startsWith('/'))
418+
definition.loc = content.path
419+
}
420+
content.sitemap = definition
421+
// loc is required
422+
if (!definition.loc)
423+
delete content.sitemap
424+
ctx.content = content
425+
})
426+
427+
addServerHandler({
428+
route: '/__sitemap__/nuxt-content-urls.json',
429+
handler: resolve('./runtime/server/routes/__sitemap__/nuxt-content-urls-v3'),
430+
})
431+
if (config.strictNuxtContentPaths) {
432+
logger.warn('You have set `strictNuxtContentPaths: true` but are using @nuxt/content v3. This is not required, please remove it.')
382433
}
434+
appGlobalSources.push({
435+
context: {
436+
name: '@nuxt/content@v3:urls',
437+
description: 'Generated from your markdown files.',
438+
tips: [`Parsing the following collections: ${Array.from(nuxtV3Collections).join(', ')}`],
439+
},
440+
fetch: '/__sitemap__/nuxt-content-urls.json',
441+
})
442+
}
443+
else if (isNuxtContentV2) {
444+
addServerPlugin(resolve('./runtime/server/plugins/nuxt-content-v2'))
445+
addServerHandler({
446+
route: '/__sitemap__/nuxt-content-urls.json',
447+
handler: resolve('./runtime/server/routes/__sitemap__/nuxt-content-urls-v2'),
448+
})
449+
const tips: string[] = []
450+
// @ts-expect-error untyped
451+
if (nuxt.options.content?.documentDriven)
452+
tips.push('Enabled because you\'re using `@nuxt/content` with `documentDriven: true`.')
453+
else if (config.strictNuxtContentPaths)
454+
tips.push('Enabled because you\'ve set `config.strictNuxtContentPaths: true`.')
455+
else
456+
tips.push('You can provide a `sitemap` key in your markdown frontmatter to configure specific URLs. Make sure you include a `loc`.')
457+
458+
appGlobalSources.push({
459+
context: {
460+
name: '@nuxt/content@v2:urls',
461+
description: 'Generated from your markdown files.',
462+
tips,
463+
},
464+
fetch: '/__sitemap__/nuxt-content-urls.json',
465+
})
383466
}
384467

385468
// config -> sitemaps
@@ -567,9 +650,9 @@ declare module 'vue-router' {
567650
// check for file in lastSegment using regex
568651
const isExplicitFile = !!(lastSegment?.match(/\.[0-9a-z]+$/i)?.[0])
569652
// avoid adding fallback pages to sitemap
570-
if (r.error || ['/200.html', '/404.html', '/index.html'].includes(r.route))
653+
if (isExplicitFile || r.error || ['/200.html', '/404.html', '/index.html'].includes(r.route))
571654
return false
572-
return (r.contentType?.includes('text/html') || !isExplicitFile)
655+
return r.contentType?.includes('text/html')
573656
})
574657
.map(r => r._sitemap),
575658
]

‎src/runtime/server/plugins/nuxt-content.ts ‎src/runtime/server/plugins/nuxt-content-v2.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { defu } from 'defu'
22
import type { ParsedContent } from '@nuxt/content'
3-
import type { NitroApp } from 'nitropack'
3+
import type { NitroApp } from 'nitropack/types'
44
import type { SitemapUrl } from '../../types'
55
import { useSimpleSitemapRuntimeConfig } from '../utils'
66
import { defineNitroPlugin } from '#imports'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { defineEventHandler } from 'h3'
2+
// @ts-expect-error alias
3+
import { queryCollectionWithEvent } from '#sitemap/content-v3-nitro-path'
4+
// @ts-expect-error alias
5+
import manifest from '#content/manifest'
6+
7+
export default defineEventHandler(async (e) => {
8+
const collections = []
9+
// each collection in the manifest has a key => with fields which has a `sitemap`, we want to get all those
10+
for (const collection in manifest) {
11+
if (manifest[collection].fields.sitemap) {
12+
collections.push(collection)
13+
}
14+
}
15+
// now we need to handle multiple queries here, we want to run the requests in parralel
16+
const contentList = []
17+
for (const collection of collections) {
18+
contentList.push(queryCollectionWithEvent(e, collection).select('sitemap').where('sitemap', 'IS NOT NULL').all())
19+
}
20+
// we need to wait for all the queries to finish
21+
const results = await Promise.all(contentList)
22+
// we need to flatten the results
23+
return results.flat().map(c => c.sitemap).filter(Boolean)
24+
})
File renamed without changes.
File renamed without changes.
File renamed without changes.

‎test/fixtures/content/nuxt.config.ts ‎test/fixtures/content-v2/nuxt.config.ts

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export default defineNuxtConfig({
99
site: {
1010
url: 'https://nuxtseo.com',
1111
},
12+
alias: {
13+
'@nuxt/content': '@nuxt/content-v2',
14+
},
1215
debug: process.env.NODE_ENV === 'test',
1316
sitemap: {
1417
autoLastmod: false,

‎test/fixtures/content-v3/.nuxtrc

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
imports.autoImport=true
2+
typescript.includeWorkspace=true

‎test/fixtures/content-v3/app.vue

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<template>
2+
<NuxtPage />
3+
</template>
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { defineCollection, defineContentConfig, z } from '@nuxt/content'
2+
import { asSitemapCollection } from '../../../src/content'
3+
4+
export default defineContentConfig({
5+
collections: {
6+
content: defineCollection(
7+
asSitemapCollection({
8+
type: 'page',
9+
source: '**/*.md',
10+
schema: z.object({
11+
date: z.string().optional(),
12+
}),
13+
}),
14+
),
15+
},
16+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# bar
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
sitemap:
3+
lastmod: 2021-10-20
4+
priority: 0.5
5+
changefreq: daily
6+
---
7+
8+
# bar
9+
10+
<img src="https://raw.githubusercontent.com/harlan-zw/static/main/sponsors.svg" alt="Sponsors" />
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
sitemap:
3+
priority: 0.5
4+
---
5+
6+
# foo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
sitemap:
3+
lastmod: 2021-10-20
4+
---
5+
# bar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
sitemap:
3+
lastmod: 2021-10-20
4+
---
5+
6+
# foo
7+
8+
no sitemap config
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# foo
2+
3+
no sitemap config
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import NuxtRobots from '../../../src/module'
2+
3+
export default defineNuxtConfig({
4+
modules: [
5+
NuxtRobots,
6+
'@nuxt/content',
7+
],
8+
9+
site: {
10+
url: 'https://nuxtseo.com',
11+
},
12+
compatibilityDate: '2024-12-06',
13+
14+
debug: process.env.NODE_ENV === 'test',
15+
16+
sitemap: {
17+
autoLastmod: false,
18+
credits: false,
19+
debug: true,
20+
},
21+
})

‎test/fixtures/content-v3/package.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"private": "true",
3+
"scripts": {
4+
"dev": "nuxi dev"
5+
},
6+
"dependencies": {
7+
"nuxt": "^3.5.3"
8+
},
9+
"devDependencies": {
10+
"@nuxt/content": "3.0.0-alpha.9"
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script setup lang="ts">
2+
import { queryCollection, useRoute } from '#imports'
3+
4+
const route = useRoute()
5+
const { data: page } = await useAsyncData(`page-${route.path}`, () => {
6+
return queryCollection('content').path(route.path).first()
7+
})
8+
useSeoMeta(page.value?.seo || {})
9+
</script>
10+
11+
<template>
12+
<div>
13+
<ContentRenderer
14+
v-if="page"
15+
:value="page"
16+
/>
17+
<div v-else>
18+
Page not found
19+
</div>
20+
</div>
21+
</template>

‎test/integration/content/default.test.ts ‎test/integration/content-v2/default.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { $fetch, setup } from '@nuxt/test-utils'
55
const { resolve } = createResolver(import.meta.url)
66

77
await setup({
8-
rootDir: resolve('../../fixtures/content'),
8+
rootDir: resolve('../../fixtures/content-v2'),
99
})
1010
describe('nuxt/content default', () => {
1111
it('basic', async () => {

‎test/integration/content/documentDriven.test.ts ‎test/integration/content-v2/documentDriven.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { $fetch, setup } from '@nuxt/test-utils'
55
const { resolve } = createResolver(import.meta.url)
66

77
await setup({
8-
rootDir: resolve('../../fixtures/content'),
8+
rootDir: resolve('../../fixtures/content-v2'),
99
content: {
1010
documentDriven: true,
1111
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { createResolver } from '@nuxt/kit'
3+
import { $fetch, setup } from '@nuxt/test-utils'
4+
5+
const { resolve } = createResolver(import.meta.url)
6+
7+
await setup({
8+
rootDir: resolve('../../fixtures/content-v3'),
9+
})
10+
describe('nuxt/content v3 default', () => {
11+
it('basic', async () => {
12+
const nuxtContentUrls = await $fetch('/__sitemap__/nuxt-content-urls.json')
13+
expect(nuxtContentUrls).toMatchInlineSnapshot(`
14+
[
15+
{
16+
"loc": "/_partial",
17+
},
18+
{
19+
"changefreq": "daily",
20+
"images": [
21+
{
22+
"loc": "https://raw.githubusercontent.com/harlan-zw/static/main/sponsors.svg",
23+
},
24+
],
25+
"lastmod": "2021-10-20",
26+
"loc": "/bar",
27+
"priority": 0.5,
28+
},
29+
{
30+
"loc": "/foo",
31+
"priority": 0.5,
32+
},
33+
{
34+
"lastmod": "2021-10-20",
35+
"loc": "/posts/bar",
36+
},
37+
{
38+
"lastmod": "2021-10-20",
39+
"loc": "/posts/fallback",
40+
},
41+
{
42+
"loc": "/posts/foo",
43+
},
44+
]
45+
`)
46+
47+
const sitemap = await $fetch('/sitemap.xml')
48+
expect(sitemap).toMatchInlineSnapshot(`
49+
"<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/__sitemap__/style.xsl"?>
50+
<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">
51+
<url>
52+
<loc>https://nuxtseo.com/</loc>
53+
</url>
54+
<url>
55+
<loc>https://nuxtseo.com/_partial</loc>
56+
</url>
57+
<url>
58+
<loc>https://nuxtseo.com/bar</loc>
59+
<image:image>
60+
<image:loc>https://raw.githubusercontent.com/harlan-zw/static/main/sponsors.svg</image:loc>
61+
</image:image>
62+
<lastmod>2021-10-20</lastmod>
63+
<priority>0.5</priority>
64+
<changefreq>daily</changefreq>
65+
</url>
66+
<url>
67+
<loc>https://nuxtseo.com/foo</loc>
68+
<priority>0.5</priority>
69+
</url>
70+
<url>
71+
<loc>https://nuxtseo.com/posts/bar</loc>
72+
<lastmod>2021-10-20</lastmod>
73+
</url>
74+
<url>
75+
<loc>https://nuxtseo.com/posts/fallback</loc>
76+
<lastmod>2021-10-20</lastmod>
77+
</url>
78+
<url>
79+
<loc>https://nuxtseo.com/posts/foo</loc>
80+
</url>
81+
</urlset>"
82+
`)
83+
}, 60000)
84+
})

0 commit comments

Comments
 (0)
Please sign in to comment.