swatchkit 0.6.2 → 0.8.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/README.md +95 -12
- package/build.js +222 -152
- package/package.json +1 -1
- package/src/layout.html +2 -2
package/README.md
CHANGED
|
@@ -201,10 +201,17 @@ SwatchKit automatically bundles your JS files, wraps them in a safety scope (IIF
|
|
|
201
201
|
Understanding the build pipeline helps you know which files to edit and which are generated.
|
|
202
202
|
|
|
203
203
|
### 1. `swatchkit init` (Scaffolding)
|
|
204
|
-
Copies "blueprints" into your project to get you started.
|
|
204
|
+
Copies "blueprints" into your project to get you started. Init tracks a manifest of every file it manages (token JSONs, CSS blueprints, layout templates) so it can report what's new, changed, or up to date.
|
|
205
|
+
|
|
206
|
+
* **Fresh project:** Creates directories and copies all blueprint files.
|
|
207
|
+
* **Already initialized:** Prints a status report comparing your files to the latest blueprints. Suggests `--force` if anything has changed.
|
|
208
|
+
* **`--force`:** Overwrites all init-managed files with the latest blueprints. Your custom swatch HTML files and any CSS files without blueprint counterparts are never touched.
|
|
209
|
+
* **`--dry-run`:** Shows what would happen without writing anything.
|
|
210
|
+
|
|
211
|
+
Files created:
|
|
205
212
|
* **`tokens/*.json`**: These are your **Source of Truth**. You edit these files.
|
|
206
|
-
* **`css/`**: Copies static CSS files (`main.css`, `reset.css`, etc.). **You own these files**.
|
|
207
|
-
* **`swatchkit/`**: Sets up the documentation structure and
|
|
213
|
+
* **`css/`**: Copies static CSS files (`main.css`, `reset.css`, compositions, etc.). **You own these files**.
|
|
214
|
+
* **`swatchkit/`**: Sets up the documentation structure, layout templates, and token display patterns.
|
|
208
215
|
|
|
209
216
|
### 2. `swatchkit` (Build Process)
|
|
210
217
|
Compiles your documentation site into `dist/swatchkit/`.
|
|
@@ -228,7 +235,8 @@ SwatchKit includes sensible defaults in `css/variables.css` and `css/global-styl
|
|
|
228
235
|
| `css/main.css` | ✅ **YES** | Your entry point. Safe. |
|
|
229
236
|
| `css/global-styles.css` | ✅ **YES** | You own this. Manually update if you rename tokens. |
|
|
230
237
|
| `css/tokens.css` | 🚫 **NO** | Overwritten by **every** `swatchkit build` and `swatchkit init`. |
|
|
231
|
-
| `swatchkit/_layout.html`| ✅ **YES** | Safe.
|
|
238
|
+
| `swatchkit/_layout.html`| ✅ **YES** | Safe during normal use. `init --force` overwrites all init-managed files, including this one. |
|
|
239
|
+
| `swatchkit/_preview.html`| ✅ **YES** | Same as `_layout.html` — safe unless you run `init --force`. |
|
|
232
240
|
| `swatchkit/tokens/*.html`| 🚫 **NO** | Overwritten by `swatchkit build` (visual previews). |
|
|
233
241
|
|
|
234
242
|
## CLI Reference
|
|
@@ -240,17 +248,20 @@ swatchkit [command] [options]
|
|
|
240
248
|
### Commands
|
|
241
249
|
|
|
242
250
|
- `swatchkit` (Default): Builds the library.
|
|
243
|
-
- `swatchkit init`: Scaffolds the layout and token files.
|
|
251
|
+
- `swatchkit init`: Scaffolds the layout and token files. If the project is already initialized, prints a status report showing which files differ from their blueprints (auto dry-run).
|
|
252
|
+
- `swatchkit init --force`: Overwrites all init-managed files with the latest blueprints. Custom swatch files and CSS files without blueprint counterparts are never touched.
|
|
253
|
+
- `swatchkit init --dry-run`: Shows what would be created or changed without writing anything.
|
|
244
254
|
|
|
245
255
|
### Flags
|
|
246
256
|
|
|
247
|
-
| Flag
|
|
248
|
-
|
|
|
249
|
-
| `--watch`
|
|
250
|
-
| `--config`
|
|
251
|
-
| `--input`
|
|
252
|
-
| `--outDir`
|
|
253
|
-
| `--force`
|
|
257
|
+
| Flag | Short | Description |
|
|
258
|
+
| :---------- | :---- | :-------------------------------------------------------------- |
|
|
259
|
+
| `--watch` | `-w` | Watch files and rebuild on change. |
|
|
260
|
+
| `--config` | `-c` | Path to config file. |
|
|
261
|
+
| `--input` | `-i` | Pattern directory (Default: `swatchkit/`). |
|
|
262
|
+
| `--outDir` | `-o` | Output directory (Default: `dist/swatchkit`). |
|
|
263
|
+
| `--force` | `-f` | Overwrite all init-managed files with latest blueprints. |
|
|
264
|
+
| `--dry-run` | | Show what init would create or change, without writing anything.|
|
|
254
265
|
|
|
255
266
|
## Configuration
|
|
256
267
|
|
|
@@ -270,11 +281,83 @@ module.exports = {
|
|
|
270
281
|
// Override tokens directory (JSON token definitions)
|
|
271
282
|
tokensDir: "./src/tokens",
|
|
272
283
|
|
|
284
|
+
// Skip copying CSS into SwatchKit's output directory.
|
|
285
|
+
// When false, SwatchKit references CSS at cssPath instead of copying it.
|
|
286
|
+
// See "Common Workflows" below for when to use this.
|
|
287
|
+
cssCopy: false,
|
|
288
|
+
|
|
289
|
+
// Relative path from SwatchKit's HTML to your CSS files.
|
|
290
|
+
// Only relevant when cssCopy is false.
|
|
291
|
+
// Defaults to "../<basename of cssDir>/" (e.g., "../css/" if cssDir is "./src/css").
|
|
292
|
+
// Set explicitly if your deployed CSS lives at a different path.
|
|
293
|
+
cssPath: "../css/",
|
|
294
|
+
|
|
273
295
|
// Exclude files (supports glob patterns)
|
|
274
296
|
exclude: ["*.test.js", "temp*"],
|
|
275
297
|
};
|
|
276
298
|
```
|
|
277
299
|
|
|
300
|
+
## Common Workflows
|
|
301
|
+
|
|
302
|
+
### Deploy alongside your project
|
|
303
|
+
|
|
304
|
+
If your build tool (Vite, Astro, etc.) already outputs CSS to `dist/`, you don't need SwatchKit to copy it again. Set `cssCopy: false` and SwatchKit's HTML will reference your existing CSS.
|
|
305
|
+
|
|
306
|
+
```javascript
|
|
307
|
+
// swatchkit.config.js
|
|
308
|
+
module.exports = {
|
|
309
|
+
cssDir: "./src/css",
|
|
310
|
+
cssCopy: false,
|
|
311
|
+
};
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
dist/
|
|
316
|
+
├── css/ # Your build tool puts CSS here
|
|
317
|
+
│ ├── main.css
|
|
318
|
+
│ └── tokens.css
|
|
319
|
+
├── index.html # Your project
|
|
320
|
+
└── swatchkit/
|
|
321
|
+
└── index.html # References ../css/main.css
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
SwatchKit derives the default `cssPath` from your `cssDir` name. If `cssDir` is `"./src/css"`, it defaults to `"../css/"`. If `cssDir` is `"./styles"`, it defaults to `"../styles/"`.
|
|
325
|
+
|
|
326
|
+
If your deployed CSS ends up somewhere else (e.g., Vite hashes it into `dist/assets/`), set `cssPath` explicitly:
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
module.exports = {
|
|
330
|
+
cssDir: "./src/css",
|
|
331
|
+
cssCopy: false,
|
|
332
|
+
cssPath: "../assets/",
|
|
333
|
+
};
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Local dev only (self-contained)
|
|
337
|
+
|
|
338
|
+
If SwatchKit is just a development tool and you don't want it in `dist/`, set `outDir` to a separate directory. Keep `cssCopy` enabled (the default) so the output is fully self-contained.
|
|
339
|
+
|
|
340
|
+
```javascript
|
|
341
|
+
// swatchkit.config.js
|
|
342
|
+
module.exports = {
|
|
343
|
+
cssDir: "./src/css",
|
|
344
|
+
outDir: "swatchkit-dist",
|
|
345
|
+
};
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
my-project/
|
|
350
|
+
├── dist/ # Your production build (no SwatchKit)
|
|
351
|
+
│ └── ...
|
|
352
|
+
└── swatchkit-dist/ # Self-contained, serve locally during dev
|
|
353
|
+
├── css/
|
|
354
|
+
│ ├── main.css
|
|
355
|
+
│ └── tokens.css
|
|
356
|
+
└── index.html
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
You can serve `swatchkit-dist/` locally during development without affecting your production build.
|
|
360
|
+
|
|
278
361
|
## Using with a Framework
|
|
279
362
|
|
|
280
363
|
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:
|
package/build.js
CHANGED
|
@@ -19,6 +19,7 @@ function parseArgs(args) {
|
|
|
19
19
|
input: null,
|
|
20
20
|
outDir: null,
|
|
21
21
|
force: false,
|
|
22
|
+
dryRun: false,
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
for (let i = 2; i < args.length; i++) {
|
|
@@ -29,6 +30,8 @@ function parseArgs(args) {
|
|
|
29
30
|
options.watch = true;
|
|
30
31
|
} else if (arg === "-f" || arg === "--force") {
|
|
31
32
|
options.force = true;
|
|
33
|
+
} else if (arg === "--dry-run") {
|
|
34
|
+
options.dryRun = true;
|
|
32
35
|
} else if (arg === "-c" || arg === "--config") {
|
|
33
36
|
// Handle case where flag is last arg
|
|
34
37
|
if (i + 1 < args.length) {
|
|
@@ -132,12 +135,24 @@ function resolveSettings(cliOptions, fileConfig) {
|
|
|
132
135
|
// Exclude patterns
|
|
133
136
|
const exclude = fileConfig.exclude || [];
|
|
134
137
|
|
|
138
|
+
// CSS copy behavior
|
|
139
|
+
// When true (default), copies cssDir into outDir/css/ for a self-contained build.
|
|
140
|
+
// When false, skips the copy — expects CSS to already exist at cssPath relative to output.
|
|
141
|
+
const cssCopy = fileConfig.cssCopy !== undefined ? fileConfig.cssCopy : true;
|
|
142
|
+
|
|
143
|
+
// Relative path from SwatchKit HTML output to the user's CSS directory.
|
|
144
|
+
// Only used when cssCopy is false. Derived from cssDir basename by default
|
|
145
|
+
// (e.g., cssDir: "./src/css" -> "../css/", cssDir: "./styles" -> "../styles/").
|
|
146
|
+
const cssPath = fileConfig.cssPath || (cssCopy ? "css/" : `../${path.basename(cssDir)}/`);
|
|
147
|
+
|
|
135
148
|
return {
|
|
136
149
|
swatchkitDir,
|
|
137
150
|
outDir,
|
|
138
151
|
cssDir,
|
|
139
152
|
tokensDir,
|
|
140
153
|
exclude,
|
|
154
|
+
cssCopy,
|
|
155
|
+
cssPath,
|
|
141
156
|
fileConfig, // Expose config to init
|
|
142
157
|
// Internal layout templates (relative to this script)
|
|
143
158
|
internalLayout: path.join(__dirname, "src/layout.html"),
|
|
@@ -158,184 +173,227 @@ function resolveSettings(cliOptions, fileConfig) {
|
|
|
158
173
|
};
|
|
159
174
|
}
|
|
160
175
|
|
|
161
|
-
// --- 4. Init
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
176
|
+
// --- 4. Init Manifest & Dry Run ---
|
|
177
|
+
|
|
178
|
+
// Builds a list of all files that init manages.
|
|
179
|
+
// Each entry maps a blueprint source to a project destination.
|
|
180
|
+
// Used by both the actual init and the dry-run status report.
|
|
181
|
+
function buildInitManifest(settings) {
|
|
182
|
+
const manifest = [];
|
|
183
|
+
const blueprintsDir = path.join(__dirname, "src/blueprints");
|
|
184
|
+
const templatesDir = path.join(__dirname, "src/templates");
|
|
185
|
+
|
|
186
|
+
// Token blueprint JSON files
|
|
187
|
+
const tokenFiles = [
|
|
188
|
+
"colors.json",
|
|
189
|
+
"text-weights.json",
|
|
190
|
+
"text-leading.json",
|
|
191
|
+
"viewports.json",
|
|
192
|
+
"text-sizes.json",
|
|
193
|
+
"spacing.json",
|
|
194
|
+
"fonts.json",
|
|
195
|
+
];
|
|
196
|
+
for (const file of tokenFiles) {
|
|
197
|
+
manifest.push({
|
|
198
|
+
src: path.join(blueprintsDir, file),
|
|
199
|
+
dest: path.join(settings.tokensDir, file),
|
|
200
|
+
});
|
|
169
201
|
}
|
|
170
202
|
|
|
171
|
-
//
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
203
|
+
// Template files (swatchkit/tokens/)
|
|
204
|
+
const templateFiles = ["prose.html", "script.js"];
|
|
205
|
+
for (const file of templateFiles) {
|
|
206
|
+
manifest.push({
|
|
207
|
+
src: path.join(templatesDir, file),
|
|
208
|
+
dest: path.join(settings.swatchkitDir, "tokens", file),
|
|
209
|
+
transform: (content) => content.trim(),
|
|
210
|
+
});
|
|
176
211
|
}
|
|
177
212
|
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
213
|
+
// CSS entry point
|
|
214
|
+
manifest.push({
|
|
215
|
+
src: path.join(blueprintsDir, "main.css"),
|
|
216
|
+
dest: settings.mainCssFile,
|
|
217
|
+
});
|
|
184
218
|
|
|
185
|
-
//
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
219
|
+
// SwatchKit UI styles
|
|
220
|
+
manifest.push({
|
|
221
|
+
src: path.join(blueprintsDir, "swatchkit-ui.css"),
|
|
222
|
+
dest: path.join(settings.cssDir, "swatchkit-ui.css"),
|
|
223
|
+
});
|
|
190
224
|
|
|
191
|
-
//
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
fs.
|
|
225
|
+
// CSS folder blueprints (global, compositions, utilities)
|
|
226
|
+
const cssFolders = ["global", "compositions", "utilities"];
|
|
227
|
+
for (const folder of cssFolders) {
|
|
228
|
+
const srcDir = path.join(blueprintsDir, folder);
|
|
229
|
+
if (fs.existsSync(srcDir)) {
|
|
230
|
+
const files = fs
|
|
231
|
+
.readdirSync(srcDir)
|
|
232
|
+
.filter((f) => !fs.statSync(path.join(srcDir, f)).isDirectory());
|
|
233
|
+
for (const file of files) {
|
|
234
|
+
manifest.push({
|
|
235
|
+
src: path.join(srcDir, file),
|
|
236
|
+
dest: path.join(settings.cssDir, folder, file),
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
196
240
|
}
|
|
197
241
|
|
|
198
|
-
//
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
242
|
+
// Layout files
|
|
243
|
+
manifest.push({
|
|
244
|
+
src: settings.internalLayout,
|
|
245
|
+
dest: settings.projectLayout,
|
|
246
|
+
});
|
|
247
|
+
manifest.push({
|
|
248
|
+
src: settings.internalPreviewLayout,
|
|
249
|
+
dest: settings.projectPreviewLayout,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
return manifest;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Directories that init ensures exist.
|
|
256
|
+
function getInitDirs(settings) {
|
|
257
|
+
return [
|
|
258
|
+
settings.swatchkitDir,
|
|
259
|
+
settings.tokensDir,
|
|
260
|
+
path.join(settings.swatchkitDir, "tokens"),
|
|
261
|
+
settings.cssDir,
|
|
262
|
+
path.join(settings.cssDir, "global"),
|
|
263
|
+
];
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Compare init-managed files against their blueprint sources and print a
|
|
267
|
+
// status report showing what would be created, changed, or is up to date.
|
|
268
|
+
function reportInitStatus(settings) {
|
|
269
|
+
const cwd = process.cwd();
|
|
270
|
+
const manifest = buildInitManifest(settings);
|
|
271
|
+
const dirs = getInitDirs(settings);
|
|
208
272
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// Copy HTML/JS template patterns to swatchkit/tokens/ (UI documentation)
|
|
218
|
-
// Note: Token display templates (colors, typography, spacing, etc.) are
|
|
219
|
-
// generated dynamically at build time from the JSON token files.
|
|
220
|
-
const copyTemplate = (srcFilename, destFilename) => {
|
|
221
|
-
const destPath = path.join(tokensUiDir, destFilename);
|
|
222
|
-
if (!fs.existsSync(destPath)) {
|
|
223
|
-
const srcPath = path.join(__dirname, "src/templates", srcFilename);
|
|
224
|
-
const content = fs.readFileSync(srcPath, "utf-8");
|
|
225
|
-
fs.writeFileSync(destPath, content.trim());
|
|
226
|
-
console.log(`+ Pattern Template: ${destFilename}`);
|
|
273
|
+
const newDirs = [];
|
|
274
|
+
const created = [];
|
|
275
|
+
const changed = [];
|
|
276
|
+
const upToDate = [];
|
|
277
|
+
|
|
278
|
+
for (const dir of dirs) {
|
|
279
|
+
if (!fs.existsSync(dir)) {
|
|
280
|
+
newDirs.push(path.relative(cwd, dir) + "/");
|
|
227
281
|
}
|
|
228
|
-
}
|
|
282
|
+
}
|
|
229
283
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
// Create main.css entry point
|
|
243
|
-
if (!fs.existsSync(settings.mainCssFile)) {
|
|
244
|
-
const srcPath = path.join(__dirname, "src/blueprints/main.css");
|
|
245
|
-
let content = fs.readFileSync(srcPath, "utf-8");
|
|
246
|
-
|
|
247
|
-
// Default: Copy the files
|
|
248
|
-
const copyCssBlueprint = (filename) => {
|
|
249
|
-
const src = path.join(__dirname, "src/blueprints", filename);
|
|
250
|
-
// Ensure destination path (cssDir) exists
|
|
251
|
-
if (!fs.existsSync(settings.cssDir)) {
|
|
252
|
-
fs.mkdirSync(settings.cssDir, { recursive: true });
|
|
253
|
-
}
|
|
254
|
-
const dest = path.join(settings.cssDir, filename);
|
|
255
|
-
// Only copy if destination doesn't exist
|
|
256
|
-
if (fs.existsSync(src) && !fs.existsSync(dest)) {
|
|
257
|
-
fs.copyFileSync(src, dest);
|
|
258
|
-
console.log(`+ CSS Blueprint: ${filename}`);
|
|
284
|
+
for (const entry of manifest) {
|
|
285
|
+
const relDest = path.relative(cwd, entry.dest);
|
|
286
|
+
if (!fs.existsSync(entry.dest)) {
|
|
287
|
+
created.push(relDest);
|
|
288
|
+
} else {
|
|
289
|
+
let srcContent = fs.readFileSync(entry.src, "utf-8");
|
|
290
|
+
if (entry.transform) srcContent = entry.transform(srcContent);
|
|
291
|
+
const destContent = fs.readFileSync(entry.dest, "utf-8");
|
|
292
|
+
if (srcContent !== destContent) {
|
|
293
|
+
changed.push(relDest);
|
|
294
|
+
} else {
|
|
295
|
+
upToDate.push(relDest);
|
|
259
296
|
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Global blueprints are now copied as a folder below
|
|
297
|
+
}
|
|
298
|
+
}
|
|
263
299
|
|
|
264
|
-
|
|
265
|
-
console.log(
|
|
300
|
+
if (newDirs.length === 0 && created.length === 0 && changed.length === 0) {
|
|
301
|
+
console.log("[SwatchKit] All init-managed files are up to date.");
|
|
302
|
+
return;
|
|
266
303
|
}
|
|
267
304
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
copyDir(globalSrc, globalDest);
|
|
305
|
+
if (newDirs.length > 0 || created.length > 0) {
|
|
306
|
+
console.log("\n New (will be created):");
|
|
307
|
+
for (const d of newDirs) console.log(` + ${d}`);
|
|
308
|
+
for (const f of created) console.log(` + ${f}`);
|
|
273
309
|
}
|
|
274
310
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
if (fs.existsSync(compositionsSrc)) {
|
|
279
|
-
copyDir(compositionsSrc, compositionsDest);
|
|
311
|
+
if (changed.length > 0) {
|
|
312
|
+
console.log("\n Changed (differs from latest blueprint):");
|
|
313
|
+
for (const f of changed) console.log(` ~ ${f}`);
|
|
280
314
|
}
|
|
281
315
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (fs.existsSync(utilitiesSrc)) {
|
|
286
|
-
copyDir(utilitiesSrc, utilitiesDest);
|
|
316
|
+
if (upToDate.length > 0) {
|
|
317
|
+
console.log("\n Up to date:");
|
|
318
|
+
for (const f of upToDate) console.log(` = ${f}`);
|
|
287
319
|
}
|
|
288
320
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
321
|
+
console.log("");
|
|
322
|
+
|
|
323
|
+
if (changed.length > 0 || created.length > 0 || newDirs.length > 0) {
|
|
324
|
+
console.log(
|
|
325
|
+
" Run 'swatchkit init --force' to update all files to latest blueprints.\n",
|
|
326
|
+
);
|
|
295
327
|
}
|
|
328
|
+
}
|
|
296
329
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
if (
|
|
304
|
-
|
|
330
|
+
// --- 5. Init Command Logic ---
|
|
331
|
+
function runInit(settings, options) {
|
|
332
|
+
const isInitialized = fs.existsSync(settings.swatchkitDir);
|
|
333
|
+
|
|
334
|
+
// --dry-run: always just report status, change nothing.
|
|
335
|
+
// Already initialized without --force: auto dry-run.
|
|
336
|
+
if (options.dryRun || (isInitialized && !options.force)) {
|
|
337
|
+
if (isInitialized && !options.dryRun) {
|
|
338
|
+
console.log("[SwatchKit] Project already initialized.");
|
|
339
|
+
}
|
|
340
|
+
reportInitStatus(settings);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Sanity check: internal layout template must exist
|
|
345
|
+
if (!fs.existsSync(settings.internalLayout)) {
|
|
346
|
+
console.error(
|
|
347
|
+
`Error: Internal layout file not found at ${settings.internalLayout}`,
|
|
348
|
+
);
|
|
349
|
+
process.exit(1);
|
|
305
350
|
}
|
|
306
351
|
|
|
307
|
-
|
|
352
|
+
console.log("[SwatchKit] Scaffolding project structure...");
|
|
308
353
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
if (fs.existsSync(
|
|
313
|
-
|
|
314
|
-
fs.
|
|
315
|
-
console.log(`+ Layout: ${path.basename(targetLayout)}`);
|
|
316
|
-
} else {
|
|
317
|
-
console.error(
|
|
318
|
-
`Error: Internal layout file not found at ${settings.internalLayout}`,
|
|
319
|
-
);
|
|
320
|
-
process.exit(1);
|
|
354
|
+
// Ensure directories exist
|
|
355
|
+
const cwd = process.cwd();
|
|
356
|
+
for (const dir of getInitDirs(settings)) {
|
|
357
|
+
if (!fs.existsSync(dir)) {
|
|
358
|
+
console.log(`+ Directory: ${path.relative(cwd, dir)}/`);
|
|
359
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
321
360
|
}
|
|
322
361
|
}
|
|
323
362
|
|
|
324
|
-
// Copy
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
)
|
|
332
|
-
|
|
333
|
-
|
|
363
|
+
// Copy all manifest files
|
|
364
|
+
const manifest = buildInitManifest(settings);
|
|
365
|
+
for (const entry of manifest) {
|
|
366
|
+
const exists = fs.existsSync(entry.dest);
|
|
367
|
+
if (options.force || !exists) {
|
|
368
|
+
// Ensure parent directory exists (for CSS subdirs like compositions/)
|
|
369
|
+
const parentDir = path.dirname(entry.dest);
|
|
370
|
+
if (!fs.existsSync(parentDir)) {
|
|
371
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
let content = fs.readFileSync(entry.src, "utf-8");
|
|
375
|
+
if (entry.transform) content = entry.transform(content);
|
|
376
|
+
fs.writeFileSync(entry.dest, content);
|
|
377
|
+
|
|
378
|
+
const label = path.relative(cwd, entry.dest);
|
|
379
|
+
console.log(`${exists ? "~ Updated" : "+ Created"}: ${label}`);
|
|
334
380
|
}
|
|
335
381
|
}
|
|
382
|
+
|
|
383
|
+
// Generate tokens.css and utility tokens.css (always — these are generated files)
|
|
384
|
+
const tokensContext = processTokens(
|
|
385
|
+
settings.tokensDir,
|
|
386
|
+
path.join(settings.cssDir, "global"),
|
|
387
|
+
);
|
|
388
|
+
if (tokensContext) {
|
|
389
|
+
generateTokenUtilities(
|
|
390
|
+
tokensContext,
|
|
391
|
+
path.join(settings.cssDir, "utilities"),
|
|
392
|
+
);
|
|
393
|
+
}
|
|
336
394
|
}
|
|
337
395
|
|
|
338
|
-
// ---
|
|
396
|
+
// --- 6. Build Logic ---
|
|
339
397
|
function copyDir(src, dest, force = false) {
|
|
340
398
|
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
|
|
341
399
|
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
@@ -467,7 +525,9 @@ function build(settings) {
|
|
|
467
525
|
}
|
|
468
526
|
|
|
469
527
|
// 3. Ensure dist directories exist
|
|
470
|
-
[settings.outDir, settings.
|
|
528
|
+
const distDirs = [settings.outDir, settings.distJsDir];
|
|
529
|
+
if (settings.cssCopy) distDirs.push(settings.distCssDir);
|
|
530
|
+
distDirs.forEach((dir) => {
|
|
471
531
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
472
532
|
});
|
|
473
533
|
|
|
@@ -490,10 +550,12 @@ function build(settings) {
|
|
|
490
550
|
}
|
|
491
551
|
}
|
|
492
552
|
|
|
493
|
-
// 3. Copy CSS files (recursively)
|
|
494
|
-
if (fs.existsSync(settings.cssDir)) {
|
|
553
|
+
// 3. Copy CSS files (recursively) — skip if cssCopy is disabled
|
|
554
|
+
if (settings.cssCopy && fs.existsSync(settings.cssDir)) {
|
|
495
555
|
console.log("Copying static CSS assets (css/*)...");
|
|
496
556
|
copyDir(settings.cssDir, settings.distCssDir, true);
|
|
557
|
+
} else if (!settings.cssCopy) {
|
|
558
|
+
console.log(`Skipping CSS copy (cssCopy: false). CSS referenced at: ${settings.cssPath}`);
|
|
497
559
|
}
|
|
498
560
|
|
|
499
561
|
// 4. Read swatches & JS
|
|
@@ -651,25 +713,32 @@ function build(settings) {
|
|
|
651
713
|
sortedKeys.forEach((section) => {
|
|
652
714
|
const swatches = sections[section];
|
|
653
715
|
swatches.forEach((p) => {
|
|
654
|
-
// Determine output path and relative CSS path
|
|
716
|
+
// Determine output path and relative CSS path.
|
|
717
|
+
// Preview pages need to navigate up to the swatchkit output root,
|
|
718
|
+
// then follow cssPath to reach the CSS files.
|
|
655
719
|
let previewFile, cssPath;
|
|
656
720
|
if (p.sectionSlug) {
|
|
657
721
|
const sectionDir = path.join(settings.distPreviewDir, p.sectionSlug);
|
|
658
722
|
if (!fs.existsSync(sectionDir))
|
|
659
723
|
fs.mkdirSync(sectionDir, { recursive: true });
|
|
660
724
|
previewFile = path.join(sectionDir, `${p.id}.html`);
|
|
661
|
-
cssPath = "../../"; // preview/section/file.html -> ../../
|
|
725
|
+
cssPath = "../../" + settings.cssPath; // preview/section/file.html -> ../../ + cssPath
|
|
662
726
|
} else {
|
|
663
727
|
if (!fs.existsSync(settings.distPreviewDir))
|
|
664
728
|
fs.mkdirSync(settings.distPreviewDir, { recursive: true });
|
|
665
729
|
previewFile = path.join(settings.distPreviewDir, `${p.id}.html`);
|
|
666
|
-
cssPath = "../"; // preview/file.html -> ../
|
|
730
|
+
cssPath = "../" + settings.cssPath; // preview/file.html -> ../ + cssPath
|
|
667
731
|
}
|
|
668
732
|
|
|
733
|
+
// JS always lives in the swatchkit output dir, so jsPath just
|
|
734
|
+
// navigates back to the output root (not to the user's CSS dir).
|
|
735
|
+
const jsPath = p.sectionSlug ? "../../" : "../";
|
|
736
|
+
|
|
669
737
|
const previewHtml = previewLayoutContent
|
|
670
738
|
.replace("<!-- PREVIEW_TITLE -->", p.name)
|
|
671
739
|
.replace("<!-- PREVIEW_CONTENT -->", p.content)
|
|
672
740
|
.replaceAll("<!-- CSS_PATH -->", cssPath)
|
|
741
|
+
.replaceAll("<!-- JS_PATH -->", jsPath)
|
|
673
742
|
.replace("<!-- HEAD_EXTRAS -->", "");
|
|
674
743
|
|
|
675
744
|
fs.writeFileSync(previewFile, previewHtml);
|
|
@@ -697,6 +766,7 @@ function build(settings) {
|
|
|
697
766
|
const finalHtml = layoutContent
|
|
698
767
|
.replace("<!-- SIDEBAR_LINKS -->", sidebarLinks)
|
|
699
768
|
.replace("<!-- SWATCHES -->", swatchBlocks)
|
|
769
|
+
.replaceAll("<!-- CSS_PATH -->", settings.cssPath)
|
|
700
770
|
.replace("<!-- HEAD_EXTRAS -->", headExtras);
|
|
701
771
|
|
|
702
772
|
// 9. Write output
|
|
@@ -705,7 +775,7 @@ function build(settings) {
|
|
|
705
775
|
console.log(`Build complete! Generated ${settings.outputFile}`);
|
|
706
776
|
}
|
|
707
777
|
|
|
708
|
-
// ---
|
|
778
|
+
// --- 7. Watch Logic ---
|
|
709
779
|
function watch(settings) {
|
|
710
780
|
const sourcePaths = [
|
|
711
781
|
settings.swatchkitDir,
|
package/package.json
CHANGED
package/src/layout.html
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>SwatchKit</title>
|
|
7
|
-
<link rel="stylesheet" href="
|
|
8
|
-
<link rel="stylesheet" href="
|
|
7
|
+
<link rel="stylesheet" href="<!-- CSS_PATH -->main.css" />
|
|
8
|
+
<link rel="stylesheet" href="<!-- CSS_PATH -->swatchkit-ui.css" />
|
|
9
9
|
<!-- HEAD_EXTRAS -->
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|