diff --git a/package-lock.json b/package-lock.json index 5ec4067..56da94e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { - "name": "react", - "version": "1.0.0", + "name": "wpds-tokens-figma-plugin", + "version": "5.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "react", - "version": "1.0.0", + "name": "wpds-tokens-figma-plugin", + "version": "5.0.0", "license": "MIT License", "dependencies": { "culori": "^4.0.2", diff --git a/plugin-src/code.ts b/plugin-src/code.ts index db0d4ce..a4e3f6b 100644 --- a/plugin-src/code.ts +++ b/plugin-src/code.ts @@ -6,7 +6,7 @@ figma.showUI(__html__, { themeColors: true, height: 300 }); // alias variables correctly. const allImportedVariables: Record = {}; -const DEFAULT_COLOR_MODE = "light"; +const DEFAULT_MODE = "default"; function isAliasValue( value: ParsedTokenValue[keyof ParsedTokenValue] @@ -22,6 +22,26 @@ function isValidColorValue(value: any): value is ParsedTokenValue { ); } +function getResolvedType(value: any): VariableResolvedDataType | undefined { + if (isValidColorValue(value)) { + return "COLOR"; + } else if (typeof value === "number") { + return "FLOAT"; + } +} + +function groupByCollection(tokens: ParsedTokens): Record { + return Object.entries(tokens).reduce>( + (result, [tokenName, tokenData]) => { + const collection = tokenName.split("/")[0]; + result[collection] = result[collection] || {}; + result[collection][tokenName] = tokenData; + return result; + }, + {} + ); +} + async function updateCollection(args: { tokens: ParsedTokens; collectionName: string; @@ -64,9 +84,19 @@ async function updateCollection(args: { let variable = variablesInCollectionBeforeImporting[tokenName]; + // Don't save variables where we can't determine the resolved type + const resolvedType = getResolvedType(value["."]); + if (!resolvedType) { + continue; + } + if (!variable) { // Create new variable - variable = figma.variables.createVariable(tokenName, collection, "COLOR"); + variable = figma.variables.createVariable( + tokenName, + collection, + resolvedType + ); } if (description) { @@ -74,21 +104,24 @@ async function updateCollection(args: { } else { variable.description = ""; } - variable.hiddenFromPublishing = /primitive/.test(tokenName); // Update scopes - if (/color\/semantic\/foreground/gi.test(tokenName)) { + if (/color\/fg/gi.test(tokenName)) { variable.scopes = ["TEXT_FILL", "SHAPE_FILL", "STROKE_COLOR"]; - } else if (/color\/semantic\/stroke/gi.test(tokenName)) { + } else if (/color\/stroke/gi.test(tokenName)) { variable.scopes = ["STROKE_COLOR", "EFFECT_COLOR"]; - } else if (/color\/semantic\/background/gi.test(tokenName)) { + } else if (/color\/bg/gi.test(tokenName)) { variable.scopes = ["FRAME_FILL", "SHAPE_FILL"]; + } else if (/dimension\/(padding|gap)/gi.test(tokenName)) { + variable.scopes = ["GAP"]; + } else if (/dimension/gi.test(tokenName)) { + variable.scopes = ["WIDTH_HEIGHT"]; } else { variable.scopes = []; } for (const [modeName, modeValue] of Object.entries(value)) { - const computedModeName = modeName === "." ? DEFAULT_COLOR_MODE : modeName; + const computedModeName = modeName === "." ? DEFAULT_MODE : modeName; if (!(computedModeName in modesInCollectionBeforeImporting)) { modesInCollectionBeforeImporting[computedModeName] = @@ -101,10 +134,6 @@ async function updateCollection(args: { continue; } - if (!isValidColorValue(modeValue)) { - continue; - } - variable.setValueForMode( modesInCollectionBeforeImporting[computedModeName], modeValue @@ -128,7 +157,7 @@ async function updateCollection(args: { } for (const [modeName, modeValue] of Object.entries(value)) { - const computedModeName = modeName === "." ? DEFAULT_COLOR_MODE : modeName; + const computedModeName = modeName === "." ? DEFAULT_MODE : modeName; if (!(computedModeName in modesInCollectionBeforeImporting)) { console.log( @@ -174,7 +203,7 @@ async function updateCollection(args: { const modesMissingValues = new Set(collection.modes.map((m) => m.modeId)); for (const [modeName] of Object.entries(value)) { - const computedModeName = modeName === "." ? DEFAULT_COLOR_MODE : modeName; + const computedModeName = modeName === "." ? DEFAULT_MODE : modeName; if (!(computedModeName in modesInCollectionBeforeImporting)) { console.log( @@ -191,9 +220,7 @@ async function updateCollection(args: { for (const modeId of modesMissingValues) { variable.setValueForMode( modeId, - variable.valuesByMode[ - modesInCollectionBeforeImporting[DEFAULT_COLOR_MODE] - ] + variable.valuesByMode[modesInCollectionBeforeImporting[DEFAULT_MODE]] ); } } @@ -220,11 +247,14 @@ async function updateCollection(args: { figma.ui.onmessage = async (msg) => { if (msg.type === "import-tokens") { const parsedTokens: ParsedTokens = msg.parsedTokens; + const groupedTokens = groupByCollection(parsedTokens); - await updateCollection({ - tokens: parsedTokens, - collectionName: "WPDS Tokens", - }); + for (const [collectionName, tokens] of Object.entries(groupedTokens)) { + await updateCollection({ + tokens: tokens, + collectionName, + }); + } } figma.closePlugin(); diff --git a/types.ts b/types.ts index 489e8f1..a4b16be 100644 --- a/types.ts +++ b/types.ts @@ -11,10 +11,10 @@ export interface RGBA { readonly a: number; } -type ColorModes = "light" | "dark" | "."; +type TokenMode = "."; export type ImportedTokenValue = { - [key in ColorModes]?: string; + [key in TokenMode]?: string; }; export interface ImportedTokens { @@ -25,7 +25,7 @@ export interface ImportedTokens { } export type ParsedTokenValue = { - [key in ColorModes]?: RGB | RGBA | string; + [key in TokenMode]?: RGB | RGBA | string | number; }; export interface ParsedTokens { [key: string]: { diff --git a/ui-src/App.tsx b/ui-src/App.tsx index dc6c6a8..a421ddd 100644 --- a/ui-src/App.tsx +++ b/ui-src/App.tsx @@ -23,8 +23,8 @@ function App() { const parsedTokens: ParsedTokens = {}; for (const [tokenName, tokenObject] of Object.entries(tokens)) { - // For now, only import colors. - if (!/color/gi.test(tokenName)) { + // Limit to supported token types + if (!/^wpds-(color|dimension)/gi.test(tokenName)) { continue; } @@ -54,6 +54,13 @@ function App() { b: Math.max(Math.min(converted.b, 1), 0), a: converted.alpha ?? 1, }; + } else if (/dimension/gi.test(tokenName)) { + if (!/px$/.test(modeValue)) { + console.warn(`Invalid dimension value: ${modeValue}`); + continue; + } + + computedModeValue = Number(modeValue.replace("px", "")); } if (!computedModeValue) {