@terrazzo/parser 0.3.5 → 0.5.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/CHANGELOG.md +41 -11
- package/dist/build/index.d.ts +1 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +11 -10
- package/dist/build/index.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +42 -21
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/lib/code-frame.d.ts +1 -0
- package/dist/lib/code-frame.d.ts.map +1 -0
- package/dist/lint/index.d.ts +1 -0
- package/dist/lint/index.d.ts.map +1 -0
- package/dist/lint/index.js +8 -5
- package/dist/lint/index.js.map +1 -1
- package/dist/lint/plugin-core/index.d.ts +1 -0
- package/dist/lint/plugin-core/index.d.ts.map +1 -0
- package/dist/lint/plugin-core/lib/docs.d.ts +1 -0
- package/dist/lint/plugin-core/lib/docs.d.ts.map +1 -0
- package/dist/lint/plugin-core/rules/a11y-min-contrast.d.ts +1 -0
- package/dist/lint/plugin-core/rules/a11y-min-contrast.d.ts.map +1 -0
- package/dist/lint/plugin-core/rules/a11y-min-font-size.d.ts +1 -0
- package/dist/lint/plugin-core/rules/a11y-min-font-size.d.ts.map +1 -0
- package/dist/lint/plugin-core/rules/colorspace.d.ts +1 -0
- package/dist/lint/plugin-core/rules/colorspace.d.ts.map +1 -0
- package/dist/lint/plugin-core/rules/consistent-naming.d.ts +1 -0
- package/dist/lint/plugin-core/rules/consistent-naming.d.ts.map +1 -0
- package/dist/lint/plugin-core/rules/descriptions.d.ts +1 -0
- package/dist/lint/plugin-core/rules/descriptions.d.ts.map +1 -0
- package/dist/lint/plugin-core/rules/duplicate-values.d.ts +1 -0
- package/dist/lint/plugin-core/rules/duplicate-values.d.ts.map +1 -0
- package/dist/lint/plugin-core/rules/max-gamut.d.ts +1 -0
- package/dist/lint/plugin-core/rules/max-gamut.d.ts.map +1 -0
- package/dist/lint/plugin-core/rules/required-children.d.ts +1 -0
- package/dist/lint/plugin-core/rules/required-children.d.ts.map +1 -0
- package/dist/lint/plugin-core/rules/required-modes.d.ts +1 -0
- package/dist/lint/plugin-core/rules/required-modes.d.ts.map +1 -0
- package/dist/lint/plugin-core/rules/required-typography-properties.d.ts +1 -0
- package/dist/lint/plugin-core/rules/required-typography-properties.d.ts.map +1 -0
- package/dist/logger.d.ts +4 -3
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +25 -14
- package/dist/logger.js.map +1 -1
- package/dist/parse/alias.d.ts +13 -3
- package/dist/parse/alias.d.ts.map +1 -0
- package/dist/parse/alias.js +94 -43
- package/dist/parse/alias.js.map +1 -1
- package/dist/parse/index.d.ts +1 -0
- package/dist/parse/index.d.ts.map +1 -0
- package/dist/parse/index.js +58 -25
- package/dist/parse/index.js.map +1 -1
- package/dist/parse/json.d.ts +3 -3
- package/dist/parse/json.d.ts.map +1 -0
- package/dist/parse/json.js +5 -7
- package/dist/parse/json.js.map +1 -1
- package/dist/parse/normalize.d.ts +1 -0
- package/dist/parse/normalize.d.ts.map +1 -0
- package/dist/parse/normalize.js +8 -6
- package/dist/parse/normalize.js.map +1 -1
- package/dist/parse/validate.d.ts +1 -0
- package/dist/parse/validate.d.ts.map +1 -0
- package/dist/parse/validate.js +194 -110
- package/dist/parse/validate.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/build/index.ts +11 -10
- package/src/config.ts +42 -22
- package/src/lint/index.ts +8 -6
- package/src/logger.ts +30 -20
- package/src/parse/alias.ts +114 -45
- package/src/parse/index.ts +59 -28
- package/src/parse/json.ts +6 -8
- package/src/parse/normalize.ts +8 -6
- package/src/parse/validate.ts +204 -110
package/dist/parse/validate.js
CHANGED
|
@@ -60,33 +60,54 @@ function isMaybeAlias(node) {
|
|
|
60
60
|
/** Assert object members match given types */
|
|
61
61
|
function validateMembersAs($value, properties, node, { filename, src, logger }) {
|
|
62
62
|
const members = getObjMembers($value);
|
|
63
|
-
for (const
|
|
64
|
-
const { validator, required } =
|
|
65
|
-
if (!members[
|
|
63
|
+
for (const [name, value] of Object.entries(properties)) {
|
|
64
|
+
const { validator, required } = value;
|
|
65
|
+
if (!members[name]) {
|
|
66
66
|
if (required) {
|
|
67
|
-
logger.error({
|
|
67
|
+
logger.error({
|
|
68
|
+
group: 'parser',
|
|
69
|
+
label: 'validate',
|
|
70
|
+
message: `Missing required property "${name}"`,
|
|
71
|
+
filename,
|
|
72
|
+
node: $value,
|
|
73
|
+
src,
|
|
74
|
+
});
|
|
68
75
|
}
|
|
69
76
|
continue;
|
|
70
77
|
}
|
|
71
|
-
const
|
|
72
|
-
if (isMaybeAlias(
|
|
73
|
-
validateAliasSyntax(
|
|
78
|
+
const memberValue = members[name];
|
|
79
|
+
if (isMaybeAlias(memberValue)) {
|
|
80
|
+
validateAliasSyntax(memberValue, node, { filename, src, logger });
|
|
74
81
|
}
|
|
75
82
|
else {
|
|
76
|
-
validator(
|
|
83
|
+
validator(memberValue, node, { filename, src, logger });
|
|
77
84
|
}
|
|
78
85
|
}
|
|
79
86
|
}
|
|
80
87
|
/** Verify an Alias $value is formatted correctly */
|
|
81
88
|
export function validateAliasSyntax($value, _node, { filename, src, logger }) {
|
|
82
89
|
if ($value.type !== 'String' || !isAlias($value.value)) {
|
|
83
|
-
logger.error({
|
|
90
|
+
logger.error({
|
|
91
|
+
group: 'parser',
|
|
92
|
+
label: 'validate',
|
|
93
|
+
message: `Invalid alias: ${print($value)}`,
|
|
94
|
+
filename,
|
|
95
|
+
node: $value,
|
|
96
|
+
src,
|
|
97
|
+
});
|
|
84
98
|
}
|
|
85
99
|
}
|
|
86
100
|
/** Verify a Border token is valid */
|
|
87
101
|
export function validateBorder($value, node, { filename, src, logger }) {
|
|
88
102
|
if ($value.type !== 'Object') {
|
|
89
|
-
logger.error({
|
|
103
|
+
logger.error({
|
|
104
|
+
group: 'parser',
|
|
105
|
+
label: 'validate',
|
|
106
|
+
message: `Expected object, received ${$value.type}`,
|
|
107
|
+
filename,
|
|
108
|
+
node: $value,
|
|
109
|
+
src,
|
|
110
|
+
});
|
|
90
111
|
}
|
|
91
112
|
else {
|
|
92
113
|
validateMembersAs($value, {
|
|
@@ -98,6 +119,7 @@ export function validateBorder($value, node, { filename, src, logger }) {
|
|
|
98
119
|
}
|
|
99
120
|
/** Verify a Color token is valid */
|
|
100
121
|
export function validateColor($value, node, { filename, src, logger }) {
|
|
122
|
+
const baseMessage = { group: 'parser', label: 'validate', filename, node: $value, src };
|
|
101
123
|
if ($value.type === 'String') {
|
|
102
124
|
// TODO: enable when object notation is finalized
|
|
103
125
|
// logger.warn({
|
|
@@ -107,7 +129,7 @@ export function validateColor($value, node, { filename, src, logger }) {
|
|
|
107
129
|
// src,
|
|
108
130
|
// });
|
|
109
131
|
if ($value.value === '') {
|
|
110
|
-
logger.error({ message: 'Expected color, received empty string'
|
|
132
|
+
logger.error({ ...baseMessage, message: 'Expected color, received empty string' });
|
|
111
133
|
}
|
|
112
134
|
}
|
|
113
135
|
else if ($value.type === 'Object') {
|
|
@@ -115,10 +137,18 @@ export function validateColor($value, node, { filename, src, logger }) {
|
|
|
115
137
|
colorSpace: {
|
|
116
138
|
validator: (v) => {
|
|
117
139
|
if (v.type !== 'String') {
|
|
118
|
-
logger.error({
|
|
140
|
+
logger.error({
|
|
141
|
+
...baseMessage,
|
|
142
|
+
message: `Expected string, received ${print(v)}`,
|
|
143
|
+
node: v,
|
|
144
|
+
});
|
|
119
145
|
}
|
|
120
146
|
if (!VALID_COLORSPACES.has(v.value)) {
|
|
121
|
-
logger.error({
|
|
147
|
+
logger.error({
|
|
148
|
+
...baseMessage,
|
|
149
|
+
message: `Unsupported colorspace ${print(v)}`,
|
|
150
|
+
node: v,
|
|
151
|
+
});
|
|
122
152
|
}
|
|
123
153
|
},
|
|
124
154
|
required: true,
|
|
@@ -126,24 +156,26 @@ export function validateColor($value, node, { filename, src, logger }) {
|
|
|
126
156
|
channels: {
|
|
127
157
|
validator: (v) => {
|
|
128
158
|
if (v.type !== 'Array') {
|
|
129
|
-
logger.error({
|
|
159
|
+
logger.error({
|
|
160
|
+
...baseMessage,
|
|
161
|
+
message: `Expected array, received ${print(v)}`,
|
|
162
|
+
node: v,
|
|
163
|
+
});
|
|
130
164
|
}
|
|
131
165
|
else {
|
|
132
166
|
if (v.elements?.length !== 3) {
|
|
133
167
|
logger.error({
|
|
168
|
+
...baseMessage,
|
|
134
169
|
message: `Expected 3 channels, received ${v.elements?.length ?? 0}`,
|
|
135
|
-
filename,
|
|
136
170
|
node: v,
|
|
137
|
-
src,
|
|
138
171
|
});
|
|
139
172
|
}
|
|
140
173
|
for (const element of v.elements) {
|
|
141
174
|
if (element.value.type !== 'Number') {
|
|
142
175
|
logger.error({
|
|
176
|
+
...baseMessage,
|
|
143
177
|
message: `Expected number, received ${print(element.value)}`,
|
|
144
|
-
filename,
|
|
145
178
|
node: element,
|
|
146
|
-
src,
|
|
147
179
|
});
|
|
148
180
|
}
|
|
149
181
|
}
|
|
@@ -161,7 +193,11 @@ export function validateColor($value, node, { filename, src, logger }) {
|
|
|
161
193
|
v.value.length === 5 + 1 ||
|
|
162
194
|
v.value.length === 7 + 1 ||
|
|
163
195
|
!/^#[a-f0-9]{3,8}$/i.test(v.value)) {
|
|
164
|
-
logger.error({
|
|
196
|
+
logger.error({
|
|
197
|
+
...baseMessage,
|
|
198
|
+
message: `Invalid hex color ${print(v)}`,
|
|
199
|
+
node: v,
|
|
200
|
+
});
|
|
165
201
|
}
|
|
166
202
|
},
|
|
167
203
|
},
|
|
@@ -169,29 +205,24 @@ export function validateColor($value, node, { filename, src, logger }) {
|
|
|
169
205
|
}, node, { filename, src, logger });
|
|
170
206
|
}
|
|
171
207
|
else {
|
|
172
|
-
logger.error({
|
|
208
|
+
logger.error({
|
|
209
|
+
...baseMessage,
|
|
210
|
+
message: `Expected object, received ${$value.type}`,
|
|
211
|
+
node: $value,
|
|
212
|
+
});
|
|
173
213
|
}
|
|
174
214
|
}
|
|
175
215
|
/** Verify a Cubic Bézier token is valid */
|
|
176
216
|
export function validateCubicBezier($value, _node, { filename, src, logger }) {
|
|
217
|
+
const baseMessage = { group: 'parser', label: 'validate', filename, node: $value, src };
|
|
177
218
|
if ($value.type !== 'Array') {
|
|
178
|
-
logger.error({ message: `Expected array of strings, received ${print($value)}
|
|
219
|
+
logger.error({ ...baseMessage, message: `Expected array of strings, received ${print($value)}` });
|
|
179
220
|
}
|
|
180
221
|
else if (!$value.elements.every((e) => e.value.type === 'Number' || (e.value.type === 'String' && isAlias(e.value.value)))) {
|
|
181
|
-
logger.error({
|
|
182
|
-
message: 'Expected an array of 4 numbers, received some non-numbers',
|
|
183
|
-
filename,
|
|
184
|
-
node: $value,
|
|
185
|
-
src,
|
|
186
|
-
});
|
|
222
|
+
logger.error({ ...baseMessage, message: 'Expected an array of 4 numbers, received some non-numbers' });
|
|
187
223
|
}
|
|
188
224
|
else if ($value.elements.length !== 4) {
|
|
189
|
-
logger.error({
|
|
190
|
-
message: `Expected an array of 4 numbers, received ${$value.elements.length}`,
|
|
191
|
-
filename,
|
|
192
|
-
node: $value,
|
|
193
|
-
src,
|
|
194
|
-
});
|
|
225
|
+
logger.error({ ...baseMessage, message: `Expected an array of 4 numbers, received ${$value.elements.length}` });
|
|
195
226
|
}
|
|
196
227
|
}
|
|
197
228
|
/** Verify a Dimension token is valid */
|
|
@@ -199,46 +230,49 @@ export function validateDimension($value, _node, { filename, src, logger }) {
|
|
|
199
230
|
if ($value.type === 'Number' && $value.value === 0) {
|
|
200
231
|
return; // `0` is a valid number
|
|
201
232
|
}
|
|
233
|
+
const baseMessage = { group: 'parser', label: 'validate', filename, node: $value, src };
|
|
234
|
+
// Give priority to object notation because it’s a faster code path
|
|
202
235
|
if ($value.type === 'Object') {
|
|
203
236
|
const { value, unit } = getObjMembers($value);
|
|
204
237
|
if (!value) {
|
|
205
|
-
logger.error({ message: 'Missing required property "value".'
|
|
238
|
+
logger.error({ ...baseMessage, message: 'Missing required property "value".' });
|
|
206
239
|
}
|
|
207
240
|
if (!unit) {
|
|
208
|
-
logger.error({ message: 'Missing required property "unit".'
|
|
241
|
+
logger.error({ ...baseMessage, message: 'Missing required property "unit".' });
|
|
209
242
|
}
|
|
210
243
|
if (value.type !== 'Number') {
|
|
211
|
-
logger.error({
|
|
244
|
+
logger.error({
|
|
245
|
+
...baseMessage,
|
|
246
|
+
message: `Expected number, received ${value.type}`,
|
|
247
|
+
node: value,
|
|
248
|
+
});
|
|
212
249
|
}
|
|
213
250
|
if (!['px', 'em', 'rem'].includes(unit.value)) {
|
|
214
251
|
logger.error({
|
|
252
|
+
...baseMessage,
|
|
215
253
|
message: `Expected unit "px", "em", or "rem", received ${print(unit)}`,
|
|
216
|
-
filename,
|
|
217
254
|
node: unit,
|
|
218
|
-
src,
|
|
219
255
|
});
|
|
220
256
|
}
|
|
221
257
|
return;
|
|
222
258
|
}
|
|
223
259
|
// Backwards compat: string
|
|
224
260
|
if ($value.type !== 'String') {
|
|
225
|
-
logger.error({ message: `Expected string, received ${$value.type}
|
|
261
|
+
logger.error({ ...baseMessage, message: `Expected string, received ${$value.type}` });
|
|
226
262
|
}
|
|
227
263
|
const value = $value.value.match(/^-?[0-9.]+/)?.[0];
|
|
228
264
|
const unit = $value.value.replace(value, '');
|
|
229
265
|
if ($value.value === '') {
|
|
230
|
-
logger.error({ message: 'Expected dimension, received empty string'
|
|
266
|
+
logger.error({ ...baseMessage, message: 'Expected dimension, received empty string' });
|
|
231
267
|
}
|
|
232
268
|
else if (!['px', 'em', 'rem'].includes(unit)) {
|
|
233
269
|
logger.error({
|
|
270
|
+
...baseMessage,
|
|
234
271
|
message: `Expected unit "px", "em", or "rem", received ${JSON.stringify(unit || $value.value)}`,
|
|
235
|
-
filename,
|
|
236
|
-
node: $value,
|
|
237
|
-
src,
|
|
238
272
|
});
|
|
239
273
|
}
|
|
240
274
|
else if (!Number.isFinite(Number.parseFloat(value))) {
|
|
241
|
-
logger.error({ message: `Expected dimension with units, received ${print($value)}
|
|
275
|
+
logger.error({ ...baseMessage, message: `Expected dimension with units, received ${print($value)}` });
|
|
242
276
|
}
|
|
243
277
|
}
|
|
244
278
|
/** Verify a Duration token is valid */
|
|
@@ -246,106 +280,97 @@ export function validateDuration($value, _node, { filename, src, logger }) {
|
|
|
246
280
|
if ($value.type === 'Number' && $value.value === 0) {
|
|
247
281
|
return; // `0` is a valid number
|
|
248
282
|
}
|
|
283
|
+
const baseMessage = { group: 'parser', label: 'validate', filename, node: $value, src };
|
|
284
|
+
// Give priority to object notation because it’s a faster code path
|
|
249
285
|
if ($value.type === 'Object') {
|
|
250
286
|
const { value, unit } = getObjMembers($value);
|
|
251
287
|
if (!value) {
|
|
252
|
-
logger.error({ message: 'Missing required property "value".'
|
|
288
|
+
logger.error({ ...baseMessage, message: 'Missing required property "value".' });
|
|
253
289
|
}
|
|
254
290
|
if (!unit) {
|
|
255
|
-
logger.error({ message: 'Missing required property "unit".'
|
|
291
|
+
logger.error({ ...baseMessage, message: 'Missing required property "unit".' });
|
|
256
292
|
}
|
|
257
293
|
if (value?.type !== 'Number') {
|
|
258
|
-
logger.error({
|
|
294
|
+
logger.error({
|
|
295
|
+
...baseMessage,
|
|
296
|
+
message: `Expected number, received ${value?.type}`,
|
|
297
|
+
node: value,
|
|
298
|
+
});
|
|
259
299
|
}
|
|
260
300
|
if (!['ms', 's'].includes(unit.value)) {
|
|
261
|
-
logger.error({
|
|
301
|
+
logger.error({
|
|
302
|
+
...baseMessage,
|
|
303
|
+
message: `Expected unit "ms" or "s", received ${print(unit)}`,
|
|
304
|
+
node: unit,
|
|
305
|
+
});
|
|
262
306
|
}
|
|
263
307
|
return;
|
|
264
308
|
}
|
|
265
309
|
// Backwards compat: string
|
|
266
310
|
if ($value.type !== 'String') {
|
|
267
|
-
logger.error({ message: `Expected string, received ${$value.type}
|
|
311
|
+
logger.error({ ...baseMessage, message: `Expected string, received ${$value.type}` });
|
|
268
312
|
}
|
|
269
313
|
const value = $value.value.match(/^-?[0-9.]+/)?.[0];
|
|
270
314
|
const unit = $value.value.replace(value, '');
|
|
271
315
|
if ($value.value === '') {
|
|
272
|
-
logger.error({ message: 'Expected duration, received empty string'
|
|
316
|
+
logger.error({ ...baseMessage, message: 'Expected duration, received empty string' });
|
|
273
317
|
}
|
|
274
318
|
else if (!['ms', 's'].includes(unit)) {
|
|
275
319
|
logger.error({
|
|
320
|
+
...baseMessage,
|
|
276
321
|
message: `Expected unit "ms" or "s", received ${JSON.stringify(unit || $value.value)}`,
|
|
277
|
-
filename,
|
|
278
|
-
node: $value,
|
|
279
|
-
src,
|
|
280
322
|
});
|
|
281
323
|
}
|
|
282
324
|
else if (!Number.isFinite(Number.parseFloat(value))) {
|
|
283
|
-
logger.error({ message: `Expected duration with units, received ${print($value)}
|
|
325
|
+
logger.error({ ...baseMessage, message: `Expected duration with units, received ${print($value)}` });
|
|
284
326
|
}
|
|
285
327
|
}
|
|
286
328
|
/** Verify a Font Family token is valid */
|
|
287
329
|
export function validateFontFamily($value, _node, { filename, src, logger }) {
|
|
330
|
+
const baseMessage = { group: 'parser', label: 'validate', filename, node: $value, src };
|
|
288
331
|
if ($value.type !== 'String' && $value.type !== 'Array') {
|
|
289
|
-
logger.error({
|
|
290
|
-
message: `Expected string or array of strings, received ${$value.type}`,
|
|
291
|
-
filename,
|
|
292
|
-
node: $value,
|
|
293
|
-
src,
|
|
294
|
-
});
|
|
332
|
+
logger.error({ ...baseMessage, message: `Expected string or array of strings, received ${$value.type}` });
|
|
295
333
|
}
|
|
296
334
|
if ($value.type === 'String' && $value.value === '') {
|
|
297
|
-
logger.error({ message: 'Expected font family name, received empty string'
|
|
335
|
+
logger.error({ ...baseMessage, message: 'Expected font family name, received empty string' });
|
|
298
336
|
}
|
|
299
337
|
if ($value.type === 'Array' && !$value.elements.every((e) => e.value.type === 'String' && e.value.value !== '')) {
|
|
300
338
|
logger.error({
|
|
339
|
+
...baseMessage,
|
|
301
340
|
message: 'Expected an array of strings, received some non-strings or empty strings',
|
|
302
|
-
filename,
|
|
303
|
-
node: $value,
|
|
304
|
-
src,
|
|
305
341
|
});
|
|
306
342
|
}
|
|
307
343
|
}
|
|
308
344
|
/** Verify a Font Weight token is valid */
|
|
309
345
|
export function validateFontWeight($value, _node, { filename, src, logger }) {
|
|
346
|
+
const baseMessage = { group: 'parser', label: 'validate', filename, node: $value, src };
|
|
310
347
|
if ($value.type !== 'String' && $value.type !== 'Number') {
|
|
311
|
-
logger.error({
|
|
312
|
-
message: `Expected a font weight name or number 0–1000, received ${$value.type}`,
|
|
313
|
-
filename,
|
|
314
|
-
node: $value,
|
|
315
|
-
src,
|
|
316
|
-
});
|
|
348
|
+
logger.error({ ...baseMessage, message: `Expected a font weight name or number 0–1000, received ${$value.type}` });
|
|
317
349
|
}
|
|
318
350
|
if ($value.type === 'String' && !FONT_WEIGHT_VALUES.has($value.value)) {
|
|
319
351
|
logger.error({
|
|
352
|
+
...baseMessage,
|
|
320
353
|
message: `Unknown font weight ${print($value)}. Expected one of: ${listFormat.format([...FONT_WEIGHT_VALUES])}.`,
|
|
321
|
-
filename,
|
|
322
|
-
node: $value,
|
|
323
|
-
src,
|
|
324
354
|
});
|
|
325
355
|
}
|
|
326
356
|
if ($value.type === 'Number' && ($value.value < 0 || $value.value > 1000)) {
|
|
327
|
-
logger.error({ message: `Expected number 0–1000, received ${print($value)}
|
|
357
|
+
logger.error({ ...baseMessage, message: `Expected number 0–1000, received ${print($value)}` });
|
|
328
358
|
}
|
|
329
359
|
}
|
|
330
360
|
/** Verify a Gradient token is valid */
|
|
331
361
|
export function validateGradient($value, _node, { filename, src, logger }) {
|
|
362
|
+
const baseMessage = { group: 'parser', label: 'validate', filename, node: $value, src };
|
|
332
363
|
if ($value.type !== 'Array') {
|
|
333
|
-
logger.error({
|
|
334
|
-
message: `Expected array of gradient stops, received ${$value.type}`,
|
|
335
|
-
filename,
|
|
336
|
-
node: $value,
|
|
337
|
-
src,
|
|
338
|
-
});
|
|
364
|
+
logger.error({ ...baseMessage, message: `Expected array of gradient stops, received ${$value.type}` });
|
|
339
365
|
}
|
|
340
366
|
else {
|
|
341
367
|
for (let i = 0; i < $value.elements.length; i++) {
|
|
342
368
|
const element = $value.elements[i];
|
|
343
369
|
if (element.value.type !== 'Object') {
|
|
344
370
|
logger.error({
|
|
371
|
+
...baseMessage,
|
|
345
372
|
message: `Stop #${i + 1}: Expected gradient stop, received ${element.value.type}`,
|
|
346
|
-
filename,
|
|
347
373
|
node: element,
|
|
348
|
-
src,
|
|
349
374
|
});
|
|
350
375
|
break;
|
|
351
376
|
}
|
|
@@ -359,19 +384,40 @@ export function validateGradient($value, _node, { filename, src, logger }) {
|
|
|
359
384
|
/** Verify a Number token is valid */
|
|
360
385
|
export function validateNumber($value, _node, { filename, src, logger }) {
|
|
361
386
|
if ($value.type !== 'Number') {
|
|
362
|
-
logger.error({
|
|
387
|
+
logger.error({
|
|
388
|
+
group: 'parser',
|
|
389
|
+
label: 'validate',
|
|
390
|
+
message: `Expected number, received ${$value.type}`,
|
|
391
|
+
filename,
|
|
392
|
+
node: $value,
|
|
393
|
+
src,
|
|
394
|
+
});
|
|
363
395
|
}
|
|
364
396
|
}
|
|
365
397
|
/** Verify a Boolean token is valid */
|
|
366
398
|
export function validateBoolean($value, _node, { filename, src, logger }) {
|
|
367
399
|
if ($value.type !== 'Boolean') {
|
|
368
|
-
logger.error({
|
|
400
|
+
logger.error({
|
|
401
|
+
group: 'parser',
|
|
402
|
+
label: 'validate',
|
|
403
|
+
message: `Expected boolean, received ${$value.type}`,
|
|
404
|
+
filename,
|
|
405
|
+
node: $value,
|
|
406
|
+
src,
|
|
407
|
+
});
|
|
369
408
|
}
|
|
370
409
|
}
|
|
371
410
|
/** Verify a Shadow token’s value is valid */
|
|
372
411
|
export function validateShadowLayer($value, node, { filename, src, logger }) {
|
|
373
412
|
if ($value.type !== 'Object') {
|
|
374
|
-
logger.error({
|
|
413
|
+
logger.error({
|
|
414
|
+
group: 'parser',
|
|
415
|
+
label: 'validate',
|
|
416
|
+
message: `Expected Object, received ${$value.type}`,
|
|
417
|
+
filename,
|
|
418
|
+
node: $value,
|
|
419
|
+
src,
|
|
420
|
+
});
|
|
375
421
|
}
|
|
376
422
|
else {
|
|
377
423
|
validateMembersAs($value, {
|
|
@@ -386,16 +432,15 @@ export function validateShadowLayer($value, node, { filename, src, logger }) {
|
|
|
386
432
|
}
|
|
387
433
|
/** Verify a Stroke Style token is valid. */
|
|
388
434
|
export function validateStrokeStyle($value, node, { filename, src, logger }) {
|
|
435
|
+
const baseMessage = { group: 'parser', label: 'validate', filename, node: $value, src };
|
|
389
436
|
// note: strokeStyle’s values are NOT aliasable (unless by string, but that breaks validations)
|
|
390
437
|
if ($value.type === 'String') {
|
|
391
438
|
if (!STROKE_STYLE_VALUES.has($value.value)) {
|
|
392
439
|
logger.error({
|
|
440
|
+
...baseMessage,
|
|
393
441
|
message: `Unknown stroke style ${print($value)}. Expected one of: ${listFormat.format([
|
|
394
442
|
...STROKE_STYLE_VALUES,
|
|
395
443
|
])}.`,
|
|
396
|
-
filename,
|
|
397
|
-
node: $value,
|
|
398
|
-
src,
|
|
399
444
|
});
|
|
400
445
|
}
|
|
401
446
|
}
|
|
@@ -403,15 +448,17 @@ export function validateStrokeStyle($value, node, { filename, src, logger }) {
|
|
|
403
448
|
const strokeMembers = getObjMembers($value);
|
|
404
449
|
for (const property of ['dashArray', 'lineCap']) {
|
|
405
450
|
if (!strokeMembers[property]) {
|
|
406
|
-
logger.error({ message: `Missing required property "${property}"
|
|
451
|
+
logger.error({ ...baseMessage, message: `Missing required property "${property}"` });
|
|
407
452
|
}
|
|
408
453
|
}
|
|
409
454
|
const { lineCap, dashArray } = strokeMembers;
|
|
410
455
|
if (lineCap?.type !== 'String' || !STROKE_STYLE_LINE_CAP_VALUES.has(lineCap.value)) {
|
|
411
456
|
logger.error({
|
|
457
|
+
...baseMessage,
|
|
412
458
|
message: `Unknown lineCap value ${print(lineCap)}. Expected one of: ${listFormat.format([
|
|
413
459
|
...STROKE_STYLE_LINE_CAP_VALUES,
|
|
414
460
|
])}.`,
|
|
461
|
+
node,
|
|
415
462
|
});
|
|
416
463
|
}
|
|
417
464
|
if (dashArray?.type === 'Array') {
|
|
@@ -426,26 +473,32 @@ export function validateStrokeStyle($value, node, { filename, src, logger }) {
|
|
|
426
473
|
}
|
|
427
474
|
else {
|
|
428
475
|
logger.error({
|
|
476
|
+
...baseMessage,
|
|
429
477
|
message: 'Expected array of strings, recieved some non-strings or empty strings.',
|
|
430
|
-
filename,
|
|
431
478
|
node: element,
|
|
432
|
-
src,
|
|
433
479
|
});
|
|
434
480
|
}
|
|
435
481
|
}
|
|
436
482
|
}
|
|
437
483
|
else {
|
|
438
|
-
logger.error({ message: `Expected array of strings, received ${dashArray.type}
|
|
484
|
+
logger.error({ ...baseMessage, message: `Expected array of strings, received ${dashArray.type}` });
|
|
439
485
|
}
|
|
440
486
|
}
|
|
441
487
|
else {
|
|
442
|
-
logger.error({ message: `Expected string or object, received ${$value.type}
|
|
488
|
+
logger.error({ ...baseMessage, message: `Expected string or object, received ${$value.type}` });
|
|
443
489
|
}
|
|
444
490
|
}
|
|
445
491
|
/** Verify a Transition token is valid */
|
|
446
492
|
export function validateTransition($value, node, { filename, src, logger }) {
|
|
447
493
|
if ($value.type !== 'Object') {
|
|
448
|
-
logger.error({
|
|
494
|
+
logger.error({
|
|
495
|
+
group: 'parser',
|
|
496
|
+
label: 'validate',
|
|
497
|
+
message: `Expected object, received ${$value.type}`,
|
|
498
|
+
filename,
|
|
499
|
+
node: $value,
|
|
500
|
+
src,
|
|
501
|
+
});
|
|
449
502
|
}
|
|
450
503
|
else {
|
|
451
504
|
validateMembersAs($value, {
|
|
@@ -461,21 +514,20 @@ export function validateTransition($value, node, { filename, src, logger }) {
|
|
|
461
514
|
* really helps in debug messages.
|
|
462
515
|
*/
|
|
463
516
|
export function validateTokenMemberNode(node, { filename, src, logger }) {
|
|
517
|
+
const baseMessage = { group: 'parser', label: 'validate', filename, node, src };
|
|
464
518
|
if (node.type !== 'Member' && node.type !== 'Object') {
|
|
465
519
|
logger.error({
|
|
520
|
+
...baseMessage,
|
|
466
521
|
message: `Expected Object, received ${JSON.stringify(
|
|
467
522
|
// @ts-ignore Yes, TypeScript, this SHOULD be unexpected. This is why we’re validating.
|
|
468
523
|
node.type)}`,
|
|
469
|
-
filename,
|
|
470
|
-
node,
|
|
471
|
-
src,
|
|
472
524
|
});
|
|
473
525
|
}
|
|
474
526
|
const rootMembers = node.value.type === 'Object' ? getObjMembers(node.value) : {};
|
|
475
527
|
const $value = rootMembers.$value;
|
|
476
528
|
const $type = rootMembers.$type;
|
|
477
529
|
if (!$value) {
|
|
478
|
-
logger.error({ message: 'Token missing $value'
|
|
530
|
+
logger.error({ ...baseMessage, message: 'Token missing $value' });
|
|
479
531
|
}
|
|
480
532
|
// If top-level value is a valid alias, this is valid (no need for $type)
|
|
481
533
|
// ⚠️ Important: ALL Object and Array nodes below will need to check for aliases within!
|
|
@@ -484,7 +536,7 @@ export function validateTokenMemberNode(node, { filename, src, logger }) {
|
|
|
484
536
|
return;
|
|
485
537
|
}
|
|
486
538
|
if (!$type) {
|
|
487
|
-
logger.error({ message: 'Token missing $type'
|
|
539
|
+
logger.error({ ...baseMessage, message: 'Token missing $type' });
|
|
488
540
|
}
|
|
489
541
|
switch ($type.value) {
|
|
490
542
|
case 'color': {
|
|
@@ -526,10 +578,9 @@ export function validateTokenMemberNode(node, { filename, src, logger }) {
|
|
|
526
578
|
}
|
|
527
579
|
else {
|
|
528
580
|
logger.error({
|
|
581
|
+
...baseMessage,
|
|
529
582
|
message: `Expected shadow object or array of shadow objects, received ${$value.type}`,
|
|
530
|
-
filename,
|
|
531
583
|
node: $value,
|
|
532
|
-
src,
|
|
533
584
|
});
|
|
534
585
|
}
|
|
535
586
|
break;
|
|
@@ -537,22 +588,38 @@ export function validateTokenMemberNode(node, { filename, src, logger }) {
|
|
|
537
588
|
// extensions
|
|
538
589
|
case 'boolean': {
|
|
539
590
|
if ($value.type !== 'Boolean') {
|
|
540
|
-
logger.error({
|
|
591
|
+
logger.error({
|
|
592
|
+
...baseMessage,
|
|
593
|
+
message: `Expected boolean, received ${$value.type}`,
|
|
594
|
+
node: $value,
|
|
595
|
+
});
|
|
541
596
|
}
|
|
542
597
|
break;
|
|
543
598
|
}
|
|
544
599
|
case 'link': {
|
|
545
600
|
if ($value.type !== 'String') {
|
|
546
|
-
logger.error({
|
|
601
|
+
logger.error({
|
|
602
|
+
...baseMessage,
|
|
603
|
+
message: `Expected string, received ${$value.type}`,
|
|
604
|
+
node: $value,
|
|
605
|
+
});
|
|
547
606
|
}
|
|
548
607
|
else if ($value.value === '') {
|
|
549
|
-
logger.error({
|
|
608
|
+
logger.error({
|
|
609
|
+
...baseMessage,
|
|
610
|
+
message: 'Expected URL, received empty string',
|
|
611
|
+
node: $value,
|
|
612
|
+
});
|
|
550
613
|
}
|
|
551
614
|
break;
|
|
552
615
|
}
|
|
553
616
|
case 'string': {
|
|
554
617
|
if ($value.type !== 'String') {
|
|
555
|
-
logger.error({
|
|
618
|
+
logger.error({
|
|
619
|
+
...baseMessage,
|
|
620
|
+
message: `Expected string, received ${$value.type}`,
|
|
621
|
+
node: $value,
|
|
622
|
+
});
|
|
556
623
|
}
|
|
557
624
|
break;
|
|
558
625
|
}
|
|
@@ -575,15 +642,18 @@ export function validateTokenMemberNode(node, { filename, src, logger }) {
|
|
|
575
642
|
}
|
|
576
643
|
case 'typography': {
|
|
577
644
|
if ($value.type !== 'Object') {
|
|
578
|
-
logger.error({
|
|
645
|
+
logger.error({
|
|
646
|
+
...baseMessage,
|
|
647
|
+
message: `Expected object, received ${$value.type}`,
|
|
648
|
+
node: $value,
|
|
649
|
+
});
|
|
579
650
|
break;
|
|
580
651
|
}
|
|
581
652
|
if ($value.members.length === 0) {
|
|
582
653
|
logger.error({
|
|
654
|
+
...baseMessage,
|
|
583
655
|
message: 'Empty typography token. Must contain at least 1 property.',
|
|
584
|
-
filename,
|
|
585
656
|
node: $value,
|
|
586
|
-
src,
|
|
587
657
|
});
|
|
588
658
|
}
|
|
589
659
|
validateMembersAs($value, {
|
|
@@ -599,6 +669,7 @@ export function validateTokenMemberNode(node, { filename, src, logger }) {
|
|
|
599
669
|
}
|
|
600
670
|
}
|
|
601
671
|
export default function validateTokenNode(node, { config, filename, logger, parent, src, subpath, $typeInheritance }) {
|
|
672
|
+
// const start = performance.now();
|
|
602
673
|
// don’t validate $value
|
|
603
674
|
if (subpath.includes('$value') || node.value.type !== 'Object') {
|
|
604
675
|
return;
|
|
@@ -615,7 +686,14 @@ export default function validateTokenNode(node, { config, filename, logger, pare
|
|
|
615
686
|
}
|
|
616
687
|
const id = subpath.join('.');
|
|
617
688
|
if (!subpath.includes('.$value') && members.value) {
|
|
618
|
-
logger.warn({
|
|
689
|
+
logger.warn({
|
|
690
|
+
group: 'parser',
|
|
691
|
+
label: 'validate',
|
|
692
|
+
message: `Group ${id} has "value". Did you mean "$value"?`,
|
|
693
|
+
filename,
|
|
694
|
+
node,
|
|
695
|
+
src,
|
|
696
|
+
});
|
|
619
697
|
}
|
|
620
698
|
const extensions = members.$extensions ? getObjMembers(members.$extensions) : undefined;
|
|
621
699
|
const sourceNode = structuredClone(node);
|
|
@@ -631,7 +709,7 @@ export default function validateTokenNode(node, { config, filename, logger, pare
|
|
|
631
709
|
}
|
|
632
710
|
}
|
|
633
711
|
if (parent$type && !members.$type) {
|
|
634
|
-
|
|
712
|
+
injectObjMembers(
|
|
635
713
|
// @ts-ignore
|
|
636
714
|
sourceNode.value, [parent$type]);
|
|
637
715
|
}
|
|
@@ -705,6 +783,12 @@ export default function validateTokenNode(node, { config, filename, logger, pare
|
|
|
705
783
|
token.mode[mode].$description = token.$description;
|
|
706
784
|
}
|
|
707
785
|
}
|
|
786
|
+
// logger.debug({
|
|
787
|
+
// message: `${token.id}: validateTokenNode`,
|
|
788
|
+
// group: 'parser', label: 'validate',
|
|
789
|
+
// label: 'validate',
|
|
790
|
+
// timing: performance.now() - start,
|
|
791
|
+
// });
|
|
708
792
|
return token;
|
|
709
793
|
}
|
|
710
794
|
//# sourceMappingURL=validate.js.map
|