@ngcorex/css 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/dist/constraints/constraint-error.d.ts.map +1 -1
- package/dist/constraints/constraint-error.js +2 -2
- package/dist/engine/build-css.js +2 -2
- package/dist/errors/ngcorex-error.d.ts +68 -1
- package/dist/errors/ngcorex-error.d.ts.map +1 -1
- package/dist/errors/ngcorex-error.js +135 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/tokens/normalize-colors.js +2 -2
- package/dist/tokens/normalize.d.ts.map +1 -1
- package/dist/tokens/normalize.js +2 -2
- package/dist/validation/color-format.d.ts +22 -0
- package/dist/validation/color-format.d.ts.map +1 -0
- package/dist/validation/color-format.js +249 -0
- package/dist/validation/index.d.ts +42 -0
- package/dist/validation/index.d.ts.map +1 -0
- package/dist/validation/index.js +206 -0
- package/dist/validation/scale-consistency.d.ts +14 -0
- package/dist/validation/scale-consistency.d.ts.map +1 -0
- package/dist/validation/scale-consistency.js +215 -0
- package/dist/validation/shadow-format.d.ts +14 -0
- package/dist/validation/shadow-format.d.ts.map +1 -0
- package/dist/validation/shadow-format.js +217 -0
- package/dist/validation/spacing-format.d.ts +14 -0
- package/dist/validation/spacing-format.d.ts.map +1 -0
- package/dist/validation/spacing-format.js +173 -0
- package/dist/validation/token-duplicates.d.ts +24 -0
- package/dist/validation/token-duplicates.d.ts.map +1 -0
- package/dist/validation/token-duplicates.js +149 -0
- package/dist/validation/types.d.ts +160 -0
- package/dist/validation/types.d.ts.map +1 -0
- package/dist/validation/types.js +4 -0
- package/dist/validation/z-index-logic.d.ts +14 -0
- package/dist/validation/z-index-logic.d.ts.map +1 -0
- package/dist/validation/z-index-logic.js +230 -0
- package/package.json +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spacing-format.d.ts","sourceRoot":"","sources":["../../src/validation/spacing-format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAgKpB;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,GAAE,MAAM,GAAG,SAAS,GAAG,OAAmB,GACjD,gBAAgB,EAAE,CAqBpB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAe5E"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spacing format validation
|
|
3
|
+
* Checks for valid CSS spacing units and consistency
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Validation code for spacing format
|
|
7
|
+
*/
|
|
8
|
+
const SPACING_FORMAT_CODE = 'SPACING_FORMAT';
|
|
9
|
+
/**
|
|
10
|
+
* Common CSS spacing units
|
|
11
|
+
*/
|
|
12
|
+
const VALID_SPACING_UNITS = new Set([
|
|
13
|
+
'px', 'rem', 'em', '%', 'vh', 'vw', 'vmin', 'vmax', 'ch', 'ex', 'fr'
|
|
14
|
+
]);
|
|
15
|
+
/**
|
|
16
|
+
* Recommended spacing units for design systems
|
|
17
|
+
*/
|
|
18
|
+
const RECOMMENDED_SPACING_UNITS = new Set(['rem', 'px']);
|
|
19
|
+
/**
|
|
20
|
+
* Parse a spacing value to extract numeric value and unit
|
|
21
|
+
*/
|
|
22
|
+
function parseSpacingValue(value) {
|
|
23
|
+
let raw;
|
|
24
|
+
let numericValue;
|
|
25
|
+
let unit;
|
|
26
|
+
if (typeof value === 'number') {
|
|
27
|
+
raw = value.toString();
|
|
28
|
+
numericValue = value;
|
|
29
|
+
unit = '';
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
raw = value;
|
|
33
|
+
const match = value.match(/^(-?\d*\.?\d+)(px|rem|em|%|vh|vw|vmin|vmax|ch|ex|fr)?$/);
|
|
34
|
+
if (!match)
|
|
35
|
+
return null;
|
|
36
|
+
numericValue = parseFloat(match[1]);
|
|
37
|
+
unit = match[2] || '';
|
|
38
|
+
}
|
|
39
|
+
return { value: numericValue, unit, raw };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if a spacing unit is valid
|
|
43
|
+
*/
|
|
44
|
+
function isValidSpacingUnit(unit) {
|
|
45
|
+
if (unit === '')
|
|
46
|
+
return true; // Unitless values are valid
|
|
47
|
+
return VALID_SPACING_UNITS.has(unit);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if a spacing unit is recommended
|
|
51
|
+
*/
|
|
52
|
+
function isRecommendedSpacingUnit(unit) {
|
|
53
|
+
if (unit === '')
|
|
54
|
+
return false; // Unitless values are not recommended for spacing
|
|
55
|
+
return RECOMMENDED_SPACING_UNITS.has(unit);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Validate a single spacing value
|
|
59
|
+
*/
|
|
60
|
+
function validateSpacingValue(path, value, severity = 'warning') {
|
|
61
|
+
const parsed = parseSpacingValue(value);
|
|
62
|
+
if (!parsed) {
|
|
63
|
+
return {
|
|
64
|
+
severity: 'error',
|
|
65
|
+
code: SPACING_FORMAT_CODE,
|
|
66
|
+
message: `Invalid spacing value: "${value}"`,
|
|
67
|
+
path,
|
|
68
|
+
suggestion: 'Use a valid CSS spacing value: number, or number with unit (px, rem, em, etc.).',
|
|
69
|
+
example: `// Examples:\n// "${path}": "1rem"\n// "${path}": "16px"\n// "${path}": "0.5rem"`
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const { value: numericValue, unit } = parsed;
|
|
73
|
+
// Check for negative values (not typically valid for spacing)
|
|
74
|
+
if (numericValue < 0) {
|
|
75
|
+
return {
|
|
76
|
+
severity: 'warning',
|
|
77
|
+
code: SPACING_FORMAT_CODE,
|
|
78
|
+
message: `Negative spacing value: "${value}"`,
|
|
79
|
+
path,
|
|
80
|
+
suggestion: 'Spacing values should typically be positive. Use negative values only for specific use cases.',
|
|
81
|
+
example: `// Change from:\n// "${path}": "${value}"\n// To:\n// "${path}": "${Math.abs(numericValue)}${unit}"`
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// Check for valid unit
|
|
85
|
+
if (!isValidSpacingUnit(unit)) {
|
|
86
|
+
return {
|
|
87
|
+
severity: 'error',
|
|
88
|
+
code: SPACING_FORMAT_CODE,
|
|
89
|
+
message: `Invalid spacing unit: "${unit}"`,
|
|
90
|
+
path,
|
|
91
|
+
suggestion: `Use a valid CSS spacing unit: ${Array.from(VALID_SPACING_UNITS).join(', ')}.`,
|
|
92
|
+
example: `// Examples:\n// "${path}": "1rem"\n// "${path}": "16px"`
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// Check for recommended unit
|
|
96
|
+
if (unit !== '' && !isRecommendedSpacingUnit(unit)) {
|
|
97
|
+
return {
|
|
98
|
+
severity: 'info',
|
|
99
|
+
code: SPACING_FORMAT_CODE,
|
|
100
|
+
message: `Using non-recommended spacing unit: "${unit}"`,
|
|
101
|
+
path,
|
|
102
|
+
suggestion: `Consider using recommended units (${Array.from(RECOMMENDED_SPACING_UNITS).join(', ')}) for better consistency.`,
|
|
103
|
+
example: `// Change from:\n// "${path}": "${value}"\n// To:\n// "${path}": "${numericValue}rem"`
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check for inconsistent spacing units
|
|
110
|
+
*/
|
|
111
|
+
function checkSpacingUnitConsistency(spacing, severity = 'warning') {
|
|
112
|
+
const results = [];
|
|
113
|
+
const units = new Map(); // unit -> count
|
|
114
|
+
for (const [key, value] of Object.entries(spacing)) {
|
|
115
|
+
const parsed = parseSpacingValue(value);
|
|
116
|
+
if (parsed) {
|
|
117
|
+
const { unit } = parsed;
|
|
118
|
+
const count = units.get(unit) || 0;
|
|
119
|
+
units.set(unit, count + 1);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Check if there are mixed units
|
|
123
|
+
if (units.size > 1) {
|
|
124
|
+
const unitList = Array.from(units.entries())
|
|
125
|
+
.map(([unit, count]) => `${unit || 'unitless'} (${count})`)
|
|
126
|
+
.join(', ');
|
|
127
|
+
results.push({
|
|
128
|
+
severity,
|
|
129
|
+
code: SPACING_FORMAT_CODE,
|
|
130
|
+
message: `Mixed spacing units detected: ${unitList}`,
|
|
131
|
+
path: 'spacing',
|
|
132
|
+
suggestion: 'Use consistent spacing units for better maintainability. Consider using rem for responsive design.',
|
|
133
|
+
example: `// Example - use rem for all spacing:\n// "spacing.xs": "0.25rem"\n// "spacing.sm": "0.5rem"\n// "spacing.md": "1rem"`
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return results;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Validate all spacing formats
|
|
140
|
+
*/
|
|
141
|
+
export function validateSpacingFormat(tokens, severity = 'warning') {
|
|
142
|
+
const results = [];
|
|
143
|
+
if (!tokens.spacing) {
|
|
144
|
+
return results;
|
|
145
|
+
}
|
|
146
|
+
const spacing = tokens.spacing;
|
|
147
|
+
// Validate each spacing value
|
|
148
|
+
for (const [key, value] of Object.entries(spacing)) {
|
|
149
|
+
const result = validateSpacingValue(`spacing.${key}`, value, severity);
|
|
150
|
+
if (result) {
|
|
151
|
+
results.push(result);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Check for unit consistency
|
|
155
|
+
results.push(...checkSpacingUnitConsistency(spacing, severity));
|
|
156
|
+
return results;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get a summary of spacing format issues
|
|
160
|
+
*/
|
|
161
|
+
export function getSpacingFormatSummary(issues) {
|
|
162
|
+
if (issues.length === 0) {
|
|
163
|
+
return 'No spacing format issues found.';
|
|
164
|
+
}
|
|
165
|
+
const summary = [];
|
|
166
|
+
summary.push(`Found ${issues.length} spacing format issue${issues.length > 1 ? 's' : ''}:`);
|
|
167
|
+
for (const issue of issues) {
|
|
168
|
+
summary.push(` • ${issue.path}: ${issue.issue}`);
|
|
169
|
+
summary.push(` ${issue.details}`);
|
|
170
|
+
summary.push(` 💡 ${issue.suggestion}`);
|
|
171
|
+
}
|
|
172
|
+
return summary.join('\n');
|
|
173
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duplicate token detection
|
|
3
|
+
* Checks for duplicate token names WITHIN the same category
|
|
4
|
+
* Cross-category duplicates are allowed (e.g., radius.sm, typography.fontSize.sm)
|
|
5
|
+
*/
|
|
6
|
+
import type { ValidationResult, TokensForValidation, DuplicateToken } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Find all duplicate tokens within each category
|
|
9
|
+
* Cross-category duplicates are NOT flagged (per spec X1)
|
|
10
|
+
*/
|
|
11
|
+
export declare function findDuplicateTokens(tokens: TokensForValidation, file?: string): DuplicateToken[];
|
|
12
|
+
/**
|
|
13
|
+
* Convert duplicate tokens to validation results
|
|
14
|
+
*/
|
|
15
|
+
export declare function duplicateTokensToValidationResults(duplicates: DuplicateToken[], severity?: 'info' | 'warning' | 'error'): ValidationResult[];
|
|
16
|
+
/**
|
|
17
|
+
* Validate tokens for duplicates
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateDuplicateTokens(tokens: TokensForValidation, file?: string, severity?: 'info' | 'warning' | 'error'): ValidationResult[];
|
|
20
|
+
/**
|
|
21
|
+
* Get a summary of duplicate tokens
|
|
22
|
+
*/
|
|
23
|
+
export declare function getDuplicateTokensSummary(duplicates: DuplicateToken[]): string;
|
|
24
|
+
//# sourceMappingURL=token-duplicates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-duplicates.d.ts","sourceRoot":"","sources":["../../src/validation/token-duplicates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EAEnB,cAAc,EACf,MAAM,YAAY,CAAC;AAOpB;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,EAAE,IAAI,GAAE,MAAsB,GAAG,cAAc,EAAE,CA+B/G;AAqFD;;GAEG;AACH,wBAAgB,kCAAkC,CAChD,UAAU,EAAE,cAAc,EAAE,EAC5B,QAAQ,GAAE,MAAM,GAAG,SAAS,GAAG,OAAmB,GACjD,gBAAgB,EAAE,CAmBpB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,mBAAmB,EAC3B,IAAI,GAAE,MAAsB,EAC5B,QAAQ,GAAE,MAAM,GAAG,SAAS,GAAG,OAAmB,GACjD,gBAAgB,EAAE,CAGpB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,cAAc,EAAE,GAAG,MAAM,CAgB9E"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duplicate token detection
|
|
3
|
+
* Checks for duplicate token names WITHIN the same category
|
|
4
|
+
* Cross-category duplicates are allowed (e.g., radius.sm, typography.fontSize.sm)
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Validation code for duplicate tokens
|
|
8
|
+
*/
|
|
9
|
+
const DUPLICATE_TOKEN_CODE = 'DUPLICATE_TOKEN';
|
|
10
|
+
/**
|
|
11
|
+
* Find all duplicate tokens within each category
|
|
12
|
+
* Cross-category duplicates are NOT flagged (per spec X1)
|
|
13
|
+
*/
|
|
14
|
+
export function findDuplicateTokens(tokens, file = 'tokens.json') {
|
|
15
|
+
const duplicates = [];
|
|
16
|
+
// Process each category separately
|
|
17
|
+
const categories = [
|
|
18
|
+
{ name: 'spacing' },
|
|
19
|
+
{ name: 'radius' },
|
|
20
|
+
{ name: 'zIndex' },
|
|
21
|
+
{ name: 'shadows' },
|
|
22
|
+
{ name: 'colors', isNested: true },
|
|
23
|
+
{ name: 'typography', isNested: true }
|
|
24
|
+
];
|
|
25
|
+
for (const { name, isNested } of categories) {
|
|
26
|
+
const category = tokens[name];
|
|
27
|
+
if (!category)
|
|
28
|
+
continue;
|
|
29
|
+
if (isNested) {
|
|
30
|
+
// Handle nested token structures (colors, typography)
|
|
31
|
+
if (typeof category === 'object' && category !== null) {
|
|
32
|
+
duplicates.push(...findDuplicatesInNested(category, name, file));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Handle flat token structures (spacing, radius, zIndex, shadows)
|
|
37
|
+
if (typeof category === 'object' && category !== null) {
|
|
38
|
+
duplicates.push(...findDuplicatesInFlat(category, name, file));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return duplicates;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Find duplicates in flat token structures
|
|
46
|
+
*/
|
|
47
|
+
function findDuplicatesInFlat(obj, category, file) {
|
|
48
|
+
const duplicates = [];
|
|
49
|
+
const keyMap = new Map();
|
|
50
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
51
|
+
const location = {
|
|
52
|
+
file,
|
|
53
|
+
category,
|
|
54
|
+
key,
|
|
55
|
+
path: `${category}.${key}`
|
|
56
|
+
};
|
|
57
|
+
if (!keyMap.has(key)) {
|
|
58
|
+
keyMap.set(key, []);
|
|
59
|
+
}
|
|
60
|
+
keyMap.get(key).push(location);
|
|
61
|
+
}
|
|
62
|
+
// Find duplicates within this category
|
|
63
|
+
for (const [name, locations] of keyMap.entries()) {
|
|
64
|
+
if (locations.length > 1) {
|
|
65
|
+
duplicates.push({ name, locations });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return duplicates;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Find duplicates in nested token structures
|
|
72
|
+
* Checks for duplicates at each nesting level separately
|
|
73
|
+
*/
|
|
74
|
+
function findDuplicatesInNested(obj, category, file, path = category) {
|
|
75
|
+
const duplicates = [];
|
|
76
|
+
if (typeof obj !== 'object' || obj === null)
|
|
77
|
+
return duplicates;
|
|
78
|
+
const keyMap = new Map();
|
|
79
|
+
// Check for duplicates at current level
|
|
80
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
81
|
+
const location = {
|
|
82
|
+
file,
|
|
83
|
+
category,
|
|
84
|
+
key,
|
|
85
|
+
path: `${path}.${key}`
|
|
86
|
+
};
|
|
87
|
+
if (!keyMap.has(key)) {
|
|
88
|
+
keyMap.set(key, []);
|
|
89
|
+
}
|
|
90
|
+
keyMap.get(key).push(location);
|
|
91
|
+
}
|
|
92
|
+
// Add duplicates found at this level
|
|
93
|
+
for (const [name, locations] of keyMap.entries()) {
|
|
94
|
+
if (locations.length > 1) {
|
|
95
|
+
duplicates.push({ name, locations });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Recursively check nested levels
|
|
99
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
100
|
+
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
101
|
+
duplicates.push(...findDuplicatesInNested(value, category, file, `${path}.${key}`));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return duplicates;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Convert duplicate tokens to validation results
|
|
108
|
+
*/
|
|
109
|
+
export function duplicateTokensToValidationResults(duplicates, severity = 'warning') {
|
|
110
|
+
const results = [];
|
|
111
|
+
for (const duplicate of duplicates) {
|
|
112
|
+
const locationsStr = duplicate.locations
|
|
113
|
+
.map(loc => loc.path)
|
|
114
|
+
.join(', ');
|
|
115
|
+
results.push({
|
|
116
|
+
severity,
|
|
117
|
+
code: DUPLICATE_TOKEN_CODE,
|
|
118
|
+
message: `Duplicate token name "${duplicate.name}" found in multiple locations`,
|
|
119
|
+
path: duplicate.locations[0].path,
|
|
120
|
+
suggestion: `Rename one of the tokens to avoid conflicts. Found in: ${locationsStr}`,
|
|
121
|
+
example: `// Example:\n// Rename ${duplicate.locations[0].path} to "${duplicate.name}Alt"\n// or rename ${duplicate.locations[1].path} to "${duplicate.name}Alt"`
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Validate tokens for duplicates
|
|
128
|
+
*/
|
|
129
|
+
export function validateDuplicateTokens(tokens, file = 'tokens.json', severity = 'warning') {
|
|
130
|
+
const duplicates = findDuplicateTokens(tokens, file);
|
|
131
|
+
return duplicateTokensToValidationResults(duplicates, severity);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get a summary of duplicate tokens
|
|
135
|
+
*/
|
|
136
|
+
export function getDuplicateTokensSummary(duplicates) {
|
|
137
|
+
if (duplicates.length === 0) {
|
|
138
|
+
return 'No duplicate tokens found.';
|
|
139
|
+
}
|
|
140
|
+
const summary = [];
|
|
141
|
+
summary.push(`Found ${duplicates.length} duplicate token name${duplicates.length > 1 ? 's' : ''}:`);
|
|
142
|
+
for (const duplicate of duplicates) {
|
|
143
|
+
summary.push(` • "${duplicate.name}" appears ${duplicate.locations.length} times:`);
|
|
144
|
+
for (const loc of duplicate.locations) {
|
|
145
|
+
summary.push(` - ${loc.path}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return summary.join('\n');
|
|
149
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types and interfaces for non-blocking token validation
|
|
3
|
+
*/
|
|
4
|
+
import type { TokenScale, NestedTokenScale } from '../tokens/types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Validation severity level
|
|
7
|
+
*/
|
|
8
|
+
export type ValidationSeverity = 'info' | 'warning' | 'error';
|
|
9
|
+
/**
|
|
10
|
+
* Validation result
|
|
11
|
+
*/
|
|
12
|
+
export interface ValidationResult {
|
|
13
|
+
severity: ValidationSeverity;
|
|
14
|
+
code: string;
|
|
15
|
+
message: string;
|
|
16
|
+
path: string;
|
|
17
|
+
suggestion?: string;
|
|
18
|
+
example?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validation report containing all validation results
|
|
22
|
+
*/
|
|
23
|
+
export interface ValidationReport {
|
|
24
|
+
valid: boolean;
|
|
25
|
+
results: ValidationResult[];
|
|
26
|
+
summary: {
|
|
27
|
+
info: number;
|
|
28
|
+
warning: number;
|
|
29
|
+
error: number;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Token location for validation
|
|
34
|
+
*/
|
|
35
|
+
export interface TokenLocation {
|
|
36
|
+
file: string;
|
|
37
|
+
category: string;
|
|
38
|
+
key: string;
|
|
39
|
+
path: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Duplicate token entry
|
|
43
|
+
*/
|
|
44
|
+
export interface DuplicateToken {
|
|
45
|
+
name: string;
|
|
46
|
+
locations: TokenLocation[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Scale consistency check result
|
|
50
|
+
*/
|
|
51
|
+
export interface ScaleConsistencyIssue {
|
|
52
|
+
scaleName: string;
|
|
53
|
+
category: string;
|
|
54
|
+
issue: 'non_monotonic' | 'gaps' | 'unexpected_values';
|
|
55
|
+
details: string;
|
|
56
|
+
suggestion: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Color format validation result
|
|
60
|
+
*/
|
|
61
|
+
export interface ColorFormatIssue {
|
|
62
|
+
path: string;
|
|
63
|
+
value: string;
|
|
64
|
+
issue: 'invalid_format' | 'inconsistent_format' | 'deprecated_format';
|
|
65
|
+
details: string;
|
|
66
|
+
suggestion: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Spacing format validation result
|
|
70
|
+
*/
|
|
71
|
+
export interface SpacingFormatIssue {
|
|
72
|
+
path: string;
|
|
73
|
+
value: string;
|
|
74
|
+
issue: 'invalid_unit' | 'inconsistent_units' | 'mixed_units';
|
|
75
|
+
details: string;
|
|
76
|
+
suggestion: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Shadow format validation result
|
|
80
|
+
*/
|
|
81
|
+
export interface ShadowFormatIssue {
|
|
82
|
+
path: string;
|
|
83
|
+
value: string;
|
|
84
|
+
issue: 'invalid_syntax' | 'invalid_color' | 'invalid_offset' | 'invalid_blur' | 'invalid_spread';
|
|
85
|
+
details: string;
|
|
86
|
+
suggestion: string;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Z-index logic validation result
|
|
90
|
+
*/
|
|
91
|
+
export interface ZIndexLogicIssue {
|
|
92
|
+
path: string;
|
|
93
|
+
issue: 'inconsistent_layering' | 'overlapping_values' | 'negative_values';
|
|
94
|
+
details: string;
|
|
95
|
+
suggestion: string;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validation configuration
|
|
99
|
+
*/
|
|
100
|
+
export interface ValidationConfig {
|
|
101
|
+
/**
|
|
102
|
+
* Enable/disable specific validations
|
|
103
|
+
*/
|
|
104
|
+
enabled: {
|
|
105
|
+
duplicateTokens: boolean;
|
|
106
|
+
scaleConsistency: boolean;
|
|
107
|
+
colorFormat: boolean;
|
|
108
|
+
spacingFormat: boolean;
|
|
109
|
+
shadowFormat: boolean;
|
|
110
|
+
zIndexLogic: boolean;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Severity level for non-blocking validations
|
|
114
|
+
* Note: These are non-blocking and will only produce warnings/info
|
|
115
|
+
*/
|
|
116
|
+
severity: ValidationSeverity;
|
|
117
|
+
/**
|
|
118
|
+
* Custom validators
|
|
119
|
+
*/
|
|
120
|
+
customValidators?: CustomValidator[];
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Custom validator interface
|
|
124
|
+
*/
|
|
125
|
+
export interface CustomValidator {
|
|
126
|
+
name: string;
|
|
127
|
+
validate: (tokens: TokensForValidation) => ValidationResult[];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Tokens structure for validation
|
|
131
|
+
*/
|
|
132
|
+
export interface TokensForValidation {
|
|
133
|
+
spacing?: TokenScale;
|
|
134
|
+
colors?: NestedTokenScale;
|
|
135
|
+
radius?: TokenScale;
|
|
136
|
+
zIndex?: TokenScale;
|
|
137
|
+
typography?: {
|
|
138
|
+
fontSize?: TokenScale;
|
|
139
|
+
fontWeight?: TokenScale;
|
|
140
|
+
lineHeight?: TokenScale;
|
|
141
|
+
};
|
|
142
|
+
shadows?: TokenScale;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Validation context
|
|
146
|
+
*/
|
|
147
|
+
export interface ValidationContext {
|
|
148
|
+
file: string;
|
|
149
|
+
tokens: TokensForValidation;
|
|
150
|
+
config: ValidationConfig;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Expected scale order for consistency checks
|
|
154
|
+
*/
|
|
155
|
+
export interface ScaleOrder {
|
|
156
|
+
category: string;
|
|
157
|
+
expectedOrder: string[];
|
|
158
|
+
isNumeric?: boolean;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/validation/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Z-index logic validation
|
|
3
|
+
* Checks for logical layering and value consistency
|
|
4
|
+
*/
|
|
5
|
+
import type { ValidationResult, TokensForValidation, ZIndexLogicIssue } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Validate all z-index logic
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateZIndexLogic(tokens: TokensForValidation, severity?: 'info' | 'warning' | 'error'): ValidationResult[];
|
|
10
|
+
/**
|
|
11
|
+
* Get a summary of z-index logic issues
|
|
12
|
+
*/
|
|
13
|
+
export declare function getZIndexLogicSummary(issues: ZIndexLogicIssue[]): string;
|
|
14
|
+
//# sourceMappingURL=z-index-logic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"z-index-logic.d.ts","sourceRoot":"","sources":["../../src/validation/z-index-logic.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAyOpB;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,GAAE,MAAM,GAAG,SAAS,GAAG,OAAmB,GACjD,gBAAgB,EAAE,CA2BpB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAexE"}
|