@ngcorex/css 0.1.6 → 0.1.7

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.
Files changed (37) hide show
  1. package/dist/constraints/constraint-error.d.ts.map +1 -1
  2. package/dist/constraints/constraint-error.js +2 -2
  3. package/dist/engine/build-css.js +2 -2
  4. package/dist/errors/ngcorex-error.d.ts +68 -1
  5. package/dist/errors/ngcorex-error.d.ts.map +1 -1
  6. package/dist/errors/ngcorex-error.js +135 -4
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +2 -0
  10. package/dist/tokens/normalize-colors.js +2 -2
  11. package/dist/tokens/normalize.d.ts.map +1 -1
  12. package/dist/tokens/normalize.js +2 -2
  13. package/dist/validation/color-format.d.ts +22 -0
  14. package/dist/validation/color-format.d.ts.map +1 -0
  15. package/dist/validation/color-format.js +249 -0
  16. package/dist/validation/index.d.ts +42 -0
  17. package/dist/validation/index.d.ts.map +1 -0
  18. package/dist/validation/index.js +206 -0
  19. package/dist/validation/scale-consistency.d.ts +14 -0
  20. package/dist/validation/scale-consistency.d.ts.map +1 -0
  21. package/dist/validation/scale-consistency.js +214 -0
  22. package/dist/validation/shadow-format.d.ts +14 -0
  23. package/dist/validation/shadow-format.d.ts.map +1 -0
  24. package/dist/validation/shadow-format.js +217 -0
  25. package/dist/validation/spacing-format.d.ts +14 -0
  26. package/dist/validation/spacing-format.d.ts.map +1 -0
  27. package/dist/validation/spacing-format.js +173 -0
  28. package/dist/validation/token-duplicates.d.ts +22 -0
  29. package/dist/validation/token-duplicates.d.ts.map +1 -0
  30. package/dist/validation/token-duplicates.js +126 -0
  31. package/dist/validation/types.d.ts +160 -0
  32. package/dist/validation/types.d.ts.map +1 -0
  33. package/dist/validation/types.js +4 -0
  34. package/dist/validation/z-index-logic.d.ts +14 -0
  35. package/dist/validation/z-index-logic.d.ts.map +1 -0
  36. package/dist/validation/z-index-logic.js +230 -0
  37. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"constraint-error.d.ts","sourceRoot":"","sources":["../../src/constraints/constraint-error.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,IAAI,CAgBN"}
