@nuxtjs/sitemap 7.0.2 → 7.2.1
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/content.d.ts +1 -0
- package/dist/client/200.html +9 -9
- package/dist/client/404.html +9 -9
- package/dist/client/_nuxt/{B5lI3vl2.js → B-Cf5GGq.js} +1 -1
- package/dist/client/_nuxt/{BLDCaNbg.js → B2vK47Ag.js} +1 -1
- package/dist/client/_nuxt/CBErYmNG.js +32 -0
- package/dist/client/_nuxt/{BCt9_I41.js → CxhUe2GG.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/b551cdd3-b342-41ea-8265-0fb9c87a6b0b.json +1 -0
- package/dist/client/_nuxt/{entry.WCUheyaE.css → entry.CJ2Eg9q-.css} +1 -1
- package/dist/client/_nuxt/error-404.DWO74KKP.css +1 -0
- package/dist/client/_nuxt/error-500.DVC0lzO_.css +1 -0
- package/dist/client/index.html +9 -9
- package/dist/content.cjs +48 -0
- package/dist/content.d.cts +231 -0
- package/dist/content.d.mts +231 -0
- package/dist/content.d.ts +231 -0
- package/dist/content.mjs +45 -0
- package/dist/module.cjs +1270 -4
- package/dist/module.d.cts +8 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +169 -71
- package/dist/runtime/server/plugins/{nuxt-content.js → nuxt-content-v2.js} +2 -10
- package/dist/runtime/server/routes/__sitemap__/debug.d.ts +1 -1
- package/dist/runtime/server/routes/__sitemap__/nuxt-content-urls-v3.d.ts +2 -0
- package/dist/runtime/server/routes/__sitemap__/nuxt-content-urls-v3.js +17 -0
- package/dist/runtime/server/routes/sitemap/[sitemap].xml.js +1 -1
- package/dist/runtime/server/routes/sitemap_index.xml.js +2 -2
- package/dist/runtime/server/sitemap/builder/sitemap-index.d.ts +2 -1
- package/dist/runtime/server/sitemap/builder/sitemap-index.js +8 -3
- package/dist/runtime/server/sitemap/builder/sitemap.d.ts +4 -3
- package/dist/runtime/server/sitemap/builder/sitemap.js +12 -7
- package/dist/runtime/server/sitemap/nitro.js +6 -2
- package/dist/runtime/server/sitemap/urlset/sources.js +16 -7
- package/dist/runtime/server/sitemap/utils/extractSitemapXML.d.ts +2 -0
- package/dist/runtime/server/sitemap/utils/extractSitemapXML.js +75 -0
- package/dist/runtime/types.d.ts +5 -1
- package/package.json +27 -22
- package/dist/client/_nuxt/BZ4NIl-o.js +0 -32
- package/dist/client/_nuxt/builds/meta/286d11d8-5fae-4d47-bddf-64b0ae9fc73d.json +0 -1
- package/dist/client/_nuxt/error-404.vQ0SaaqA.css +0 -1
- package/dist/client/_nuxt/error-500.ayRVCnRF.css +0 -1
- /package/dist/runtime/server/plugins/{nuxt-content.d.ts → nuxt-content-v2.d.ts} +0 -0
- /package/dist/runtime/server/routes/__sitemap__/{nuxt-content-urls.d.ts → nuxt-content-urls-v2.d.ts} +0 -0
- /package/dist/runtime/server/routes/__sitemap__/{nuxt-content-urls.js → nuxt-content-urls-v2.js} +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
import { ModuleOptions as ModuleOptions$1 } from '../dist/runtime/types.js';
|
|
3
|
+
|
|
4
|
+
interface ModuleOptions extends ModuleOptions$1 {
|
|
5
|
+
}
|
|
6
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
7
|
+
|
|
8
|
+
export { type ModuleOptions, _default as default };
|
package/dist/module.json
CHANGED
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,
|
|
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';
|
|
@@ -264,6 +264,22 @@ function resolveNitroPreset(nitroConfig) {
|
|
|
264
264
|
return preset.replace("_", "-");
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
+
const videoRegex = /<video[^>]*>([\s\S]*?)<\/video>/g;
|
|
268
|
+
const videoSrcRegex = /<video[^>]*\ssrc="([^"]+)"/;
|
|
269
|
+
const videoPosterRegex = /<video[^>]*\sposter="([^"]+)"/;
|
|
270
|
+
const videoTitleRegex = /<video[^>]*\sdata-title="([^"]+)"/;
|
|
271
|
+
const videoDescriptionRegex = /<video[^>]*\sdata-description="([^"]+)"/;
|
|
272
|
+
const videoPlayerLocRegex = /<video[^>]*\sdata-player-loc="([^"]+)"/;
|
|
273
|
+
const videoDurationRegex = /<video[^>]*\sdata-duration="([^"]+)"/;
|
|
274
|
+
const videoExpirationDateRegex = /<video[^>]*\sdata-expiration-date="([^"]+)"/;
|
|
275
|
+
const videoRatingRegex = /<video[^>]*\sdata-rating="([^"]+)"/;
|
|
276
|
+
const videoViewCountRegex = /<video[^>]*\sdata-view-count="([^"]+)"/;
|
|
277
|
+
const videoPublicationDateRegex = /<video[^>]*\sdata-publication-date="([^"]+)"/;
|
|
278
|
+
const videoFamilyFriendlyRegex = /<video[^>]*\sdata-family-friendly="([^"]+)"/;
|
|
279
|
+
const videoRequiresSubscriptionRegex = /<video[^>]*\sdata-requires-subscription="([^"]+)"/;
|
|
280
|
+
const videoLiveRegex = /<video[^>]*\sdata-live="([^"]+)"/;
|
|
281
|
+
const videoTagRegex = /<video[^>]*\sdata-tag="([^"]+)"/;
|
|
282
|
+
const sourceRegex = /<source[^>]*\ssrc="([^"]+)"/g;
|
|
267
283
|
function extractSitemapMetaFromHtml(html, options) {
|
|
268
284
|
options = options || { images: true, videos: true, lastmod: true, alternatives: true };
|
|
269
285
|
const payload = {};
|
|
@@ -291,54 +307,74 @@ function extractSitemapMetaFromHtml(html, options) {
|
|
|
291
307
|
const mainRegex = /<main[^>]*>([\s\S]*?)<\/main>/;
|
|
292
308
|
const mainMatch = mainRegex.exec(html);
|
|
293
309
|
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
310
|
let videoMatch;
|
|
301
311
|
while ((videoMatch = videoRegex.exec(mainMatch[1])) !== null) {
|
|
302
312
|
const videoContent = videoMatch[1];
|
|
303
313
|
const videoTag = videoMatch[0];
|
|
304
|
-
const
|
|
305
|
-
const
|
|
306
|
-
const poster = (videoPosterRegex.exec(videoTag) || [])[1] || "";
|
|
314
|
+
const content_loc = (videoSrcRegex.exec(videoTag) || [])[1] || "";
|
|
315
|
+
const thumbnail_loc = (videoPosterRegex.exec(videoTag) || [])[1] || "";
|
|
307
316
|
const title = (videoTitleRegex.exec(videoTag) || [])[1] || "";
|
|
308
317
|
const description = (videoDescriptionRegex.exec(videoTag) || [])[1] || "";
|
|
318
|
+
const videoObj = {
|
|
319
|
+
content_loc,
|
|
320
|
+
thumbnail_loc,
|
|
321
|
+
title,
|
|
322
|
+
description
|
|
323
|
+
};
|
|
324
|
+
const player_loc = (videoPlayerLocRegex.exec(videoTag) || [])[1];
|
|
325
|
+
if (player_loc)
|
|
326
|
+
videoObj.player_loc = player_loc;
|
|
327
|
+
const duration = (videoDurationRegex.exec(videoTag) || [])[1];
|
|
328
|
+
if (duration)
|
|
329
|
+
videoObj.duration = Number.parseInt(duration, 10);
|
|
330
|
+
const expiration_date = (videoExpirationDateRegex.exec(videoTag) || [])[1];
|
|
331
|
+
if (expiration_date)
|
|
332
|
+
videoObj.expiration_date = expiration_date;
|
|
333
|
+
const rating = (videoRatingRegex.exec(videoTag) || [])[1];
|
|
334
|
+
if (rating)
|
|
335
|
+
videoObj.rating = Number.parseFloat(rating);
|
|
336
|
+
const view_count = (videoViewCountRegex.exec(videoTag) || [])[1];
|
|
337
|
+
if (view_count)
|
|
338
|
+
videoObj.view_count = Number.parseInt(view_count, 10);
|
|
339
|
+
const publication_date = (videoPublicationDateRegex.exec(videoTag) || [])[1];
|
|
340
|
+
if (publication_date)
|
|
341
|
+
videoObj.publication_date = publication_date;
|
|
342
|
+
const family_friendly = (videoFamilyFriendlyRegex.exec(videoTag) || [])[1];
|
|
343
|
+
if (family_friendly)
|
|
344
|
+
videoObj.family_friendly = family_friendly;
|
|
345
|
+
const requires_subscription = (videoRequiresSubscriptionRegex.exec(videoTag) || [])[1];
|
|
346
|
+
if (requires_subscription)
|
|
347
|
+
videoObj.requires_subscription = requires_subscription;
|
|
348
|
+
const live = (videoLiveRegex.exec(videoTag) || [])[1];
|
|
349
|
+
if (live)
|
|
350
|
+
videoObj.live = live;
|
|
351
|
+
const tag = (videoTagRegex.exec(videoTag) || [])[1];
|
|
352
|
+
if (tag)
|
|
353
|
+
videoObj.tag = tag;
|
|
309
354
|
const sources = [];
|
|
310
355
|
let sourceMatch;
|
|
311
356
|
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
|
-
});
|
|
357
|
+
sources.push(sourceMatch[1]);
|
|
327
358
|
}
|
|
328
359
|
if (sources.length > 0) {
|
|
329
|
-
videos.push(...sources)
|
|
360
|
+
videos.push(...sources.map((source) => {
|
|
361
|
+
if (source.startsWith("/"))
|
|
362
|
+
source = tryUseNuxt() ? withSiteUrl(source) : source;
|
|
363
|
+
return {
|
|
364
|
+
...videoObj,
|
|
365
|
+
content_loc: source
|
|
366
|
+
};
|
|
367
|
+
}));
|
|
368
|
+
} else {
|
|
369
|
+
videos.push(videoObj);
|
|
330
370
|
}
|
|
331
371
|
}
|
|
332
372
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
title: video.title,
|
|
339
|
-
description: video.description
|
|
340
|
-
})
|
|
341
|
-
);
|
|
373
|
+
const validVideos = videos.filter((v) => {
|
|
374
|
+
return v.content_loc && v.thumbnail_loc && v.title && v.description;
|
|
375
|
+
});
|
|
376
|
+
if (validVideos.length > 0) {
|
|
377
|
+
payload.videos = validVideos;
|
|
342
378
|
}
|
|
343
379
|
}
|
|
344
380
|
if (options?.lastmod) {
|
|
@@ -788,6 +824,7 @@ declare module 'nitropack' {
|
|
|
788
824
|
}
|
|
789
825
|
interface NitroRuntimeHooks {
|
|
790
826
|
'sitemap:index-resolved': (ctx: import('${typesPath}').SitemapIndexRenderCtx) => void | Promise<void>
|
|
827
|
+
'sitemap:input': (ctx: import('${typesPath}').SitemapInputCtx) => void | Promise<void>
|
|
791
828
|
'sitemap:resolved': (ctx: import('${typesPath}').SitemapRenderCtx) => void | Promise<void>
|
|
792
829
|
'sitemap:output': (ctx: import('${typesPath}').SitemapOutputHookCtx) => void | Promise<void>
|
|
793
830
|
}
|
|
@@ -832,7 +869,7 @@ declare module 'vue-router' {
|
|
|
832
869
|
nuxt.options.nitro.routeRules["/sitemap_index.xml"] = routeRules;
|
|
833
870
|
if (typeof config.sitemaps === "object") {
|
|
834
871
|
for (const k in config.sitemaps) {
|
|
835
|
-
nuxt.options.nitro.routeRules[joinURL(config.sitemapsPathPrefix, `/${k}.xml`)] = routeRules;
|
|
872
|
+
nuxt.options.nitro.routeRules[joinURL(config.sitemapsPathPrefix || "", `/${k}.xml`)] = routeRules;
|
|
836
873
|
}
|
|
837
874
|
} else {
|
|
838
875
|
nuxt.options.nitro.routeRules[`/${config.sitemapName}`] = routeRules;
|
|
@@ -845,31 +882,81 @@ declare module 'vue-router' {
|
|
|
845
882
|
if (config.experimentalCompression)
|
|
846
883
|
addServerPlugin(resolve("./runtime/server/plugins/compression"));
|
|
847
884
|
const isNuxtContentDocumentDriven = !!nuxt.options.content?.documentDriven || config.strictNuxtContentPaths;
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
885
|
+
const usingNuxtContent = hasNuxtModule("@nuxt/content");
|
|
886
|
+
const isNuxtContentV3 = usingNuxtContent && await hasNuxtModuleCompatibility("@nuxt/content", "^3");
|
|
887
|
+
const nuxtV3Collections = /* @__PURE__ */ new Set();
|
|
888
|
+
const isNuxtContentV2 = usingNuxtContent && await hasNuxtModuleCompatibility("@nuxt/content", "^2");
|
|
889
|
+
if (isNuxtContentV3) {
|
|
890
|
+
nuxt.options.alias["#sitemap/content-v3-nitro-path"] = resolve(dirname(resolveModule("@nuxt/content")), "runtime/nitro");
|
|
891
|
+
nuxt.hooks.hook("content:file:afterParse", (ctx) => {
|
|
892
|
+
const content = ctx.content;
|
|
893
|
+
nuxtV3Collections.add(ctx.collection.name);
|
|
894
|
+
if (!("sitemap" in ctx.collection.fields)) {
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
const images = [];
|
|
898
|
+
if (config.discoverImages) {
|
|
899
|
+
images.push(
|
|
900
|
+
...content.body.value?.filter(
|
|
901
|
+
(c) => ["image", "img", "nuxtimg", "nuxt-img"].includes(c[0])
|
|
902
|
+
).filter((c) => c[1]?.src).map((c) => ({ loc: c[1].src })) || []
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
const sitemapConfig = typeof content.sitemap === "object" ? content.sitemap : {};
|
|
906
|
+
const lastmod = content.seo?.articleModifiedTime || content.updatedAt;
|
|
907
|
+
const defaults = {
|
|
908
|
+
loc: content.path
|
|
909
|
+
};
|
|
910
|
+
if (images.length > 0)
|
|
911
|
+
defaults.images = images;
|
|
912
|
+
if (lastmod)
|
|
913
|
+
defaults.lastmod = lastmod;
|
|
914
|
+
const definition = defu(sitemapConfig, defaults);
|
|
915
|
+
if (!definition.loc) {
|
|
916
|
+
if (content.path && content.path && content.path.startsWith("/"))
|
|
917
|
+
definition.loc = content.path;
|
|
918
|
+
}
|
|
919
|
+
content.sitemap = definition;
|
|
920
|
+
if (!definition.loc)
|
|
921
|
+
delete content.sitemap;
|
|
922
|
+
ctx.content = content;
|
|
923
|
+
});
|
|
924
|
+
addServerHandler({
|
|
925
|
+
route: "/__sitemap__/nuxt-content-urls.json",
|
|
926
|
+
handler: resolve("./runtime/server/routes/__sitemap__/nuxt-content-urls-v3")
|
|
927
|
+
});
|
|
928
|
+
if (config.strictNuxtContentPaths) {
|
|
929
|
+
logger.warn("You have set `strictNuxtContentPaths: true` but are using @nuxt/content v3. This is not required, please remove it.");
|
|
872
930
|
}
|
|
931
|
+
appGlobalSources.push({
|
|
932
|
+
context: {
|
|
933
|
+
name: "@nuxt/content@v3:urls",
|
|
934
|
+
description: "Generated from your markdown files.",
|
|
935
|
+
tips: [`Parsing the following collections: ${Array.from(nuxtV3Collections).join(", ")}`]
|
|
936
|
+
},
|
|
937
|
+
fetch: "/__sitemap__/nuxt-content-urls.json"
|
|
938
|
+
});
|
|
939
|
+
} else if (isNuxtContentV2) {
|
|
940
|
+
addServerPlugin(resolve("./runtime/server/plugins/nuxt-content-v2"));
|
|
941
|
+
addServerHandler({
|
|
942
|
+
route: "/__sitemap__/nuxt-content-urls.json",
|
|
943
|
+
handler: resolve("./runtime/server/routes/__sitemap__/nuxt-content-urls-v2")
|
|
944
|
+
});
|
|
945
|
+
const tips = [];
|
|
946
|
+
if (nuxt.options.content?.documentDriven)
|
|
947
|
+
tips.push("Enabled because you're using `@nuxt/content` with `documentDriven: true`.");
|
|
948
|
+
else if (config.strictNuxtContentPaths)
|
|
949
|
+
tips.push("Enabled because you've set `config.strictNuxtContentPaths: true`.");
|
|
950
|
+
else
|
|
951
|
+
tips.push("You can provide a `sitemap` key in your markdown frontmatter to configure specific URLs. Make sure you include a `loc`.");
|
|
952
|
+
appGlobalSources.push({
|
|
953
|
+
context: {
|
|
954
|
+
name: "@nuxt/content@v2:urls",
|
|
955
|
+
description: "Generated from your markdown files.",
|
|
956
|
+
tips
|
|
957
|
+
},
|
|
958
|
+
fetch: "/__sitemap__/nuxt-content-urls.json"
|
|
959
|
+
});
|
|
873
960
|
}
|
|
874
961
|
const sitemaps = {};
|
|
875
962
|
if (usingMultiSitemaps) {
|
|
@@ -879,12 +966,23 @@ declare module 'vue-router' {
|
|
|
879
966
|
lazy: true,
|
|
880
967
|
middleware: false
|
|
881
968
|
});
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
969
|
+
if (config.sitemapsPathPrefix && config.sitemapsPathPrefix !== "/") {
|
|
970
|
+
addServerHandler({
|
|
971
|
+
route: joinURL(config.sitemapsPathPrefix, `/**:sitemap`),
|
|
972
|
+
handler: resolve("./runtime/server/routes/sitemap/[sitemap].xml"),
|
|
973
|
+
lazy: true,
|
|
974
|
+
middleware: false
|
|
975
|
+
});
|
|
976
|
+
} else {
|
|
977
|
+
for (const sitemapName of Object.keys(config.sitemaps || {})) {
|
|
978
|
+
addServerHandler({
|
|
979
|
+
route: withLeadingSlash(`${sitemapName}.xml`),
|
|
980
|
+
handler: resolve("./runtime/server/routes/sitemap/[sitemap].xml"),
|
|
981
|
+
lazy: true,
|
|
982
|
+
middleware: false
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
}
|
|
888
986
|
sitemaps.index = {
|
|
889
987
|
sitemapName: "index",
|
|
890
988
|
_route: withBase("sitemap_index.xml", nuxt.options.app.baseURL || "/"),
|
|
@@ -899,7 +997,7 @@ declare module 'vue-router' {
|
|
|
899
997
|
sitemaps[sitemapName] = defu(
|
|
900
998
|
{
|
|
901
999
|
sitemapName,
|
|
902
|
-
_route: withBase(joinURL(config.sitemapsPathPrefix, `${sitemapName}.xml`), nuxt.options.app.baseURL || "/"),
|
|
1000
|
+
_route: withBase(joinURL(config.sitemapsPathPrefix || "", `${sitemapName}.xml`), nuxt.options.app.baseURL || "/"),
|
|
903
1001
|
_hasSourceChunk: typeof definition.urls !== "undefined" || definition.sources?.length
|
|
904
1002
|
},
|
|
905
1003
|
{ ...definition, urls: void 0, sources: void 0 },
|
|
@@ -1030,9 +1128,9 @@ declare module 'vue-router' {
|
|
|
1030
1128
|
...((await nitroPromise)._prerenderedRoutes || []).filter((r) => {
|
|
1031
1129
|
const lastSegment = r.route.split("/").pop();
|
|
1032
1130
|
const isExplicitFile = !!lastSegment?.match(/\.[0-9a-z]+$/i)?.[0];
|
|
1033
|
-
if (r.error || ["/200.html", "/404.html", "/index.html"].includes(r.route))
|
|
1131
|
+
if (isExplicitFile || r.error || ["/200.html", "/404.html", "/index.html"].includes(r.route))
|
|
1034
1132
|
return false;
|
|
1035
|
-
return r.contentType?.includes("text/html")
|
|
1133
|
+
return r.contentType?.includes("text/html");
|
|
1036
1134
|
}).map((r) => r._sitemap)
|
|
1037
1135
|
];
|
|
1038
1136
|
const pageSource = convertNuxtPagesToSitemapEntries(await pagesPromise, {
|
|
@@ -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,
|
|
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
|
|
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,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
|
|
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 {
|
|
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,
|
|
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;
|
|
@@ -5,7 +5,7 @@ import { childSitemapSources, globalSitemapSources, resolveSitemapSources } from
|
|
|
5
5
|
import { sortSitemapUrls } from "../urlset/sort.js";
|
|
6
6
|
import { createPathFilter, logger, splitForLocales } from "../../../utils-pure.js";
|
|
7
7
|
import { handleEntry, wrapSitemapXml } from "./xml.js";
|
|
8
|
-
export function resolveSitemapEntries(sitemap,
|
|
8
|
+
export function resolveSitemapEntries(sitemap, urls, runtimeConfig, resolvers) {
|
|
9
9
|
const {
|
|
10
10
|
autoI18n,
|
|
11
11
|
isI18nMapped
|
|
@@ -14,7 +14,7 @@ export function resolveSitemapEntries(sitemap, sources, runtimeConfig, resolvers
|
|
|
14
14
|
include: sitemap.include,
|
|
15
15
|
exclude: sitemap.exclude
|
|
16
16
|
});
|
|
17
|
-
const _urls =
|
|
17
|
+
const _urls = urls.map((_e) => {
|
|
18
18
|
const e = preNormalizeEntry(_e, resolvers);
|
|
19
19
|
if (!e.loc || !filterPath(e.loc))
|
|
20
20
|
return false;
|
|
@@ -139,7 +139,7 @@ export function resolveSitemapEntries(sitemap, sources, runtimeConfig, resolvers
|
|
|
139
139
|
}
|
|
140
140
|
return _urls;
|
|
141
141
|
}
|
|
142
|
-
export async function buildSitemapUrls(sitemap, resolvers, runtimeConfig) {
|
|
142
|
+
export async function buildSitemapUrls(sitemap, resolvers, runtimeConfig, nitro) {
|
|
143
143
|
const {
|
|
144
144
|
sitemaps,
|
|
145
145
|
// enhancing
|
|
@@ -175,10 +175,15 @@ export async function buildSitemapUrls(sitemap, resolvers, runtimeConfig) {
|
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
const
|
|
181
|
-
const
|
|
178
|
+
const sourcesInput = sitemap.includeAppSources ? await globalSitemapSources() : [];
|
|
179
|
+
sourcesInput.push(...await childSitemapSources(sitemap));
|
|
180
|
+
const sources = await resolveSitemapSources(sourcesInput, resolvers.event);
|
|
181
|
+
const resolvedCtx = {
|
|
182
|
+
urls: sources.flatMap((s) => s.urls),
|
|
183
|
+
sitemapName: sitemap.sitemapName
|
|
184
|
+
};
|
|
185
|
+
await nitro?.hooks.callHook("sitemap:input", resolvedCtx);
|
|
186
|
+
const enhancedUrls = resolveSitemapEntries(sitemap, resolvedCtx.urls, { autoI18n, isI18nMapped }, resolvers);
|
|
182
187
|
const filteredUrls = enhancedUrls.filter((e) => {
|
|
183
188
|
if (isMultiSitemap && e._sitemap && sitemap.sitemapName)
|
|
184
189
|
return e._sitemap === sitemap.sitemapName;
|
|
@@ -4,7 +4,7 @@ import { defu } from "defu";
|
|
|
4
4
|
import { logger, mergeOnKey, splitForLocales } from "../../utils-pure.js";
|
|
5
5
|
import { createNitroRouteRuleMatcher } from "../kit.js";
|
|
6
6
|
import { buildSitemapUrls, urlsToXml } from "./builder/sitemap.js";
|
|
7
|
-
import { normaliseEntry } from "./urlset/normalise.js";
|
|
7
|
+
import { normaliseEntry, preNormalizeEntry } from "./urlset/normalise.js";
|
|
8
8
|
import { sortSitemapUrls } from "./urlset/sort.js";
|
|
9
9
|
import { useNitroApp, createSitePathResolver, getPathRobotConfig, useSiteConfig } from "#imports";
|
|
10
10
|
export function useNitroUrlResolvers(e) {
|
|
@@ -39,7 +39,7 @@ export async function createSitemap(event, definition, runtimeConfig) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
const resolvers = useNitroUrlResolvers(event);
|
|
42
|
-
let sitemapUrls = await buildSitemapUrls(definition, resolvers, runtimeConfig);
|
|
42
|
+
let sitemapUrls = await buildSitemapUrls(definition, resolvers, runtimeConfig, nitro);
|
|
43
43
|
const routeRuleMatcher = createNitroRouteRuleMatcher();
|
|
44
44
|
const { autoI18n } = runtimeConfig;
|
|
45
45
|
sitemapUrls = sitemapUrls.map((u) => {
|
|
@@ -63,11 +63,15 @@ export async function createSitemap(event, definition, runtimeConfig) {
|
|
|
63
63
|
return false;
|
|
64
64
|
return routeRules.sitemap ? defu(u, routeRules.sitemap) : u;
|
|
65
65
|
}).filter(Boolean);
|
|
66
|
+
const locSize = sitemapUrls.length;
|
|
66
67
|
const resolvedCtx = {
|
|
67
68
|
urls: sitemapUrls,
|
|
68
69
|
sitemapName
|
|
69
70
|
};
|
|
70
71
|
await nitro.hooks.callHook("sitemap:resolved", resolvedCtx);
|
|
72
|
+
if (resolvedCtx.urls.length !== locSize) {
|
|
73
|
+
resolvedCtx.urls = resolvedCtx.urls.map((e) => preNormalizeEntry(e, resolvers));
|
|
74
|
+
}
|
|
71
75
|
const maybeSort = (urls2) => runtimeConfig.sortEntries ? sortSitemapUrls(urls2) : urls2;
|
|
72
76
|
const normalizedPreDedupe = resolvedCtx.urls.map((e) => normaliseEntry(e, definition.defaults, resolvers));
|
|
73
77
|
const urls = maybeSort(mergeOnKey(normalizedPreDedupe, "_key").map((e) => normaliseEntry(e, definition.defaults, resolvers)));
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { getRequestHost } from "h3";
|
|
2
2
|
import { defu } from "defu";
|
|
3
|
+
import { parseURL } from "ufo";
|
|
4
|
+
import { extractSitemapXML } from "../utils/extractSitemapXML.js";
|
|
3
5
|
export async function fetchDataSource(input, event) {
|
|
4
6
|
const context = typeof input.context === "string" ? { name: input.context } : input.context || { name: "fetch" };
|
|
5
7
|
context.tips = context.tips || [];
|
|
@@ -9,24 +11,25 @@ export async function fetchDataSource(input, event) {
|
|
|
9
11
|
const timeout = options.timeout || 5e3;
|
|
10
12
|
const timeoutController = new AbortController();
|
|
11
13
|
const abortRequestTimeout = setTimeout(() => timeoutController.abort(), timeout);
|
|
12
|
-
let
|
|
14
|
+
let isMaybeErrorResponse = false;
|
|
15
|
+
const isXmlRequest = parseURL(url).pathname.endsWith(".xml");
|
|
16
|
+
const fetchContainer = url.startsWith("/") && event ? event : globalThis;
|
|
13
17
|
try {
|
|
14
|
-
const
|
|
15
|
-
const urls = await fetchContainer.$fetch(url, {
|
|
18
|
+
const res = await fetchContainer.$fetch(url, {
|
|
16
19
|
...options,
|
|
17
|
-
responseType: "json",
|
|
20
|
+
responseType: isXmlRequest ? "text" : "json",
|
|
18
21
|
signal: timeoutController.signal,
|
|
19
22
|
headers: defu(options?.headers, {
|
|
20
|
-
Accept: "application/json"
|
|
23
|
+
Accept: isXmlRequest ? "text/xml" : "application/json"
|
|
21
24
|
}, event ? { Host: getRequestHost(event, { xForwardedHost: true }) } : {}),
|
|
22
25
|
// @ts-expect-error untyped
|
|
23
26
|
onResponse({ response }) {
|
|
24
27
|
if (typeof response._data === "string" && response._data.startsWith("<!DOCTYPE html>"))
|
|
25
|
-
|
|
28
|
+
isMaybeErrorResponse = true;
|
|
26
29
|
}
|
|
27
30
|
});
|
|
28
31
|
const timeTakenMs = Date.now() - start;
|
|
29
|
-
if (
|
|
32
|
+
if (isMaybeErrorResponse) {
|
|
30
33
|
context.tips.push("This is usually because the URL isn't correct or is throwing an error. Please check the URL");
|
|
31
34
|
return {
|
|
32
35
|
...input,
|
|
@@ -36,6 +39,12 @@ export async function fetchDataSource(input, event) {
|
|
|
36
39
|
error: "Received HTML response instead of JSON"
|
|
37
40
|
};
|
|
38
41
|
}
|
|
42
|
+
let urls = [];
|
|
43
|
+
if (typeof res === "object") {
|
|
44
|
+
urls = res.urls || res;
|
|
45
|
+
} else if (typeof res === "string" && parseURL(url).pathname.endsWith(".xml")) {
|
|
46
|
+
urls = extractSitemapXML(res);
|
|
47
|
+
}
|
|
39
48
|
return {
|
|
40
49
|
...input,
|
|
41
50
|
context,
|