@nuxtjs/sitemap 7.0.2 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/client/200.html +8 -8
  2. package/dist/client/404.html +8 -8
  3. package/dist/client/_nuxt/{BLDCaNbg.js → B2vK47Ag.js} +1 -1
  4. package/dist/client/_nuxt/{B5lI3vl2.js → DIH-cllJ.js} +1 -1
  5. package/dist/client/_nuxt/{BCt9_I41.js → Djzw0wLt.js} +1 -1
  6. package/dist/client/_nuxt/builds/latest.json +1 -1
  7. package/dist/client/_nuxt/builds/meta/cbd506e7-b089-42a0-8062-dff717a0d923.json +1 -0
  8. package/dist/client/_nuxt/error-404.DWO74KKP.css +1 -0
  9. package/dist/client/_nuxt/error-500.DVC0lzO_.css +1 -0
  10. package/dist/client/_nuxt/sSZQ7D2b.js +32 -0
  11. package/dist/client/index.html +8 -8
  12. package/dist/module.d.mts +4 -1
  13. package/dist/module.d.ts +4 -1
  14. package/dist/module.json +1 -1
  15. package/dist/module.mjs +220 -72
  16. package/dist/runtime/server/plugins/{nuxt-content.js → nuxt-content-v2.js} +2 -10
  17. package/dist/runtime/server/routes/__sitemap__/debug.d.ts +1 -1
  18. package/dist/runtime/server/routes/__sitemap__/nuxt-content-urls-v3.d.ts +2 -0
  19. package/dist/runtime/server/routes/__sitemap__/nuxt-content-urls-v3.js +17 -0
  20. package/dist/runtime/server/routes/sitemap/[sitemap].xml.js +1 -1
  21. package/dist/runtime/server/routes/sitemap_index.xml.js +2 -2
  22. package/dist/runtime/server/sitemap/builder/sitemap-index.d.ts +2 -1
  23. package/dist/runtime/server/sitemap/builder/sitemap-index.js +8 -3
  24. package/dist/runtime/server/sitemap/builder/sitemap.d.ts +4 -3
  25. package/dist/runtime/server/sitemap/builder/sitemap.js +12 -7
  26. package/dist/runtime/server/sitemap/nitro.js +6 -2
  27. package/dist/runtime/server/sitemap/urlset/sources.js +16 -7
  28. package/dist/runtime/server/sitemap/utils/extractSitemapXML.d.ts +2 -0
  29. package/dist/runtime/server/sitemap/utils/extractSitemapXML.js +75 -0
  30. package/dist/runtime/types.d.ts +5 -1
  31. package/dist/types.d.mts +1 -1
  32. package/dist/types.d.ts +1 -1
  33. package/package.json +14 -13
  34. package/dist/client/_nuxt/BZ4NIl-o.js +0 -32
  35. package/dist/client/_nuxt/builds/meta/286d11d8-5fae-4d47-bddf-64b0ae9fc73d.json +0 -1
  36. package/dist/client/_nuxt/error-404.vQ0SaaqA.css +0 -1
  37. package/dist/client/_nuxt/error-500.ayRVCnRF.css +0 -1
  38. /package/dist/runtime/server/plugins/{nuxt-content.d.ts → nuxt-content-v2.d.ts} +0 -0
  39. /package/dist/runtime/server/routes/__sitemap__/{nuxt-content-urls.d.ts → nuxt-content-urls-v2.d.ts} +0 -0
  40. /package/dist/runtime/server/routes/__sitemap__/{nuxt-content-urls.js → nuxt-content-urls-v2.js} +0 -0
@@ -1,7 +1,7 @@
1
1
  <!DOCTYPE html><html data-capo=""><head><meta charset="utf-8">
2
2
  <meta name="viewport" content="width=device-width, initial-scale=1">
3
3
  <link rel="stylesheet" href="/__sitemap__/devtools/_nuxt/entry.WCUheyaE.css" crossorigin>
4
- <link rel="modulepreload" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/BZ4NIl-o.js">
4
+ <link rel="modulepreload" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/sSZQ7D2b.js">
5
5
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/DsBKuouk.js">
6
6
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/D_z4Izcz.js">
7
7
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/727ZlQH0.js">
@@ -195,7 +195,7 @@
195
195
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/C1XDQQGZ.js">
196
196
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/CQjiPCtT.js">
197
197
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/DQ1-QYvQ.js">
198
- <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/BLDCaNbg.js">
198
+ <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/B2vK47Ag.js">
199
199
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/BbSNqyBO.js">
200
200
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/CB2ApiWb.js">
201
201
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/wI6OXr6j.js">
@@ -275,9 +275,9 @@
275
275
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/D0r3Knsf.js">
276
276
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/CVO1_9PV.js">
277
277
  <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/CG6Dc4jp.js">
