swatchkit 0.5.0 → 0.6.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/README.md +20 -3
- package/build.js +58 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ my-project/
|
|
|
36
36
|
│ ├── colors.html
|
|
37
37
|
│ ├── typography.html
|
|
38
38
|
│ └── ...
|
|
39
|
-
└──
|
|
39
|
+
└── dist/
|
|
40
40
|
└── swatchkit/ # Built pattern library
|
|
41
41
|
└── index.html
|
|
42
42
|
```
|
|
@@ -207,7 +207,7 @@ Copies "blueprints" into your project to get you started.
|
|
|
207
207
|
* **`swatchkit/`**: Sets up the documentation structure and layout.
|
|
208
208
|
|
|
209
209
|
### 2. `swatchkit` (Build Process)
|
|
210
|
-
Compiles your documentation site into `
|
|
210
|
+
Compiles your documentation site into `dist/swatchkit/`.
|
|
211
211
|
|
|
212
212
|
1. **Reads JSON Tokens**: Scans `tokens/*.json` and calculates fluid typography/spacing.
|
|
213
213
|
2. **Generates CSS**: Creates `css/tokens.css`. **Do not edit this file**; it is overwritten every build.
|
|
@@ -249,7 +249,7 @@ swatchkit [command] [options]
|
|
|
249
249
|
| `--watch` | `-w` | Watch files and rebuild on change. |
|
|
250
250
|
| `--config` | `-c` | Path to config file. |
|
|
251
251
|
| `--input` | `-i` | Pattern directory (Default: `swatchkit/`). |
|
|
252
|
-
| `--outDir` | `-o` | Output directory (Default: `
|
|
252
|
+
| `--outDir` | `-o` | Output directory (Default: `dist/swatchkit`). |
|
|
253
253
|
| `--force` | `-f` | Overwrite layout file during init. |
|
|
254
254
|
|
|
255
255
|
## Configuration
|
|
@@ -275,6 +275,23 @@ module.exports = {
|
|
|
275
275
|
};
|
|
276
276
|
```
|
|
277
277
|
|
|
278
|
+
## Using with a Framework
|
|
279
|
+
|
|
280
|
+
SwatchKit outputs to `dist/swatchkit/` by default. If your framework (Vite, Astro, etc.) cleans the `dist/` directory during its build, run SwatchKit **after** your framework build:
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
{
|
|
284
|
+
"scripts": {
|
|
285
|
+
"build": "vite build && swatchkit",
|
|
286
|
+
"dev": "vite dev & swatchkit -w"
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
In watch mode, SwatchKit detects when its output directory is deleted by an external tool and automatically rebuilds.
|
|
292
|
+
|
|
293
|
+
SwatchKit only ever writes inside its own output subdirectory — it will never modify or delete other files in `dist/`.
|
|
294
|
+
|
|
278
295
|
## Acknowledgements
|
|
279
296
|
|
|
280
297
|
The CSS compositions included by default in SwatchKit are adapted from [Every Layout](https://every-layout.dev/) by Heydon Pickering and Andy Bell. Highly recommend their documentation for a deep dive into their brilliant CSS techniques.
|
package/build.js
CHANGED
|
@@ -110,12 +110,12 @@ function resolveSettings(cliOptions, fileConfig) {
|
|
|
110
110
|
const swatchkitDir = findSwatchkitDir();
|
|
111
111
|
|
|
112
112
|
// Output Dir
|
|
113
|
-
// Default:
|
|
113
|
+
// Default: dist/swatchkit
|
|
114
114
|
const outDir = cliOptions.outDir
|
|
115
115
|
? path.resolve(cwd, cliOptions.outDir)
|
|
116
116
|
: fileConfig.outDir
|
|
117
117
|
? path.resolve(cwd, fileConfig.outDir)
|
|
118
|
-
: path.join(cwd, "
|
|
118
|
+
: path.join(cwd, "dist/swatchkit");
|
|
119
119
|
|
|
120
120
|
// CSS directory - where tokens.css and user's main.css live
|
|
121
121
|
// Default: css/ at project root
|
|
@@ -428,6 +428,24 @@ ${scriptContent}
|
|
|
428
428
|
return swatches;
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
+
function validateOutDir(outDir) {
|
|
432
|
+
const cwd = process.cwd();
|
|
433
|
+
const relative = path.relative(cwd, outDir);
|
|
434
|
+
|
|
435
|
+
if (
|
|
436
|
+
!relative || // outDir === cwd
|
|
437
|
+
relative === '..' || // above cwd
|
|
438
|
+
relative.startsWith('../') || // above cwd
|
|
439
|
+
path.isAbsolute(relative) || // different drive/root
|
|
440
|
+
relative.split(path.sep).length < 2 // top-level dir like "dist" with no subfolder
|
|
441
|
+
) {
|
|
442
|
+
console.error(
|
|
443
|
+
`[SwatchKit] Refusing to clean outDir "${outDir}" — must be a subdirectory at least 2 levels deep (e.g., dist/swatchkit).`,
|
|
444
|
+
);
|
|
445
|
+
process.exit(1);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
431
449
|
function build(settings) {
|
|
432
450
|
console.log(`[SwatchKit] Starting build...`);
|
|
433
451
|
console.log(` Source: ${settings.swatchkitDir}`);
|
|
@@ -442,7 +460,13 @@ function build(settings) {
|
|
|
442
460
|
process.exit(1);
|
|
443
461
|
}
|
|
444
462
|
|
|
445
|
-
// 2.
|
|
463
|
+
// 2. Clean previous output (only our subdirectory, never the parent)
|
|
464
|
+
validateOutDir(settings.outDir);
|
|
465
|
+
if (fs.existsSync(settings.outDir)) {
|
|
466
|
+
fs.rmSync(settings.outDir, { recursive: true });
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// 3. Ensure dist directories exist
|
|
446
470
|
[settings.outDir, settings.distCssDir, settings.distJsDir].forEach((dir) => {
|
|
447
471
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
448
472
|
});
|
|
@@ -683,7 +707,7 @@ function build(settings) {
|
|
|
683
707
|
|
|
684
708
|
// --- 6. Watch Logic ---
|
|
685
709
|
function watch(settings) {
|
|
686
|
-
const
|
|
710
|
+
const sourcePaths = [
|
|
687
711
|
settings.swatchkitDir,
|
|
688
712
|
settings.tokensDir,
|
|
689
713
|
settings.projectLayout,
|
|
@@ -692,30 +716,56 @@ function watch(settings) {
|
|
|
692
716
|
|
|
693
717
|
console.log("[SwatchKit] Watch mode enabled.");
|
|
694
718
|
console.log("Watching for changes in:");
|
|
695
|
-
|
|
719
|
+
sourcePaths.forEach((p) => console.log(` - ${p}`));
|
|
720
|
+
console.log(` Polling: ${settings.outDir} (rebuild if deleted by external tools)`);
|
|
696
721
|
|
|
697
722
|
let buildTimeout;
|
|
723
|
+
let isRebuilding = false;
|
|
724
|
+
|
|
698
725
|
const rebuild = () => {
|
|
699
726
|
if (buildTimeout) clearTimeout(buildTimeout);
|
|
700
727
|
buildTimeout = setTimeout(() => {
|
|
701
728
|
try {
|
|
729
|
+
isRebuilding = true;
|
|
702
730
|
console.log("[SwatchKit] Change detected. Rebuilding...");
|
|
703
731
|
build(settings);
|
|
704
732
|
} catch (e) {
|
|
705
733
|
console.error("[SwatchKit] Build failed:", e.message);
|
|
734
|
+
} finally {
|
|
735
|
+
isRebuilding = false;
|
|
706
736
|
}
|
|
707
737
|
}, 100); // 100ms debounce
|
|
708
738
|
};
|
|
709
739
|
|
|
710
|
-
|
|
711
|
-
|
|
740
|
+
// Watch source files for changes.
|
|
741
|
+
// Ignore the tokens UI directory inside swatchkitDir — the build generates
|
|
742
|
+
// HTML files there (swatchkit/tokens/*.html), which would retrigger the
|
|
743
|
+
// watcher and cause an infinite rebuild loop.
|
|
744
|
+
const tokensUiDir = path.join(settings.swatchkitDir, "tokens");
|
|
745
|
+
|
|
746
|
+
const sourceWatcher = chokidar.watch(sourcePaths, {
|
|
747
|
+
ignored: [
|
|
748
|
+
/(^|[\/\\])\../, // ignore dotfiles
|
|
749
|
+
tokensUiDir, // ignore build-generated token HTML
|
|
750
|
+
],
|
|
712
751
|
persistent: true,
|
|
713
752
|
ignoreInitial: true,
|
|
714
753
|
});
|
|
715
754
|
|
|
716
|
-
|
|
755
|
+
sourceWatcher.on("all", () => {
|
|
717
756
|
rebuild();
|
|
718
757
|
});
|
|
758
|
+
|
|
759
|
+
// Poll for output directory deletion (e.g., when a framework build wipes dist/).
|
|
760
|
+
// We use polling instead of a chokidar watcher on the output dir to avoid
|
|
761
|
+
// infinite rebuild loops — since our own build deletes and recreates the
|
|
762
|
+
// output directory, an event-based watcher would retrigger endlessly.
|
|
763
|
+
setInterval(() => {
|
|
764
|
+
if (!isRebuilding && !fs.existsSync(settings.outDir)) {
|
|
765
|
+
console.log("[SwatchKit] Output directory was deleted. Rebuilding...");
|
|
766
|
+
rebuild();
|
|
767
|
+
}
|
|
768
|
+
}, 2000);
|
|
719
769
|
}
|
|
720
770
|
|
|
721
771
|
// --- Main Execution ---
|