1
+ {"version":3,"file":"constraint-error.d.ts","sourceRoot":"","sources":["../../src/constraints/constraint-error.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,IAAI,CAiBN"}
@@ -1,10 +1,10 @@
1
- import { NgCorexError } from '../errors/ngcorex-error.js';
1
+ import { NgCorexError, NgCorexErrorCode } from '../errors/ngcorex-error.js';
2
2
  export function constraintViolation(level, rule, message, fix) {
3
3
  if (level === 'off') {
4
4
  return;
5
5
  }
6
6
  if (level === 'error') {
7
- throw new NgCorexError(`Constraint violation: ${rule}`, `${message}\n\nFix:\n${fix}`);
7
+ throw new NgCorexError(NgCorexErrorCode.CONSTRAINT_VIOLATION_STRING, `Constraint violation: ${rule}`, `${message}\n\nFix:\n${fix}`);
8
8
  }
9
9
  // warning
10
10
  console.warn(`ngCorex Warning: ${rule}\n\n${message}\n\nFix:\n${fix}\n`);
@@ -2,7 +2,7 @@ import { normalizeTokenScale } from '../tokens/normalize.js';
2
2
  import { normalizeColorTokens } from '../tokens/normalize-colors.js';
3
3
  import { generateCssVariables } from '../tokens/generate-css.js';
4
4
  import { presetRegistry } from '../presets/index.js';
5
- import { NgCorexError } from '../errors/ngcorex-error.js';
5
+ import { NgCorexError, NgCorexErrorCode } from '../errors/ngcorex-error.js';
6
6
  import { deepMerge } from '../utils/deep-merge.js';
7
7
  import { runConstraints } from '../constraints/run-constraints.js';
8
8
  import { wrapCss } from '../output/wrap-css.js';
@@ -17,7 +17,7 @@ export function buildCssFromConfig(config) {
17
17
  for (const presetName of config.presets) {
18
18
  const preset = presetRegistry[presetName];
19
19
  if (!preset) {
20
- throw new NgCorexError('Unknown preset', `Preset "${presetName}" does not exist.
20
+ throw new NgCorexError(NgCorexErrorCode.UNKNOWN_PRESET_STRING, `Preset "${presetName}" does not exist.
21
21
 
22
22
  Available presets:
23
23
  - ${Object.keys(presetRegistry).join('\n- ')}
@@ -1,4 +1,71 @@
1
+ /**
2
+ * Enhanced error class for ngCorex with improved developer experience
3
+ */
4
+ /**
5
+ * Error codes for categorizing different types of errors
6
+ */
7
+ export declare enum NgCorexErrorCode {
8
+ TOKEN_INVALID_FORMAT = "TOKEN_INVALID_FORMAT",
9
+ TOKEN_INVALID_TYPE = "TOKEN_INVALID_TYPE",
10
+ TOKEN_DUPLICATE = "TOKEN_DUPLICATE",
11
+ TOKEN_MISSING = "TOKEN_MISSING",
12
+ CONSTRAINT_VIOLATION = "CONSTRAINT_VIOLATION",
13
+ CONSTRAINT_INVALID_CONFIG = "CONSTRAINT_INVALID_CONFIG",
14
+ CONFIG_INVALID = "CONFIG_INVALID",
15
+ CONFIG_MISSING = "CONFIG_MISSING",
16
+ CONFIG_PARSE_ERROR = "CONFIG_PARSE_ERROR",
17
+ OUTPUT_WRITE_ERROR = "OUTPUT_WRITE_ERROR",
18
+ OUTPUT_INVALID_PATH = "OUTPUT_INVALID_PATH",
19
+ UNKNOWN_ERROR = "UNKNOWN_ERROR",
20
+ CONSTRAINT_VIOLATION_STRING = "Constraint violation",
21
+ UNKNOWN_PRESET_STRING = "Unknown preset",
22
+ INVALID_COLOR_TOKEN_STRING = "Invalid color token",
23
+ INVALID_TOKEN_STRING = "Invalid"
24
+ }
25
+ /**
26
+ * Error location information
27
+ */
28
+ export interface ErrorLocation {
29
+ file?: string;
30
+ line?: number;
31
+ column?: number;
32
+ path?: string;
33
+ }
34
+ /**
35
+ * Error suggestion for fixing the issue
36
+ */
37
+ export interface ErrorSuggestion {
38
+ message: string;
39
+ code?: string;
40
+ }
41
+ /**
42
+ * Enhanced error class with error codes, location, and suggestions
43
+ */
1
44
  export declare class NgCorexError extends Error {
2
- constructor(message: string, details?: string);
45
+ readonly code: NgCorexErrorCode;
46
+ readonly location?: ErrorLocation;
47
+ readonly suggestion?: ErrorSuggestion;
48
+ readonly docsLink?: string;
49
+ constructor(code: NgCorexErrorCode, message: string, details?: string, location?: ErrorLocation, suggestion?: ErrorSuggestion, docsLink?: string);
50
+ /**
51
+ * Get a formatted error message for display
52
+ */
53
+ getDisplayMessage(): string;
3
54
  }
55
+ /**
56
+ * Helper function to create a token format error
57
+ */
58
+ export declare function createTokenFormatError(tokenPath: string, value: unknown, expectedFormat: string, file?: string): NgCorexError;
59
+ /**
60
+ * Helper function to create a token type error
61
+ */
62
+ export declare function createTokenTypeError(tokenPath: string, actualType: string, expectedType: string, file?: string): NgCorexError;
63
+ /**
64
+ * Helper function to create a duplicate token error
65
+ */
66
+ export declare function createDuplicateTokenError(tokenName: string, locations: string[]): NgCorexError;
67
+ /**
68
+ * Helper function to create a constraint violation error
69
+ */
70
+ export declare function createConstraintViolationError(rule: string, message: string, fix: string): NgCorexError;
4
71
  //# sourceMappingURL=ngcorex-error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ngcorex-error.d.ts","sourceRoot":"","sources":["../../src/errors/ngcorex-error.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAQ9C"}
1
+ {"version":3,"file":"ngcorex-error.d.ts","sourceRoot":"","sources":["../../src/errors/ngcorex-error.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,oBAAY,gBAAgB;IAE1B,oBAAoB,yBAAyB;IAC7C,kBAAkB,uBAAuB;IACzC,eAAe,oBAAoB;IACnC,aAAa,kBAAkB;IAG/B,oBAAoB,yBAAyB;IAC7C,yBAAyB,8BAA8B;IAGvD,cAAc,mBAAmB;IACjC,cAAc,mBAAmB;IACjC,kBAAkB,uBAAuB;IAGzC,kBAAkB,uBAAuB;IACzC,mBAAmB,wBAAwB;IAG3C,aAAa,kBAAkB;IAG/B,2BAA2B,yBAAyB;IACpD,qBAAqB,mBAAmB;IACxC,0BAA0B,wBAAwB;IAClD,oBAAoB,YAAY;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;gBAGzB,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,aAAa,EACxB,UAAU,CAAC,EAAE,eAAe,EAC5B,QAAQ,CAAC,EAAE,MAAM;IAUnB;;OAEG;IACH,iBAAiB,IAAI,MAAM;CA4B5B;AAuCD;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,cAAc,EAAE,MAAM,EACtB,IAAI,CAAC,EAAE,MAAM,GACZ,YAAY,CAWd;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,MAAM,GACZ,YAAY,CAWd;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EAAE,GAClB,YAAY,CAWd;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,YAAY,CAUd"}
@@ -1,8 +1,139 @@
1
+ /**
2
+ * Enhanced error class for ngCorex with improved developer experience
3
+ */
4
+ /**
5
+ * Error codes for categorizing different types of errors
6
+ */
7
+ export var NgCorexErrorCode;
8
+ (function (NgCorexErrorCode) {
9
+ // Token validation errors
10
+ NgCorexErrorCode["TOKEN_INVALID_FORMAT"] = "TOKEN_INVALID_FORMAT";
11
+ NgCorexErrorCode["TOKEN_INVALID_TYPE"] = "TOKEN_INVALID_TYPE";
12
+ NgCorexErrorCode["TOKEN_DUPLICATE"] = "TOKEN_DUPLICATE";
13
+ NgCorexErrorCode["TOKEN_MISSING"] = "TOKEN_MISSING";
14
+ // Constraint errors
15
+ NgCorexErrorCode["CONSTRAINT_VIOLATION"] = "CONSTRAINT_VIOLATION";
16
+ NgCorexErrorCode["CONSTRAINT_INVALID_CONFIG"] = "CONSTRAINT_INVALID_CONFIG";
17
+ // Config errors
18
+ NgCorexErrorCode["CONFIG_INVALID"] = "CONFIG_INVALID";
19
+ NgCorexErrorCode["CONFIG_MISSING"] = "CONFIG_MISSING";
20
+ NgCorexErrorCode["CONFIG_PARSE_ERROR"] = "CONFIG_PARSE_ERROR";
21
+ // Output errors
22
+ NgCorexErrorCode["OUTPUT_WRITE_ERROR"] = "OUTPUT_WRITE_ERROR";
23
+ NgCorexErrorCode["OUTPUT_INVALID_PATH"] = "OUTPUT_INVALID_PATH";
24
+ // General errors
25
+ NgCorexErrorCode["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
26
+ // Additional error codes for existing code
27
+ NgCorexErrorCode["CONSTRAINT_VIOLATION_STRING"] = "Constraint violation";
28
+ NgCorexErrorCode["UNKNOWN_PRESET_STRING"] = "Unknown preset";
29
+ NgCorexErrorCode["INVALID_COLOR_TOKEN_STRING"] = "Invalid color token";
30
+ NgCorexErrorCode["INVALID_TOKEN_STRING"] = "Invalid";
31
+ })(NgCorexErrorCode || (NgCorexErrorCode = {}));
32
+ /**
33
+ * Enhanced error class with error codes, location, and suggestions
34
+ */
1
35
  export class NgCorexError extends Error {
2
- constructor(message, details) {
3
- super(details
4
- ? `ngCorex Error: ${message}\n\n${details}`
5
- : `ngCorex Error: ${message}`);
36
+ constructor(code, message, details, location, suggestion, docsLink) {
37
+ super(formatErrorMessage(code, message, details, location, suggestion));
6
38
  this.name = 'NgCorexError';
39
+ this.code = code;
40
+ this.location = location;
41
+ this.suggestion = suggestion;
42
+ this.docsLink = docsLink;
7
43
  }
44
+ /**
45
+ * Get a formatted error message for display
46
+ */
47
+ getDisplayMessage() {
48
+ let output = '';
49
+ output += `Error: ${this.code}\n`;
50
+ output += `Message: ${this.message}\n`;
51
+ if (this.location) {
52
+ const locParts = [];
53
+ if (this.location.file)
54
+ locParts.push(`file: ${this.location.file}`);
55
+ if (this.location.path)
56
+ locParts.push(`path: ${this.location.path}`);
57
+ if (this.location.line)
58
+ locParts.push(`line: ${this.location.line}`);
59
+ if (this.location.column)
60
+ locParts.push(`column: ${this.location.column}`);
61
+ output += `Location: ${locParts.join(', ')}\n`;
62
+ }
63
+ if (this.suggestion) {
64
+ output += `Suggestion: ${this.suggestion.message}\n`;
65
+ if (this.suggestion.code) {
66
+ output += `Example:\n${this.suggestion.code}\n`;
67
+ }
68
+ }
69
+ if (this.docsLink) {
70
+ output += `Documentation: ${this.docsLink}\n`;
71
+ }
72
+ return output;
73
+ }
74
+ }
75
+ /**
76
+ * Format error message for display
77
+ */
78
+ function formatErrorMessage(code, message, details, location, suggestion) {
79
+ let output = `ngCorex Error [${code}]: ${message}`;
80
+ if (location) {
81
+ const locParts = [];
82
+ if (location.file)
83
+ locParts.push(`file: ${location.file}`);
84
+ if (location.path)
85
+ locParts.push(`path: ${location.path}`);
86
+ if (location.line)
87
+ locParts.push(`line: ${location.line}`);
88
+ if (location.column)
89
+ locParts.push(`column: ${location.column}`);
90
+ if (locParts.length > 0) {
91
+ output += `\nLocation: ${locParts.join(', ')}`;
92
+ }
93
+ }
94
+ if (details) {
95
+ output += `\n\nDetails:\n${details}`;
96
+ }
97
+ if (suggestion) {
98
+ output += `\n\n💡 Suggestion:\n${suggestion.message}`;
99
+ if (suggestion.code) {
100
+ output += `\n\nExample:\n${suggestion.code}`;
101
+ }
102
+ }
103
+ return output;
104
+ }
105
+ /**
106
+ * Helper function to create a token format error
107
+ */
108
+ export function createTokenFormatError(tokenPath, value, expectedFormat, file) {
109
+ return new NgCorexError(NgCorexErrorCode.TOKEN_INVALID_FORMAT, `Invalid token format for "${tokenPath}"`, `Received value: ${JSON.stringify(value)}\nExpected format: ${expectedFormat}`, { file, path: tokenPath }, {
110
+ message: `Update the token value to match the expected format.`,
111
+ code: `// Example for ${tokenPath}:\n"${tokenPath}": "${expectedFormat}"`
112
+ });
113
+ }
114
+ /**
115
+ * Helper function to create a token type error
116
+ */
117
+ export function createTokenTypeError(tokenPath, actualType, expectedType, file) {
118
+ return new NgCorexError(NgCorexErrorCode.TOKEN_INVALID_TYPE, `Invalid token type for "${tokenPath}"`, `Received type: ${actualType}\nExpected type: ${expectedType}`, { file, path: tokenPath }, {
119
+ message: `Update the token value to the correct type.`,
120
+ code: `// Example for ${tokenPath}:\n"${tokenPath}": <${expectedType}>`
121
+ });
122
+ }
123
+ /**
124
+ * Helper function to create a duplicate token error
125
+ */
126
+ export function createDuplicateTokenError(tokenName, locations) {
127
+ return new NgCorexError(NgCorexErrorCode.TOKEN_DUPLICATE, `Duplicate token name found: "${tokenName}"`, `Token "${tokenName}" appears in multiple locations:\n${locations.map(l => ` - ${l}`).join('\n')}`, undefined, {
128
+ message: `Rename one of the tokens to avoid conflicts.`,
129
+ code: `// Example:\n// Change ${locations[0]} to "${tokenName}Alt"\n// or rename ${locations[1]} to "${tokenName}Alt"`
130
+ });
131
+ }
132
+ /**
133
+ * Helper function to create a constraint violation error
134
+ */
135
+ export function createConstraintViolationError(rule, message, fix) {
136
+ return new NgCorexError(NgCorexErrorCode.CONSTRAINT_VIOLATION, `Constraint violation: ${rule}`, message, undefined, {
137
+ message: fix
138
+ });
8
139
  }
package/dist/index.d.ts CHANGED
@@ -8,5 +8,7 @@ export { buildCssFromConfig } from './engine/build-css.js';
8
8
  export { presetRegistry } from './presets/index.js';
9
9
  export { NgCorexError } from './errors/ngcorex-error.js';
10
10
  export { runConstraints } from './constraints/run-constraints.js';
11
+ export { runValidations, runValidationsWithoutInfo, getValidationSummary, printValidationResults, hasValidationResults, hasValidationErrors, hasValidationWarnings, hasValidationInfo } from './validation/index.js';
12
+ export type { ValidationReport, ValidationResult, ValidationConfig, TokensForValidation, TokenLocation, DuplicateToken, ScaleConsistencyIssue, ColorFormatIssue, SpacingFormatIssue, ShadowFormatIssue, ZIndexLogicIssue } from './validation/types.js';
11
13
  export { wrapCss } from './output/wrap-css.js';
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,YAAY,EACV,aAAa,EACb,YAAY,EACZ,eAAe,EACf,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACV,UAAU,EACV,eAAe,EACf,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAElE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,YAAY,EACV,aAAa,EACb,YAAY,EACZ,eAAe,EACf,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACV,UAAU,EACV,eAAe,EACf,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAGlE,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -7,4 +7,6 @@ export { buildCssFromConfig } from './engine/build-css.js';
7
7
  export { presetRegistry } from './presets/index.js';
8
8
  export { NgCorexError } from './errors/ngcorex-error.js';
9
9
  export { runConstraints } from './constraints/run-constraints.js';
10
+ // Validation API
11
+ export { runValidations, runValidationsWithoutInfo, getValidationSummary, printValidationResults, hasValidationResults, hasValidationErrors, hasValidationWarnings, hasValidationInfo } from './validation/index.js';
10
12
  export { wrapCss } from './output/wrap-css.js';
@@ -1,4 +1,4 @@
1
- import { NgCorexError } from '../errors/ngcorex-error.js';
1
+ import { NgCorexError, NgCorexErrorCode } from '../errors/ngcorex-error.js';
2
2
  const CSS_VAR_PREFIX = 'nx';
3
3
  /**
4
4
  * Normalize nested color tokens (e.g. primary.500)
@@ -10,7 +10,7 @@ export function normalizeColorTokens(colors) {
10
10
  for (const shade in palette) {
11
11
  const value = palette[shade];
12
12
  if (typeof value !== 'string') {
13
- throw new NgCorexError('Invalid color token', `Token: colors.${paletteName}.${shade}
13
+ throw new NgCorexError(NgCorexErrorCode.INVALID_COLOR_TOKEN_STRING, `Token: colors.${paletteName}.${shade}
14
14
  Value: ${String(value)}
15
15
  Expected: string (e.g. "#ffffff")
16
16
 
@@ -1 +1 @@
1
- {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/tokens/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAmB,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAMpF;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,UAAU,GAChB,oBAAoB,CA8BtB"}
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/tokens/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAmB,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAMpF;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,UAAU,GAChB,oBAAoB,CA+BtB"}
@@ -1,4 +1,4 @@
1
- import { NgCorexError } from '../errors/ngcorex-error.js';
1
+ import { NgCorexError, NgCorexErrorCode } from '../errors/ngcorex-error.js';
2
2
  const CSS_VAR_PREFIX = 'nx';
3
3
  /**
4
4
  * Normalize a single token scale (e.g. spacing, radius)
@@ -9,7 +9,7 @@ export function normalizeTokenScale(category, scale) {
9
9
  const value = scale[key];
10
10
  // Basic validation
11
11
  if (typeof value !== 'string') {
12
- throw new NgCorexError(`Invalid ${category} token`, `Token: ${category}.${key}
12
+ throw new NgCorexError(NgCorexErrorCode.INVALID_TOKEN_STRING, `Invalid ${category} token`, `Token: ${category}.${key}
13
13
  Value: ${String(value)}
14
14
  Expected: string (e.g. "1rem")
15
15
 
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Color format validation
3
+ * Checks for valid CSS color formats and consistency
4
+ */
5
+ import type { ValidationResult, TokensForValidation, ColorFormatIssue } from './types.js';
6
+ /**
7
+ * Determine the color format type
8
+ */
9
+ export declare function getColorFormat(value: string): string | null;
10
+ /**
11
+ * Check if a color value is valid
12
+ */
13
+ export declare function isValidColor(value: string): boolean;
14
+ /**
15
+ * Validate all color formats
16
+ */
17
+ export declare function validateColorFormat(tokens: TokensForValidation, severity?: 'info' | 'warning' | 'error'): ValidationResult[];
18
+ /**
19
+ * Get a summary of color format issues
20
+ */
21
+ export declare function getColorFormatSummary(issues: ColorFormatIssue[]): string;
22
+ //# sourceMappingURL=color-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"color-format.d.ts","sourceRoot":"","sources":["../../src/validation/color-format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AA6BpB;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW3D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AA2LD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,GAAE,MAAM,GAAG,SAAS,GAAG,OAAmB,GACjD,gBAAgB,EAAE,CAsBpB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAexE"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Color format validation
3
+ * Checks for valid CSS color formats and consistency
4
+ */
5
+ /**
6
+ * Validation code for color format
7
+ */
8
+ const COLOR_FORMAT_CODE = 'COLOR_FORMAT';
9
+ /**
10
+ * Color format patterns
11
+ */
12
+ const COLOR_PATTERNS = {
13
+ // Hex colors: #fff or #ffffff
14
+ hex3: /^#([0-9a-fA-F]{3})$/,
15
+ hex4: /^#([0-9a-fA-F]{4})$/,
16
+ hex6: /^#([0-9a-fA-F]{6})$/,
17
+ hex8: /^#([0-9a-fA-F]{8})$/,
18
+ // RGB/RGBA: rgb(r, g, b) or rgba(r, g, b, a)
19
+ rgb: /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/,
20
+ rgba: /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*([01]?\.?\d*)\s*\)$/,
21
+ // HSL/HSLA: hsl(h, s%, l%) or hsla(h, s%, l%, a)
22
+ hsl: /^hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)$/,
23
+ hsla: /^hsla\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*([01]?\.?\d*)\s*\)$/,
24
+ // Named colors
25
+ named: /^[a-zA-Z]+$/
26
+ };
27
+ /**
28
+ * Determine the color format type
29
+ */
30
+ export function getColorFormat(value) {
31
+ if (COLOR_PATTERNS.hex3.test(value))
32
+ return 'hex3';
33
+ if (COLOR_PATTERNS.hex4.test(value))
34
+ return 'hex4';
35
+ if (COLOR_PATTERNS.hex6.test(value))
36
+ return 'hex6';
37
+ if (COLOR_PATTERNS.hex8.test(value))
38
+ return 'hex8';
39
+ if (COLOR_PATTERNS.rgb.test(value))
40
+ return 'rgb';
41
+ if (COLOR_PATTERNS.rgba.test(value))
42
+ return 'rgba';
43
+ if (COLOR_PATTERNS.hsl.test(value))
44
+ return 'hsl';
45
+ if (COLOR_PATTERNS.hsla.test(value))
46
+ return 'hsla';
47
+ if (COLOR_PATTERNS.named.test(value))
48
+ return 'named';
49
+ return null;
50
+ }
51
+ /**
52
+ * Check if a color value is valid
53
+ */
54
+ export function isValidColor(value) {
55
+ return getColorFormat(value) !== null;
56
+ }
57
+ /**
58
+ * Validate RGB values
59
+ */
60
+ function validateRgbValues(r, g, b) {
61
+ return r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
62
+ }
63
+ /**
64
+ * Validate HSL hue value
65
+ */
66
+ function validateHslHue(h) {
67
+ return h >= 0 && h <= 360;
68
+ }
69
+ /**
70
+ * Validate HSL saturation/lightness values
71
+ */
72
+ function validateHslPercent(s, l) {
73
+ return s >= 0 && s <= 100 && l >= 0 && l <= 100;
74
+ }
75
+ /**
76
+ * Check for deprecated color formats
77
+ */
78
+ function isDeprecatedFormat(format) {
79
+ // hex3 and hex4 are shorter but less precise
80
+ return format === 'hex3' || format === 'hex4';
81
+ }
82
+ /**
83
+ * Validate a single color value
84
+ */
85
+ function validateColorValue(path, value, severity = 'warning') {
86
+ const format = getColorFormat(value);
87
+ if (!format) {
88
+ return {
89
+ severity: 'error',
90
+ code: COLOR_FORMAT_CODE,
91
+ message: `Invalid color format: "${value}"`,
92
+ path,
93
+ suggestion: 'Use a valid CSS color format: hex (#ffffff), rgb(255,255,255), rgba(255,255,255,1), hsl(0,0%,100%), or a named color.',
94
+ example: `// Examples:\n// "${path}": "#ffffff"\n// "${path}": "rgb(255, 255, 255)"`
95
+ };
96
+ }
97
+ // Check for deprecated formats
98
+ if (isDeprecatedFormat(format)) {
99
+ return {
100
+ severity: 'info',
101
+ code: COLOR_FORMAT_CODE,
102
+ message: `Using deprecated color format: "${format}"`,
103
+ path,
104
+ suggestion: 'Consider using the full 6-digit hex format for better precision and consistency.',
105
+ example: `// Change from:\n// "${path}": "${value}"\n// To:\n// "${path}": "${expandHex(value)}"`
106
+ };
107
+ }
108
+ // Validate RGB values if applicable
109
+ if (format === 'rgb' || format === 'rgba') {
110
+ const match = value.match(format === 'rgb' ? COLOR_PATTERNS.rgb : COLOR_PATTERNS.rgba);
111
+ if (match) {
112
+ const r = parseInt(match[1], 10);
113
+ const g = parseInt(match[2], 10);
114
+ const b = parseInt(match[3], 10);
115
+ if (!validateRgbValues(r, g, b)) {
116
+ return {
117
+ severity: 'error',
118
+ code: COLOR_FORMAT_CODE,
119
+ message: `Invalid RGB values in color: "${value}"`,
120
+ path,
121
+ suggestion: 'RGB values must be between 0 and 255.',
122
+ example: `// Example:\n// "${path}": "rgb(255, 255, 255)"`
123
+ };
124
+ }
125
+ }
126
+ }
127
+ // Validate HSL values if applicable
128
+ if (format === 'hsl' || format === 'hsla') {
129
+ const match = value.match(format === 'hsl' ? COLOR_PATTERNS.hsl : COLOR_PATTERNS.hsla);
130
+ if (match) {
131
+ const h = parseInt(match[1], 10);
132
+ const s = parseInt(match[2], 10);
133
+ const l = parseInt(match[3], 10);
134
+ if (!validateHslHue(h) || !validateHslPercent(s, l)) {
135
+ return {
136
+ severity: 'error',
137
+ code: COLOR_FORMAT_CODE,
138
+ message: `Invalid HSL values in color: "${value}"`,
139
+ path,
140
+ suggestion: 'HSL hue must be 0-360, saturation and lightness must be 0-100%.',
141
+ example: `// Example:\n// "${path}": "hsl(0, 0%, 100%)"`
142
+ };
143
+ }
144
+ }
145
+ }
146
+ return null;
147
+ }
148
+ /**
149
+ * Expand a short hex color to full format
150
+ */
151
+ function expandHex(hex) {
152
+ if (COLOR_PATTERNS.hex3.test(hex)) {
153
+ return '#' + hex.slice(1).split('').map(c => c + c).join('');
154
+ }
155
+ if (COLOR_PATTERNS.hex4.test(hex)) {
156
+ const chars = hex.slice(1).split('');
157
+ return '#' + chars[0] + chars[0] + chars[1] + chars[1] + chars[2] + chars[2];
158
+ }
159
+ return hex;
160
+ }
161
+ /**
162
+ * Collect all color values from tokens
163
+ */
164
+ function collectColorValues(colors, path = 'colors') {
165
+ const results = [];
166
+ if (typeof colors === 'string') {
167
+ results.push({ path, value: colors });
168
+ }
169
+ else if (typeof colors === 'object' && colors !== null && !Array.isArray(colors)) {
170
+ for (const [key, value] of Object.entries(colors)) {
171
+ results.push(...collectColorValues(value, `${path}.${key}`));
172
+ }
173
+ }
174
+ return results;
175
+ }
176
+ /**
177
+ * Check for inconsistent color formats within a color family
178
+ */
179
+ function checkColorFormatConsistency(colorValues, severity = 'warning') {
180
+ const results = [];
181
+ // Group by color family (e.g., gray, blue, red)
182
+ const families = new Map();
183
+ for (const { path, value } of colorValues) {
184
+ const format = getColorFormat(value);
185
+ if (!format)
186
+ continue;
187
+ const pathParts = path.split('.');
188
+ const family = pathParts[1] || 'default';
189
+ if (!families.has(family)) {
190
+ families.set(family, []);
191
+ }
192
+ families.get(family).push({ path, value, format });
193
+ }
194
+ // Check each family for format consistency
195
+ for (const [family, values] of families.entries()) {
196
+ if (values.length < 2)
197
+ continue;
198
+ const formats = new Set(values.map(v => v.format));
199
+ if (formats.size > 1) {
200
+ const formatList = Array.from(formats).sort().join(', ');
201
+ results.push({
202
+ severity,
203
+ code: COLOR_FORMAT_CODE,
204
+ message: `Inconsistent color formats in "${family}" family: ${formatList}`,
205
+ path: `colors.${family}`,
206
+ suggestion: 'Use consistent color formats within a color family for better maintainability.',
207
+ example: `// Example - use hex6 format:\n// "colors.${family}.100": "#f3f4f6"\n// "colors.${family}.900": "#111827"`
208
+ });
209
+ }
210
+ }
211
+ return results;
212
+ }
213
+ /**
214
+ * Validate all color formats
215
+ */
216
+ export function validateColorFormat(tokens, severity = 'warning') {
217
+ const results = [];
218
+ if (!tokens.colors) {
219
+ return results;
220
+ }
221
+ // Collect all color values
222
+ const colorValues = collectColorValues(tokens.colors);
223
+ // Validate each color value
224
+ for (const { path, value } of colorValues) {
225
+ const result = validateColorValue(path, value, severity);
226
+ if (result) {
227
+ results.push(result);
228
+ }
229
+ }
230
+ // Check for format consistency
231
+ results.push(...checkColorFormatConsistency(colorValues, severity));
232
+ return results;
233
+ }
234
+ /**
235
+ * Get a summary of color format issues
236
+ */
237
+ export function getColorFormatSummary(issues) {
238
+ if (issues.length === 0) {
239
+ return 'No color format issues found.';
240
+ }
241
+ const summary = [];
242
+ summary.push(`Found ${issues.length} color format issue${issues.length > 1 ? 's' : ''}:`);
243
+ for (const issue of issues) {
244
+ summary.push(` • ${issue.path}: ${issue.issue}`);
245
+ summary.push(` ${issue.details}`);
246
+ summary.push(` 💡 ${issue.suggestion}`);
247
+ }
248
+ return summary.join('\n');
249
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Main validation entry point
3
+ * Coordinates all non-blocking token validations
4
+ */
5
+ import type { ValidationReport, ValidationConfig, TokensForValidation } from './types.js';
6
+ /**
7
+ * Default validation configuration
8
+ */
9
+ export declare const DEFAULT_VALIDATION_CONFIG: ValidationConfig;
10
+ /**
11
+ * Run all enabled validations on tokens
12
+ */
13
+ export declare function runValidations(tokens: TokensForValidation, config?: ValidationConfig): ValidationReport;
14
+ /**
15
+ * Run validations and return only warnings and errors (filter out info)
16
+ */
17
+ export declare function runValidationsWithoutInfo(tokens: TokensForValidation, config?: ValidationConfig): ValidationReport;
18
+ /**
19
+ * Get a human-readable summary of the validation report
20
+ */
21
+ export declare function getValidationSummary(report: ValidationReport): string;
22
+ /**
23
+ * Print validation results grouped by severity
24
+ */
25
+ export declare function printValidationResults(report: ValidationReport): void;
26
+ /**
27
+ * Check if validation report has any results
28
+ */
29
+ export declare function hasValidationResults(report: ValidationReport): boolean;
30
+ /**
31
+ * Check if validation report has errors
32
+ */
33
+ export declare function hasValidationErrors(report: ValidationReport): boolean;
34
+ /**
35
+ * Check if validation report has warnings
36
+ */
37
+ export declare function hasValidationWarnings(report: ValidationReport): boolean;
38
+ /**
39
+ * Check if validation report has info messages
40
+ */
41
+ export declare function hasValidationInfo(report: ValidationReport): boolean;
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAEhB,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AASpB;;GAEG;AACH,eAAO,MAAM,yBAAyB,EAAE,gBAUvC,CAAC;AAEF;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,mBAAmB,EAC3B,MAAM,GAAE,gBAA4C,GACnD,gBAAgB,CA8DlB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,mBAAmB,EAC3B,MAAM,GAAE,gBAA4C,GACnD,gBAAgB,CAalB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CA2BrE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CA8DrE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAEtE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAErE;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAEvE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAEnE"}