@iterant/site-runtime 3.11.0 → 3.11.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/docs/runtime-contract.md
CHANGED
|
@@ -50,7 +50,7 @@ runtime and says so.
|
|
|
50
50
|
|
|
51
51
|
<!-- generated: available libraries -->
|
|
52
52
|
|
|
53
|
-
_Generated from package.json by scripts/generate-kit-table.mjs. Runtime 3.11.
|
|
53
|
+
_Generated from package.json by scripts/generate-kit-table.mjs. Runtime 3.11.1._
|
|
54
54
|
|
|
55
55
|
**Toolchain** (this package owns the version; do NOT declare these):
|
|
56
56
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iterant/site-runtime",
|
|
3
|
-
"version": "3.11.
|
|
3
|
+
"version": "3.11.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The platform layer every Iterant brand site runs on: content grammar, collection schemas, SEO head and JSON-LD, layout core, Astro config preset, dev integrations and the verify gates.",
|
|
6
6
|
"scripts": {
|
|
@@ -33,11 +33,15 @@ function resolvePagesDir({ pagesDir, root }: SitemapPathsOptions): string {
|
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Every advertised page entry's route (neither draft nor noindex), home
|
|
36
|
-
* excluded (@astrojs/sitemap already emits the site root)
|
|
36
|
+
* excluded (@astrojs/sitemap already emits the site root), beside `deny`: the
|
|
37
|
+
* routes of the entries that are NOT advertised. The integration crawls the
|
|
38
|
+
* prerendered pages itself and would list those a second way, so the caller
|
|
39
|
+
* drops them through its filter. Returns `pagesDir` so a caller can report
|
|
37
40
|
* WHERE it looked when the answer is empty.
|
|
38
41
|
*/
|
|
39
42
|
export function getSitemapPaths(options: SitemapPathsOptions = {}): {
|
|
40
43
|
paths: string[];
|
|
44
|
+
deny: string[];
|
|
41
45
|
entryCount: number;
|
|
42
46
|
pagesDir: string;
|
|
43
47
|
} {
|
|
@@ -46,22 +50,24 @@ export function getSitemapPaths(options: SitemapPathsOptions = {}): {
|
|
|
46
50
|
try {
|
|
47
51
|
entries = readdirSync(pagesDir, { recursive: true }) as string[];
|
|
48
52
|
} catch {
|
|
49
|
-
return { paths: [], pagesDir, entryCount: 0 }; // no page entries yet
|
|
53
|
+
return { paths: [], deny: [], pagesDir, entryCount: 0 }; // no page entries yet
|
|
50
54
|
}
|
|
51
55
|
const jsonEntries = entries.filter((entry) => entry.endsWith(".json"));
|
|
52
56
|
const entryCount = jsonEntries.length;
|
|
53
|
-
const paths =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
57
|
+
const paths: string[] = [];
|
|
58
|
+
const deny: string[] = [];
|
|
59
|
+
for (const rel of jsonEntries) {
|
|
60
|
+
try {
|
|
61
|
+
const data = JSON.parse(readFileSync(join(pagesDir, rel), "utf8"));
|
|
62
|
+
if (typeof data.route !== "string") continue;
|
|
63
|
+
if (!isAdvertised(data, { includeDrafts: false })) {
|
|
64
|
+
deny.push(data.route as string);
|
|
65
|
+
} else if (data.route !== "/") {
|
|
66
|
+
paths.push(data.route as string);
|
|
63
67
|
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
} catch {
|
|
69
|
+
// malformed entry; the build will surface the schema error
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return { paths, deny, pagesDir, entryCount };
|
|
67
73
|
}
|
|
@@ -14,11 +14,16 @@ const PLACEHOLDER = "https://starter.invalid";
|
|
|
14
14
|
// names them here.
|
|
15
15
|
const PLATFORM_DENY = new Set(["/under-construction"]);
|
|
16
16
|
|
|
17
|
-
/** Whether a sitemap URL may be listed:
|
|
18
|
-
|
|
17
|
+
/** Whether a sitemap URL may be listed: neither a platform route nor a denied
|
|
18
|
+
* entry route (a draft or a noindex page), whichever way the integration
|
|
19
|
+
* found it. */
|
|
20
|
+
export function sitemapPageAllowed(
|
|
21
|
+
url: string,
|
|
22
|
+
deny: ReadonlySet<string> = new Set(),
|
|
23
|
+
): boolean {
|
|
19
24
|
try {
|
|
20
25
|
const pathname = new URL(url).pathname.replace(/\/+$/, "") || "/";
|
|
21
|
-
return !PLATFORM_DENY.has(pathname);
|
|
26
|
+
return !PLATFORM_DENY.has(pathname) && !deny.has(pathname);
|
|
22
27
|
} catch {
|
|
23
28
|
return true;
|
|
24
29
|
}
|
|
@@ -41,6 +46,9 @@ export function sitemapWithCustomPages(
|
|
|
41
46
|
// This integration is ordered ahead of @astrojs/sitemap, so the array is
|
|
42
47
|
// populated before anything reads it.
|
|
43
48
|
const customPages: string[] = [...(sitemapOptions.customPages ?? [])];
|
|
49
|
+
// Filled beside customPages: the entry routes the integration must not list
|
|
50
|
+
// from its own crawl of prerendered pages.
|
|
51
|
+
const denied = new Set<string>();
|
|
44
52
|
|
|
45
53
|
return [
|
|
46
54
|
{
|
|
@@ -49,6 +57,7 @@ export function sitemapWithCustomPages(
|
|
|
49
57
|
"astro:config:setup": ({ config, logger }) => {
|
|
50
58
|
const {
|
|
51
59
|
paths,
|
|
60
|
+
deny,
|
|
52
61
|
pagesDir: searched,
|
|
53
62
|
entryCount,
|
|
54
63
|
} = getSitemapPaths({
|
|
@@ -68,6 +77,9 @@ export function sitemapWithCustomPages(
|
|
|
68
77
|
`page entries in ${searched} are all drafts or the site root; the sitemap lists no SSR routes yet`,
|
|
69
78
|
);
|
|
70
79
|
}
|
|
80
|
+
for (const path of deny) {
|
|
81
|
+
denied.add(path.replace(/\/+$/, "") || "/");
|
|
82
|
+
}
|
|
71
83
|
for (const path of paths) {
|
|
72
84
|
customPages.push(
|
|
73
85
|
`${PLACEHOLDER}${path.startsWith("/") ? path : `/${path}`}`,
|
|
@@ -85,7 +97,8 @@ export function sitemapWithCustomPages(
|
|
|
85
97
|
...sitemapOptions,
|
|
86
98
|
customPages,
|
|
87
99
|
filter: (page) =>
|
|
88
|
-
sitemapPageAllowed(page) &&
|
|
100
|
+
sitemapPageAllowed(page, denied) &&
|
|
101
|
+
(userFilter ? userFilter(page) : true),
|
|
89
102
|
serialize(item) {
|
|
90
103
|
if (resolvedSite && item.url.startsWith(PLACEHOLDER)) {
|
|
91
104
|
item.url = resolvedSite + item.url.slice(PLACEHOLDER.length);
|