@canopy-iiif/app 1.8.15 → 1.9.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/iiif.js CHANGED
@@ -16,7 +16,14 @@ const {
16
16
  readSiteMetadata,
17
17
  readPrimaryNavigation,
18
18
  withBase,
19
+ resolveLocaleFromHref,
20
+ getLocaleRouteEntries,
21
+ getDefaultRoute,
22
+ buildRouteRelativePath,
23
+ getLocaleRouteConfig,
24
+ getDefaultLocaleCode,
19
25
  } = require("../common");
26
+ const {readCanopyLocalesWithMessages} = require("../locales");
20
27
  const {resolveCanopyConfigPath} = require("../config-path");
21
28
  const mdx = require("./mdx");
22
29
  const {log, logLine, logResponse} = require("./log");
@@ -174,9 +181,9 @@ function normalizeSlugBase(value, fallback) {
174
181
  return clampSlugLength(safeFallback, MAX_ENTRY_SLUG_LENGTH) || safeFallback;
175
182
  }
176
183
 
177
- function manifestHrefFromSlug(slug) {
184
+ function manifestHrefFromSlug(slug, routePath) {
178
185
  if (!slug) return "";
179
- const rel = `works/${String(slug).trim()}.html`;
186
+ const rel = buildRouteRelativePath(routePath || getDefaultRoute("works"), `${String(slug).trim()}.html`);
180
187
  return rootRelativeHref(rel);
181
188
  }
182
189
 
@@ -203,10 +210,10 @@ function extractHomepageId(resource) {
203
210
  return "";
204
211
  }
205
212
 
206
- function resolveManifestCanonical(manifest, slug) {
213
+ function resolveManifestCanonical(manifest, slug, routePath) {
207
214
  const homepageId = extractHomepageId(manifest);
208
215
  if (homepageId) return homepageId;
209
- return manifestHrefFromSlug(slug);
216
+ return manifestHrefFromSlug(slug, routePath);
210
217
  }
211
218
 
212
219
  function resolveCollectionCanonical(collection) {
@@ -223,9 +230,9 @@ function assignEntryCanonical(entry, canonical) {
223
230
  return value;
224
231
  }
225
232
 
226
- function applyManifestEntryCanonical(entry, manifest, slug) {
233
+ function applyManifestEntryCanonical(entry, manifest, slug, routePath) {
227
234
  if (!entry || entry.type !== "Manifest") return "";
228
- const canonical = resolveManifestCanonical(manifest, slug);
235
+ const canonical = resolveManifestCanonical(manifest, slug, routePath);
229
236
  return assignEntryCanonical(entry, canonical);
230
237
  }
231
238
 
@@ -1127,7 +1134,7 @@ async function loadCachedManifestById(id) {
1127
1134
  slug,
1128
1135
  parent: "",
1129
1136
  };
1130
- applyManifestEntryCanonical(entry, null, slug);
1137
+ applyManifestEntryCanonical(entry, null, slug, getDefaultRoute("works"));
1131
1138
  if (existingEntryIdx >= 0) index.byId[existingEntryIdx] = entry;
1132
1139
  else index.byId.push(entry);
1133
1140
  await saveManifestIndex(index);
@@ -1160,6 +1167,7 @@ async function loadCachedManifestById(id) {
1160
1167
  entry,
1161
1168
  normalized,
1162
1169
  slug,
1170
+ getDefaultRoute("works"),
1163
1171
  );
1164
1172
  if (nextCanonical !== prevCanonical) {
1165
1173
  await saveManifestIndex(index);
@@ -1202,7 +1210,7 @@ async function saveCachedManifest(manifest, id, parentId) {
1202
1210
  slug,
1203
1211
  parent: parentId ? String(parentId) : "",
1204
1212
  };
1205
- applyManifestEntryCanonical(entry, normalizedManifest, slug);
1213
+ applyManifestEntryCanonical(entry, normalizedManifest, slug, getDefaultRoute("works"));
1206
1214
  if (existingEntryIdx >= 0) index.byId[existingEntryIdx] = entry;
1207
1215
  else index.byId.push(entry);
1208
1216
  await saveManifestIndex(index);
@@ -1860,6 +1868,16 @@ async function buildIiifCollectionPages(CONFIG) {
1860
1868
  const iiifRecords = [];
1861
1869
  const navPlaceRecords = [];
1862
1870
  const {size: thumbSize, unsafe: unsafeThumbs} = resolveThumbnailPreferences();
1871
+ let workRouteEntries = getLocaleRouteEntries("works");
1872
+ if (!workRouteEntries.length) {
1873
+ workRouteEntries = [
1874
+ {
1875
+ locale: getDefaultLocaleCode(),
1876
+ route: getDefaultRoute("works"),
1877
+ isDefault: true,
1878
+ },
1879
+ ];
1880
+ }
1863
1881
 
1864
1882
  // Compile the works layout component once per run
1865
1883
  const worksLayoutPath = path.join(CONTENT_DIR, "works", "_layout.mdx");
@@ -2028,10 +2046,20 @@ async function buildIiifCollectionPages(CONFIG) {
2028
2046
  if (normalizedManifestId) renderedManifestIds.add(normalizedManifestId);
2029
2047
  logDebug(`Resolved slug ${slug} for ${manifestLabel}`);
2030
2048
  const references = referenced.getReferencesForManifest(manifestId);
2031
- const href = path.join("works", slug + ".html");
2032
- const outPath = path.join(OUT_DIR, href);
2033
- ensureDirSync(path.dirname(outPath));
2034
- try {
2049
+ for (const routeEntry of workRouteEntries) {
2050
+ const routeBase =
2051
+ routeEntry && routeEntry.route
2052
+ ? routeEntry.route
2053
+ : getDefaultRoute("works");
2054
+ const isDefaultRoute = routeEntry && routeEntry.isDefault === true;
2055
+ const localeFromRoute =
2056
+ routeEntry && routeEntry.locale
2057
+ ? routeEntry.locale
2058
+ : getDefaultLocaleCode();
2059
+ const href = buildRouteRelativePath(routeBase, `${slug}.html`);
2060
+ const outPath = path.join(OUT_DIR, href);
2061
+ ensureDirSync(path.dirname(outPath));
2062
+ try {
2035
2063
  let components = {};
2036
2064
  try {
2037
2065
  components = await mdx.loadUiComponents();
@@ -2062,8 +2090,9 @@ async function buildIiifCollectionPages(CONFIG) {
2062
2090
  }
2063
2091
  const normalizedHref = href.split(path.sep).join("/");
2064
2092
  const pageHref = rootRelativeHref(normalizedHref);
2093
+ const pageLocale = localeFromRoute || resolveLocaleFromHref(pageHref);
2065
2094
  const pageDescription = summaryForMeta || title;
2066
- const canonical = resolveManifestCanonical(manifest, slug);
2095
+ const canonical = resolveManifestCanonical(manifest, slug, routeBase);
2067
2096
  const pageDetails = {
2068
2097
  title,
2069
2098
  href: pageHref,
@@ -2074,12 +2103,14 @@ async function buildIiifCollectionPages(CONFIG) {
2074
2103
  manifestId,
2075
2104
  referencedBy: references,
2076
2105
  canonical,
2106
+ locale: pageLocale,
2077
2107
  meta: {
2078
2108
  title,
2079
2109
  description: pageDescription,
2080
2110
  type: "work",
2081
2111
  url: pageHref,
2082
2112
  canonical,
2113
+ locale: pageLocale,
2083
2114
  },
2084
2115
  };
2085
2116
  const ogImageForPage =
@@ -2095,11 +2126,33 @@ async function buildIiifCollectionPages(CONFIG) {
2095
2126
  navigationRoots && Object.keys(navigationRoots).length
2096
2127
  ? {allRoots: navigationRoots}
2097
2128
  : null;
2098
- const primaryNav = readPrimaryNavigation();
2129
+ const primaryNav = readPrimaryNavigation(pageLocale);
2130
+ const siteMeta = readSiteMetadata ? {...readSiteMetadata()} : null;
2131
+ const siteLanguageToggle = (() => {
2132
+ try {
2133
+ const data = readCanopyLocalesWithMessages();
2134
+ if (data && Array.isArray(data.locales) && data.locales.length) {
2135
+ return {locales: data.locales, messages: data.messages || {}};
2136
+ }
2137
+ } catch (_) {}
2138
+ return null;
2139
+ })();
2140
+ const siteContext = siteMeta ? {...siteMeta} : {};
2141
+ if (siteLanguageToggle) {
2142
+ siteContext.languageToggle = siteLanguageToggle;
2143
+ }
2144
+ try {
2145
+ const localeRoutes = getLocaleRouteConfig(pageLocale);
2146
+ if (localeRoutes) siteContext.routes = localeRoutes;
2147
+ } catch (_) {}
2148
+ try {
2149
+ const defaultRoutes = getLocaleRouteConfig(getDefaultLocaleCode());
2150
+ if (defaultRoutes) siteContext.routesDefault = defaultRoutes;
2151
+ } catch (_) {}
2099
2152
  const pageContextValue = {
2100
2153
  navigation: navigationContext,
2101
2154
  page: pageDetails,
2102
- site: readSiteMetadata ? {...readSiteMetadata()} : null,
2155
+ site: siteContext && Object.keys(siteContext).length ? siteContext : null,
2103
2156
  primaryNavigation: Array.isArray(primaryNav) ? primaryNav : [],
2104
2157
  };
2105
2158
  if (
@@ -2329,6 +2382,7 @@ async function buildIiifCollectionPages(CONFIG) {
2329
2382
  scriptHref: jsRel,
2330
2383
  headExtra,
2331
2384
  bodyClass,
2385
+ lang: pageLocale,
2332
2386
  });
2333
2387
  try {
2334
2388
  html = require("../common").applyBaseToHtml(html);
@@ -2501,104 +2555,124 @@ async function buildIiifCollectionPages(CONFIG) {
2501
2555
  }
2502
2556
  }
2503
2557
  } catch (_) {}
2504
- let metadataValues = [];
2505
- let summaryValue = "";
2506
- let annotationValue = "";
2507
- try {
2508
- const metadataEntries = extractMetadataEntries(manifest, {
2509
- includeAll: metadataCollectAllLabels,
2510
- labelsSet: metadataLabelSet,
2511
- });
2512
- if (metadataEntries && metadataEntries.length) {
2513
- for (const entry of metadataEntries) recordMetadataIndexEntry(entry);
2514
- }
2515
- } catch (_) {}
2516
- if (metadataOptions && metadataOptions.enabled) {
2558
+ if (isDefaultRoute) {
2559
+ let metadataValues = [];
2560
+ let summaryValue = "";
2561
+ let annotationValue = "";
2517
2562
  try {
2518
- metadataValues = extractMetadataValues(manifest, metadataOptions);
2519
- } catch (_) {
2520
- metadataValues = [];
2563
+ const metadataEntries = extractMetadataEntries(manifest, {
2564
+ includeAll: metadataCollectAllLabels,
2565
+ labelsSet: metadataLabelSet,
2566
+ });
2567
+ if (metadataEntries && metadataEntries.length) {
2568
+ for (const entry of metadataEntries) recordMetadataIndexEntry(entry);
2569
+ }
2570
+ } catch (_) {}
2571
+ if (metadataOptions && metadataOptions.enabled) {
2572
+ try {
2573
+ metadataValues = extractMetadataValues(manifest, metadataOptions);
2574
+ } catch (_) {
2575
+ metadataValues = [];
2576
+ }
2521
2577
  }
2522
- }
2523
- if (summaryOptions && summaryOptions.enabled) {
2524
- summaryValue = summaryRaw || "";
2525
- }
2526
- if (annotationsOptions && annotationsOptions.enabled) {
2527
- try {
2528
- annotationValue = await extractAnnotationText(
2529
- manifest,
2530
- annotationsOptions,
2578
+ if (summaryOptions && summaryOptions.enabled) {
2579
+ summaryValue = summaryRaw || "";
2580
+ }
2581
+ if (annotationsOptions && annotationsOptions.enabled) {
2582
+ try {
2583
+ annotationValue = await extractAnnotationText(
2584
+ manifest,
2585
+ annotationsOptions,
2586
+ );
2587
+ } catch (_) {
2588
+ annotationValue = "";
2589
+ }
2590
+ }
2591
+ const fallbackThumbnail =
2592
+ (heroMedia && heroMedia.heroThumbnail) || "";
2593
+ const fallbackThumbWidth =
2594
+ heroMedia && typeof heroMedia.heroThumbnailWidth === "number"
2595
+ ? heroMedia.heroThumbnailWidth
2596
+ : undefined;
2597
+ const fallbackThumbHeight =
2598
+ heroMedia && typeof heroMedia.heroThumbnailHeight === "number"
2599
+ ? heroMedia.heroThumbnailHeight
2600
+ : undefined;
2601
+ const navThumbnail = thumbUrl || fallbackThumbnail;
2602
+ const navThumbWidth =
2603
+ typeof thumbWidth === "number" ? thumbWidth : fallbackThumbWidth;
2604
+ const navThumbHeight =
2605
+ typeof thumbHeight === "number" ? thumbHeight : fallbackThumbHeight;
2606
+ const navRecord = navPlace.buildManifestNavPlaceRecord({
2607
+ manifest,
2608
+ slug,
2609
+ href: pageHref,
2610
+ title,
2611
+ summary: summaryRaw,
2612
+ thumbnail: navThumbnail,
2613
+ thumbnailWidth: navThumbWidth,
2614
+ thumbnailHeight: navThumbHeight,
2615
+ });
2616
+ if (navRecord) navPlaceRecords.push(navRecord);
2617
+
2618
+ const recordThumbnail = navThumbnail;
2619
+ const recordThumbWidth = navThumbWidth;
2620
+ const recordThumbHeight = navThumbHeight;
2621
+ const localeHrefMap = {};
2622
+ for (const entry of workRouteEntries) {
2623
+ const targetBase =
2624
+ entry && entry.route ? entry.route : getDefaultRoute("works");
2625
+ const targetLocale =
2626
+ entry && entry.locale ? entry.locale : getDefaultLocaleCode();
2627
+ const relHref = buildRouteRelativePath(
2628
+ targetBase,
2629
+ `${slug}.html`,
2630
+ );
2631
+ localeHrefMap[targetLocale] = rootRelativeHref(
2632
+ relHref.split(path.sep).join("/"),
2531
2633
  );
2532
- } catch (_) {
2533
- annotationValue = "";
2534
2634
  }
2635
+ iiifRecords.push({
2636
+ id: String(manifest.id || id),
2637
+ title,
2638
+ href: pageHref,
2639
+ type: "work",
2640
+ slug,
2641
+ locale: pageLocale,
2642
+ thumbnail: recordThumbnail || undefined,
2643
+ thumbnailWidth:
2644
+ typeof recordThumbWidth === "number"
2645
+ ? recordThumbWidth
2646
+ : undefined,
2647
+ thumbnailHeight:
2648
+ typeof recordThumbHeight === "number"
2649
+ ? recordThumbHeight
2650
+ : undefined,
2651
+ searchMetadataValues:
2652
+ metadataValues && metadataValues.length
2653
+ ? metadataValues
2654
+ : undefined,
2655
+ searchSummary:
2656
+ summaryValue && summaryValue.length ? summaryValue : undefined,
2657
+ searchAnnotation:
2658
+ annotationValue && annotationValue.length
2659
+ ? annotationValue
2660
+ : undefined,
2661
+ routes: localeHrefMap,
2662
+ });
2663
+ logDebug(
2664
+ `Search record queued for ${manifestLabel}: ${pageHref} (metadata values ${
2665
+ metadataValues ? metadataValues.length : 0
2666
+ })`,
2667
+ );
2535
2668
  }
2536
- const fallbackThumbnail =
2537
- (heroMedia && heroMedia.heroThumbnail) || "";
2538
- const fallbackThumbWidth =
2539
- heroMedia && typeof heroMedia.heroThumbnailWidth === "number"
2540
- ? heroMedia.heroThumbnailWidth
2541
- : undefined;
2542
- const fallbackThumbHeight =
2543
- heroMedia && typeof heroMedia.heroThumbnailHeight === "number"
2544
- ? heroMedia.heroThumbnailHeight
2545
- : undefined;
2546
- const navThumbnail = thumbUrl || fallbackThumbnail;
2547
- const navThumbWidth =
2548
- typeof thumbWidth === "number" ? thumbWidth : fallbackThumbWidth;
2549
- const navThumbHeight =
2550
- typeof thumbHeight === "number" ? thumbHeight : fallbackThumbHeight;
2551
- const navRecord = navPlace.buildManifestNavPlaceRecord({
2552
- manifest,
2553
- slug,
2554
- href: pageHref,
2555
- title,
2556
- summary: summaryRaw,
2557
- thumbnail: navThumbnail,
2558
- thumbnailWidth: navThumbWidth,
2559
- thumbnailHeight: navThumbHeight,
2560
- });
2561
- if (navRecord) navPlaceRecords.push(navRecord);
2562
-
2563
- const recordThumbnail = navThumbnail;
2564
- const recordThumbWidth = navThumbWidth;
2565
- const recordThumbHeight = navThumbHeight;
2566
- iiifRecords.push({
2567
- id: String(manifest.id || id),
2568
- title,
2569
- href: pageHref,
2570
- type: "work",
2571
- thumbnail: recordThumbnail || undefined,
2572
- thumbnailWidth:
2573
- typeof recordThumbWidth === "number"
2574
- ? recordThumbWidth
2575
- : undefined,
2576
- thumbnailHeight:
2577
- typeof recordThumbHeight === "number"
2578
- ? recordThumbHeight
2579
- : undefined,
2580
- searchMetadataValues:
2581
- metadataValues && metadataValues.length
2582
- ? metadataValues
2583
- : undefined,
2584
- searchSummary:
2585
- summaryValue && summaryValue.length ? summaryValue : undefined,
2586
- searchAnnotation:
2587
- annotationValue && annotationValue.length
2588
- ? annotationValue
2589
- : undefined,
2590
- });
2591
- logDebug(
2592
- `Search record queued for ${manifestLabel}: ${pageHref} (metadata values ${
2593
- metadataValues ? metadataValues.length : 0
2594
- })`,
2595
- );
2596
2669
  } catch (e) {
2597
2670
  lns.push([
2598
2671
  `IIIF: failed to render for ${id || "<unknown>"} — ${e.message}`,
2599
2672
  "red",
2600
2673
  ]);
2601
2674
  }
2675
+ }
2602
2676
  logs[idx] = lns;
2603
2677
  tryFlush();
2604
2678
  }
package/lib/build/mdx.js CHANGED
@@ -13,12 +13,31 @@ const {
13
13
  withBase,
14
14
  readSiteMetadata,
15
15
  readPrimaryNavigation,
16
+ getLocaleRouteConfig,
17
+ getDefaultLocaleCode,
16
18
  } = require("../common");
17
-
18
19
  const globalRoot = typeof globalThis !== "undefined" ? globalThis : global;
19
20
  if (globalRoot && typeof globalRoot.__canopyRequire !== "function") {
20
21
  globalRoot.__canopyRequire = typeof require === "function" ? require : null;
21
22
  }
23
+ const {readCanopyLocalesWithMessages} = require("../locales");
24
+
25
+ function getSiteLanguageToggle() {
26
+ try {
27
+ const data = readCanopyLocalesWithMessages();
28
+ if (
29
+ data &&
30
+ Array.isArray(data.locales) &&
31
+ data.locales.length
32
+ ) {
33
+ return {
34
+ locales: data.locales,
35
+ messages: data.messages || {},
36
+ };
37
+ }
38
+ } catch (_) {}
39
+ return null;
40
+ }
22
41
  let remarkGfm = null;
23
42
  try {
24
43
  const mod = require("remark-gfm");
@@ -1069,12 +1088,29 @@ async function compileMdxFile(filePath, outPath, Layout, extraProps = {}) {
1069
1088
  const withApp = React.createElement(app.App, null, withLayout);
1070
1089
  const PageContext = getPageContext();
1071
1090
  const siteMeta = readSiteMetadata();
1072
- const primaryNav = readPrimaryNavigation();
1091
+ const pageLocale =
1092
+ extraProps && extraProps.page && typeof extraProps.page.locale === "string"
1093
+ ? extraProps.page.locale
1094
+ : undefined;
1095
+ const primaryNav = readPrimaryNavigation(pageLocale);
1096
+ const siteLanguageToggle = getSiteLanguageToggle();
1097
+ const siteContext = siteMeta ? {...siteMeta} : {};
1098
+ if (siteLanguageToggle) {
1099
+ siteContext.languageToggle = siteLanguageToggle;
1100
+ }
1101
+ try {
1102
+ const localeRoutes = getLocaleRouteConfig(pageLocale);
1103
+ if (localeRoutes) siteContext.routes = localeRoutes;
1104
+ } catch (_) {}
1105
+ try {
1106
+ const defaultRoutes = getLocaleRouteConfig(getDefaultLocaleCode());
1107
+ if (defaultRoutes) siteContext.routesDefault = defaultRoutes;
1108
+ } catch (_) {}
1073
1109
  const contextValue = {
1074
1110
  navigation:
1075
1111
  extraProps && extraProps.navigation ? extraProps.navigation : null,
1076
1112
  page: extraProps && extraProps.page ? extraProps.page : null,
1077
- site: siteMeta ? {...siteMeta} : null,
1113
+ site: siteContext && Object.keys(siteContext).length ? siteContext : null,
1078
1114
  primaryNavigation: Array.isArray(primaryNav) ? primaryNav : [],
1079
1115
  };
1080
1116
  const withContext = PageContext
@@ -8,6 +8,9 @@ const {
8
8
  htmlShell,
9
9
  canopyBodyClassForType,
10
10
  rootRelativeHref,
11
+ resolveLocaleFromContentPath,
12
+ canonicalizeLocaleCode,
13
+ getDefaultLocaleCode,
11
14
  } = require('../common');
12
15
  const { log } = require('./log');
13
16
  const mdx = require('./mdx');
@@ -109,12 +112,20 @@ async function renderContentMdxToHtml(filePath, outPath, extraProps = {}, source
109
112
  ? mdx.parseFrontmatter(source)
110
113
  : { data: null, content: source };
111
114
  const frontmatterData = frontmatter && isPlainObject(frontmatter.data) ? frontmatter.data : null;
115
+ const frontmatterLocaleRaw = readFrontmatterString(frontmatterData, 'locale');
116
+ const frontmatterLocale = canonicalizeLocaleCode(frontmatterLocaleRaw);
117
+ const pageLocale =
118
+ frontmatterLocale ||
119
+ resolveLocaleFromContentPath(relContentPath) ||
120
+ getDefaultLocaleCode();
112
121
  const referencedManifestIdsRaw = frontmatterData ? frontmatterData.referencedManifests : null;
113
122
  const referencedManifestIds = referenced.normalizeReferencedManifestList(
114
123
  referencedManifestIdsRaw
115
124
  );
116
125
  const referencedItems = referencedManifestIds.length
117
- ? referenced.buildReferencedItems(referencedManifestIds)
126
+ ? referenced.buildReferencedItems(referencedManifestIds, {
127
+ locale: pageLocale,
128
+ })
118
129
  : [];
119
130
  let layoutMeta = null;
120
131
  try {
@@ -141,6 +152,7 @@ async function renderContentMdxToHtml(filePath, outPath, extraProps = {}, source
141
152
  const frontmatterMeta = frontmatterData && isPlainObject(frontmatterData.meta) ? frontmatterData.meta : null;
142
153
  const headings = mdx.extractHeadings(source);
143
154
  const basePage = pageInfo ? { ...pageInfo } : {};
155
+ if (pageLocale) basePage.locale = pageLocale;
144
156
  if (title) basePage.title = title;
145
157
  if (resolvedType) basePage.type = resolvedType;
146
158
  if (resolvedDescription) basePage.description = resolvedDescription;
@@ -171,6 +183,7 @@ async function renderContentMdxToHtml(filePath, outPath, extraProps = {}, source
171
183
  pageMeta.image = resolvedImage;
172
184
  if (!pageMeta.ogImage) pageMeta.ogImage = resolvedImage;
173
185
  }
186
+ if (pageLocale) pageMeta.locale = pageLocale;
174
187
  if (frontmatterMeta) Object.assign(pageMeta, frontmatterMeta);
175
188
  if (Object.keys(pageMeta).length) basePage.meta = pageMeta;
176
189
  if (referencedManifestIds.length) {
@@ -357,6 +370,7 @@ async function renderContentMdxToHtml(filePath, outPath, extraProps = {}, source
357
370
  scriptHref: jsRel,
358
371
  headExtra,
359
372
  bodyClass,
373
+ lang: pageLocale,
360
374
  });
361
375
  const { applyBaseToHtml } = require('../common');
362
376
  return applyBaseToHtml(html);
@@ -1,6 +1,6 @@
1
1
 
2
2
  const { logLine } = require('./log');
3
- const { rootRelativeHref } = require('../common');
3
+ const { rootRelativeHref, buildRouteRelativePath, getDefaultRoute } = require('../common');
4
4
 
5
5
  function pagesToRecords(pageRecords) {
6
6
  const list = Array.isArray(pageRecords) ? pageRecords : [];
@@ -29,7 +29,8 @@ function maybeMockRecords() {
29
29
  const svg = encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300"><rect width="400" height="300" fill="#dbeafe"/><text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="24" fill="#1d4ed8">Mock</text></svg>');
30
30
  const thumb = `data:image/svg+xml;charset=utf-8,${svg}`;
31
31
  for (let i = 1; i <= 120; i++) {
32
- mock.push({ title: `Mock Work #${i}`, href: rootRelativeHref(`works/mock-${i}.html`), type: 'work', thumbnail: thumb });
32
+ const rel = buildRouteRelativePath(getDefaultRoute('works'), `mock-${i}.html`);
33
+ mock.push({ title: `Mock Work #${i}`, href: rootRelativeHref(rel), type: 'work', thumbnail: thumb });
33
34
  }
34
35
  mock.push({ title: 'Mock Doc A', href: rootRelativeHref('getting-started/index.html'), type: 'docs' });
35
36
  mock.push({ title: 'Mock Doc B', href: rootRelativeHref('getting-started/example.html'), type: 'docs' });
@@ -1,4 +1,11 @@
1
- const { fs, path, OUT_DIR } = require('../common');
1
+ const {
2
+ fs,
3
+ path,
4
+ OUT_DIR,
5
+ getLocaleRouteEntries,
6
+ getDefaultRoute,
7
+ getDefaultLocaleCode,
8
+ } = require('../common');
2
9
  const search = require('../search/search');
3
10
  const runtimes = require('./runtimes');
4
11
  const { generateFacets } = require('./facets');
@@ -10,7 +17,12 @@ const { logLine } = require('./log');
10
17
  * and build the page so subsequent steps can update artifacts incrementally.
11
18
  */
12
19
  async function ensureSearchInitialized() {
13
- const searchPath = path.join(OUT_DIR, 'search.html');
20
+ const entries = getLocaleRouteEntries('search');
21
+ const defaultEntry = entries.length
22
+ ? entries[0]
23
+ : { locale: getDefaultLocaleCode(), route: getDefaultRoute('search') };
24
+ const rel = search.resolveSearchOutputRelative(defaultEntry.route || '');
25
+ const searchPath = path.join(OUT_DIR, rel);
14
26
  const needCreatePage = !fs.existsSync(searchPath);
15
27
  if (!needCreatePage) return;
16
28
  try { logLine('• Preparing search (initial)...', 'blue', { bright: true }); } catch (_) {}
@@ -20,7 +32,7 @@ async function ensureSearchInitialized() {
20
32
  await search.writeSearchIndex([]);
21
33
  try { logLine(' - Writing runtime...', 'blue'); } catch (_) {}
22
34
  await runtimes.prepareSearchRuntime(process.env.CANOPY_BUNDLE_TIMEOUT || 10000, 'initial');
23
- try { logLine(' - Building search.html...', 'blue'); } catch (_) {}
35
+ try { logLine(' - Building search page...', 'blue'); } catch (_) {}
24
36
  await search.buildSearchPage();
25
37
  try { logLine('✓ Created search page', 'cyan'); } catch (_) {}
26
38
  }
@@ -38,7 +50,7 @@ async function finalizeSearch(combinedRecords) {
38
50
  try { logLine('• Writing search runtime (final)...', 'blue', { bright: true }); } catch (_) {}
39
51
  await runtimes.prepareSearchRuntime(process.env.CANOPY_BUNDLE_TIMEOUT || 10000, 'final');
40
52
  try { await search.ensureResultTemplate(); } catch (_) {}
41
- try { logLine('• Updating search.html...', 'blue'); } catch (_) {}
53
+ try { logLine('• Updating search page...', 'blue'); } catch (_) {}
42
54
  await search.buildSearchPage();
43
55
  try { logLine('✓ Search page updated', 'cyan'); } catch (_) {}
44
56
 
@@ -58,4 +70,3 @@ async function finalizeSearch(combinedRecords) {
58
70
  }
59
71
 
60
72
  module.exports = { ensureSearchInitialized, finalizeSearch };
61
-