@nuxtjs/sitemap 7.3.1 → 7.4.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.
- package/dist/client/200.html +7 -8
- package/dist/client/404.html +7 -8
- package/dist/client/_nuxt/ChEizYIG.js +172 -0
- package/dist/client/_nuxt/{CT3BV8Rj.js → SQMF8ibg.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/048e1f4c-a575-4a94-bbab-d777afe4c585.json +1 -0
- package/dist/client/_nuxt/{5vafBU9X.js → cqJZcoo0.js} +1 -1
- package/dist/client/_nuxt/error-404.DljSaiyF.css +1 -0
- package/dist/client/_nuxt/error-500.DbX9fggi.css +1 -0
- package/dist/client/index.html +7 -8
- package/dist/module.cjs +28 -18
- package/dist/module.json +1 -1
- package/dist/module.mjs +28 -18
- package/dist/runtime/server/content-compat.d.ts +1 -0
- package/dist/runtime/server/content-compat.js +2 -0
- package/dist/runtime/server/routes/__sitemap__/nuxt-content-urls-v3.d.ts +1 -1
- package/dist/runtime/server/routes/__sitemap__/nuxt-content-urls-v3.js +4 -2
- package/dist/runtime/server/routes/sitemap.xsl.js +37 -13
- package/dist/runtime/server/routes/sitemap_index.xml.js +6 -2
- package/dist/runtime/server/sitemap/builder/sitemap-index.d.ts +11 -2
- package/dist/runtime/server/sitemap/builder/sitemap-index.js +23 -5
- package/dist/runtime/server/sitemap/builder/sitemap.d.ts +7 -1
- package/dist/runtime/server/sitemap/builder/sitemap.js +10 -5
- package/dist/runtime/server/sitemap/builder/xml.d.ts +4 -1
- package/dist/runtime/server/sitemap/builder/xml.js +13 -4
- package/dist/runtime/server/sitemap/nitro.js +7 -3
- package/dist/runtime/server/sitemap/urlset/normalise.js +4 -3
- package/dist/runtime/server/sitemap/urlset/sources.js +62 -17
- package/dist/runtime/server/utils.d.ts +1 -0
- package/dist/runtime/server/utils.js +3 -0
- package/dist/runtime/types.d.ts +1 -0
- package/package.json +11 -10
- package/dist/client/_nuxt/BIHI7g3E.js +0 -1
- package/dist/client/_nuxt/Bn78IMkz.js +0 -172
- package/dist/client/_nuxt/builds/meta/5ecca6e1-2b8a-4fc5-a128-35cbc27bf6d7.json +0 -1
- package/dist/client/_nuxt/error-404.D_zhMyJm.css +0 -1
- package/dist/client/_nuxt/error-500.rdOYVbxo.css +0 -1
|
@@ -41,7 +41,7 @@ async function buildSitemapXml(event, definition, resolvers, runtimeConfig) {
|
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
const sitemapUrls = await buildSitemapUrls(definition, resolvers, runtimeConfig, nitro);
|
|
44
|
+
const { urls: sitemapUrls, failedSources } = await buildSitemapUrls(definition, resolvers, runtimeConfig, nitro);
|
|
45
45
|
const routeRuleMatcher = createNitroRouteRuleMatcher();
|
|
46
46
|
const { autoI18n } = runtimeConfig;
|
|
47
47
|
let validCount = 0;
|
|
@@ -94,7 +94,11 @@ async function buildSitemapXml(event, definition, resolvers, runtimeConfig) {
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
|
-
const
|
|
97
|
+
const errorInfo = failedSources.length > 0 ? {
|
|
98
|
+
messages: failedSources.map((f) => f.error),
|
|
99
|
+
urls: failedSources.map((f) => f.url)
|
|
100
|
+
} : void 0;
|
|
101
|
+
const sitemap = urlsToXml(urls, resolvers, runtimeConfig, errorInfo);
|
|
98
102
|
const ctx = { sitemap, sitemapName, event };
|
|
99
103
|
await nitro.hooks.callHook("sitemap:output", ctx);
|
|
100
104
|
return ctx.sitemap;
|
|
@@ -120,7 +124,7 @@ const buildSitemapXmlCached = defineCachedFunction(
|
|
|
120
124
|
);
|
|
121
125
|
export async function createSitemap(event, definition, runtimeConfig) {
|
|
122
126
|
const resolvers = useNitroUrlResolvers(event);
|
|
123
|
-
const shouldCache = !import.meta.dev && runtimeConfig.cacheMaxAgeSeconds > 0;
|
|
127
|
+
const shouldCache = !import.meta.dev && typeof runtimeConfig.cacheMaxAgeSeconds === "number" && runtimeConfig.cacheMaxAgeSeconds > 0;
|
|
124
128
|
const xml = shouldCache ? await buildSitemapXmlCached(event, definition, resolvers, runtimeConfig) : await buildSitemapXml(event, definition, resolvers, runtimeConfig);
|
|
125
129
|
setHeader(event, "Content-Type", "text/xml; charset=UTF-8");
|
|
126
130
|
if (runtimeConfig.cacheMaxAgeSeconds) {
|
|
@@ -75,7 +75,7 @@ export function normaliseEntry(_e, defaults, resolvers) {
|
|
|
75
75
|
delete e.lastmod;
|
|
76
76
|
e.loc = resolve(e.loc, resolvers);
|
|
77
77
|
if (e.alternatives) {
|
|
78
|
-
const alternatives = e.alternatives;
|
|
78
|
+
const alternatives = e.alternatives.map((a) => ({ ...a }));
|
|
79
79
|
for (let i = 0; i < alternatives.length; i++) {
|
|
80
80
|
const alt = alternatives[i];
|
|
81
81
|
if (typeof alt.href === "string") {
|
|
@@ -87,19 +87,20 @@ export function normaliseEntry(_e, defaults, resolvers) {
|
|
|
87
87
|
e.alternatives = mergeOnKey(alternatives, "hreflang");
|
|
88
88
|
}
|
|
89
89
|
if (e.images) {
|
|
90
|
-
const images = e.images;
|
|
90
|
+
const images = e.images.map((i) => ({ ...i }));
|
|
91
91
|
for (let i = 0; i < images.length; i++) {
|
|
92
92
|
images[i].loc = resolve(images[i].loc, resolvers);
|
|
93
93
|
}
|
|
94
94
|
e.images = mergeOnKey(images, "loc");
|
|
95
95
|
}
|
|
96
96
|
if (e.videos) {
|
|
97
|
-
const videos = e.videos;
|
|
97
|
+
const videos = e.videos.map((v) => ({ ...v }));
|
|
98
98
|
for (let i = 0; i < videos.length; i++) {
|
|
99
99
|
if (videos[i].content_loc) {
|
|
100
100
|
videos[i].content_loc = resolve(videos[i].content_loc, resolvers);
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
+
e.videos = mergeOnKey(videos, "content_loc");
|
|
103
104
|
}
|
|
104
105
|
return e;
|
|
105
106
|
}
|
|
@@ -2,35 +2,70 @@ import { getRequestHost } from "h3";
|
|
|
2
2
|
import { defu } from "defu";
|
|
3
3
|
import { parseURL } from "ufo";
|
|
4
4
|
import { extractSitemapXML } from "../utils/extractSitemapXML.js";
|
|
5
|
+
import { logger } from "../../../utils-pure.js";
|
|
6
|
+
async function tryFetchWithFallback(url, options, event) {
|
|
7
|
+
const isExternalUrl = !url.startsWith("/");
|
|
8
|
+
if (isExternalUrl) {
|
|
9
|
+
const strategies = [
|
|
10
|
+
// Strategy 1: Use globalThis.$fetch (original approach)
|
|
11
|
+
() => globalThis.$fetch(url, options),
|
|
12
|
+
// Strategy 2: If event is available, try using event context even for external URLs
|
|
13
|
+
event ? () => event.$fetch(url, options) : null,
|
|
14
|
+
// Strategy 3: Use native fetch as last resort
|
|
15
|
+
() => $fetch(url, options)
|
|
16
|
+
].filter(Boolean);
|
|
17
|
+
let lastError = null;
|
|
18
|
+
for (const strategy of strategies) {
|
|
19
|
+
try {
|
|
20
|
+
return await strategy();
|
|
21
|
+
} catch (error) {
|
|
22
|
+
lastError = error;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
throw lastError;
|
|
27
|
+
}
|
|
28
|
+
const fetchContainer = url.startsWith("/") && event ? event : globalThis;
|
|
29
|
+
return await fetchContainer.$fetch(url, options);
|
|
30
|
+
}
|
|
5
31
|
export async function fetchDataSource(input, event) {
|
|
6
32
|
const context = typeof input.context === "string" ? { name: input.context } : input.context || { name: "fetch" };
|
|
7
|
-
context.tips = context.tips || [];
|
|
8
33
|
const url = typeof input.fetch === "string" ? input.fetch : input.fetch[0];
|
|
9
34
|
const options = typeof input.fetch === "string" ? {} : input.fetch[1];
|
|
10
35
|
const start = Date.now();
|
|
11
|
-
const
|
|
36
|
+
const isExternalUrl = !url.startsWith("/");
|
|
37
|
+
const timeout = isExternalUrl ? 1e4 : options.timeout || 5e3;
|
|
12
38
|
const timeoutController = new AbortController();
|
|
13
39
|
const abortRequestTimeout = setTimeout(() => timeoutController.abort(), timeout);
|
|
14
|
-
let isMaybeErrorResponse = false;
|
|
15
|
-
const isXmlRequest = parseURL(url).pathname.endsWith(".xml");
|
|
16
|
-
const fetchContainer = url.startsWith("/") && event ? event : globalThis;
|
|
17
40
|
try {
|
|
18
|
-
|
|
41
|
+
let isMaybeErrorResponse = false;
|
|
42
|
+
const isXmlRequest = parseURL(url).pathname.endsWith(".xml");
|
|
43
|
+
const mergedHeaders = defu(
|
|
44
|
+
options?.headers,
|
|
45
|
+
{
|
|
46
|
+
Accept: isXmlRequest ? "text/xml" : "application/json"
|
|
47
|
+
},
|
|
48
|
+
event ? { host: getRequestHost(event, { xForwardedHost: true }) } : {}
|
|
49
|
+
);
|
|
50
|
+
const fetchOptions = {
|
|
19
51
|
...options,
|
|
20
52
|
responseType: isXmlRequest ? "text" : "json",
|
|
21
53
|
signal: timeoutController.signal,
|
|
22
|
-
headers:
|
|
23
|
-
|
|
24
|
-
|
|
54
|
+
headers: mergedHeaders,
|
|
55
|
+
// Use ofetch's built-in retry for external sources
|
|
56
|
+
...isExternalUrl && {
|
|
57
|
+
retry: 2,
|
|
58
|
+
retryDelay: 200
|
|
59
|
+
},
|
|
25
60
|
// @ts-expect-error untyped
|
|
26
61
|
onResponse({ response }) {
|
|
27
62
|
if (typeof response._data === "string" && response._data.startsWith("<!DOCTYPE html>"))
|
|
28
63
|
isMaybeErrorResponse = true;
|
|
29
64
|
}
|
|
30
|
-
}
|
|
65
|
+
};
|
|
66
|
+
const res = await tryFetchWithFallback(url, fetchOptions, event);
|
|
31
67
|
const timeTakenMs = Date.now() - start;
|
|
32
68
|
if (isMaybeErrorResponse) {
|
|
33
|
-
context.tips.push("This is usually because the URL isn't correct or is throwing an error. Please check the URL");
|
|
34
69
|
return {
|
|
35
70
|
...input,
|
|
36
71
|
context,
|
|
@@ -53,16 +88,26 @@ export async function fetchDataSource(input, event) {
|
|
|
53
88
|
};
|
|
54
89
|
} catch (_err) {
|
|
55
90
|
const error = _err;
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
91
|
+
if (isExternalUrl) {
|
|
92
|
+
const errorInfo = {
|
|
93
|
+
url,
|
|
94
|
+
timeout,
|
|
95
|
+
error: error.message,
|
|
96
|
+
statusCode: error.response?.status,
|
|
97
|
+
statusText: error.response?.statusText,
|
|
98
|
+
method: options?.method || "GET"
|
|
99
|
+
};
|
|
100
|
+
logger.error("Failed to fetch external source.", errorInfo);
|
|
101
|
+
} else {
|
|
102
|
+
logger.error("Failed to fetch source.", { url, error: error.message });
|
|
103
|
+
}
|
|
61
104
|
return {
|
|
62
105
|
...input,
|
|
63
106
|
context,
|
|
64
107
|
urls: [],
|
|
65
|
-
error: error.message
|
|
108
|
+
error: error.message,
|
|
109
|
+
_isFailure: true
|
|
110
|
+
// Mark as failure to prevent caching
|
|
66
111
|
};
|
|
67
112
|
} finally {
|
|
68
113
|
if (abortRequestTimeout) {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { useRuntimeConfig } from "nitropack/runtime";
|
|
2
2
|
import { normalizeRuntimeFilters } from "../utils-pure.js";
|
|
3
3
|
export * from "../utils-pure.js";
|
|
4
|
+
export function xmlEscape(str) {
|
|
5
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
6
|
+
}
|
|
4
7
|
export function useSitemapRuntimeConfig(e) {
|
|
5
8
|
const clone = JSON.parse(JSON.stringify(useRuntimeConfig(e).sitemap));
|
|
6
9
|
for (const k in clone.sitemaps) {
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -178,6 +178,7 @@ export interface SitemapSourceResolved extends Omit<SitemapSourceBase, 'urls'> {
|
|
|
178
178
|
urls: SitemapUrlInput[];
|
|
179
179
|
error?: any;
|
|
180
180
|
timeTakenMs?: number;
|
|
181
|
+
_isFailure?: boolean;
|
|
181
182
|
}
|
|
182
183
|
export type AppSourceContext = 'nuxt:pages' | 'nuxt:prerender' | 'nuxt:route-rules' | '@nuxtjs/i18n:pages' | '@nuxt/content:document-driven';
|
|
183
184
|
export type SitemapSourceInput = string | [string, FetchOptions] | SitemapSourceBase | SitemapSourceResolved;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxtjs/sitemap",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "7.
|
|
4
|
+
"version": "7.4.0",
|
|
5
5
|
"description": "Powerfully flexible XML Sitemaps that integrate seamlessly, for Nuxt.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@nuxt/devtools-kit": "^2.
|
|
48
|
-
"@nuxt/kit": "^3.17.
|
|
47
|
+
"@nuxt/devtools-kit": "^2.5.0",
|
|
48
|
+
"@nuxt/kit": "^3.17.5",
|
|
49
49
|
"chalk": "^5.4.1",
|
|
50
50
|
"defu": "^6.1.4",
|
|
51
51
|
"h3-compression": "^0.3.2",
|
|
@@ -59,23 +59,24 @@
|
|
|
59
59
|
"ufo": "^1.6.1"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@arethetypeswrong/cli": "^0.18.
|
|
63
|
-
"@nuxt/content": "^3.
|
|
62
|
+
"@arethetypeswrong/cli": "^0.18.2",
|
|
63
|
+
"@nuxt/content": "^3.6.0",
|
|
64
64
|
"@nuxt/eslint-config": "^1.4.1",
|
|
65
65
|
"@nuxt/module-builder": "^1.0.1",
|
|
66
66
|
"@nuxt/test-utils": "^3.19.1",
|
|
67
67
|
"@nuxt/ui": "^3.1.3",
|
|
68
68
|
"@nuxtjs/i18n": "^9.5.5",
|
|
69
69
|
"@nuxtjs/robots": "^5.2.10",
|
|
70
|
+
"better-sqlite3": "^11.10.0",
|
|
70
71
|
"bumpp": "^10.1.1",
|
|
71
|
-
"eslint": "^9.
|
|
72
|
-
"eslint-plugin-n": "^17.
|
|
72
|
+
"eslint": "^9.29.0",
|
|
73
|
+
"eslint-plugin-n": "^17.20.0",
|
|
73
74
|
"execa": "^9.6.0",
|
|
74
|
-
"happy-dom": "^
|
|
75
|
-
"nuxt": "^3.17.
|
|
75
|
+
"happy-dom": "^18.0.1",
|
|
76
|
+
"nuxt": "^3.17.5",
|
|
76
77
|
"nuxt-i18n-micro": "^1.87.0",
|
|
77
78
|
"typescript": "^5.8.3",
|
|
78
|
-
"vitest": "^3.2.
|
|
79
|
+
"vitest": "^3.2.3",
|
|
79
80
|
"vue-tsc": "^2.2.10"
|
|
80
81
|
},
|
|
81
82
|
"scripts": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const e={};export{e as default};
|