@canopy-iiif/app 0.10.24 → 0.10.27
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/mdx.js +366 -182
- package/lib/page-context.js +15 -5
- package/package.json +1 -1
- package/ui/dist/index.mjs +126 -7
- package/ui/dist/index.mjs.map +4 -4
- package/ui/dist/server.mjs +71 -4
- package/ui/dist/server.mjs.map +4 -4
- package/ui/styles/components/_card.scss +0 -1
- package/ui/styles/components/_diagram.scss +75 -0
- package/ui/styles/components/header/_navbar.scss +55 -0
- package/ui/styles/components/iiif/_image.scss +31 -1
- package/ui/styles/components/iiif/_slider.scss +91 -0
- package/ui/styles/components/iiif/index.scss +1 -0
- package/ui/styles/components/index.scss +1 -0
- package/ui/styles/components/search/_tabs.scss +36 -0
- package/ui/styles/components/search/index.scss +4 -3
- package/ui/styles/index.css +236 -1
package/lib/build/mdx.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const React = require("react");
|
|
2
2
|
const ReactDOMServer = require("react-dom/server");
|
|
3
|
-
const {
|
|
3
|
+
const {pathToFileURL} = require("url");
|
|
4
4
|
const {
|
|
5
5
|
fs,
|
|
6
6
|
fsp,
|
|
@@ -22,7 +22,10 @@ try {
|
|
|
22
22
|
|
|
23
23
|
const EXTRA_REMARK_PLUGINS = (() => {
|
|
24
24
|
try {
|
|
25
|
-
const absPath = path.resolve(
|
|
25
|
+
const absPath = path.resolve(
|
|
26
|
+
process.cwd(),
|
|
27
|
+
"packages/helpers/docs/remark-code-meta.js"
|
|
28
|
+
);
|
|
26
29
|
if (fs.existsSync(absPath)) {
|
|
27
30
|
const plugin = require(absPath);
|
|
28
31
|
if (typeof plugin === "function") return [plugin];
|
|
@@ -53,13 +56,13 @@ function buildCompileOptions(overrides = {}) {
|
|
|
53
56
|
base.remarkPlugins = remarkPlugins;
|
|
54
57
|
}
|
|
55
58
|
if (overrides && typeof overrides === "object") {
|
|
56
|
-
const {
|
|
59
|
+
const {remarkPlugins: _omit, ...rest} = overrides;
|
|
57
60
|
Object.assign(base, rest);
|
|
58
61
|
}
|
|
59
62
|
return base;
|
|
60
63
|
}
|
|
61
64
|
const yaml = require("js-yaml");
|
|
62
|
-
const {
|
|
65
|
+
const {getPageContext} = require("../page-context");
|
|
63
66
|
|
|
64
67
|
function parseFrontmatter(src) {
|
|
65
68
|
let input = String(src || "");
|
|
@@ -67,7 +70,7 @@ function parseFrontmatter(src) {
|
|
|
67
70
|
if (input.charCodeAt(0) === 0xfeff) input = input.slice(1);
|
|
68
71
|
// Allow a few leading blank lines before frontmatter
|
|
69
72
|
const m = input.match(/^(?:\s*\r?\n)*---\s*\r?\n([\s\S]*?)\r?\n---\s*\r?\n?/);
|
|
70
|
-
if (!m) return {
|
|
73
|
+
if (!m) return {data: null, content: input};
|
|
71
74
|
let data = null;
|
|
72
75
|
try {
|
|
73
76
|
data = yaml.load(m[1]) || null;
|
|
@@ -75,7 +78,7 @@ function parseFrontmatter(src) {
|
|
|
75
78
|
data = null;
|
|
76
79
|
}
|
|
77
80
|
const content = input.slice(m[0].length);
|
|
78
|
-
return {
|
|
81
|
+
return {data, content};
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
// ESM-only in v3; load dynamically from CJS
|
|
@@ -94,130 +97,201 @@ async function getMdxProvider() {
|
|
|
94
97
|
// Lazily load UI components from the workspace package and cache them.
|
|
95
98
|
// Re-import when the built UI server bundle changes on disk.
|
|
96
99
|
let UI_COMPONENTS = null;
|
|
97
|
-
let UI_COMPONENTS_PATH =
|
|
100
|
+
let UI_COMPONENTS_PATH = "";
|
|
98
101
|
let UI_COMPONENTS_MTIME = 0;
|
|
99
|
-
const DEBUG =
|
|
102
|
+
const DEBUG =
|
|
103
|
+
process.env.CANOPY_DEBUG === "1" || process.env.CANOPY_DEBUG === "true";
|
|
100
104
|
async function loadUiComponents() {
|
|
101
105
|
// Do not rely on a cached mapping; re-import each time to avoid transient races.
|
|
102
106
|
try {
|
|
103
107
|
// Prefer the workspace dist path during dev to avoid export-map resolution issues
|
|
104
108
|
let resolved = null;
|
|
105
109
|
try {
|
|
106
|
-
const wsDist = path.join(
|
|
110
|
+
const wsDist = path.join(
|
|
111
|
+
process.cwd(),
|
|
112
|
+
"packages",
|
|
113
|
+
"app",
|
|
114
|
+
"ui",
|
|
115
|
+
"dist",
|
|
116
|
+
"server.mjs"
|
|
117
|
+
);
|
|
107
118
|
if (fs.existsSync(wsDist)) resolved = wsDist;
|
|
108
119
|
} catch (_) {}
|
|
109
120
|
// Prefer explicit dist path to avoid export-map issues
|
|
110
121
|
if (!resolved) {
|
|
111
|
-
try {
|
|
112
|
-
|
|
122
|
+
try {
|
|
123
|
+
resolved = require.resolve("@canopy-iiif/app/ui/dist/server.mjs");
|
|
124
|
+
} catch (_) {
|
|
125
|
+
try {
|
|
126
|
+
resolved = require.resolve("@canopy-iiif/app/ui/server");
|
|
127
|
+
} catch (_) {
|
|
128
|
+
resolved = null;
|
|
129
|
+
}
|
|
113
130
|
}
|
|
114
131
|
}
|
|
115
132
|
// Determine current mtime for change detection
|
|
116
|
-
let currentPath = resolved ||
|
|
133
|
+
let currentPath = resolved || "";
|
|
117
134
|
let currentMtime = 0;
|
|
118
135
|
if (currentPath) {
|
|
119
|
-
try {
|
|
136
|
+
try {
|
|
137
|
+
const st = fs.statSync(currentPath);
|
|
138
|
+
currentMtime = Math.floor(st.mtimeMs || 0);
|
|
139
|
+
} catch (_) {
|
|
140
|
+
currentMtime = 0;
|
|
141
|
+
}
|
|
120
142
|
}
|
|
121
143
|
// If we have a cached module and the path/mtime have not changed, return cached
|
|
122
|
-
if (
|
|
144
|
+
if (
|
|
145
|
+
UI_COMPONENTS &&
|
|
146
|
+
UI_COMPONENTS_PATH === currentPath &&
|
|
147
|
+
UI_COMPONENTS_MTIME === currentMtime
|
|
148
|
+
) {
|
|
123
149
|
if (DEBUG) {
|
|
124
|
-
try {
|
|
150
|
+
try {
|
|
151
|
+
console.log("[canopy][mdx] UI components cache hit:", {
|
|
152
|
+
path: UI_COMPONENTS_PATH,
|
|
153
|
+
mtime: UI_COMPONENTS_MTIME,
|
|
154
|
+
});
|
|
155
|
+
} catch (_) {}
|
|
125
156
|
}
|
|
126
157
|
return UI_COMPONENTS;
|
|
127
158
|
}
|
|
128
159
|
let mod = null;
|
|
129
160
|
let importErr = null;
|
|
130
161
|
if (resolved) {
|
|
131
|
-
const {
|
|
162
|
+
const {pathToFileURL} = require("url");
|
|
132
163
|
const fileUrl = pathToFileURL(resolved).href;
|
|
133
164
|
const attempts = 5;
|
|
134
165
|
for (let i = 0; i < attempts && !mod; i++) {
|
|
135
|
-
const bustVal = currentMtime
|
|
166
|
+
const bustVal = currentMtime
|
|
167
|
+
? `${currentMtime}-${i}`
|
|
168
|
+
: `${Date.now()}-${i}`;
|
|
136
169
|
try {
|
|
137
170
|
mod = await import(fileUrl + `?v=${bustVal}`);
|
|
138
171
|
} catch (e) {
|
|
139
172
|
importErr = e;
|
|
140
173
|
if (DEBUG) {
|
|
141
|
-
try {
|
|
174
|
+
try {
|
|
175
|
+
console.warn(
|
|
176
|
+
"[canopy][mdx] ESM import failed for",
|
|
177
|
+
resolved,
|
|
178
|
+
"(attempt",
|
|
179
|
+
i + 1,
|
|
180
|
+
"of",
|
|
181
|
+
attempts + ")\n",
|
|
182
|
+
e && (e.stack || e.message || String(e))
|
|
183
|
+
);
|
|
184
|
+
} catch (_) {}
|
|
142
185
|
}
|
|
143
186
|
// Small delay to avoid watch-write race
|
|
144
187
|
await new Promise((r) => setTimeout(r, 60));
|
|
145
188
|
}
|
|
146
189
|
}
|
|
147
190
|
if (DEBUG) {
|
|
148
|
-
try {
|
|
191
|
+
try {
|
|
192
|
+
console.log("[canopy][mdx] UI components resolved", {
|
|
193
|
+
path: resolved,
|
|
194
|
+
mtime: currentMtime,
|
|
195
|
+
loaded: !!mod,
|
|
196
|
+
});
|
|
197
|
+
} catch (_) {}
|
|
149
198
|
}
|
|
150
199
|
}
|
|
151
200
|
if (!mod) {
|
|
152
201
|
// Try package subpath as a secondary resolution path to avoid export-map issues
|
|
153
202
|
try {
|
|
154
|
-
mod = await import(
|
|
203
|
+
mod = await import("@canopy-iiif/app/ui/server");
|
|
155
204
|
} catch (e2) {
|
|
156
205
|
const msgA = importErr && (importErr.stack || importErr.message);
|
|
157
206
|
const msgB = e2 && (e2.stack || e2.message);
|
|
158
|
-
throw new Error(
|
|
207
|
+
throw new Error(
|
|
208
|
+
"Failed to load @canopy-iiif/app/ui/server. Ensure the UI package is built.\nPath import error: " +
|
|
209
|
+
(msgA || "") +
|
|
210
|
+
"\nExport-map import error: " +
|
|
211
|
+
(msgB || "")
|
|
212
|
+
);
|
|
159
213
|
}
|
|
160
214
|
}
|
|
161
|
-
let comp =
|
|
215
|
+
let comp = mod && typeof mod === "object" ? mod : {};
|
|
162
216
|
// Hard-require core exports; do not inject fallbacks
|
|
163
|
-
const required = [
|
|
217
|
+
const required = [
|
|
218
|
+
"SearchPanel",
|
|
219
|
+
"SearchFormModal",
|
|
220
|
+
"SearchResults",
|
|
221
|
+
"SearchSummary",
|
|
222
|
+
"SearchTabs",
|
|
223
|
+
"Viewer",
|
|
224
|
+
"Slider",
|
|
225
|
+
"RelatedItems",
|
|
226
|
+
"Interstitials",
|
|
227
|
+
];
|
|
164
228
|
const missing = required.filter((k) => !comp || !comp[k]);
|
|
165
229
|
if (missing.length) {
|
|
166
|
-
throw new Error(
|
|
230
|
+
throw new Error(
|
|
231
|
+
"[canopy][mdx] Missing UI exports: " + missing.join(", ")
|
|
232
|
+
);
|
|
167
233
|
}
|
|
168
234
|
if (DEBUG) {
|
|
169
|
-
try {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
235
|
+
try {
|
|
236
|
+
console.log("[canopy][mdx] UI component sources", {
|
|
237
|
+
path: currentPath,
|
|
238
|
+
mtime: currentMtime,
|
|
239
|
+
hasServerExport: !!mod,
|
|
240
|
+
hasWorkspace: typeof comp !== "undefined",
|
|
241
|
+
SearchFormModal: !!comp.SearchFormModal,
|
|
242
|
+
Viewer: !!comp.Viewer,
|
|
243
|
+
Slider: !!comp.Slider,
|
|
244
|
+
});
|
|
245
|
+
} catch (_) {}
|
|
178
246
|
}
|
|
179
247
|
UI_COMPONENTS = comp;
|
|
180
248
|
UI_COMPONENTS_PATH = currentPath;
|
|
181
249
|
UI_COMPONENTS_MTIME = currentMtime;
|
|
182
250
|
} catch (e) {
|
|
183
|
-
const msg = e && (e.stack || e.message || String(e)) ||
|
|
184
|
-
throw new Error(
|
|
251
|
+
const msg = (e && (e.stack || e.message || String(e))) || "unknown error";
|
|
252
|
+
throw new Error(
|
|
253
|
+
"[canopy][mdx] Failed to load UI components (no fallbacks): " + msg
|
|
254
|
+
);
|
|
185
255
|
}
|
|
186
256
|
return UI_COMPONENTS;
|
|
187
257
|
}
|
|
188
258
|
|
|
189
259
|
function slugifyHeading(text) {
|
|
190
260
|
try {
|
|
191
|
-
return String(text ||
|
|
261
|
+
return String(text || "")
|
|
192
262
|
.toLowerCase()
|
|
193
263
|
.trim()
|
|
194
|
-
.replace(/[^a-z0-9\s-]/g,
|
|
195
|
-
.replace(/\s+/g,
|
|
264
|
+
.replace(/[^a-z0-9\s-]/g, "")
|
|
265
|
+
.replace(/\s+/g, "-");
|
|
196
266
|
} catch (_) {
|
|
197
|
-
return
|
|
267
|
+
return "";
|
|
198
268
|
}
|
|
199
269
|
}
|
|
200
270
|
|
|
201
271
|
function extractHeadings(mdxSource) {
|
|
202
|
-
const {
|
|
203
|
-
const cleaned = content.replace(/```[\s\S]*?```/g,
|
|
272
|
+
const {content} = parseFrontmatter(String(mdxSource || ""));
|
|
273
|
+
const cleaned = content.replace(/```[\s\S]*?```/g, "");
|
|
204
274
|
const headingRegex = /^ {0,3}(#{1,6})\s+(.+?)\s*$/gm;
|
|
205
275
|
const seen = new Map();
|
|
206
276
|
const headings = [];
|
|
207
277
|
let match;
|
|
208
278
|
while ((match = headingRegex.exec(cleaned))) {
|
|
209
|
-
const hashes = match[1] ||
|
|
279
|
+
const hashes = match[1] || "";
|
|
210
280
|
const depth = hashes.length;
|
|
211
|
-
let raw = match[2] ||
|
|
281
|
+
let raw = match[2] || "";
|
|
212
282
|
let explicitId = null;
|
|
213
283
|
const idMatch = raw.match(/\s*\{#([A-Za-z0-9_-]+)\}\s*$/);
|
|
214
284
|
if (idMatch) {
|
|
215
285
|
explicitId = idMatch[1];
|
|
216
286
|
raw = raw.slice(0, raw.length - idMatch[0].length);
|
|
217
287
|
}
|
|
218
|
-
const title = raw
|
|
288
|
+
const title = raw
|
|
289
|
+
.replace(/\<[^>]*\>/g, "")
|
|
290
|
+
.replace(/\[([^\]]+)\]\([^)]*\)/g, "$1")
|
|
291
|
+
.trim();
|
|
219
292
|
if (!title) continue;
|
|
220
|
-
const baseId =
|
|
293
|
+
const baseId =
|
|
294
|
+
explicitId || slugifyHeading(title) || `section-${headings.length + 1}`;
|
|
221
295
|
const count = seen.get(baseId) || 0;
|
|
222
296
|
seen.set(baseId, count + 1);
|
|
223
297
|
const id = count === 0 ? baseId : `${baseId}-${count + 1}`;
|
|
@@ -231,39 +305,39 @@ function extractHeadings(mdxSource) {
|
|
|
231
305
|
}
|
|
232
306
|
|
|
233
307
|
function extractPlainText(mdxSource) {
|
|
234
|
-
let {
|
|
235
|
-
if (!content) return
|
|
236
|
-
content = content.replace(/```[\s\S]*?```/g,
|
|
237
|
-
content = content.replace(/`{1,3}([^`]+)`{1,3}/g,
|
|
238
|
-
content = content.replace(/!\[[^\]]*\]\([^)]*\)/g,
|
|
239
|
-
content = content.replace(/\[[^\]]*\]\([^)]*\)/g,
|
|
240
|
-
content = content.replace(/<[^>]+>/g,
|
|
241
|
-
content = content.replace(/\{#([^}]+)\}/g,
|
|
242
|
-
content = content.replace(/\{\/[A-Za-z0-9_.-]+\}/g,
|
|
243
|
-
content = content.replace(/\{[^{}]*\}/g,
|
|
244
|
-
content = content.replace(/[#>*~_\-]+/g,
|
|
245
|
-
content = content.replace(/\n+/g,
|
|
246
|
-
content = content.replace(/\s+/g,
|
|
308
|
+
let {content} = parseFrontmatter(String(mdxSource || ""));
|
|
309
|
+
if (!content) return "";
|
|
310
|
+
content = content.replace(/```[\s\S]*?```/g, " ");
|
|
311
|
+
content = content.replace(/`{1,3}([^`]+)`{1,3}/g, "$1");
|
|
312
|
+
content = content.replace(/!\[[^\]]*\]\([^)]*\)/g, " ");
|
|
313
|
+
content = content.replace(/\[[^\]]*\]\([^)]*\)/g, "$1");
|
|
314
|
+
content = content.replace(/<[^>]+>/g, " ");
|
|
315
|
+
content = content.replace(/\{#([^}]+)\}/g, " ");
|
|
316
|
+
content = content.replace(/\{\/[A-Za-z0-9_.-]+\}/g, " ");
|
|
317
|
+
content = content.replace(/\{[^{}]*\}/g, " ");
|
|
318
|
+
content = content.replace(/[#>*~_\-]+/g, " ");
|
|
319
|
+
content = content.replace(/\n+/g, " ");
|
|
320
|
+
content = content.replace(/\s+/g, " ").trim();
|
|
247
321
|
return content;
|
|
248
322
|
}
|
|
249
323
|
|
|
250
324
|
function extractMarkdownSummary(mdxSource) {
|
|
251
|
-
let {
|
|
252
|
-
if (!content) return
|
|
253
|
-
content = content.replace(/^import[^\n]+$/gm,
|
|
254
|
-
content = content.replace(/^export[^\n]+$/gm,
|
|
255
|
-
content = content.replace(/```[\s\S]*?```/g,
|
|
256
|
-
content = content.replace(/<[A-Za-z][^>]*?>[\s\S]*?<\/[A-Za-z][^>]*?>/g,
|
|
257
|
-
content = content.replace(/<[A-Za-z][^>]*?\/>/g,
|
|
258
|
-
content = content.replace(/\{\/[A-Za-z0-9_.-]+\}/g,
|
|
259
|
-
content = content.replace(/\{[^{}]*\}/g,
|
|
260
|
-
content = content.replace(/^#{1,6}\s+.*$/gm,
|
|
261
|
-
content = content.replace(/\s+/g,
|
|
325
|
+
let {content} = parseFrontmatter(String(mdxSource || ""));
|
|
326
|
+
if (!content) return "";
|
|
327
|
+
content = content.replace(/^import[^\n]+$/gm, " ");
|
|
328
|
+
content = content.replace(/^export[^\n]+$/gm, " ");
|
|
329
|
+
content = content.replace(/```[\s\S]*?```/g, " ");
|
|
330
|
+
content = content.replace(/<[A-Za-z][^>]*?>[\s\S]*?<\/[A-Za-z][^>]*?>/g, " ");
|
|
331
|
+
content = content.replace(/<[A-Za-z][^>]*?\/>/g, " ");
|
|
332
|
+
content = content.replace(/\{\/[A-Za-z0-9_.-]+\}/g, " ");
|
|
333
|
+
content = content.replace(/\{[^{}]*\}/g, " ");
|
|
334
|
+
content = content.replace(/^#{1,6}\s+.*$/gm, " ");
|
|
335
|
+
content = content.replace(/\s+/g, " ").trim();
|
|
262
336
|
return content;
|
|
263
337
|
}
|
|
264
338
|
|
|
265
339
|
function extractTitle(mdxSource) {
|
|
266
|
-
const {
|
|
340
|
+
const {data, content} = parseFrontmatter(String(mdxSource || ""));
|
|
267
341
|
if (data && typeof data.title === "string" && data.title.trim()) {
|
|
268
342
|
return data.title.trim();
|
|
269
343
|
}
|
|
@@ -314,9 +388,9 @@ async function loadAppWrapper() {
|
|
|
314
388
|
// Keep missing _app as a build-time error as specified
|
|
315
389
|
throw new Error("Missing required file: content/_app.mdx");
|
|
316
390
|
}
|
|
317
|
-
const {
|
|
391
|
+
const {compile} = await import("@mdx-js/mdx");
|
|
318
392
|
const raw = await fsp.readFile(appPath, "utf8");
|
|
319
|
-
const {
|
|
393
|
+
const {content: source} = parseFrontmatter(raw);
|
|
320
394
|
let code = String(await compile(source, buildCompileOptions()));
|
|
321
395
|
// MDX v3 default export (MDXContent) does not forward external children.
|
|
322
396
|
// When present, expose the underlying layout function as __MDXLayout for wrapping.
|
|
@@ -338,10 +412,14 @@ async function loadAppWrapper() {
|
|
|
338
412
|
// Try to render the probe inside an MDXProvider with UI server components
|
|
339
413
|
const components = await loadUiComponents();
|
|
340
414
|
const MDXProvider = await getMdxProvider();
|
|
341
|
-
const probeChild = React.createElement("span", {
|
|
342
|
-
const probeTree = React.createElement(
|
|
415
|
+
const probeChild = React.createElement("span", {"data-canopy-probe": "1"});
|
|
416
|
+
const probeTree = React.createElement(
|
|
417
|
+
App || (() => null),
|
|
418
|
+
null,
|
|
419
|
+
probeChild
|
|
420
|
+
);
|
|
343
421
|
const probe = MDXProvider
|
|
344
|
-
? React.createElement(MDXProvider, {
|
|
422
|
+
? React.createElement(MDXProvider, {components}, probeTree)
|
|
345
423
|
: probeTree;
|
|
346
424
|
const out = ReactDOMServer.renderToStaticMarkup(probe);
|
|
347
425
|
ok = !!(out && out.indexOf("data-canopy-probe") !== -1);
|
|
@@ -353,14 +431,14 @@ async function loadAppWrapper() {
|
|
|
353
431
|
"content/_app.mdx must render {children}. Update the layout so downstream pages receive their content."
|
|
354
432
|
);
|
|
355
433
|
}
|
|
356
|
-
APP_WRAPPER = {
|
|
434
|
+
APP_WRAPPER = {App, Head};
|
|
357
435
|
return APP_WRAPPER;
|
|
358
436
|
}
|
|
359
437
|
|
|
360
438
|
async function compileMdxFile(filePath, outPath, Layout, extraProps = {}) {
|
|
361
|
-
const {
|
|
439
|
+
const {compile} = await import("@mdx-js/mdx");
|
|
362
440
|
const raw = await fsp.readFile(filePath, "utf8");
|
|
363
|
-
const {
|
|
441
|
+
const {content: source} = parseFrontmatter(raw);
|
|
364
442
|
const compiled = await compile(source, buildCompileOptions());
|
|
365
443
|
const code = String(compiled);
|
|
366
444
|
ensureDirSync(CACHE_DIR);
|
|
@@ -392,9 +470,11 @@ async function compileMdxFile(filePath, outPath, Layout, extraProps = {}) {
|
|
|
392
470
|
components.CodeBlock ||
|
|
393
471
|
components.MarkdownCodeBlock ||
|
|
394
472
|
components.MDXCodeBlock);
|
|
395
|
-
const rawHeadings = Array.isArray(
|
|
473
|
+
const rawHeadings = Array.isArray(
|
|
474
|
+
extraProps && extraProps.page && extraProps.page.headings
|
|
475
|
+
)
|
|
396
476
|
? extraProps.page.headings
|
|
397
|
-
.map((heading) => (heading ? {
|
|
477
|
+
.map((heading) => (heading ? {...heading} : heading))
|
|
398
478
|
.filter(Boolean)
|
|
399
479
|
: [];
|
|
400
480
|
const headingQueue = rawHeadings.slice();
|
|
@@ -407,7 +487,7 @@ async function compileMdxFile(filePath, outPath, Layout, extraProps = {}) {
|
|
|
407
487
|
});
|
|
408
488
|
|
|
409
489
|
function reserveHeadingId(base) {
|
|
410
|
-
const fallback = base ||
|
|
490
|
+
const fallback = base || "section";
|
|
411
491
|
let candidate = fallback;
|
|
412
492
|
let attempt = 1;
|
|
413
493
|
while (headingIdCounts.has(candidate)) {
|
|
@@ -419,18 +499,21 @@ async function compileMdxFile(filePath, outPath, Layout, extraProps = {}) {
|
|
|
419
499
|
}
|
|
420
500
|
|
|
421
501
|
function extractTextFromChildren(children) {
|
|
422
|
-
if (children == null) return
|
|
423
|
-
if (typeof children ===
|
|
424
|
-
|
|
425
|
-
if (
|
|
426
|
-
|
|
502
|
+
if (children == null) return "";
|
|
503
|
+
if (typeof children === "string" || typeof children === "number")
|
|
504
|
+
return String(children);
|
|
505
|
+
if (Array.isArray(children))
|
|
506
|
+
return children.map((child) => extractTextFromChildren(child)).join("");
|
|
507
|
+
if (React.isValidElement(children))
|
|
508
|
+
return extractTextFromChildren(children.props && children.props.children);
|
|
509
|
+
return "";
|
|
427
510
|
}
|
|
428
511
|
|
|
429
512
|
function takeHeading(level, children) {
|
|
430
513
|
if (!headingQueue.length) return null;
|
|
431
514
|
const idx = headingQueue.findIndex((item) => {
|
|
432
|
-
if (!item || typeof item !==
|
|
433
|
-
const depth = typeof item.depth ===
|
|
515
|
+
if (!item || typeof item !== "object") return false;
|
|
516
|
+
const depth = typeof item.depth === "number" ? item.depth : item.level;
|
|
434
517
|
return depth === level;
|
|
435
518
|
});
|
|
436
519
|
if (idx === -1) return null;
|
|
@@ -452,7 +535,7 @@ async function compileMdxFile(filePath, outPath, Layout, extraProps = {}) {
|
|
|
452
535
|
return function HeadingComponent(props) {
|
|
453
536
|
const heading = takeHeading(level, props && props.children);
|
|
454
537
|
const id = props && props.id ? props.id : heading && heading.id;
|
|
455
|
-
const finalProps = id ? {
|
|
538
|
+
const finalProps = id ? {...props, id} : props;
|
|
456
539
|
return React.createElement(Base, finalProps, props && props.children);
|
|
457
540
|
};
|
|
458
541
|
}
|
|
@@ -461,7 +544,9 @@ async function compileMdxFile(filePath, outPath, Layout, extraProps = {}) {
|
|
|
461
544
|
new Set(
|
|
462
545
|
headingQueue
|
|
463
546
|
.map((heading) => (heading ? heading.depth || heading.level : null))
|
|
464
|
-
.filter(
|
|
547
|
+
.filter(
|
|
548
|
+
(level) => typeof level === "number" && level >= 1 && level <= 6
|
|
549
|
+
)
|
|
465
550
|
)
|
|
466
551
|
);
|
|
467
552
|
const headingComponents = levelsPresent.length
|
|
@@ -473,27 +558,28 @@ async function compileMdxFile(filePath, outPath, Layout, extraProps = {}) {
|
|
|
473
558
|
const MDXProvider = await getMdxProvider();
|
|
474
559
|
// Base path support for anchors
|
|
475
560
|
const Anchor = function A(props) {
|
|
476
|
-
let {
|
|
561
|
+
let {href = "", ...rest} = props || {};
|
|
477
562
|
href = withBase(href);
|
|
478
|
-
return React.createElement("a", {
|
|
563
|
+
return React.createElement("a", {href, ...rest}, props.children);
|
|
479
564
|
};
|
|
480
565
|
const app = await loadAppWrapper();
|
|
481
566
|
const dirLayout = await getNearestDirLayout(filePath);
|
|
482
567
|
const contentNode = React.createElement(MDXContent, extraProps);
|
|
483
|
-
const layoutProps = dirLayout ? {
|
|
568
|
+
const layoutProps = dirLayout ? {...extraProps} : null;
|
|
484
569
|
const withLayout = dirLayout
|
|
485
570
|
? React.createElement(dirLayout, layoutProps, contentNode)
|
|
486
571
|
: contentNode;
|
|
572
|
+
const withApp = React.createElement(app.App, null, withLayout);
|
|
487
573
|
const PageContext = getPageContext();
|
|
488
574
|
const contextValue = {
|
|
489
|
-
navigation:
|
|
575
|
+
navigation:
|
|
576
|
+
extraProps && extraProps.navigation ? extraProps.navigation : null,
|
|
490
577
|
page: extraProps && extraProps.page ? extraProps.page : null,
|
|
491
578
|
};
|
|
492
579
|
const withContext = PageContext
|
|
493
|
-
? React.createElement(PageContext.Provider, {
|
|
494
|
-
:
|
|
495
|
-
const
|
|
496
|
-
const compMap = { ...components, ...headingComponents, a: Anchor };
|
|
580
|
+
? React.createElement(PageContext.Provider, {value: contextValue}, withApp)
|
|
581
|
+
: withApp;
|
|
582
|
+
const compMap = {...components, ...headingComponents, a: Anchor};
|
|
497
583
|
if (markdownTableComponent && !compMap.table) {
|
|
498
584
|
compMap.table = markdownTableComponent;
|
|
499
585
|
}
|
|
@@ -501,27 +587,31 @@ async function compileMdxFile(filePath, outPath, Layout, extraProps = {}) {
|
|
|
501
587
|
compMap.pre = codeBlockComponent;
|
|
502
588
|
}
|
|
503
589
|
const page = MDXProvider
|
|
504
|
-
? React.createElement(MDXProvider, {
|
|
505
|
-
:
|
|
590
|
+
? React.createElement(MDXProvider, {components: compMap}, withContext)
|
|
591
|
+
: withContext;
|
|
506
592
|
const body = ReactDOMServer.renderToStaticMarkup(page);
|
|
507
|
-
let head =
|
|
593
|
+
let head = "";
|
|
508
594
|
if (app && app.Head) {
|
|
509
595
|
const headElement = React.createElement(app.Head, {
|
|
510
596
|
page: contextValue.page,
|
|
511
597
|
navigation: contextValue.navigation,
|
|
512
598
|
});
|
|
513
599
|
const wrappedHead = PageContext
|
|
514
|
-
? React.createElement(
|
|
600
|
+
? React.createElement(
|
|
601
|
+
PageContext.Provider,
|
|
602
|
+
{value: contextValue},
|
|
603
|
+
headElement
|
|
604
|
+
)
|
|
515
605
|
: headElement;
|
|
516
606
|
head = ReactDOMServer.renderToStaticMarkup(wrappedHead);
|
|
517
607
|
}
|
|
518
|
-
return {
|
|
608
|
+
return {body, head};
|
|
519
609
|
}
|
|
520
610
|
|
|
521
611
|
async function compileMdxToComponent(filePath) {
|
|
522
|
-
const {
|
|
612
|
+
const {compile} = await import("@mdx-js/mdx");
|
|
523
613
|
const raw = await fsp.readFile(filePath, "utf8");
|
|
524
|
-
const {
|
|
614
|
+
const {content: source} = parseFrontmatter(raw);
|
|
525
615
|
const compiled = await compile(source, buildCompileOptions());
|
|
526
616
|
const code = String(compiled);
|
|
527
617
|
ensureDirSync(CACHE_DIR);
|
|
@@ -557,9 +647,12 @@ async function ensureClientRuntime() {
|
|
|
557
647
|
esbuild = require("esbuild");
|
|
558
648
|
} catch (_) {}
|
|
559
649
|
}
|
|
560
|
-
if (!esbuild)
|
|
650
|
+
if (!esbuild)
|
|
651
|
+
throw new Error(
|
|
652
|
+
"Viewer runtime bundling requires esbuild. Install dependencies before building."
|
|
653
|
+
);
|
|
561
654
|
ensureDirSync(OUT_DIR);
|
|
562
|
-
const scriptsDir = path.join(OUT_DIR,
|
|
655
|
+
const scriptsDir = path.join(OUT_DIR, "scripts");
|
|
563
656
|
ensureDirSync(scriptsDir);
|
|
564
657
|
const outFile = path.join(scriptsDir, "canopy-viewer.js");
|
|
565
658
|
const entry = `
|
|
@@ -646,16 +739,34 @@ async function ensureClientRuntime() {
|
|
|
646
739
|
export const hydrateRoot = RDC.hydrateRoot;
|
|
647
740
|
`;
|
|
648
741
|
const plugin = {
|
|
649
|
-
name:
|
|
742
|
+
name: "canopy-react-shims",
|
|
650
743
|
setup(build) {
|
|
651
|
-
const ns =
|
|
652
|
-
build.onResolve({
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
build.
|
|
657
|
-
|
|
658
|
-
|
|
744
|
+
const ns = "canopy-shim";
|
|
745
|
+
build.onResolve({filter: /^react$/}, () => ({
|
|
746
|
+
path: "react",
|
|
747
|
+
namespace: ns,
|
|
748
|
+
}));
|
|
749
|
+
build.onResolve({filter: /^react-dom$/}, () => ({
|
|
750
|
+
path: "react-dom",
|
|
751
|
+
namespace: ns,
|
|
752
|
+
}));
|
|
753
|
+
build.onResolve({filter: /^react-dom\/client$/}, () => ({
|
|
754
|
+
path: "react-dom-client",
|
|
755
|
+
namespace: ns,
|
|
756
|
+
}));
|
|
757
|
+
build.onLoad({filter: /^react$/, namespace: ns}, () => ({
|
|
758
|
+
contents: reactShim,
|
|
759
|
+
loader: "js",
|
|
760
|
+
}));
|
|
761
|
+
build.onLoad({filter: /^react-dom$/, namespace: ns}, () => ({
|
|
762
|
+
contents: rdomShim,
|
|
763
|
+
loader: "js",
|
|
764
|
+
}));
|
|
765
|
+
build.onLoad({filter: /^react-dom-client$/, namespace: ns}, () => ({
|
|
766
|
+
contents: rdomClientShim,
|
|
767
|
+
loader: "js",
|
|
768
|
+
}));
|
|
769
|
+
},
|
|
659
770
|
};
|
|
660
771
|
await esbuild.build({
|
|
661
772
|
stdin: {
|
|
@@ -675,11 +786,15 @@ async function ensureClientRuntime() {
|
|
|
675
786
|
plugins: [plugin],
|
|
676
787
|
});
|
|
677
788
|
try {
|
|
678
|
-
const {
|
|
679
|
-
let size = 0;
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
789
|
+
const {logLine} = require("./log");
|
|
790
|
+
let size = 0;
|
|
791
|
+
try {
|
|
792
|
+
const st = fs.statSync(outFile);
|
|
793
|
+
size = (st && st.size) || 0;
|
|
794
|
+
} catch (_) {}
|
|
795
|
+
const kb = size ? ` (${(size / 1024).toFixed(1)} KB)` : "";
|
|
796
|
+
const rel = path.relative(process.cwd(), outFile).split(path.sep).join("/");
|
|
797
|
+
logLine(`✓ Wrote ${rel}${kb}`, "cyan");
|
|
683
798
|
} catch (_) {}
|
|
684
799
|
}
|
|
685
800
|
|
|
@@ -687,14 +802,22 @@ async function ensureClientRuntime() {
|
|
|
687
802
|
// and renders a Slider for each.
|
|
688
803
|
async function ensureFacetsRuntime() {
|
|
689
804
|
let esbuild = null;
|
|
690
|
-
try {
|
|
805
|
+
try {
|
|
806
|
+
esbuild = require("../../ui/node_modules/esbuild");
|
|
807
|
+
} catch (_) {
|
|
808
|
+
try {
|
|
809
|
+
esbuild = require("esbuild");
|
|
810
|
+
} catch (_) {}
|
|
811
|
+
}
|
|
691
812
|
if (!esbuild) {
|
|
692
|
-
throw new Error(
|
|
813
|
+
throw new Error(
|
|
814
|
+
"RelatedItems runtime bundling requires esbuild. Install dependencies before building."
|
|
815
|
+
);
|
|
693
816
|
}
|
|
694
817
|
ensureDirSync(OUT_DIR);
|
|
695
|
-
const scriptsDir = path.join(OUT_DIR,
|
|
818
|
+
const scriptsDir = path.join(OUT_DIR, "scripts");
|
|
696
819
|
ensureDirSync(scriptsDir);
|
|
697
|
-
const outFile = path.join(scriptsDir,
|
|
820
|
+
const outFile = path.join(scriptsDir, "canopy-related-items.js");
|
|
698
821
|
const entry = `
|
|
699
822
|
function ready(fn){ if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',fn,{once:true}); else fn(); }
|
|
700
823
|
function parseProps(el){ try{ const s=el.querySelector('script[type="application/json"]'); if(s) return JSON.parse(s.textContent||'{}'); }catch(_){ } return {}; }
|
|
@@ -749,6 +872,7 @@ async function ensureFacetsRuntime() {
|
|
|
749
872
|
const pick = candidates[Math.floor(Math.random() * candidates.length)];
|
|
750
873
|
const wrap = document.createElement('div');
|
|
751
874
|
wrap.setAttribute('data-facet-label', entry.label);
|
|
875
|
+
wrap.setAttribute('class', 'canopy-slider');
|
|
752
876
|
const ph = makeSliderPlaceholder({ iiifContent: rootBase() + '/api/facet/' + (allow.slug) + '/' + pick.valueSlug + '.json' + verQ });
|
|
753
877
|
if (ph) wrap.appendChild(ph);
|
|
754
878
|
el.appendChild(wrap);
|
|
@@ -762,6 +886,7 @@ async function ensureFacetsRuntime() {
|
|
|
762
886
|
selected.forEach((s) => {
|
|
763
887
|
const wrap = document.createElement('div');
|
|
764
888
|
wrap.setAttribute('data-facet-label', s.label);
|
|
889
|
+
wrap.setAttribute('class', 'canopy-slider');
|
|
765
890
|
const ph = makeSliderPlaceholder({ iiifContent: rootBase() + '/api/facet/' + s.labelSlug + '/' + s.valueSlug + '.json' + verQ });
|
|
766
891
|
if (ph) wrap.appendChild(ph);
|
|
767
892
|
el.appendChild(wrap);
|
|
@@ -770,30 +895,39 @@ async function ensureFacetsRuntime() {
|
|
|
770
895
|
});
|
|
771
896
|
});
|
|
772
897
|
`;
|
|
773
|
-
const shim = {
|
|
898
|
+
const shim = {name: "facets-vanilla", setup() {}};
|
|
774
899
|
try {
|
|
775
900
|
await esbuild.build({
|
|
776
|
-
stdin: {
|
|
901
|
+
stdin: {
|
|
902
|
+
contents: entry,
|
|
903
|
+
resolveDir: process.cwd(),
|
|
904
|
+
sourcefile: "canopy-facets-entry.js",
|
|
905
|
+
loader: "js",
|
|
906
|
+
},
|
|
777
907
|
outfile: outFile,
|
|
778
|
-
platform:
|
|
779
|
-
format:
|
|
908
|
+
platform: "browser",
|
|
909
|
+
format: "iife",
|
|
780
910
|
bundle: true,
|
|
781
911
|
sourcemap: false,
|
|
782
|
-
target: [
|
|
783
|
-
logLevel:
|
|
912
|
+
target: ["es2018"],
|
|
913
|
+
logLevel: "silent",
|
|
784
914
|
minify: true,
|
|
785
|
-
plugins: [shim]
|
|
915
|
+
plugins: [shim],
|
|
786
916
|
});
|
|
787
917
|
} catch (e) {
|
|
788
918
|
const message = e && e.message ? e.message : e;
|
|
789
919
|
throw new Error(`RelatedItems runtime build failed: ${message}`);
|
|
790
920
|
}
|
|
791
921
|
try {
|
|
792
|
-
const {
|
|
793
|
-
let size = 0;
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
922
|
+
const {logLine} = require("./log");
|
|
923
|
+
let size = 0;
|
|
924
|
+
try {
|
|
925
|
+
const st = fs.statSync(outFile);
|
|
926
|
+
size = (st && st.size) || 0;
|
|
927
|
+
} catch (_) {}
|
|
928
|
+
const kb = size ? ` (${(size / 1024).toFixed(1)} KB)` : "";
|
|
929
|
+
const rel = path.relative(process.cwd(), outFile).split(path.sep).join("/");
|
|
930
|
+
logLine(`✓ Wrote ${rel}${kb}`, "cyan");
|
|
797
931
|
} catch (_) {}
|
|
798
932
|
}
|
|
799
933
|
|
|
@@ -803,11 +937,16 @@ async function ensureSliderRuntime() {
|
|
|
803
937
|
try {
|
|
804
938
|
esbuild = require("../ui/node_modules/esbuild");
|
|
805
939
|
} catch (_) {
|
|
806
|
-
try {
|
|
940
|
+
try {
|
|
941
|
+
esbuild = require("esbuild");
|
|
942
|
+
} catch (_) {}
|
|
807
943
|
}
|
|
808
|
-
if (!esbuild)
|
|
944
|
+
if (!esbuild)
|
|
945
|
+
throw new Error(
|
|
946
|
+
"Slider runtime bundling requires esbuild. Install dependencies before building."
|
|
947
|
+
);
|
|
809
948
|
ensureDirSync(OUT_DIR);
|
|
810
|
-
const scriptsDir = path.join(OUT_DIR,
|
|
949
|
+
const scriptsDir = path.join(OUT_DIR, "scripts");
|
|
811
950
|
ensureDirSync(scriptsDir);
|
|
812
951
|
const outFile = path.join(scriptsDir, "canopy-slider.js");
|
|
813
952
|
const entry = `
|
|
@@ -892,39 +1031,67 @@ async function ensureSliderRuntime() {
|
|
|
892
1031
|
export const hydrateRoot = RDC.hydrateRoot;
|
|
893
1032
|
`;
|
|
894
1033
|
const plugin = {
|
|
895
|
-
name:
|
|
1034
|
+
name: "canopy-react-shims-slider",
|
|
896
1035
|
setup(build) {
|
|
897
|
-
const ns =
|
|
898
|
-
build.onResolve({
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
build.
|
|
903
|
-
|
|
1036
|
+
const ns = "canopy-shim";
|
|
1037
|
+
build.onResolve({filter: /^react$/}, () => ({
|
|
1038
|
+
path: "react",
|
|
1039
|
+
namespace: ns,
|
|
1040
|
+
}));
|
|
1041
|
+
build.onResolve({filter: /^react-dom$/}, () => ({
|
|
1042
|
+
path: "react-dom",
|
|
1043
|
+
namespace: ns,
|
|
1044
|
+
}));
|
|
1045
|
+
build.onResolve({filter: /^react-dom\/client$/}, () => ({
|
|
1046
|
+
path: "react-dom-client",
|
|
1047
|
+
namespace: ns,
|
|
1048
|
+
}));
|
|
1049
|
+
build.onLoad({filter: /^react$/, namespace: ns}, () => ({
|
|
1050
|
+
contents: reactShim,
|
|
1051
|
+
loader: "js",
|
|
1052
|
+
}));
|
|
1053
|
+
build.onLoad({filter: /^react-dom$/, namespace: ns}, () => ({
|
|
1054
|
+
contents:
|
|
1055
|
+
"export default ((typeof window!=='undefined' && window.ReactDOM) || {});",
|
|
1056
|
+
loader: "js",
|
|
1057
|
+
}));
|
|
1058
|
+
build.onLoad({filter: /^react-dom-client$/, namespace: ns}, () => ({
|
|
1059
|
+
contents: rdomClientShim,
|
|
1060
|
+
loader: "js",
|
|
1061
|
+
}));
|
|
904
1062
|
// Inline imported CSS into a <style> tag at runtime so we don't need a separate CSS file
|
|
905
|
-
build.onLoad({
|
|
906
|
-
const fs = require(
|
|
907
|
-
let css =
|
|
908
|
-
try {
|
|
1063
|
+
build.onLoad({filter: /\.css$/}, (args) => {
|
|
1064
|
+
const fs = require("fs");
|
|
1065
|
+
let css = "";
|
|
1066
|
+
try {
|
|
1067
|
+
css = fs.readFileSync(args.path, "utf8");
|
|
1068
|
+
} catch (_) {
|
|
1069
|
+
css = "";
|
|
1070
|
+
}
|
|
909
1071
|
const js = [
|
|
910
1072
|
`var css = ${JSON.stringify(css)};`,
|
|
911
1073
|
`(function(){ try { var s = document.createElement('style'); s.setAttribute('data-canopy-slider-css',''); s.textContent = css; document.head.appendChild(s); } catch (e) {} })();`,
|
|
912
|
-
`export default css
|
|
913
|
-
].join(
|
|
914
|
-
return {
|
|
1074
|
+
`export default css;`,
|
|
1075
|
+
].join("\n");
|
|
1076
|
+
return {contents: js, loader: "js"};
|
|
915
1077
|
});
|
|
916
|
-
}
|
|
1078
|
+
},
|
|
917
1079
|
};
|
|
918
1080
|
try {
|
|
919
1081
|
await esbuild.build({
|
|
920
|
-
stdin: {
|
|
1082
|
+
stdin: {
|
|
1083
|
+
contents: entry,
|
|
1084
|
+
resolveDir: process.cwd(),
|
|
1085
|
+
sourcefile: "canopy-slider-entry.js",
|
|
1086
|
+
loader: "js",
|
|
1087
|
+
},
|
|
921
1088
|
outfile: outFile,
|
|
922
|
-
platform:
|
|
923
|
-
format:
|
|
1089
|
+
platform: "browser",
|
|
1090
|
+
format: "iife",
|
|
924
1091
|
bundle: true,
|
|
925
1092
|
sourcemap: false,
|
|
926
|
-
target: [
|
|
927
|
-
logLevel:
|
|
1093
|
+
target: ["es2018"],
|
|
1094
|
+
logLevel: "silent",
|
|
928
1095
|
minify: true,
|
|
929
1096
|
plugins: [plugin],
|
|
930
1097
|
});
|
|
@@ -933,11 +1100,15 @@ async function ensureSliderRuntime() {
|
|
|
933
1100
|
throw new Error(`Slider runtime build failed: ${message}`);
|
|
934
1101
|
}
|
|
935
1102
|
try {
|
|
936
|
-
const {
|
|
937
|
-
let size = 0;
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1103
|
+
const {logLine} = require("./log");
|
|
1104
|
+
let size = 0;
|
|
1105
|
+
try {
|
|
1106
|
+
const st = fs.statSync(outFile);
|
|
1107
|
+
size = (st && st.size) || 0;
|
|
1108
|
+
} catch (_) {}
|
|
1109
|
+
const kb = size ? ` (${(size / 1024).toFixed(1)} KB)` : "";
|
|
1110
|
+
const rel = path.relative(process.cwd(), outFile).split(path.sep).join("/");
|
|
1111
|
+
logLine(`✓ Wrote ${rel}${kb}`, "cyan");
|
|
941
1112
|
} catch (_) {}
|
|
942
1113
|
}
|
|
943
1114
|
|
|
@@ -951,8 +1122,11 @@ async function ensureReactGlobals() {
|
|
|
951
1122
|
esbuild = require("esbuild");
|
|
952
1123
|
} catch (_) {}
|
|
953
1124
|
}
|
|
954
|
-
if (!esbuild)
|
|
955
|
-
|
|
1125
|
+
if (!esbuild)
|
|
1126
|
+
throw new Error(
|
|
1127
|
+
"React globals bundling requires esbuild. Install dependencies before building."
|
|
1128
|
+
);
|
|
1129
|
+
const {path} = require("../common");
|
|
956
1130
|
ensureDirSync(OUT_DIR);
|
|
957
1131
|
const scriptsDir = path.join(OUT_DIR, "scripts");
|
|
958
1132
|
ensureDirSync(scriptsDir);
|
|
@@ -978,7 +1152,7 @@ async function ensureReactGlobals() {
|
|
|
978
1152
|
target: ["es2018"],
|
|
979
1153
|
logLevel: "silent",
|
|
980
1154
|
minify: true,
|
|
981
|
-
define: {
|
|
1155
|
+
define: {"process.env.NODE_ENV": '"production"'},
|
|
982
1156
|
});
|
|
983
1157
|
}
|
|
984
1158
|
|
|
@@ -987,35 +1161,45 @@ async function ensureHeroRuntime() {
|
|
|
987
1161
|
try {
|
|
988
1162
|
esbuild = require("../ui/node_modules/esbuild");
|
|
989
1163
|
} catch (_) {
|
|
990
|
-
try {
|
|
1164
|
+
try {
|
|
1165
|
+
esbuild = require("esbuild");
|
|
1166
|
+
} catch (_) {}
|
|
991
1167
|
}
|
|
992
|
-
if (!esbuild)
|
|
1168
|
+
if (!esbuild)
|
|
1169
|
+
throw new Error(
|
|
1170
|
+
"Hero slider runtime bundling requires esbuild. Install dependencies before building."
|
|
1171
|
+
);
|
|
993
1172
|
ensureDirSync(OUT_DIR);
|
|
994
|
-
const scriptsDir = path.join(OUT_DIR,
|
|
1173
|
+
const scriptsDir = path.join(OUT_DIR, "scripts");
|
|
995
1174
|
ensureDirSync(scriptsDir);
|
|
996
|
-
const outFile = path.join(scriptsDir,
|
|
997
|
-
const entryFile = path.join(
|
|
1175
|
+
const outFile = path.join(scriptsDir, "canopy-hero-slider.js");
|
|
1176
|
+
const entryFile = path.join(
|
|
1177
|
+
__dirname,
|
|
1178
|
+
"..",
|
|
1179
|
+
"components",
|
|
1180
|
+
"hero-slider-runtime.js"
|
|
1181
|
+
);
|
|
998
1182
|
await esbuild.build({
|
|
999
1183
|
entryPoints: [entryFile],
|
|
1000
1184
|
outfile: outFile,
|
|
1001
|
-
platform:
|
|
1002
|
-
format:
|
|
1185
|
+
platform: "browser",
|
|
1186
|
+
format: "iife",
|
|
1003
1187
|
bundle: true,
|
|
1004
1188
|
sourcemap: false,
|
|
1005
|
-
target: [
|
|
1006
|
-
logLevel:
|
|
1189
|
+
target: ["es2018"],
|
|
1190
|
+
logLevel: "silent",
|
|
1007
1191
|
minify: true,
|
|
1008
1192
|
});
|
|
1009
1193
|
try {
|
|
1010
|
-
const {
|
|
1194
|
+
const {logLine} = require("./log");
|
|
1011
1195
|
let size = 0;
|
|
1012
1196
|
try {
|
|
1013
1197
|
const st = fs.statSync(outFile);
|
|
1014
1198
|
size = (st && st.size) || 0;
|
|
1015
1199
|
} catch (_) {}
|
|
1016
|
-
const kb = size ? ` (${(size / 1024).toFixed(1)} KB)` :
|
|
1017
|
-
const rel = path.relative(process.cwd(), outFile).split(path.sep).join(
|
|
1018
|
-
logLine(`✓ Wrote ${rel}${kb}`,
|
|
1200
|
+
const kb = size ? ` (${(size / 1024).toFixed(1)} KB)` : "";
|
|
1201
|
+
const rel = path.relative(process.cwd(), outFile).split(path.sep).join("/");
|
|
1202
|
+
logLine(`✓ Wrote ${rel}${kb}`, "cyan");
|
|
1019
1203
|
} catch (_) {}
|
|
1020
1204
|
}
|
|
1021
1205
|
|