@canopy-iiif/app 0.10.32 → 0.12.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 +109 -11
- package/package.json +1 -1
- package/ui/dist/server.mjs +4049 -44
- package/ui/dist/server.mjs.map +4 -4
- package/ui/styles/components/_interstitial-hero.scss +17 -0
- package/ui/styles/index.css +13 -0
package/lib/build/dev.js
CHANGED
|
@@ -3,6 +3,12 @@ const fsp = fs.promises;
|
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const { spawn, spawnSync } = require("child_process");
|
|
5
5
|
const http = require("http");
|
|
6
|
+
let sass = null;
|
|
7
|
+
try {
|
|
8
|
+
sass = require("sass");
|
|
9
|
+
} catch (_) {
|
|
10
|
+
sass = null;
|
|
11
|
+
}
|
|
6
12
|
const {
|
|
7
13
|
CONTENT_DIR,
|
|
8
14
|
OUT_DIR,
|
|
@@ -29,6 +35,13 @@ const UI_DIST_DIR = path.resolve(path.join(__dirname, "../../ui/dist"));
|
|
|
29
35
|
const APP_PACKAGE_ROOT = path.resolve(path.join(__dirname, "..", ".."));
|
|
30
36
|
const APP_LIB_DIR = path.join(APP_PACKAGE_ROOT, "lib");
|
|
31
37
|
const APP_UI_DIR = path.join(APP_PACKAGE_ROOT, "ui");
|
|
38
|
+
let loadUiTheme = null;
|
|
39
|
+
try {
|
|
40
|
+
const uiTheme = require(path.join(APP_UI_DIR, "theme.js"));
|
|
41
|
+
if (uiTheme && typeof uiTheme.loadCanopyTheme === "function") {
|
|
42
|
+
loadUiTheme = uiTheme.loadCanopyTheme;
|
|
43
|
+
}
|
|
44
|
+
} catch (_) {}
|
|
32
45
|
const APP_WATCH_TARGETS = [
|
|
33
46
|
{ dir: APP_LIB_DIR, label: "@canopy-iiif/app/lib" },
|
|
34
47
|
{ dir: APP_UI_DIR, label: "@canopy-iiif/app/ui" },
|
|
@@ -1025,6 +1038,7 @@ async function dev() {
|
|
|
1025
1038
|
);
|
|
1026
1039
|
const uiStylesDir = path.join(APP_UI_DIR, "styles");
|
|
1027
1040
|
const uiStylesCss = path.join(uiStylesDir, "index.css");
|
|
1041
|
+
const uiStylesEntry = path.join(uiStylesDir, "index.scss");
|
|
1028
1042
|
const pluginFiles = [uiPlugin, uiPreset].filter((p) => {
|
|
1029
1043
|
try {
|
|
1030
1044
|
return fs.existsSync(p);
|
|
@@ -1056,6 +1070,36 @@ async function dev() {
|
|
|
1056
1070
|
});
|
|
1057
1071
|
} catch (_) {}
|
|
1058
1072
|
}
|
|
1073
|
+
const rebuildUiStyles = () => {
|
|
1074
|
+
if (!sass || !fs.existsSync(uiStylesEntry)) return false;
|
|
1075
|
+
try {
|
|
1076
|
+
const theme = loadUiTheme ? loadUiTheme({ cwd: process.cwd() }) : null;
|
|
1077
|
+
const source = `${
|
|
1078
|
+
theme && theme.sassConfig ? theme.sassConfig : ""
|
|
1079
|
+
}@use 'index';`;
|
|
1080
|
+
const result = sass.compileString(source, {
|
|
1081
|
+
loadPaths: [uiStylesDir],
|
|
1082
|
+
style: "expanded",
|
|
1083
|
+
});
|
|
1084
|
+
let cssOutput = result && result.css ? result.css : "";
|
|
1085
|
+
const themeCss = theme && theme.css ? theme.css.trim() : "";
|
|
1086
|
+
if (themeCss) {
|
|
1087
|
+
cssOutput = `/* canopy-theme */\n${themeCss}\n/* canopy-theme:end */\n${cssOutput}`;
|
|
1088
|
+
}
|
|
1089
|
+
fs.writeFileSync(uiStylesCss, cssOutput, "utf8");
|
|
1090
|
+
console.log(
|
|
1091
|
+
"[tailwind] rebuilt @canopy-iiif/app/ui styles →",
|
|
1092
|
+
prettyPath(uiStylesCss)
|
|
1093
|
+
);
|
|
1094
|
+
return true;
|
|
1095
|
+
} catch (err) {
|
|
1096
|
+
console.warn(
|
|
1097
|
+
"[tailwind] failed to rebuild @canopy-iiif/app/ui styles:",
|
|
1098
|
+
err && err.message ? err.message : err
|
|
1099
|
+
);
|
|
1100
|
+
return false;
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1059
1103
|
const attachCssWatcher = () => {
|
|
1060
1104
|
if (uiCssWatcherAttached) {
|
|
1061
1105
|
if (fs.existsSync(uiStylesCss)) return;
|
|
@@ -1080,11 +1124,15 @@ async function dev() {
|
|
|
1080
1124
|
} catch (_) {}
|
|
1081
1125
|
}
|
|
1082
1126
|
};
|
|
1127
|
+
if (fs.existsSync(uiStylesEntry)) rebuildUiStyles();
|
|
1083
1128
|
attachCssWatcher();
|
|
1084
1129
|
const handleUiSassChange = () => {
|
|
1130
|
+
const ok = rebuildUiStyles();
|
|
1085
1131
|
attachCssWatcher();
|
|
1086
1132
|
scheduleTailwindRestart(
|
|
1087
|
-
|
|
1133
|
+
ok
|
|
1134
|
+
? "[tailwind] detected @canopy-iiif/app/ui Sass change — restarting Tailwind"
|
|
1135
|
+
: "[tailwind] Sass compile failed — attempting Tailwind restart",
|
|
1088
1136
|
"[tailwind] compile after UI Sass change failed"
|
|
1089
1137
|
);
|
|
1090
1138
|
};
|
|
@@ -1148,16 +1196,66 @@ async function dev() {
|
|
|
1148
1196
|
const stylesDir = path.dirname(inputCss);
|
|
1149
1197
|
if (stylesDir && stylesDir.includes(path.join("app", "styles"))) {
|
|
1150
1198
|
let cssDebounce = null;
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1199
|
+
const triggerCssRebuild = () => {
|
|
1200
|
+
clearTimeout(cssDebounce);
|
|
1201
|
+
cssDebounce = setTimeout(() => {
|
|
1202
|
+
try { onBuildStart(); } catch (_) {}
|
|
1203
|
+
safeCompile("[tailwind] compile after CSS change failed");
|
|
1204
|
+
try { onCssChange(); } catch (_) {}
|
|
1205
|
+
}, 50);
|
|
1206
|
+
};
|
|
1207
|
+
const shouldHandle = (filename) => {
|
|
1208
|
+
if (!filename) return true;
|
|
1209
|
+
return /\.(css|s[ac]ss)$/i.test(String(filename));
|
|
1210
|
+
};
|
|
1211
|
+
const attachRecursiveWatch = () => {
|
|
1212
|
+
try {
|
|
1213
|
+
fs.watch(
|
|
1214
|
+
stylesDir,
|
|
1215
|
+
{ persistent: false, recursive: true },
|
|
1216
|
+
(evt, fn) => {
|
|
1217
|
+
if (!shouldHandle(fn)) return;
|
|
1218
|
+
triggerCssRebuild();
|
|
1219
|
+
}
|
|
1220
|
+
);
|
|
1221
|
+
return true;
|
|
1222
|
+
} catch (_) {
|
|
1223
|
+
return false;
|
|
1224
|
+
}
|
|
1225
|
+
};
|
|
1226
|
+
if (!attachRecursiveWatch()) {
|
|
1227
|
+
const watchers = new Map();
|
|
1228
|
+
function watchDir(dir) {
|
|
1229
|
+
if (watchers.has(dir)) return;
|
|
1230
|
+
try {
|
|
1231
|
+
const watcher = fs.watch(
|
|
1232
|
+
dir,
|
|
1233
|
+
{ persistent: false },
|
|
1234
|
+
(evt, fn) => {
|
|
1235
|
+
if (shouldHandle(fn)) triggerCssRebuild();
|
|
1236
|
+
scanDir(dir);
|
|
1237
|
+
}
|
|
1238
|
+
);
|
|
1239
|
+
watchers.set(dir, watcher);
|
|
1240
|
+
} catch (_) {}
|
|
1241
|
+
}
|
|
1242
|
+
function scanDir(dir) {
|
|
1243
|
+
let entries = [];
|
|
1244
|
+
try {
|
|
1245
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
1246
|
+
} catch (_) {
|
|
1247
|
+
return;
|
|
1248
|
+
}
|
|
1249
|
+
for (const entry of entries) {
|
|
1250
|
+
if (!entry || !entry.isDirectory()) continue;
|
|
1251
|
+
const next = path.join(dir, entry.name);
|
|
1252
|
+
watchDir(next);
|
|
1253
|
+
scanDir(next);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
watchDir(stylesDir);
|
|
1257
|
+
scanDir(stylesDir);
|
|
1258
|
+
}
|
|
1161
1259
|
}
|
|
1162
1260
|
} catch (err) {
|
|
1163
1261
|
console.error("[tailwind] setup failed:", err && err.message ? err.message : err);
|