swatchkit 0.7.0 → 0.8.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 +28 -13
- package/build.js +192 -146
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,7 +38,10 @@ my-project/
|
|
|
38
38
|
│ └── ...
|
|
39
39
|
└── dist/
|
|
40
40
|
└── swatchkit/ # Built pattern library
|
|
41
|
-
|
|
41
|
+
├── index.html
|
|
42
|
+
├── js/
|
|
43
|
+
│ └── swatches.js # Bundled swatch scripts
|
|
44
|
+
└── preview/ # Full-screen preview pages
|
|
42
45
|
```
|
|
43
46
|
|
|
44
47
|
---
|
|
@@ -201,10 +204,17 @@ SwatchKit automatically bundles your JS files, wraps them in a safety scope (IIF
|
|
|
201
204
|
Understanding the build pipeline helps you know which files to edit and which are generated.
|
|
202
205
|
|
|
203
206
|
### 1. `swatchkit init` (Scaffolding)
|
|
204
|
-
Copies "blueprints" into your project to get you started.
|
|
207
|
+
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.
|
|
208
|
+
|
|
209
|
+
* **Fresh project:** Creates directories and copies all blueprint files.
|
|
210
|
+
* **Already initialized:** Prints a status report comparing your files to the latest blueprints. Suggests `--force` if anything has changed.
|
|
211
|
+
* **`--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.
|
|
212
|
+
* **`--dry-run`:** Shows what would happen without writing anything.
|
|
213
|
+
|
|
214
|
+
Files created:
|
|
205
215
|
* **`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
|
|
216
|
+
* **`css/`**: Copies static CSS files (`main.css`, `reset.css`, compositions, etc.). **You own these files**.
|
|
217
|
+
* **`swatchkit/`**: Sets up the documentation structure, layout templates, and token display patterns.
|
|
208
218
|
|
|
209
219
|
### 2. `swatchkit` (Build Process)
|
|
210
220
|
Compiles your documentation site into `dist/swatchkit/`.
|
|
@@ -213,6 +223,7 @@ Compiles your documentation site into `dist/swatchkit/`.
|
|
|
213
223
|
2. **Generates CSS**: Creates `css/tokens.css`. **Do not edit this file**; it is overwritten every build.
|
|
214
224
|
3. **Copies Assets**: Copies your `css/` folder (including your manually edited `global-styles.css` and `main.css`) to the output folder.
|
|
215
225
|
4. **Scans Patterns**: Finds all HTML files in `swatchkit/` and stitches them into the documentation site.
|
|
226
|
+
5. **Bundles JavaScript**: Collects any `.js` files from swatch folders (e.g., `swatchkit/carousel/script.js`) and section directories into a single `js/swatches.js` bundle. The default token display script (`swatchkit/tokens/script.js`) is included here — it shows computed CSS values alongside token documentation.
|
|
216
227
|
|
|
217
228
|
### Global Styles & Variables
|
|
218
229
|
SwatchKit includes sensible defaults in `css/variables.css` and `css/global-styles.css`.
|
|
@@ -228,7 +239,8 @@ SwatchKit includes sensible defaults in `css/variables.css` and `css/global-styl
|
|
|
228
239
|
| `css/main.css` | ✅ **YES** | Your entry point. Safe. |
|
|
229
240
|
| `css/global-styles.css` | ✅ **YES** | You own this. Manually update if you rename tokens. |
|
|
230
241
|
| `css/tokens.css` | 🚫 **NO** | Overwritten by **every** `swatchkit build` and `swatchkit init`. |
|
|
231
|
-
| `swatchkit/_layout.html`| ✅ **YES** | Safe.
|
|
242
|
+
| `swatchkit/_layout.html`| ✅ **YES** | Safe during normal use. `init --force` overwrites all init-managed files, including this one. |
|
|
243
|
+
| `swatchkit/_preview.html`| ✅ **YES** | Same as `_layout.html` — safe unless you run `init --force`. |
|
|
232
244
|
| `swatchkit/tokens/*.html`| 🚫 **NO** | Overwritten by `swatchkit build` (visual previews). |
|
|
233
245
|
|
|
234
246
|
## CLI Reference
|
|
@@ -240,17 +252,20 @@ swatchkit [command] [options]
|
|
|
240
252
|
### Commands
|
|
241
253
|
|
|
242
254
|
- `swatchkit` (Default): Builds the library.
|
|
243
|
-
- `swatchkit init`: Scaffolds the layout and token files.
|
|
255
|
+
- `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).
|
|
256
|
+
- `swatchkit init --force`: Overwrites all init-managed files with the latest blueprints. Custom swatch files and CSS files without blueprint counterparts are never touched.
|
|
257
|
+
- `swatchkit init --dry-run`: Shows what would be created or changed without writing anything.
|
|
244
258
|
|
|
245
259
|
### Flags
|
|
246
260
|
|
|
247
|
-
| Flag
|
|
248
|
-
|
|
|
249
|
-
| `--watch`
|
|
250
|
-
| `--config`
|
|
251
|
-
| `--input`
|
|
252
|
-
| `--outDir`
|
|
253
|
-
| `--force`
|
|
261
|
+
| Flag | Short | Description |
|
|
262
|
+
| :---------- | :---- | :-------------------------------------------------------------- |
|
|
263
|
+
| `--watch` | `-w` | Watch files and rebuild on change. |
|
|
264
|
+
| `--config` | `-c` | Path to config file. |
|
|
265
|
+
| `--input` | `-i` | Pattern directory (Default: `swatchkit/`). |
|
|
266
|
+
| `--outDir` | `-o` | Output directory (Default: `dist/swatchkit`). |
|
|
267
|
+
| `--force` | `-f` | Overwrite all init-managed files with latest blueprints. |
|
|
268
|
+
| `--dry-run` | | Show what init would create or change, without writing anything.|
|
|
254
269
|
|
|
255
270
|
## Configuration
|
|
256
271
|
|
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) {
|
|
@@ -170,184 +173,227 @@ function resolveSettings(cliOptions, fileConfig) {
|
|
|
170
173
|
};
|
|
171
174
|
}
|
|
172
175
|
|
|
173
|
-
// --- 4. Init
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
+
});
|
|
181
201
|
}
|
|
182
202
|
|
|
183
|
-
//
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
+
});
|
|
188
211
|
}
|
|
189
212
|
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
213
|
+
// CSS entry point
|
|
214
|
+
manifest.push({
|
|
215
|
+
src: path.join(blueprintsDir, "main.css"),
|
|
216
|
+
dest: settings.mainCssFile,
|
|
217
|
+
});
|
|
196
218
|
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
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
|
+
});
|
|
202
224
|
|
|
203
|
-
//
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
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
|
+
}
|
|
208
240
|
}
|
|
209
241
|
|
|
210
|
-
//
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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
|
+
}
|
|
220
265
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if (!fs.existsSync(
|
|
235
|
-
|
|
236
|
-
const content = fs.readFileSync(srcPath, "utf-8");
|
|
237
|
-
fs.writeFileSync(destPath, content.trim());
|
|
238
|
-
console.log(`+ Pattern Template: ${destFilename}`);
|
|
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);
|
|
272
|
+
|
|
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) + "/");
|
|
239
281
|
}
|
|
240
|
-
}
|
|
282
|
+
}
|
|
241
283
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
// Create main.css entry point
|
|
255
|
-
if (!fs.existsSync(settings.mainCssFile)) {
|
|
256
|
-
const srcPath = path.join(__dirname, "src/blueprints/main.css");
|
|
257
|
-
let content = fs.readFileSync(srcPath, "utf-8");
|
|
258
|
-
|
|
259
|
-
// Default: Copy the files
|
|
260
|
-
const copyCssBlueprint = (filename) => {
|
|
261
|
-
const src = path.join(__dirname, "src/blueprints", filename);
|
|
262
|
-
// Ensure destination path (cssDir) exists
|
|
263
|
-
if (!fs.existsSync(settings.cssDir)) {
|
|
264
|
-
fs.mkdirSync(settings.cssDir, { recursive: true });
|
|
265
|
-
}
|
|
266
|
-
const dest = path.join(settings.cssDir, filename);
|
|
267
|
-
// Only copy if destination doesn't exist
|
|
268
|
-
if (fs.existsSync(src) && !fs.existsSync(dest)) {
|
|
269
|
-
fs.copyFileSync(src, dest);
|
|
270
|
-
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);
|
|
271
296
|
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Global blueprints are now copied as a folder below
|
|
297
|
+
}
|
|
298
|
+
}
|
|
275
299
|
|
|
276
|
-
|
|
277
|
-
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;
|
|
278
303
|
}
|
|
279
304
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
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}`);
|
|
285
309
|
}
|
|
286
310
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (fs.existsSync(compositionsSrc)) {
|
|
291
|
-
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}`);
|
|
292
314
|
}
|
|
293
315
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (fs.existsSync(utilitiesSrc)) {
|
|
298
|
-
copyDir(utilitiesSrc, utilitiesDest);
|
|
316
|
+
if (upToDate.length > 0) {
|
|
317
|
+
console.log("\n Up to date:");
|
|
318
|
+
for (const f of upToDate) console.log(` = ${f}`);
|
|
299
319
|
}
|
|
300
320
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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
|
+
);
|
|
307
327
|
}
|
|
328
|
+
}
|
|
308
329
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
if (
|
|
316
|
-
|
|
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);
|
|
317
350
|
}
|
|
318
351
|
|
|
319
|
-
|
|
352
|
+
console.log("[SwatchKit] Scaffolding project structure...");
|
|
320
353
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
if (fs.existsSync(
|
|
325
|
-
|
|
326
|
-
fs.
|
|
327
|
-
console.log(`+ Layout: ${path.basename(targetLayout)}`);
|
|
328
|
-
} else {
|
|
329
|
-
console.error(
|
|
330
|
-
`Error: Internal layout file not found at ${settings.internalLayout}`,
|
|
331
|
-
);
|
|
332
|
-
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 });
|
|
333
360
|
}
|
|
334
361
|
}
|
|
335
362
|
|
|
336
|
-
// Copy
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
)
|
|
344
|
-
|
|
345
|
-
|
|
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}`);
|
|
346
380
|
}
|
|
347
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
|
+
}
|
|
348
394
|
}
|
|
349
395
|
|
|
350
|
-
// ---
|
|
396
|
+
// --- 6. Build Logic ---
|
|
351
397
|
function copyDir(src, dest, force = false) {
|
|
352
398
|
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
|
|
353
399
|
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
@@ -729,7 +775,7 @@ function build(settings) {
|
|
|
729
775
|
console.log(`Build complete! Generated ${settings.outputFile}`);
|
|
730
776
|
}
|
|
731
777
|
|
|
732
|
-
// ---
|
|
778
|
+
// --- 7. Watch Logic ---
|
|
733
779
|
function watch(settings) {
|
|
734
780
|
const sourcePaths = [
|
|
735
781
|
settings.swatchkitDir,
|