@ngcorex/cli 0.1.5 → 0.1.6

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.md CHANGED
@@ -1,6 +1,6 @@
1
- MIT License
1
+ # MIT License
2
2
 
3
- Copyright (c) 2026 Ajay Kumar Sharma
3
+ Copyright © 2026 Ajay Kumar Sharma
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
6
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ngcorex/cli
2
2
 
3
- ![NPM Version](https://img.shields.io/npm/v/%40ngcorex%2Fcli?style=flat-square&logo=npm&labelColor=%23D50100&color=%23000) ![NPM License](https://img.shields.io/npm/l/%40ngcorex%2Fcli?style=flat-square) ![Static Badge](https://img.shields.io/badge/Github-Repo-blue?style=flat-square&logo=github) ![NPM Downloads](https://img.shields.io/npm/dm/%40ngcorex%2Fcli?style=flat-square&logo=npm&logoColor=%23ffffff&labelColor=%23D50100&color=%23000)
3
+ ![NPM Version](https://img.shields.io/npm/v/%40ngcorex%2Fcli?style=flat-square&logo=npm&labelColor=%23D50100&color=%23000) ![NPM License](https://img.shields.io/npm/l/%40ngcorex%2Fcli?style=flat-square) ![Static Badge](https://img.shields.io/badge/Github-Repo-blue?style=flat-square&logo=github) ![NPM Downloads](https://img.shields.io/npm/dm/%40ngcorex%2Fcli?style=flat-square&logo=npm&logoColor=%23ffffff&labelColor=%23D50100&color=%23000) ![GitHub Issues or Pull Requests](https://img.shields.io/github/issues/arkdezin/ngcorex)
4
4
 
5
5
  Command-line interface for **ngCorex**.
6
6
 
@@ -63,18 +63,191 @@ Create a `tokens.json` file at your project root:
63
63
  ```json
64
64
  {
65
65
  "spacing": {
66
- "1": "1rem",
67
- "2": "2rem"
66
+ "xs": "1rem",
67
+ "sm": "1.25rem"
68
68
  },
69
69
  "colors": {
70
70
  "gray": {
71
71
  "100": "#f3f4f6",
72
72
  "900": "#111827"
73
73
  }
74
+ },
75
+ "radius": {
76
+ "sm": "4px",
77
+ "md": "8px",
78
+ "lg": "16px",
79
+ "full": "9999px"
80
+ },
81
+ "zIndex": {
82
+ "dropdown": "1000",
83
+ "modal": "2000",
84
+ "toast": "3000"
85
+ },
86
+ "typography": {
87
+ "fontSize": {
88
+ "xs": "0.75rem",
89
+ "sm": "0.875rem",
90
+ "base": "1rem",
91
+ "lg": "1.125rem",
92
+ "xl": "1.25rem"
93
+ },
94
+ "fontWeight": {
95
+ "normal": "400",
96
+ "medium": "500",
97
+ "semibold": "600",
98
+ "bold": "700"
99
+ },
100
+ "lineHeight": {
101
+ "tight": "1.25",
102
+ "normal": "1.5",
103
+ "relaxed": "1.75"
104
+ }
105
+ },
106
+ "shadows": {
107
+ "sm": "0 1px 2px 0 rgba(0,0,0,0.05)",
108
+ "md": "0 4px 6px -1px rgba(0,0,0,0.1)",
109
+ "lg": "0 10px 15px -3px rgba(0,0,0,0.1)",
110
+ "xl": "0 20px 25px -5px rgba(0,0,0,0.1)"
74
111
  }
75
112
  }
76
113
  ```
77
114
 
115
+ ### Supported Token Categories
116
+
117
+ ngCorex supports the following design token categories:
118
+
119
+ | Category | Description | Example Values |
120
+ | ---------- | ------------- | ---------------- |
121
+ | `spacing` | Spacing scale for margins, padding, gaps | `"4px"`, `"1rem"`, `"0.5em"` |
122
+ | `colors` | Color palette with nested shades | `"#f3f4f6"`, `"rgb(37, 99, 235)"` |
123
+ | `radius` | Border radius values | `"4px"`, `"8px"`, `"16px"`, `"full"` |
124
+ | `zIndex` | Z-index layer values | `"1000"`, `"2000"`, `"3000"` |
125
+ | `typography` | Font properties (fontSize, fontWeight, lineHeight) | See below |
126
+ | `shadows` | Box shadow values | `"0 1px 2px 0 rgba(0,0,0,0.05)"` |
127
+
128
+ #### Typography Sub-categories
129
+
130
+ | Sub-category | Description | Example Values |
131
+ | ------------- | ------------- | ---------------- |
132
+ | `fontSize` | Font size values | `"0.75rem"`, `"16px"`, `"1.25em"` |
133
+ | `fontWeight` | Font weight values | `"400"`, `"500"`, `"bold"`, `"700"` |
134
+ | `lineHeight` | Line height values | `"1.25"`, `"1.5"`, `"1.75"` |
135
+
136
+ ### Constraint Configuration
137
+
138
+ You can configure constraint levels in your `ngcorex.config.ts`:
139
+
140
+ ```ts
141
+ import { defineNgCorexConfig } from '@ngcorex/css';
142
+
143
+ export default defineNgCorexConfig({
144
+ constraints: {
145
+ spacing: {
146
+ unit: 'warning', // Warn about unitless numbers
147
+ format: 'error', // Error on invalid formats
148
+ type: 'error' // Error on wrong types
149
+ },
150
+ colors: {
151
+ format: 'error',
152
+ shadeKey: 'error',
153
+ type: 'error'
154
+ },
155
+ radius: {
156
+ unit: 'warning',
157
+ format: 'error',
158
+ type: 'error'
159
+ },
160
+ zIndex: {
161
+ format: 'error',
162
+ type: 'error'
163
+ },
164
+ typography: {
165
+ fontSize: {
166
+ format: 'error',
167
+ type: 'error'
168
+ },
169
+ fontWeight: {
170
+ format: 'error',
171
+ type: 'error'
172
+ },
173
+ lineHeight: {
174
+ format: 'error',
175
+ type: 'error'
176
+ }
177
+ },
178
+ shadows: {
179
+ format: 'error',
180
+ type: 'error'
181
+ }
182
+ }
183
+ });
184
+ ```
185
+
186
+ Available constraint levels: `'error'`, `'warning'`, `'off'`.
187
+
188
+ ### Output Layer Configuration
189
+
190
+ You can optionally wrap generated CSS in a CSS layer for better organization and specificity control:
191
+
192
+ ```ts
193
+ import { defineNgCorexConfig } from '@ngcorex/css';
194
+
195
+ export default defineNgCorexConfig({
196
+ output: {
197
+ layer: 'tokens', // Wraps CSS in @layer tokens { ... }
198
+ file: 'src/styles/ngcorex.css'
199
+ }
200
+ });
201
+ ```
202
+
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
+
78
251
  If `tokens.json` is present, it is used automatically.
79
252
 
80
253
  ## Configuration File
@@ -95,6 +268,18 @@ export default defineNgCorexConfig({
95
268
  });
96
269
  ```
97
270
 
271
+ In case you want to output in layer
272
+ **add:**
273
+
274
+ ```ts
275
+ export default defineNgCorexConfig({
276
+ output: {
277
+ layer: 'layer-name',
278
+ file: 'src/styles/ngcorex.css'
279
+ }
280
+ });
281
+ ```
282
+
98
283
  ### Important Rules
99
284
 
100
285
  - The config file **must import from npm packages only**
@@ -107,12 +292,12 @@ export default defineNgCorexConfig({
107
292
 
108
293
  The ngCorex CLI supports the following commands:
109
294
 
110
- - `ngcorex init` create starter config and tokens
111
- - `ngcorex build` generate CSS from tokens
112
- - `ngcorex build --watch` rebuild on file changes
113
- - `ngcorex build --dry-run` validate without writing files
114
- - `ngcorex version` / `--version` / `-v` print CLI version
115
- - `ngcorex --help` / `-h` show help information
295
+ - `ngcorex init` - create starter config and tokens
296
+ - `ngcorex build` - generate CSS from tokens
297
+ - `ngcorex build --watch` - rebuild on file changes
298
+ - `ngcorex build --dry-run` - validate without writing files
299
+ - `ngcorex version` / `--version` / `-v` - print CLI version
300
+ - `ngcorex --help` / `-h` - show help information
116
301
 
117
302
  ## Commands
118
303
 
@@ -187,11 +372,20 @@ The CLI generates CSS variables based on your tokens and constraints.
187
372
  Example output:
188
373
 
189
374
  ```css
190
- :root {
191
- --nx-spacing-1: 1rem;
192
- --nx-spacing-2: 2rem;
193
- --nx-color-gray-100: #f3f4f6;
194
- --nx-color-gray-900: #111827;
375
+ @layer tokens {
376
+ :root {
377
+ --nx-spacing-xs: 1rem;
378
+ --nx-spacing-sm: 1.25rem;
379
+ --nx-color-gray-100: #f3f4f6;
380
+ --nx-color-gray-900: #111827;
381
+ --nx-radius-sm: 4px;
382
+ --nx-radius-md: 8px;
383
+ --nx-zIndex-dropdown: 1000;
384
+ --nx-fontSize-xs: 0.75rem;
385
+ --nx-fontWeight-medium: 500;
386
+ --nx-lineHeight-normal: 1.5;
387
+ --nx-shadows-sm: 0 1px 2px 0 rgba(0,0,0,0.05);
388
+ }
195
389
  }
196
390
  ```
197
391
 
@@ -66,6 +66,50 @@ export async function runBuild(options = {}) {
66
66
  process.exit(1);
67
67
  }
68
68
  }
69
+ if ('radius' in tokens) {
70
+ if (typeof tokens.radius !== 'object' ||
71
+ tokens.radius === null ||
72
+ Array.isArray(tokens.radius)) {
73
+ console.error('');
74
+ console.error('❌ Invalid tokens.json');
75
+ console.error('The "radius" token must be an object.');
76
+ console.error('');
77
+ process.exit(1);
78
+ }
79
+ }
80
+ if ('zIndex' in tokens) {
81
+ if (typeof tokens.zIndex !== 'object' ||
82
+ tokens.zIndex === null ||
83
+ Array.isArray(tokens.zIndex)) {
84
+ console.error('');
85
+ console.error('❌ Invalid tokens.json');
86
+ console.error('The "zIndex" token must be an object.');
87
+ console.error('');
88
+ process.exit(1);
89
+ }
90
+ }
91
+ if ('typography' in tokens) {
92
+ if (typeof tokens.typography !== 'object' ||
93
+ tokens.typography === null ||
94
+ Array.isArray(tokens.typography)) {
95
+ console.error('');
96
+ console.error('❌ Invalid tokens.json');
97
+ console.error('The "typography" token must be an object.');
98
+ console.error('');
99
+ process.exit(1);
100
+ }
101
+ }
102
+ if ('shadows' in tokens) {
103
+ if (typeof tokens.shadows !== 'object' ||
104
+ tokens.shadows === null ||
105
+ Array.isArray(tokens.shadows)) {
106
+ console.error('');
107
+ console.error('❌ Invalid tokens.json');
108
+ console.error('The "shadows" token must be an object.');
109
+ console.error('');
110
+ process.exit(1);
111
+ }
112
+ }
69
113
  }
70
114
  // Validate spacing token values
71
115
  if (fileTokens !== null) {
@@ -82,6 +126,124 @@ export async function runBuild(options = {}) {
82
126
  }
83
127
  }
84
128
  }
129
+ // Validate radius token values
130
+ if (fileTokens !== null) {
131
+ const tokens = fileTokens;
132
+ if (tokens.radius) {
133
+ const radius = tokens.radius;
134
+ for (const [key, value] of Object.entries(radius)) {
135
+ if (typeof value !== 'number' && typeof value !== 'string') {
136
+ console.error('');
137
+ console.error('❌ Invalid tokens.json');
138
+ console.error(`Invalid radius value for key "${key}". Expected number or string.`);
139
+ console.error('');
140
+ process.exit(1);
141
+ }
142
+ }
143
+ }
144
+ }
145
+ // Validate z-index token values
146
+ if (fileTokens !== null) {
147
+ const tokens = fileTokens;
148
+ if (tokens.zIndex) {
149
+ const zIndex = tokens.zIndex;
150
+ for (const [key, value] of Object.entries(zIndex)) {
151
+ if (typeof value !== 'number' && typeof value !== 'string') {
152
+ console.error('');
153
+ console.error('❌ Invalid tokens.json');
154
+ console.error(`Invalid zIndex value for key "${key}". Expected number or string.`);
155
+ console.error('');
156
+ process.exit(1);
157
+ }
158
+ }
159
+ }
160
+ }
161
+ // Validate typography token structure
162
+ if (fileTokens !== null) {
163
+ const tokens = fileTokens;
164
+ if (tokens.typography) {
165
+ const typography = tokens.typography;
166
+ if (typography.fontSize) {
167
+ if (typeof typography.fontSize !== 'object' ||
168
+ typography.fontSize === null ||
169
+ Array.isArray(typography.fontSize)) {
170
+ console.error('');
171
+ console.error('❌ Invalid tokens.json');
172
+ console.error('The "typography.fontSize" token must be an object.');
173
+ console.error('');
174
+ process.exit(1);
175
+ }
176
+ const fontSize = typography.fontSize;
177
+ for (const [key, value] of Object.entries(fontSize)) {
178
+ if (typeof value !== 'number' && typeof value !== 'string') {
179
+ console.error('');
180
+ console.error('❌ Invalid tokens.json');
181
+ console.error(`Invalid typography.fontSize value for key "${key}". Expected number or string.`);
182
+ console.error('');
183
+ process.exit(1);
184
+ }
185
+ }
186
+ }
187
+ if (typography.fontWeight) {
188
+ if (typeof typography.fontWeight !== 'object' ||
189
+ typography.fontWeight === null ||
190
+ Array.isArray(typography.fontWeight)) {
191
+ console.error('');
192
+ console.error('❌ Invalid tokens.json');
193
+ console.error('The "typography.fontWeight" token must be an object.');
194
+ console.error('');
195
+ process.exit(1);
196
+ }
197
+ const fontWeight = typography.fontWeight;
198
+ for (const [key, value] of Object.entries(fontWeight)) {
199
+ if (typeof value !== 'number' && typeof value !== 'string') {
200
+ console.error('');
201
+ console.error('❌ Invalid tokens.json');
202
+ console.error(`Invalid typography.fontWeight value for key "${key}". Expected number or string.`);
203
+ console.error('');
204
+ process.exit(1);
205
+ }
206
+ }
207
+ }
208
+ if (typography.lineHeight) {
209
+ if (typeof typography.lineHeight !== 'object' ||
210
+ typography.lineHeight === null ||
211
+ Array.isArray(typography.lineHeight)) {
212
+ console.error('');
213
+ console.error('❌ Invalid tokens.json');
214
+ console.error('The "typography.lineHeight" token must be an object.');
215
+ console.error('');
216
+ process.exit(1);
217
+ }
218
+ const lineHeight = typography.lineHeight;
219
+ for (const [key, value] of Object.entries(lineHeight)) {
220
+ if (typeof value !== 'number' && typeof value !== 'string') {
221
+ console.error('');
222
+ console.error('❌ Invalid tokens.json');
223
+ console.error(`Invalid typography.lineHeight value for key "${key}". Expected number or string.`);
224
+ console.error('');
225
+ process.exit(1);
226
+ }
227
+ }
228
+ }
229
+ }
230
+ }
231
+ // Validate shadows token values
232
+ if (fileTokens !== null) {
233
+ const tokens = fileTokens;
234
+ if (tokens.shadows) {
235
+ const shadows = tokens.shadows;
236
+ for (const [key, value] of Object.entries(shadows)) {
237
+ if (typeof value !== 'string') {
238
+ console.error('');
239
+ console.error('❌ Invalid tokens.json');
240
+ console.error(`Invalid shadows value for key "${key}". Expected string.`);
241
+ console.error('');
242
+ process.exit(1);
243
+ }
244
+ }
245
+ }
246
+ }
85
247
  }
86
248
  // Validate color token structure & values
87
249
  if (fileTokens !== null) {
@@ -139,8 +301,8 @@ export async function runBuild(options = {}) {
139
301
  config.tokens &&
140
302
  !hasShownInlineTokenNotice) {
141
303
  console.info('');
142
- console.info('ℹ️ Inline tokens detected.');
143
- console.info(' Using tokens.json is recommended for larger or shared projects.');
304
+ console.info('i Inline tokens detected.');
305
+ console.info('Using tokens.json is recommended for larger or shared projects.');
144
306
  console.info('');
145
307
  hasShownInlineTokenNotice = true;
146
308
  }
@@ -2,7 +2,7 @@ import { mkdirSync, writeFileSync } from 'node:fs';
2
2
  import { dirname } from 'node:path';
3
3
  export function writeCss(filePath, css, options = {}) {
4
4
  if (options.dryRun) {
5
- console.log(`ℹ Dry run skipping write to ${filePath}`);
5
+ console.log(`i Dry run - skipping write to ${filePath}`);
6
6
  return;
7
7
  }
8
8
  const dir = dirname(filePath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngcorex/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "CLI for ngCorex - Angular-native design token engine",
5
5
  "keywords": [
6
6
  "design-tokens",
@@ -12,7 +12,12 @@
12
12
  "frontend-tooling",
13
13
  "ngcorex",
14
14
  "typescript",
15
- "angular"
15
+ "angular",
16
+ "css-variables",
17
+ "utility-css",
18
+ "build-time",
19
+ "design-system",
20
+ "theming"
16
21
  ],
17
22
  "license": "MIT",
18
23
  "type": "module",