@warlock.js/sitemap 5.15.0 → 5.17.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/CHANGELOG.md +18 -0
- package/README.md +179 -137
- package/cjs/index.cjs +677 -201
- package/cjs/index.cjs.map +1 -1
- package/esm/atomic-publish.mjs +85 -0
- package/esm/atomic-publish.mjs.map +1 -0
- package/esm/atomic-write-file.mjs +50 -0
- package/esm/atomic-write-file.mjs.map +1 -0
- package/esm/duplicate-path-tracker.mjs +36 -0
- package/esm/duplicate-path-tracker.mjs.map +1 -0
- package/esm/errors.d.mts +39 -0
- package/esm/errors.mjs +52 -0
- package/esm/errors.mjs.map +1 -0
- package/esm/index.d.mts +8 -8
- package/esm/index.mjs +6 -6
- package/esm/lastmod.mjs +23 -0
- package/esm/lastmod.mjs.map +1 -0
- package/esm/normalize-entry.mjs +59 -0
- package/esm/normalize-entry.mjs.map +1 -0
- package/esm/route-counter.mjs +19 -0
- package/esm/route-counter.mjs.map +1 -0
- package/esm/shard-name.mjs +28 -0
- package/esm/shard-name.mjs.map +1 -0
- package/esm/sitemap-index-options.mjs +31 -0
- package/esm/sitemap-index-options.mjs.map +1 -0
- package/esm/sitemap-index-types.d.mts +39 -0
- package/esm/sitemap-index-xml.mjs +20 -0
- package/esm/sitemap-index-xml.mjs.map +1 -0
- package/esm/sitemap-index.d.mts +31 -0
- package/esm/sitemap-index.mjs +96 -0
- package/esm/sitemap-index.mjs.map +1 -0
- package/esm/sitemap-shard-writer.mjs +89 -0
- package/esm/sitemap-shard-writer.mjs.map +1 -0
- package/esm/sitemap.d.mts +63 -0
- package/esm/sitemap.mjs +129 -0
- package/esm/sitemap.mjs.map +1 -0
- package/esm/types.d.mts +51 -20
- package/esm/url.d.mts +1 -20
- package/esm/url.mjs +26 -19
- package/esm/url.mjs.map +1 -1
- package/esm/xml.d.mts +15 -4
- package/esm/xml.mjs +30 -8
- package/esm/xml.mjs.map +1 -1
- package/llms-full.txt +139 -159
- package/llms.txt +2 -2
- package/package.json +2 -14
- package/skills/sitemap-overview/SKILL.md +139 -159
- package/esm/collect-entries.d.mts +0 -44
- package/esm/collect-entries.mjs +0 -73
- package/esm/collect-entries.mjs.map +0 -1
- package/esm/diagnostic.d.mts +0 -13
- package/esm/diagnostic.mjs +0 -19
- package/esm/diagnostic.mjs.map +0 -1
- package/esm/routable-page.d.mts +0 -27
- package/esm/sitemap-connector.d.mts +0 -60
- package/esm/sitemap-connector.mjs +0 -117
- package/esm/sitemap-connector.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,24 @@ All notable changes to `@warlock.js/sitemap` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
|
|
6
6
|
|
|
7
|
+
## 5.16.0 - 2026-09-18
|
|
8
|
+
|
|
9
|
+
### Upgrading
|
|
10
|
+
|
|
11
|
+
- The 5.15 connector API is gone. In a Warlock app, remove `sitemapConnector()` from `warlock.config.ts` and `src/config/sitemap.ts`, then configure `web.sitemap` in `src/config/web.ts` (`warlock add sitemap` writes this section). Outside Warlock, build the sitemap with `new Sitemap({ baseUrl })`.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `SitemapIndex`: streams entries into size-capped shards plus a master index, and optionally writes `.xml.gz` files. It publishes the whole output directory atomically and marks it with `.sitemap-set.json`.
|
|
16
|
+
- `Sitemap.publishTo(outDir, fileName?)`, and `saveTo()` now writes atomically (temp file, then rename, with retries on Windows `EPERM`/`EBUSY`).
|
|
17
|
+
- `UnownedOutputDirectoryError`: publishing refuses to replace a non-empty directory that lacks the ownership marker.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **BREAKING:** the package no longer depends on any framework. The connector API is removed: `sitemapConnector()`, `collectSitemapEntries()`, the `SitemapConfig` config module, `MissingPublicUrlError`, `NoPageRegistryError` and `RoutablePage`. Use the `Sitemap` builder class instead (`new Sitemap({ baseUrl })`, `add` / `addMany` / `declareRoute`, `toXML` / `saveTo`). Warlock apps configure `web.sitemap` in `@warlock.js/web` instead.
|
|
22
|
+
- `baseUrl` is validated in the constructor (`InvalidBaseUrlError`). Entries are keyed by path, and `duplicates()` reports every collision.
|
|
23
|
+
- Dropped the `@warlock.js/core` and `@warlock.js/web` dependencies.
|
|
24
|
+
|
|
7
25
|
## 5.15.0 - 2026-09-18
|
|
8
26
|
|
|
9
27
|
### Added
|
package/README.md
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
# @warlock.js/sitemap
|
|
2
2
|
|
|
3
|
-
A
|
|
4
|
-
|
|
5
|
-
dynamic route can't be enumerated. `@warlock.js/core` and `@warlock.js/web`
|
|
6
|
-
are **optional peers** — everything except `sitemapConnector()` imports
|
|
7
|
-
nothing from either, and `sitemapConnector()` itself only reaches them
|
|
8
|
-
through a lazy `import()` at boot. Three ways to use it, below.
|
|
3
|
+
A sitemap builder that knows nothing about any framework. Entries in, a valid
|
|
4
|
+
[sitemaps.org](https://www.sitemaps.org/protocol.html) document out.
|
|
9
5
|
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
**Zero runtime dependencies.** Generation only — emitting XML needs no
|
|
7
|
+
dependency; parsing one does, and nothing here needs it yet.
|
|
12
8
|
|
|
13
9
|
## Install
|
|
14
10
|
|
|
@@ -16,170 +12,216 @@ needs no dependency; parsing one does, and nothing needs it yet.
|
|
|
16
12
|
npm install @warlock.js/sitemap
|
|
17
13
|
```
|
|
18
14
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
No Warlock at all. Build the `RoutablePage[]` array yourself — from a route
|
|
22
|
-
table, a database, wherever your app already knows its own URLs — and call
|
|
23
|
-
`collectSitemapEntries` + `buildSitemapXml` directly. Nothing on this path
|
|
24
|
-
resolves `@warlock.js/core` or `@warlock.js/web`.
|
|
15
|
+
## Use it
|
|
25
16
|
|
|
26
17
|
```ts
|
|
27
|
-
import
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
defaults: { changefreq: "weekly", priority: 0.5 },
|
|
18
|
+
import { Sitemap } from "@warlock.js/sitemap";
|
|
19
|
+
|
|
20
|
+
const sitemap = new Sitemap({
|
|
21
|
+
baseUrl: "https://example.com",
|
|
22
|
+
changefreq: "weekly",
|
|
23
|
+
priority: 0.5,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
sitemap.add({ path: "/" });
|
|
27
|
+
|
|
28
|
+
for (const post of await Post.all()) {
|
|
29
|
+
sitemap.add({
|
|
30
|
+
name: "post-details",
|
|
31
|
+
route: "/posts/:id",
|
|
32
|
+
path: `/posts/${post.slug}`,
|
|
33
|
+
lastmod: post.updatedAt,
|
|
34
|
+
priority: 0.8,
|
|
45
35
|
});
|
|
36
|
+
}
|
|
46
37
|
|
|
47
|
-
|
|
38
|
+
const xml = sitemap.toXML();
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
});
|
|
40
|
+
await sitemap.saveTo("public/sitemap.xml");
|
|
51
41
|
```
|
|
52
42
|
|
|
53
|
-
|
|
43
|
+
That is the whole common case. It is the same three lines from an Express
|
|
44
|
+
handler, a cron script, a Warlock app, or a `node build-sitemap.mjs` you wrote
|
|
45
|
+
in five minutes.
|
|
54
46
|
|
|
55
|
-
|
|
56
|
-
have nothing to list. Pass `entries` and `sitemapConnector()` uses it instead;
|
|
57
|
-
`@warlock.js/web` is not required on this path.
|
|
47
|
+
## The API
|
|
58
48
|
|
|
59
|
-
|
|
60
|
-
// warlock.config.ts
|
|
61
|
-
import { sitemapConnector } from "@warlock.js/sitemap";
|
|
62
|
-
|
|
63
|
-
export default defineConfig({
|
|
64
|
-
connectors: [
|
|
65
|
-
sitemapConnector({
|
|
66
|
-
entries: async () => {
|
|
67
|
-
const products = await db.products.find();
|
|
68
|
-
|
|
69
|
-
return products.map((product) => ({ path: `/products/${product.slug}` }));
|
|
70
|
-
},
|
|
71
|
-
}),
|
|
72
|
-
],
|
|
73
|
-
});
|
|
74
|
-
```
|
|
49
|
+
### `new Sitemap(options)`
|
|
75
50
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
51
|
+
| Option | Meaning |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| `baseUrl` | **Required.** Absolute origin, e.g. `https://example.com` or `https://example.com/docs`. |
|
|
54
|
+
| `changefreq` | Applied to any entry that does not set its own. |
|
|
55
|
+
| `priority` | Same. |
|
|
56
|
+
| `lastmod` | Same. |
|
|
79
57
|
|
|
80
|
-
|
|
58
|
+
`baseUrl` is validated **in the constructor**. A `Sitemap` that cannot produce
|
|
59
|
+
a valid URL should not exist, and you should learn about a typo at the line
|
|
60
|
+
that wrote it rather than at the first request. Anything that is not an
|
|
61
|
+
absolute `http(s)` URL throws `InvalidBaseUrlError`.
|
|
81
62
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
63
|
+
### `add(entry)` / `addMany(entries)`
|
|
64
|
+
|
|
65
|
+
Only `path` is required, and it must be a **concrete path** — `/posts/123`, not
|
|
66
|
+
`/posts/:id`. A pattern is not a URL.
|
|
67
|
+
|
|
68
|
+
| Field | Meaning |
|
|
69
|
+
| --- | --- |
|
|
70
|
+
| `path` | **Required.** Resolved against `baseUrl`. An absolute URL is used as given. |
|
|
71
|
+
| `name` | Optional label for the route, for your own diagnostics. |
|
|
72
|
+
| `route` | Optional pattern this URL came from, e.g. `/posts/:id`. |
|
|
73
|
+
| `lastmod` | `Date` (serialised as W3C datetime) or a string (passed through untouched). |
|
|
74
|
+
| `changefreq` | One of the seven protocol values. |
|
|
75
|
+
| `priority` | `0.0`–`1.0`. Anything else throws. |
|
|
76
|
+
| `alternates` | Language versions of this page — see below. |
|
|
77
|
+
|
|
78
|
+
Both return `this`, so they chain.
|
|
79
|
+
|
|
80
|
+
**Adding the same path twice keeps the later entry, silently.** Entries are
|
|
81
|
+
stored keyed by path, because a duplicate `<loc>` makes the document invalid
|
|
82
|
+
and two loops legitimately covering an overlapping set is the normal cause. It
|
|
83
|
+
is silent, not hidden — see `duplicates()`.
|
|
85
84
|
|
|
86
|
-
|
|
85
|
+
### `entries()` / `size`
|
|
86
|
+
|
|
87
|
+
What will actually be emitted, with defaults already folded in. `entries()`
|
|
88
|
+
hands back a copy.
|
|
89
|
+
|
|
90
|
+
### `routes()` — the diagnostic
|
|
87
91
|
|
|
88
92
|
```ts
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
path: "/sitemap.xml",
|
|
92
|
-
defaults: { changefreq: "weekly", priority: 0.5 },
|
|
93
|
-
};
|
|
93
|
+
sitemap.routes();
|
|
94
|
+
// [ { route: "/posts/:id", count: 400 }, { route: "/products/:slug", count: 0 } ]
|
|
94
95
|
```
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
Only a dynamic route needs a page-level `sitemap` export; a static route is
|
|
101
|
-
included automatically at its own path.
|
|
97
|
+
**The interesting row is the zero.** It means a route you expected to
|
|
98
|
+
contribute URLs contributed none, and a whole section of your site is missing
|
|
99
|
+
from a document that otherwise looks perfect. Use `declareRoute()` to name a
|
|
100
|
+
pattern you expect to produce URLs:
|
|
102
101
|
|
|
103
102
|
```ts
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
];
|
|
103
|
+
sitemap.declareRoute("/products/:slug");
|
|
104
|
+
|
|
105
|
+
const empty = sitemap.routes().filter((route) => route.count === 0);
|
|
108
106
|
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
if (empty.length > 0) {
|
|
108
|
+
throw new Error(`empty sitemap routes: ${empty.map((route) => route.route).join(", ")}`);
|
|
109
|
+
}
|
|
111
110
|
```
|
|
112
111
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
nothing outside a sitemap.
|
|
112
|
+
**This package reports; it never prints.** Whether a zero is a warning or a
|
|
113
|
+
build failure is your decision, not ours.
|
|
116
114
|
|
|
117
|
-
|
|
118
|
-
generated XML if nobody is watching.** In development this package reports it
|
|
119
|
-
instead: a dynamic route cannot be enumerated without application data, and
|
|
120
|
-
the framework's whole job here is to make sure you find out, rather than
|
|
121
|
-
shipping a sitemap that looks complete while it quietly drops every product
|
|
122
|
-
page on the site.
|
|
115
|
+
### `duplicates()`
|
|
123
116
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
117
|
+
```ts
|
|
118
|
+
sitemap.duplicates();
|
|
119
|
+
// [ { path: "/posts/1", count: 2, routes: ["/posts/:id", "/:slug"] } ]
|
|
120
|
+
```
|
|
127
121
|
|
|
128
|
-
|
|
122
|
+
Every path that was added more than once, and the `route` of each add — so a
|
|
123
|
+
collision between two sources is nameable. Never throws.
|
|
129
124
|
|
|
130
|
-
|
|
131
|
-
| --- | --- |
|
|
132
|
-
| `enabled` | no-op when not `true` — the connector registers no route |
|
|
133
|
-
| `path` | defaults to `/sitemap.xml` |
|
|
134
|
-
| `defaults.changefreq` / `defaults.priority` | applied to any entry that omits them, page-derived or app-supplied |
|
|
125
|
+
### `toXML()`
|
|
135
126
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
level up in `@warlock.js/core`, because canonical links, OG tags and absolute
|
|
139
|
-
mail URLs need the same value. If the sitemap is `enabled` and no origin is
|
|
140
|
-
configured, the app refuses to boot rather than guess — a sitemap served with
|
|
141
|
-
the wrong host is worse than one that never started.
|
|
127
|
+
Pure and repeatable: calling it twice returns the same string, and it mutates
|
|
128
|
+
nothing. It is **synchronous and stays synchronous** — there is no I/O in it.
|
|
142
129
|
|
|
143
|
-
|
|
130
|
+
`Sitemap` structurally satisfies `@warlock.js/core`'s `XMLable` contract
|
|
131
|
+
(`toXML(): string`), so a Warlock controller can `return response.xml(sitemap)`
|
|
132
|
+
directly — this package still depends on nothing from core to make that true.
|
|
133
|
+
That path is for a single `Sitemap` under the sitemaps.org 50,000-URL / 50MB
|
|
134
|
+
ceiling. `SitemapIndex` has no `toXML()` and is never passed to `response.xml()`;
|
|
135
|
+
see [Very large sites](#very-large-sites) below for how its output is served instead.
|
|
144
136
|
|
|
145
|
-
|
|
146
|
-
| --- | --- |
|
|
147
|
-
| static route | included |
|
|
148
|
-
| not-found route | excluded |
|
|
149
|
-
| error page | excluded — it isn't a routable page at all |
|
|
150
|
-
| page whose `metadata.robots` says `noindex` | excluded |
|
|
151
|
-
| page exporting `sitemap: false` | excluded |
|
|
152
|
-
| dynamic route (`[id]`, `[...slug]`) **with** a `sitemap` export | the entries that export returns |
|
|
153
|
-
| dynamic route **without** a `sitemap` export | **omitted, and named in a dev-mode diagnostic** |
|
|
154
|
-
| `sitemapConnector({ entries })` result | added to the above, `entries` wins on a `path` collision |
|
|
155
|
-
|
|
156
|
-
## No page registry, no `entries`
|
|
157
|
-
|
|
158
|
-
If `@warlock.js/web` is not installed and no `entries` option is supplied,
|
|
159
|
-
`sitemapConnector()` throws `NoPageRegistryError` at `boot()` — before the
|
|
160
|
-
route is even registered — rather than serving an empty sitemap that looks
|
|
161
|
-
correct. Fix it either way:
|
|
137
|
+
### `saveTo(filePath)`
|
|
162
138
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
so there is no page registry to read, and no `entries` option was supplied either.
|
|
166
|
-
Fix this by installing `@warlock.js/web`, or by passing
|
|
167
|
-
`sitemapConnector({ entries: async () => [...] })` with your own supplier.
|
|
168
|
-
```
|
|
139
|
+
Writes the document, creating parent directories. Works on a clean checkout
|
|
140
|
+
with no `dist/`.
|
|
169
141
|
|
|
170
|
-
|
|
142
|
+
### `publishTo(outDir, fileName = "sitemap.xml")`
|
|
171
143
|
|
|
172
|
-
|
|
173
|
-
|
|
144
|
+
Publishes the document as the whole content of `outDir`, the same way
|
|
145
|
+
`SitemapIndex.saveTo(outDir)` publishes a set: swapped in atomically and marked
|
|
146
|
+
as owned (see below). Use it when the sitemap may later grow into an index: an
|
|
147
|
+
index can then be published into the same directory, and publishing a single
|
|
148
|
+
file again clears out old shards. Returns the published file's path.
|
|
174
149
|
|
|
175
|
-
##
|
|
150
|
+
## Language alternates
|
|
176
151
|
|
|
177
|
-
|
|
152
|
+
`alternates` emits `<xhtml:link rel="alternate" hreflang="…">` inside each
|
|
153
|
+
`<url>` — the thing search engines actually consume to learn that two URLs are
|
|
154
|
+
one page in two languages.
|
|
178
155
|
|
|
179
|
-
```
|
|
180
|
-
|
|
156
|
+
```ts
|
|
157
|
+
const alternates = [
|
|
158
|
+
{ hreflang: "en", path: "/en/about" },
|
|
159
|
+
{ hreflang: "ar", path: "/ar/about-us" },
|
|
160
|
+
{ hreflang: "x-default", path: "/en/about" },
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
sitemap.add({ path: "/en/about", alternates });
|
|
164
|
+
sitemap.add({ path: "/ar/about-us", alternates });
|
|
181
165
|
```
|
|
182
166
|
|
|
183
|
-
|
|
167
|
+
Two rules worth knowing:
|
|
168
|
+
|
|
169
|
+
1. **Every language version is also its own `<url>`, carrying the complete
|
|
170
|
+
alternate set including itself.** Listing alternates on only one of them is
|
|
171
|
+
the usual way this gets shipped broken.
|
|
172
|
+
2. **This package does not know what a locale is.** `hreflang` is any string —
|
|
173
|
+
`en`, `en-GB`, `x-default` — and it never derives `/{locale}/…` for you. You
|
|
174
|
+
supply each path explicitly, which is the only thing that works when slugs
|
|
175
|
+
diverge between languages.
|
|
176
|
+
|
|
177
|
+
The `xhtml` namespace is declared only when something actually uses it.
|
|
178
|
+
|
|
179
|
+
## Very large sites
|
|
180
|
+
|
|
181
|
+
The protocol caps one file at **50,000 URLs or 50MB uncompressed**. `Sitemap`
|
|
182
|
+
retains every entry — that is what makes `entries()` and a repeatable
|
|
183
|
+
`toXML()` possible — so it is the right tool up to that ceiling and the wrong
|
|
184
|
+
one above it. `SitemapIndex` is the streaming writer for sites past it: it
|
|
185
|
+
emits shards plus a flat master index and retains nothing but the current
|
|
186
|
+
shard's buffer.
|
|
187
|
+
|
|
188
|
+
`alternates` works the same way across a shard boundary — each `<xhtml:link>`
|
|
189
|
+
resolves to an absolute URL, so it is invisible to where one shard ends and
|
|
190
|
+
the next begins. Each shard declares `xmlns:xhtml` only when its own entries
|
|
191
|
+
carry alternates, and an alternate's bytes count toward that shard's byte
|
|
192
|
+
ceiling exactly like the rest of its `<url>` block.
|
|
193
|
+
|
|
194
|
+
`maxBytesPerFile` is enforced at shard boundaries, not within an entry: a
|
|
195
|
+
single entry (with its alternates) larger than the ceiling is written alone
|
|
196
|
+
in its own shard rather than split, since an entry can't be split.
|
|
197
|
+
|
|
198
|
+
### `saveTo(outDir)` owns the directory it is given
|
|
199
|
+
|
|
200
|
+
`SitemapIndex.saveTo(outDir)` publishes atomically: it writes the full set
|
|
201
|
+
into a sibling temp directory, then swaps it into `outDir` in one `rename` —
|
|
202
|
+
a crawler never sees a partial set, and a failed run leaves the previous set
|
|
203
|
+
untouched.
|
|
204
|
+
|
|
205
|
+
That swap replaces the ENTIRE contents of `outDir`, so `outDir` must be a
|
|
206
|
+
directory **dedicated to this sitemap set** — never an app's `public/` or
|
|
207
|
+
any other directory something else writes to. Every successful publish marks
|
|
208
|
+
`outDir` with `.sitemap-set.json`; a later `saveTo()` call only swaps a
|
|
209
|
+
directory that either does not exist yet, is empty, or already carries that
|
|
210
|
+
marker. If `outDir` exists, is non-empty, and has no marker,
|
|
211
|
+
`saveTo()` throws `UnownedOutputDirectoryError` and leaves the directory
|
|
212
|
+
completely untouched. Point `saveTo()` at a directory this package alone
|
|
213
|
+
writes to. `Sitemap.publishTo(outDir)` follows the same rule.
|
|
214
|
+
|
|
215
|
+
## Errors
|
|
216
|
+
|
|
217
|
+
| Error | When |
|
|
218
|
+
| --- | --- |
|
|
219
|
+
| `InvalidBaseUrlError` | `baseUrl` is missing, relative, or not `http(s)`. Thrown from the constructor. |
|
|
220
|
+
| `InvalidSitemapEntryError` | An entry the protocol cannot represent: no path, a priority outside `0.0`–`1.0`, an unknown `changefreq`, an invalid `Date`, an alternate with no `hreflang`. |
|
|
221
|
+
| `UnownedOutputDirectoryError` | `SitemapIndex.saveTo(outDir)` or `Sitemap.publishTo(outDir)`: `outDir` is a non-empty directory with no `.sitemap-set.json` marker from a previous publish, so it is refused rather than swapped or deleted. |
|
|
222
|
+
|
|
223
|
+
## Also exported
|
|
184
224
|
|
|
185
|
-
|
|
225
|
+
`buildSitemapXml(entries, baseUrl)`, `escapeXml(value)` and
|
|
226
|
+
`joinOrigin(origin, path)` — the pieces `Sitemap` is built from, for when you
|
|
227
|
+
want the serialiser without the builder.
|