@nuxtjs/sitemap 7.4.9 → 7.4.11

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 (33) hide show
  1. package/dist/client/200.html +1 -1
  2. package/dist/client/404.html +1 -1
  3. package/dist/client/_nuxt/{SKYDSeR3.js → CjT5ejtq.js} +1 -1
  4. package/dist/client/_nuxt/{QpeyiL4d.js → DBmpb9dG.js} +1 -1
  5. package/dist/client/_nuxt/{Cu_iTDKX.js → FE81ed4p.js} +14 -16
  6. package/dist/client/_nuxt/builds/latest.json +1 -1
  7. package/dist/client/_nuxt/builds/meta/ef370d03-581a-4487-a7bd-237af16aab04.json +1 -0
  8. package/dist/client/_nuxt/error-404.DC9fsYfS.css +1 -0
  9. package/dist/client/_nuxt/error-500.DPVweS-0.css +1 -0
  10. package/dist/client/index.html +1 -1
  11. package/dist/client/sitemap.xml +1 -1
  12. package/dist/module.json +1 -1
  13. package/dist/module.mjs +25 -19
  14. package/dist/runtime/server/plugins/nuxt-content-v2.js +6 -7
  15. package/dist/runtime/server/routes/__sitemap__/debug.js +3 -2
  16. package/dist/runtime/server/routes/__sitemap__/nuxt-content-urls-v2.d.ts +1 -1
  17. package/dist/runtime/server/routes/__sitemap__/nuxt-content-urls-v3.d.ts +3 -1
  18. package/dist/runtime/server/routes/__sitemap__/nuxt-content-urls-v3.js +7 -6
  19. package/dist/runtime/server/routes/sitemap/[sitemap].xml.js +1 -1
  20. package/dist/runtime/server/sitemap/builder/sitemap-index.js +1 -2
  21. package/dist/runtime/server/sitemap/builder/sitemap.js +64 -75
  22. package/dist/runtime/server/sitemap/builder/xml.js +81 -169
  23. package/dist/runtime/server/sitemap/nitro.js +4 -3
  24. package/dist/runtime/server/sitemap/urlset/normalise.js +29 -26
  25. package/dist/runtime/server/sitemap/urlset/sources.d.ts +2 -2
  26. package/dist/runtime/server/sitemap/urlset/sources.js +8 -6
  27. package/dist/runtime/types.d.ts +7 -1
  28. package/dist/runtime/utils-pure.js +29 -19
  29. package/dist/utils.mjs +1 -2
  30. package/package.json +14 -14
  31. package/dist/client/_nuxt/builds/meta/bafd23ec-aaa0-4756-a4c4-11462568906c.json +0 -1
  32. package/dist/client/_nuxt/error-404.CqOOUcXJ.css +0 -1
  33. package/dist/client/_nuxt/error-500.jRvomCfk.css +0 -1
@@ -5,193 +5,105 @@ export function escapeValueForXml(value) {
5
5
  return value ? "yes" : "no";
6
6
  return xmlEscape(String(value));
7
7
  }
8
+ const yesNo = (v) => v === "yes" || v === true ? "yes" : "no";
8
9
  const URLSET_OPENING_TAG = '<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">';
