figma-tokens-flattener 1.0.12 → 1.0.14
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 +68 -161
- package/package.json +3 -2
package/index.js
CHANGED
|
@@ -49,11 +49,15 @@ function flattenSeedTokens(seedTokens) {
|
|
|
49
49
|
|
|
50
50
|
let valueToUse;
|
|
51
51
|
|
|
52
|
-
if (
|
|
52
|
+
if (Object.hasOwn(tokenObj, 'value') && typeof tokenObj.value === 'object' && tokenObj.value !== null && Object.hasOwn(tokenObj.value, 'style')) {
|
|
53
|
+
valueToUse = tokenObj.value.style;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
else if (Object.hasOwn(tokenObj, 'value')) {
|
|
53
57
|
valueToUse = tokenObj.value;
|
|
54
58
|
}
|
|
55
59
|
|
|
56
|
-
else if (
|
|
60
|
+
else if (Object.hasOwn(tokenObj, 'style') && tokenObj.style && typeof tokenObj.style === 'object' && Object.hasOwn(tokenObj.style, 'value')) {
|
|
57
61
|
valueToUse = tokenObj.style.value;
|
|
58
62
|
}
|
|
59
63
|
|
|
@@ -72,6 +76,7 @@ function flattenSeedTokens(seedTokens) {
|
|
|
72
76
|
|
|
73
77
|
flattened[tokenName] = valueToUse;
|
|
74
78
|
})
|
|
79
|
+
|
|
75
80
|
return flattened;
|
|
76
81
|
}
|
|
77
82
|
|
|
@@ -190,138 +195,62 @@ function flattenMapTokensWrapper(mapTokens, seedContext) {
|
|
|
190
195
|
}
|
|
191
196
|
|
|
192
197
|
/* Alias */
|
|
193
|
-
function isDropShadowStructure(obj) {
|
|
194
|
-
if (!obj || typeof obj !== 'object') {
|
|
195
|
-
return false;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const keys = Object.keys(obj);
|
|
199
|
-
if (keys.length === 0) {
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
for (const key of keys) {
|
|
204
|
-
if (isNaN(key)) {
|
|
205
|
-
return false;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const firstShadow = obj[keys[0]];
|
|
210
|
-
if (!firstShadow || typeof firstShadow !== 'object') {
|
|
211
|
-
return false;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const expectedProps = ['x', 'y', 'blur', 'spread', 'color', 'type'];
|
|
215
|
-
for (const prop of expectedProps) {
|
|
216
|
-
if (!firstShadow.hasOwnProperty(prop)) {
|
|
217
|
-
return false;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
198
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
199
|
+
function processSingleShadow(shadowDef, contextTokens) {
|
|
200
|
+
if (!shadowDef || typeof shadowDef !== 'object') {
|
|
201
|
+
return undefined;
|
|
225
202
|
}
|
|
226
203
|
|
|
227
|
-
if (
|
|
228
|
-
|
|
204
|
+
if (typeof shadowDef.x === 'undefined' || typeof shadowDef.y === 'undefined' || typeof shadowDef.color === 'undefined') {
|
|
205
|
+
console.warn('Invalid shadow structure, missing x, y or color:', shadowDef);
|
|
206
|
+
return undefined;
|
|
229
207
|
}
|
|
230
208
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
209
|
+
const x = flattenMapTokens(shadowDef.x, contextTokens);
|
|
210
|
+
const y = flattenMapTokens(shadowDef.y, contextTokens);
|
|
211
|
+
const blur = flattenMapTokens(shadowDef.blur || '0', contextTokens);
|
|
212
|
+
const spread = flattenMapTokens(shadowDef.spread || '0', contextTokens);
|
|
213
|
+
const color = flattenMapTokens(shadowDef.color, contextTokens);
|
|
234
214
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
if (!shadow || typeof shadow !== 'object') {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
for (const coordProp of ['x', 'y', 'blur', 'spread']) {
|
|
242
|
-
if (!shadow[coordProp] || typeof shadow[coordProp] !== 'object' || !shadow[coordProp].hasOwnProperty('value')) {
|
|
243
|
-
return false;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
if (!shadow.color || typeof shadow.color !== 'object' || !shadow.color.hasOwnProperty('value')) {
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
if (shadow.type?.value !== 'dropShadow' && shadow.type !== 'dropShadow') {
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
215
|
+
if (typeof x !== 'number' || typeof y !== 'number' || typeof blur !== 'number' || typeof spread !== 'number' || typeof color !== 'string') {
|
|
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;
|
|
252
218
|
}
|
|
253
219
|
|
|
254
|
-
|
|
220
|
+
// Forming a line for one shadow
|
|
221
|
+
return `${x}px ${y}px ${blur}px ${spread}px ${color}`;
|
|
255
222
|
}
|
|
256
223
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
for (const coordProp of ['x', 'y', 'blur', 'spread']) {
|
|
271
|
-
if (!obj[coordProp] || typeof obj[coordProp] !== 'object' || !obj[coordProp].hasOwnProperty('value')) {
|
|
272
|
-
return false;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (!obj.color || typeof obj.color !== 'object' || !obj.color.hasOwnProperty('value')) {
|
|
277
|
-
return false;
|
|
224
|
+
function processBoxShadow(shadowData, contextTokens) {
|
|
225
|
+
let shadowsArray;
|
|
226
|
+
|
|
227
|
+
if (Array.isArray(shadowData)) {
|
|
228
|
+
// This is an array of shadows
|
|
229
|
+
shadowsArray = shadowData;
|
|
230
|
+
} else if (typeof shadowData === 'object' && shadowData !== null) {
|
|
231
|
+
// This is a single shadow object
|
|
232
|
+
shadowsArray = [shadowData];
|
|
233
|
+
} else {
|
|
234
|
+
console.warn('Expected array or shadow object, received::', shadowData);
|
|
235
|
+
return undefined;
|
|
278
236
|
}
|
|
279
237
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
return true;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/* Collects the boxShadow string from the dropShadow structure (multiple). */
|
|
288
|
-
function buildBoxShadowString(shadowStructure, contextTokens) {
|
|
289
|
-
const shadowParts = [];
|
|
290
|
-
const keys = Object.keys(shadowStructure).sort((a, b) => parseInt(a) - parseInt(b));
|
|
291
|
-
|
|
292
|
-
for (const key of keys) {
|
|
293
|
-
const shadowDef = shadowStructure[key];
|
|
294
|
-
const shadowString = buildSingleShadowString(shadowDef, contextTokens);
|
|
238
|
+
const processedShadows = [];
|
|
239
|
+
for (const shadowDef of shadowsArray) {
|
|
240
|
+
const shadowString = processSingleShadow(shadowDef, contextTokens);
|
|
295
241
|
if (shadowString) {
|
|
296
|
-
|
|
242
|
+
processedShadows.push(shadowString);
|
|
297
243
|
}
|
|
298
244
|
}
|
|
299
245
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/* Collects a row for one shadow from the dropShadow structure. */
|
|
305
|
-
function buildSingleShadowString(singleShadowDef, contextTokens) {
|
|
306
|
-
// Extracting and calculating the values
|
|
307
|
-
const x = flattenMapTokens(singleShadowDef.x.value, contextTokens);
|
|
308
|
-
const y = flattenMapTokens(singleShadowDef.y.value, contextTokens);
|
|
309
|
-
const blur = flattenMapTokens(singleShadowDef.blur.value, contextTokens);
|
|
310
|
-
const spread = flattenMapTokens(singleShadowDef.spread.value, contextTokens);
|
|
311
|
-
const color = flattenMapTokens(singleShadowDef.color.value, contextTokens);
|
|
312
|
-
|
|
313
|
-
// Checking if all values are numeric (or color)
|
|
314
|
-
if (typeof x !== 'number' || typeof y !== 'number' || typeof blur !== 'number' || typeof spread !== 'number' || typeof color !== 'string') {
|
|
315
|
-
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})`);
|
|
316
|
-
return undefined; // Returning undefined to skip this shadow
|
|
246
|
+
if (processedShadows.length === 0) {
|
|
247
|
+
return undefined;
|
|
317
248
|
}
|
|
318
249
|
|
|
319
|
-
//
|
|
320
|
-
return
|
|
250
|
+
// Combining all the shadow lines into one boxShadow line
|
|
251
|
+
return processedShadows.join(', ');
|
|
321
252
|
}
|
|
322
253
|
|
|
323
|
-
|
|
324
|
-
/* An auxiliary function for converting the alias token structure. */
|
|
325
254
|
function flattenAliasTokens(aliasTokens, contextTokens) {
|
|
326
255
|
const flattened = {};
|
|
327
256
|
if (!aliasTokens || typeof aliasTokens !== 'object') {
|
|
@@ -336,36 +265,30 @@ function flattenAliasTokens(aliasTokens, contextTokens) {
|
|
|
336
265
|
return;
|
|
337
266
|
}
|
|
338
267
|
|
|
339
|
-
if (tokenContent && typeof tokenContent === 'object' &&
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
// boxShadow structure processing (multiple)
|
|
349
|
-
const boxShadowValue = buildBoxShadowString(tokenContent, contextTokens);
|
|
350
|
-
flattened[tokenName] = boxShadowValue;
|
|
351
|
-
|
|
352
|
-
} else if (isSingleDropShadowStructure(tokenContent)) {
|
|
353
|
-
// Processing the structure of a single shadow
|
|
354
|
-
const singleShadowValue = buildSingleShadowString(tokenContent, contextTokens);
|
|
355
|
-
|
|
356
|
-
if (singleShadowValue) {
|
|
357
|
-
flattened[tokenName] = singleShadowValue;
|
|
268
|
+
if (tokenContent && typeof tokenContent === 'object' && Object.hasOwn(tokenContent, 'value')) {
|
|
269
|
+
if (
|
|
270
|
+
(Array.isArray(tokenContent.value) && tokenContent.value.length > 0) ||
|
|
271
|
+
(typeof tokenContent.value === 'object' && tokenContent.value !== null && Object.hasOwn(tokenContent.value, 'x'))
|
|
272
|
+
) {
|
|
273
|
+
const boxShadowValue = processBoxShadow(tokenContent.value, contextTokens);
|
|
274
|
+
if (boxShadowValue !== undefined) {
|
|
275
|
+
flattened[tokenName] = boxShadowValue;
|
|
358
276
|
} else {
|
|
359
|
-
console.warn(
|
|
277
|
+
console.warn(`${tokenName}: The boxShadow structure could not be processed.`, tokenContent.value);
|
|
360
278
|
}
|
|
361
|
-
} else {
|
|
362
|
-
console.warn(`Unsupported structure for alias token ${tokenName}:`, tokenContent);
|
|
363
279
|
}
|
|
280
|
+
else {
|
|
281
|
+
const rawValue = tokenContent.value;
|
|
282
|
+
const processedValue = flattenMapTokens(rawValue, contextTokens);
|
|
283
|
+
flattened[tokenName] = processedValue;
|
|
284
|
+
}
|
|
285
|
+
} else {
|
|
286
|
+
console.warn(`Unsupported structure for alias token ${tokenName}:`, tokenContent);
|
|
364
287
|
}
|
|
365
|
-
})
|
|
288
|
+
});
|
|
366
289
|
|
|
367
290
|
return flattened;
|
|
368
|
-
}
|
|
291
|
+
}
|
|
369
292
|
|
|
370
293
|
function checkAndResolveVarValues(contextTokens) {
|
|
371
294
|
const resolved = {};
|
|
@@ -405,8 +328,8 @@ function flattenDefaultValueTokens(defaultTokens) {
|
|
|
405
328
|
|
|
406
329
|
const extractRefKey = (value) => {
|
|
407
330
|
if (typeof value !== 'string') return null;
|
|
408
|
-
const tokenMatch
|
|
409
|
-
return tokenMatch
|
|
331
|
+
const tokenMatch = value.match(/^\s*\{([^}]+)\}\s*$/);
|
|
332
|
+
return tokenMatch ? tokenMatch[1].trim() : null;
|
|
410
333
|
};
|
|
411
334
|
|
|
412
335
|
// 2) Iterative resolution of "{key}" links
|
|
@@ -443,11 +366,11 @@ function flattenDefaultValueTokens(defaultTokens) {
|
|
|
443
366
|
}
|
|
444
367
|
|
|
445
368
|
// 3) Returning numeric values only
|
|
446
|
-
const numericTokens
|
|
369
|
+
const numericTokens = {};
|
|
447
370
|
for (const [tokenName, tokenValue] of Object.entries(resolved)) {
|
|
448
|
-
if (typeof tokenValue === 'number' && Number.isFinite(tokenValue)) numericTokens
|
|
371
|
+
if (typeof tokenValue === 'number' && Number.isFinite(tokenValue)) numericTokens[tokenName] = tokenValue;
|
|
449
372
|
}
|
|
450
|
-
return numericTokens
|
|
373
|
+
return numericTokens;
|
|
451
374
|
}
|
|
452
375
|
|
|
453
376
|
/* Components */
|
|
@@ -476,23 +399,7 @@ function flattenComponentsTokens(componentsTokens, contextTokens) {
|
|
|
476
399
|
const processedValue = flattenMapTokens(rawValue, contextTokens);
|
|
477
400
|
processedComponentTokens[tokenName] = processedValue;
|
|
478
401
|
} else {
|
|
479
|
-
|
|
480
|
-
if (tokenDefinition && typeof tokenDefinition === 'object' && tokenDefinition.style && typeof tokenDefinition.style === 'object' && Object.hasOwn(tokenDefinition.style, 'value')) {
|
|
481
|
-
const rawValue = tokenDefinition.style.value;
|
|
482
|
-
|
|
483
|
-
const processedValue = flattenMapTokens(rawValue, contextTokens);
|
|
484
|
-
processedComponentTokens[tokenName] = processedValue;
|
|
485
|
-
|
|
486
|
-
} else {
|
|
487
|
-
if (isDropShadowStructure(tokenDefinition)) {
|
|
488
|
-
// Processing of the boxShadowSecondary structure (multiple)
|
|
489
|
-
const boxShadowValue = buildBoxShadowString(tokenDefinition, contextTokens);
|
|
490
|
-
processedComponentTokens[tokenName] = boxShadowValue;
|
|
491
|
-
|
|
492
|
-
} else {
|
|
493
|
-
console.warn(`Unsupported token structure ${componentName}.${tokenName}:`, tokenDefinition);
|
|
494
|
-
}
|
|
495
|
-
}
|
|
402
|
+
console.warn(`Unsupported token structure ${componentName}.${tokenName}:`, tokenDefinition);
|
|
496
403
|
}
|
|
497
404
|
})
|
|
498
405
|
|
|
@@ -512,7 +419,7 @@ function flatten() {
|
|
|
512
419
|
config = JSON.parse(configContent);
|
|
513
420
|
} catch (configError) {
|
|
514
421
|
if (configError.code === 'ENOENT') {
|
|
515
|
-
console.log('The configuration file is
|
|
422
|
+
console.log('The configuration file is figma-tokens-flattener-config.json was not found. We use the path - the root directory.');
|
|
516
423
|
} else {
|
|
517
424
|
console.error('Error when reading or parsing the configuration file:', configError.message);
|
|
518
425
|
// Continue with an empty configuration, by default
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "figma-tokens-flattener",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
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
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"figma-tokens-flattener": "index.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"test:local": "node index.js"
|
|
11
12
|
},
|
|
12
13
|
"keywords": ["figma", "design-tokens", "tokens", "json", "flattener", "transformer", "parser"],
|
|
13
14
|
"author": "Yurii Sudarskii",
|