278
- <link rel="prefetch" as="style" crossorigin href="/__sitemap__/devtools/_nuxt/error-404.vQ0SaaqA.css">
279
- <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/BCt9_I41.js">
280
- <link rel="prefetch" as="style" crossorigin href="/__sitemap__/devtools/_nuxt/error-500.ayRVCnRF.css">
281
- <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/B5lI3vl2.js">
282
- <script type="module" src="/__sitemap__/devtools/_nuxt/BZ4NIl-o.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1736821946446,false]</script>
283
- <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__sitemap__/devtools",buildId:"286d11d8-5fae-4d47-bddf-64b0ae9fc73d",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
278
+ <link rel="prefetch" as="style" crossorigin href="/__sitemap__/devtools/_nuxt/error-404.DWO74KKP.css">
279
+ <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/Djzw0wLt.js">
280
+ <link rel="prefetch" as="style" crossorigin href="/__sitemap__/devtools/_nuxt/error-500.DVC0lzO_.css">
281
+ <link rel="prefetch" as="script" crossorigin href="/__sitemap__/devtools/_nuxt/DIH-cllJ.js">
282
+ <script type="module" src="/__sitemap__/devtools/_nuxt/sSZQ7D2b.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1737249777375,false]</script>
283
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__sitemap__/devtools",buildId:"cbd506e7-b089-42a0-8062-dff717a0d923",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
package/dist/module.d.mts CHANGED
@@ -1,8 +1,11 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
2
  import { ModuleOptions as ModuleOptions$1 } from '../dist/runtime/types.js';
3
3
 
4
+ declare function asSitemapCollection(collection: any): any;
5
+
4
6
  interface ModuleOptions extends ModuleOptions$1 {
5
7
  }
8
+
6
9
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
7
10
 
8
- export { type ModuleOptions, _default as default };
11
+ export { type ModuleOptions, asSitemapCollection, _default as default };
package/dist/module.d.ts CHANGED
@@ -1,8 +1,11 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
2
  import { ModuleOptions as ModuleOptions$1 } from '../dist/runtime/types.js';
3
3
 
4
+ declare function asSitemapCollection(collection: any): any;
5
+
4
6
  interface ModuleOptions extends ModuleOptions$1 {
5
7
  }
8
+
6
9
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
7
10
 
8
- export { type ModuleOptions, _default as default };
11
+ export { type ModuleOptions, asSitemapCollection, _default as default };
package/dist/module.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "bridge": false
6
6
  },
7
7
  "configKey": "sitemap",
8
- "version": "7.0.1",
8
+ "version": "7.1.0",
9
9
  "builder": {
10
10
  "@nuxt/module-builder": "0.8.4",
11
11
  "unbuild": "2.0.0"
package/dist/module.mjs CHANGED
@@ -1,10 +1,10 @@
1
- import { useNuxt, loadNuxtModuleInstance, createResolver, addTemplate, extendPages, tryUseNuxt, defineNuxtModule, useLogger, hasNuxtModule, getNuxtModuleVersion, hasNuxtModuleCompatibility, addServerImports, addServerPlugin, addServerHandler, addPrerenderRoutes } from '@nuxt/kit';
2
- import { withHttps, withBase, parseURL, joinURL, withoutLeadingSlash, withoutTrailingSlash, withLeadingSlash } from 'ufo';
1
+ import { useNuxt, loadNuxtModuleInstance, createResolver, addTemplate, extendPages, tryUseNuxt, defineNuxtModule, useLogger, hasNuxtModule, getNuxtModuleVersion, hasNuxtModuleCompatibility, addServerImports, addServerPlugin, resolveModule, addServerHandler, addPrerenderRoutes } from '@nuxt/kit';
2
+ import { withHttps, withBase, parseURL, joinURL, withoutLeadingSlash, withLeadingSlash, withoutTrailingSlash } from 'ufo';
3
3
  import { withSiteUrl, installNuxtSiteConfig } from 'nuxt-site-config/kit';
4
4
  import { defu } from 'defu';
5
5
  import { readPackageJSON } from 'pkg-types';
6
- import { statSync, existsSync } from 'node:fs';
7
6
  import { extname, relative, dirname } from 'pathe';
7
+ import { statSync, existsSync } from 'node:fs';
8
8
  import { createPathFilter, splitForLocales, mergeOnKey } from '../dist/runtime/utils-pure.js';
9
9
  import { provider, env } from 'std-env';
10
10
  import { mkdir, writeFile } from 'node:fs/promises';
@@ -12,6 +12,7 @@ import { join } from 'node:path';
12
12
  import chalk from 'chalk';
13
13
  import { build } from 'nitropack';
14
14
  import { normaliseDate } from '../dist/runtime/server/sitemap/urlset/normalise.js';
15
+ import { z } from '@nuxt/content';
15
16
 
16
17
  async function resolveUrls(urls, ctx) {
17
18
  if (typeof urls === "function")
@@ -264,6 +265,22 @@ function resolveNitroPreset(nitroConfig) {
264
265
  return preset.replace("_", "-");
265
266
  }
266
267
 
268
+ const videoRegex = /<video[^>]*>([\s\S]*?)<\/video>/g;
269
+ const videoSrcRegex = /<video[^>]*\ssrc="([^"]+)"/;
270
+ const videoPosterRegex = /<video[^>]*\sposter="([^"]+)"/;
271
+ const videoTitleRegex = /<video[^>]*\sdata-title="([^"]+)"/;
272
+ const videoDescriptionRegex = /<video[^>]*\sdata-description="([^"]+)"/;
273
+ const videoPlayerLocRegex = /<video[^>]*\sdata-player-loc="([^"]+)"/;
274
+ const videoDurationRegex = /<video[^>]*\sdata-duration="([^"]+)"/;
275
+ const videoExpirationDateRegex = /<video[^>]*\sdata-expiration-date="([^"]+)"/;
276
+ const videoRatingRegex = /<video[^>]*\sdata-rating="([^"]+)"/;
277
+ const videoViewCountRegex = /<video[^>]*\sdata-view-count="([^"]+)"/;
278
+ const videoPublicationDateRegex = /<video[^>]*\sdata-publication-date="([^"]+)"/;
279
+ const videoFamilyFriendlyRegex = /<video[^>]*\sdata-family-friendly="([^"]+)"/;
280
+ const videoRequiresSubscriptionRegex = /<video[^>]*\sdata-requires-subscription="([^"]+)"/;
281
+ const videoLiveRegex = /<video[^>]*\sdata-live="([^"]+)"/;
282
+ const videoTagRegex = /<video[^>]*\sdata-tag="([^"]+)"/;
283
+ const sourceRegex = /<source[^>]*\ssrc="([^"]+)"/g;
267
284
  function extractSitemapMetaFromHtml(html, options) {
268
285
  options = options || { images: true, videos: true, lastmod: true, alternatives: true };
269
286
  const payload = {};
@@ -291,54 +308,74 @@ function extractSitemapMetaFromHtml(html, options) {
291
308
  const mainRegex = /<main[^>]*>([\s\S]*?)<\/main>/;
292
309
  const mainMatch = mainRegex.exec(html);
293
310
  if (mainMatch?.[1] && mainMatch[1].includes("<video")) {
294
- const videoRegex = /<video[^>]*>([\s\S]*?)<\/video>/g;
295
- const videoAttrRegex = /<video[^>]*\ssrc="([^"]+)"(?:[^>]*\sposter="([^"]+)")?/;
296
- const videoPosterRegex = /<video[^>]*\sposter="([^"]+)"/;
297
- const videoTitleRegex = /<video[^>]*\sdata-title="([^"]+)"/;
298
- const videoDescriptionRegex = /<video[^>]*\sdata-description="([^"]+)"/;
299
- const sourceRegex = /<source[^>]*\ssrc="([^"]+)"/g;
300
311
  let videoMatch;