9
- function buildUrlXml(url) {
10
- const capacity = 50;
11
- const parts = Array.from({ length: capacity });
12
- let partIndex = 0;
13
- parts[partIndex++] = " <url>";
14
- if (url.loc) {
15
- parts[partIndex++] = ` <loc>${escapeValueForXml(url.loc)}</loc>`;
16
- }
17
- if (url.lastmod) {
18
- parts[partIndex++] = ` <lastmod>${url.lastmod}</lastmod>`;
10
+ function buildUrlXml(url, NL, I1, I2, I3, I4) {
11
+ let xml = `${I1}<url>${NL}`;
12
+ if (url.loc) xml += `${I2}<loc>${xmlEscape(url.loc)}</loc>${NL}`;
13
+ if (url.lastmod) xml += `${I2}<lastmod>${url.lastmod}</lastmod>${NL}`;
14
+ if (url.changefreq) xml += `${I2}<changefreq>${url.changefreq}</changefreq>${NL}`;
15
+ if (url.priority !== void 0) {
16
+ const p = typeof url.priority === "number" ? url.priority : Number.parseFloat(url.priority);
17
+ xml += `${I2}<priority>${p % 1 === 0 ? p : p.toFixed(1)}</priority>${NL}`;
19
18
  }
20
- if (url.changefreq) {
21
- parts[partIndex++] = ` <changefreq>${url.changefreq}</changefreq>`;
19
+ if (url.alternatives) {
20
+ for (const alt of url.alternatives) {
21
+ let attrs = "";
22
+ for (const [k, v] of Object.entries(alt)) attrs += ` ${k}="${xmlEscape(String(v))}"`;
23
+ xml += `${I2}<xhtml:link rel="alternate"${attrs} />${NL}`;
24
+ }
22
25
  }
23
- if (url.priority !== void 0) {
24
- const priorityValue = Number.parseFloat(String(url.priority));
25
- const formattedPriority = priorityValue % 1 === 0 ? String(priorityValue) : priorityValue.toFixed(1);
26
- parts[partIndex++] = ` <priority>${formattedPriority}</priority>`;
26
+ if (url.images) {
27
+ for (const img of url.images) {
28
+ xml += `${I2}<image:image>${NL}${I3}<image:loc>${xmlEscape(img.loc)}</image:loc>${NL}`;
29
+ if (img.title) xml += `${I3}<image:title>${xmlEscape(img.title)}</image:title>${NL}`;
30
+ if (img.caption) xml += `${I3}<image:caption>${xmlEscape(img.caption)}</image:caption>${NL}`;
31
+ if (img.geo_location) xml += `${I3}<image:geo_location>${xmlEscape(img.geo_location)}</image:geo_location>${NL}`;
32
+ if (img.license) xml += `${I3}<image:license>${xmlEscape(img.license)}</image:license>${NL}`;
33
+ xml += `${I2}</image:image>${NL}`;
34
+ }
27
35
  }
28
- const keys = Object.keys(url).filter((k) => !k.startsWith("_") && !["loc", "lastmod", "changefreq", "priority"].includes(k));
29
- for (const key of keys) {
30
- const value = url[key];
31
- if (value === void 0 || value === null) continue;
32
- switch (key) {
33
- case "alternatives":
34
- if (Array.isArray(value) && value.length > 0) {
35
- for (const alt of value) {
36
- const attrs = Object.entries(alt).map(([k, v]) => `${k}="${escapeValueForXml(v)}"`).join(" ");
37
- parts[partIndex++] = ` <xhtml:link rel="alternate" ${attrs} />`;
38
- }
39
- }
40
- break;
41
- case "images":
42
- if (Array.isArray(value) && value.length > 0) {
43
- for (const img of value) {
44
- parts[partIndex++] = " <image:image>";
45
- parts[partIndex++] = ` <image:loc>${escapeValueForXml(img.loc)}</image:loc>`;
46
- if (img.title) parts[partIndex++] = ` <image:title>${escapeValueForXml(img.title)}</image:title>`;
47
- if (img.caption) parts[partIndex++] = ` <image:caption>${escapeValueForXml(img.caption)}</image:caption>`;
48
- if (img.geo_location) parts[partIndex++] = ` <image:geo_location>${escapeValueForXml(img.geo_location)}</image:geo_location>`;
49
- if (img.license) parts[partIndex++] = ` <image:license>${escapeValueForXml(img.license)}</image:license>`;
50
- parts[partIndex++] = " </image:image>";
51
- }
36
+ if (url.videos) {
37
+ for (const video of url.videos) {
38
+ xml += `${I2}<video:video>${NL}${I3}<video:title>${xmlEscape(video.title)}</video:title>${NL}`;
39
+ if (video.thumbnail_loc) xml += `${I3}<video:thumbnail_loc>${xmlEscape(video.thumbnail_loc)}</video:thumbnail_loc>${NL}`;
40
+ xml += `${I3}<video:description>${xmlEscape(video.description)}</video:description>${NL}`;
41
+ if (video.content_loc) xml += `${I3}<video:content_loc>${xmlEscape(video.content_loc)}</video:content_loc>${NL}`;
42
+ if (video.player_loc) xml += `${I3}<video:player_loc>${xmlEscape(video.player_loc)}</video:player_loc>${NL}`;
43
+ if (video.duration !== void 0) xml += `${I3}<video:duration>${video.duration}</video:duration>${NL}`;
44
+ if (video.expiration_date) xml += `${I3}<video:expiration_date>${video.expiration_date}</video:expiration_date>${NL}`;
45
+ if (video.rating !== void 0) xml += `${I3}<video:rating>${video.rating}</video:rating>${NL}`;
46
+ if (video.view_count !== void 0) xml += `${I3}<video:view_count>${video.view_count}</video:view_count>${NL}`;
47
+ if (video.publication_date) xml += `${I3}<video:publication_date>${video.publication_date}</video:publication_date>${NL}`;
48
+ if (video.family_friendly !== void 0) xml += `${I3}<video:family_friendly>${yesNo(video.family_friendly)}</video:family_friendly>${NL}`;
49
+ if (video.restriction) xml += `${I3}<video:restriction relationship="${video.restriction.relationship || "allow"}">${xmlEscape(video.restriction.restriction)}</video:restriction>${NL}`;
50
+ if (video.platform) xml += `${I3}<video:platform relationship="${video.platform.relationship || "allow"}">${xmlEscape(video.platform.platform)}</video:platform>${NL}`;
51
+ if (video.requires_subscription !== void 0) xml += `${I3}<video:requires_subscription>${yesNo(video.requires_subscription)}</video:requires_subscription>${NL}`;
52
+ if (video.price) {
53
+ for (const price of video.price) {
54
+ const c = price.currency ? ` currency="${price.currency}"` : "";
55
+ const t = price.type ? ` type="${price.type}"` : "";
56
+ xml += `${I3}<video:price${c}${t}>${xmlEscape(String(price.price ?? ""))}</video:price>${NL}`;
52
57
  }
53
- break;
54
- case "videos":
55
- if (Array.isArray(value) && value.length > 0) {
56
- for (const video of value) {
57
- parts[partIndex++] = " <video:video>";
58
- parts[partIndex++] = ` <video:title>${escapeValueForXml(video.title)}</video:title>`;
59
- if (video.thumbnail_loc) {
60
- parts[partIndex++] = ` <video:thumbnail_loc>${escapeValueForXml(video.thumbnail_loc)}</video:thumbnail_loc>`;
61
- }
62
- parts[partIndex++] = ` <video:description>${escapeValueForXml(video.description)}</video:description>`;
63
- if (video.content_loc) {
64
- parts[partIndex++] = ` <video:content_loc>${escapeValueForXml(video.content_loc)}</video:content_loc>`;
65
- }
66
- if (video.player_loc) {
67
- const attrs = video.player_loc.allow_embed ? ' allow_embed="yes"' : "";
68
- const autoplay = video.player_loc.autoplay ? ' autoplay="yes"' : "";
69
- parts[partIndex++] = ` <video:player_loc${attrs}${autoplay}>${escapeValueForXml(video.player_loc)}</video:player_loc>`;
70
- }
71
- if (video.duration !== void 0) {
72
- parts[partIndex++] = ` <video:duration>${video.duration}</video:duration>`;
73
- }
74
- if (video.expiration_date) {
75
- parts[partIndex++] = ` <video:expiration_date>${video.expiration_date}</video:expiration_date>`;
76
- }
77
- if (video.rating !== void 0) {
78
- parts[partIndex++] = ` <video:rating>${video.rating}</video:rating>`;
79
- }
80
- if (video.view_count !== void 0) {
81
- parts[partIndex++] = ` <video:view_count>${video.view_count}</video:view_count>`;
82
- }
83
- if (video.publication_date) {
84
- parts[partIndex++] = ` <video:publication_date>${video.publication_date}</video:publication_date>`;
85
- }
86
- if (video.family_friendly !== void 0) {
87
- parts[partIndex++] = ` <video:family_friendly>${video.family_friendly === "yes" || video.family_friendly === true ? "yes" : "no"}</video:family_friendly>`;
88
- }
89
- if (video.restriction) {
90
- const relationship = video.restriction.relationship || "allow";
91
- parts[partIndex++] = ` <video:restriction relationship="${relationship}">${escapeValueForXml(video.restriction.restriction)}</video:restriction>`;
92
- }
93
- if (video.platform) {
94
- const relationship = video.platform.relationship || "allow";
95
- parts[partIndex++] = ` <video:platform relationship="${relationship}">${escapeValueForXml(video.platform.platform)}</video:platform>`;
96
- }
97
- if (video.requires_subscription !== void 0) {
98
- parts[partIndex++] = ` <video:requires_subscription>${video.requires_subscription === "yes" || video.requires_subscription === true ? "yes" : "no"}</video:requires_subscription>`;
99
- }
100
- if (video.price) {
101
- const prices = Array.isArray(video.price) ? video.price : [video.price];
102
- for (const price of prices) {
103
- const attrs = [];
104
- if (price.currency) attrs.push(`currency="${price.currency}"`);
105
- if (price.type) attrs.push(`type="${price.type}"`);
106
- const attrsStr = attrs.length > 0 ? " " + attrs.join(" ") : "";
107
- parts[partIndex++] = ` <video:price${attrsStr}>${escapeValueForXml(price.price)}</video:price>`;
108
- }
109
- }
110
- if (video.uploader) {
111
- const info = video.uploader.info ? ` info="${escapeValueForXml(video.uploader.info)}"` : "";
112
- parts[partIndex++] = ` <video:uploader${info}>${escapeValueForXml(video.uploader.uploader)}</video:uploader>`;
113
- }
114
- if (video.live !== void 0) {
115
- parts[partIndex++] = ` <video:live>${video.live === "yes" || video.live === true ? "yes" : "no"}</video:live>`;
116
- }
117
- if (video.tag) {
118
- const tags = Array.isArray(video.tag) ? video.tag : [video.tag];
119
- for (const tag of tags) {
120
- parts[partIndex++] = ` <video:tag>${escapeValueForXml(tag)}</video:tag>`;
121
- }
122
- }
123
- if (video.category) {
124
- parts[partIndex++] = ` <video:category>${escapeValueForXml(video.category)}</video:category>`;
125
- }
126
- if (video.gallery_loc) {
127
- const title = video.gallery_loc.title ? ` title="${escapeValueForXml(video.gallery_loc.title)}"` : "";
128
- parts[partIndex++] = ` <video:gallery_loc${title}>${escapeValueForXml(video.gallery_loc)}</video:gallery_loc>`;
129
- }
130
- parts[partIndex++] = " </video:video>";
131
- }
132
- }
133
- break;
134
- case "news":
135
- if (value) {
136
- parts[partIndex++] = " <news:news>";
137
- parts[partIndex++] = " <news:publication>";
138
- parts[partIndex++] = ` <news:name>${escapeValueForXml(value.publication.name)}</news:name>`;
139
- parts[partIndex++] = ` <news:language>${escapeValueForXml(value.publication.language)}</news:language>`;
140
- parts[partIndex++] = " </news:publication>";
141
- if (value.title) {
142
- parts[partIndex++] = ` <news:title>${escapeValueForXml(value.title)}</news:title>`;
143
- }
144
- if (value.publication_date) {
145
- parts[partIndex++] = ` <news:publication_date>${value.publication_date}</news:publication_date>`;
146
- }
147
- if (value.access) {
148
- parts[partIndex++] = ` <news:access>${value.access}</news:access>`;
149
- }
150
- if (value.genres) {
151
- parts[partIndex++] = ` <news:genres>${escapeValueForXml(value.genres)}</news:genres>`;
152
- }
153
- if (value.keywords) {
154
- parts[partIndex++] = ` <news:keywords>${escapeValueForXml(value.keywords)}</news:keywords>`;
155
- }
156
- if (value.stock_tickers) {
157
- parts[partIndex++] = ` <news:stock_tickers>${escapeValueForXml(value.stock_tickers)}</news:stock_tickers>`;
158
- }
159
- parts[partIndex++] = " </news:news>";
160
- }
161
- break;
58
+ }
59
+ if (video.uploader) {
60
+ const info = video.uploader.info ? ` info="${xmlEscape(video.uploader.info)}"` : "";
61
+ xml += `${I3}<video:uploader${info}>${xmlEscape(video.uploader.uploader)}</video:uploader>${NL}`;
62
+ }
63
+ if (video.live !== void 0) xml += `${I3}<video:live>${yesNo(video.live)}</video:live>${NL}`;
64
+ if (video.tag) {
65
+ const tags = Array.isArray(video.tag) ? video.tag : [video.tag];
66
+ for (const t of tags) xml += `${I3}<video:tag>${xmlEscape(t)}</video:tag>${NL}`;
67
+ }
68
+ if (video.category) xml += `${I3}<video:category>${xmlEscape(video.category)}</video:category>${NL}`;
69
+ if (video.gallery_loc) xml += `${I3}<video:gallery_loc>${xmlEscape(video.gallery_loc)}</video:gallery_loc>${NL}`;
70
+ xml += `${I2}</video:video>${NL}`;
162
71
  }
163
72
  }
164
- parts[partIndex++] = " </url>";
165
- return parts.slice(0, partIndex).join("\n");
73
+ if (url.news) {
74
+ xml += `${I2}<news:news>${NL}${I3}<news:publication>${NL}`;
75
+ xml += `${I4}<news:name>${xmlEscape(url.news.publication.name)}</news:name>${NL}`;
76
+ xml += `${I4}<news:language>${xmlEscape(url.news.publication.language)}</news:language>${NL}`;
77
+ xml += `${I3}</news:publication>${NL}`;
78
+ if (url.news.title) xml += `${I3}<news:title>${xmlEscape(url.news.title)}</news:title>${NL}`;
79
+ if (url.news.publication_date) xml += `${I3}<news:publication_date>${url.news.publication_date}</news:publication_date>${NL}`;
80
+ xml += `${I2}</news:news>${NL}`;
81
+ }
82
+ xml += `${I1}</url>`;
83
+ return xml;
166
84
  }
167
85
  export function urlsToXml(urls, resolvers, { version, xsl, credits, minify }, errorInfo) {
168
- const estimatedSize = urls.length + 5;
169
- const xmlParts = Array.from({ length: estimatedSize });
170
- let partIndex = 0;
171
86
  let xslHref = xsl ? resolvers.relativeBaseUrlResolver(xsl) : false;
172
- if (xslHref && errorInfo && errorInfo.messages.length > 0) {
87
+ if (xslHref && errorInfo?.messages.length) {
173
88
  xslHref = withQuery(xslHref, {
174
89
  errors: "true",
175
90
  error_messages: errorInfo.messages,
176
91
  error_urls: errorInfo.urls
177
92
  });
178
93
  }
179
- if (xslHref) {
180
- xmlParts[partIndex++] = `<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="${escapeValueForXml(xslHref)}"?>`;
181
- } else {
182
- xmlParts[partIndex++] = '<?xml version="1.0" encoding="UTF-8"?>';
183
- }
184
- xmlParts[partIndex++] = URLSET_OPENING_TAG;
94
+ const NL = minify ? "" : "\n";
95
+ const I1 = minify ? "" : " ";
96
+ const I2 = minify ? "" : " ";
97
+ const I3 = minify ? "" : " ";
98
+ const I4 = minify ? "" : " ";
99
+ let xml = xslHref ? `<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="${escapeValueForXml(xslHref)}"?>${NL}` : `<?xml version="1.0" encoding="UTF-8"?>${NL}`;
100
+ xml += URLSET_OPENING_TAG + NL;
185
101
  for (const url of urls) {
186
- xmlParts[partIndex++] = buildUrlXml(url);
102
+ xml += buildUrlXml(url, NL, I1, I2, I3, I4) + NL;
187
103
  }
188
- xmlParts[partIndex++] = "</urlset>";
104
+ xml += "</urlset>";
189
105
  if (credits) {
190
- xmlParts[partIndex++] = `<!-- XML Sitemap generated by @nuxtjs/sitemap v${version} at ${(/* @__PURE__ */ new Date()).toISOString()} -->`;
191
- }
192
- const xmlContent = xmlParts.slice(0, partIndex);
193
- if (minify) {
194
- return xmlContent.join("").replace(/(?<!<[^>]*)\s(?![^<]*>)/g, "");
106
+ xml += `${NL}<!-- XML Sitemap generated by @nuxtjs/sitemap v${version} at ${(/* @__PURE__ */ new Date()).toISOString()} -->`;
195
107
  }
196
- return xmlContent.join("\n");
108
+ return xml;
197
109
  }
@@ -35,7 +35,7 @@ async function buildSitemapXml(event, definition, resolvers, runtimeConfig) {
35
35
  nitro._sitemapWarned = true;
36
36
  logger.error("Sitemap Site URL missing!");
37
37
  logger.info("To fix this please add `{ site: { url: 'site.com' } }` to your Nuxt config or a `NUXT_PUBLIC_SITE_URL=site.com` to your .env. Learn more at https://nuxtseo.com/site-config/getting-started/how-it-works");
38
- throw new createError({
38
+ throw createError({
39
39
  statusMessage: "You must provide a site URL to prerender a sitemap.",
40
40
  statusCode: 500
41
41
  });
@@ -78,8 +78,9 @@ async function buildSitemapXml(event, definition, resolvers, runtimeConfig) {
78
78
  resolvedCtx.urls = resolvedCtx.urls.map((e) => preNormalizeEntry(e, resolvers));
79
79
  }
80
80
  const maybeSort = (urls2) => runtimeConfig.sortEntries ? sortInPlace(urls2) : urls2;
81
- const normalizedPreDedupe = resolvedCtx.urls.map((e) => normaliseEntry(e, definition.defaults, resolvers));
82
- const urls = maybeSort(mergeOnKey(normalizedPreDedupe, "_key").map((e) => normaliseEntry(e, definition.defaults, resolvers)));
81
+ const defaults = definition.defaults || {};
82
+ const normalizedPreDedupe = resolvedCtx.urls.map((e) => normaliseEntry(e, defaults, resolvers));
83
+ const urls = maybeSort(mergeOnKey(normalizedPreDedupe, "_key").map((e) => normaliseEntry(e, defaults, resolvers)));
83
84
  if (definition._isChunking && definition.sitemapName.includes("-")) {
84
85
  const parts = definition.sitemapName.split("-");
85
86
  const lastPart = parts.pop();
@@ -11,36 +11,39 @@ import {
11
11
  import { defu } from "defu";
12
12
  import { mergeOnKey } from "../../../utils-pure.js";
13
13
  function resolve(s, resolvers) {
14
- if (typeof s === "undefined" || !resolvers)
15
- return s;
16
- s = typeof s === "string" ? s : s.toString();
17
- if (hasProtocol(s, { acceptRelative: true, strict: false }))
18
- return resolvers.fixSlashes(s);
19
- return resolvers.canonicalUrlResolver(s);
14
+ if (typeof s === "undefined")
15
+ return void 0;
16
+ const str = typeof s === "string" ? s : s.toString();
17
+ if (!resolvers)
18
+ return str;
19
+ if (hasProtocol(str, { acceptRelative: true, strict: false }))
20
+ return resolvers.fixSlashes(str);
21
+ return resolvers.canonicalUrlResolver(str);
20
22
  }
21
23
  function removeTrailingSlash(s) {
22
24
  return s.replace(/\/(\?|#|$)/, "$1");
23
25
  }
24
26
  export function preNormalizeEntry(_e, resolvers) {
25
- const e = typeof _e === "string" ? { loc: _e } : { ..._e };
26
- if (e.url && !e.loc) {
27
- e.loc = e.url;
28
- delete e.url;
27
+ const input = typeof _e === "string" ? { loc: _e } : { ..._e };
28
+ if (input.url && !input.loc) {
29
+ input.loc = input.url;
29
30
  }
30
- if (typeof e.loc !== "string") {
31
- e.loc = "";
31
+ delete input.url;
32
+ if (typeof input.loc !== "string") {
33
+ input.loc = "";
32
34
  }
35
+ const e = input;
33
36
  e.loc = removeTrailingSlash(e.loc);
34
37
  e._abs = hasProtocol(e.loc, { acceptRelative: false, strict: false });
35
38
  try {
36
39
  e._path = e._abs ? parseURL(e.loc) : parsePath(e.loc);
37
- } catch (e2) {
38
- e2._path = null;
40
+ } catch {
41
+ e._path = null;
39
42
  }
40
43
  if (e._path) {
41
- const query = parseQuery(e._path.search);
42
- const qs = stringifyQuery(query);
43
- e._relativeLoc = `${encodePath(e._path?.pathname)}${qs.length ? `?${qs}` : ""}`;
44
+ const search = e._path.search;
45
+ const qs = search && search.length > 1 ? stringifyQuery(parseQuery(search)) : "";
46
+ e._relativeLoc = `${encodePath(e._path.pathname)}${qs.length ? `?${qs}` : ""}`;
44
47
  if (e._path.host) {
45
48
  e.loc = stringifyParsedURL(e._path);
46
49
  } else {
@@ -76,8 +79,7 @@ export function normaliseEntry(_e, defaults, resolvers) {
76
79
  e.loc = resolve(e.loc, resolvers);
77
80
  if (e.alternatives) {
78
81
  const alternatives = e.alternatives.map((a) => ({ ...a }));
79
- for (let i = 0; i < alternatives.length; i++) {
80
- const alt = alternatives[i];
82
+ for (const alt of alternatives) {
81
83
  if (typeof alt.href === "string") {
82
84
  alt.href = resolve(alt.href, resolvers);
83
85
  } else if (typeof alt.href === "object" && alt.href) {
@@ -88,16 +90,16 @@ export function normaliseEntry(_e, defaults, resolvers) {
88
90
  }
89
91
  if (e.images) {
90
92
  const images = e.images.map((i) => ({ ...i }));
91
- for (let i = 0; i < images.length; i++) {
92
- images[i].loc = resolve(images[i].loc, resolvers);
93
+ for (const img of images) {
94
+ img.loc = resolve(img.loc, resolvers);
93
95
  }
94
96
  e.images = mergeOnKey(images, "loc");
95
97
  }
96
98
  if (e.videos) {
97
99
  const videos = e.videos.map((v) => ({ ...v }));
98
- for (let i = 0; i < videos.length; i++) {
99
- if (videos[i].content_loc) {
100
- videos[i].content_loc = resolve(videos[i].content_loc, resolvers);
100
+ for (const video of videos) {
101
+ if (video.content_loc) {
102
+ video.content_loc = resolve(video.content_loc, resolvers);
101
103
  }
102
104
  }
103
105
  e.videos = mergeOnKey(videos, "content_loc");
@@ -115,8 +117,9 @@ export function isValidW3CDate(d) {
115
117
  }
116
118
  export function normaliseDate(d) {
117
119
  if (typeof d === "string") {
118
- if (d.includes("T")) {
119
- const t = d.split("T")[1];
120
+ const tIdx = d.indexOf("T");
121
+ if (tIdx !== -1) {
122
+ const t = d.slice(tIdx + 1);
120
123
  if (!t.includes("+") && !t.includes("-") && !t.includes("Z")) {
121
124
  d += "Z";
122
125
  }
@@ -1,6 +1,6 @@
1
1
  import type { H3Event } from 'h3';
2
2
  import type { ModuleRuntimeConfig, SitemapSourceBase, SitemapSourceResolved } from '../../../types.js';
3
3
  export declare function fetchDataSource(input: SitemapSourceBase | SitemapSourceResolved, event?: H3Event): Promise<SitemapSourceResolved>;
4
- export declare function globalSitemapSources(): Promise<any>;
5
- export declare function childSitemapSources(definition: ModuleRuntimeConfig['sitemaps'][string]): Promise<any>;
4
+ export declare function globalSitemapSources(): Promise<any[]>;
5
+ export declare function childSitemapSources(definition: ModuleRuntimeConfig['sitemaps'][string]): Promise<any[]>;
6
6
  export declare function resolveSitemapSources(sources: (SitemapSourceBase | SitemapSourceResolved)[], event?: H3Event): Promise<SitemapSourceResolved[]>;
@@ -120,11 +120,12 @@ export async function globalSitemapSources() {
120
120
  if (import.meta.prerender) {
121
121
  const { readSourcesFromFilesystem } = await import("#sitemap-virtual/read-sources.mjs");
122
122
  const sources = await readSourcesFromFilesystem("global-sources.json");
123
- if (sources)
124
- return sources;
123
+ if (sources) {
124
+ return [...sources];
125
+ }
125
126
  }
126
127
  const m = await import("#sitemap-virtual/global-sources.mjs");
127
- return m.sources;
128
+ return [...m.sources];
128
129
  }
129
130
  export async function childSitemapSources(definition) {
130
131
  if (!definition?._hasSourceChunk)
@@ -132,11 +133,12 @@ export async function childSitemapSources(definition) {
132
133
  if (import.meta.prerender) {
133
134
  const { readSourcesFromFilesystem } = await import("#sitemap-virtual/read-sources.mjs");
134
135
  const allSources = await readSourcesFromFilesystem("child-sources.json");
135
- if (allSources)
136
- return allSources[definition.sitemapName] || [];
136
+ if (allSources) {
137
+ return [...allSources[definition.sitemapName] || []];
138
+ }
137
139
  }
138
140
  const m = await import("#sitemap-virtual/child-sources.mjs");
139
- return m.sources[definition.sitemapName] || [];
141
+ return [...m.sources[definition.sitemapName] || []];
140
142
  }
141
143
  export async function resolveSitemapSources(sources, event) {
142
144
  return (await Promise.all(
@@ -247,7 +247,7 @@ export type ResolvedSitemapUrl = Omit<SitemapUrl, 'url'> & Required<Pick<Sitemap
247
247
  /**
248
248
  * @internal
249
249
  */
250
- _path: ParsedURL;
250
+ _path: ParsedURL | null;
251
251
  /**
252
252
  * @internal
253
253
  */
@@ -362,6 +362,10 @@ export interface SitemapSourcesHookCtx extends NitroBaseHook {
362
362
  export type Changefreq = 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
363
363
  export interface SitemapUrl {
364
364
  loc: string;
365
+ /**
366
+ * Alias for `loc`. Will be normalized to `loc`.
367
+ */
368
+ url?: string;
365
369
  lastmod?: string | Date;
366
370
  changefreq?: Changefreq;
367
371
  priority?: 0 | 0.1 | 0.2 | 0.3 | 0.4 | 0.5 | 0.6 | 0.7 | 0.8 | 0.9 | 1;
@@ -436,6 +440,8 @@ export interface VideoEntry {
436
440
  };
437
441
  live?: 'yes' | 'no' | boolean;
438
442
  tag?: string | string[];
443
+ category?: string;
444
+ gallery_loc?: string | URL;
439
445
  }
440
446
  export interface Restriction {
441
447
  relationship: 'allow' | 'deny';
@@ -26,11 +26,12 @@ export function mergeOnKey(arr, key) {
26
26
  result[resultLength++] = item;
27
27
  }
28
28
  }
29
- return result.slice(0, resultLength);
29
+ result.length = resultLength;
30
+ return result;
30
31
  }
31
32
  export function splitForLocales(path, locales) {
32
33
  const prefix = withLeadingSlash(path).split("/")[1];
33
- if (locales.includes(prefix))
34
+ if (prefix && locales.includes(prefix))
34
35
  return [prefix, path.replace(`/${prefix}`, "")];
35
36
  return [null, path];
36
37
  }
@@ -62,24 +63,33 @@ export function createFilter(options = {}) {
62
63
  const exclude = options.exclude || [];
63
64
  if (include.length === 0 && exclude.length === 0)
64
65
  return () => true;
66
+ const excludeRegex = exclude.filter((r) => r instanceof RegExp);
67
+ const includeRegex = include.filter((r) => r instanceof RegExp);
68
+ const excludeStrings = exclude.filter((r) => typeof r === "string");
69
+ const includeStrings = include.filter((r) => typeof r === "string");
70
+ const excludeMatcher = excludeStrings.length > 0 ? toRouteMatcher(createRouter({
71
+ routes: Object.fromEntries(excludeStrings.map((r) => [r, true])),
72
+ strictTrailingSlash: false
73
+ })) : null;
74
+ const includeMatcher = includeStrings.length > 0 ? toRouteMatcher(createRouter({
75
+ routes: Object.fromEntries(includeStrings.map((r) => [r, true])),
76
+ strictTrailingSlash: false
77
+ })) : null;
78
+ const excludeExact = new Set(excludeStrings);
79
+ const includeExact = new Set(includeStrings);
65
80
  return function(path) {
66
- for (const v of [{ rules: exclude, result: false }, { rules: include, result: true }]) {
67
- const regexRules = v.rules.filter((r) => r instanceof RegExp);
68
- if (regexRules.some((r) => r.test(path)))
69
- return v.result;
70
- const stringRules = v.rules.filter((r) => typeof r === "string");
71
- if (stringRules.length > 0) {
72
- const routes = {};
73
- for (const r of stringRules) {
74
- if (r === path)
75
- return v.result;
76
- routes[r] = true;
77
- }
78
- const routeRulesMatcher = toRouteMatcher(createRouter({ routes, strictTrailingSlash: false }));
79
- if (routeRulesMatcher.matchAll(path).length > 0)
80
- return Boolean(v.result);
81
- }
82
- }
81
+ if (excludeRegex.some((r) => r.test(path)))
82
+ return false;
83
+ if (excludeExact.has(path))
84
+ return false;
85
+ if (excludeMatcher && excludeMatcher.matchAll(path).length > 0)
86
+ return false;
87
+ if (includeRegex.some((r) => r.test(path)))
88
+ return true;
89
+ if (includeExact.has(path))
90
+ return true;
91
+ if (includeMatcher && includeMatcher.matchAll(path).length > 0)
92
+ return true;
83
93
  return include.length === 0;
84
94
  };
85
95
  }
package/dist/utils.mjs CHANGED
@@ -319,12 +319,11 @@ function extractUrlFromParsedElement(urlElement, warnings) {
319
319
  });
320
320
  }
321
321
  }
322
- const filteredUrlObj = Object.fromEntries(
322
+ return Object.fromEntries(
323
323
  Object.entries(urlObj).filter(
324
324
  ([_, value]) => value != null && (!Array.isArray(value) || value.length > 0)
325
325
  )
326
326
  );
327
- return filteredUrlObj;
328
327
  }
329
328
  async function parseSitemapXml(xml) {
330
329
  const warnings = [];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nuxtjs/sitemap",
3
3
  "type": "module",
4
- "version": "7.4.9",
4
+ "version": "7.4.11",
5
5
  "description": "Powerfully flexible XML Sitemaps that integrate seamlessly, for Nuxt.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -49,12 +49,12 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@nuxt/devtools-kit": "^3.1.1",
52
- "@nuxt/kit": "^4.2.1",
52
+ "@nuxt/kit": "^4.2.2",
53
53
  "chalk": "^5.6.2",
54
54
  "defu": "^6.1.4",
55
- "fast-xml-parser": "^5.3.2",
55
+ "fast-xml-parser": "^5.3.3",
56
56
  "h3-compression": "^0.3.2",
57
- "nuxt-site-config": "^3.2.11",
57
+ "nuxt-site-config": "^3.2.14",
58
58
  "ofetch": "^1.5.1",
59
59
  "pathe": "^2.0.3",
60
60
  "pkg-types": "^2.3.0",
@@ -66,7 +66,7 @@
66
66
  "ultrahtml": "^1.6.0"
67
67
  },
68
68
  "peerDependencies": {
69
- "zod": "^3.0.0 || ^4.0.0"
69
+ "zod": ">=3"
70
70
  },
71
71
  "peerDependenciesMeta": {
72
72
  "zod": {
@@ -76,24 +76,24 @@
76
76
  "devDependencies": {
77
77
  "@arethetypeswrong/cli": "^0.18.2",
78
78
  "@nuxt/content": "^3.9.0",
79
- "@nuxt/eslint-config": "^1.11.0",
79
+ "@nuxt/eslint-config": "^1.12.1",
80
80
  "@nuxt/module-builder": "^1.0.2",
81
81
  "@nuxt/test-utils": "^3.21.0",
82
82
  "@nuxt/ui": "^4.2.1",
83
83
  "@nuxtjs/i18n": "^10.2.1",
84
- "@nuxtjs/robots": "^5.6.1",
84
+ "@nuxtjs/robots": "^5.6.7",
85
85
  "better-sqlite3": "^12.5.0",
86
86
  "bumpp": "^10.3.2",
87
- "eslint": "^9.39.1",
87
+ "eslint": "^9.39.2",
88
88
  "eslint-plugin-n": "^17.23.1",
89
89
  "execa": "^9.6.1",
90
90
  "happy-dom": "^20.0.11",
91
- "nuxt": "^4.2.1",
92
- "nuxt-i18n-micro": "^2.13.0",
91
+ "nuxt": "^4.2.2",
92
+ "nuxt-i18n-micro": "^2.15.2",
93
93
  "typescript": "^5.9.3",
94
- "vitest": "^3",
95
- "vue-tsc": "^3.1.6",
96
- "@nuxtjs/sitemap": "7.4.9"
94
+ "vitest": "3.2.4",
95
+ "vue-tsc": "^3.1.8",
96
+ "@nuxtjs/sitemap": "7.4.11"
97
97
  },
98
98
  "scripts": {
99
99
  "lint": "eslint .",
@@ -110,6 +110,6 @@
110
110
  "test": "vitest run && pnpm run test:attw",
111
111
  "test:unit": "vitest --project=unit",
112
112
  "test:attw": "attw --pack",
113
- "typecheck": "vue-tsc --noEmit"
113
+ "typecheck": "nuxt typecheck"
114
114
  }
115
115
  }
@@ -1 +0,0 @@
1
- {"id":"bafd23ec-aaa0-4756-a4c4-11462568906c","timestamp":1765075641425,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}