@canopy-iiif/app 1.6.21 → 1.7.0

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/dev.js CHANGED
@@ -15,6 +15,10 @@ const {
15
15
  ASSETS_DIR,
16
16
  ensureDirSync,
17
17
  } = require("../common");
18
+ const {
19
+ injectThemeTokens,
20
+ stripTailwindThemeLayer,
21
+ } = require("./styles");
18
22
  const APP_COMPONENTS_DIR = path.join(process.cwd(), "app", "components");
19
23
 
20
24
  function resolveTailwindCli() {
@@ -60,14 +64,6 @@ const HAS_APP_WORKSPACE = (() => {
60
64
  return false;
61
65
  }
62
66
  })();
63
-
64
- function stripTailwindThemeLayer(targetPath) {
65
- try {
66
- const raw = fs.readFileSync(targetPath, "utf8");
67
- const cleaned = raw.replace(/@layer theme\{[\s\S]*?\}(?=@layer|$)/g, "");
68
- if (cleaned !== raw) fs.writeFileSync(targetPath, cleaned, "utf8");
69
- } catch (_) {}
70
- }
71
67
  let pendingModuleReload = false;
72
68
  let building = false;
73
69
  let buildAgain = false;
@@ -992,6 +988,7 @@ async function dev() {
992
988
  }
993
989
  throw new Error("[tailwind] Initial Tailwind build failed.");
994
990
  }
991
+ injectThemeTokens(outputCss);
995
992
  stripTailwindThemeLayer(outputCss);