301
312
  while ((videoMatch = videoRegex.exec(mainMatch[1])) !== null) {
302
313
  const videoContent = videoMatch[1];
303
314
  const videoTag = videoMatch[0];
304
- const videoAttrMatch = videoAttrRegex.exec(videoTag);
305
- const videoSrc = videoAttrMatch ? videoAttrMatch[1] : "";
306
- const poster = (videoPosterRegex.exec(videoTag) || [])[1] || "";
315
+ const content_loc = (videoSrcRegex.exec(videoTag) || [])[1] || "";
316
+ const thumbnail_loc = (videoPosterRegex.exec(videoTag) || [])[1] || "";
307
317
  const title = (videoTitleRegex.exec(videoTag) || [])[1] || "";
308
318
  const description = (videoDescriptionRegex.exec(videoTag) || [])[1] || "";
319
+ const videoObj = {
320
+ content_loc,
321
+ thumbnail_loc,
322
+ title,
323
+ description
324
+ };
325
+ const player_loc = (videoPlayerLocRegex.exec(videoTag) || [])[1];
326
+ if (player_loc)
327
+ videoObj.player_loc = player_loc;
328
+ const duration = (videoDurationRegex.exec(videoTag) || [])[1];
329
+ if (duration)
330
+ videoObj.duration = Number.parseInt(duration, 10);
331
+ const expiration_date = (videoExpirationDateRegex.exec(videoTag) || [])[1];
332
+ if (expiration_date)
333
+ videoObj.expiration_date = expiration_date;
334
+ const rating = (videoRatingRegex.exec(videoTag) || [])[1];
335
+ if (rating)
336
+ videoObj.rating = Number.parseFloat(rating);
337
+ const view_count = (videoViewCountRegex.exec(videoTag) || [])[1];
338
+ if (view_count)
339
+ videoObj.view_count = Number.parseInt(view_count, 10);
340
+ const publication_date = (videoPublicationDateRegex.exec(videoTag) || [])[1];
341
+ if (publication_date)
342
+ videoObj.publication_date = publication_date;
343
+ const family_friendly = (videoFamilyFriendlyRegex.exec(videoTag) || [])[1];
344
+ if (family_friendly)
345
+ videoObj.family_friendly = family_friendly;
346
+ const requires_subscription = (videoRequiresSubscriptionRegex.exec(videoTag) || [])[1];
347
+ if (requires_subscription)
348
+ videoObj.requires_subscription = requires_subscription;
349
+ const live = (videoLiveRegex.exec(videoTag) || [])[1];
350
+ if (live)
351
+ videoObj.live = live;
352
+ const tag = (videoTagRegex.exec(videoTag) || [])[1];
353
+ if (tag)
354
+ videoObj.tag = tag;
309
355
  const sources = [];
310
356
  let sourceMatch;
311
357
  while ((sourceMatch = sourceRegex.exec(videoContent)) !== null) {
312
- sources.push({
313
- src: sourceMatch[1],
314
- poster,
315
- title,
316
- description
317
- });
318
- }
319
- if (videoSrc) {
320
- videos.push({
321
- src: videoSrc,
322
- poster,
323
- title,
324
- description,
325
- sources: []
326
- });
358
+ sources.push(sourceMatch[1]);
327
359
  }
328
360
  if (sources.length > 0) {
329
- videos.push(...sources);
361
+ videos.push(...sources.map((source) => {
362
+ if (source.startsWith("/"))
363
+ source = tryUseNuxt() ? withSiteUrl(source) : source;
364
+ return {
365
+ ...videoObj,
366
+ content_loc: source
367
+ };
368
+ }));
369
+ } else {
370
+ videos.push(videoObj);
330
371
  }
331
372
  }
