@canopy-iiif/app 0.7.0 → 0.7.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/lib/build/build.js +37 -93
- package/lib/build/dev.js +493 -204
- package/lib/build/iiif.js +26 -17
- package/lib/build/log.js +19 -52
- package/lib/build/search-workflow.js +61 -0
- package/lib/build/styles.js +82 -40
- package/package.json +2 -1
package/lib/build/build.js
CHANGED
|
@@ -9,11 +9,13 @@ const {
|
|
|
9
9
|
const mdx = require("./mdx");
|
|
10
10
|
const iiif = require("./iiif");
|
|
11
11
|
const pages = require("./pages");
|
|
12
|
-
const search = require("../search/search");
|
|
13
12
|
const searchBuild = require("./search");
|
|
14
13
|
const { buildSearchIndex } = require("./search-index");
|
|
15
|
-
const { generateFacets } = require("./facets");
|
|
16
14
|
const runtimes = require("./runtimes");
|
|
15
|
+
const {
|
|
16
|
+
ensureSearchInitialized,
|
|
17
|
+
finalizeSearch,
|
|
18
|
+
} = require("./search-workflow");
|
|
17
19
|
const { ensureStyles } = require("./styles");
|
|
18
20
|
const { copyAssets } = require("./assets");
|
|
19
21
|
const { logLine } = require("./log");
|
|
@@ -23,7 +25,7 @@ let iiifRecordsCache = [];
|
|
|
23
25
|
let pageRecords = [];
|
|
24
26
|
|
|
25
27
|
async function build(options = {}) {
|
|
26
|
-
const skipIiif = !!options?.skipIiif;
|
|
28
|
+
const skipIiif = !!(options?.skipIiif || process.env.CANOPY_SKIP_IIIF === '1' || process.env.CANOPY_SKIP_IIIF === 'true');
|
|
27
29
|
if (!fs.existsSync(CONTENT_DIR)) {
|
|
28
30
|
console.error("No content directory found at", CONTENT_DIR);
|
|
29
31
|
process.exit(1);
|
|
@@ -32,15 +34,17 @@ async function build(options = {}) {
|
|
|
32
34
|
/**
|
|
33
35
|
* Clean and prepare output directory
|
|
34
36
|
*/
|
|
35
|
-
logLine("\
|
|
37
|
+
logLine("\nClean and prepare directories", "magenta", {
|
|
36
38
|
bright: true,
|
|
39
|
+
underscore: true,
|
|
37
40
|
});
|
|
41
|
+
logLine("• Reset MDX cache", "blue", { dim: true });
|
|
38
42
|
mdx?.resetMdxCaches();
|
|
39
43
|
if (!skipIiif) {
|
|
40
44
|
await cleanDir(OUT_DIR);
|
|
41
|
-
logLine(
|
|
45
|
+
logLine(`• Cleaned output directory`, "blue", { dim: true });
|
|
42
46
|
} else {
|
|
43
|
-
logLine("•
|
|
47
|
+
logLine("• Retaining cache (skipping IIIF rebuild)", "blue", { dim: true });
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
/**
|
|
@@ -48,19 +52,15 @@ async function build(options = {}) {
|
|
|
48
52
|
* This includes building IIIF manifests for works and collections,
|
|
49
53
|
* as well as collecting search records for works.
|
|
50
54
|
*/
|
|
51
|
-
logLine("\
|
|
55
|
+
logLine("\nBuild IIIF Collection content", "magenta", {
|
|
52
56
|
bright: true,
|
|
57
|
+
underscore: true,
|
|
53
58
|
});
|
|
54
|
-
let
|
|
59
|
+
let iiifRecords = [];
|
|
55
60
|
if (!skipIiif) {
|
|
56
61
|
const CONFIG = await iiif.loadConfig();
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
? res.searchRecords
|
|
60
|
-
: [];
|
|
61
|
-
iiifRecordsCache = searchRecords;
|
|
62
|
-
} else {
|
|
63
|
-
searchRecords = Array.isArray(iiifRecordsCache) ? iiifRecordsCache : [];
|
|
62
|
+
const results = await iiif.buildIiifCollectionPages(CONFIG);
|
|
63
|
+
iiifRecords = results?.iiifRecords;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
@@ -68,109 +68,53 @@ async function build(options = {}) {
|
|
|
68
68
|
* This includes collecting page metadata for sitemap and search index,
|
|
69
69
|
* as well as building all MDX pages to HTML.
|
|
70
70
|
*/
|
|
71
|
-
logLine("\
|
|
71
|
+
logLine("\nBuild contextual content from Markdown pages", "magenta", {
|
|
72
72
|
bright: true,
|
|
73
|
+
underscore: true,
|
|
73
74
|
});
|
|
74
|
-
// Collect pages metadata for sitemap injection
|
|
75
75
|
pageRecords = await searchBuild.collectMdxPageRecords();
|
|
76
|
-
// Build all MDX and assets
|
|
77
|
-
logLine("\n• Building MDX pages...", "blue", { bright: true });
|
|
78
76
|
await pages.buildContentTree(CONTENT_DIR, pageRecords);
|
|
79
|
-
logLine("✓ MDX pages built
|
|
77
|
+
logLine("✓ MDX pages built", "green");
|
|
80
78
|
|
|
81
79
|
/**
|
|
82
80
|
* Build search index from IIIF and MDX records, then build or update
|
|
83
81
|
* the search.html page and search runtime bundle.
|
|
84
82
|
* This is done after all content is built so that the index is comprehensive.
|
|
85
83
|
*/
|
|
86
|
-
logLine("\
|
|
84
|
+
logLine("\nCreate search indices", "magenta", {
|
|
85
|
+
bright: true,
|
|
86
|
+
underscore: true,
|
|
87
|
+
});
|
|
87
88
|
try {
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
try {
|
|
96
|
-
await search.ensureResultTemplate();
|
|
97
|
-
} catch (_) {}
|
|
98
|
-
try {
|
|
99
|
-
logLine(" - Writing empty index...", "blue");
|
|
100
|
-
} catch (_) {}
|
|
101
|
-
await search.writeSearchIndex([]);
|
|
102
|
-
try {
|
|
103
|
-
logLine(" - Writing runtime...", "blue");
|
|
104
|
-
} catch (_) {}
|
|
105
|
-
const timeoutMs = Number(process.env.CANOPY_BUNDLE_TIMEOUT || 10000);
|
|
106
|
-
let timedOut = false;
|
|
107
|
-
await runtimes.prepareSearchRuntime(
|
|
108
|
-
process.env.CANOPY_BUNDLE_TIMEOUT || 10000,
|
|
109
|
-
"initial"
|
|
110
|
-
);
|
|
111
|
-
try {
|
|
112
|
-
logLine(" - Building search.html...", "blue");
|
|
113
|
-
} catch (_) {}
|
|
114
|
-
await search.buildSearchPage();
|
|
115
|
-
logLine("✓ Created search page", "cyan");
|
|
116
|
-
}
|
|
117
|
-
// Always (re)write the search index combining IIIF and MDX pages
|
|
118
|
-
const combined = await buildSearchIndex(searchRecords, pageRecords);
|
|
119
|
-
// Build facets for IIIF works based on configured metadata labels
|
|
120
|
-
await generateFacets(combined);
|
|
121
|
-
try {
|
|
122
|
-
logLine("• Writing search runtime (final)...", "blue", { bright: true });
|
|
123
|
-
} catch (_) {}
|
|
124
|
-
await runtimes.prepareSearchRuntime(
|
|
125
|
-
process.env.CANOPY_BUNDLE_TIMEOUT || 10000,
|
|
126
|
-
"final"
|
|
127
|
-
);
|
|
128
|
-
// Rebuild result item template after content processing to capture latest
|
|
129
|
-
try {
|
|
130
|
-
await search.ensureResultTemplate();
|
|
131
|
-
} catch (_) {}
|
|
132
|
-
// Rebuild search.html to inline the latest result template
|
|
133
|
-
try {
|
|
134
|
-
logLine("• Updating search.html...", "blue");
|
|
135
|
-
} catch (_) {}
|
|
136
|
-
await search.buildSearchPage();
|
|
137
|
-
try {
|
|
138
|
-
logLine("✓ Search page updated", "cyan");
|
|
139
|
-
} catch (_) {}
|
|
140
|
-
// Itemize counts by type for a clearer summary
|
|
141
|
-
const counts = new Map();
|
|
142
|
-
for (const r of combined) {
|
|
143
|
-
const t = String((r && r.type) || "page").toLowerCase();
|
|
144
|
-
counts.set(t, (counts.get(t) || 0) + 1);
|
|
145
|
-
}
|
|
146
|
-
const parts = Array.from(counts.entries())
|
|
147
|
-
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
|
|
148
|
-
.map(([t, n]) => `${t}: ${n}`);
|
|
149
|
-
const breakdown = parts.length ? `: ${parts.join(", ")}` : "";
|
|
150
|
-
logLine(
|
|
151
|
-
`✓ Search index: ${combined.length} total records${breakdown}`,
|
|
152
|
-
"cyan"
|
|
153
|
-
);
|
|
154
|
-
} catch (_) {}
|
|
89
|
+
await ensureSearchInitialized();
|
|
90
|
+
const combined = await buildSearchIndex(iiifRecords, pageRecords);
|
|
91
|
+
await finalizeSearch(combined);
|
|
92
|
+
} catch (e) {
|
|
93
|
+
logLine("✗ Search index creation failed", "red", { bright: true });
|
|
94
|
+
logLine(" " + String(e), "red");
|
|
95
|
+
}
|
|
155
96
|
|
|
156
97
|
/**
|
|
157
98
|
* Prepare client runtimes (e.g. search) by bundling with esbuild.
|
|
158
99
|
* This is done early so that MDX content can reference runtime assets if needed.
|
|
159
100
|
*/
|
|
160
|
-
logLine("\
|
|
101
|
+
logLine("\nPrepare client runtimes and stylesheets", "magenta", {
|
|
161
102
|
bright: true,
|
|
103
|
+
underscore: true,
|
|
162
104
|
});
|
|
163
|
-
await runtimes.prepareAllRuntimes();
|
|
164
|
-
ensureDirSync(path.join(OUT_DIR, "styles"));
|
|
165
105
|
if (!process.env.CANOPY_SKIP_STYLES) {
|
|
166
106
|
await ensureStyles();
|
|
167
|
-
logLine("✓ Wrote styles.css
|
|
107
|
+
logLine("✓ Wrote styles.css", "cyan");
|
|
168
108
|
}
|
|
109
|
+
await runtimes.prepareAllRuntimes();
|
|
169
110
|
|
|
170
111
|
/**
|
|
171
112
|
* Copy static assets from the assets directory to the output directory.
|
|
172
113
|
*/
|
|
173
|
-
logLine("\
|
|
114
|
+
logLine("\nCopy static assets", "magenta", {
|
|
115
|
+
bright: true,
|
|
116
|
+
underscore: true,
|
|
117
|
+
});
|
|
174
118
|
await copyAssets();
|
|
175
119
|
}
|
|
176
120
|
|