@stratixlabs/core 1.7.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/LICENSE +21 -0
- package/README.md +249 -0
- package/bin/substrata.js +521 -0
- package/index.js +3 -0
- package/package.json +49 -0
- package/scripts/detect-breaking-changes.js +155 -0
- package/scripts/figma-sync.js +738 -0
- package/scripts/generate-dts-from-tokens.js +77 -0
- package/scripts/generate-tokens.js +138 -0
- package/scripts/lint-code.js +186 -0
- package/scripts/lint-hardcoded.js +49 -0
- package/scripts/tokens-to-css.js +145 -0
- package/scripts/validate-tokens.js +113 -0
- package/src/base.css +41 -0
- package/src/components/components.css +279 -0
- package/src/consumption/plain.css +22 -0
- package/src/consumption/sass-example.scss +30 -0
- package/src/consumption/styled-components.js +28 -0
- package/src/consumption/tailwind.config.js +44 -0
- package/src/consumption/vanilla-extract.css.ts +28 -0
- package/src/substrata.css +11 -0
- package/src/tokens/breakpoints.css +7 -0
- package/src/tokens/colors.css +21 -0
- package/src/tokens/elevation.css +7 -0
- package/src/tokens/motion.css +7 -0
- package/src/tokens/opacity.css +7 -0
- package/src/tokens/radius-and-borders.css +9 -0
- package/src/tokens/semantic-aliases.css +12 -0
- package/src/tokens/spacing.css +10 -0
- package/src/tokens/typography.css +18 -0
- package/substrata.config.js +4 -0
- package/substrata.d.ts +123 -0
- package/tokens.json +348 -0
package/bin/substrata.js
ADDED
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
const command = args[0];
|
|
8
|
+
|
|
9
|
+
if (!command || (command !== 'init' && command !== 'generate' && command !== 'figma')) {
|
|
10
|
+
console.log('Usage: @stratixlabs/core <command>');
|
|
11
|
+
console.log('Commands:');
|
|
12
|
+
console.log(' init Initialize a complete Substrata project with tokens, scripts, and examples');
|
|
13
|
+
console.log(' generate Generate tokens.json from source');
|
|
14
|
+
console.log(' figma Figma-related automation (sync, apply-preview)');
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (command === 'init') {
|
|
19
|
+
console.log('š Initializing Substrata...\n');
|
|
20
|
+
|
|
21
|
+
const cwd = process.cwd();
|
|
22
|
+
const configPath = path.join(cwd, 'substrata.config.js');
|
|
23
|
+
const tokensDir = path.join(cwd, 'src/tokens');
|
|
24
|
+
const consumptionDir = path.join(cwd, 'src/consumption');
|
|
25
|
+
const scriptsDir = path.join(cwd, 'scripts');
|
|
26
|
+
const srcDir = path.join(cwd, 'src');
|
|
27
|
+
|
|
28
|
+
// 1. Create config file
|
|
29
|
+
if (fs.existsSync(configPath)) {
|
|
30
|
+
console.log('ā ļø substrata.config.js already exists.');
|
|
31
|
+
} else {
|
|
32
|
+
const defaultConfig = `module.exports = {
|
|
33
|
+
tokens: './src/tokens',
|
|
34
|
+
output: './tokens.json'
|
|
35
|
+
};
|
|
36
|
+
`;
|
|
37
|
+
fs.writeFileSync(configPath, defaultConfig);
|
|
38
|
+
console.log('ā
Created substrata.config.js');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 2. Create directory structure
|
|
42
|
+
if (!fs.existsSync(tokensDir)) {
|
|
43
|
+
fs.mkdirSync(tokensDir, { recursive: true });
|
|
44
|
+
console.log('ā
Created src/tokens/ directory');
|
|
45
|
+
}
|
|
46
|
+
if (!fs.existsSync(consumptionDir)) {
|
|
47
|
+
fs.mkdirSync(consumptionDir, { recursive: true });
|
|
48
|
+
console.log('ā
Created src/consumption/ directory');
|
|
49
|
+
}
|
|
50
|
+
if (!fs.existsSync(scriptsDir)) {
|
|
51
|
+
fs.mkdirSync(scriptsDir, { recursive: true });
|
|
52
|
+
console.log('ā
Created scripts/ directory');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 3. Create all token files
|
|
56
|
+
const tokens = {
|
|
57
|
+
'colors.css': `:root {
|
|
58
|
+
|
|
59
|
+
/* ==============================
|
|
60
|
+
Colors
|
|
61
|
+
============================== */
|
|
62
|
+
|
|
63
|
+
/* Neutrals */
|
|
64
|
+
--neutral-0: #ffffff;
|
|
65
|
+
--neutral-50: #f8fafc;
|
|
66
|
+
--neutral-100: #f1f5f9;
|
|
67
|
+
--neutral-200: #e2e8f0;
|
|
68
|
+
--neutral-300: #cbd5e1;
|
|
69
|
+
--neutral-400: #94a3b8;
|
|
70
|
+
--neutral-500: #64748b;
|
|
71
|
+
--neutral-600: #475569;
|
|
72
|
+
--neutral-700: #334155;
|
|
73
|
+
--neutral-800: #1e293b;
|
|
74
|
+
--neutral-900: #0f172a;
|
|
75
|
+
|
|
76
|
+
/* Brand */
|
|
77
|
+
--brand-300: #93c5fd;
|
|
78
|
+
--brand-500: #3b82f6;
|
|
79
|
+
--brand-700: #1d4ed8;
|
|
80
|
+
|
|
81
|
+
/* Feedback */
|
|
82
|
+
--color-success: #22c55e;
|
|
83
|
+
--color-warning: #eab308;
|
|
84
|
+
--color-danger: #ef4444;
|
|
85
|
+
}
|
|
86
|
+
`,
|
|
87
|
+
'spacing.css': `:root {
|
|
88
|
+
|
|
89
|
+
/* ==============================
|
|
90
|
+
Spacing
|
|
91
|
+
============================== */
|
|
92
|
+
|
|
93
|
+
--space-1: 0.25rem;
|
|
94
|
+
--space-2: 0.5rem;
|
|
95
|
+
--space-3: 0.75rem;
|
|
96
|
+
--space-4: 1rem;
|
|
97
|
+
--space-5: 1.5rem;
|
|
98
|
+
--space-6: 2rem;
|
|
99
|
+
|
|
100
|
+
}
|
|
101
|
+
`,
|
|
102
|
+
'typography.css': `:root {
|
|
103
|
+
/* ==============================
|
|
104
|
+
Typography
|
|
105
|
+
============================== */
|
|
106
|
+
|
|
107
|
+
--font-family-base: system-ui, -apple-system, BlinkMacSystemFont,
|
|
108
|
+
"Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
109
|
+
|
|
110
|
+
--font-size-xs: 0.75rem;
|
|
111
|
+
--font-size-sm: 0.875rem;
|
|
112
|
+
--font-size-md: 1rem;
|
|
113
|
+
--font-size-lg: 1.25rem;
|
|
114
|
+
--font-size-xl: 1.5rem;
|
|
115
|
+
--font-size-2xl: 2rem;
|
|
116
|
+
|
|
117
|
+
--font-weight-regular: 400;
|
|
118
|
+
--font-weight-medium: 500;
|
|
119
|
+
--font-weight-semibold: 600;
|
|
120
|
+
--font-weight-bold: 700;
|
|
121
|
+
|
|
122
|
+
--line-height-tight: 1.25;
|
|
123
|
+
--line-height-normal: 1.5;
|
|
124
|
+
--line-height-relaxed: 1.75;
|
|
125
|
+
}
|
|
126
|
+
`,
|
|
127
|
+
'radius-and-borders.css': `:root {
|
|
128
|
+
|
|
129
|
+
/* ==============================
|
|
130
|
+
Radius & Borders
|
|
131
|
+
============================== */
|
|
132
|
+
|
|
133
|
+
--radius-sm: 0.375rem;
|
|
134
|
+
--radius-md: 0.5rem;
|
|
135
|
+
--radius-lg: 0.75rem;
|
|
136
|
+
|
|
137
|
+
--border-width: 1px;
|
|
138
|
+
--border-color: var(--neutral-200);
|
|
139
|
+
|
|
140
|
+
}
|
|
141
|
+
`,
|
|
142
|
+
'elevation.css': `:root {
|
|
143
|
+
|
|
144
|
+
/* ==============================
|
|
145
|
+
Shadows
|
|
146
|
+
============================== */
|
|
147
|
+
|
|
148
|
+
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
|
|
149
|
+
--shadow-md: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);
|
|
150
|
+
--shadow-lg: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.2);
|
|
151
|
+
}
|
|
152
|
+
`,
|
|
153
|
+
'motion.css': `:root {
|
|
154
|
+
|
|
155
|
+
/* ==============================
|
|
156
|
+
Motion
|
|
157
|
+
============================== */
|
|
158
|
+
|
|
159
|
+
--motion-fast: 200ms;
|
|
160
|
+
--motion-normal: 300ms;
|
|
161
|
+
--motion-slow: 400ms;
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
`,
|
|
165
|
+
'opacity.css': `:root {
|
|
166
|
+
|
|
167
|
+
/* ==============================
|
|
168
|
+
Opacity
|
|
169
|
+
============================== */
|
|
170
|
+
|
|
171
|
+
--opacity-0: 0;
|
|
172
|
+
--opacity-20: 0.2;
|
|
173
|
+
--opacity-40: 0.4;
|
|
174
|
+
--opacity-60: 0.6;
|
|
175
|
+
--opacity-80: 0.8;
|
|
176
|
+
--opacity-100: 1;
|
|
177
|
+
|
|
178
|
+
}
|
|
179
|
+
`,
|
|
180
|
+
'breakpoints.css': `:root {
|
|
181
|
+
|
|
182
|
+
/* ==============================
|
|
183
|
+
Breakpoints
|
|
184
|
+
============================== */
|
|
185
|
+
|
|
186
|
+
--breakpoint-sm: 640px;
|
|
187
|
+
--breakpoint-md: 768px;
|
|
188
|
+
--breakpoint-lg: 1024px;
|
|
189
|
+
}
|
|
190
|
+
`,
|
|
191
|
+
'semantic-aliases.css': `:root {
|
|
192
|
+
|
|
193
|
+
/* ==============================
|
|
194
|
+
Semantic Aliases
|
|
195
|
+
============================== */
|
|
196
|
+
|
|
197
|
+
--color-bg: var(--neutral-50);
|
|
198
|
+
--color-surface: var(--neutral-50);
|
|
199
|
+
--color-text-primary: var(--neutral-900);
|
|
200
|
+
--color-text-secondary: var(--neutral-700);
|
|
201
|
+
--color-border: var(--neutral-200);
|
|
202
|
+
|
|
203
|
+
--color-brand-primary: var(--brand-500);
|
|
204
|
+
--color-brand-hover: var(--brand-700);
|
|
205
|
+
--color-text-inverse: var(--neutral-0);
|
|
206
|
+
|
|
207
|
+
}
|
|
208
|
+
`
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
console.log('');
|
|
212
|
+
for (const [file, content] of Object.entries(tokens)) {
|
|
213
|
+
const filePath = path.join(tokensDir, file);
|
|
214
|
+
if (!fs.existsSync(filePath)) {
|
|
215
|
+
fs.writeFileSync(filePath, content);
|
|
216
|
+
console.log(`ā
Created src/tokens/${file}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// 4. Create substrata.css (imports all tokens)
|
|
221
|
+
const substrataCssPath = path.join(srcDir, 'substrata.css');
|
|
222
|
+
const substrataCss = `@import "tokens/typography.css";
|
|
223
|
+
@import "tokens/spacing.css";
|
|
224
|
+
@import "tokens/colors.css";
|
|
225
|
+
@import "tokens/radius-and-borders.css";
|
|
226
|
+
@import "tokens/elevation.css";
|
|
227
|
+
@import "tokens/motion.css";
|
|
228
|
+
@import "tokens/opacity.css";
|
|
229
|
+
@import "tokens/breakpoints.css";
|
|
230
|
+
@import "tokens/semantic-aliases.css";
|
|
231
|
+
|
|
232
|
+
@import "./base.css";
|
|
233
|
+
`;
|
|
234
|
+
if (!fs.existsSync(substrataCssPath)) {
|
|
235
|
+
if (!fs.existsSync(srcDir)) fs.mkdirSync(srcDir, { recursive: true });
|
|
236
|
+
fs.writeFileSync(substrataCssPath, substrataCss);
|
|
237
|
+
console.log('\nā
Created src/substrata.css');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// 5. Create base.css
|
|
241
|
+
const baseCssPath = path.join(srcDir, 'base.css');
|
|
242
|
+
const baseCss = `body {
|
|
243
|
+
font-family: var(--font-family-base);
|
|
244
|
+
font-size: var(--font-size-md);
|
|
245
|
+
font-weight: var(--font-weight-regular);
|
|
246
|
+
line-height: var(--line-height-normal);
|
|
247
|
+
color: var(--neutral-900);
|
|
248
|
+
background-color: var(--neutral-0);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/* ==============================
|
|
252
|
+
Typography
|
|
253
|
+
============================== */
|
|
254
|
+
|
|
255
|
+
h1 {
|
|
256
|
+
font-size: var(--font-size-2xl);
|
|
257
|
+
font-weight: var(--font-weight-bold);
|
|
258
|
+
line-height: var(--line-height-tight);
|
|
259
|
+
margin-bottom: var(--space-3);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
h2 {
|
|
263
|
+
font-size: var(--font-size-xl);
|
|
264
|
+
font-weight: var(--font-weight-semibold);
|
|
265
|
+
line-height: var(--line-height-normal);
|
|
266
|
+
margin-bottom: var(--space-3);
|
|
267
|
+
margin-top: 40px;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
h3 {
|
|
271
|
+
font-size: var(--font-size-lg);
|
|
272
|
+
font-weight: var(--font-weight-semibold);
|
|
273
|
+
margin-bottom: var(--space-3);
|
|
274
|
+
margin-top: 40px;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
h4 {
|
|
278
|
+
font-size: var(--font-size-md);
|
|
279
|
+
font-weight: var(--font-weight-medium);
|
|
280
|
+
margin-bottom: var(--space-3);
|
|
281
|
+
}
|
|
282
|
+
`;
|
|
283
|
+
if (!fs.existsSync(baseCssPath)) {
|
|
284
|
+
fs.writeFileSync(baseCssPath, baseCss);
|
|
285
|
+
console.log('ā
Created src/base.css');
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// 6. Create consumption examples
|
|
289
|
+
const consumptionExamples = {
|
|
290
|
+
'plain.css': `/*
|
|
291
|
+
Plain CSS Consumption Example
|
|
292
|
+
Import Substrata tokens and use them directly in your styles.
|
|
293
|
+
*/
|
|
294
|
+
|
|
295
|
+
@import "@stratixlabs/core/substrata.css";
|
|
296
|
+
|
|
297
|
+
.card {
|
|
298
|
+
background: var(--color-surface);
|
|
299
|
+
border: var(--border-width) solid var(--color-border);
|
|
300
|
+
border-radius: var(--radius-md);
|
|
301
|
+
padding: var(--space-4);
|
|
302
|
+
box-shadow: var(--shadow-sm);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.button {
|
|
306
|
+
padding: var(--space-2) var(--space-4);
|
|
307
|
+
background: var(--color-brand-primary);
|
|
308
|
+
color: var(--color-text-inverse);
|
|
309
|
+
border-radius: var(--radius-sm);
|
|
310
|
+
font-weight: var(--font-weight-medium);
|
|
311
|
+
transition: background var(--motion-normal);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.button:hover {
|
|
315
|
+
background: var(--color-brand-hover);
|
|
316
|
+
}
|
|
317
|
+
`,
|
|
318
|
+
'styled-components.js': `/*
|
|
319
|
+
CSS-in-JS Consumption Example (styled-components / emotion)
|
|
320
|
+
Use Substrata tokens in template literals via CSS variables.
|
|
321
|
+
*/
|
|
322
|
+
|
|
323
|
+
import styled from 'styled-components';
|
|
324
|
+
|
|
325
|
+
export const Card = styled.div\`
|
|
326
|
+
padding: var(--space-4);
|
|
327
|
+
background: var(--color-surface);
|
|
328
|
+
color: var(--color-text-primary);
|
|
329
|
+
border-radius: var(--radius-md);
|
|
330
|
+
box-shadow: var(--shadow-sm);
|
|
331
|
+
\`;
|
|
332
|
+
|
|
333
|
+
export const Button = styled.button\`
|
|
334
|
+
padding: var(--space-2) var(--space-4);
|
|
335
|
+
background: var(--color-brand-primary);
|
|
336
|
+
color: var(--color-text-inverse);
|
|
337
|
+
font-family: var(--font-family-base);
|
|
338
|
+
border-radius: var(--radius-sm);
|
|
339
|
+
border: none;
|
|
340
|
+
cursor: pointer;
|
|
341
|
+
transition: background var(--motion-normal);
|
|
342
|
+
|
|
343
|
+
&:hover {
|
|
344
|
+
background: var(--color-brand-hover);
|
|
345
|
+
}
|
|
346
|
+
\`;
|
|
347
|
+
`,
|
|
348
|
+
'tailwind.config.js': `/*
|
|
349
|
+
Tailwind CSS Consumption Example
|
|
350
|
+
Map Substrata tokens to Tailwind's theme configuration.
|
|
351
|
+
*/
|
|
352
|
+
|
|
353
|
+
/** @type {import('tailwindcss').Config} */
|
|
354
|
+
module.exports = {
|
|
355
|
+
content: ["./src/**/*.{html,js}"],
|
|
356
|
+
theme: {
|
|
357
|
+
extend: {
|
|
358
|
+
colors: {
|
|
359
|
+
brand: {
|
|
360
|
+
300: "var(--brand-300)",
|
|
361
|
+
500: "var(--brand-500)",
|
|
362
|
+
700: "var(--brand-700)",
|
|
363
|
+
},
|
|
364
|
+
neutral: {
|
|
365
|
+
0: "var(--neutral-0)",
|
|
366
|
+
50: "var(--neutral-50)",
|
|
367
|
+
100: "var(--neutral-100)",
|
|
368
|
+
200: "var(--neutral-200)",
|
|
369
|
+
300: "var(--neutral-300)",
|
|
370
|
+
400: "var(--neutral-400)",
|
|
371
|
+
500: "var(--neutral-500)",
|
|
372
|
+
600: "var(--neutral-600)",
|
|
373
|
+
700: "var(--neutral-700)",
|
|
374
|
+
800: "var(--neutral-800)",
|
|
375
|
+
900: "var(--neutral-900)",
|
|
376
|
+
},
|
|
377
|
+
surface: "var(--color-surface)",
|
|
378
|
+
text: "var(--color-text-primary)",
|
|
379
|
+
},
|
|
380
|
+
spacing: {
|
|
381
|
+
1: "var(--space-1)",
|
|
382
|
+
2: "var(--space-2)",
|
|
383
|
+
3: "var(--space-3)",
|
|
384
|
+
4: "var(--space-4)",
|
|
385
|
+
5: "var(--space-5)",
|
|
386
|
+
6: "var(--space-6)",
|
|
387
|
+
},
|
|
388
|
+
borderRadius: {
|
|
389
|
+
sm: "var(--radius-sm)",
|
|
390
|
+
md: "var(--radius-md)",
|
|
391
|
+
lg: "var(--radius-lg)",
|
|
392
|
+
},
|
|
393
|
+
fontFamily: {
|
|
394
|
+
body: "var(--font-family-base)",
|
|
395
|
+
heading: "var(--font-family-heading)",
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
plugins: [],
|
|
400
|
+
};
|
|
401
|
+
`
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
console.log('');
|
|
405
|
+
for (const [file, content] of Object.entries(consumptionExamples)) {
|
|
406
|
+
const filePath = path.join(consumptionDir, file);
|
|
407
|
+
if (!fs.existsSync(filePath)) {
|
|
408
|
+
fs.writeFileSync(filePath, content);
|
|
409
|
+
console.log(`ā
Created src/consumption/${file}`);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// 7. Create validation scripts
|
|
414
|
+
const scripts = {
|
|
415
|
+
'generate-tokens.js': fs.readFileSync(path.join(__dirname, '../scripts/generate-tokens.js'), 'utf8'),
|
|
416
|
+
'validate-tokens.js': fs.readFileSync(path.join(__dirname, '../scripts/validate-tokens.js'), 'utf8'),
|
|
417
|
+
'lint-hardcoded.js': fs.readFileSync(path.join(__dirname, '../scripts/lint-hardcoded.js'), 'utf8'),
|
|
418
|
+
'figma-sync.js': fs.readFileSync(path.join(__dirname, '../scripts/figma-sync.js'), 'utf8')
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
console.log('');
|
|
422
|
+
for (const [file, content] of Object.entries(scripts)) {
|
|
423
|
+
const filePath = path.join(scriptsDir, file);
|
|
424
|
+
if (!fs.existsSync(filePath)) {
|
|
425
|
+
fs.writeFileSync(filePath, content);
|
|
426
|
+
console.log(`ā
Created scripts/${file}`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// 8. Add scripts to package.json
|
|
431
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
432
|
+
if (fs.existsSync(pkgPath)) {
|
|
433
|
+
try {
|
|
434
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
435
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
436
|
+
|
|
437
|
+
let updated = false;
|
|
438
|
+
if (!pkg.scripts['build:tokens']) {
|
|
439
|
+
pkg.scripts['build:tokens'] = 'node scripts/generate-tokens.js';
|
|
440
|
+
updated = true;
|
|
441
|
+
}
|
|
442
|
+
if (!pkg.scripts['test:tokens']) {
|
|
443
|
+
pkg.scripts['test:tokens'] = 'node scripts/validate-tokens.js';
|
|
444
|
+
updated = true;
|
|
445
|
+
}
|
|
446
|
+
if (!pkg.scripts['lint:tokens']) {
|
|
447
|
+
pkg.scripts['lint:tokens'] = 'node scripts/lint-hardcoded.js';
|
|
448
|
+
updated = true;
|
|
449
|
+
}
|
|
450
|
+
if (!pkg.scripts['sync:figma']) {
|
|
451
|
+
pkg.scripts['sync:figma'] = 'node scripts/figma-sync.js';
|
|
452
|
+
updated = true;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (updated) {
|
|
456
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
457
|
+
console.log('\nā
Added npm scripts to package.json');
|
|
458
|
+
}
|
|
459
|
+
} catch (e) {
|
|
460
|
+
console.log('\nā ļø Could not update package.json (invalid JSON or permissions)');
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
console.log('\n⨠Substrata is ready!\n');
|
|
465
|
+
console.log('š Generated structure:');
|
|
466
|
+
console.log(' āāā substrata.config.js');
|
|
467
|
+
console.log(' āāā src/');
|
|
468
|
+
console.log(' ā āāā tokens/ (9 token files)');
|
|
469
|
+
console.log(' ā āāā consumption/ (3 framework examples)');
|
|
470
|
+
console.log(' ā āāā substrata.css (main entry point)');
|
|
471
|
+
console.log(' ā āāā base.css');
|
|
472
|
+
console.log(' āāā scripts/ (3 automation scripts)\n');
|
|
473
|
+
console.log('ā¶ļø Next steps:');
|
|
474
|
+
console.log(' 1. Import src/substrata.css in your app');
|
|
475
|
+
console.log(' 2. Run: npm run build:tokens');
|
|
476
|
+
console.log(' 3. Check src/consumption/ for framework integration examples\n');
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (command === 'generate') {
|
|
480
|
+
console.log('Generating tokens...');
|
|
481
|
+
try {
|
|
482
|
+
const scriptPath = path.join(__dirname, '../scripts/generate-tokens.js');
|
|
483
|
+
|
|
484
|
+
if (fs.existsSync(scriptPath)) {
|
|
485
|
+
require(scriptPath);
|
|
486
|
+
} else {
|
|
487
|
+
console.error('ā Could not find generation script at:', scriptPath);
|
|
488
|
+
process.exit(1);
|
|
489
|
+
}
|
|
490
|
+
} catch (error) {
|
|
491
|
+
console.error('ā Error during generation:', error);
|
|
492
|
+
process.exit(1);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (command === 'figma') {
|
|
497
|
+
const subcommand = args[1];
|
|
498
|
+
|
|
499
|
+
if (!subcommand || subcommand !== 'apply-preview') {
|
|
500
|
+
console.log('Usage: @stratixlabs/core figma <subcommand>');
|
|
501
|
+
console.log('Subcommands:');
|
|
502
|
+
console.log(' apply-preview Apply figma-push-preview.json to Figma via Variables REST API');
|
|
503
|
+
process.exit(1);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const scriptPath = path.join(__dirname, '../scripts/figma-sync.js');
|
|
507
|
+
|
|
508
|
+
if (!fs.existsSync(scriptPath)) {
|
|
509
|
+
console.error('ā Could not find Figma script at:', scriptPath);
|
|
510
|
+
process.exit(1);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
process.env.FIGMA_SYNC_DIRECTION = 'apply';
|
|
514
|
+
|
|
515
|
+
try {
|
|
516
|
+
require(scriptPath);
|
|
517
|
+
} catch (error) {
|
|
518
|
+
console.error('ā Error applying Figma push preview:', error);
|
|
519
|
+
process.exit(1);
|
|
520
|
+
}
|
|
521
|
+
}
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stratixlabs/core",
|
|
3
|
+
"version": "1.7.1",
|
|
4
|
+
"description": "...",
|
|
5
|
+
"bin": {
|
|
6
|
+
"substrata": "bin/substrata.js"
|
|
7
|
+
},
|
|
8
|
+
"main": "index.js",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "npm run test:tokens",
|
|
11
|
+
"build:tokens": "node scripts/generate-tokens.js",
|
|
12
|
+
"build:css-from-tokens": "node scripts/tokens-to-css.js",
|
|
13
|
+
"build:types": "node scripts/generate-dts-from-tokens.js",
|
|
14
|
+
"test:tokens": "node scripts/validate-tokens.js",
|
|
15
|
+
"lint:tokens": "node scripts/lint-hardcoded.js",
|
|
16
|
+
"lint:code": "node scripts/lint-code.js",
|
|
17
|
+
"detect:breaking": "node scripts/detect-breaking-changes.js",
|
|
18
|
+
"sync:figma": "node scripts/figma-sync.js"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"stratix",
|
|
22
|
+
"design-tokens",
|
|
23
|
+
"design-system",
|
|
24
|
+
"infra",
|
|
25
|
+
"platform"
|
|
26
|
+
],
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/mikaelcarrara/stratix"
|
|
30
|
+
},
|
|
31
|
+
"author": "Mikael Carrara",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"bin",
|
|
38
|
+
"scripts",
|
|
39
|
+
"src",
|
|
40
|
+
"index.js",
|
|
41
|
+
"tokens.json",
|
|
42
|
+
"substrata.d.ts",
|
|
43
|
+
"README.md",
|
|
44
|
+
"substrata.config.js"
|
|
45
|
+
],
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"ajv": "^8.12.0"
|
|
48
|
+
}
|
|
49
|
+
}
|