Skip to content
This repository was archived by the owner on Dec 23, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 50 additions & 20 deletions plugin-src/code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ figma.showUI(__html__, { themeColors: true, height: 300 });
// alias variables correctly.
const allImportedVariables: Record<string, Variable> = {};

const DEFAULT_COLOR_MODE = "light";
const DEFAULT_MODE = "default";

function isAliasValue(
value: ParsedTokenValue[keyof ParsedTokenValue]
Expand All @@ -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<string, ParsedTokens> {
return Object.entries(tokens).reduce<Record<string, ParsedTokens>>(
(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;
Expand Down Expand Up @@ -64,31 +84,44 @@ 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) {
variable.description = description;
} 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] =
Expand All @@ -101,10 +134,6 @@ async function updateCollection(args: {
continue;
}

if (!isValidColorValue(modeValue)) {
continue;
}

variable.setValueForMode(
modesInCollectionBeforeImporting[computedModeName],
modeValue
Expand All @@ -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(
Expand Down Expand Up @@ -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(
Expand All @@ -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]]
);
}
}
Expand All @@ -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();
Expand Down
6 changes: 3 additions & 3 deletions types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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]: {
Expand Down
11 changes: 9 additions & 2 deletions ui-src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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) {
Expand Down