figma-tokens-flattener 1.0.13 → 1.0.15
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/index.js +15 -222
- package/package.json +24 -16
package/index.js
CHANGED
|
@@ -76,7 +76,7 @@ function flattenSeedTokens(seedTokens) {
|
|
|
76
76
|
|
|
77
77
|
flattened[tokenName] = valueToUse;
|
|
78
78
|
})
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
return flattened;
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -198,34 +198,26 @@ function flattenMapTokensWrapper(mapTokens, seedContext) {
|
|
|
198
198
|
|
|
199
199
|
function processSingleShadow(shadowDef, contextTokens) {
|
|
200
200
|
if (!shadowDef || typeof shadowDef !== 'object') {
|
|
201
|
-
console.warn(' processSingleShadow: Ожидаемый объект тени, получен:', shadowDef);
|
|
202
201
|
return undefined;
|
|
203
202
|
}
|
|
204
203
|
|
|
205
|
-
// Проверим наличие необходимых свойств (используем 'in' или 'hasOwn' как рекомендовал тимлид)
|
|
206
|
-
// Но для простоты и т.к. структура известна, можно просто проверить тип.
|
|
207
|
-
// Проверим, есть ли хотя бы 'x', 'y', 'color' как минимум.
|
|
208
204
|
if (typeof shadowDef.x === 'undefined' || typeof shadowDef.y === 'undefined' || typeof shadowDef.color === 'undefined') {
|
|
209
|
-
console.warn('
|
|
205
|
+
console.warn('Invalid shadow structure, missing x, y or color:', shadowDef);
|
|
210
206
|
return undefined;
|
|
211
207
|
}
|
|
212
208
|
|
|
213
|
-
// Извлекаем и обрабатываем значения
|
|
214
|
-
// Используем flattenMapTokens для разрешения ссылок и вычисления выражений
|
|
215
209
|
const x = flattenMapTokens(shadowDef.x, contextTokens);
|
|
216
210
|
const y = flattenMapTokens(shadowDef.y, contextTokens);
|
|
217
|
-
const blur = flattenMapTokens(shadowDef.blur || '0', contextTokens);
|
|
218
|
-
const spread = flattenMapTokens(shadowDef.spread || '0', contextTokens);
|
|
211
|
+
const blur = flattenMapTokens(shadowDef.blur || '0', contextTokens);
|
|
212
|
+
const spread = flattenMapTokens(shadowDef.spread || '0', contextTokens);
|
|
219
213
|
const color = flattenMapTokens(shadowDef.color, contextTokens);
|
|
220
214
|
|
|
221
|
-
// Проверяем, все ли значения числовые (или цвет для color)
|
|
222
|
-
// flattenMapTokens может вернуть число, строку или undefined
|
|
223
215
|
if (typeof x !== 'number' || typeof y !== 'number' || typeof blur !== 'number' || typeof spread !== 'number' || typeof color !== 'string') {
|
|
224
|
-
console.warn(`
|
|
225
|
-
return undefined;
|
|
216
|
+
console.warn(`Invalid value type in shadow: x=${x}(${typeof x}), y=${y}(${typeof y}), blur=${blur}(${typeof blur}), spread=${spread}(${typeof spread}), color=${color}(${typeof color})`);
|
|
217
|
+
return undefined;
|
|
226
218
|
}
|
|
227
219
|
|
|
228
|
-
//
|
|
220
|
+
// Forming a line for one shadow
|
|
229
221
|
return `${x}px ${y}px ${blur}px ${spread}px ${color}`;
|
|
230
222
|
}
|
|
231
223
|
|
|
@@ -233,13 +225,13 @@ function processBoxShadow(shadowData, contextTokens) {
|
|
|
233
225
|
let shadowsArray;
|
|
234
226
|
|
|
235
227
|
if (Array.isArray(shadowData)) {
|
|
236
|
-
//
|
|
228
|
+
// This is an array of shadows
|
|
237
229
|
shadowsArray = shadowData;
|
|
238
230
|
} else if (typeof shadowData === 'object' && shadowData !== null) {
|
|
239
|
-
//
|
|
231
|
+
// This is a single shadow object
|
|
240
232
|
shadowsArray = [shadowData];
|
|
241
233
|
} else {
|
|
242
|
-
console.warn('
|
|
234
|
+
console.warn('Expected array or shadow object, received::', shadowData);
|
|
243
235
|
return undefined;
|
|
244
236
|
}
|
|
245
237
|
|
|
@@ -252,24 +244,20 @@ function processBoxShadow(shadowData, contextTokens) {
|
|
|
252
244
|
}
|
|
253
245
|
|
|
254
246
|
if (processedShadows.length === 0) {
|
|
255
|
-
console.warn(' processBoxShadow: Не удалось обработать ни одной тени.');
|
|
256
247
|
return undefined;
|
|
257
248
|
}
|
|
258
249
|
|
|
259
|
-
//
|
|
250
|
+
// Combining all the shadow lines into one boxShadow line
|
|
260
251
|
return processedShadows.join(', ');
|
|
261
252
|
}
|
|
262
253
|
|
|
263
254
|
function flattenAliasTokens(aliasTokens, contextTokens) {
|
|
264
255
|
const flattened = {};
|
|
265
256
|
if (!aliasTokens || typeof aliasTokens !== 'object') {
|
|
266
|
-
console.warn('
|
|
257
|
+
console.warn('An object with alias tokens was expected, but received:', aliasTokens);
|
|
267
258
|
return flattened;
|
|
268
259
|
}
|
|
269
260
|
|
|
270
|
-
console.log(' Вычисление alias токенов...');
|
|
271
|
-
|
|
272
|
-
// --- ЗАМЕНЕНО: for...in на Object.keys().forEach() ---
|
|
273
261
|
Object.keys(aliasTokens).forEach((tokenName) => {
|
|
274
262
|
const tokenContent = aliasTokens[tokenName];
|
|
275
263
|
|
|
@@ -277,226 +265,31 @@ function flattenAliasTokens(aliasTokens, contextTokens) {
|
|
|
277
265
|
return;
|
|
278
266
|
}
|
|
279
267
|
|
|
280
|
-
// Проверяем, что объект имеет ожидаемую структуру { "value": "..." }
|
|
281
|
-
// --- ИСПРАВЛЕНО: Используем Object.hasOwn вместо hasOwnProperty ---
|
|
282
268
|
if (tokenContent && typeof tokenContent === 'object' && Object.hasOwn(tokenContent, 'value')) {
|
|
283
|
-
// --- НОВАЯ ПРОВЕРКА: boxShadow (новый формат) ---
|
|
284
|
-
// Проверим, является ли value массивом или объектом с x, y, color
|
|
285
269
|
if (
|
|
286
270
|
(Array.isArray(tokenContent.value) && tokenContent.value.length > 0) ||
|
|
287
271
|
(typeof tokenContent.value === 'object' && tokenContent.value !== null && Object.hasOwn(tokenContent.value, 'x'))
|
|
288
272
|
) {
|
|
289
|
-
// Обработка новой структуры boxShadow (одиночный или множественный)
|
|
290
273
|
const boxShadowValue = processBoxShadow(tokenContent.value, contextTokens);
|
|
291
274
|
if (boxShadowValue !== undefined) {
|
|
292
275
|
flattened[tokenName] = boxShadowValue;
|
|
293
|
-
console.log(` ${tokenName}: (boxShadow array/object structure) -> ${boxShadowValue}`);
|
|
294
276
|
} else {
|
|
295
|
-
console.warn(
|
|
296
|
-
// Можно добавить как есть или пропустить
|
|
297
|
-
// flattened[tokenName] = tokenContent.value;
|
|
277
|
+
console.warn(`${tokenName}: The boxShadow structure could not be processed.`, tokenContent.value);
|
|
298
278
|
}
|
|
299
279
|
}
|
|
300
|
-
// --- КОНЕЦ НОВОЙ ПРОВЕРКИ ---
|
|
301
280
|
else {
|
|
302
|
-
// Это стандартный токен: { "value": "..." }
|
|
303
281
|
const rawValue = tokenContent.value;
|
|
304
|
-
// Обрабатываем значение с помощью вспомогательной функции, аналогичной для map
|
|
305
|
-
// Она должна уметь разрешать ссылки и вычислять выражения
|
|
306
282
|
const processedValue = flattenMapTokens(rawValue, contextTokens);
|
|
307
283
|
flattened[tokenName] = processedValue;
|
|
308
|
-
// console.log(` ${tokenName}: ${rawValue} -> ${processedValue}`); // Опционально: подробное логирование
|
|
309
284
|
}
|
|
310
285
|
} else {
|
|
311
|
-
|
|
312
|
-
// Неизвестная структура, просто добавим как есть или выведем предупреждение
|
|
313
|
-
console.warn(` Неподдерживаемая структура для alias токена ${tokenName}:`, tokenContent);
|
|
314
|
-
// Можно добавить как есть, если нужно сохранить:
|
|
315
|
-
// flattened[tokenName] = tokenContent;
|
|
286
|
+
console.warn(`Unsupported structure for alias token ${tokenName}:`, tokenContent);
|
|
316
287
|
}
|
|
317
288
|
});
|
|
318
|
-
|
|
319
|
-
console.log(` Вычислено ${Object.keys(flattened).length} alias токенов.`);
|
|
289
|
+
|
|
320
290
|
return flattened;
|
|
321
291
|
}
|
|
322
292
|
|
|
323
|
-
// function isDropShadowStructure(obj) {
|
|
324
|
-
// if (!obj || typeof obj !== 'object') {
|
|
325
|
-
// return false;
|
|
326
|
-
// }
|
|
327
|
-
|
|
328
|
-
// const keys = Object.keys(obj);
|
|
329
|
-
// if (keys.length === 0) {
|
|
330
|
-
// return false;
|
|
331
|
-
// }
|
|
332
|
-
|
|
333
|
-
// for (const key of keys) {
|
|
334
|
-
// if (isNaN(key)) {
|
|
335
|
-
// return false;
|
|
336
|
-
// }
|
|
337
|
-
// }
|
|
338
|
-
|
|
339
|
-
// const firstShadow = obj[keys[0]];
|
|
340
|
-
// if (!firstShadow || typeof firstShadow !== 'object') {
|
|
341
|
-
// return false;
|
|
342
|
-
// }
|
|
343
|
-
|
|
344
|
-
// const expectedProps = ['x', 'y', 'blur', 'spread', 'color', 'type'];
|
|
345
|
-
// for (const prop of expectedProps) {
|
|
346
|
-
// if (!firstShadow.hasOwnProperty(prop)) {
|
|
347
|
-
// return false;
|
|
348
|
-
// }
|
|
349
|
-
// }
|
|
350
|
-
|
|
351
|
-
// for (const coordProp of ['x', 'y', 'blur', 'spread']) {
|
|
352
|
-
// if (!firstShadow[coordProp] || typeof firstShadow[coordProp] !== 'object' || !firstShadow[coordProp].hasOwnProperty('value')) {
|
|
353
|
-
// return false;
|
|
354
|
-
// }
|
|
355
|
-
// }
|
|
356
|
-
|
|
357
|
-
// if (!firstShadow.color || typeof firstShadow.color !== 'object' || !firstShadow.color.hasOwnProperty('value')) {
|
|
358
|
-
// return false;
|
|
359
|
-
// }
|
|
360
|
-
|
|
361
|
-
// if (firstShadow.type?.value !== 'dropShadow' && firstShadow.type !== 'dropShadow') {
|
|
362
|
-
// return false;
|
|
363
|
-
// }
|
|
364
|
-
|
|
365
|
-
// // If the first shadow has passed the test, we will check the rest.
|
|
366
|
-
// for (const key of keys) {
|
|
367
|
-
// const shadow = obj[key];
|
|
368
|
-
// if (!shadow || typeof shadow !== 'object') {
|
|
369
|
-
// return false;
|
|
370
|
-
// }
|
|
371
|
-
// for (const coordProp of ['x', 'y', 'blur', 'spread']) {
|
|
372
|
-
// if (!shadow[coordProp] || typeof shadow[coordProp] !== 'object' || !shadow[coordProp].hasOwnProperty('value')) {
|
|
373
|
-
// return false;
|
|
374
|
-
// }
|
|
375
|
-
// }
|
|
376
|
-
// if (!shadow.color || typeof shadow.color !== 'object' || !shadow.color.hasOwnProperty('value')) {
|
|
377
|
-
// return false;
|
|
378
|
-
// }
|
|
379
|
-
// if (shadow.type?.value !== 'dropShadow' && shadow.type !== 'dropShadow') {
|
|
380
|
-
// return false;
|
|
381
|
-
// }
|
|
382
|
-
// }
|
|
383
|
-
|
|
384
|
-
// return true;
|
|
385
|
-
// }
|
|
386
|
-
|
|
387
|
-
// /* Checks whether the object is a single dropShadow structure. */
|
|
388
|
-
// function isSingleDropShadowStructure(obj) {
|
|
389
|
-
// if (!obj || typeof obj !== 'object') {
|
|
390
|
-
// return false;
|
|
391
|
-
// }
|
|
392
|
-
|
|
393
|
-
// const expectedProps = ['x', 'y', 'blur', 'spread', 'color', 'type'];
|
|
394
|
-
// for (const prop of expectedProps) {
|
|
395
|
-
// if (!obj.hasOwnProperty(prop)) {
|
|
396
|
-
// return false;
|
|
397
|
-
// }
|
|
398
|
-
// }
|
|
399
|
-
|
|
400
|
-
// for (const coordProp of ['x', 'y', 'blur', 'spread']) {
|
|
401
|
-
// if (!obj[coordProp] || typeof obj[coordProp] !== 'object' || !obj[coordProp].hasOwnProperty('value')) {
|
|
402
|
-
// return false;
|
|
403
|
-
// }
|
|
404
|
-
// }
|
|
405
|
-
|
|
406
|
-
// if (!obj.color || typeof obj.color !== 'object' || !obj.color.hasOwnProperty('value')) {
|
|
407
|
-
// return false;
|
|
408
|
-
// }
|
|
409
|
-
|
|
410
|
-
// if (obj.type?.value !== 'dropShadow' && obj.type !== 'dropShadow') {
|
|
411
|
-
// return false;
|
|
412
|
-
// }
|
|
413
|
-
|
|
414
|
-
// return true;
|
|
415
|
-
// }
|
|
416
|
-
|
|
417
|
-
// /* Collects the boxShadow string from the dropShadow structure (multiple). */
|
|
418
|
-
// function buildBoxShadowString(shadowStructure, contextTokens) {
|
|
419
|
-
// const shadowParts = [];
|
|
420
|
-
// const keys = Object.keys(shadowStructure).sort((a, b) => parseInt(a) - parseInt(b));
|
|
421
|
-
|
|
422
|
-
// for (const key of keys) {
|
|
423
|
-
// const shadowDef = shadowStructure[key];
|
|
424
|
-
// const shadowString = buildSingleShadowString(shadowDef, contextTokens);
|
|
425
|
-
// if (shadowString) {
|
|
426
|
-
// shadowParts.push(shadowString);
|
|
427
|
-
// }
|
|
428
|
-
// }
|
|
429
|
-
|
|
430
|
-
// // Combine all the shadows into one line
|
|
431
|
-
// return shadowParts.join(', ');
|
|
432
|
-
// }
|
|
433
|
-
|
|
434
|
-
// /* Collects a row for one shadow from the dropShadow structure. */
|
|
435
|
-
// function buildSingleShadowString(singleShadowDef, contextTokens) {
|
|
436
|
-
// // Extracting and calculating the values
|
|
437
|
-
// const x = flattenMapTokens(singleShadowDef.x.value, contextTokens);
|
|
438
|
-
// const y = flattenMapTokens(singleShadowDef.y.value, contextTokens);
|
|
439
|
-
// const blur = flattenMapTokens(singleShadowDef.blur.value, contextTokens);
|
|
440
|
-
// const spread = flattenMapTokens(singleShadowDef.spread.value, contextTokens);
|
|
441
|
-
// const color = flattenMapTokens(singleShadowDef.color.value, contextTokens);
|
|
442
|
-
|
|
443
|
-
// // Checking if all values are numeric (or color)
|
|
444
|
-
// if (typeof x !== 'number' || typeof y !== 'number' || typeof blur !== 'number' || typeof spread !== 'number' || typeof color !== 'string') {
|
|
445
|
-
// console.warn(`Invalid value type in dropShadow: x=${x}(${typeof x}), y=${y}(${typeof y}), blur=${blur}(${typeof blur}), spread=${spread}(${typeof spread}), color=${color}(${typeof color})`);
|
|
446
|
-
// return undefined; // Returning undefined to skip this shadow
|
|
447
|
-
// }
|
|
448
|
-
|
|
449
|
-
// // Forming a row for one shadow
|
|
450
|
-
// return `${x}px ${y}px ${blur}px ${spread}px ${color}`;
|
|
451
|
-
// }
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
// /* An auxiliary function for converting the alias token structure. */
|
|
455
|
-
// function flattenAliasTokens(aliasTokens, contextTokens) {
|
|
456
|
-
// const flattened = {};
|
|
457
|
-
// if (!aliasTokens || typeof aliasTokens !== 'object') {
|
|
458
|
-
// console.warn('An object with alias tokens was expected, but received:', aliasTokens);
|
|
459
|
-
// return flattened;
|
|
460
|
-
// }
|
|
461
|
-
|
|
462
|
-
// Object.keys(aliasTokens).forEach((tokenName) => {
|
|
463
|
-
// const tokenContent = aliasTokens[tokenName];
|
|
464
|
-
|
|
465
|
-
// if (tokenName[0] === tokenName[0].toUpperCase()) {
|
|
466
|
-
// return;
|
|
467
|
-
// }
|
|
468
|
-
|
|
469
|
-
// if (tokenContent && typeof tokenContent === 'object' && tokenContent.hasOwnProperty('value')) {
|
|
470
|
-
// const rawValue = tokenContent.value;
|
|
471
|
-
// const processedValue = flattenMapTokens(rawValue, contextTokens);
|
|
472
|
-
|
|
473
|
-
// flattened[tokenName] = processedValue;
|
|
474
|
-
// } else {
|
|
475
|
-
// // It can be a complex token, for example, a boxShadow (multiple or single)
|
|
476
|
-
// if (isDropShadowStructure(tokenContent)) {
|
|
477
|
-
|
|
478
|
-
// // boxShadow structure processing (multiple)
|
|
479
|
-
// const boxShadowValue = buildBoxShadowString(tokenContent, contextTokens);
|
|
480
|
-
// flattened[tokenName] = boxShadowValue;
|
|
481
|
-
|
|
482
|
-
// } else if (isSingleDropShadowStructure(tokenContent)) {
|
|
483
|
-
// // Processing the structure of a single shadow
|
|
484
|
-
// const singleShadowValue = buildSingleShadowString(tokenContent, contextTokens);
|
|
485
|
-
|
|
486
|
-
// if (singleShadowValue) {
|
|
487
|
-
// flattened[tokenName] = singleShadowValue;
|
|
488
|
-
// } else {
|
|
489
|
-
// console.warn(`Couldn't form a line for a single shadow ${tokenName}:`, tokenContent);
|
|
490
|
-
// }
|
|
491
|
-
// } else {
|
|
492
|
-
// console.warn(`Unsupported structure for alias token ${tokenName}:`, tokenContent);
|
|
493
|
-
// }
|
|
494
|
-
// }
|
|
495
|
-
// })
|
|
496
|
-
|
|
497
|
-
// return flattened;
|
|
498
|
-
// };
|
|
499
|
-
|
|
500
293
|
function checkAndResolveVarValues(contextTokens) {
|
|
501
294
|
const resolved = {};
|
|
502
295
|
|
package/package.json
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "figma-tokens-flattener",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "A tool for transforming Ant Design tokens from Tokens Studio for Figma (Single file) into flat style mappings for light and dark themes.",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"figma-tokens-flattener": "index.js"
|
|
8
|
-
},
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
},
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "figma-tokens-flattener",
|
|
3
|
+
"version": "1.0.15",
|
|
4
|
+
"description": "A tool for transforming Ant Design tokens from Tokens Studio for Figma (Single file) into flat style mappings for light and dark themes.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"figma-tokens-flattener": "index.js"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/jurassic-period/figma-tokens-flattener.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/jurassic-period/figma-tokens-flattener#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/jurassic-period/figma-tokens-flattener/issues"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
19
|
+
"test:local": "node index.js"
|
|
20
|
+
},
|
|
21
|
+
"keywords": ["figma", "design-tokens", "tokens", "json", "flattener", "transformer", "parser"],
|
|
22
|
+
"author": "Yurii Sudarskii",
|
|
23
|
+
"license": "ISC"
|
|
24
|
+
}
|