swatchkit 0.0.1 → 0.0.3
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 +68 -32
- package/build.js +380 -90
- package/package.json +1 -1
- package/src/layout.html +2 -1
package/README.md
CHANGED
|
@@ -1,57 +1,93 @@
|
|
|
1
1
|
# SwatchKit
|
|
2
2
|
|
|
3
|
-
**SwatchKit** is a lightweight
|
|
3
|
+
**SwatchKit** is a lightweight tool for generating HTML pattern libraries. It acts as a **Pattern Discovery Engine**: it scans your folders for HTML components and stitches them into a documentation site using a layout you control.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
It follows the "Magic Folder" principle: drop files in, and a library comes out.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
2. **Add Styles:** Add standard CSS to `src/css/styles.css`.
|
|
9
|
-
3. **Build:** Run `node build.js`.
|
|
7
|
+
## Quick Start
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
Try it instantly in any project:
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
```bash
|
|
12
|
+
# 1. Initialize the layout
|
|
13
|
+
npx swatchkit init
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
* **SwatchKit** will automatically find it, wrap it in an IIFE (to protect scope), and bundle it into the final site. You can have multiple JS files per pattern.
|
|
15
|
+
# 2. Build the library
|
|
16
|
+
npx swatchkit
|
|
17
|
+
```
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
No config files. No build pipelines. No complex templating engines. Just HTML, CSS, and JS.
|
|
19
|
+
This will create a `swatches/` folder and build your site to `public/swatchkit/`.
|
|
24
20
|
|
|
25
|
-
|
|
21
|
+
---
|
|
26
22
|
|
|
27
|
-
|
|
23
|
+
## Project Setup (Recommended)
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
npx swatchkit
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Installing locally
|
|
25
|
+
For real projects, install SwatchKit as a development dependency to lock the version.
|
|
35
26
|
|
|
36
|
-
Install as a dev dependency:
|
|
37
27
|
```bash
|
|
38
28
|
npm install -D swatchkit
|
|
39
29
|
```
|
|
40
30
|
|
|
41
|
-
Then add to your `package.json` scripts:
|
|
31
|
+
Then add it to your `package.json` scripts:
|
|
32
|
+
|
|
42
33
|
```json
|
|
43
34
|
"scripts": {
|
|
44
|
-
"
|
|
35
|
+
"patterns": "swatchkit"
|
|
45
36
|
}
|
|
46
37
|
```
|
|
47
38
|
|
|
48
|
-
|
|
39
|
+
## How It Works
|
|
40
|
+
|
|
41
|
+
### 1. The Magic Folder
|
|
42
|
+
By default, SwatchKit looks for a `swatches/` folder in your project root.
|
|
43
|
+
* **Single File:** Drop `card.html` into `swatches/`. It appears in the library.
|
|
44
|
+
* **Component Folder:** Drop a folder like `swatches/carousel/` containing `index.html`. It works the same way.
|
|
45
|
+
|
|
46
|
+
### 2. Custom Layouts
|
|
47
|
+
When you run `swatchkit init`, we create `swatches/_layout.html`.
|
|
48
|
+
**You own this file.**
|
|
49
|
+
* Add your own `<link rel="stylesheet" href="/css/app.css">`.
|
|
50
|
+
* Add custom fonts, scripts, or meta tags.
|
|
51
|
+
* Change the HTML structure, logo, or classes.
|
|
52
|
+
|
|
53
|
+
SwatchKit simply injects the content into the `<!-- PATTERNS -->` and `<!-- SIDEBAR_LINKS -->` placeholders.
|
|
54
|
+
|
|
55
|
+
### 3. JavaScript Bundling
|
|
56
|
+
If your component needs client-side JS:
|
|
57
|
+
1. Create a folder: `swatches/carousel/`.
|
|
58
|
+
2. Add `index.html` (Markup).
|
|
59
|
+
3. Add `script.js` (Logic).
|
|
60
|
+
|
|
61
|
+
SwatchKit automatically bundles your JS files, wraps them in a safety scope (IIFE), and injects them into the final build.
|
|
62
|
+
|
|
63
|
+
## CLI Reference
|
|
64
|
+
|
|
49
65
|
```bash
|
|
50
|
-
|
|
66
|
+
swatchkit [command] [options]
|
|
51
67
|
```
|
|
52
68
|
|
|
53
|
-
###
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
### Commands
|
|
70
|
+
* `swatchkit` (Default): Builds the library.
|
|
71
|
+
* `swatchkit init`: Scaffolds the `_layout.html` file.
|
|
72
|
+
|
|
73
|
+
### Flags
|
|
74
|
+
| Flag | Short | Description |
|
|
75
|
+
| :--- | :--- | :--- |
|
|
76
|
+
| `--watch` | `-w` | Watch mode (coming soon). |
|
|
77
|
+
| `--config` | `-c` | Path to config file. |
|
|
78
|
+
| `--input` | `-i` | Pattern directory (Default: `swatches/`). |
|
|
79
|
+
| `--outDir` | `-o` | Output directory (Default: `public/swatchkit`). |
|
|
80
|
+
| `--force` | `-f` | Overwrite layout file during init. |
|
|
81
|
+
|
|
82
|
+
## Configuration
|
|
83
|
+
Optional. Create `swatchkit.config.js` in your root for persistent settings.
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
module.exports = {
|
|
87
|
+
// Override default pattern directory
|
|
88
|
+
input: './src/patterns',
|
|
89
|
+
|
|
90
|
+
// Override default output directory
|
|
91
|
+
outDir: './dist/docs'
|
|
92
|
+
};
|
|
57
93
|
```
|
package/build.js
CHANGED
|
@@ -1,132 +1,422 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const fs = require(
|
|
3
|
-
const path = require(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { processTokens } = require("./src/tokens");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* SwatchKit Build Script
|
|
8
|
+
* Refactored for Phase 1 Expansion
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// --- 1. CLI Argument Parsing ---
|
|
12
|
+
function parseArgs(args) {
|
|
13
|
+
const options = {
|
|
14
|
+
command: null,
|
|
15
|
+
watch: false,
|
|
16
|
+
config: null,
|
|
17
|
+
input: null,
|
|
18
|
+
outDir: null,
|
|
19
|
+
force: false,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
for (let i = 2; i < args.length; i++) {
|
|
23
|
+
const arg = args[i];
|
|
24
|
+
if (arg === "init") {
|
|
25
|
+
options.command = "init";
|
|
26
|
+
} else if (arg === "-w" || arg === "--watch") {
|
|
27
|
+
options.watch = true;
|
|
28
|
+
} else if (arg === "-f" || arg === "--force") {
|
|
29
|
+
options.force = true;
|
|
30
|
+
} else if (arg === "-c" || arg === "--config") {
|
|
31
|
+
// Handle case where flag is last arg
|
|
32
|
+
if (i + 1 < args.length) {
|
|
33
|
+
options.config = args[++i];
|
|
34
|
+
}
|
|
35
|
+
} else if (arg === "-i" || arg === "--input") {
|
|
36
|
+
if (i + 1 < args.length) {
|
|
37
|
+
options.input = args[++i];
|
|
38
|
+
}
|
|
39
|
+
} else if (arg === "-o" || arg === "--outDir") {
|
|
40
|
+
if (i + 1 < args.length) {
|
|
41
|
+
options.outDir = args[++i];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return options;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// --- 2. Config Loading ---
|
|
49
|
+
function loadConfig(configPath) {
|
|
50
|
+
let finalPath;
|
|
51
|
+
if (configPath) {
|
|
52
|
+
finalPath = path.resolve(process.cwd(), configPath);
|
|
53
|
+
} else {
|
|
54
|
+
finalPath = path.join(process.cwd(), "swatchkit.config.js");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (fs.existsSync(finalPath)) {
|
|
58
|
+
try {
|
|
59
|
+
console.log(`[SwatchKit] Loading config from ${finalPath}`);
|
|
60
|
+
return require(finalPath);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.error("[SwatchKit] Error loading config file:", e.message);
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return {};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// --- 3. Smart Defaults & Path Resolution ---
|
|
70
|
+
function resolveSettings(cliOptions, fileConfig) {
|
|
71
|
+
const cwd = process.cwd();
|
|
72
|
+
|
|
73
|
+
// Helper to find patterns dir
|
|
74
|
+
function findPatternsDir() {
|
|
75
|
+
// 1. Explicit input
|
|
76
|
+
if (cliOptions.input) return path.resolve(cwd, cliOptions.input);
|
|
77
|
+
if (fileConfig.input) return path.resolve(cwd, fileConfig.input);
|
|
78
|
+
|
|
79
|
+
// 2. Search candidates
|
|
80
|
+
const candidates = ["swatches", "src/swatches", "src/patterns"];
|
|
81
|
+
for (const cand of candidates) {
|
|
82
|
+
const absPath = path.join(cwd, cand);
|
|
83
|
+
if (fs.existsSync(absPath)) return absPath;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 3. Fallback default (swatches)
|
|
87
|
+
return path.join(cwd, "swatches");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const patternsDir = findPatternsDir();
|
|
91
|
+
|
|
92
|
+
// Output Dir
|
|
93
|
+
// Default: public/swatchkit
|
|
94
|
+
const outDir = cliOptions.outDir
|
|
95
|
+
? path.resolve(cwd, cliOptions.outDir)
|
|
96
|
+
: fileConfig.outDir
|
|
97
|
+
? path.resolve(cwd, fileConfig.outDir)
|
|
98
|
+
: path.join(cwd, "public/swatchkit");
|
|
99
|
+
|
|
100
|
+
// CSS Dir (Legacy support: src/css)
|
|
101
|
+
const cssDir = path.join(cwd, "src/css");
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
patternsDir,
|
|
105
|
+
outDir,
|
|
106
|
+
cssDir,
|
|
107
|
+
// Internal layout template (relative to this script)
|
|
108
|
+
internalLayout: path.join(__dirname, "src/layout.html"),
|
|
109
|
+
// Project specific layout override
|
|
110
|
+
projectLayout: path.join(patternsDir, "_layout.html"),
|
|
111
|
+
|
|
112
|
+
// Derived paths
|
|
113
|
+
distCssDir: path.join(outDir, "css"),
|
|
114
|
+
distTokensCssFile: path.join(outDir, "css", "tokens.css"),
|
|
115
|
+
distJsDir: path.join(outDir, "js"),
|
|
116
|
+
outputFile: path.join(outDir, "index.html"),
|
|
117
|
+
outputJsFile: path.join(outDir, "js/patterns.js"),
|
|
118
|
+
tokensCssFile: path.join(cssDir, "tokens.css"),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// --- 4. Init Command Logic ---
|
|
123
|
+
function runInit(settings, options) {
|
|
124
|
+
console.log("[SwatchKit] Initializing...");
|
|
125
|
+
|
|
126
|
+
// Ensure patterns directory exists
|
|
127
|
+
if (!fs.existsSync(settings.patternsDir)) {
|
|
128
|
+
console.log(`Creating patterns directory: ${settings.patternsDir}`);
|
|
129
|
+
fs.mkdirSync(settings.patternsDir, { recursive: true });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Create src/tokens directory and sample colors.json
|
|
133
|
+
const tokensDir = path.join(process.cwd(), "src/tokens");
|
|
134
|
+
if (!fs.existsSync(tokensDir)) {
|
|
135
|
+
console.log(`Creating tokens directory: ${tokensDir}`);
|
|
136
|
+
fs.mkdirSync(tokensDir, { recursive: true });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const colorsFile = path.join(tokensDir, "colors.json");
|
|
140
|
+
if (!fs.existsSync(colorsFile)) {
|
|
141
|
+
const sampleColors = {
|
|
142
|
+
title: "Colors",
|
|
143
|
+
description:
|
|
144
|
+
"Hex color codes that can be shared, cross-platform. They can be converted at point of usage, such as HSL for web or CMYK for print.",
|
|
145
|
+
items: [
|
|
146
|
+
{ name: "Dark", value: "#171406" },
|
|
147
|
+
{ name: "Dark Glare", value: "#2d2816" },
|
|
148
|
+
{ name: "Mid", value: "#ABA9A2" },
|
|
149
|
+
{ name: "Light", value: "#ffffff" },
|
|
150
|
+
{ name: "Primary", value: "#fcad26" },
|
|
151
|
+
],
|
|
152
|
+
};
|
|
153
|
+
fs.writeFileSync(colorsFile, JSON.stringify(sampleColors, null, 2));
|
|
154
|
+
console.log(`Created sample tokens file at ${colorsFile}`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Create sample colors.html pattern
|
|
158
|
+
const colorsPatternFile = path.join(settings.patternsDir, "colors.html");
|
|
159
|
+
if (!fs.existsSync(colorsPatternFile)) {
|
|
160
|
+
const colorsHtml = `
|
|
161
|
+
<style>
|
|
162
|
+
.swatch-grid {
|
|
163
|
+
display: grid;
|
|
164
|
+
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
165
|
+
gap: 1rem;
|
|
166
|
+
padding: 1rem;
|
|
167
|
+
}
|
|
168
|
+
.swatch {
|
|
169
|
+
border: 1px solid #ddd;
|
|
170
|
+
border-radius: 8px;
|
|
171
|
+
overflow: hidden;
|
|
172
|
+
}
|
|
173
|
+
.swatch-color {
|
|
174
|
+
height: 100px;
|
|
175
|
+
width: 100%;
|
|
176
|
+
}
|
|
177
|
+
.swatch-info {
|
|
178
|
+
padding: 0.5rem;
|
|
179
|
+
font-family: monospace;
|
|
180
|
+
font-size: 0.9rem;
|
|
181
|
+
background: #f9f9f9;
|
|
182
|
+
}
|
|
183
|
+
</style>
|
|
184
|
+
|
|
185
|
+
<div class="swatch-grid">
|
|
186
|
+
<div class="swatch">
|
|
187
|
+
<div class="swatch-color" style="background-color: var(--color-dark);"></div>
|
|
188
|
+
<div class="swatch-info">
|
|
189
|
+
<strong>Dark</strong><br>
|
|
190
|
+
var(--color-dark)
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
<div class="swatch">
|
|
194
|
+
<div class="swatch-color" style="background-color: var(--color-dark-glare);"></div>
|
|
195
|
+
<div class="swatch-info">
|
|
196
|
+
<strong>Dark Glare</strong><br>
|
|
197
|
+
var(--color-dark-glare)
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
<div class="swatch">
|
|
201
|
+
<div class="swatch-color" style="background-color: var(--color-mid);"></div>
|
|
202
|
+
<div class="swatch-info">
|
|
203
|
+
<strong>Mid</strong><br>
|
|
204
|
+
var(--color-mid)
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
<div class="swatch">
|
|
208
|
+
<div class="swatch-color" style="background-color: var(--color-light);"></div>
|
|
209
|
+
<div class="swatch-info">
|
|
210
|
+
<strong>Light</strong><br>
|
|
211
|
+
var(--color-light)
|
|
212
|
+
</div>
|
|
213
|
+
</div>
|
|
214
|
+
<div class="swatch">
|
|
215
|
+
<div class="swatch-color" style="background-color: var(--color-primary);"></div>
|
|
216
|
+
<div class="swatch-info">
|
|
217
|
+
<strong>Primary</strong><br>
|
|
218
|
+
var(--color-primary)
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
`;
|
|
223
|
+
fs.writeFileSync(colorsPatternFile, colorsHtml.trim());
|
|
224
|
+
console.log(`Created sample pattern at ${colorsPatternFile}`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Generate initial CSS
|
|
228
|
+
processTokens(process.cwd(), settings.cssDir);
|
|
229
|
+
|
|
230
|
+
const targetLayout = settings.projectLayout;
|
|
231
|
+
|
|
232
|
+
if (fs.existsSync(targetLayout) && !options.force) {
|
|
233
|
+
console.warn(`Warning: Layout file already exists at ${targetLayout}`);
|
|
234
|
+
console.warn("Use --force to overwrite.");
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (fs.existsSync(settings.internalLayout)) {
|
|
239
|
+
const layoutContent = fs.readFileSync(settings.internalLayout, "utf-8");
|
|
240
|
+
fs.writeFileSync(targetLayout, layoutContent);
|
|
241
|
+
console.log(`Created layout file at ${targetLayout}`);
|
|
242
|
+
} else {
|
|
243
|
+
console.error(
|
|
244
|
+
`Error: Internal layout file not found at ${settings.internalLayout}`,
|
|
245
|
+
);
|
|
246
|
+
process.exit(1);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// --- 5. Build Logic ---
|
|
251
|
+
function build(settings) {
|
|
252
|
+
console.log(`[SwatchKit] Starting build...`);
|
|
253
|
+
console.log(` Patterns: ${settings.patternsDir}`);
|
|
254
|
+
console.log(` Output: ${settings.outDir}`);
|
|
19
255
|
|
|
20
256
|
// 1. Check if patterns directory exists
|
|
21
|
-
if (!fs.existsSync(
|
|
22
|
-
console.error(
|
|
257
|
+
if (!fs.existsSync(settings.patternsDir)) {
|
|
258
|
+
console.error(
|
|
259
|
+
`Error: Patterns directory not found at ${settings.patternsDir}`,
|
|
260
|
+
);
|
|
261
|
+
console.error('Run "swatchkit init" to get started.');
|
|
23
262
|
process.exit(1);
|
|
24
263
|
}
|
|
25
264
|
|
|
26
265
|
// 2. Ensure dist directories exist
|
|
27
|
-
[
|
|
266
|
+
[settings.outDir, settings.distCssDir, settings.distJsDir].forEach((dir) => {
|
|
28
267
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
29
268
|
});
|
|
30
269
|
|
|
270
|
+
// 2.5 Process Tokens
|
|
271
|
+
processTokens(process.cwd(), settings.cssDir);
|
|
272
|
+
|
|
31
273
|
// 3. Copy CSS files
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
274
|
+
if (fs.existsSync(settings.cssDir)) {
|
|
275
|
+
console.log("Copying CSS...");
|
|
276
|
+
const cssFiles = fs
|
|
277
|
+
.readdirSync(settings.cssDir)
|
|
278
|
+
.filter((file) => file.endsWith(".css"));
|
|
279
|
+
cssFiles.forEach((file) => {
|
|
280
|
+
fs.copyFileSync(
|
|
281
|
+
path.join(settings.cssDir, file),
|
|
282
|
+
path.join(settings.distCssDir, file),
|
|
283
|
+
);
|
|
284
|
+
});
|
|
38
285
|
}
|
|
39
286
|
|
|
40
287
|
// 4. Read patterns & JS
|
|
41
|
-
console.log(
|
|
288
|
+
console.log("Processing patterns...");
|
|
42
289
|
const patterns = [];
|
|
43
290
|
const scripts = [];
|
|
44
291
|
|
|
45
|
-
const items = fs.readdirSync(
|
|
46
|
-
|
|
47
|
-
items.forEach(item => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
292
|
+
const items = fs.readdirSync(settings.patternsDir);
|
|
293
|
+
|
|
294
|
+
items.forEach((item) => {
|
|
295
|
+
// Skip _layout.html or hidden files
|
|
296
|
+
if (item.startsWith("_") || item.startsWith(".")) return;
|
|
297
|
+
|
|
298
|
+
const itemPath = path.join(settings.patternsDir, item);
|
|
299
|
+
const stat = fs.statSync(itemPath);
|
|
300
|
+
|
|
301
|
+
let name, content, id;
|
|
302
|
+
|
|
303
|
+
// Handle Directory Pattern
|
|
304
|
+
if (stat.isDirectory()) {
|
|
305
|
+
const indexFile = path.join(itemPath, "index.html");
|
|
306
|
+
|
|
307
|
+
if (fs.existsSync(indexFile)) {
|
|
308
|
+
name = item;
|
|
309
|
+
id = item;
|
|
310
|
+
content = fs.readFileSync(indexFile, "utf-8");
|
|
311
|
+
|
|
312
|
+
// Find all .js files
|
|
313
|
+
const jsFiles = fs
|
|
314
|
+
.readdirSync(itemPath)
|
|
315
|
+
.filter((file) => file.endsWith(".js"));
|
|
316
|
+
|
|
317
|
+
jsFiles.forEach((jsFile) => {
|
|
318
|
+
const scriptContent = fs.readFileSync(
|
|
319
|
+
path.join(itemPath, jsFile),
|
|
320
|
+
"utf-8",
|
|
321
|
+
);
|
|
322
|
+
scripts.push(`
|
|
68
323
|
/* --- Pattern: ${name} / File: ${jsFile} --- */
|
|
69
324
|
(function() {
|
|
70
325
|
${scriptContent}
|
|
71
326
|
})();
|
|
72
327
|
`);
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
// Handle Single File Pattern (.html)
|
|
77
|
-
else if (item.endsWith('.html')) {
|
|
78
|
-
name = path.basename(item, '.html');
|
|
79
|
-
id = name;
|
|
80
|
-
content = fs.readFileSync(itemPath, 'utf-8');
|
|
328
|
+
});
|
|
81
329
|
}
|
|
330
|
+
}
|
|
331
|
+
// Handle Single File Pattern
|
|
332
|
+
else if (item.endsWith(".html")) {
|
|
333
|
+
name = path.basename(item, ".html");
|
|
334
|
+
id = name;
|
|
335
|
+
content = fs.readFileSync(itemPath, "utf-8");
|
|
336
|
+
}
|
|
82
337
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
338
|
+
if (name && content) {
|
|
339
|
+
patterns.push({ name, id, content });
|
|
340
|
+
}
|
|
341
|
+
});
|
|
87
342
|
|
|
88
343
|
// 5. Generate HTML fragments
|
|
89
|
-
const sidebarLinks = patterns
|
|
90
|
-
`<a href="#${p.id}">${p.name}</a>`
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const patternBlocks = patterns
|
|
94
|
-
|
|
95
|
-
.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
344
|
+
const sidebarLinks = patterns
|
|
345
|
+
.map((p) => `<a href="#${p.id}">${p.name}</a>`)
|
|
346
|
+
.join("\n");
|
|
347
|
+
|
|
348
|
+
const patternBlocks = patterns
|
|
349
|
+
.map((p) => {
|
|
350
|
+
const escapedContent = p.content
|
|
351
|
+
.replace(/&/g, "&")
|
|
352
|
+
.replace(/</g, "<")
|
|
353
|
+
.replace(/>/g, ">")
|
|
354
|
+
.replace(/"/g, """)
|
|
355
|
+
.replace(/'/g, "'");
|
|
356
|
+
|
|
357
|
+
return `
|
|
102
358
|
<section id="${p.id}">
|
|
103
359
|
<h2>${p.name}</h2>
|
|
104
360
|
<div class="preview">${p.content}</div>
|
|
105
361
|
<pre><code>${escapedContent}</code></pre>
|
|
106
362
|
</section>
|
|
107
363
|
`;
|
|
108
|
-
|
|
364
|
+
})
|
|
365
|
+
.join("\n");
|
|
109
366
|
|
|
110
367
|
// 6. Write JS Bundle
|
|
111
368
|
if (scripts.length > 0) {
|
|
112
|
-
fs.writeFileSync(
|
|
113
|
-
console.log(
|
|
369
|
+
fs.writeFileSync(settings.outputJsFile, scripts.join("\n"));
|
|
370
|
+
console.log(
|
|
371
|
+
`Bundled ${scripts.length} scripts to ${settings.outputJsFile}`,
|
|
372
|
+
);
|
|
373
|
+
} else {
|
|
374
|
+
fs.writeFileSync(settings.outputJsFile, "// No pattern scripts found");
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// 7. Load Layout
|
|
378
|
+
let layoutContent;
|
|
379
|
+
if (fs.existsSync(settings.projectLayout)) {
|
|
380
|
+
console.log(`Using custom layout: ${settings.projectLayout}`);
|
|
381
|
+
layoutContent = fs.readFileSync(settings.projectLayout, "utf-8");
|
|
114
382
|
} else {
|
|
115
|
-
//
|
|
116
|
-
fs.
|
|
383
|
+
// console.log(`Using internal layout`);
|
|
384
|
+
layoutContent = fs.readFileSync(settings.internalLayout, "utf-8");
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
let headExtras = "";
|
|
388
|
+
// Check if the tokens file exists in the *output* directory (where we copied it to)
|
|
389
|
+
if (fs.existsSync(settings.distTokensCssFile)) {
|
|
390
|
+
headExtras = '<link rel="stylesheet" href="css/tokens.css">';
|
|
117
391
|
}
|
|
118
392
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
.replace('<!-- SIDEBAR_LINKS -->', sidebarLinks)
|
|
124
|
-
.replace('<!-- PATTERNS -->', patternBlocks);
|
|
393
|
+
const finalHtml = layoutContent
|
|
394
|
+
.replace("<!-- SIDEBAR_LINKS -->", sidebarLinks)
|
|
395
|
+
.replace("<!-- PATTERNS -->", patternBlocks)
|
|
396
|
+
.replace("<!-- HEAD_EXTRAS -->", headExtras);
|
|
125
397
|
|
|
126
398
|
// 8. Write output
|
|
127
|
-
fs.writeFileSync(
|
|
128
|
-
|
|
129
|
-
console.log(`Build complete! Generated ${
|
|
399
|
+
fs.writeFileSync(settings.outputFile, finalHtml);
|
|
400
|
+
|
|
401
|
+
console.log(`Build complete! Generated ${settings.outputFile}`);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// --- Main Execution ---
|
|
405
|
+
try {
|
|
406
|
+
const cliOptions = parseArgs(process.argv);
|
|
407
|
+
const fileConfig = loadConfig(cliOptions.config);
|
|
408
|
+
const settings = resolveSettings(cliOptions, fileConfig);
|
|
409
|
+
|
|
410
|
+
if (cliOptions.command === "init") {
|
|
411
|
+
runInit(settings, cliOptions);
|
|
412
|
+
} else {
|
|
413
|
+
build(settings);
|
|
414
|
+
if (cliOptions.watch) {
|
|
415
|
+
console.log("[SwatchKit] Watch mode is not yet fully implemented.");
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
} catch (error) {
|
|
419
|
+
console.error("[SwatchKit] Error:", error.message);
|
|
420
|
+
process.exit(1);
|
|
130
421
|
}
|
|
131
422
|
|
|
132
|
-
build();
|
package/package.json
CHANGED
package/src/layout.html
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>SwatchKit</title>
|
|
7
7
|
<link rel="stylesheet" href="/css/global.css" />
|
|
8
|
+
<!-- HEAD_EXTRAS -->
|
|
8
9
|
<style>
|
|
9
10
|
body {
|
|
10
11
|
display: flex;
|
|
@@ -86,4 +87,4 @@
|
|
|
86
87
|
</main>
|
|
87
88
|
<script src="js/patterns.js"></script>
|
|
88
89
|
</body>
|
|
89
|
-
</html>
|
|
90
|
+
</html>
|