@ngcorex/cli 0.1.6 → 0.2.0
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 +83 -75
- package/dist/commands/init.js +68 -5
- package/dist/commands/run-build.js +137 -99
- package/dist/utils/logger.js +246 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -63,25 +63,41 @@ Create a `tokens.json` file at your project root:
|
|
|
63
63
|
```json
|
|
64
64
|
{
|
|
65
65
|
"spacing": {
|
|
66
|
-
"xs": "
|
|
67
|
-
"sm": "
|
|
66
|
+
"xs": "0.25rem",
|
|
67
|
+
"sm": "0.5rem",
|
|
68
|
+
"md": "1rem",
|
|
69
|
+
"lg": "1.5rem",
|
|
70
|
+
"xl": "2rem"
|
|
68
71
|
},
|
|
69
72
|
"colors": {
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
+
"neutral": {
|
|
74
|
+
"0": "#ffffff",
|
|
75
|
+
"100": "#f5f5f5",
|
|
76
|
+
"300": "#d4d4d4",
|
|
77
|
+
"500": "#737373",
|
|
78
|
+
"700": "#404040",
|
|
79
|
+
"900": "#171717"
|
|
80
|
+
},
|
|
81
|
+
"primary": {
|
|
82
|
+
"500": "#2563eb"
|
|
73
83
|
}
|
|
74
84
|
},
|
|
75
85
|
"radius": {
|
|
76
|
-
"sm": "
|
|
77
|
-
"md": "
|
|
78
|
-
"lg": "
|
|
86
|
+
"sm": "0.25rem",
|
|
87
|
+
"md": "0.5rem",
|
|
88
|
+
"lg": "0.75rem",
|
|
89
|
+
"xl": "1rem",
|
|
79
90
|
"full": "9999px"
|
|
80
91
|
},
|
|
81
92
|
"zIndex": {
|
|
93
|
+
"base": "0",
|
|
82
94
|
"dropdown": "1000",
|
|
83
|
-
"
|
|
84
|
-
"
|
|
95
|
+
"sticky": "1020",
|
|
96
|
+
"fixed": "1030",
|
|
97
|
+
"modal-backdrop": "1040",
|
|
98
|
+
"modal": "1050",
|
|
99
|
+
"popover": "1060",
|
|
100
|
+
"tooltip": "1070"
|
|
85
101
|
},
|
|
86
102
|
"typography": {
|
|
87
103
|
"fontSize": {
|
|
@@ -89,25 +105,35 @@ Create a `tokens.json` file at your project root:
|
|
|
89
105
|
"sm": "0.875rem",
|
|
90
106
|
"base": "1rem",
|
|
91
107
|
"lg": "1.125rem",
|
|
92
|
-
"xl": "1.25rem"
|
|
108
|
+
"xl": "1.25rem",
|
|
109
|
+
"2xl": "1.5rem",
|
|
110
|
+
"3xl": "1.875rem",
|
|
111
|
+
"4xl": "2.25rem"
|
|
93
112
|
},
|
|
94
113
|
"fontWeight": {
|
|
114
|
+
"light": "300",
|
|
95
115
|
"normal": "400",
|
|
96
116
|
"medium": "500",
|
|
97
117
|
"semibold": "600",
|
|
98
|
-
"bold": "700"
|
|
118
|
+
"bold": "700",
|
|
119
|
+
"extrabold": "800"
|
|
99
120
|
},
|
|
100
121
|
"lineHeight": {
|
|
122
|
+
"none": "1",
|
|
101
123
|
"tight": "1.25",
|
|
124
|
+
"snug": "1.375",
|
|
102
125
|
"normal": "1.5",
|
|
103
|
-
"relaxed": "1.
|
|
126
|
+
"relaxed": "1.625",
|
|
127
|
+
"loose": "2"
|
|
104
128
|
}
|
|
105
129
|
},
|
|
106
130
|
"shadows": {
|
|
107
|
-
"sm": "0 1px 2px 0
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"
|
|
131
|
+
"sm": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
|
|
132
|
+
"base": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
|
|
133
|
+
"md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
|
|
134
|
+
"lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
|
|
135
|
+
"xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
|
|
136
|
+
"2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)"
|
|
111
137
|
}
|
|
112
138
|
}
|
|
113
139
|
```
|
|
@@ -200,56 +226,6 @@ export default defineNgCorexConfig({
|
|
|
200
226
|
});
|
|
201
227
|
```
|
|
202
228
|
|
|
203
|
-
```ts
|
|
204
|
-
import { defineNgCorexConfig } from '@ngcorex/css';
|
|
205
|
-
|
|
206
|
-
export default defineNgCorexConfig({
|
|
207
|
-
constraints: {
|
|
208
|
-
spacing: {
|
|
209
|
-
unit: 'warning', // Warn about unitless numbers
|
|
210
|
-
format: 'error', // Error on invalid formats
|
|
211
|
-
type: 'error' // Error on wrong types
|
|
212
|
-
},
|
|
213
|
-
colors: {
|
|
214
|
-
format: 'error',
|
|
215
|
-
shadeKey: 'error',
|
|
216
|
-
type: 'error'
|
|
217
|
-
},
|
|
218
|
-
radius: {
|
|
219
|
-
unit: 'warning',
|
|
220
|
-
format: 'error',
|
|
221
|
-
type: 'error'
|
|
222
|
-
},
|
|
223
|
-
zIndex: {
|
|
224
|
-
format: 'error',
|
|
225
|
-
type: 'error'
|
|
226
|
-
},
|
|
227
|
-
typography: {
|
|
228
|
-
fontSize: {
|
|
229
|
-
format: 'error',
|
|
230
|
-
type: 'error'
|
|
231
|
-
},
|
|
232
|
-
fontWeight: {
|
|
233
|
-
format: 'error',
|
|
234
|
-
type: 'error'
|
|
235
|
-
},
|
|
236
|
-
lineHeight: {
|
|
237
|
-
format: 'error',
|
|
238
|
-
type: 'error'
|
|
239
|
-
}
|
|
240
|
-
},
|
|
241
|
-
shadows: {
|
|
242
|
-
format: 'error',
|
|
243
|
-
type: 'error'
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Available constraint levels: `'error'`, `'warning'`, `'off'`.
|
|
250
|
-
|
|
251
|
-
If `tokens.json` is present, it is used automatically.
|
|
252
|
-
|
|
253
229
|
## Configuration File
|
|
254
230
|
|
|
255
231
|
The CLI expects a file named:
|
|
@@ -374,17 +350,49 @@ Example output:
|
|
|
374
350
|
```css
|
|
375
351
|
@layer tokens {
|
|
376
352
|
:root {
|
|
377
|
-
|
|
378
|
-
--nx-spacing-
|
|
379
|
-
--nx-
|
|
380
|
-
--nx-
|
|
381
|
-
--nx-
|
|
382
|
-
--nx-
|
|
353
|
+
/* Spacing */
|
|
354
|
+
--nx-spacing-xs: 0.25rem;
|
|
355
|
+
--nx-spacing-sm: 0.5rem;
|
|
356
|
+
--nx-spacing-md: 1rem;
|
|
357
|
+
--nx-spacing-lg: 1.5rem;
|
|
358
|
+
--nx-spacing-xl: 2rem;
|
|
359
|
+
|
|
360
|
+
/* Colors */
|
|
361
|
+
--nx-color-neutral-0: #ffffff;
|
|
362
|
+
--nx-color-neutral-100: #f5f5f5;
|
|
363
|
+
--nx-color-neutral-500: #737373;
|
|
364
|
+
--nx-color-neutral-900: #171717;
|
|
365
|
+
--nx-color-primary-500: #2563eb;
|
|
366
|
+
|
|
367
|
+
/* Radius */
|
|
368
|
+
--nx-radius-sm: 0.25rem;
|
|
369
|
+
--nx-radius-md: 0.5rem;
|
|
370
|
+
--nx-radius-lg: 0.75rem;
|
|
371
|
+
--nx-radius-xl: 1rem;
|
|
372
|
+
--nx-radius-full: 9999px;
|
|
373
|
+
|
|
374
|
+
/* Z-Index */
|
|
375
|
+
--nx-zIndex-base: 0;
|
|
383
376
|
--nx-zIndex-dropdown: 1000;
|
|
377
|
+
--nx-zIndex-modal: 1050;
|
|
378
|
+
--nx-zIndex-tooltip: 1070;
|
|
379
|
+
|
|
380
|
+
/* Typography */
|
|
384
381
|
--nx-fontSize-xs: 0.75rem;
|
|
385
|
-
--nx-
|
|
382
|
+
--nx-fontSize-base: 1rem;
|
|
383
|
+
--nx-fontSize-xl: 1.25rem;
|
|
384
|
+
--nx-fontSize-3xl: 1.875rem;
|
|
385
|
+
--nx-fontWeight-normal: 400;
|
|
386
|
+
--nx-fontWeight-bold: 700;
|
|
386
387
|
--nx-lineHeight-normal: 1.5;
|
|
387
|
-
--nx-
|
|
388
|
+
--nx-lineHeight-loose: 2;
|
|
389
|
+
|
|
390
|
+
/* Shadows */
|
|
391
|
+
--nx-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
392
|
+
--nx-shadow-base: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
393
|
+
--nx-shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
394
|
+
--nx-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
395
|
+
--nx-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
|
388
396
|
}
|
|
389
397
|
}
|
|
390
398
|
```
|
package/dist/commands/init.js
CHANGED
|
@@ -9,14 +9,77 @@ export async function initCommand() {
|
|
|
9
9
|
if (!fs.existsSync(tokensPath)) {
|
|
10
10
|
fs.writeFileSync(tokensPath, JSON.stringify({
|
|
11
11
|
spacing: {
|
|
12
|
-
"xs": "
|
|
13
|
-
"sm": "
|
|
12
|
+
"xs": "0.25rem",
|
|
13
|
+
"sm": "0.5rem",
|
|
14
|
+
"md": "1rem",
|
|
15
|
+
"lg": "1.5rem",
|
|
16
|
+
"xl": "2rem"
|
|
14
17
|
},
|
|
15
18
|
colors: {
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
+
neutral: {
|
|
20
|
+
"0": "#ffffff",
|
|
21
|
+
"100": "#f5f5f5",
|
|
22
|
+
"300": "#d4d4d4",
|
|
23
|
+
"500": "#737373",
|
|
24
|
+
"700": "#404040",
|
|
25
|
+
"900": "#171717"
|
|
26
|
+
},
|
|
27
|
+
primary: {
|
|
28
|
+
"500": "#2563eb"
|
|
19
29
|
}
|
|
30
|
+
},
|
|
31
|
+
radius: {
|
|
32
|
+
"sm": "0.25rem",
|
|
33
|
+
"md": "0.5rem",
|
|
34
|
+
"lg": "0.75rem",
|
|
35
|
+
"xl": "1rem",
|
|
36
|
+
"full": "9999px"
|
|
37
|
+
},
|
|
38
|
+
zIndex: {
|
|
39
|
+
"base": "0",
|
|
40
|
+
"dropdown": "1000",
|
|
41
|
+
"sticky": "1020",
|
|
42
|
+
"fixed": "1030",
|
|
43
|
+
"modal-backdrop": "1040",
|
|
44
|
+
"modal": "1050",
|
|
45
|
+
"popover": "1060",
|
|
46
|
+
"tooltip": "1070"
|
|
47
|
+
},
|
|
48
|
+
typography: {
|
|
49
|
+
fontSize: {
|
|
50
|
+
"xs": "0.75rem",
|
|
51
|
+
"sm": "0.875rem",
|
|
52
|
+
"base": "1rem",
|
|
53
|
+
"lg": "1.125rem",
|
|
54
|
+
"xl": "1.25rem",
|
|
55
|
+
"2xl": "1.5rem",
|
|
56
|
+
"3xl": "1.875rem",
|
|
57
|
+
"4xl": "2.25rem"
|
|
58
|
+
},
|
|
59
|
+
fontWeight: {
|
|
60
|
+
"light": "300",
|
|
61
|
+
"normal": "400",
|
|
62
|
+
"medium": "500",
|
|
63
|
+
"semibold": "600",
|
|
64
|
+
"bold": "700",
|
|
65
|
+
"extrabold": "800"
|
|
66
|
+
},
|
|
67
|
+
lineHeight: {
|
|
68
|
+
"none": "1",
|
|
69
|
+
"tight": "1.25",
|
|
70
|
+
"snug": "1.375",
|
|
71
|
+
"normal": "1.5",
|
|
72
|
+
"relaxed": "1.625",
|
|
73
|
+
"loose": "2"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
shadows: {
|
|
77
|
+
"sm": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
|
|
78
|
+
"base": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
|
|
79
|
+
"md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
|
|
80
|
+
"lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
|
|
81
|
+
"xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
|
|
82
|
+
"2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)"
|
|
20
83
|
}
|
|
21
84
|
}, null, 2));
|
|
22
85
|
console.info('✔ Created tokens.json');
|
|
@@ -3,13 +3,15 @@ import path from 'node:path';
|
|
|
3
3
|
import { resolveConfigPath } from '../config/resolve-path.js';
|
|
4
4
|
import { loadConfig } from '../config/load-config.js';
|
|
5
5
|
import { writeCss } from '../output/write-css.js';
|
|
6
|
-
import { buildCssFromConfig } from '@ngcorex/css';
|
|
6
|
+
import { buildCssFromConfig, runValidations, printValidationResults, hasValidationResults, hasValidationErrors, hasValidationWarnings } from '@ngcorex/css';
|
|
7
7
|
import { resolve } from 'node:path';
|
|
8
|
+
import { BuildSummary, success, info, warning, error, section } from '../utils/logger.js';
|
|
8
9
|
let hasShownInlineTokenNotice = false;
|
|
9
10
|
export async function runBuild(options = {}) {
|
|
11
|
+
const buildSummary = new BuildSummary();
|
|
10
12
|
const configPath = resolveConfigPath();
|
|
11
13
|
const config = await loadConfig(configPath);
|
|
12
|
-
|
|
14
|
+
success('Loaded ngcorex.config.ts');
|
|
13
15
|
const outputFile = config.output?.file ?? 'src/styles/ngcorex.css';
|
|
14
16
|
const outputPath = resolve(process.cwd(), outputFile);
|
|
15
17
|
const tokensPath = path.resolve(process.cwd(), 'tokens.json');
|
|
@@ -20,24 +22,19 @@ export async function runBuild(options = {}) {
|
|
|
20
22
|
try {
|
|
21
23
|
fileTokens = JSON.parse(raw);
|
|
22
24
|
}
|
|
23
|
-
catch (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (error instanceof SyntaxError) {
|
|
28
|
-
console.error(error.message);
|
|
25
|
+
catch (err) {
|
|
26
|
+
error('Invalid tokens.json');
|
|
27
|
+
if (err instanceof SyntaxError) {
|
|
28
|
+
console.log(` Details: ${err.message}`);
|
|
29
29
|
}
|
|
30
|
-
console.error('');
|
|
31
30
|
process.exit(1);
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
// Validate top-level token shape
|
|
35
34
|
if (fileTokens !== null) {
|
|
36
35
|
if (typeof fileTokens !== 'object' || Array.isArray(fileTokens)) {
|
|
37
|
-
|
|
38
|
-
console.
|
|
39
|
-
console.error('The file must export a JSON object at the top level.');
|
|
40
|
-
console.error('');
|
|
36
|
+
error('Invalid tokens.json');
|
|
37
|
+
console.log(' Details: The file must export a JSON object at top level.');
|
|
41
38
|
process.exit(1);
|
|
42
39
|
}
|
|
43
40
|
}
|
|
@@ -48,10 +45,8 @@ export async function runBuild(options = {}) {
|
|
|
48
45
|
if (typeof tokens.spacing !== 'object' ||
|
|
49
46
|
tokens.spacing === null ||
|
|
50
47
|
Array.isArray(tokens.spacing)) {
|
|
51
|
-
|
|
52
|
-
console.
|
|
53
|
-
console.error('The "spacing" token must be an object.');
|
|
54
|
-
console.error('');
|
|
48
|
+
error('Invalid tokens.json');
|
|
49
|
+
console.log(' Details: The "spacing" token must be an object.');
|
|
55
50
|
process.exit(1);
|
|
56
51
|
}
|
|
57
52
|
}
|
|
@@ -59,10 +54,8 @@ export async function runBuild(options = {}) {
|
|
|
59
54
|
if (typeof tokens.colors !== 'object' ||
|
|
60
55
|
tokens.colors === null ||
|
|
61
56
|
Array.isArray(tokens.colors)) {
|
|
62
|
-
|
|
63
|
-
console.
|
|
64
|
-
console.error('The "colors" token must be an object.');
|
|
65
|
-
console.error('');
|
|
57
|
+
error('Invalid tokens.json');
|
|
58
|
+
console.log(' Details: The "colors" token must be an object.');
|
|
66
59
|
process.exit(1);
|
|
67
60
|
}
|
|
68
61
|
}
|
|
@@ -70,10 +63,8 @@ export async function runBuild(options = {}) {
|
|
|
70
63
|
if (typeof tokens.radius !== 'object' ||
|
|
71
64
|
tokens.radius === null ||
|
|
72
65
|
Array.isArray(tokens.radius)) {
|
|
73
|
-
|
|
74
|
-
console.
|
|
75
|
-
console.error('The "radius" token must be an object.');
|
|
76
|
-
console.error('');
|
|
66
|
+
error('Invalid tokens.json');
|
|
67
|
+
console.log(' Details: The "radius" token must be an object.');
|
|
77
68
|
process.exit(1);
|
|
78
69
|
}
|
|
79
70
|
}
|
|
@@ -81,10 +72,8 @@ export async function runBuild(options = {}) {
|
|
|
81
72
|
if (typeof tokens.zIndex !== 'object' ||
|
|
82
73
|
tokens.zIndex === null ||
|
|
83
74
|
Array.isArray(tokens.zIndex)) {
|
|
84
|
-
|
|
85
|
-
console.
|
|
86
|
-
console.error('The "zIndex" token must be an object.');
|
|
87
|
-
console.error('');
|
|
75
|
+
error('Invalid tokens.json');
|
|
76
|
+
console.log(' Details: The "zIndex" token must be an object.');
|
|
88
77
|
process.exit(1);
|
|
89
78
|
}
|
|
90
79
|
}
|
|
@@ -92,10 +81,8 @@ export async function runBuild(options = {}) {
|
|
|
92
81
|
if (typeof tokens.typography !== 'object' ||
|
|
93
82
|
tokens.typography === null ||
|
|
94
83
|
Array.isArray(tokens.typography)) {
|
|
95
|
-
|
|
96
|
-
console.
|
|
97
|
-
console.error('The "typography" token must be an object.');
|
|
98
|
-
console.error('');
|
|
84
|
+
error('Invalid tokens.json');
|
|
85
|
+
console.log(' Details: The "typography" token must be an object.');
|
|
99
86
|
process.exit(1);
|
|
100
87
|
}
|
|
101
88
|
}
|
|
@@ -103,10 +90,8 @@ export async function runBuild(options = {}) {
|
|
|
103
90
|
if (typeof tokens.shadows !== 'object' ||
|
|
104
91
|
tokens.shadows === null ||
|
|
105
92
|
Array.isArray(tokens.shadows)) {
|
|
106
|
-
|
|
107
|
-
console.
|
|
108
|
-
console.error('The "shadows" token must be an object.');
|
|
109
|
-
console.error('');
|
|
93
|
+
error('Invalid tokens.json');
|
|
94
|
+
console.log(' Details: The "shadows" token must be an object.');
|
|
110
95
|
process.exit(1);
|
|
111
96
|
}
|
|
112
97
|
}
|
|
@@ -118,10 +103,8 @@ export async function runBuild(options = {}) {
|
|
|
118
103
|
const spacing = tokens.spacing;
|
|
119
104
|
for (const [key, value] of Object.entries(spacing)) {
|
|
120
105
|
if (typeof value !== 'number' && typeof value !== 'string') {
|
|
121
|
-
|
|
122
|
-
console.
|
|
123
|
-
console.error(`Invalid spacing value for key "${key}". Expected number or string.`);
|
|
124
|
-
console.error('');
|
|
106
|
+
error('Invalid tokens.json');
|
|
107
|
+
console.log(` Details: Invalid spacing value for key "${key}". Expected number or string.`);
|
|
125
108
|
process.exit(1);
|
|
126
109
|
}
|
|
127
110
|
}
|
|
@@ -133,10 +116,8 @@ export async function runBuild(options = {}) {
|
|
|
133
116
|
const radius = tokens.radius;
|
|
134
117
|
for (const [key, value] of Object.entries(radius)) {
|
|
135
118
|
if (typeof value !== 'number' && typeof value !== 'string') {
|
|
136
|
-
|
|
137
|
-
console.
|
|
138
|
-
console.error(`Invalid radius value for key "${key}". Expected number or string.`);
|
|
139
|
-
console.error('');
|
|
119
|
+
error('Invalid tokens.json');
|
|
120
|
+
console.log(` Details: Invalid radius value for key "${key}". Expected number or string.`);
|
|
140
121
|
process.exit(1);
|
|
141
122
|
}
|
|
142
123
|
}
|
|
@@ -149,10 +130,8 @@ export async function runBuild(options = {}) {
|
|
|
149
130
|
const zIndex = tokens.zIndex;
|
|
150
131
|
for (const [key, value] of Object.entries(zIndex)) {
|
|
151
132
|
if (typeof value !== 'number' && typeof value !== 'string') {
|
|
152
|
-
|
|
153
|
-
console.
|
|
154
|
-
console.error(`Invalid zIndex value for key "${key}". Expected number or string.`);
|
|
155
|
-
console.error('');
|
|
133
|
+
error('Invalid tokens.json');
|
|
134
|
+
console.log(` Details: Invalid zIndex value for key "${key}". Expected number or string.`);
|
|
156
135
|
process.exit(1);
|
|
157
136
|
}
|
|
158
137
|
}
|
|
@@ -167,19 +146,15 @@ export async function runBuild(options = {}) {
|
|
|
167
146
|
if (typeof typography.fontSize !== 'object' ||
|
|
168
147
|
typography.fontSize === null ||
|
|
169
148
|
Array.isArray(typography.fontSize)) {
|
|
170
|
-
|
|
171
|
-
console.
|
|
172
|
-
console.error('The "typography.fontSize" token must be an object.');
|
|
173
|
-
console.error('');
|
|
149
|
+
error('Invalid tokens.json');
|
|
150
|
+
console.log(' Details: The "typography.fontSize" token must be an object.');
|
|
174
151
|
process.exit(1);
|
|
175
152
|
}
|
|
176
153
|
const fontSize = typography.fontSize;
|
|
177
154
|
for (const [key, value] of Object.entries(fontSize)) {
|
|
178
155
|
if (typeof value !== 'number' && typeof value !== 'string') {
|
|
179
|
-
|
|
180
|
-
console.
|
|
181
|
-
console.error(`Invalid typography.fontSize value for key "${key}". Expected number or string.`);
|
|
182
|
-
console.error('');
|
|
156
|
+
error('Invalid tokens.json');
|
|
157
|
+
console.log(` Details: Invalid typography.fontSize value for key "${key}". Expected number or string.`);
|
|
183
158
|
process.exit(1);
|
|
184
159
|
}
|
|
185
160
|
}
|
|
@@ -188,19 +163,15 @@ export async function runBuild(options = {}) {
|
|
|
188
163
|
if (typeof typography.fontWeight !== 'object' ||
|
|
189
164
|
typography.fontWeight === null ||
|
|
190
165
|
Array.isArray(typography.fontWeight)) {
|
|
191
|
-
|
|
192
|
-
console.
|
|
193
|
-
console.error('The "typography.fontWeight" token must be an object.');
|
|
194
|
-
console.error('');
|
|
166
|
+
error('Invalid tokens.json');
|
|
167
|
+
console.log(' Details: The "typography.fontWeight" token must be an object.');
|
|
195
168
|
process.exit(1);
|
|
196
169
|
}
|
|
197
170
|
const fontWeight = typography.fontWeight;
|
|
198
171
|
for (const [key, value] of Object.entries(fontWeight)) {
|
|
199
172
|
if (typeof value !== 'number' && typeof value !== 'string') {
|
|
200
|
-
|
|
201
|
-
console.
|
|
202
|
-
console.error(`Invalid typography.fontWeight value for key "${key}". Expected number or string.`);
|
|
203
|
-
console.error('');
|
|
173
|
+
error('Invalid tokens.json');
|
|
174
|
+
console.log(` Details: Invalid typography.fontWeight value for key "${key}". Expected number or string.`);
|
|
204
175
|
process.exit(1);
|
|
205
176
|
}
|
|
206
177
|
}
|
|
@@ -209,19 +180,15 @@ export async function runBuild(options = {}) {
|
|
|
209
180
|
if (typeof typography.lineHeight !== 'object' ||
|
|
210
181
|
typography.lineHeight === null ||
|
|
211
182
|
Array.isArray(typography.lineHeight)) {
|
|
212
|
-
|
|
213
|
-
console.
|
|
214
|
-
console.error('The "typography.lineHeight" token must be an object.');
|
|
215
|
-
console.error('');
|
|
183
|
+
error('Invalid tokens.json');
|
|
184
|
+
console.log(' Details: The "typography.lineHeight" token must be an object.');
|
|
216
185
|
process.exit(1);
|
|
217
186
|
}
|
|
218
187
|
const lineHeight = typography.lineHeight;
|
|
219
188
|
for (const [key, value] of Object.entries(lineHeight)) {
|
|
220
189
|
if (typeof value !== 'number' && typeof value !== 'string') {
|
|
221
|
-
|
|
222
|
-
console.
|
|
223
|
-
console.error(`Invalid typography.lineHeight value for key "${key}". Expected number or string.`);
|
|
224
|
-
console.error('');
|
|
190
|
+
error('Invalid tokens.json');
|
|
191
|
+
console.log(` Details: Invalid typography.lineHeight value for key "${key}". Expected number or string.`);
|
|
225
192
|
process.exit(1);
|
|
226
193
|
}
|
|
227
194
|
}
|
|
@@ -235,10 +202,8 @@ export async function runBuild(options = {}) {
|
|
|
235
202
|
const shadows = tokens.shadows;
|
|
236
203
|
for (const [key, value] of Object.entries(shadows)) {
|
|
237
204
|
if (typeof value !== 'string') {
|
|
238
|
-
|
|
239
|
-
console.
|
|
240
|
-
console.error(`Invalid shadows value for key "${key}". Expected string.`);
|
|
241
|
-
console.error('');
|
|
205
|
+
error('Invalid tokens.json');
|
|
206
|
+
console.log(` Details: Invalid shadows value for key "${key}". Expected string.`);
|
|
242
207
|
process.exit(1);
|
|
243
208
|
}
|
|
244
209
|
}
|
|
@@ -254,43 +219,62 @@ export async function runBuild(options = {}) {
|
|
|
254
219
|
if (typeof shades !== 'object' ||
|
|
255
220
|
shades === null ||
|
|
256
221
|
Array.isArray(shades)) {
|
|
257
|
-
|
|
258
|
-
console.
|
|
259
|
-
console.error(`Color "${colorName}" must be an object of shade values.`);
|
|
260
|
-
console.error('');
|
|
222
|
+
error('Invalid tokens.json');
|
|
223
|
+
console.log(` Details: Color "${colorName}" must be an object of shade values.`);
|
|
261
224
|
process.exit(1);
|
|
262
225
|
}
|
|
263
226
|
for (const [shade, value] of Object.entries(shades)) {
|
|
264
227
|
// shade keys must be numeric
|
|
265
228
|
if (!/^\d+$/.test(shade)) {
|
|
266
|
-
|
|
267
|
-
console.
|
|
268
|
-
console.error(`Invalid shade key "${shade}" in color "${colorName}". Shade keys must be numeric.`);
|
|
269
|
-
console.error('');
|
|
229
|
+
error('Invalid tokens.json');
|
|
230
|
+
console.log(` Details: Invalid shade key "${shade}" in color "${colorName}". Shade keys must be numeric.`);
|
|
270
231
|
process.exit(1);
|
|
271
232
|
}
|
|
272
233
|
// value must be a string
|
|
273
234
|
if (typeof value !== 'string') {
|
|
274
|
-
|
|
275
|
-
console.
|
|
276
|
-
console.error(`Invalid value for ${colorName}.${shade}. Expected a color string.`);
|
|
277
|
-
console.error('');
|
|
235
|
+
error('Invalid tokens.json');
|
|
236
|
+
console.log(` Details: Invalid value for ${colorName}.${shade}. Expected a color string.`);
|
|
278
237
|
process.exit(1);
|
|
279
238
|
}
|
|
280
239
|
// very light color format validation (delegate strictness to engine)
|
|
281
240
|
if (!value.startsWith('#') &&
|
|
282
241
|
!value.startsWith('rgb(') &&
|
|
283
242
|
!value.startsWith('rgba(')) {
|
|
284
|
-
|
|
285
|
-
console.
|
|
286
|
-
console.error(`Invalid color format for ${colorName}.${shade}: "${value}".`);
|
|
287
|
-
console.error('');
|
|
243
|
+
error('Invalid tokens.json');
|
|
244
|
+
console.log(` Details: Invalid color format for ${colorName}.${shade}: "${value}".`);
|
|
288
245
|
process.exit(1);
|
|
289
246
|
}
|
|
290
247
|
}
|
|
291
248
|
}
|
|
292
249
|
}
|
|
293
250
|
}
|
|
251
|
+
// Run non-blocking validations
|
|
252
|
+
if (fileTokens !== null) {
|
|
253
|
+
section('Token Validation');
|
|
254
|
+
const validationReport = runValidations(fileTokens);
|
|
255
|
+
if (hasValidationResults(validationReport)) {
|
|
256
|
+
if (hasValidationErrors(validationReport)) {
|
|
257
|
+
error('Blocking validation errors found');
|
|
258
|
+
console.log(' Details: Please fix errors below before proceeding.');
|
|
259
|
+
printValidationResults(validationReport);
|
|
260
|
+
process.exit(1);
|
|
261
|
+
}
|
|
262
|
+
else if (hasValidationWarnings(validationReport)) {
|
|
263
|
+
warning('Non-blocking validation warnings found');
|
|
264
|
+
console.log(' Details: Review warnings below for potential improvements.');
|
|
265
|
+
printValidationResults(validationReport);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
// Only info messages present
|
|
269
|
+
info('Validation info messages found');
|
|
270
|
+
console.log(' Details: Review info messages below for optional improvements.');
|
|
271
|
+
printValidationResults(validationReport);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
success('Token validation passed');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
294
278
|
const effectiveConfig = fileTokens
|
|
295
279
|
? {
|
|
296
280
|
...config,
|
|
@@ -300,16 +284,70 @@ export async function runBuild(options = {}) {
|
|
|
300
284
|
if (!fileTokens &&
|
|
301
285
|
config.tokens &&
|
|
302
286
|
!hasShownInlineTokenNotice) {
|
|
303
|
-
|
|
304
|
-
console.
|
|
305
|
-
console.info('Using tokens.json is recommended for larger or shared projects.');
|
|
306
|
-
console.info('');
|
|
287
|
+
info('Inline tokens detected');
|
|
288
|
+
console.log(' Details: Using tokens.json is recommended for larger or shared projects.');
|
|
307
289
|
hasShownInlineTokenNotice = true;
|
|
308
290
|
}
|
|
291
|
+
section('Building CSS');
|
|
309
292
|
const css = buildCssFromConfig(effectiveConfig);
|
|
310
|
-
|
|
293
|
+
success('Generated CSS');
|
|
294
|
+
// Count tokens for build summary
|
|
295
|
+
if (effectiveConfig.tokens) {
|
|
296
|
+
if (effectiveConfig.tokens.spacing) {
|
|
297
|
+
buildSummary.addTokenCategory('spacing', Object.keys(effectiveConfig.tokens.spacing).length);
|
|
298
|
+
}
|
|
299
|
+
if (effectiveConfig.tokens.colors) {
|
|
300
|
+
const colorCount = countNestedTokens(effectiveConfig.tokens.colors);
|
|
301
|
+
buildSummary.addTokenCategory('colors', colorCount);
|
|
302
|
+
}
|
|
303
|
+
if (effectiveConfig.tokens.radius) {
|
|
304
|
+
buildSummary.addTokenCategory('radius', Object.keys(effectiveConfig.tokens.radius).length);
|
|
305
|
+
}
|
|
306
|
+
if (effectiveConfig.tokens.zIndex) {
|
|
307
|
+
buildSummary.addTokenCategory('zIndex', Object.keys(effectiveConfig.tokens.zIndex).length);
|
|
308
|
+
}
|
|
309
|
+
if (effectiveConfig.tokens.typography) {
|
|
310
|
+
const typography = effectiveConfig.tokens.typography;
|
|
311
|
+
if (typography.fontSize) {
|
|
312
|
+
buildSummary.addTokenCategory('typography.fontSize', Object.keys(typography.fontSize).length);
|
|
313
|
+
}
|
|
314
|
+
if (typography.fontWeight) {
|
|
315
|
+
buildSummary.addTokenCategory('typography.fontWeight', Object.keys(typography.fontWeight).length);
|
|
316
|
+
}
|
|
317
|
+
if (typography.lineHeight) {
|
|
318
|
+
buildSummary.addTokenCategory('typography.lineHeight', Object.keys(typography.lineHeight).length);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (effectiveConfig.tokens.shadows) {
|
|
322
|
+
buildSummary.addTokenCategory('shadows', Object.keys(effectiveConfig.tokens.shadows).length);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
buildSummary.setOutputFile(outputFile);
|
|
311
326
|
writeCss(outputPath, css, { dryRun: options.dryRun });
|
|
312
327
|
if (!options.dryRun) {
|
|
313
|
-
|
|
328
|
+
success(`Output written to ${outputFile}`);
|
|
329
|
+
// Get output file size
|
|
330
|
+
const stats = fs.statSync(outputPath);
|
|
331
|
+
buildSummary.setOutputSize(stats.size);
|
|
332
|
+
}
|
|
333
|
+
// Print build summary
|
|
334
|
+
buildSummary.print();
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Count tokens in a nested structure (like colors)
|
|
338
|
+
*/
|
|
339
|
+
function countNestedTokens(obj) {
|
|
340
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
let count = 0;
|
|
344
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
345
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
346
|
+
count += countNestedTokens(value);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
count++;
|
|
350
|
+
}
|
|
314
351
|
}
|
|
352
|
+
return count;
|
|
315
353
|
}
|
package/dist/utils/logger.js
CHANGED
|
@@ -1,8 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced logger for ngCorex CLI with improved developer experience
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Build summary tracker
|
|
6
|
+
*/
|
|
7
|
+
export class BuildSummary {
|
|
8
|
+
constructor(options = {}) {
|
|
9
|
+
this.tokensProcessed = new Map();
|
|
10
|
+
this.warnings = [];
|
|
11
|
+
this.errors = [];
|
|
12
|
+
this.startTime = Date.now();
|
|
13
|
+
this.options = {};
|
|
14
|
+
this.options = options;
|
|
15
|
+
}
|
|
16
|
+
addTokenCategory(category, count) {
|
|
17
|
+
this.tokensProcessed.set(category, count);
|
|
18
|
+
}
|
|
19
|
+
addWarning(message) {
|
|
20
|
+
this.warnings.push({
|
|
21
|
+
timestamp: Date.now(),
|
|
22
|
+
message
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
addError(message) {
|
|
26
|
+
this.errors.push({
|
|
27
|
+
timestamp: Date.now(),
|
|
28
|
+
message
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
setOutputFile(file) {
|
|
32
|
+
this.options.outputFile = file;
|
|
33
|
+
}
|
|
34
|
+
setOutputSize(size) {
|
|
35
|
+
this.options.outputSize = size;
|
|
36
|
+
}
|
|
37
|
+
getWarnings() {
|
|
38
|
+
return this.warnings;
|
|
39
|
+
}
|
|
40
|
+
getErrors() {
|
|
41
|
+
return this.errors;
|
|
42
|
+
}
|
|
43
|
+
getTokensProcessed() {
|
|
44
|
+
return this.tokensProcessed;
|
|
45
|
+
}
|
|
46
|
+
getDuration() {
|
|
47
|
+
return Date.now() - this.startTime;
|
|
48
|
+
}
|
|
49
|
+
hasWarnings() {
|
|
50
|
+
return this.warnings.length > 0;
|
|
51
|
+
}
|
|
52
|
+
hasErrors() {
|
|
53
|
+
return this.errors.length > 0;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Format file size in human-readable format
|
|
57
|
+
*/
|
|
58
|
+
formatFileSize(bytes) {
|
|
59
|
+
if (bytes < 1024)
|
|
60
|
+
return `${bytes} B`;
|
|
61
|
+
if (bytes < 1024 * 1024)
|
|
62
|
+
return `${(bytes / 1024).toFixed(2)} KB`;
|
|
63
|
+
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Format duration in human-readable format
|
|
67
|
+
*/
|
|
68
|
+
formatDuration(ms) {
|
|
69
|
+
if (ms < 1000)
|
|
70
|
+
return `${ms}ms`;
|
|
71
|
+
return `${(ms / 1000).toFixed(2)}s`;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Print the build summary
|
|
75
|
+
*/
|
|
76
|
+
print() {
|
|
77
|
+
const duration = this.getDuration();
|
|
78
|
+
const totalTokens = Array.from(this.tokensProcessed.values()).reduce((a, b) => a + b, 0);
|
|
79
|
+
console.log('');
|
|
80
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
81
|
+
console.log(' 📦 Build Summary');
|
|
82
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
83
|
+
console.log('');
|
|
84
|
+
// Tokens processed
|
|
85
|
+
if (this.tokensProcessed.size > 0) {
|
|
86
|
+
console.log(' Tokens Processed:');
|
|
87
|
+
for (const [category, count] of this.tokensProcessed.entries()) {
|
|
88
|
+
console.log(` • ${category.padEnd(12)} ${count.toString().padStart(4)} tokens`);
|
|
89
|
+
}
|
|
90
|
+
console.log(` ${'─'.repeat(20)}`);
|
|
91
|
+
console.log(` ${'Total'.padEnd(12)} ${totalTokens.toString().padStart(4)} tokens`);
|
|
92
|
+
console.log('');
|
|
93
|
+
}
|
|
94
|
+
// Output file
|
|
95
|
+
if (this.options.outputFile) {
|
|
96
|
+
console.log(' Output:');
|
|
97
|
+
console.log(` • File: ${this.options.outputFile}`);
|
|
98
|
+
if (this.options.outputSize) {
|
|
99
|
+
console.log(` • Size: ${this.formatFileSize(this.options.outputSize)}`);
|
|
100
|
+
}
|
|
101
|
+
console.log('');
|
|
102
|
+
}
|
|
103
|
+
// Duration
|
|
104
|
+
console.log(` Duration: ${this.formatDuration(duration)}`);
|
|
105
|
+
console.log('');
|
|
106
|
+
// Warnings and errors
|
|
107
|
+
if (this.hasWarnings() || this.hasErrors()) {
|
|
108
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
109
|
+
if (this.hasWarnings()) {
|
|
110
|
+
console.log(` ⚠️ ${this.warnings.length} Warning${this.warnings.length > 1 ? 's' : ''}`);
|
|
111
|
+
}
|
|
112
|
+
if (this.hasErrors()) {
|
|
113
|
+
console.log(` ❌ ${this.errors.length} Error${this.errors.length > 1 ? 's' : ''}`);
|
|
114
|
+
}
|
|
115
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
116
|
+
console.log('');
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
console.log(' ✅ Build completed successfully!');
|
|
120
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
121
|
+
console.log('');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Print detailed warnings
|
|
126
|
+
*/
|
|
127
|
+
printWarnings() {
|
|
128
|
+
if (!this.hasWarnings())
|
|
129
|
+
return;
|
|
130
|
+
console.log('');
|
|
131
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
132
|
+
console.log(' ⚠️ Warnings');
|
|
133
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
134
|
+
console.log('');
|
|
135
|
+
for (const entry of this.warnings) {
|
|
136
|
+
const { message } = entry;
|
|
137
|
+
console.log(` ${getIcon(message.type)} ${message.message}`);
|
|
138
|
+
if (message.location) {
|
|
139
|
+
console.log(` Location: ${message.location}`);
|
|
140
|
+
}
|
|
141
|
+
if (message.details) {
|
|
142
|
+
console.log(` Details: ${message.details}`);
|
|
143
|
+
}
|
|
144
|
+
if (message.suggestion) {
|
|
145
|
+
console.log(` 💡 ${message.suggestion}`);
|
|
146
|
+
}
|
|
147
|
+
console.log('');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Print detailed errors
|
|
152
|
+
*/
|
|
153
|
+
printErrors() {
|
|
154
|
+
if (!this.hasErrors())
|
|
155
|
+
return;
|
|
156
|
+
console.log('');
|
|
157
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
158
|
+
console.log(' ❌ Errors');
|
|
159
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
160
|
+
console.log('');
|
|
161
|
+
for (const entry of this.errors) {
|
|
162
|
+
const { message } = entry;
|
|
163
|
+
console.log(` ${getIcon(message.type)} ${message.message}`);
|
|
164
|
+
if (message.location) {
|
|
165
|
+
console.log(` Location: ${message.location}`);
|
|
166
|
+
}
|
|
167
|
+
if (message.details) {
|
|
168
|
+
console.log(` Details: ${message.details}`);
|
|
169
|
+
}
|
|
170
|
+
if (message.suggestion) {
|
|
171
|
+
console.log(` 💡 ${message.suggestion}`);
|
|
172
|
+
}
|
|
173
|
+
console.log('');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get icon for log level
|
|
179
|
+
*/
|
|
180
|
+
function getIcon(level) {
|
|
181
|
+
const icons = {
|
|
182
|
+
success: '✅',
|
|
183
|
+
info: 'ℹ️',
|
|
184
|
+
warning: '⚠️',
|
|
185
|
+
error: '❌'
|
|
186
|
+
};
|
|
187
|
+
return icons[level] || '•';
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Log a success message
|
|
191
|
+
*/
|
|
192
|
+
export function success(message) {
|
|
193
|
+
console.log(`✅ ${message}`);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Log an info message
|
|
197
|
+
*/
|
|
198
|
+
export function info(message) {
|
|
199
|
+
console.log(`ℹ️ ${message}`);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Log a warning message
|
|
203
|
+
*/
|
|
204
|
+
export function warning(message) {
|
|
205
|
+
console.log('');
|
|
206
|
+
console.log(`⚠️ ${message}`);
|
|
207
|
+
console.log('');
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Log an error message
|
|
211
|
+
*/
|
|
212
|
+
export function error(message) {
|
|
213
|
+
console.log('');
|
|
214
|
+
console.log(`❌ ${message}`);
|
|
215
|
+
console.log('');
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Handle CLI errors with improved formatting
|
|
219
|
+
*/
|
|
1
220
|
export function handleCliError(error) {
|
|
221
|
+
console.log('');
|
|
222
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
223
|
+
console.log(' ❌ Error');
|
|
224
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
225
|
+
console.log('');
|
|
2
226
|
if (error instanceof Error) {
|
|
3
|
-
console.
|
|
227
|
+
console.log(` ${error.message}`);
|
|
4
228
|
}
|
|
5
229
|
else {
|
|
6
|
-
console.
|
|
230
|
+
console.log(' Unknown error occurred');
|
|
7
231
|
}
|
|
232
|
+
console.log('');
|
|
233
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
234
|
+
console.log('');
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Log a section header
|
|
238
|
+
*/
|
|
239
|
+
export function section(title) {
|
|
240
|
+
console.log('');
|
|
241
|
+
console.log(`━━━ ${title} ━━━`);
|
|
242
|
+
console.log('');
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Log a sub-section header
|
|
246
|
+
*/
|
|
247
|
+
export function subsection(title) {
|
|
248
|
+
console.log('');
|
|
249
|
+
console.log(` ${title}`);
|
|
250
|
+
console.log(` ${'─'.repeat(title.length)}`);
|
|
251
|
+
console.log('');
|
|
8
252
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ngcorex/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "CLI for ngCorex - Angular-native design token engine",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"design-tokens",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "tsc -p tsconfig.json"
|
|
38
38
|
},
|
|
39
|
-
|
|
39
|
+
"repository": {
|
|
40
40
|
"type": "git",
|
|
41
41
|
"url": "https://github.com/arkdezin/ngCorex.git",
|
|
42
42
|
"directory": "packages/cli"
|
|
43
43
|
},
|
|
44
44
|
|
|
45
|
-
"homepage": "https://github.com/arkdezin/ngCorex"
|
|
45
|
+
"homepage": "https://github.com/arkdezin/ngCorex/blob/main/README.md"
|
|
46
46
|
}
|