996
993
  console.log(
997
994
  `[tailwind] initial build ok (${fileSizeKb(outputCss)} KB) →`,
@@ -1017,6 +1014,7 @@ async function dev() {
1017
1014
  cssWatcherAttached = true;
1018
1015
  try {
1019
1016
  fs.watch(outputCss, { persistent: false }, () => {
1017
+ injectThemeTokens(outputCss);
1020
1018
  stripTailwindThemeLayer(outputCss);
1021
1019
  if (!unmuted) {
1022
1020
  unmuted = true;
@@ -1044,6 +1042,7 @@ async function dev() {
1044
1042
  }
1045
1043
  throw new Error("[tailwind] On-demand Tailwind compile failed.");
1046
1044
  }
1045
+ injectThemeTokens(outputCss);
1047
1046
  stripTailwindThemeLayer(outputCss);
1048
1047
  console.log(
1049
1048
  `[tailwind] compiled (${fileSizeKb(outputCss)} KB) →`,
package/lib/build/iiif.js CHANGED
@@ -15,6 +15,7 @@ const {
15
15
  canopyBodyClassForType,
16
16
  readSiteMetadata,
17
17
  readPrimaryNavigation,
18
+ withBase,
18
19
  } = require("../common");
19
20
  const {resolveCanopyConfigPath} = require("../config-path");
20
21
  const mdx = require("./mdx");
@@ -2033,15 +2034,10 @@ async function buildIiifCollectionPages(CONFIG) {
2033
2034
  try {
2034
2035
  let components = {};
2035
2036
  try {
2036
- components = await import("@canopy-iiif/app/ui/server");
2037
+ components = await mdx.loadUiComponents();
2037
2038
  } catch (_) {
2038
- try {
2039
- components = await import("@canopy-iiif/app/ui");
2040
- } catch (_) {
2041
- components = {};
2042
- }
2039
+ components = {};
2043
2040
  }
2044
- const {withBase} = require("../common");
2045
2041
  const Anchor = function A(props) {
2046
2042
  let {href = "", ...rest} = props || {};
2047
2043
  href = withBase(href);
@@ -2056,8 +2052,7 @@ async function buildIiifCollectionPages(CONFIG) {
2056
2052
  } catch (_) {
2057
2053
  MDXProvider = null;
2058
2054
  }
2059
- const {loadAppWrapper} = require("./mdx");
2060
- const app = await loadAppWrapper();
2055
+ const app = await mdx.loadAppWrapper();
2061
2056
 
2062
2057
  let heroMedia = null;
2063
2058
  try {
@@ -2174,6 +2169,9 @@ async function buildIiifCollectionPages(CONFIG) {
2174
2169
  const needsTimeline = body.includes("data-canopy-timeline");
2175
2170
  const needsMap = body.includes("data-canopy-map");
2176
2171
  const needsSearchForm = body.includes("data-canopy-search-form");
2172
+ const needsCustomClients = body.includes(
2173
+ "data-canopy-client-component",
2174
+ );
2177
2175
  const needsHydrate =
2178
2176
  body.includes("data-canopy-hydrate") ||
2179
2177
  needsHydrateViewer ||
@@ -2213,11 +2211,39 @@ async function buildIiifCollectionPages(CONFIG) {
2213
2211
  const searchFormRel = needsSearchForm
2214
2212
  ? relativeRuntimeScript(outPath, "canopy-search-form.js", true)
2215
2213
  : null;
2214
+ let customClientRel = null;
2215
+ if (needsCustomClients) {
2216
+ try {
2217
+ await mdx.ensureCustomClientRuntime();
2218
+ const customAbs = path.join(
2219
+ OUT_DIR,
2220
+ "scripts",
2221
+ "canopy-custom-components.js",
2222
+ );
2223
+ let rel = path
2224
+ .relative(path.dirname(outPath), customAbs)
2225
+ .split(path.sep)
2226
+ .join("/");
2227
+ try {
2228
+ const st = fs.statSync(customAbs);
2229
+ rel += `?v=${Math.floor(st.mtimeMs || Date.now())}`;
2230
+ } catch (_) {}
2231
+ customClientRel = rel;
2232
+ } catch (e) {
2233
+ try {
2234
+ console.warn(
2235
+ "[canopy][mdx] failed to build custom client runtime:",
2236
+ e && e.message ? e.message : e,
2237
+ );
2238
+ } catch (_) {}
2239
+ }
2240
+ }
2216
2241
 
2217
2242
  const moduleScriptRels = [];
2218
2243
  if (viewerRel) moduleScriptRels.push(viewerRel);
2219
2244
  if (sliderRel) moduleScriptRels.push(sliderRel);
2220
2245
  if (imageStoryRel) moduleScriptRels.push(imageStoryRel);
2246
+ if (customClientRel) moduleScriptRels.push(customClientRel);
2221
2247
  const primaryClassicScripts = [];
2222
2248
  if (heroRel) primaryClassicScripts.push(heroRel);
2223
2249
  if (relatedRel) primaryClassicScripts.push(relatedRel);
@@ -2238,7 +2264,8 @@ async function buildIiifCollectionPages(CONFIG) {
2238
2264
  needsHydrateViewer ||
2239
2265
  needsRelated ||
2240
2266
  needsTimeline ||
2241
- needsMap
2267
+ needsMap ||
2268
+ (customClientRel && needsCustomClients)
2242
2269
  );
2243
2270
  let vendorTag = "";
2244
2271
  if (needsReact) {
package/lib/build/mdx.js CHANGED
@@ -14,6 +14,11 @@ const {
14
14
  readSiteMetadata,
15
15
  readPrimaryNavigation,
16
16
  } = require("../common");
17
+
18
+ const globalRoot = typeof globalThis !== "undefined" ? globalThis : global;
19
+ if (globalRoot && typeof globalRoot.__canopyRequire !== "function") {
20
+ globalRoot.__canopyRequire = typeof require === "function" ? require : null;
21
+ }
17
22
  let remarkGfm = null;
18
23
  try {
19
24
  const mod = require("remark-gfm");
@@ -1904,6 +1909,7 @@ module.exports = {
1904
1909
  compileMdxToComponent,
1905
1910
  loadCustomLayout,
1906
1911
  loadAppWrapper,
1912
+ loadUiComponents,
1907
1913
  ensureClientRuntime,
1908
1914
  ensureSliderRuntime,
1909
1915
  ensureTimelineRuntime,
@@ -7,6 +7,49 @@ const {
7
7
  ensureDirSync,
8
8
  } = require("../common");
9
9
 
10
+ function resolveTailwindCli() {
11
+ const localBin = path.join(
12
+ process.cwd(),
13
+ "node_modules",
14
+ ".bin",
15
+ process.platform === "win32" ? "tailwindcss.cmd" : "tailwindcss"
16
+ );
17
+ if (fs.existsSync(localBin)) return {cmd: localBin, args: []};
18
+ return {cmd: "tailwindcss", args: []};
19
+ }
20
+
21
+ function injectThemeTokens(targetPath) {
22
+ try {
23
+ const {loadCanopyTheme} = require("@canopy-iiif/app/ui/theme");
24
+ const theme = loadCanopyTheme();
25
+ const themeCss = theme && theme.css ? theme.css.trim() : "";
26
+ if (!themeCss) return;
27
+
28
+ let existing = "";
29
+ try {
30
+ existing = fs.readFileSync(targetPath, "utf8");
31
+ } catch (_) {}
32
+
33
+ const marker = "/* canopy-theme */";
34
+ const markerEnd = "/* canopy-theme:end */";
35
+ const markerRegex = new RegExp(`${marker}[\\s\\S]*?${markerEnd}\\n?`, "g");
36
+ const sanitized = existing.replace(markerRegex, "").replace(/\s+$/, "");
37
+
38
+ const themeBlock = `${marker}\n${themeCss}\n${markerEnd}\n`;
39
+ const separator = sanitized ? "\n" : "";
40
+ const next = `${sanitized}${separator}${themeBlock}`;
41
+ fs.writeFileSync(targetPath, next, "utf8");
42
+ } catch (_) {}
43
+ }
44
+
45
+ function stripTailwindThemeLayer(targetPath) {
46
+ try {
47
+ const raw = fs.readFileSync(targetPath, "utf8");
48
+ const cleaned = raw.replace(/@layer theme\{[\s\S]*?\}(?=@layer|$)/g, "");
49
+ if (cleaned !== raw) fs.writeFileSync(targetPath, cleaned, "utf8");
50
+ } catch (_) {}
51
+ }
52
+
10
53
  async function ensureStyles() {
11
54
  const stylesDir = path.join(OUT_DIR, "styles");
12
55
  const dest = path.join(stylesDir, "styles.css");
@@ -69,16 +112,6 @@ async function ensureStyles() {
69
112
  }
70
113
  }
71
114
 
72
- function resolveTailwindCli() {
73
- const localBin = path.join(
74
- process.cwd(),
75
- "node_modules",
76
- ".bin",
77
- process.platform === "win32" ? "tailwindcss.cmd" : "tailwindcss"
78
- );
79
- if (fs.existsSync(localBin)) return { cmd: localBin, args: [] };
80
- return { cmd: 'tailwindcss', args: [] };
81
- }
82
115
  function buildTailwindCli({ input, output, config, minify = true }) {
83
116
  try {
84
117
  const cli = resolveTailwindCli();
@@ -97,38 +130,6 @@ async function ensureStyles() {
97
130
  }
98
131
  }
99
132
 
100
- function injectThemeTokens(targetPath) {
101
- try {
102
- const { loadCanopyTheme } = require("@canopy-iiif/app/ui/theme");
103
- const theme = loadCanopyTheme();
104
- const themeCss = theme && theme.css ? theme.css.trim() : "";
105
- if (!themeCss) return;
106
-
107
- let existing = "";
108
- try {
109
- existing = fs.readFileSync(targetPath, "utf8");
110
- } catch (_) {}
111
-
112
- const marker = "/* canopy-theme */";
113
- const markerEnd = "/* canopy-theme:end */";
114
- const markerRegex = new RegExp(`${marker}[\\s\\S]*?${markerEnd}\\n?`, "g");
115
- const sanitized = existing.replace(markerRegex, "").replace(/\s+$/, "");
116
-
117
- const themeBlock = `${marker}\n${themeCss}\n${markerEnd}\n`;
118
- const separator = sanitized ? "\n" : "";
119
- const next = `${sanitized}${separator}${themeBlock}`;
120
- fs.writeFileSync(targetPath, next, "utf8");
121
- } catch (_) {}
122
- }
123
-
124
- function stripTailwindThemeLayer(targetPath) {
125
- try {
126
- const raw = fs.readFileSync(targetPath, "utf8");
127
- const cleaned = raw.replace(/@layer theme\{[\s\S]*?\}(?=@layer|$)/g, "");
128
- if (cleaned !== raw) fs.writeFileSync(targetPath, cleaned, "utf8");
129
- } catch (_) {}
130
- }
131
-
132
133
  if (configPath && (inputCss || generatedInput)) {
133
134
  const ok = buildTailwindCli({
134
135
  input: inputCss || generatedInput,
@@ -174,4 +175,8 @@ async function ensureStyles() {
174
175
  stripTailwindThemeLayer(dest);
175
176
  }
176
177
 
177
- module.exports = { ensureStyles };
178
+ module.exports = {
179
+ ensureStyles,
180
+ injectThemeTokens,
181
+ stripTailwindThemeLayer,
182
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canopy-iiif/app",
3
- "version": "1.6.21",
3
+ "version": "1.7.0",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "author": "Mat Jordan <mat@northwestern.edu>",