@canopy-iiif/app 1.2.1 → 1.2.3
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/lib/build/build.js +15 -0
- package/lib/build/sitemap.js +75 -0
- package/package.json +1 -1
package/lib/build/build.js
CHANGED
|
@@ -12,6 +12,7 @@ const pages = require("./pages");
|
|
|
12
12
|
const searchBuild = require("./search");
|
|
13
13
|
const { buildSearchIndex } = require("./search-index");
|
|
14
14
|
const runtimes = require("./runtimes");
|
|
15
|
+
const { writeSitemap } = require("./sitemap");
|
|
15
16
|
const {
|
|
16
17
|
ensureSearchInitialized,
|
|
17
18
|
finalizeSearch,
|
|
@@ -112,6 +113,20 @@ async function build(options = {}) {
|
|
|
112
113
|
logLine(" " + String(e), "red");
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Generate a sitemap so static hosts can discover every rendered page.
|
|
118
|
+
*/
|
|
119
|
+
logLine("\nWrite sitemap", "magenta", {
|
|
120
|
+
bright: true,
|
|
121
|
+
underscore: true,
|
|
122
|
+
});
|
|
123
|
+
try {
|
|
124
|
+
await writeSitemap(iiifRecords, pageRecords);
|
|
125
|
+
} catch (e) {
|
|
126
|
+
logLine("✗ Failed to write sitemap.xml", "red", { bright: true });
|
|
127
|
+
logLine(" " + String(e), "red");
|
|
128
|
+
}
|
|
129
|
+
|
|
115
130
|
// No-op: Featured API file no longer written (SSR reads from cache directly)
|
|
116
131
|
|
|
117
132
|
/**
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const { fsp, path, OUT_DIR, absoluteUrl, rootRelativeHref } = require('../common');
|
|
2
|
+
const { logLine } = require('./log');
|
|
3
|
+
|
|
4
|
+
const DEFAULT_CHANGEFREQ = 'monthly';
|
|
5
|
+
const DEFAULT_PRIORITY = '0.5';
|
|
6
|
+
|
|
7
|
+
function escapeXml(value) {
|
|
8
|
+
return String(value || '')
|
|
9
|
+
.replace(/&/g, '&')
|
|
10
|
+
.replace(/</g, '<')
|
|
11
|
+
.replace(/>/g, '>')
|
|
12
|
+
.replace(/"/g, '"')
|
|
13
|
+
.replace(/'/g, ''');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function normalizeHref(href) {
|
|
17
|
+
if (!href && href !== 0) return '';
|
|
18
|
+
const rel = rootRelativeHref(href);
|
|
19
|
+
if (!rel || rel === '#') return '';
|
|
20
|
+
if (rel.startsWith('?') || rel.startsWith('#')) return '';
|
|
21
|
+
return rel;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function collectAbsoluteUrls(iiifRecords, pageRecords) {
|
|
25
|
+
const urls = new Set();
|
|
26
|
+
const push = (href) => {
|
|
27
|
+
const rel = normalizeHref(href);
|
|
28
|
+
if (!rel) return;
|
|
29
|
+
try {
|
|
30
|
+
const abs = absoluteUrl(rel);
|
|
31
|
+
if (abs) urls.add(abs);
|
|
32
|
+
} catch (_) {}
|
|
33
|
+
};
|
|
34
|
+
(Array.isArray(pageRecords) ? pageRecords : []).forEach((page) => {
|
|
35
|
+
if (!page || !page.href) return;
|
|
36
|
+
push(page.href);
|
|
37
|
+
});
|
|
38
|
+
(Array.isArray(iiifRecords) ? iiifRecords : []).forEach((record) => {
|
|
39
|
+
if (!record || !record.href) return;
|
|
40
|
+
push(record.href);
|
|
41
|
+
});
|
|
42
|
+
// Ensure the search page is always present even though it is generated separately
|
|
43
|
+
push('/search.html');
|
|
44
|
+
return Array.from(urls.values()).sort((a, b) => a.localeCompare(b));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function writeSitemap(iiifRecords, pageRecords) {
|
|
48
|
+
const urls = collectAbsoluteUrls(iiifRecords, pageRecords);
|
|
49
|
+
if (!urls.length) {
|
|
50
|
+
logLine('• No URLs to write to sitemap', 'yellow');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const rows = urls.map((loc) => {
|
|
54
|
+
const escapedLoc = escapeXml(loc);
|
|
55
|
+
return [
|
|
56
|
+
' <url>',
|
|
57
|
+
` <loc>${escapedLoc}</loc>`,
|
|
58
|
+
` <changefreq>${DEFAULT_CHANGEFREQ}</changefreq>`,
|
|
59
|
+
` <priority>${DEFAULT_PRIORITY}</priority>`,
|
|
60
|
+
' </url>',
|
|
61
|
+
].join('\n');
|
|
62
|
+
});
|
|
63
|
+
const xml = [
|
|
64
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
65
|
+
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
66
|
+
rows.join('\n'),
|
|
67
|
+
'</urlset>',
|
|
68
|
+
'',
|
|
69
|
+
].join('\n');
|
|
70
|
+
const dest = path.join(OUT_DIR, 'sitemap.xml');
|
|
71
|
+
await fsp.writeFile(dest, xml, 'utf8');
|
|
72
|
+
logLine(`✓ Wrote sitemap.xml (${urls.length} urls)`, 'cyan');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = { writeSitemap };
|