@nuxtjs/sitemap 8.3.0 → 8.3.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.
@@ -144,13 +144,22 @@ export function normaliseEntry(_e, defaults, resolvers, cache) {
144
144
  return e;
145
145
  }
146
146
  const IS_VALID_W3C_DATE = [
147
- /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/,
147
+ /^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)$/,
148
+ /^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)$/,
149
+ /^\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)$/,
148
150
  /^\d{4}-[01]\d-[0-3]\d$/,
149
151
  /^\d{4}-[01]\d$/,
150
152
  /^\d{4}$/
151
153
  ];
152
154
  export function isValidW3CDate(d) {
153
- return IS_VALID_W3C_DATE.some((r) => r.test(d));
155
+ if (!IS_VALID_W3C_DATE.some((r) => r.test(d)))
156
+ return false;
157
+ const [year, month, day] = d.slice(0, 10).split("-").map(Number);
158
+ if (month !== void 0 && (month < 1 || month > 12))
159
+ return false;
160
+ if (day !== void 0 && (day < 1 || day > new Date(year, month, 0).getDate()))
161
+ return false;
162
+ return true;
154
163
  }
155
164
  export function normaliseDate(d) {
156
165
  if (typeof d === "string") {
@@ -1,8 +1,39 @@
1
- import { parseSitemapXml } from "@nuxtjs/sitemap/utils";
2
1
  import { defu } from "defu";
3
2
  import { getRequestHost } from "h3";
3
+ import { collectSitemap } from "sitemapd/parse";
4
4
  import { parseURL } from "ufo";
5
5
  import { logger } from "../../../utils-pure.js";
6
+ const changeFrequencies = /* @__PURE__ */ new Set([
7
+ "always",
8
+ "hourly",
9
+ "daily",
10
+ "weekly",
11
+ "monthly",
12
+ "yearly",
13
+ "never"
14
+ ]);
15
+ function readerEntryToSitemapInput(entry) {
16
+ const priority = entry.priority === void 0 ? void 0 : Number.parseFloat(entry.priority);
17
+ const changefreq = entry.changefreq && changeFrequencies.has(entry.changefreq) ? entry.changefreq : void 0;
18
+ return {
19
+ loc: entry.loc,
20
+ ...entry.lastmod ? { lastmod: entry.lastmod } : {},
21
+ ...changefreq ? { changefreq } : {},
22
+ ...priority !== void 0 && Number.isFinite(priority) ? { priority } : {},
23
+ ...entry.extensions?.alternatives ? { alternatives: entry.extensions.alternatives.map(({ hreflang, href }) => ({ hreflang, href })) } : {},
24
+ ...entry.extensions?.images ? {
25
+ images: entry.extensions.images.map((image) => ({
26
+ loc: image.loc,
27
+ ...image.caption ? { caption: image.caption } : {},
28
+ ...image.geoLocation ? { geo_location: image.geoLocation } : {},
29
+ ...image.title ? { title: image.title } : {},
30
+ ...image.license ? { license: image.license } : {}
31
+ }))
32
+ } : {},
33
+ ...entry.extensions?.videos ? { videos: entry.extensions.videos } : {},
34
+ ...entry.extensions?.news ? { news: entry.extensions.news } : {}
35
+ };
36
+ }
6
37
  export function normalizeSourceInput(source) {
7
38
  if (typeof source === "string") {
8
39
  return { context: { name: "hook" }, fetch: source };
@@ -48,7 +79,9 @@ export async function fetchDataSource(input, event) {
48
79
  const abortRequestTimeout = setTimeout(() => timeoutController.abort(), timeout);
49
80
  try {
50
81
  let isMaybeErrorResponse = false;
51
- const isXmlRequest = parseURL(url).pathname.endsWith(".xml");
82
+ const pathname = parseURL(url).pathname.toLowerCase();
83
+ const isGzUrl = pathname.endsWith(".gz");
84
+ const isXmlRequest = pathname.endsWith(".xml") || isGzUrl;
52
85
  const mergedHeaders = defu(
53
86
  options?.headers,
54
87
  {
@@ -58,7 +91,10 @@ export async function fetchDataSource(input, event) {
58
91
  );
59
92
  const fetchOptions = {
60
93
  ...options,
61
- responseType: isXmlRequest ? "text" : "json",
94
+ // Fetch XML sources as raw bytes so we can detect and decompress a gzip body
95
+ // (either a `.gz` URL, or a server that serves gzip without Content-Encoding)
96
+ // before it's mangled by a UTF-8 text decode.
97
+ responseType: isXmlRequest ? "arrayBuffer" : "json",
62
98
  signal: timeoutController.signal,
63
99
  headers: mergedHeaders,
64
100
  // Use ofetch's built-in retry for external sources
@@ -84,11 +120,16 @@ export async function fetchDataSource(input, event) {
84
120
  };
85
121
  }
86
122
  let urls = [];
87
- if (typeof res === "object") {
123
+ if (isXmlRequest) {
124
+ const bytes = res instanceof Uint8Array ? res : new Uint8Array(res);
125
+ const result = await collectSitemap(bytes);
126
+ if (result._tag !== "document")
127
+ throw new Error(result.issues.map((issue) => issue.message).join("; ") || "Invalid sitemap document");
128
+ if (result.document._tag !== "urlset")
129
+ throw new Error("Sitemap URL source must be a URL set, not a sitemap index");
130
+ urls = result.document.entries.map(readerEntryToSitemapInput);
131
+ } else if (typeof res === "object") {
88
132
  urls = res.urls || res;
89
- } else if (typeof res === "string" && isXmlRequest) {
90
- const result = await parseSitemapXml(res);
91
- urls = result.urls;
92
133
  }
93
134
  return {
94
135
  ...input,
@@ -1,13 +1,8 @@
1
- import { createConsola } from "consola";
2
1
  import { createDefu } from "defu";
3
- import { createFilter } from "nuxtseo-shared/utils";
2
+ import { createFilter, createModuleLogger } from "nuxtseo-shared/utils";
4
3
  import { parseURL, withoutBase } from "ufo";
5
4
  export { createFilter } from "nuxtseo-shared/utils";
6
- export const logger = createConsola({
7
- defaults: {
8
- tag: "@nuxt/sitemap"
9
- }
10
- });
5
+ export const logger = createModuleLogger("@nuxt/sitemap");
11
6
  const XML_ENTITIES = {
12
7
  "&": "&amp;",
13
8
  "<": "&lt;",
package/dist/utils.d.mts CHANGED
@@ -1,5 +1,8 @@
1
- import { SitemapUrl, SitemapUrlInput } from '../dist/runtime/types.js';
1
+ import { SitemapUrl } from '../dist/runtime/types.js';
2
2
  export * from '../dist/runtime/types.js';
3
+ export { SitemapDocumentLoadResult, SitemapDocumentLoader, SitemapLoadFailureCode, SitemapLoadRequest, SitemapLoadSource, SitemapReadOptions, SitemapReadResult, SitemapReader, SitemapReaderOptions, SitemapTargetAuthorization, SitemapTargetAuthorizer, SitemapWalkDocument, SitemapWalkDocumentVisitor, SitemapWalkFailure, SitemapWalkNonRetainedResult, SitemapWalkOptions, SitemapWalkPartialReason, SitemapWalkResult, SitemapWalkRetainedResult, createSitemapReader } from 'sitemapd';
4
+ export { FetchDocumentLoaderOptions, SitemapFetch, createFetchDocumentLoader } from 'sitemapd/fetch';
5
+ export { CollectSitemapResult, ParseSitemapOptions, SitemapCompleteness, SitemapDocument, SitemapDocumentKind, SitemapExtensions, SitemapFormat, SitemapInput, SitemapIssue, SitemapIssueCode, SitemapParseEvent, SitemapReference, SitemapUrlRecord, collectSitemap, parseSitemap } from 'sitemapd/parse';
3
6
 
4
7
  declare function parseHtmlExtractSitemapMeta(html: string, options?: {
5
8
  images?: boolean;
@@ -9,59 +12,4 @@ declare function parseHtmlExtractSitemapMeta(html: string, options?: {
9
12
  resolveUrl?: (s: string) => string;
10
13
  }): Partial<SitemapUrl> | null;
11
14
 
12
- interface SitemapWarning {
13
- type: 'validation';
14
- message: string;
15
- context?: {
16
- url?: string;
17
- field?: string;
18
- value?: unknown;
19
- };
20
- }
21
- interface SitemapParseResult {
22
- urls: SitemapUrlInput[];
23
- warnings: SitemapWarning[];
24
- }
25
- type SitemapXmlChunk = string | Uint8Array;
26
- type SitemapXmlInput = SitemapXmlChunk | Iterable<SitemapXmlChunk> | AsyncIterable<SitemapXmlChunk> | ReadableStream<SitemapXmlChunk>;
27
- interface SitemapStreamOptions {
28
- maxEntryBytes?: number;
29
- maxBufferBytes?: number;
30
- }
31
- type SitemapXmlStreamEvent = {
32
- _tag: 'url';
33
- url: SitemapUrlInput;
34
- } | {
35
- _tag: 'warning';
36
- warning: SitemapWarning;
37
- };
38
- type SitemapIndexStreamEvent = {
39
- _tag: 'sitemap';
40
- sitemap: SitemapIndexEntry;
41
- } | {
42
- _tag: 'warning';
43
- warning: SitemapWarning;
44
- };
45
- type SitemapKind = 'urlset' | 'index';
46
- type SitemapStreamEvent = {
47
- _tag: 'kind';
48
- kind: SitemapKind;
49
- } | SitemapXmlStreamEvent | SitemapIndexStreamEvent;
50
- declare function parseSitemapStream(input: SitemapXmlInput, options?: SitemapStreamOptions): AsyncGenerator<SitemapStreamEvent>;
51
- declare function parseSitemapXmlStream(input: SitemapXmlInput, options?: SitemapStreamOptions): AsyncGenerator<SitemapXmlStreamEvent>;
52
- declare function parseSitemapIndexStream(input: SitemapXmlInput, options?: SitemapStreamOptions): AsyncGenerator<SitemapIndexStreamEvent>;
53
- declare function parseSitemapXml(xml: string): Promise<SitemapParseResult>;
54
-
55
- interface SitemapIndexEntry {
56
- loc: string;
57
- lastmod?: string;
58
- }
59
- interface SitemapIndexParseResult {
60
- entries: SitemapIndexEntry[];
61
- warnings: SitemapWarning[];
62
- }
63
- declare function parseSitemapIndex(xml: string): Promise<SitemapIndexParseResult>;
64
- declare function isSitemapIndex(xml: string): boolean;
65
-
66
- export { isSitemapIndex, parseHtmlExtractSitemapMeta, parseSitemapIndex, parseSitemapIndexStream, parseSitemapStream, parseSitemapXml, parseSitemapXmlStream };
67
- export type { SitemapIndexEntry, SitemapIndexParseResult, SitemapIndexStreamEvent, SitemapKind, SitemapParseResult, SitemapStreamEvent, SitemapStreamOptions, SitemapWarning, SitemapXmlChunk, SitemapXmlInput, SitemapXmlStreamEvent };
15
+ export { parseHtmlExtractSitemapMeta };
package/dist/utils.d.ts CHANGED
@@ -1,5 +1,8 @@
1
- import { SitemapUrl, SitemapUrlInput } from '../dist/runtime/types.js';
1
+ import { SitemapUrl } from '../dist/runtime/types.js';
2
2
  export * from '../dist/runtime/types.js';
3
+ export { SitemapDocumentLoadResult, SitemapDocumentLoader, SitemapLoadFailureCode, SitemapLoadRequest, SitemapLoadSource, SitemapReadOptions, SitemapReadResult, SitemapReader, SitemapReaderOptions, SitemapTargetAuthorization, SitemapTargetAuthorizer, SitemapWalkDocument, SitemapWalkDocumentVisitor, SitemapWalkFailure, SitemapWalkNonRetainedResult, SitemapWalkOptions, SitemapWalkPartialReason, SitemapWalkResult, SitemapWalkRetainedResult, createSitemapReader } from 'sitemapd';
4
+ export { FetchDocumentLoaderOptions, SitemapFetch, createFetchDocumentLoader } from 'sitemapd/fetch';
5
+ export { CollectSitemapResult, ParseSitemapOptions, SitemapCompleteness, SitemapDocument, SitemapDocumentKind, SitemapExtensions, SitemapFormat, SitemapInput, SitemapIssue, SitemapIssueCode, SitemapParseEvent, SitemapReference, SitemapUrlRecord, collectSitemap, parseSitemap } from 'sitemapd/parse';
3
6
 
4
7
  declare function parseHtmlExtractSitemapMeta(html: string, options?: {
5
8
  images?: boolean;
@@ -9,59 +12,4 @@ declare function parseHtmlExtractSitemapMeta(html: string, options?: {
9
12
  resolveUrl?: (s: string) => string;
10
13
  }): Partial<SitemapUrl> | null;
11
14
 
12
- interface SitemapWarning {
13
- type: 'validation';
14
- message: string;
15
- context?: {
16
- url?: string;
17
- field?: string;
18
- value?: unknown;
19
- };
20
- }
21
- interface SitemapParseResult {
22
- urls: SitemapUrlInput[];
23
- warnings: SitemapWarning[];
24
- }
25
- type SitemapXmlChunk = string | Uint8Array;
26
- type SitemapXmlInput = SitemapXmlChunk | Iterable<SitemapXmlChunk> | AsyncIterable<SitemapXmlChunk> | ReadableStream<SitemapXmlChunk>;
27
- interface SitemapStreamOptions {
28
- maxEntryBytes?: number;
29
- maxBufferBytes?: number;
30
- }
31
- type SitemapXmlStreamEvent = {
32
- _tag: 'url';
33
- url: SitemapUrlInput;
34
- } | {
35
- _tag: 'warning';
36
- warning: SitemapWarning;
37
- };
38
- type SitemapIndexStreamEvent = {
39
- _tag: 'sitemap';
40
- sitemap: SitemapIndexEntry;
41
- } | {
42
- _tag: 'warning';
43
- warning: SitemapWarning;
44
- };
45
- type SitemapKind = 'urlset' | 'index';
46
- type SitemapStreamEvent = {
47
- _tag: 'kind';
48
- kind: SitemapKind;
49
- } | SitemapXmlStreamEvent | SitemapIndexStreamEvent;
50
- declare function parseSitemapStream(input: SitemapXmlInput, options?: SitemapStreamOptions): AsyncGenerator<SitemapStreamEvent>;
51
- declare function parseSitemapXmlStream(input: SitemapXmlInput, options?: SitemapStreamOptions): AsyncGenerator<SitemapXmlStreamEvent>;
52
- declare function parseSitemapIndexStream(input: SitemapXmlInput, options?: SitemapStreamOptions): AsyncGenerator<SitemapIndexStreamEvent>;
53
- declare function parseSitemapXml(xml: string): Promise<SitemapParseResult>;
54
-
55
- interface SitemapIndexEntry {
56
- loc: string;
57
- lastmod?: string;
58
- }
59
- interface SitemapIndexParseResult {
60
- entries: SitemapIndexEntry[];
61
- warnings: SitemapWarning[];
62
- }
63
- declare function parseSitemapIndex(xml: string): Promise<SitemapIndexParseResult>;
64
- declare function isSitemapIndex(xml: string): boolean;
65
-
66
- export { isSitemapIndex, parseHtmlExtractSitemapMeta, parseSitemapIndex, parseSitemapIndexStream, parseSitemapStream, parseSitemapXml, parseSitemapXmlStream };
67
- export type { SitemapIndexEntry, SitemapIndexParseResult, SitemapIndexStreamEvent, SitemapKind, SitemapParseResult, SitemapStreamEvent, SitemapStreamOptions, SitemapWarning, SitemapXmlChunk, SitemapXmlInput, SitemapXmlStreamEvent };
15
+ export { parseHtmlExtractSitemapMeta };