swatchkit 0.0.1 → 0.0.2
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 +194 -36
- package/package.json +1 -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
|
@@ -2,38 +2,170 @@
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
5
|
+
/**
|
|
6
|
+
* SwatchKit Build Script
|
|
7
|
+
* Refactored for Phase 1 Expansion
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// --- 1. CLI Argument Parsing ---
|
|
11
|
+
function parseArgs(args) {
|
|
12
|
+
const options = {
|
|
13
|
+
command: null,
|
|
14
|
+
watch: false,
|
|
15
|
+
config: null,
|
|
16
|
+
input: null,
|
|
17
|
+
outDir: null,
|
|
18
|
+
force: false
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
for (let i = 2; i < args.length; i++) {
|
|
22
|
+
const arg = args[i];
|
|
23
|
+
if (arg === 'init') {
|
|
24
|
+
options.command = 'init';
|
|
25
|
+
} else if (arg === '-w' || arg === '--watch') {
|
|
26
|
+
options.watch = true;
|
|
27
|
+
} else if (arg === '-f' || arg === '--force') {
|
|
28
|
+
options.force = true;
|
|
29
|
+
} else if (arg === '-c' || arg === '--config') {
|
|
30
|
+
// Handle case where flag is last arg
|
|
31
|
+
if (i + 1 < args.length) {
|
|
32
|
+
options.config = args[++i];
|
|
33
|
+
}
|
|
34
|
+
} else if (arg === '-i' || arg === '--input') {
|
|
35
|
+
if (i + 1 < args.length) {
|
|
36
|
+
options.input = args[++i];
|
|
37
|
+
}
|
|
38
|
+
} else if (arg === '-o' || arg === '--outDir') {
|
|
39
|
+
if (i + 1 < args.length) {
|
|
40
|
+
options.outDir = args[++i];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return options;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// --- 2. Config Loading ---
|
|
48
|
+
function loadConfig(configPath) {
|
|
49
|
+
let finalPath;
|
|
50
|
+
if (configPath) {
|
|
51
|
+
finalPath = path.resolve(process.cwd(), configPath);
|
|
52
|
+
} else {
|
|
53
|
+
finalPath = path.join(process.cwd(), 'swatchkit.config.js');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (fs.existsSync(finalPath)) {
|
|
57
|
+
try {
|
|
58
|
+
console.log(`[SwatchKit] Loading config from ${finalPath}`);
|
|
59
|
+
return require(finalPath);
|
|
60
|
+
} catch (e) {
|
|
61
|
+
console.error('[SwatchKit] Error loading config file:', e.message);
|
|
62
|
+
return {};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return {};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// --- 3. Smart Defaults & Path Resolution ---
|
|
69
|
+
function resolveSettings(cliOptions, fileConfig) {
|
|
70
|
+
const cwd = process.cwd();
|
|
71
|
+
|
|
72
|
+
// Helper to find patterns dir
|
|
73
|
+
function findPatternsDir() {
|
|
74
|
+
// 1. Explicit input
|
|
75
|
+
if (cliOptions.input) return path.resolve(cwd, cliOptions.input);
|
|
76
|
+
if (fileConfig.input) return path.resolve(cwd, fileConfig.input);
|
|
77
|
+
|
|
78
|
+
// 2. Search candidates
|
|
79
|
+
const candidates = ['swatches', 'src/swatches', 'src/patterns'];
|
|
80
|
+
for (const cand of candidates) {
|
|
81
|
+
const absPath = path.join(cwd, cand);
|
|
82
|
+
if (fs.existsSync(absPath)) return absPath;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// 3. Fallback default (swatches)
|
|
86
|
+
return path.join(cwd, 'swatches');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const patternsDir = findPatternsDir();
|
|
90
|
+
|
|
91
|
+
// Output Dir
|
|
92
|
+
// Default: public/swatchkit
|
|
93
|
+
const outDir = cliOptions.outDir
|
|
94
|
+
? path.resolve(cwd, cliOptions.outDir)
|
|
95
|
+
: (fileConfig.outDir ? path.resolve(cwd, fileConfig.outDir) : path.join(cwd, 'public/swatchkit'));
|
|
96
|
+
|
|
97
|
+
// CSS Dir (Legacy support: src/css)
|
|
98
|
+
const cssDir = path.join(cwd, 'src/css');
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
patternsDir,
|
|
102
|
+
outDir,
|
|
103
|
+
cssDir,
|
|
104
|
+
// Internal layout template (relative to this script)
|
|
105
|
+
internalLayout: path.join(__dirname, 'src/layout.html'),
|
|
106
|
+
// Project specific layout override
|
|
107
|
+
projectLayout: path.join(patternsDir, '_layout.html'),
|
|
108
|
+
|
|
109
|
+
// Derived paths
|
|
110
|
+
distCssDir: path.join(outDir, 'css'),
|
|
111
|
+
distJsDir: path.join(outDir, 'js'),
|
|
112
|
+
outputFile: path.join(outDir, 'index.html'),
|
|
113
|
+
outputJsFile: path.join(outDir, 'js/patterns.js')
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// --- 4. Init Command Logic ---
|
|
118
|
+
function runInit(settings, options) {
|
|
119
|
+
console.log('[SwatchKit] Initializing...');
|
|
120
|
+
|
|
121
|
+
// Ensure patterns directory exists
|
|
122
|
+
if (!fs.existsSync(settings.patternsDir)) {
|
|
123
|
+
console.log(`Creating patterns directory: ${settings.patternsDir}`);
|
|
124
|
+
fs.mkdirSync(settings.patternsDir, { recursive: true });
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const targetLayout = settings.projectLayout;
|
|
128
|
+
|
|
129
|
+
if (fs.existsSync(targetLayout) && !options.force) {
|
|
130
|
+
console.warn(`Warning: Layout file already exists at ${targetLayout}`);
|
|
131
|
+
console.warn('Use --force to overwrite.');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (fs.existsSync(settings.internalLayout)) {
|
|
136
|
+
const layoutContent = fs.readFileSync(settings.internalLayout, 'utf-8');
|
|
137
|
+
fs.writeFileSync(targetLayout, layoutContent);
|
|
138
|
+
console.log(`Created layout file at ${targetLayout}`);
|
|
139
|
+
} else {
|
|
140
|
+
console.error(`Error: Internal layout file not found at ${settings.internalLayout}`);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// --- 5. Build Logic ---
|
|
146
|
+
function build(settings) {
|
|
147
|
+
console.log(`[SwatchKit] Starting build...`);
|
|
148
|
+
console.log(` Patterns: ${settings.patternsDir}`);
|
|
149
|
+
console.log(` Output: ${settings.outDir}`);
|
|
19
150
|
|
|
20
151
|
// 1. Check if patterns directory exists
|
|
21
|
-
if (!fs.existsSync(
|
|
22
|
-
console.error(
|
|
152
|
+
if (!fs.existsSync(settings.patternsDir)) {
|
|
153
|
+
console.error(`Error: Patterns directory not found at ${settings.patternsDir}`);
|
|
154
|
+
console.error('Run "swatchkit init" to get started.');
|
|
23
155
|
process.exit(1);
|
|
24
156
|
}
|
|
25
157
|
|
|
26
158
|
// 2. Ensure dist directories exist
|
|
27
|
-
[
|
|
159
|
+
[settings.outDir, settings.distCssDir, settings.distJsDir].forEach(dir => {
|
|
28
160
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
29
161
|
});
|
|
30
162
|
|
|
31
163
|
// 3. Copy CSS files
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const cssFiles = fs.readdirSync(
|
|
164
|
+
if (fs.existsSync(settings.cssDir)) {
|
|
165
|
+
console.log('Copying CSS...');
|
|
166
|
+
const cssFiles = fs.readdirSync(settings.cssDir).filter(file => file.endsWith('.css'));
|
|
35
167
|
cssFiles.forEach(file => {
|
|
36
|
-
fs.copyFileSync(path.join(
|
|
168
|
+
fs.copyFileSync(path.join(settings.cssDir, file), path.join(settings.distCssDir, file));
|
|
37
169
|
});
|
|
38
170
|
}
|
|
39
171
|
|
|
@@ -42,15 +174,18 @@ function build() {
|
|
|
42
174
|
const patterns = [];
|
|
43
175
|
const scripts = [];
|
|
44
176
|
|
|
45
|
-
const items = fs.readdirSync(
|
|
177
|
+
const items = fs.readdirSync(settings.patternsDir);
|
|
46
178
|
|
|
47
179
|
items.forEach(item => {
|
|
48
|
-
|
|
180
|
+
// Skip _layout.html or hidden files
|
|
181
|
+
if (item.startsWith('_') || item.startsWith('.')) return;
|
|
182
|
+
|
|
183
|
+
const itemPath = path.join(settings.patternsDir, item);
|
|
49
184
|
const stat = fs.statSync(itemPath);
|
|
50
185
|
|
|
51
186
|
let name, content, id;
|
|
52
187
|
|
|
53
|
-
// Handle Directory Pattern
|
|
188
|
+
// Handle Directory Pattern
|
|
54
189
|
if (stat.isDirectory()) {
|
|
55
190
|
const indexFile = path.join(itemPath, 'index.html');
|
|
56
191
|
|
|
@@ -59,7 +194,7 @@ function build() {
|
|
|
59
194
|
id = item;
|
|
60
195
|
content = fs.readFileSync(indexFile, 'utf-8');
|
|
61
196
|
|
|
62
|
-
// Find all .js files
|
|
197
|
+
// Find all .js files
|
|
63
198
|
const jsFiles = fs.readdirSync(itemPath).filter(file => file.endsWith('.js'));
|
|
64
199
|
|
|
65
200
|
jsFiles.forEach(jsFile => {
|
|
@@ -73,7 +208,7 @@ ${scriptContent}
|
|
|
73
208
|
});
|
|
74
209
|
}
|
|
75
210
|
}
|
|
76
|
-
// Handle Single File Pattern
|
|
211
|
+
// Handle Single File Pattern
|
|
77
212
|
else if (item.endsWith('.html')) {
|
|
78
213
|
name = path.basename(item, '.html');
|
|
79
214
|
id = name;
|
|
@@ -109,24 +244,47 @@ ${scriptContent}
|
|
|
109
244
|
|
|
110
245
|
// 6. Write JS Bundle
|
|
111
246
|
if (scripts.length > 0) {
|
|
112
|
-
fs.writeFileSync(
|
|
113
|
-
console.log(`Bundled ${scripts.length} scripts to ${
|
|
247
|
+
fs.writeFileSync(settings.outputJsFile, scripts.join('\n'));
|
|
248
|
+
console.log(`Bundled ${scripts.length} scripts to ${settings.outputJsFile}`);
|
|
114
249
|
} else {
|
|
115
|
-
//
|
|
116
|
-
fs.writeFileSync(config.outputJsFile, '// No pattern scripts found');
|
|
250
|
+
fs.writeFileSync(settings.outputJsFile, '// No pattern scripts found');
|
|
117
251
|
}
|
|
118
252
|
|
|
119
|
-
// 7.
|
|
120
|
-
let
|
|
253
|
+
// 7. Load Layout
|
|
254
|
+
let layoutContent;
|
|
255
|
+
if (fs.existsSync(settings.projectLayout)) {
|
|
256
|
+
console.log(`Using custom layout: ${settings.projectLayout}`);
|
|
257
|
+
layoutContent = fs.readFileSync(settings.projectLayout, 'utf-8');
|
|
258
|
+
} else {
|
|
259
|
+
// console.log(`Using internal layout`);
|
|
260
|
+
layoutContent = fs.readFileSync(settings.internalLayout, 'utf-8');
|
|
261
|
+
}
|
|
121
262
|
|
|
122
|
-
const finalHtml =
|
|
263
|
+
const finalHtml = layoutContent
|
|
123
264
|
.replace('<!-- SIDEBAR_LINKS -->', sidebarLinks)
|
|
124
265
|
.replace('<!-- PATTERNS -->', patternBlocks);
|
|
125
266
|
|
|
126
267
|
// 8. Write output
|
|
127
|
-
fs.writeFileSync(
|
|
268
|
+
fs.writeFileSync(settings.outputFile, finalHtml);
|
|
128
269
|
|
|
129
|
-
console.log(`Build complete! Generated ${
|
|
270
|
+
console.log(`Build complete! Generated ${settings.outputFile}`);
|
|
130
271
|
}
|
|
131
272
|
|
|
132
|
-
|
|
273
|
+
// --- Main Execution ---
|
|
274
|
+
try {
|
|
275
|
+
const cliOptions = parseArgs(process.argv);
|
|
276
|
+
const fileConfig = loadConfig(cliOptions.config);
|
|
277
|
+
const settings = resolveSettings(cliOptions, fileConfig);
|
|
278
|
+
|
|
279
|
+
if (cliOptions.command === 'init') {
|
|
280
|
+
runInit(settings, cliOptions);
|
|
281
|
+
} else {
|
|
282
|
+
build(settings);
|
|
283
|
+
if (cliOptions.watch) {
|
|
284
|
+
console.log('[SwatchKit] Watch mode is not yet fully implemented.');
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
} catch (error) {
|
|
288
|
+
console.error('[SwatchKit] Error:', error.message);
|
|
289
|
+
process.exit(1);
|
|
290
|
+
}
|