swatchkit 0.0.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 +57 -0
- package/build.js +132 -0
- package/package.json +27 -0
- package/src/layout.html +89 -0
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# SwatchKit
|
|
2
|
+
|
|
3
|
+
**SwatchKit** is a lightweight, zero-configuration tool for creating HTML pattern libraries. It follows the "Magic Folder" principle: you drop files in, and a documentation site comes out.
|
|
4
|
+
|
|
5
|
+
## How it works
|
|
6
|
+
|
|
7
|
+
1. **Drop Patterns:** Add `.html` files (or folders) to `src/patterns/`.
|
|
8
|
+
2. **Add Styles:** Add standard CSS to `src/css/styles.css`.
|
|
9
|
+
3. **Build:** Run `node build.js`.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
### 1. The Magic Folder
|
|
14
|
+
* **Single File:** Drop `button.html` into `src/patterns/`. It automatically appears in the library.
|
|
15
|
+
* **Component Folder:** Drop a folder like `src/patterns/carousel/` containing `index.html`. It works exactly the same way.
|
|
16
|
+
|
|
17
|
+
### 2. Automatic JS Bundling
|
|
18
|
+
If your component needs client-side JavaScript, just add a `.js` file to its folder.
|
|
19
|
+
* Example: `src/patterns/carousel/script.js`
|
|
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.
|
|
21
|
+
|
|
22
|
+
### 3. Zero Config
|
|
23
|
+
No config files. No build pipelines. No complex templating engines. Just HTML, CSS, and JS.
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Using npx (Recommended)
|
|
28
|
+
|
|
29
|
+
Run directly without installing:
|
|
30
|
+
```bash
|
|
31
|
+
npx swatchkit
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Installing locally
|
|
35
|
+
|
|
36
|
+
Install as a dev dependency:
|
|
37
|
+
```bash
|
|
38
|
+
npm install -D swatchkit
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then add to your `package.json` scripts:
|
|
42
|
+
```json
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build:patterns": "swatchkit"
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
And run:
|
|
49
|
+
```bash
|
|
50
|
+
npm run build:patterns
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### View the library
|
|
54
|
+
After building, open the generated file:
|
|
55
|
+
```bash
|
|
56
|
+
open dist/index.html
|
|
57
|
+
```
|
package/build.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
const config = {
|
|
6
|
+
srcDir: path.join(process.cwd(), 'src'),
|
|
7
|
+
cssDir: path.join(process.cwd(), 'src/css'),
|
|
8
|
+
patternsDir: path.join(process.cwd(), 'src/patterns'),
|
|
9
|
+
layoutFile: path.join(__dirname, 'src/layout.html'),
|
|
10
|
+
distDir: path.join(process.cwd(), 'dist'),
|
|
11
|
+
distCssDir: path.join(process.cwd(), 'dist/css'),
|
|
12
|
+
distJsDir: path.join(process.cwd(), 'dist/js'),
|
|
13
|
+
outputFile: path.join(process.cwd(), 'dist/index.html'),
|
|
14
|
+
outputJsFile: path.join(process.cwd(), 'dist/js/patterns.js')
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function build() {
|
|
18
|
+
console.log('[SwatchKit] Starting build...');
|
|
19
|
+
|
|
20
|
+
// 1. Check if patterns directory exists
|
|
21
|
+
if (!fs.existsSync(config.patternsDir)) {
|
|
22
|
+
console.error('Error: No patterns found. Create src/patterns to get started.');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 2. Ensure dist directories exist
|
|
27
|
+
[config.distDir, config.distCssDir, config.distJsDir].forEach(dir => {
|
|
28
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// 3. Copy CSS files
|
|
32
|
+
console.log('Copying CSS...');
|
|
33
|
+
if (fs.existsSync(config.cssDir)) {
|
|
34
|
+
const cssFiles = fs.readdirSync(config.cssDir).filter(file => file.endsWith('.css'));
|
|
35
|
+
cssFiles.forEach(file => {
|
|
36
|
+
fs.copyFileSync(path.join(config.cssDir, file), path.join(config.distCssDir, file));
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 4. Read patterns & JS
|
|
41
|
+
console.log('Processing patterns...');
|
|
42
|
+
const patterns = [];
|
|
43
|
+
const scripts = [];
|
|
44
|
+
|
|
45
|
+
const items = fs.readdirSync(config.patternsDir);
|
|
46
|
+
|
|
47
|
+
items.forEach(item => {
|
|
48
|
+
const itemPath = path.join(config.patternsDir, item);
|
|
49
|
+
const stat = fs.statSync(itemPath);
|
|
50
|
+
|
|
51
|
+
let name, content, id;
|
|
52
|
+
|
|
53
|
+
// Handle Directory Pattern (Folder with index.html + optional JS files)
|
|
54
|
+
if (stat.isDirectory()) {
|
|
55
|
+
const indexFile = path.join(itemPath, 'index.html');
|
|
56
|
+
|
|
57
|
+
if (fs.existsSync(indexFile)) {
|
|
58
|
+
name = item;
|
|
59
|
+
id = item;
|
|
60
|
+
content = fs.readFileSync(indexFile, 'utf-8');
|
|
61
|
+
|
|
62
|
+
// Find all .js files in this directory
|
|
63
|
+
const jsFiles = fs.readdirSync(itemPath).filter(file => file.endsWith('.js'));
|
|
64
|
+
|
|
65
|
+
jsFiles.forEach(jsFile => {
|
|
66
|
+
const scriptContent = fs.readFileSync(path.join(itemPath, jsFile), 'utf-8');
|
|
67
|
+
scripts.push(`
|
|
68
|
+
/* --- Pattern: ${name} / File: ${jsFile} --- */
|
|
69
|
+
(function() {
|
|
70
|
+
${scriptContent}
|
|
71
|
+
})();
|
|
72
|
+
`);
|
|
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');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (name && content) {
|
|
84
|
+
patterns.push({ name, id, content });
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// 5. Generate HTML fragments
|
|
89
|
+
const sidebarLinks = patterns.map(p =>
|
|
90
|
+
`<a href="#${p.id}">${p.name}</a>`
|
|
91
|
+
).join('\n');
|
|
92
|
+
|
|
93
|
+
const patternBlocks = patterns.map(p => {
|
|
94
|
+
const escapedContent = p.content
|
|
95
|
+
.replace(/&/g, "&")
|
|
96
|
+
.replace(/</g, "<")
|
|
97
|
+
.replace(/>/g, ">")
|
|
98
|
+
.replace(/"/g, """)
|
|
99
|
+
.replace(/'/g, "'");
|
|
100
|
+
|
|
101
|
+
return `
|
|
102
|
+
<section id="${p.id}">
|
|
103
|
+
<h2>${p.name}</h2>
|
|
104
|
+
<div class="preview">${p.content}</div>
|
|
105
|
+
<pre><code>${escapedContent}</code></pre>
|
|
106
|
+
</section>
|
|
107
|
+
`;
|
|
108
|
+
}).join('\n');
|
|
109
|
+
|
|
110
|
+
// 6. Write JS Bundle
|
|
111
|
+
if (scripts.length > 0) {
|
|
112
|
+
fs.writeFileSync(config.outputJsFile, scripts.join('\n'));
|
|
113
|
+
console.log(`Bundled ${scripts.length} scripts to ${config.outputJsFile}`);
|
|
114
|
+
} else {
|
|
115
|
+
// Write empty file if no scripts so browser doesn't 404
|
|
116
|
+
fs.writeFileSync(config.outputJsFile, '// No pattern scripts found');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 7. Read layout and replace placeholders
|
|
120
|
+
let layout = fs.readFileSync(config.layoutFile, 'utf-8');
|
|
121
|
+
|
|
122
|
+
const finalHtml = layout
|
|
123
|
+
.replace('<!-- SIDEBAR_LINKS -->', sidebarLinks)
|
|
124
|
+
.replace('<!-- PATTERNS -->', patternBlocks);
|
|
125
|
+
|
|
126
|
+
// 8. Write output
|
|
127
|
+
fs.writeFileSync(config.outputFile, finalHtml);
|
|
128
|
+
|
|
129
|
+
console.log(`Build complete! Generated ${config.outputFile}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
build();
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "swatchkit",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A lightweight tool for creating HTML pattern libraries.",
|
|
5
|
+
"main": "build.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"swatchkit": "./build.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"build.js",
|
|
11
|
+
"src/layout.html"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"start": "node build.js",
|
|
15
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/cwebley/swatchkit.git"
|
|
20
|
+
},
|
|
21
|
+
"author": "cwebley",
|
|
22
|
+
"license": "ISC",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/cwebley/swatchkit/issues"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/cwebley/swatchkit#readme"
|
|
27
|
+
}
|
package/src/layout.html
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>SwatchKit</title>
|
|
7
|
+
<link rel="stylesheet" href="/css/global.css" />
|
|
8
|
+
<style>
|
|
9
|
+
body {
|
|
10
|
+
display: flex;
|
|
11
|
+
margin: 0;
|
|
12
|
+
min-height: 100vh;
|
|
13
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
14
|
+
}
|
|
15
|
+
aside {
|
|
16
|
+
width: 250px;
|
|
17
|
+
background-color: #f7f7f7;
|
|
18
|
+
border-right: 1px solid #e5e5e5;
|
|
19
|
+
padding: 2rem 1.5rem;
|
|
20
|
+
flex-shrink: 0;
|
|
21
|
+
height: 100vh;
|
|
22
|
+
position: sticky;
|
|
23
|
+
top: 0;
|
|
24
|
+
overflow-y: auto;
|
|
25
|
+
}
|
|
26
|
+
aside h2 {
|
|
27
|
+
margin-top: 0;
|
|
28
|
+
font-size: 1.25rem;
|
|
29
|
+
margin-bottom: 1.5rem;
|
|
30
|
+
}
|
|
31
|
+
aside nav {
|
|
32
|
+
display: flex;
|
|
33
|
+
flex-direction: column;
|
|
34
|
+
gap: 0.75rem;
|
|
35
|
+
}
|
|
36
|
+
aside nav a {
|
|
37
|
+
text-decoration: none;
|
|
38
|
+
color: #333;
|
|
39
|
+
}
|
|
40
|
+
aside nav a:hover {
|
|
41
|
+
color: #000;
|
|
42
|
+
text-decoration: underline;
|
|
43
|
+
}
|
|
44
|
+
main {
|
|
45
|
+
flex: 1;
|
|
46
|
+
padding: 3rem;
|
|
47
|
+
max-width: 1200px;
|
|
48
|
+
}
|
|
49
|
+
section {
|
|
50
|
+
margin-bottom: 4rem;
|
|
51
|
+
border-bottom: 1px solid #eee;
|
|
52
|
+
padding-bottom: 2rem;
|
|
53
|
+
}
|
|
54
|
+
section h2 {
|
|
55
|
+
margin-top: 0;
|
|
56
|
+
font-size: 1.5rem;
|
|
57
|
+
margin-bottom: 1rem;
|
|
58
|
+
}
|
|
59
|
+
.preview {
|
|
60
|
+
border: 1px solid #e5e5e5;
|
|
61
|
+
padding: 2rem;
|
|
62
|
+
border-radius: 4px;
|
|
63
|
+
background: white;
|
|
64
|
+
margin-bottom: 1.5rem;
|
|
65
|
+
}
|
|
66
|
+
pre {
|
|
67
|
+
background: #2d2d2d;
|
|
68
|
+
color: #fff;
|
|
69
|
+
padding: 1rem;
|
|
70
|
+
border-radius: 4px;
|
|
71
|
+
overflow-x: auto;
|
|
72
|
+
}
|
|
73
|
+
</style>
|
|
74
|
+
</head>
|
|
75
|
+
<body>
|
|
76
|
+
<aside>
|
|
77
|
+
<header>
|
|
78
|
+
<h2>SwatchKit</h2>
|
|
79
|
+
</header>
|
|
80
|
+
<nav>
|
|
81
|
+
<!-- SIDEBAR_LINKS -->
|
|
82
|
+
</nav>
|
|
83
|
+
</aside>
|
|
84
|
+
<main>
|
|
85
|
+
<!-- PATTERNS -->
|
|
86
|
+
</main>
|
|
87
|
+
<script src="js/patterns.js"></script>
|
|
88
|
+
</body>
|
|
89
|
+
</html>
|