@canopy-iiif/app 0.7.14 → 0.7.17
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/AGENTS.md +66 -0
- package/lib/build/dev.js +252 -355
- package/lib/build/iiif.js +19 -50
- package/lib/build/mdx.js +42 -76
- package/lib/build/pages.js +1 -5
- package/lib/build/runtimes.js +40 -103
- package/lib/build/search.js +2 -5
- package/lib/build/styles.js +9 -15
- package/lib/common.js +16 -8
- package/lib/head.js +21 -0
- package/lib/index.js +5 -1
- package/lib/search/command-runtime.js +370 -0
- package/lib/search/search-app.jsx +2 -2
- package/lib/search/search.js +12 -191
- package/package.json +10 -3
- package/ui/dist/index.mjs +108 -83
- package/ui/dist/index.mjs.map +4 -4
- package/ui/dist/server.mjs +108 -70
- package/ui/dist/server.mjs.map +4 -4
- package/ui/styles/base/_common.scss +8 -0
- package/ui/styles/base/index.scss +1 -0
- package/ui/styles/components/_command.scss +84 -1
- package/ui/styles/components/_header.scss +0 -0
- package/ui/styles/components/_hero.scss +22 -0
- package/ui/styles/components/index.scss +2 -3
- package/ui/styles/index.css +106 -1
- package/ui/styles/index.scss +3 -2
- package/ui/tailwind-canopy-iiif-plugin.js +7 -12
- package/ui/tailwind-canopy-iiif-preset.js +15 -0
package/lib/build/dev.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
2
|
const fsp = fs.promises;
|
|
3
3
|
const path = require("path");
|
|
4
|
-
const { spawn } = require("child_process");
|
|
4
|
+
const { spawn, spawnSync } = require("child_process");
|
|
5
5
|
const { build } = require("../build/build");
|
|
6
6
|
const http = require("http");
|
|
7
7
|
const url = require("url");
|
|
@@ -11,30 +11,17 @@ const {
|
|
|
11
11
|
ASSETS_DIR,
|
|
12
12
|
ensureDirSync,
|
|
13
13
|
} = require("../common");
|
|
14
|
-
const twHelper = (() => {
|
|
15
|
-
try {
|
|
16
|
-
return require("../../helpers/build-tailwind");
|
|
17
|
-
} catch (_) {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
})();
|
|
21
14
|
function resolveTailwindCli() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
".bin",
|
|
31
|
-
process.platform === "win32" ? "tailwindcss.cmd" : "tailwindcss"
|
|
32
|
-
);
|
|
33
|
-
if (fs.existsSync(bin)) return { cmd: bin, args: [] };
|
|
34
|
-
} catch (_) {}
|
|
35
|
-
return null;
|
|
15
|
+
const bin = path.join(
|
|
16
|
+
process.cwd(),
|
|
17
|
+
"node_modules",
|
|
18
|
+
".bin",
|
|
19
|
+
process.platform === "win32" ? "tailwindcss.cmd" : "tailwindcss"
|
|
20
|
+
);
|
|
21
|
+
if (fs.existsSync(bin)) return { cmd: bin, args: [] };
|
|
22
|
+
return { cmd: 'tailwindcss', args: [] };
|
|
36
23
|
}
|
|
37
|
-
const PORT = Number(process.env.PORT ||
|
|
24
|
+
const PORT = Number(process.env.PORT || 5001);
|
|
38
25
|
let onBuildSuccess = () => {};
|
|
39
26
|
let onBuildStart = () => {};
|
|
40
27
|
let onCssChange = () => {};
|
|
@@ -609,381 +596,291 @@ async function dev() {
|
|
|
609
596
|
"tailwind.config.mjs",
|
|
610
597
|
"tailwind.config.ts",
|
|
611
598
|
].map((n) => path.join(appStylesDir, n));
|
|
612
|
-
|
|
599
|
+
const configPath = [...twConfigsApp, ...twConfigsRoot].find((p) => {
|
|
613
600
|
try {
|
|
614
601
|
return fs.existsSync(p);
|
|
615
602
|
} catch (_) {
|
|
616
603
|
return false;
|
|
617
604
|
}
|
|
618
605
|
});
|
|
606
|
+
if (!configPath) {
|
|
607
|
+
throw new Error(
|
|
608
|
+
"[tailwind] Missing Tailwind config. Expected app/styles/tailwind.config.{js,cjs,mjs,ts} or a root-level Tailwind config."
|
|
609
|
+
);
|
|
610
|
+
}
|
|
619
611
|
const inputCandidates = [
|
|
620
612
|
path.join(appStylesDir, "index.css"),
|
|
621
613
|
path.join(CONTENT_DIR, "_styles.css"),
|
|
622
614
|
];
|
|
623
|
-
|
|
615
|
+
const inputCss = inputCandidates.find((p) => {
|
|
624
616
|
try {
|
|
625
617
|
return fs.existsSync(p);
|
|
626
618
|
} catch (_) {
|
|
627
619
|
return false;
|
|
628
620
|
}
|
|
629
621
|
});
|
|
630
|
-
// Generate fallback config and input if missing
|
|
631
|
-
if (!configPath) {
|
|
632
|
-
try {
|
|
633
|
-
const { CACHE_DIR } = require("./common");
|
|
634
|
-
const genDir = path.join(CACHE_DIR, "tailwind");
|
|
635
|
-
ensureDirSync(genDir);
|
|
636
|
-
const genCfg = path.join(genDir, "tailwind.config.js");
|
|
637
|
-
const cfg = `module.exports = {\n presets: [require('@canopy-iiif/app/ui/canopy-iiif-preset')],\n content: [\n './content/**/*.{mdx,html}',\n './site/**/*.html',\n './site/**/*.js',\n './packages/app/ui/**/*.{js,jsx,ts,tsx}',\n './packages/app/lib/iiif/components/**/*.{js,jsx}',\n ],\n theme: { extend: {} },\n plugins: [require('@canopy-iiif/app/ui/canopy-iiif-plugin')],\n};\n`;
|
|
638
|
-
fs.writeFileSync(genCfg, cfg, "utf8");
|
|
639
|
-
configPath = genCfg;
|
|
640
|
-
} catch (_) {
|
|
641
|
-
configPath = null;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
622
|
if (!inputCss) {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
ensureDirSync(genDir);
|
|
649
|
-
const genCss = path.join(genDir, "index.css");
|
|
650
|
-
fs.writeFileSync(
|
|
651
|
-
genCss,
|
|
652
|
-
`@tailwind base;\n@tailwind components;\n@tailwind utilities;\n`,
|
|
653
|
-
"utf8"
|
|
654
|
-
);
|
|
655
|
-
inputCss = genCss;
|
|
656
|
-
} catch (_) {
|
|
657
|
-
inputCss = null;
|
|
658
|
-
}
|
|
623
|
+
throw new Error(
|
|
624
|
+
"[tailwind] Missing Tailwind entry stylesheet. Create app/styles/index.css (or content/_styles.css)."
|
|
625
|
+
);
|
|
659
626
|
}
|
|
660
627
|
const outputCss = path.join(OUT_DIR, "styles", "styles.css");
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
}
|
|
677
|
-
} catch (_) {}
|
|
628
|
+
ensureDirSync(path.dirname(outputCss));
|
|
629
|
+
|
|
630
|
+
const cli = resolveTailwindCli();
|
|
631
|
+
if (!cli) {
|
|
632
|
+
throw new Error(
|
|
633
|
+
"[tailwind] Tailwind CLI not found. Install the 'tailwindcss' package in the workspace."
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
const fileSizeKb = (p) => {
|
|
638
|
+
try {
|
|
639
|
+
const st = fs.statSync(p);
|
|
640
|
+
return st && st.size ? (st.size / 1024).toFixed(1) : "0.0";
|
|
641
|
+
} catch (_) {
|
|
642
|
+
return "0.0";
|
|
678
643
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
const baseArgs = [
|
|
647
|
+
"-i",
|
|
648
|
+
inputCss,
|
|
649
|
+
"-o",
|
|
650
|
+
outputCss,
|
|
651
|
+
"-c",
|
|
652
|
+
configPath,
|
|
653
|
+
"--minify",
|
|
654
|
+
];
|
|
655
|
+
|
|
656
|
+
const initial = spawnSync(cli.cmd, [...cli.args, ...baseArgs], {
|
|
657
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
658
|
+
env: { ...process.env, BROWSERSLIST_IGNORE_OLD_DATA: "1" },
|
|
659
|
+
});
|
|
660
|
+
if (!initial || initial.status !== 0) {
|
|
661
|
+
if (initial && initial.stderr) {
|
|
662
|
+
try { process.stderr.write(initial.stderr); } catch (_) {}
|
|
686
663
|
}
|
|
687
|
-
|
|
664
|
+
throw new Error("[tailwind] Initial Tailwind build failed.");
|
|
665
|
+
}
|
|
666
|
+
console.log(
|
|
667
|
+
`[tailwind] initial build ok (${fileSizeKb(outputCss)} KB) →`,
|
|
668
|
+
prettyPath(outputCss)
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
const watchArgs = [
|
|
672
|
+
"-i",
|
|
673
|
+
inputCss,
|
|
674
|
+
"-o",
|
|
675
|
+
outputCss,
|
|
676
|
+
"--watch",
|
|
677
|
+
"-c",
|
|
678
|
+
configPath,
|
|
679
|
+
"--minify",
|
|
680
|
+
];
|
|
681
|
+
let child = null;
|
|
682
|
+
let unmuted = false;
|
|
683
|
+
let cssWatcherAttached = false;
|
|
684
|
+
|
|
685
|
+
function attachCssWatcherOnce() {
|
|
686
|
+
if (cssWatcherAttached) return;
|
|
687
|
+
cssWatcherAttached = true;
|
|
688
688
|
try {
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
const argsOnce = [
|
|
693
|
-
"-i",
|
|
694
|
-
inputCss,
|
|
695
|
-
"-o",
|
|
696
|
-
outputCss,
|
|
697
|
-
"-c",
|
|
698
|
-
configPath,
|
|
699
|
-
"--minify",
|
|
700
|
-
];
|
|
701
|
-
const res = spawnSync(cliOnce.cmd, [...cliOnce.args, ...argsOnce], {
|
|
702
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
703
|
-
env: { ...process.env, BROWSERSLIST_IGNORE_OLD_DATA: "1" },
|
|
704
|
-
});
|
|
705
|
-
if (res && res.status === 0) {
|
|
689
|
+
fs.watch(outputCss, { persistent: false }, () => {
|
|
690
|
+
if (!unmuted) {
|
|
691
|
+
unmuted = true;
|
|
706
692
|
console.log(
|
|
707
|
-
`[tailwind]
|
|
708
|
-
|
|
693
|
+
`[tailwind] watching ${prettyPath(
|
|
694
|
+
inputCss
|
|
695
|
+
)} — compiled (${fileSizeKb(outputCss)} KB)`
|
|
709
696
|
);
|
|
710
|
-
} else {
|
|
711
|
-
console.warn("[tailwind] initial build failed; using fallback CSS");
|
|
712
|
-
try {
|
|
713
|
-
if (res && res.stderr) process.stderr.write(res.stderr);
|
|
714
|
-
} catch (_) {}
|
|
715
|
-
writeFallbackCssIfMissing();
|
|
716
697
|
}
|
|
717
|
-
} else {
|
|
718
|
-
console.warn("[tailwind] CLI not found; using fallback CSS");
|
|
719
|
-
writeFallbackCssIfMissing();
|
|
720
|
-
}
|
|
721
|
-
} catch (_) {}
|
|
722
|
-
// Prefer direct CLI spawn so we can mute initial rebuild logs
|
|
723
|
-
const cli = resolveTailwindCli();
|
|
724
|
-
if (cli) {
|
|
725
|
-
const args = [
|
|
726
|
-
"-i",
|
|
727
|
-
inputCss,
|
|
728
|
-
"-o",
|
|
729
|
-
outputCss,
|
|
730
|
-
"--watch",
|
|
731
|
-
"-c",
|
|
732
|
-
configPath,
|
|
733
|
-
"--minify",
|
|
734
|
-
];
|
|
735
|
-
let unmuted = false;
|
|
736
|
-
let cssWatcherAttached = false;
|
|
737
|
-
function attachCssWatcherOnce() {
|
|
738
|
-
if (cssWatcherAttached) return;
|
|
739
|
-
cssWatcherAttached = true;
|
|
740
698
|
try {
|
|
741
|
-
|
|
742
|
-
if (!unmuted) {
|
|
743
|
-
unmuted = true;
|
|
744
|
-
console.log(
|
|
745
|
-
`[tailwind] watching ${prettyPath(
|
|
746
|
-
inputCss
|
|
747
|
-
)} — compiled (${fileSizeKb(outputCss)} KB)`
|
|
748
|
-
);
|
|
749
|
-
}
|
|
750
|
-
try {
|
|
751
|
-
onCssChange();
|
|
752
|
-
} catch (_) {}
|
|
753
|
-
});
|
|
699
|
+
onCssChange();
|
|
754
700
|
} catch (_) {}
|
|
701
|
+
});
|
|
702
|
+
} catch (_) {}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
function compileTailwindOnce() {
|
|
706
|
+
const res = spawnSync(cli.cmd, [...cli.args, ...baseArgs], {
|
|
707
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
708
|
+
env: { ...process.env, BROWSERSLIST_IGNORE_OLD_DATA: "1" },
|
|
709
|
+
});
|
|
710
|
+
if (!res || res.status !== 0) {
|
|
711
|
+
if (res && res.stderr) {
|
|
712
|
+
try { process.stderr.write(res.stderr); } catch (_) {}
|
|
755
713
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
prettyPath(outputCss)
|
|
780
|
-
);
|
|
781
|
-
try {
|
|
782
|
-
onCssChange();
|
|
783
|
-
} catch (_) {}
|
|
784
|
-
} else {
|
|
785
|
-
console.warn("[tailwind] on-demand compile failed");
|
|
786
|
-
try {
|
|
787
|
-
if (res && res.stderr) process.stderr.write(res.stderr);
|
|
788
|
-
} catch (_) {}
|
|
714
|
+
throw new Error("[tailwind] On-demand Tailwind compile failed.");
|
|
715
|
+
}
|
|
716
|
+
console.log(
|
|
717
|
+
`[tailwind] compiled (${fileSizeKb(outputCss)} KB) →`,
|
|
718
|
+
prettyPath(outputCss)
|
|
719
|
+
);
|
|
720
|
+
try {
|
|
721
|
+
onCssChange();
|
|
722
|
+
} catch (_) {}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
function startTailwindWatcher() {
|
|
726
|
+
unmuted = false;
|
|
727
|
+
const proc = spawn(cli.cmd, [...cli.args, ...watchArgs], {
|
|
728
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
729
|
+
env: { ...process.env, BROWSERSLIST_IGNORE_OLD_DATA: "1" },
|
|
730
|
+
});
|
|
731
|
+
if (proc.stdout)
|
|
732
|
+
proc.stdout.on("data", (d) => {
|
|
733
|
+
const s = d ? String(d) : "";
|
|
734
|
+
if (!unmuted) {
|
|
735
|
+
if (/error/i.test(s)) {
|
|
736
|
+
try { process.stdout.write("[tailwind] " + s); } catch (_) {}
|
|
789
737
|
}
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
const s = d ? String(d) : "";
|
|
801
|
-
if (!unmuted) {
|
|
802
|
-
if (/error/i.test(s)) {
|
|
803
|
-
try {
|
|
804
|
-
process.stdout.write("[tailwind] " + s);
|
|
805
|
-
} catch (_) {}
|
|
806
|
-
}
|
|
807
|
-
} else {
|
|
808
|
-
try {
|
|
809
|
-
process.stdout.write(s);
|
|
810
|
-
} catch (_) {}
|
|
811
|
-
}
|
|
812
|
-
});
|
|
813
|
-
if (proc.stderr)
|
|
814
|
-
proc.stderr.on("data", (d) => {
|
|
815
|
-
const s = d ? String(d) : "";
|
|
816
|
-
if (!unmuted) {
|
|
817
|
-
if (s.trim()) {
|
|
818
|
-
try {
|
|
819
|
-
process.stderr.write("[tailwind] " + s);
|
|
820
|
-
} catch (_) {}
|
|
821
|
-
}
|
|
822
|
-
} else {
|
|
823
|
-
try {
|
|
824
|
-
process.stderr.write(s);
|
|
825
|
-
} catch (_) {}
|
|
826
|
-
}
|
|
827
|
-
});
|
|
828
|
-
proc.on("exit", (code) => {
|
|
829
|
-
// Ignore null exits (expected when we intentionally restart the watcher)
|
|
830
|
-
if (code !== 0 && code !== null) {
|
|
831
|
-
console.error("[tailwind] watcher exited with code", code);
|
|
738
|
+
} else {
|
|
739
|
+
try { process.stdout.write(s); } catch (_) {}
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
if (proc.stderr)
|
|
743
|
+
proc.stderr.on("data", (d) => {
|
|
744
|
+
const s = d ? String(d) : "";
|
|
745
|
+
if (!unmuted) {
|
|
746
|
+
if (s.trim()) {
|
|
747
|
+
try { process.stderr.write("[tailwind] " + s); } catch (_) {}
|
|
832
748
|
}
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
|
|
749
|
+
} else {
|
|
750
|
+
try { process.stderr.write(s); } catch (_) {}
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
proc.on("exit", (code) => {
|
|
754
|
+
if (code !== null && code !== 0) {
|
|
755
|
+
console.error("[tailwind] watcher exited with code", code);
|
|
756
|
+
process.exit(typeof code === "number" ? code : 1);
|
|
836
757
|
}
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
758
|
+
});
|
|
759
|
+
attachCssWatcherOnce();
|
|
760
|
+
return proc;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
const safeCompile = (label) => {
|
|
764
|
+
try {
|
|
765
|
+
compileTailwindOnce();
|
|
766
|
+
} catch (err) {
|
|
767
|
+
console.error(label ? `${label}: ${err.message || err}` : err);
|
|
768
|
+
process.exit(1);
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
|
|
772
|
+
child = startTailwindWatcher();
|
|
773
|
+
|
|
774
|
+
const uiPlugin = path.join(
|
|
775
|
+
__dirname,
|
|
776
|
+
"../ui",
|
|
777
|
+
"tailwind-canopy-iiif-plugin.js"
|
|
778
|
+
);
|
|
779
|
+
const uiPreset = path.join(
|
|
780
|
+
__dirname,
|
|
781
|
+
"../ui",
|
|
782
|
+
"tailwind-canopy-iiif-preset.js"
|
|
783
|
+
);
|
|
784
|
+
const uiStylesDir = path.join(__dirname, "../ui", "styles");
|
|
785
|
+
const files = [uiPlugin, uiPreset].filter((p) => {
|
|
786
|
+
try {
|
|
787
|
+
return fs.existsSync(p);
|
|
788
|
+
} catch (_) {
|
|
789
|
+
return false;
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
let restartTimer = null;
|
|
793
|
+
const restart = () => {
|
|
794
|
+
clearTimeout(restartTimer);
|
|
795
|
+
restartTimer = setTimeout(() => {
|
|
796
|
+
console.log(
|
|
797
|
+
"[tailwind] detected UI plugin/preset change — restarting Tailwind"
|
|
798
|
+
);
|
|
840
799
|
try {
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
let restartTimer = null;
|
|
860
|
-
const restart = () => {
|
|
861
|
-
clearTimeout(restartTimer);
|
|
862
|
-
restartTimer = setTimeout(() => {
|
|
863
|
-
console.log(
|
|
864
|
-
"[tailwind] detected UI plugin/preset change — restarting Tailwind"
|
|
865
|
-
);
|
|
866
|
-
try {
|
|
867
|
-
if (child && !child.killed) child.kill();
|
|
868
|
-
} catch (_) {}
|
|
869
|
-
// Force a compile immediately so new CSS lands before reload
|
|
870
|
-
compileTailwindOnce();
|
|
871
|
-
child = startTailwindWatcher();
|
|
872
|
-
// Notify clients that a rebuild is in progress; CSS watcher will trigger reload on write
|
|
873
|
-
try {
|
|
874
|
-
onBuildStart();
|
|
875
|
-
} catch (_) {}
|
|
876
|
-
}, 50);
|
|
877
|
-
};
|
|
878
|
-
for (const f of files) {
|
|
800
|
+
if (child && !child.killed) child.kill();
|
|
801
|
+
} catch (_) {}
|
|
802
|
+
safeCompile("[tailwind] compile after plugin change failed");
|
|
803
|
+
child = startTailwindWatcher();
|
|
804
|
+
try { onBuildStart(); } catch (_) {}
|
|
805
|
+
}, 50);
|
|
806
|
+
};
|
|
807
|
+
for (const f of files) {
|
|
808
|
+
try {
|
|
809
|
+
fs.watch(f, { persistent: false }, restart);
|
|
810
|
+
} catch (_) {}
|
|
811
|
+
}
|
|
812
|
+
if (fs.existsSync(uiStylesDir)) {
|
|
813
|
+
try {
|
|
814
|
+
fs.watch(
|
|
815
|
+
uiStylesDir,
|
|
816
|
+
{ persistent: false, recursive: true },
|
|
817
|
+
(evt, fn) => {
|
|
879
818
|
try {
|
|
880
|
-
|
|
819
|
+
if (fn && /\.s[ac]ss$/i.test(String(fn))) restart();
|
|
881
820
|
} catch (_) {}
|
|
882
821
|
}
|
|
883
|
-
|
|
822
|
+
);
|
|
823
|
+
} catch (_) {
|
|
824
|
+
const watchers = new Map();
|
|
825
|
+
const watchDir = (dir) => {
|
|
826
|
+
if (watchers.has(dir)) return;
|
|
884
827
|
try {
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
(
|
|
891
|
-
|
|
892
|
-
if (fn && /\.s[ac]ss$/i.test(String(fn))) restart();
|
|
893
|
-
} catch (_) {}
|
|
894
|
-
}
|
|
895
|
-
);
|
|
896
|
-
} catch (_) {
|
|
897
|
-
// Fallback: per-dir watch without recursion
|
|
898
|
-
const watchers = new Map();
|
|
899
|
-
const watchDir = (dir) => {
|
|
900
|
-
if (watchers.has(dir)) return;
|
|
901
|
-
try {
|
|
902
|
-
const w = fs.watch(
|
|
903
|
-
dir,
|
|
904
|
-
{ persistent: false },
|
|
905
|
-
(evt, fn) => {
|
|
906
|
-
try {
|
|
907
|
-
if (fn && /\.s[ac]ss$/i.test(String(fn))) restart();
|
|
908
|
-
} catch (_) {}
|
|
909
|
-
}
|
|
910
|
-
);
|
|
911
|
-
watchers.set(dir, w);
|
|
912
|
-
} catch (_) {}
|
|
913
|
-
};
|
|
914
|
-
const scan = (dir) => {
|
|
915
|
-
try {
|
|
916
|
-
const entries = fs.readdirSync(dir, {
|
|
917
|
-
withFileTypes: true,
|
|
918
|
-
});
|
|
919
|
-
for (const e of entries) {
|
|
920
|
-
const p = path.join(dir, e.name);
|
|
921
|
-
if (e.isDirectory()) {
|
|
922
|
-
watchDir(p);
|
|
923
|
-
scan(p);
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
} catch (_) {}
|
|
927
|
-
};
|
|
928
|
-
watchDir(uiStylesDir);
|
|
929
|
-
scan(uiStylesDir);
|
|
828
|
+
const w = fs.watch(
|
|
829
|
+
dir,
|
|
830
|
+
{ persistent: false },
|
|
831
|
+
(evt, fn) => {
|
|
832
|
+
try {
|
|
833
|
+
if (fn && /\.s[ac]ss$/i.test(String(fn))) restart();
|
|
834
|
+
} catch (_) {}
|
|
930
835
|
}
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
// Also watch the app Tailwind config; restart Tailwind when it changes
|
|
934
|
-
try {
|
|
935
|
-
if (configPath && fs.existsSync(configPath))
|
|
936
|
-
fs.watch(configPath, { persistent: false }, () => {
|
|
937
|
-
console.log(
|
|
938
|
-
"[tailwind] tailwind.config change — restarting Tailwind"
|
|
939
|
-
);
|
|
940
|
-
restart();
|
|
941
|
-
});
|
|
942
|
-
} catch (_) {}
|
|
943
|
-
// If the input CSS lives under app/styles, watch the directory for direct edits to CSS/partials
|
|
944
|
-
try {
|
|
945
|
-
const stylesDir = path.dirname(inputCss || "");
|
|
946
|
-
if (stylesDir && stylesDir.includes(path.join("app", "styles"))) {
|
|
947
|
-
let cssDebounce = null;
|
|
948
|
-
fs.watch(stylesDir, { persistent: false }, (evt, fn) => {
|
|
949
|
-
clearTimeout(cssDebounce);
|
|
950
|
-
cssDebounce = setTimeout(() => {
|
|
951
|
-
try {
|
|
952
|
-
onBuildStart();
|
|
953
|
-
} catch (_) {}
|
|
954
|
-
// Force a compile so changes in index.css or partials are reflected immediately
|
|
955
|
-
try {
|
|
956
|
-
compileTailwindOnce();
|
|
957
|
-
} catch (_) {}
|
|
958
|
-
try {
|
|
959
|
-
onCssChange();
|
|
960
|
-
} catch (_) {}
|
|
961
|
-
}, 50);
|
|
962
|
-
});
|
|
963
|
-
}
|
|
836
|
+
);
|
|
837
|
+
watchers.set(dir, w);
|
|
964
838
|
} catch (_) {}
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
// Fallback to helper (cannot mute its initial logs)
|
|
968
|
-
child = twHelper.watchTailwind({
|
|
969
|
-
input: inputCss,
|
|
970
|
-
output: outputCss,
|
|
971
|
-
config: configPath,
|
|
972
|
-
minify: false,
|
|
973
|
-
});
|
|
974
|
-
if (child) {
|
|
975
|
-
console.log("[tailwind] watching", prettyPath(inputCss));
|
|
839
|
+
};
|
|
840
|
+
const scan = (dir) => {
|
|
976
841
|
try {
|
|
977
|
-
fs.
|
|
978
|
-
|
|
979
|
-
onCssChange();
|
|
980
|
-
} catch (_) {}
|
|
842
|
+
const entries = fs.readdirSync(dir, {
|
|
843
|
+
withFileTypes: true,
|
|
981
844
|
});
|
|
845
|
+
for (const e of entries) {
|
|
846
|
+
const p = path.join(dir, e.name);
|
|
847
|
+
if (e.isDirectory()) {
|
|
848
|
+
watchDir(p);
|
|
849
|
+
scan(p);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
982
852
|
} catch (_) {}
|
|
983
|
-
}
|
|
853
|
+
};
|
|
854
|
+
watchDir(uiStylesDir);
|
|
855
|
+
scan(uiStylesDir);
|
|
984
856
|
}
|
|
985
857
|
}
|
|
986
|
-
|
|
858
|
+
if (fs.existsSync(configPath)) {
|
|
859
|
+
try {
|
|
860
|
+
fs.watch(configPath, { persistent: false }, () => {
|
|
861
|
+
console.log("[tailwind] tailwind.config change — restarting Tailwind");
|
|
862
|
+
restart();
|
|
863
|
+
});
|
|
864
|
+
} catch (_) {}
|
|
865
|
+
}
|
|
866
|
+
const stylesDir = path.dirname(inputCss);
|
|
867
|
+
if (stylesDir && stylesDir.includes(path.join("app", "styles"))) {
|
|
868
|
+
let cssDebounce = null;
|
|
869
|
+
try {
|
|
870
|
+
fs.watch(stylesDir, { persistent: false }, (evt, fn) => {
|
|
871
|
+
clearTimeout(cssDebounce);
|
|
872
|
+
cssDebounce = setTimeout(() => {
|
|
873
|
+
try { onBuildStart(); } catch (_) {}
|
|
874
|
+
safeCompile("[tailwind] compile after CSS change failed");
|
|
875
|
+
try { onCssChange(); } catch (_) {}
|
|
876
|
+
}, 50);
|
|
877
|
+
});
|
|
878
|
+
} catch (_) {}
|
|
879
|
+
}
|
|
880
|
+
} catch (err) {
|
|
881
|
+
console.error("[tailwind] setup failed:", err && err.message ? err.message : err);
|
|
882
|
+
process.exit(1);
|
|
883
|
+
}
|
|
987
884
|
console.log("[Watching]", prettyPath(CONTENT_DIR), "(Ctrl+C to stop)");
|
|
988
885
|
const rw = tryRecursiveWatch();
|
|
989
886
|
if (!rw) watchPerDir();
|