From c04ebec3718ec221166d22b87a20d27ec93ada7b Mon Sep 17 00:00:00 2001 From: origami-z Date: Thu, 11 Jan 2024 09:12:50 +0000 Subject: [PATCH] Suffix default to any variable name also being group name --- packages/export-variables-rest-api/index.js | 69 +++++++++++++++++---- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/packages/export-variables-rest-api/index.js b/packages/export-variables-rest-api/index.js index 7cd5b1a..255bab4 100644 --- a/packages/export-variables-rest-api/index.js +++ b/packages/export-variables-rest-api/index.js @@ -95,9 +95,14 @@ function callFigmaAPI(successCallback) { function processData(data) { console.log("processData", data); - const tokens = extractTokenFromVariables(data.variables); + + const newData = addDefaultToVariableNameFromApiResponse(data); + console.log("data with default name suffix", newData); + + const tokens = extractTokenFromVariables(newData.variables); console.log("extracted full tokens:", tokens); - writeTokensToFile(data, tokens); + + writeTokensToFile(newData, tokens); buildUsingStyleDictionary(); } @@ -160,24 +165,66 @@ function addDefaultToNestedTokens(tokens) { return newTokens; } +/** + * Filter out remote variables and collections, add "/default" suffix to any + * variable (in the same collection group) which also served as group name. + * + * e.g. when "Black" and "Black/100" both exist, variable with "Black" name + * will be modified to be "Black/default". + * + * @param {*} data Figma variables REST API response's `meta` data + * @returns new data with remote filtered out and variable name modified + */ function addDefaultToVariableNameFromApiResponse(data) { - // New data object, prep for non-mutate + // New data object + const newData = { variableCollections: {}, variables: {} }; // Find all non-remote collections + const nonRemoteCollections = Object.values(data.variableCollections).filter( + (c) => !c.remote + ); + // Add collection to new object.variableCollections + nonRemoteCollections.forEach((c) => (newData.variableCollections[c.id] = c)); // Filter and group non-remote variables by collections - // Add collection to new object.variableCollections + const variablesByGroup = {}; + for (const v of Object.values(data.variables)) { + if (v.remote) { + continue; + } + const collectionId = v.variableCollectionId; + if (variablesByGroup[collectionId] === undefined) { + variablesByGroup[collectionId] = []; + } + variablesByGroup[collectionId].push(v); + } // In each collection group - - // Sort variables by name - - // Iterate variables, compare name with previous name - - // If name has exactly one more "/", previous one needs to be appended a "default" - // Add variable (with new modified name) to new object.variables + for (const variablesInCollection of Object.values(variablesByGroup)) { + // Sort variables by name + variablesInCollection.sort((a, b) => a.name.localeCompare(b.name)); + + // Iterate variables, compare name with previous name + let prevVariable = undefined; + for (let index = 0; index < variablesInCollection.length; index++) { + const element = variablesInCollection[index]; + newData.variables[element.id] = element; + + if (prevVariable !== undefined) { + // If name has exactly one more "/", previous one needs to be appended a "default" + const lastSlashIndex = element.name.lastIndexOf("/"); + if (lastSlashIndex !== -1) { + if (element.name.substring(0, lastSlashIndex) === prevVariable.name) { + prevVariable.name = prevVariable.name + "/default"; + } + } + } + prevVariable = element; + } + } // return new object + return newData; } function writeTokensToFile(data, tokens) {