332
373
  }
333
- if (videos.length > 0) {
334
- payload.videos = videos.map(
335
- (video) => ({
336
- content_loc: video.src,
337
- thumbnail_loc: video.poster,
338
- title: video.title,
339
- description: video.description
340
- })
341
- );
374
+ const validVideos = videos.filter((v) => {
375
+ return v.content_loc && v.thumbnail_loc && v.title && v.description;
376
+ });
377
+ if (validVideos.length > 0) {
378
+ payload.videos = validVideos;
342
379
  }
343
380
  }
344
381
  if (options?.lastmod) {
@@ -572,6 +609,55 @@ function normalizeFilters(filters) {
572
609
  }).filter(Boolean);
573
610
  }
574
611
 
612
+ const sitemap = z.object({
613
+ loc: z.string().optional(),
614
+ lastmod: z.date().optional(),
615
+ 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(),
616
+ priority: z.number().optional(),
617
+ images: z.array(z.object({
618
+ loc: z.string(),
619
+ caption: z.string().optional(),
620
+ geo_location: z.string().optional(),
621
+ title: z.string().optional(),
622
+ license: z.string().optional()
623
+ })).optional(),
624
+ videos: z.array(z.object({
625
+ content_loc: z.string(),
626
+ player_loc: z.string().optional(),
627
+ duration: z.string().optional(),
628
+ expiration_date: z.date().optional(),
629
+ rating: z.number().optional(),
630
+ view_count: z.number().optional(),
631
+ publication_date: z.date().optional(),
632
+ family_friendly: z.boolean().optional(),
633
+ tag: z.string().optional(),
634
+ category: z.string().optional(),
635
+ restriction: z.object({
636
+ relationship: z.literal("allow").optional(),
637
+ value: z.string().optional()
638
+ }).optional(),
639
+ gallery_loc: z.string().optional(),
640
+ price: z.string().optional(),
641
+ requires_subscription: z.boolean().optional(),
642
+ uploader: z.string().optional()
643
+ })).optional()
644
+ }).optional();
645
+ function asSitemapCollection(collection) {
646
+ if (collection.type !== "page") {
647
+ return;
648
+ }
649
+ if (!collection.schema) {
650
+ collection.schema = z.object({
651
+ sitemap
652
+ });
653
+ } else {
654
+ collection.schema = collection.schema.extend({
655
+ sitemap
656
+ });
657
+ }
658
+ return collection;
659
+ }
660
+
575
661
  const module = defineNuxtModule({
576
662
  meta: {
577
663
  name: "@nuxtjs/sitemap",
@@ -788,6 +874,7 @@ declare module 'nitropack' {
788
874
  }
789
875
  interface NitroRuntimeHooks {
790
876
  'sitemap:index-resolved': (ctx: import('${typesPath}').SitemapIndexRenderCtx) => void | Promise<void>
877
+ 'sitemap:input': (ctx: import('${typesPath}').SitemapInputCtx) => void | Promise<void>
791
878
  'sitemap:resolved': (ctx: import('${typesPath}').SitemapRenderCtx) => void | Promise<void>
792
879
  'sitemap:output': (ctx: import('${typesPath}').SitemapOutputHookCtx) => void | Promise<void>
793
880
  }
@@ -832,7 +919,7 @@ declare module 'vue-router' {
832
919
  nuxt.options.nitro.routeRules["/sitemap_index.xml"] = routeRules;
833
920
  if (typeof config.sitemaps === "object") {
834
921
  for (const k in config.sitemaps) {
835
- nuxt.options.nitro.routeRules[joinURL(config.sitemapsPathPrefix, `/${k}.xml`)] = routeRules;
922
+ nuxt.options.nitro.routeRules[joinURL(config.sitemapsPathPrefix || "", `/${k}.xml`)] = routeRules;
836
923
  }
837
924
  } else {
838
925
  nuxt.options.nitro.routeRules[`/${config.sitemapName}`] = routeRules;
@@ -845,31 +932,81 @@ declare module 'vue-router' {
845
932
  if (config.experimentalCompression)
846
933
  addServerPlugin(resolve("./runtime/server/plugins/compression"));
847
934
  const isNuxtContentDocumentDriven = !!nuxt.options.content?.documentDriven || config.strictNuxtContentPaths;
848
- if (hasNuxtModule("@nuxt/content")) {
849
- if (await hasNuxtModuleCompatibility("@nuxt/content", "^3")) {
850
- logger.warn("Nuxt Sitemap does not work with Nuxt Content v3 yet, the integration will be disabled.");
851
- } else {
852
- addServerPlugin(resolve("./runtime/server/plugins/nuxt-content"));
853
- addServerHandler({
854
- route: "/__sitemap__/nuxt-content-urls.json",
855
- handler: resolve("./runtime/server/routes/__sitemap__/nuxt-content-urls")
856
- });
857
- const tips = [];
858
- if (nuxt.options.content?.documentDriven)
859
- tips.push("Enabled because you're using `@nuxt/content` with `documentDriven: true`.");
860
- else if (config.strictNuxtContentPaths)
861
- tips.push("Enabled because you've set `config.strictNuxtContentPaths: true`.");
862
- else
863
- tips.push("You can provide a `sitemap` key in your markdown frontmatter to configure specific URLs. Make sure you include a `loc`.");
864
- appGlobalSources.push({
865
- context: {
866
- name: "@nuxt/content:urls",
867
- description: "Generated from your markdown files.",
868
- tips
869
- },
870
- fetch: "/__sitemap__/nuxt-content-urls.json"
871
- });
935
+ const usingNuxtContent = hasNuxtModule("@nuxt/content");
936
+ const isNuxtContentV3 = usingNuxtContent && await hasNuxtModuleCompatibility("@nuxt/content", "^3");
937
+ const nuxtV3Collections = /* @__PURE__ */ new Set();
938
+ const isNuxtContentV2 = usingNuxtContent && await hasNuxtModuleCompatibility("@nuxt/content", "^2");
939
+ if (isNuxtContentV3) {
940
+ nuxt.options.alias["#sitemap/content-v3-nitro-path"] = resolve(dirname(resolveModule("@nuxt/content")), "runtime/nitro");
941
+ nuxt.hooks.hook("content:file:afterParse", (ctx) => {
942
+ const content = ctx.content;
943
+ nuxtV3Collections.add(ctx.collection.name);
944
+ if (!("sitemap" in ctx.collection.fields)) {
945
+ return;
946
+ }
947
+ const images = [];
948
+ if (config.discoverImages) {
949
+ images.push(
950
+ ...content.body.value?.filter(
951
+ (c) => ["image", "img", "nuxtimg", "nuxt-img"].includes(c[0])
952
+ ).filter((c) => c[1]?.src).map((c) => ({ loc: c[1].src })) || []
953
+ );
954
+ }
955
+ const sitemapConfig = typeof content.sitemap === "object" ? content.sitemap : {};
956
+ const lastmod = content.seo?.articleModifiedTime || content.updatedAt;
957
+ const defaults = {
958
+ loc: content.path
959
+ };
960
+ if (images.length > 0)
961
+ defaults.images = images;
962
+ if (lastmod)
963
+ defaults.lastmod = lastmod;
964
+ const definition = defu(sitemapConfig, defaults);
965
+ if (!definition.loc) {
966
+ if (content.path && content.path && content.path.startsWith("/"))
967
+ definition.loc = content.path;
968
+ }
969
+ content.sitemap = definition;
970
+ if (!definition.loc)
971
+ delete content.sitemap;
972
+ ctx.content = content;
973
+ });
974
+ addServerHandler({
975
+ route: "/__sitemap__/nuxt-content-urls.json",
976
+ handler: resolve("./runtime/server/routes/__sitemap__/nuxt-content-urls-v3")
977
+ });
978
+ if (config.strictNuxtContentPaths) {
979
+ logger.warn("You have set `strictNuxtContentPaths: true` but are using @nuxt/content v3. This is not required, please remove it.");
872
980
  }
981
+ appGlobalSources.push({
982
+ context: {
983
+ name: "@nuxt/content@v3:urls",
984
+ description: "Generated from your markdown files.",
985
+ tips: [`Parsing the following collections: ${Array.from(nuxtV3Collections).join(", ")}`]
986
+ },
987
+ fetch: "/__sitemap__/nuxt-content-urls.json"
988
+ });
989
+ } else if (isNuxtContentV2) {
990
+ addServerPlugin(resolve("./runtime/server/plugins/nuxt-content-v2"));
991
+ addServerHandler({
992
+ route: "/__sitemap__/nuxt-content-urls.json",
993
+ handler: resolve("./runtime/server/routes/__sitemap__/nuxt-content-urls-v2")
994
+ });
995
+ const tips = [];
996
+ if (nuxt.options.content?.documentDriven)
997
+ tips.push("Enabled because you're using `@nuxt/content` with `documentDriven: true`.");
998
+ else if (config.strictNuxtContentPaths)
999
+ tips.push("Enabled because you've set `config.strictNuxtContentPaths: true`.");
1000
+ else
1001
+ tips.push("You can provide a `sitemap` key in your markdown frontmatter to configure specific URLs. Make sure you include a `loc`.");
1002
+ appGlobalSources.push({
1003
+ context: {
1004
+ name: "@nuxt/content@v2:urls",
1005
+ description: "Generated from your markdown files.",
1006
+ tips
1007
+ },
1008
+ fetch: "/__sitemap__/nuxt-content-urls.json"
1009
+ });
873
1010
  }
874
1011
  const sitemaps = {};
875
1012
  if (usingMultiSitemaps) {
@@ -879,12 +1016,23 @@ declare module 'vue-router' {
879
1016
  lazy: true,
880
1017
  middleware: false
881
1018
  });
882
- addServerHandler({
883
- route: joinURL(config.sitemapsPathPrefix, `/**:sitemap`),
884
- handler: resolve("./runtime/server/routes/sitemap/[sitemap].xml"),
885
- lazy: true,
886
- middleware: false
887
- });
1019
+ if (config.sitemapsPathPrefix && config.sitemapsPathPrefix !== "/") {
1020
+ addServerHandler({
1021
+ route: joinURL(config.sitemapsPathPrefix, `/**:sitemap`),
1022
+ handler: resolve("./runtime/server/routes/sitemap/[sitemap].xml"),
1023
+ lazy: true,
1024
+ middleware: false
1025
+ });
1026
+ } else {
1027
+ for (const sitemapName of Object.keys(config.sitemaps || {})) {
1028
+ addServerHandler({
1029
+ route: withLeadingSlash(`${sitemapName}.xml`),
1030
+ handler: resolve("./runtime/server/routes/sitemap/[sitemap].xml"),
1031
+ lazy: true,
1032
+ middleware: false
1033
+ });
1034
+ }
1035
+ }
888
1036
  sitemaps.index = {
889
1037
  sitemapName: "index",
890
1038
  _route: withBase("sitemap_index.xml", nuxt.options.app.baseURL || "/"),
@@ -899,7 +1047,7 @@ declare module 'vue-router' {
899
1047
  sitemaps[sitemapName] = defu(
900
1048
  {
901
1049
  sitemapName,
902
- _route: withBase(joinURL(config.sitemapsPathPrefix, `${sitemapName}.xml`), nuxt.options.app.baseURL || "/"),
1050
+ _route: withBase(joinURL(config.sitemapsPathPrefix || "", `${sitemapName}.xml`), nuxt.options.app.baseURL || "/"),
903
1051
  _hasSourceChunk: typeof definition.urls !== "undefined" || definition.sources?.length
904
1052
  },
905
1053
  { ...definition, urls: void 0, sources: void 0 },
@@ -1030,9 +1178,9 @@ declare module 'vue-router' {
1030
1178
  ...((await nitroPromise)._prerenderedRoutes || []).filter((r) => {
1031
1179
  const lastSegment = r.route.split("/").pop();
1032
1180
  const isExplicitFile = !!lastSegment?.match(/\.[0-9a-z]+$/i)?.[0];
1033
- if (r.error || ["/200.html", "/404.html", "/index.html"].includes(r.route))
1181
+ if (isExplicitFile || r.error || ["/200.html", "/404.html", "/index.html"].includes(r.route))
1034
1182
  return false;
1035
- return r.contentType?.includes("text/html") || !isExplicitFile;
1183
+ return r.contentType?.includes("text/html");
1036
1184
  }).map((r) => r._sitemap)
1037
1185
  ];
1038
1186
  const pageSource = convertNuxtPagesToSitemapEntries(await pagesPromise, {
@@ -1163,4 +1311,4 @@ declare module 'vue-router' {
1163
1311
  }
1164
1312
  });
1165
1313
 
1166
- export { module as default };
1314
+ export { asSitemapCollection, module as default };
@@ -2,7 +2,7 @@ import { defu } from "defu";
2
2
  import { useSimpleSitemapRuntimeConfig } from "../utils.js";
3
3
  import { defineNitroPlugin } from "#imports";
4
4
  export default defineNitroPlugin((nitroApp) => {
5
- const { discoverImages, discoverVideos, isNuxtContentDocumentDriven } = useSimpleSitemapRuntimeConfig();
5
+ const { discoverImages, isNuxtContentDocumentDriven } = useSimpleSitemapRuntimeConfig();
6
6
  nitroApp.hooks.hook("content:file:afterParse", async (content) => {
7
7
  const validExtensions = ["md", "mdx"];
8
8
  if (content.sitemap === false || content._draft || !validExtensions.includes(content._extension) || content._partial || content.robots === false)
@@ -13,12 +13,6 @@ export default defineNitroPlugin((nitroApp) => {
13
13
  (c) => c.tag && c.props?.src && ["image", "img", "nuxtimg", "nuxt-img"].includes(c.tag.toLowerCase())
14
14
  ).map((i) => ({ loc: i.props.src })) || [];
15
15
  }
16
- let videos = [];
17
- if (discoverVideos) {
18
- videos = content.body?.children?.filter(
19
- (c) => c.tag && c.props?.src && ["video"].includes(c.tag.toLowerCase())
20
- ).map((i) => ({ content_loc: i.props.src })) || [];
21
- }
22
16
  const sitemapConfig = typeof content.sitemap === "object" ? content.sitemap : {};
23
17
  const lastmod = content.modifiedAt || content.updatedAt;
24
18
  const defaults = {};
@@ -26,10 +20,8 @@ export default defineNitroPlugin((nitroApp) => {
26
20
  defaults.loc = content._path;
27
21
  if (content.path)
28
22
  defaults.loc = content.path;
29
- if (images.length > 0)
23
+ if (images?.length)
30
24
  defaults.images = images;
31
- if (videos.length > 0)
32
- defaults.videos = videos;
33
25
  if (lastmod)
34
26
  defaults.lastmod = lastmod;
35
27
  const definition = defu(sitemapConfig, defaults);
@@ -15,7 +15,7 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
15
15
  autoI18n?: import("../../../types").AutoI18nConfig;
16
16
  isMultiSitemap: boolean;
17
17
  isI18nMapped: boolean;
18
- sitemapsPathPrefix: string;
18
+ sitemapsPathPrefix: string | false;
19
19
  cacheMaxAgeSeconds: number | false;
20
20
  sitemapName: string;
21
21
  excludeAppSources: true | (import("../../../types").AppSourceContext[]);
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
2
+ export default _default;
@@ -0,0 +1,17 @@
1
+ import { defineEventHandler } from "h3";
2
+ import { queryCollectionWithEvent } from "#sitemap/content-v3-nitro-path";
3
+ import manifest from "#content/manifest";
4
+ export default defineEventHandler(async (e) => {
5
+ const collections = [];
6
+ for (const collection in manifest) {
7
+ if (manifest[collection].fields.sitemap) {
8
+ collections.push(collection);
9
+ }
10
+ }
11
+ const contentList = [];
12
+ for (const collection of collections) {
13
+ contentList.push(queryCollectionWithEvent(e, collection).select("sitemap").where("sitemap", "IS NOT NULL").all());
14
+ }
15
+ const results = await Promise.all(contentList);
16
+ return results.flat().map((c) => c.sitemap).filter(Boolean);
17
+ });
@@ -5,7 +5,7 @@ import { createSitemap } from "../../sitemap/nitro.js";
5
5
  export default defineEventHandler(async (e) => {
6
6
  const runtimeConfig = useSimpleSitemapRuntimeConfig(e);
7
7
  const { sitemaps } = runtimeConfig;
8
- const sitemapName = withoutLeadingSlash(withoutTrailingSlash((getRouterParam(e, "sitemap") || e.path)?.replace(".xml", "").replace(runtimeConfig.sitemapsPathPrefix, "")));
8
+ const sitemapName = withoutLeadingSlash(withoutTrailingSlash((getRouterParam(e, "sitemap") || e.path)?.replace(".xml", "").replace(runtimeConfig.sitemapsPathPrefix || "", "")));
9
9
  const isChunking = typeof sitemaps.chunks !== "undefined" && !Number.isNaN(Number(sitemapName));
10
10
  if (!sitemapName || !(sitemapName in sitemaps) && !isChunking) {
11
11
  return createError({
@@ -8,12 +8,12 @@ export default defineEventHandler(async (e) => {
8
8
  const runtimeConfig = useSimpleSitemapRuntimeConfig();
9
9
  const nitro = useNitroApp();
10
10
  const resolvers = useNitroUrlResolvers(e);
11
- const sitemaps = await buildSitemapIndex(resolvers, runtimeConfig);
11
+ const sitemaps = await buildSitemapIndex(resolvers, runtimeConfig, nitro);
12
12
  if (import.meta.prerender) {
13
13
  appendHeader(
14
14
  e,
15
15
  "x-nitro-prerender",
16
- sitemaps.filter((entry) => !!entry._sitemapName).map((entry) => encodeURIComponent(joinURL(runtimeConfig.sitemapsPathPrefix, `/${entry._sitemapName}.xml`))).join(", ")
16
+ sitemaps.filter((entry) => !!entry._sitemapName).map((entry) => encodeURIComponent(joinURL(runtimeConfig.sitemapsPathPrefix || "", `/${entry._sitemapName}.xml`))).join(", ")
17
17
  );
18
18
  }
19
19
  const indexResolvedCtx = { sitemaps };
@@ -1,3 +1,4 @@
1
+ import type { NitroApp } from 'nitropack/types';
1
2
  import type { ModuleRuntimeConfig, NitroUrlResolvers, SitemapIndexEntry } from '../../../types.js';
2
- export declare function buildSitemapIndex(resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig): Promise<SitemapIndexEntry[]>;
3
+ export declare function buildSitemapIndex(resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig, nitro?: NitroApp): Promise<SitemapIndexEntry[]>;
3
4
  export declare function urlsToIndexXml(sitemaps: SitemapIndexEntry[], resolvers: NitroUrlResolvers, { version, xsl, credits, minify }: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>): string;
@@ -5,7 +5,7 @@ import { globalSitemapSources, resolveSitemapSources } from "../urlset/sources.j
5
5
  import { sortSitemapUrls } from "../urlset/sort.js";
6
6
  import { escapeValueForXml, wrapSitemapXml } from "./xml.js";
7
7
  import { resolveSitemapEntries } from "./sitemap.js";
8
- export async function buildSitemapIndex(resolvers, runtimeConfig) {
8
+ export async function buildSitemapIndex(resolvers, runtimeConfig, nitro) {
9
9
  const {
10
10
  sitemaps,
11
11
  // enhancing
@@ -27,7 +27,12 @@ export async function buildSitemapIndex(resolvers, runtimeConfig) {
27
27
  if (isChunking) {
28
28
  const sitemap = sitemaps.chunks;
29
29
  const sources = await resolveSitemapSources(await globalSitemapSources());
30
- const normalisedUrls = resolveSitemapEntries(sitemap, sources, { autoI18n, isI18nMapped }, resolvers);
30
+ const resolvedCtx = {
31
+ urls: sources.flatMap((s) => s.urls),
32
+ sitemapName: sitemap.sitemapName
33
+ };
34
+ await nitro?.hooks.callHook("sitemap:input", resolvedCtx);
35
+ const normalisedUrls = resolveSitemapEntries(sitemap, resolvedCtx.urls, { autoI18n, isI18nMapped }, resolvers);
31
36
  const enhancedUrls = normalisedUrls.map((e) => defu(e, sitemap.defaults));
32
37
  const sortedUrls = maybeSort(enhancedUrls);
33
38
  sortedUrls.forEach((url, i) => {
@@ -47,7 +52,7 @@ export async function buildSitemapIndex(resolvers, runtimeConfig) {
47
52
  const sitemap = chunks[name];
48
53
  const entry = {
49
54
  _sitemapName: name,
50
- sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix, `/${name}.xml`))
55
+ sitemap: resolvers.canonicalUrlResolver(joinURL(sitemapsPathPrefix || "", `/${name}.xml`))
51
56
  };
52
57
  let lastmod = sitemap.urls.filter((a) => !!a?.lastmod).map((a) => typeof a.lastmod === "string" ? new Date(a.lastmod) : a.lastmod).sort((a, b) => (b?.getTime() || 0) - (a?.getTime() || 0))?.[0];
53
58
  if (!lastmod && autoLastmod)
@@ -1,9 +1,10 @@
1
- import type { AutoI18nConfig, ModuleRuntimeConfig, NitroUrlResolvers, ResolvedSitemapUrl, SitemapDefinition, SitemapSourceResolved } from '../../../types.js';
1
+ import type { NitroApp } from 'nitropack/types';
2
+ import type { AutoI18nConfig, ModuleRuntimeConfig, NitroUrlResolvers, ResolvedSitemapUrl, SitemapDefinition, SitemapUrlInput } from '../../../types.js';
2
3
  export interface NormalizedI18n extends ResolvedSitemapUrl {
3
4
  _pathWithoutPrefix: string;
4
5
  _locale: AutoI18nConfig['locales'][number];
5
6
  _index?: number;
6
7
  }
7
- export declare function resolveSitemapEntries(sitemap: SitemapDefinition, sources: SitemapSourceResolved[], runtimeConfig: Pick<ModuleRuntimeConfig, 'autoI18n' | 'isI18nMapped'>, resolvers?: NitroUrlResolvers): ResolvedSitemapUrl[];
8
- export declare function buildSitemapUrls(sitemap: SitemapDefinition, resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig): Promise<ResolvedSitemapUrl[]>;
8
+ export declare function resolveSitemapEntries(sitemap: SitemapDefinition, urls: SitemapUrlInput[], runtimeConfig: Pick<ModuleRuntimeConfig, 'autoI18n' | 'isI18nMapped'>, resolvers?: NitroUrlResolvers): ResolvedSitemapUrl[];
9
+ export declare function buildSitemapUrls(sitemap: SitemapDefinition, resolvers: NitroUrlResolvers, runtimeConfig: ModuleRuntimeConfig, nitro?: NitroApp): Promise<ResolvedSitemapUrl[]>;
9
10
  export declare function urlsToXml(urls: ResolvedSitemapUrl[], resolvers: NitroUrlResolvers, { version, xsl, credits, minify }: Pick<ModuleRuntimeConfig, 'version' | 'xsl' | 'credits' | 'minify'>): string;