swatchkit 0.0.2 → 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/build.js +231 -99
- package/package.json +1 -1
- package/src/layout.html +2 -1
package/build.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const fs = require(
|
|
3
|
-
const path = require(
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const { processTokens } = require("./src/tokens");
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* SwatchKit Build Script
|
|
@@ -15,27 +16,27 @@ function parseArgs(args) {
|
|
|
15
16
|
config: null,
|
|
16
17
|
input: null,
|
|
17
18
|
outDir: null,
|
|
18
|
-
force: false
|
|
19
|
+
force: false,
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
for (let i = 2; i < args.length; i++) {
|
|
22
23
|
const arg = args[i];
|
|
23
|
-
if (arg ===
|
|
24
|
-
options.command =
|
|
25
|
-
} else if (arg ===
|
|
24
|
+
if (arg === "init") {
|
|
25
|
+
options.command = "init";
|
|
26
|
+
} else if (arg === "-w" || arg === "--watch") {
|
|
26
27
|
options.watch = true;
|
|
27
|
-
} else if (arg ===
|
|
28
|
+
} else if (arg === "-f" || arg === "--force") {
|
|
28
29
|
options.force = true;
|
|
29
|
-
} else if (arg ===
|
|
30
|
+
} else if (arg === "-c" || arg === "--config") {
|
|
30
31
|
// Handle case where flag is last arg
|
|
31
32
|
if (i + 1 < args.length) {
|
|
32
33
|
options.config = args[++i];
|
|
33
34
|
}
|
|
34
|
-
} else if (arg ===
|
|
35
|
+
} else if (arg === "-i" || arg === "--input") {
|
|
35
36
|
if (i + 1 < args.length) {
|
|
36
37
|
options.input = args[++i];
|
|
37
38
|
}
|
|
38
|
-
} else if (arg ===
|
|
39
|
+
} else if (arg === "-o" || arg === "--outDir") {
|
|
39
40
|
if (i + 1 < args.length) {
|
|
40
41
|
options.outDir = args[++i];
|
|
41
42
|
}
|
|
@@ -50,7 +51,7 @@ function loadConfig(configPath) {
|
|
|
50
51
|
if (configPath) {
|
|
51
52
|
finalPath = path.resolve(process.cwd(), configPath);
|
|
52
53
|
} else {
|
|
53
|
-
finalPath = path.join(process.cwd(),
|
|
54
|
+
finalPath = path.join(process.cwd(), "swatchkit.config.js");
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
if (fs.existsSync(finalPath)) {
|
|
@@ -58,7 +59,7 @@ function loadConfig(configPath) {
|
|
|
58
59
|
console.log(`[SwatchKit] Loading config from ${finalPath}`);
|
|
59
60
|
return require(finalPath);
|
|
60
61
|
} catch (e) {
|
|
61
|
-
console.error(
|
|
62
|
+
console.error("[SwatchKit] Error loading config file:", e.message);
|
|
62
63
|
return {};
|
|
63
64
|
}
|
|
64
65
|
}
|
|
@@ -76,47 +77,51 @@ function resolveSettings(cliOptions, fileConfig) {
|
|
|
76
77
|
if (fileConfig.input) return path.resolve(cwd, fileConfig.input);
|
|
77
78
|
|
|
78
79
|
// 2. Search candidates
|
|
79
|
-
const candidates = [
|
|
80
|
+
const candidates = ["swatches", "src/swatches", "src/patterns"];
|
|
80
81
|
for (const cand of candidates) {
|
|
81
82
|
const absPath = path.join(cwd, cand);
|
|
82
83
|
if (fs.existsSync(absPath)) return absPath;
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
// 3. Fallback default (swatches)
|
|
86
|
-
return path.join(cwd,
|
|
87
|
+
return path.join(cwd, "swatches");
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
const patternsDir = findPatternsDir();
|
|
90
91
|
|
|
91
92
|
// Output Dir
|
|
92
93
|
// Default: public/swatchkit
|
|
93
|
-
const outDir = cliOptions.outDir
|
|
94
|
+
const outDir = cliOptions.outDir
|
|
94
95
|
? path.resolve(cwd, cliOptions.outDir)
|
|
95
|
-
:
|
|
96
|
+
: fileConfig.outDir
|
|
97
|
+
? path.resolve(cwd, fileConfig.outDir)
|
|
98
|
+
: path.join(cwd, "public/swatchkit");
|
|
96
99
|
|
|
97
100
|
// CSS Dir (Legacy support: src/css)
|
|
98
|
-
const cssDir = path.join(cwd,
|
|
101
|
+
const cssDir = path.join(cwd, "src/css");
|
|
99
102
|
|
|
100
103
|
return {
|
|
101
104
|
patternsDir,
|
|
102
105
|
outDir,
|
|
103
106
|
cssDir,
|
|
104
107
|
// Internal layout template (relative to this script)
|
|
105
|
-
internalLayout: path.join(__dirname,
|
|
108
|
+
internalLayout: path.join(__dirname, "src/layout.html"),
|
|
106
109
|
// Project specific layout override
|
|
107
|
-
projectLayout: path.join(patternsDir,
|
|
108
|
-
|
|
110
|
+
projectLayout: path.join(patternsDir, "_layout.html"),
|
|
111
|
+
|
|
109
112
|
// Derived paths
|
|
110
|
-
distCssDir: path.join(outDir,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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"),
|
|
114
119
|
};
|
|
115
120
|
}
|
|
116
121
|
|
|
117
122
|
// --- 4. Init Command Logic ---
|
|
118
123
|
function runInit(settings, options) {
|
|
119
|
-
console.log(
|
|
124
|
+
console.log("[SwatchKit] Initializing...");
|
|
120
125
|
|
|
121
126
|
// Ensure patterns directory exists
|
|
122
127
|
if (!fs.existsSync(settings.patternsDir)) {
|
|
@@ -124,20 +129,120 @@ function runInit(settings, options) {
|
|
|
124
129
|
fs.mkdirSync(settings.patternsDir, { recursive: true });
|
|
125
130
|
}
|
|
126
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
|
+
|
|
127
230
|
const targetLayout = settings.projectLayout;
|
|
128
|
-
|
|
231
|
+
|
|
129
232
|
if (fs.existsSync(targetLayout) && !options.force) {
|
|
130
233
|
console.warn(`Warning: Layout file already exists at ${targetLayout}`);
|
|
131
|
-
console.warn(
|
|
234
|
+
console.warn("Use --force to overwrite.");
|
|
132
235
|
return;
|
|
133
236
|
}
|
|
134
237
|
|
|
135
238
|
if (fs.existsSync(settings.internalLayout)) {
|
|
136
|
-
const layoutContent = fs.readFileSync(settings.internalLayout,
|
|
239
|
+
const layoutContent = fs.readFileSync(settings.internalLayout, "utf-8");
|
|
137
240
|
fs.writeFileSync(targetLayout, layoutContent);
|
|
138
241
|
console.log(`Created layout file at ${targetLayout}`);
|
|
139
242
|
} else {
|
|
140
|
-
console.error(
|
|
243
|
+
console.error(
|
|
244
|
+
`Error: Internal layout file not found at ${settings.internalLayout}`,
|
|
245
|
+
);
|
|
141
246
|
process.exit(1);
|
|
142
247
|
}
|
|
143
248
|
}
|
|
@@ -150,123 +255,149 @@ function build(settings) {
|
|
|
150
255
|
|
|
151
256
|
// 1. Check if patterns directory exists
|
|
152
257
|
if (!fs.existsSync(settings.patternsDir)) {
|
|
153
|
-
console.error(
|
|
258
|
+
console.error(
|
|
259
|
+
`Error: Patterns directory not found at ${settings.patternsDir}`,
|
|
260
|
+
);
|
|
154
261
|
console.error('Run "swatchkit init" to get started.');
|
|
155
262
|
process.exit(1);
|
|
156
263
|
}
|
|
157
264
|
|
|
158
265
|
// 2. Ensure dist directories exist
|
|
159
|
-
[settings.outDir, settings.distCssDir, settings.distJsDir].forEach(dir => {
|
|
266
|
+
[settings.outDir, settings.distCssDir, settings.distJsDir].forEach((dir) => {
|
|
160
267
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
161
268
|
});
|
|
162
269
|
|
|
270
|
+
// 2.5 Process Tokens
|
|
271
|
+
processTokens(process.cwd(), settings.cssDir);
|
|
272
|
+
|
|
163
273
|
// 3. Copy CSS files
|
|
164
274
|
if (fs.existsSync(settings.cssDir)) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
+
});
|
|
170
285
|
}
|
|
171
286
|
|
|
172
287
|
// 4. Read patterns & JS
|
|
173
|
-
console.log(
|
|
288
|
+
console.log("Processing patterns...");
|
|
174
289
|
const patterns = [];
|
|
175
290
|
const scripts = [];
|
|
176
291
|
|
|
177
292
|
const items = fs.readdirSync(settings.patternsDir);
|
|
178
293
|
|
|
179
|
-
items.forEach(item => {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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(`
|
|
203
323
|
/* --- Pattern: ${name} / File: ${jsFile} --- */
|
|
204
324
|
(function() {
|
|
205
325
|
${scriptContent}
|
|
206
326
|
})();
|
|
207
327
|
`);
|
|
208
|
-
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
// Handle Single File Pattern
|
|
212
|
-
else if (item.endsWith('.html')) {
|
|
213
|
-
name = path.basename(item, '.html');
|
|
214
|
-
id = name;
|
|
215
|
-
content = fs.readFileSync(itemPath, 'utf-8');
|
|
328
|
+
});
|
|
216
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
|
+
}
|
|
217
337
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
338
|
+
if (name && content) {
|
|
339
|
+
patterns.push({ name, id, content });
|
|
340
|
+
}
|
|
341
|
+
});
|
|
222
342
|
|
|
223
343
|
// 5. Generate HTML fragments
|
|
224
|
-
const sidebarLinks = patterns
|
|
225
|
-
`<a href="#${p.id}">${p.name}</a>`
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const patternBlocks = patterns
|
|
229
|
-
|
|
230
|
-
.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
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 `
|
|
237
358
|
<section id="${p.id}">
|
|
238
359
|
<h2>${p.name}</h2>
|
|
239
360
|
<div class="preview">${p.content}</div>
|
|
240
361
|
<pre><code>${escapedContent}</code></pre>
|
|
241
362
|
</section>
|
|
242
363
|
`;
|
|
243
|
-
|
|
364
|
+
})
|
|
365
|
+
.join("\n");
|
|
244
366
|
|
|
245
367
|
// 6. Write JS Bundle
|
|
246
368
|
if (scripts.length > 0) {
|
|
247
|
-
fs.writeFileSync(settings.outputJsFile, scripts.join(
|
|
248
|
-
console.log(
|
|
369
|
+
fs.writeFileSync(settings.outputJsFile, scripts.join("\n"));
|
|
370
|
+
console.log(
|
|
371
|
+
`Bundled ${scripts.length} scripts to ${settings.outputJsFile}`,
|
|
372
|
+
);
|
|
249
373
|
} else {
|
|
250
|
-
fs.writeFileSync(settings.outputJsFile,
|
|
374
|
+
fs.writeFileSync(settings.outputJsFile, "// No pattern scripts found");
|
|
251
375
|
}
|
|
252
376
|
|
|
253
377
|
// 7. Load Layout
|
|
254
378
|
let layoutContent;
|
|
255
379
|
if (fs.existsSync(settings.projectLayout)) {
|
|
256
380
|
console.log(`Using custom layout: ${settings.projectLayout}`);
|
|
257
|
-
layoutContent = fs.readFileSync(settings.projectLayout,
|
|
381
|
+
layoutContent = fs.readFileSync(settings.projectLayout, "utf-8");
|
|
258
382
|
} else {
|
|
259
383
|
// console.log(`Using internal layout`);
|
|
260
|
-
layoutContent = fs.readFileSync(settings.internalLayout,
|
|
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">';
|
|
261
391
|
}
|
|
262
|
-
|
|
392
|
+
|
|
263
393
|
const finalHtml = layoutContent
|
|
264
|
-
.replace(
|
|
265
|
-
.replace(
|
|
394
|
+
.replace("<!-- SIDEBAR_LINKS -->", sidebarLinks)
|
|
395
|
+
.replace("<!-- PATTERNS -->", patternBlocks)
|
|
396
|
+
.replace("<!-- HEAD_EXTRAS -->", headExtras);
|
|
266
397
|
|
|
267
398
|
// 8. Write output
|
|
268
399
|
fs.writeFileSync(settings.outputFile, finalHtml);
|
|
269
|
-
|
|
400
|
+
|
|
270
401
|
console.log(`Build complete! Generated ${settings.outputFile}`);
|
|
271
402
|
}
|
|
272
403
|
|
|
@@ -276,15 +407,16 @@ try {
|
|
|
276
407
|
const fileConfig = loadConfig(cliOptions.config);
|
|
277
408
|
const settings = resolveSettings(cliOptions, fileConfig);
|
|
278
409
|
|
|
279
|
-
if (cliOptions.command ===
|
|
410
|
+
if (cliOptions.command === "init") {
|
|
280
411
|
runInit(settings, cliOptions);
|
|
281
412
|
} else {
|
|
282
413
|
build(settings);
|
|
283
414
|
if (cliOptions.watch) {
|
|
284
|
-
console.log(
|
|
415
|
+
console.log("[SwatchKit] Watch mode is not yet fully implemented.");
|
|
285
416
|
}
|
|
286
417
|
}
|
|
287
418
|
} catch (error) {
|
|
288
|
-
console.error(
|
|
419
|
+
console.error("[SwatchKit] Error:", error.message);
|
|
289
420
|
process.exit(1);
|
|
290
421
|
}
|
|
422
|
+
|
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>
|