#!/usr/bin/env node "use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // index.ts var path6 = __toESM(require("path"), 1); // bin/entities/Config/baseConfig.ts var baseConfig = { debugMode: false, camelizeTokenNames: true, borderWidthUnit: "px", fontUnit: "rem", letterSpacingUnit: "em", lineHeightUnit: "unitless", opacitiesUnit: "float", radiusUnit: "px", shadowUnit: "px", spacingUnit: "rem", durationUnit: "s", figmaData: "figma.json", figmagicFolder: ".figmagic", outputFolderElements: "elements", outputFolderGraphics: "graphics", outputFolderTokens: "tokens", outputFormatColors: "rgba", outputFormatCss: "ts", outputFormatDescription: "md", outputFormatElements: "tsx", outputFormatGraphics: "svg", outputFormatStorybook: "js", outputFormatTokens: "ts", outputGraphicElements: false, outputGraphicElementsMap: false, outputScaleGraphics: 1, outputDataTypeToken: null, overwrite: { css: false, description: false, graphic: false, react: false, storybook: false, styled: false }, recompileLocal: false, remSize: 16, skipFileGeneration: { forceUpdate: true, skipCss: false, skipDescription: false, skipReact: false, skipStorybook: false, skipStyled: false }, syncElements: false, syncGraphics: false, syncTokens: true, templates: { templatePathGraphic: "./node_modules/figmagic/templates/graphic", templatePathReact: "./node_modules/figmagic/templates/react", templatePathStorybook: "./node_modules/figmagic/templates/story", templatePathStyled: "./node_modules/figmagic/templates/styled" }, token: "", tokensRelativeImportPrefix: "", unitlessPrecision: 2, url: "", usePostscriptFontNames: false, useLiteralFontFamilies: false, versionName: null }; // bin/frameworks/system/colors.ts var colors = { BgBlack: "\x1B[40m", BgBlue: "\x1B[44m", BgCyan: "\x1B[46m", BgGreen: "\x1B[42m", BgMagenta: "\x1B[45m", BgRed: "\x1B[41m", BgWhite: "\x1B[47m", BgYellow: "\x1B[43m", FgBlack: "\x1B[30m", FgBlue: "\x1B[34m", FgCyan: "\x1B[36m", FgGreen: "\x1B[32m", FgMagenta: "\x1B[35m", FgRed: "\x1B[31m", FgWhite: "\x1B[37m", FgYellow: "\x1B[33m", Blink: "\x1B[5m", Bright: "\x1B[1m", Dim: "\x1B[2m", Hidden: "\x1B[8m", Reset: "\x1B[0m", Reverse: "\x1B[7m", Underscore: "\x1B[4m" }; // bin/frameworks/errors/errors.ts function ErrorMessage(str) { return `${colors.FgRed}${str}${colors.Reset}`; } var ErrorAddDescriptionToElements = ErrorMessage( "Missing elements and/or components in addDescriptionToElements()!" ); var ErrorCalculateDegree2Point = ErrorMessage( "Missing point1 and/or point2 in calculateDegree2Point!" ); var ErrorCheckIfStringOnlyContainsReturnsOrSpaces = ErrorMessage( "No string provided to checkIfStringOnlyContainsReturnsOrSpaces()!" ); var ErrorCleanArrays = ErrorMessage( 'Missing one or more of "classNames" and/or "classContent" when calling cleanArrays()!' ); var ErrorCleanSvgData = ErrorMessage( "No data passed to cleanSvgData()!" ); var ErrorConvertHexToRgba = ErrorMessage( 'Missing six-digit hex color string (such as "#33ff00") in convertHexToRgba()!' ); var ErrorConvertRgbaToHex = ErrorMessage( 'Missing color value (as string, like "rgba(123,123,123,0.05) when calling convertRgbaToHex()!' ); var ErrorCreateConfigurationNoDefault = ErrorMessage( "No default configuration provided to createConfiguration()!" ); var ErrorCreateCssString = ErrorMessage( 'Missing one or more of required arguments: "intersections", "uniqueValues"!' ); var ErrorCreateElements = ErrorMessage( "Missing arguments provided to createElements()!" ); var ErrorCreateEnumStringOutOfObject = ErrorMessage( "No object provided to createEnumStringOutOfObject()!" ); var ErrorCreateFolder = ErrorMessage( "No directory specified for createFolder()!" ); var ErrorCreateMissingFoldersFromPath = ErrorMessage( "No directory specified for createMissingFoldersFromPath()!" ); var ErrorCreateGraphics = ErrorMessage( "Missing arguments provided to createGraphics()!" ); var ErrorCreateImportStringFromList = ErrorMessage( 'No "importArray" provided to createImportStringFromList()!' ); var ErrorCreateImportStringFromListZeroLength = ErrorMessage( 'Provided "importArray" is zero-length when calling createImportStringFromList()!' ); var ErrorCreateLinearGradientString = ErrorMessage( "Missing fills and gradientHandlePositions in createLinearGradientString!" ); var ErrorCreateRadialGradientString = ErrorMessage( "Missing fills and gradientHandlePositions in createRadialGradientString!" ); var ErrorCreatePage = ErrorMessage( "No pages provided to createPage()!" ); var ErrorCreateSolidColorString = ErrorMessage( "Missing fills in createSolidColorString!" ); var ErrorCreateTokens = ErrorMessage( "Missing required arguments when calling createTokens()!" ); var ErrorDownloadFile = ErrorMessage( 'Missing one or more of "url", "folder", or "file" arguments in downloadFile()!' ); var ErrorExtractDescription = ErrorMessage( "Missing description in extractDescription()!" ); var ErrorExtractTokens = ErrorMessage( "No sheet or name for processTokens()!" ); var ErrorExtractTokensNoConfig = ErrorMessage( "No config provided to processTokens()!" ); var ErrorFigmagicController = ErrorMessage( "Error in FigmagicController()!" ); var ErrorFindShortenedNameMatchWrongType = ErrorMessage( "Arguments are not of string type!" ); var ErrorGetAlphaInPercent = ErrorMessage( "Missing RGB(A) color string when calling getAlphaInPercent()!" ); var ErrorGetData = ErrorMessage( "Could not retrieve any data. Are you missing a valid API key?" ); var ErrorGetDataFailedLocalAndRemote = ErrorMessage( "Failed to get local and/or remote data in getData()!" ); var ErrorGetDataLocal = ErrorMessage( "Missing arguments when calling getDataLocal()!" ); var ErrorGetDataNoData = ErrorMessage( 'No data retrieved. Verify that your Figma document ID ("Figma URL") is correct.' ); var ErrorGetDataNoTokenOrUrl = ErrorMessage( "Missing token and/or URL when attempting to get remote data!" ); var ErrorGetDescription = ErrorMessage( "Missing element in getDescription()!" ); var ErrorGetFigmaDocumentId = ErrorMessage( "Missing URL when calling getFigmaDocumentId()!" ); var ErrorGetFileContentAndPath = ErrorMessage( "Missing argument in getFileContentAndPath()!" ); var ErrorGetFileContentAndPathMissingFields = ErrorMessage( "Missing fields in getFileContentAndPath()!" ); var ErrorGetFileContentAndPathNoReturn = ErrorMessage( "Missing return in getFileContentAndPath()!" ); var ErrorGetFileContents = ErrorMessage( "Missing path, name and/or format!" ); var ErrorGetFileList = ErrorMessage( 'Missing one or more of required arguments: "imageResponse", "ids" and/or "outputFormatGraphics" when calling getFileList()!' ); var ErrorGetFiles = ErrorMessage("Error in getFiles()!"); var ErrorGetFontColor = ErrorMessage("Error in getFontColor()!"); var ErrorGetFromApi = (errorMessage) => ErrorMessage(`Error occurred while using the Figma API: "${errorMessage}"`); var ErrorGetFromApiMissingValues = ErrorMessage( 'Missing one or more of required arguments: "figmaToken", "figmaUrl" when attempting to get data from Figma API!' ); var ErrorGetIds = ErrorMessage( "No (or zero-length) array passed to getIds()!" ); var ErrorGetIdstring = ErrorMessage( 'Missing required argument "ids" when calling getIdString()!' ); var ErrorGetIntersectingValues = ErrorMessage( 'Missing "arrays" argument when calling getIntersectingValues()!' ); var ErrorGetPaddingX = ErrorMessage( "Error when calling getPaddingX()!" ); var ErrorGetPaddingY = ErrorMessage( "Error when calling getPaddingY()!" ); var ErrorGetTokenMatch = ErrorMessage( 'Missing one or more of required arguments: "tokenFileName", "property", and/or "expectedValue"!' ); var ErrorGetSvgFileData = ErrorMessage( "Missing string when calling getSvgFileData()!" ); var ErrorGetTokenMatchNoRemSize = ErrorMessage( 'Missing required "remSize" argument for getTokenMatch() when converting to rem/em!' ); var ErrorGetUniqueValues = ErrorMessage( 'Missing one or more of required arguments: "arrays", and/or "intersections" when calling getUniqueValues()!' ); var ErrorHandleNestedElements = ErrorMessage( "Missing element in handleNestedElements()!" ); var ErrorLoadFile = (path7) => { if (!path7) throw Error("No string passed to ErrorLoadFile!"); return ErrorMessage(`Could not find file: ${path7}!`); }; var ErrorGetBackgroundColor = ErrorMessage( "Error in getBackgroundColor()!" ); var ErrorGetBorderColor = ErrorMessage("Error in getBorderColor()!"); var ErrorGetShadow = ErrorMessage("Error in getShadow()!"); var ErrorMakeBorderWidthTokensMissingProps = ErrorMessage( 'Missing "name" or "strokeWeight" properties in border width frame!' ); var ErrorMakeBorderWidthTokensNoChildren = ErrorMessage( "Border Width has no children!" ); var ErrorMakeBorderWidthTokensNoFrame = ErrorMessage( "No frame for makeBorderWidthTokens()!" ); var ErrorMakeColorTokensNoChildren = ErrorMessage( "Color tokens frame has no children!" ); var ErrorMakeColorTokensNoFrame = ErrorMessage( "No frame for makeColorTokens()!" ); var ErrorMakeDelayTokensMissingProps = ErrorMessage( 'Missing "name" or "characters" properties in Delay frame!' ); var ErrorMakeDelayTokensNoChildren = ErrorMessage( "Delay frame has no children!" ); var ErrorMakeDelayTokensNoFrame = ErrorMessage( "No frame for makeDelayTokens()!" ); var ErrorMakeDurationTokensMissingProps = ErrorMessage( 'Missing "name" or "characters" properties in Duration frame!' ); var ErrorMakeDurationTokensNoChildren = ErrorMessage( "Duration frame has no children!" ); var ErrorMakeDurationTokensNoFrame = ErrorMessage( "No frame for makeDurationTokens()!" ); var ErrorMakeEasingTokensMissingProps = ErrorMessage( 'Missing "name" or "characters" properties in Easing frame!' ); var ErrorMakeEasingTokensNoChildren = ErrorMessage( "Easing frame has no children!" ); var ErrorMakeEasingTokensNoFrame = ErrorMessage( "No frame for makeEasingTokens()!" ); var ErrorMakeFontSizeTokensMissingProps = ErrorMessage( 'Missing "name" or "style" properties in font sizes frame!' ); var ErrorMakeFontSizeTokensMissingSize = ErrorMessage( 'Missing required "style.fontSize" property!' ); var ErrorMakeFontSizeTokensNoChildren = ErrorMessage( 'Font size frame is missing "children" array!' ); var ErrorMakeFontSizeTokensNoFrame = ErrorMessage( "No frame for makeFontSizeTokens()!" ); var ErrorMakeFontSizeTokensNoSizing = ErrorMessage( 'Missing "fontUnit" or "remSize" properties when calling makeFontSizeTokens()!' ); var ErrorMakeFontTokensMissingProps = ErrorMessage( 'Missing "name" or "style" properties in font tokens frame!' ); var ErrorMakeLiteralFontTokensMissingProps = ErrorMessage( 'Missing "character" property in font tokens frame!' ); var ErrorMakeFontTokensNoChildren = ErrorMessage( 'Font tokens frame is missing "children" array!' ); var ErrorMakeFontTokensNoFrame = ErrorMessage( "No frame for makeFontTokens()!" ); var ErrorMakeFontWeightTokensMissingProps = ErrorMessage( 'Missing "name" or "style" properties in font weights frame!' ); var ErrorMakeFontWeightTokensMissingWeight = ErrorMessage( 'Missing required "style.fontWeight" property!' ); var ErrorMakeFontWeightTokensNoChildren = ErrorMessage( 'Font weights frame is missing "children" array!' ); var ErrorMakeFontWeightTokensNoFrame = ErrorMessage( "No frame for makeFontWeightTokens()!" ); var ErrorMakeLetterSpacingTokensMissingProps = ErrorMessage( 'Missing "name" or "style" properties in letter spacing frame!' ); var ErrorMakeLineHeightTokensMissingProps = ErrorMessage( 'Missing "name" or "style" properties in line height frame!' ); var ErrorMakeLetterSpacingTokensNoChildren = ErrorMessage( "Letter Spacing frame has no children!" ); var ErrorMakeLetterSpacingTokensNoFrame = ErrorMessage( "No frame for makeLetterSpacingTokens()!" ); var ErrorMakeLineHeightTokensNoChildren = ErrorMessage( "Line heights frame has no children!" ); var ErrorMakeLineHeightTokensNoName = ErrorMessage( "Line heights frame is missing name!" ); var ErrorMakeLineHeightTokensNoStyle = ErrorMessage( "Line heights frame is missing style!" ); var ErrorMakeLineHeightTokensNoFrame = ErrorMessage( "No frame for makeLineHeightTokens()!" ); var ErrorMakeOpacityTokensMissingProps = ErrorMessage( 'Missing "name" or "characters" properties in opacities frame!' ); var ErrorMakeOpacityTokensNoChildren = ErrorMessage( "Opacities frame has no children!" ); var ErrorMakeOpacityTokensNoFrame = ErrorMessage( "No frame for makeOpacityTokens()!" ); var ErrorMakeRadiusTokensMissingProps = ErrorMessage( 'Missing "name" property in radius frame!' ); var ErrorMakeRadiusTokensNoChildren = ErrorMessage( "Radius frame has no children!" ); var ErrorMakeRadiusTokensNoFrame = ErrorMessage( "No frame for makeRadiusTokens()!" ); var ErrorMakeShadowTokensMissingProps = ErrorMessage( 'Missing "effects" property in shadow frame!' ); var ErrorMakeShadowTokensNoChildren = ErrorMessage( "Shadow frame has no children!" ); var ErrorMakeShadowTokensNoFrame = ErrorMessage( "No frame for makeShadowTokens()!" ); var ErrorMakeSpacingTokensMissingProps = ErrorMessage( 'Missing "name" or "absoluteBoundingBox" properties in spacing frame!' ); var ErrorMakeSpacingTokensNoChildren = ErrorMessage( "Spacing frame has no children!" ); var ErrorMakeSpacingTokensNoFrame = ErrorMessage( "No frame for makeSpacingTokens()!" ); var ErrorMakeSpacingTokensNoUnits = ErrorMessage( 'Missing "spacingUnit" or "remSize" properties when calling makeSpacingTokens()!' ); var ErrorMakeZindexTokensMissingProps = ErrorMessage( 'Missing "name" or "characters" properties in Z index frame!' ); var ErrorMakeZindexTokensNoChildren = ErrorMessage( "Z Index frame has no children!" ); var ErrorMakeZindexTokensNoFrame = ErrorMessage( "No frame for makeZindexTokens()!" ); var ErrorNormalizeUnits = ErrorMessage( "Missing arguments for normalizeUnits()!" ); var ErrorNormalizeUnitsNoRemSize = ErrorMessage( 'Missing required "remSize" argument for normalizeUnits() when converting to rem/em!' ); var ErrorNormalizeUnitsUndefined = ErrorMessage( 'arguments "rootSize" or "unitSize" are undefined!' ); var ErrorParseBackgroundColor = ErrorMessage( "Error in parseBackgroundColor()!" ); var ErrorParseBorderColor = ErrorMessage( "Error in parseBorderColor()!" ); var ErrorParseBorderRadius = ErrorMessage( "Error in parseBorderRadius()!" ); var ErrorParseBorderWidth = ErrorMessage( "Error in parseBorderWidth()!" ); var ErrorParseCliArgs = ErrorMessage( "No arguments array passed to parseCliArgs()!" ); var ErrorParseCssFromElement = ErrorMessage( 'Missing one or more of required arguments: "layoutElement", "textElement", "remSize", and/or "outputFormatTokens" when calling parseCssFromElement()!' ); var ErrorParseElement = ErrorMessage( 'Missing one or more of required arguments: "element", and/or "remSize" when calling parseElement()!' ); var ErrorParseHeight = ErrorMessage("Error in parseHeight()!"); var ErrorParsePadding = ErrorMessage("Error in parsePadding()!"); var ErrorParseShadow = ErrorMessage("Error in parseShadow()!"); var ErrorParseTypographyStylingFromElement = ErrorMessage( 'Missing one or more of required arguments: "element", or "remSize" when calling parseTypographyStylingFromElement()!' ); var ErrorPrepFileComponent = ErrorMessage( "Missing required arguments in type, when calling prepComponent()!" ); var ErrorPrepFileCss = ErrorMessage( "Missing required arguments in type, when calling prepComponent()!" ); var ErrorPrepFileDescription = ErrorMessage( "Missing required arguments in type, when calling prepComponent()!" ); var ErrorPrepFileStorybook = ErrorMessage( "Missing required arguments in type, when calling prepComponent()!" ); var ErrorPrepFileStyledComponents = ErrorMessage( "Missing required arguments in type, when calling prepComponent()!" ); var ErrorPrepFileGraphicComponent = ErrorMessage( "Missing required arguments in type, when calling prepGraphicComponent()!" ); var ErrorPrepareWrite = ErrorMessage( "No templates provided to prepareWrite()!" ); var ErrorProcessElements = ErrorMessage( 'Missing one or more of required arguments: "elementsPage", "config", and/or "components"! Make sure you have a page called "Elements" in your Figma document.' ); var ErrorProcessElementsNoMainElement = ErrorMessage( "No MAIN_ELEMENT in processElements()!" ); var ErrorProcessGraphics = ErrorMessage( 'Graphics page is undefined or empty! Make sure you have a page called "Graphics" in your Figma document.' ); var ErrorProcessGraphicsImageError = ErrorMessage( "Error when fetching graphics from Figma API!" ); var ErrorProcessGraphicElementsMap = ErrorMessage( "No graphics, or zero-length array, passed to processGraphicElementsMap()!" ); var ErrorProcessGraphicsNoImages = ErrorMessage( "No images received from Figma API!" ); var ErrorProcessNestedCss = ErrorMessage( 'No "css" string provided to processNestedCss()!' ); var ErrorRefresh = ErrorMessage("No path provided to refresh()!"); var ErrorReplaceMediaQuery = ErrorMessage( 'Missing one or more of required arguments: "str", and/or "match" when calling replaceMediaQuery()!' ); var ErrorRoundColor = ErrorMessage( 'Error while rounding color value: Required argument "quantity" was not passed in!' ); var ErrorRoundColorValue = ErrorMessage( "Error while rounding color value: Scale value must be equal to or less than 255!" ); var ErrorSanitizeString = ErrorMessage( "No string provided to sanitizeString()!" ); var ErrorSetupMediaQueryTokensMissingProps = ErrorMessage( 'Missing "absoluteBoundingBox" property in media query frame!' ); var ErrorSetupMediaQueryTokensNoChildren = ErrorMessage( "Media Query frame has no children!" ); var ErrorSetupMediaQueryTokensNoFrame = ErrorMessage( "No frame for makeMediaQueryTokens()!" ); var ErrorSliceOutObjectFromFile = ErrorMessage( "Error in sliceOutObjectFromFile()!" ); var ErrorToPascalCase = ErrorMessage( 'Missing "str" argument when calling toPascalCase()!' ); var ErrorUpdateParsing = ErrorMessage("Error in updateParsing()!"); var ErrorValidateConfig = ErrorMessage( "Error when validating config!" ); var ErrorValidateConfigFileName = ErrorMessage( "Provided Figma file name in configuration is invalid!" ); var ErrorValidateConfigFolderName = ErrorMessage( "Provided Figma folder name in configuration is invalid!" ); var ErrorValidateBorderWidthUnit = ErrorMessage( 'Received unrecognized "borderWidthUnit" argument, it must be "px" (default), "em" or "rem".' ); var ErrorValidateRadiusUnit = ErrorMessage( 'Received unrecognized "radiusUnit" argument, it must be "px" (default), "em" or "rem".' ); var ErrorValidateShadowUnit = ErrorMessage( 'Received unrecognized "shadowUnit" argument, it must be "px" (default), "em" or "rem".' ); var ErrorValidateDurationUnit = ErrorMessage( 'Received unrecognized "durationUnit" argument, it must be "s" (default) or "ms".' ); var ErrorValidateConfigFontUnit = ErrorMessage( 'Received unrecognized "fontUnit" argument, it must be "rem" (default), "em" or "px".' ); var ErrorValidateConfigLetterSpacingUnit = ErrorMessage( 'Received unrecognized "letterSpacingUnit" argument, it must be "em" (default) or "px".' ); var ErrorValidateConfigLineHeightUnit = ErrorMessage( 'Received unrecognized "lineHeightUnit" argument, it must be "unitless" (default), "em", "rem" or "px".' ); var ErrorValidateConfigOpacitiesUnit = ErrorMessage( 'Received unrecognized "opacitiesUnit" argument, it must be "float" (default) or "percent".' ); var ErrorValidateConfigOutputDataTypeToken = ErrorMessage( 'Received unrecognized "outputDataTypeToken" arguments, it must be null (default), or "enum".' ); var ErrorValidateConfigOutputFormatColors = ErrorMessage( 'Received unrecognized "outputFormatColors" arguments, it must be "rgba" (default) or "hex".' ); var ErrorValidateConfigOutputFormatCss = ErrorMessage( 'Received unrecognized "outputFormatCss" arguments, it must be "ts" (default), "mjs" or "js".' ); var ErrorValidateConfigOutputFormatDesc = ErrorMessage( 'Received unrecognized "outputFormatDescription" arguments, it must be "md" (default), or "txt".' ); var ErrorValidateConfigOutputFormatElements = ErrorMessage( 'Received unrecognized "outputFormatElements" arguments, it must be "tsx" (default), or "jsx".' ); var ErrorValidateConfigOutputFormatGraphics = ErrorMessage( 'Received unrecognized "outputFormatGraphics" arguments, it must be "svg" (default) or "png".' ); var ErrorValidateConfigOutputFormatStorybook = ErrorMessage( 'Received unrecognized "outputFormatStorybook" arguments, it must be "js" (default), "ts" or "mdx".' ); var ErrorValidateConfigOutputFormatTokens = ErrorMessage( 'Received unrecognized "outputFormatTokens" arguments, it must be "ts" (default), "mjs", "js", "json", "css", or "scss".' ); var ErrorValidateConfigOutputScaleGraphics = ErrorMessage( 'Argument "outputScaleGraphics" is invalid!' ); var ErrorValidateConfigSpacingUnit = ErrorMessage( 'Received unrecognized "spacingUnit" argument, it must be "rem" (default), "em" or "px".' ); var ErrorValidateConfigTemplatePathReact = ErrorMessage( 'Argument "templatePathReact" cannot be empty!' ); var ErrorValidateConfigTemplatePathStorybook = ErrorMessage( 'Argument "templatePathStorybook" cannot be empty!' ); var ErrorValidateConfigTemplatePathStyled = ErrorMessage( 'Argument "templatePathStyled" cannot be empty!' ); var ErrorValidateConfigTemplatePathGraphic = ErrorMessage( 'Argument "templatePathGraphic" cannot be empty!' ); var ErrorWrite = ErrorMessage("Error while attempting to write file!"); var ErrorWriteBaseJson = ErrorMessage( "Error while attempting to write Figma JSON!" ); var ErrorWriteElements = ErrorMessage( 'Missing "elements" and/or "config" properties when calling writeElements()!' ); var ErrorWriteFile = ErrorMessage( "Missing required arguments to correctly run writeFile()!" ); var ErrorWriteFileWrongType = ErrorMessage( "Provided invalid file type to writeFile()!" ); var ErrorWriteGraphics = ErrorMessage( 'Missing "fileList" and/or "config" argument when calling writeGraphics()!' ); var ErrorWriteGraphicElementsMap = ErrorMessage( 'Missing one or more of required arguments "folder", "filePath", and/or "fileContent" when calling writeGraphicElementsMap()!' ); var ErrorWriteTokens = ErrorMessage( 'Less than one token provided to writeTokens()! Make sure you have a page called "Design Tokens" in your Figma document.' ); var ErrorWriteTokensNoSettings = ErrorMessage( 'Missing "settings" argument/object when attempting to write tokens!' ); // bin/entities/Config/logic/parseCliArgs.ts function parseCliArgs(argsArray) { if (!argsArray) throw Error(ErrorParseCliArgs); if (argsArray.length === 0) return {}; const config = {}; const setConfigValue = (key, value) => { config[key] = value; }; const setConfigChildValue = (key, childKey, value) => { config[key] = { ...config[key], [childKey]: value }; }; const cliArguments = { "--debug": () => setConfigValue("debugMode", true), "-d": () => setConfigValue("debugMode", true), "--noCamelizeTokenNames": () => setConfigValue("camelizeTokenNames", false), "-cml": () => setConfigValue("camelizeTokenNames", false), "--borderWidthUnit": (val) => setConfigValue("borderWidthUnit", val.toLowerCase()), "-bwu": (val) => setConfigValue("borderWidthUnit", val.toLowerCase()), "--radiusUnit": (val) => setConfigValue("radiusUnit", val.toLowerCase()), "-ru": (val) => setConfigValue("radiusUnit", val.toLowerCase()), "--shadowUnit": (val) => setConfigValue("shadowUnit", val.toLowerCase()), "-su": (val) => setConfigValue("shadowUnit", val.toLowerCase()), "--fontUnit": (val) => setConfigValue("fontUnit", val.toLowerCase()), "-fu": (val) => setConfigValue("fontUnit", val.toLowerCase()), "--letterSpacingUnit": (val) => setConfigValue("letterSpacingUnit", val.toLowerCase()), "-lsu": (val) => setConfigValue("letterSpacingUnit", val.toLowerCase()), "--lineHeightUnit": (val) => setConfigValue("lineHeightUnit", val.toLowerCase()), "-lhu": (val) => setConfigValue("lineHeightUnit", val.toLowerCase()), "--opacitiesUnit": (val) => setConfigValue("opacitiesUnit", val.toLowerCase()), "-ou": (val) => setConfigValue("opacitiesUnit", val.toLowerCase()), "--durationUnit": (val) => setConfigValue("durationUnit", val.toLowerCase()), "-du": (val) => setConfigValue("durationUnit", val.toLowerCase()), "--figmaData": (val) => setConfigValue("figmaData", val), "-data": (val) => setConfigValue("figmaData", val), "--figmagicFolder": (val) => setConfigValue("figmagicFolder", val), "-base": (val) => setConfigValue("figmagicFolder", val), "--outputFolderElements": (val) => setConfigValue("outputFolderElements", val), "-elements": (val) => setConfigValue("outputFolderElements", val), "--outputFolderGraphics": (val) => setConfigValue("outputFolderGraphics", val), "-graphics": (val) => setConfigValue("outputFolderGraphics", val), "--outputFolderTokens": (val) => setConfigValue("outputFolderTokens", val), "-tokens": (val) => setConfigValue("outputFolderTokens", val), "--outputFormatColors": (val) => setConfigValue("outputFormatColors", val.toLowerCase()), "-fcol": (val) => setConfigValue("outputFormatColors", val.toLowerCase()), "--outputFormatCss": (val) => setConfigValue("outputFormatCss", val.toLowerCase()), "-fc": (val) => setConfigValue("outputFormatCss", val.toLowerCase()), "--outputFormatDesc": (val) => setConfigValue("outputFormatDescription", val.toLowerCase()), "-fd": (val) => setConfigValue("outputFormatDescription", val.toLowerCase()), "--outputFormatElements": (val) => setConfigValue("outputFormatElements", val.toLowerCase()), "-fe": (val) => setConfigValue("outputFormatElements", val.toLowerCase()), "--outputFormatGraphics": (val) => setConfigValue("outputFormatGraphics", val.toLowerCase()), "-fg": (val) => setConfigValue("outputFormatGraphics", val.toLowerCase()), "--outputFormatStorybook": (val) => setConfigValue("outputFormatStorybook", val.toLowerCase()), "-fs": (val) => setConfigValue("outputFormatStorybook", val.toLowerCase()), "--outputFormatTokens": (val) => setConfigValue("outputFormatTokens", val.toLowerCase()), "-ft": (val) => setConfigValue("outputFormatTokens", val.toLowerCase()), "--outputGraphicElements": () => setConfigValue("outputGraphicElements", true), "-oge": () => setConfigValue("outputGraphicElements", true), "--outputGraphicElementsMap": () => setConfigValue("outputGraphicElementsMap", true), "-ogm": () => setConfigValue("outputGraphicElementsMap", true), "--outputScaleGraphics": (val) => setConfigValue("outputScaleGraphics", parseInt(val)), "-scale": (val) => setConfigValue("outputScaleGraphics", parseInt(val)), "--outputDataTypeToken": (val) => setConfigValue("outputDataTypeToken", val.toLowerCase()), "-tokentype": (val) => setConfigValue("outputDataTypeToken", val.toLowerCase()), "--recompileLocal": () => setConfigValue("recompileLocal", true), "-local": () => setConfigValue("recompileLocal", true), "--remSize": (val) => setConfigValue("remSize", parseInt(val, 10)), "-rem": (val) => setConfigValue("remSize", parseInt(val, 10)), "--forceUpdate": () => setConfigChildValue("skipFileGeneration", "forceUpdate", true), "-force": () => setConfigChildValue("skipFileGeneration", "forceUpdate", true), "--skipCss": () => setConfigChildValue("skipFileGeneration", "skipCss", true), "-nocss": () => setConfigChildValue("skipFileGeneration", "skipCss", true), "--skipDescription": () => setConfigChildValue("skipFileGeneration", "skipDescription", true), "-nodesc": () => setConfigChildValue("skipFileGeneration", "skipDescription", true), "--skipReact": () => setConfigChildValue("skipFileGeneration", "skipReact", true), "-noreact": () => setConfigChildValue("skipFileGeneration", "skipReact", true), "--skipStorybook": () => setConfigChildValue("skipFileGeneration", "skipStorybook", true), "-nostory": () => setConfigChildValue("skipFileGeneration", "skipStorybook", true), "--skipStyled": () => setConfigChildValue("skipFileGeneration", "skipStyled", true), "-nostyled": () => setConfigChildValue("skipFileGeneration", "skipStyled", true), "--spacingUnit": (val) => setConfigValue("spacingUnit", val.toLowerCase()), "-s": (val) => setConfigValue("spacingUnit", val.toLowerCase()), "--syncElements": () => setConfigValue("syncElements", true), "-se": () => setConfigValue("syncElements", true), "--syncGraphics": () => setConfigValue("syncGraphics", true), "-sg": () => setConfigValue("syncGraphics", true), "--syncTokens": () => setConfigValue("syncTokens", true), "-st": () => setConfigValue("syncTokens", true), "--templatePathReact": (val) => setConfigChildValue("templates", "templatePathReact", val), "-tpreact": (val) => setConfigChildValue("templates", "templatePathReact", val), "--templatePathStorybook": (val) => setConfigChildValue("templates", "templatePathStorybook", val), "-tpstory": (val) => setConfigChildValue("templates", "templatePathStorybook", val), "--templatePathStyled": (val) => setConfigChildValue("templates", "templatePathStyled", val), "-tpstyled": (val) => setConfigChildValue("templates", "templatePathStyled", val), "--templatePathGraphic": (val) => setConfigChildValue("templates", "templatePathGraphic", val), "-tpgraphic": (val) => setConfigChildValue("templates", "templatePathGraphic", val), "--token": (val) => setConfigValue("token", val), "-t": (val) => setConfigValue("token", val), "--tokensRelativeImportPrefix": (val) => setConfigValue("tokensRelativeImportPrefix", val), "-tip": (val) => setConfigValue("tokensRelativeImportPrefix", val), "--unitlessPrecision": (val) => setConfigValue("unitlessPrecision", parseInt(val, 10)), "-up": (val) => setConfigValue("unitlessPrecision", parseInt(val, 10)), "--url": (val) => setConfigValue("url", val), "-u": (val) => setConfigValue("url", val), "--usePostscriptFontNames": () => setConfigValue("usePostscriptFontNames", true), "-ps": () => setConfigValue("usePostscriptFontNames", true), "--useLiteralFontFamilies": () => setConfigValue("useLiteralFontFamilies", true), "-lff": () => setConfigValue("useLiteralFontFamilies", true), "--versionName": (val) => setConfigValue("versionName", val), "-v": (val) => setConfigValue("versionName", val) }; argsArray.forEach((arg, index) => { if (cliArguments.hasOwnProperty(arg)) { cliArguments[arg](argsArray[index + 1]); } }); return config; } // bin/frameworks/filesystem/loadFile.ts var import_fs = __toESM(require("fs"), 1); // bin/frameworks/filesystem/isJsonString.ts var isJsonString = (str) => { try { JSON.parse(str); } catch (_e) { return false; } return true; }; // bin/frameworks/filesystem/loadFile.ts function loadFile(path7) { if (!path7) throw Error(ErrorLoadFile(path7)); if (!import_fs.default.existsSync(path7)) throw Error(ErrorLoadFile(path7)); const data = import_fs.default.readFileSync(path7, "utf8"); return isJsonString(data) ? JSON.parse(data) : data; } // bin/frameworks/string/getFigmaDocumentId.ts function getFigmaDocumentId(url) { if (!url) throw Error(ErrorGetFigmaDocumentId); if (!url.startsWith("https://www.figma.com/file/")) return url; return url.split("https://www.figma.com/file/")[1].split("/")[0]; } // bin/frameworks/messages/messages.ts function Message(str, warn) { if (warn) return `${colors.FgYellow}${str}${colors.Reset}`; else return str; } function SuccessMessage(str) { return `${colors.FgGreen}${str}${colors.Reset}`; } var MsgConfigDebugCli = Message( `USER: Command-Line configuration (Medium priority) `, true ); var MsgConfigDebugEnv = Message( `USER: Environment configuration (Low priority) `, true ); var MsgConfigDebugFinal = Message( `SYSTEM: Final user configuration that will be used... `, true ); var MsgConfigDebugRc = Message( `USER: figmagic.json/.figmagicrc configuration (Highest priority) `, true ); var MsgGeneratedFileWarning = Message( "THIS FILE IS AUTO-GENERATED BY FIGMAGIC. DO NOT MAKE EDITS IN THIS FILE! CHANGES WILL GET OVER-WRITTEN BY ANY FURTHER PROCESSING.", false ); var MsgGetTokenMatchNoMatch = Message( `No matching token! Hard-coding to expected value:`, true ); var MsgJobComplete = SuccessMessage( ` Figmagic completed operations successfully! ` ); var MsgJobCompleteInit = SuccessMessage( ` Figmagic created a base configuration (figmagic.json) for you. ` ); var MsgJobCompleteInitStopped = Message( ` Figmagic tried to create a base configuration for you, but one already existed at figmagic.json... `, true ); var MsgProcessElementsCreatingElement = (elementName, fixedName) => `Processing Figma element "${elementName}" as ---> ${fixedName}`; var MsgSetDataFromApi = Message( ` Attempting to fetch data from Figma API...`, true ); var MsgSetDataFromLocal = Message( ` Attempting to recompile data from local Figma JSON file...`, true ); var MsgSyncElements = Message( ` Attempting to parse elements... `, true ); var MsgSyncGraphics = Message( ` Getting images from Figma API...`, true ); var MsgWriteBaseFile = Message(` Writing Figma base file...`, true); var MsgWriteTokens = Message(` Writing design tokens...`, true); var MsgNoTokensFound = Message( `No design tokens found! Do you have a "Design tokens" page in Figma and token frames in it? Read more at https://github.com/mikaelvesavuori/figmagic#preparing-figma-for-figmagic-usage`, true ); // bin/entities/Config/logic/createConfiguration.ts async function createConfiguration(baseConfig2, userConfigPath, cliArgs) { if (!baseConfig2) throw Error(ErrorCreateConfigurationNoDefault); const defaultConfig = baseConfig2; const rcConfig = (() => { if (userConfigPath && userConfigPath !== "") { try { return loadFile(userConfigPath); } catch (_e) { } } return {}; })(); const envConfig = { token: process.env.FIGMA_TOKEN || rcConfig.token || "", url: getEnvUrl(process.env.FIGMA_URL, rcConfig.url || "") }; const cliConfig = parseCliArgs(cliArgs); const CONFIG = { ...defaultConfig, ...rcConfig, ...envConfig, ...cliConfig, templates: { ...defaultConfig.templates, ...rcConfig.templates, ...cliConfig.templates }, skipFileGeneration: { ...defaultConfig.skipFileGeneration, ...rcConfig.skipFileGeneration, ...cliConfig.skipFileGeneration } }; if (CONFIG.debugMode === true) printConfigs(envConfig, cliConfig, rcConfig, CONFIG); return CONFIG; } function printConfigs(envConfig, cliConfig, rcConfig, config) { console.log(MsgConfigDebugEnv); console.log(envConfig); console.log(MsgConfigDebugCli); console.log(cliConfig); console.log(MsgConfigDebugRc); console.log(rcConfig); console.log(MsgConfigDebugFinal); console.log(config); } var getEnvUrl = (processEnvUrl, rcConfigUrl) => { if (processEnvUrl) return getFigmaDocumentId(processEnvUrl); if (rcConfigUrl) return getFigmaDocumentId(rcConfigUrl); return ""; }; // bin/frameworks/system/validatorLists.ts var validBorderWidthUnitList = ["rem", "em", "px"]; var validFontUnitList = ["rem", "em", "px"]; var validLetterSpacingUnitList = ["em", "px"]; var validLineHeightUnitList = ["unitless", "em", "px", "rem"]; var validOpacitiesUnitList = ["float", "percent"]; var validOutputDataTypeTokenList = ["enum", "null", null, void 0]; var validOutputFormatColors = ["hex", "rgba"]; var validOutputFormatCssList = ["ts", "mjs", "js"]; var validOutputFormatDescList = ["md", "txt"]; var validOutputFormatElementsList = ["tsx", "jsx", "mjs", "js"]; var validOutputFormatGraphicsList = ["svg", "png"]; var validOutputFormatStorybookList = ["ts", "js", "mdx"]; var validOutputFormatTokensList = [ "ts", "mjs", "js", "json", "css", "scss" ]; var validRadiusUnitList = ["rem", "em", "px"]; var validShadowUnitList = ["rem", "em", "px"]; var validDurationUnitList = ["s", "ms"]; var validSpacingUnitList = ["rem", "em", "px"]; // bin/entities/Config/logic/validateConfig.ts function validateConfig(config) { if (!config) throw Error(ErrorValidateConfig); validateBorderWidthUnit(config.borderWidthUnit); validateFileName(config.figmaData); validateFolderName(config.figmagicFolder); validateFolderName(config.outputFolderElements); validateFolderName(config.outputFolderGraphics); validateFolderName(config.outputFolderTokens); validateFontUnit(config.fontUnit); validateLetterSpacingUnit(config.letterSpacingUnit); validateOpacitiesUnit(config.opacitiesUnit); validateOutputDataTypeToken(config.outputDataTypeToken); validateOutputFormatColors(config.outputFormatColors); validateOutputFormatCss(config.outputFormatCss); validateOutputFormatDesc(config.outputFormatDescription); validateOutputFormatElements(config.outputFormatElements); validateOutputFormatGraphics(config.outputFormatGraphics); validateOutputFormatStorybook(config.outputFormatStorybook); validateOutputFormatTokens(config.outputFormatTokens); validateOutputScaleGraphics(config.outputScaleGraphics); validateRadiusUnit(config.radiusUnit); validateShadowUnit(config.shadowUnit); validateDurationUnit(config.durationUnit); validateSpacingUnit(config.spacingUnit); validateTemplatePathGraphic(config.templates.templatePathGraphic); validateTemplatePathReact(config.templates.templatePathReact); validateTemplatePathStorybook(config.templates.templatePathStorybook); validateTemplatePathStyled(config.templates.templatePathStyled); validLineHeightUnit(config.lineHeightUnit); return true; } var validateFontUnit = (unit) => { if (validFontUnitList.includes(unit)) return true; throw Error(ErrorValidateConfigFontUnit); }; var validateBorderWidthUnit = (unit) => { if (validBorderWidthUnitList.includes(unit)) return true; throw Error(ErrorValidateBorderWidthUnit); }; var validateRadiusUnit = (unit) => { if (validRadiusUnitList.includes(unit)) return true; throw Error(ErrorValidateRadiusUnit); }; var validateShadowUnit = (unit) => { if (validShadowUnitList.includes(unit)) return true; throw Error(ErrorValidateShadowUnit); }; var validateDurationUnit = (unit) => { if (validDurationUnitList.includes(unit)) return true; throw Error(ErrorValidateDurationUnit); }; var validateLetterSpacingUnit = (unit) => { if (validLetterSpacingUnitList.includes(unit)) return true; throw Error(ErrorValidateConfigLetterSpacingUnit); }; var validLineHeightUnit = (unit) => { if (validLineHeightUnitList.includes(unit)) return true; throw Error(ErrorValidateConfigLineHeightUnit); }; var validateOpacitiesUnit = (unit) => { if (validOpacitiesUnitList.includes(unit)) return true; throw Error(ErrorValidateConfigOpacitiesUnit); }; var validateFileName = (filename) => { if (filename) return true; throw Error(ErrorValidateConfigFileName); }; var validateFolderName = (filename) => { if (filename) return true; throw Error(ErrorValidateConfigFolderName); }; var validateOutputFormatColors = (format) => { if (validOutputFormatColors.includes(format)) return true; throw Error(ErrorValidateConfigOutputFormatColors); }; var validateOutputFormatCss = (format) => { if (validOutputFormatCssList.includes(format)) return true; throw Error(ErrorValidateConfigOutputFormatCss); }; var validateOutputFormatDesc = (format) => { if (validOutputFormatDescList.includes(format)) return true; throw Error(ErrorValidateConfigOutputFormatDesc); }; var validateOutputFormatElements = (format) => { if (validOutputFormatElementsList.includes(format)) return true; throw Error(ErrorValidateConfigOutputFormatElements); }; var validateOutputFormatGraphics = (format) => { if (validOutputFormatGraphicsList.includes(format)) return true; throw Error(ErrorValidateConfigOutputFormatGraphics); }; var validateOutputFormatStorybook = (format) => { if (validOutputFormatStorybookList.includes(format)) return true; throw Error(ErrorValidateConfigOutputFormatStorybook); }; var validateOutputFormatTokens = (format) => { if (validOutputFormatTokensList.includes(format)) return true; throw Error(ErrorValidateConfigOutputFormatTokens); }; var validateOutputScaleGraphics = (scale) => { if (scale && typeof scale === "number" && scale > 0) return true; throw Error(ErrorValidateConfigOutputScaleGraphics); }; var validateOutputDataTypeToken = (format) => { if (!format || validOutputDataTypeTokenList.includes(format)) return true; throw Error(ErrorValidateConfigOutputDataTypeToken); }; var validateSpacingUnit = (unit) => { if (validSpacingUnitList.includes(unit)) return true; throw Error(ErrorValidateConfigSpacingUnit); }; var validateTemplatePathReact = (path7) => { if (path7) return true; throw Error(ErrorValidateConfigTemplatePathReact); }; var validateTemplatePathStorybook = (path7) => { if (path7) return true; throw Error(ErrorValidateConfigTemplatePathStorybook); }; var validateTemplatePathStyled = (path7) => { if (path7) return true; throw Error(ErrorValidateConfigTemplatePathStyled); }; var validateTemplatePathGraphic = (path7) => { if (path7) return true; throw Error(ErrorValidateConfigTemplatePathGraphic); }; // bin/entities/Config/index.ts var makeConfiguration = async (userConfigPath, ...cliArgs) => { const config = new Configuration(userConfigPath, cliArgs); await config.createConfig(); return config.getConfig(); }; var Configuration = class { baseConfiguration; userConfigPath; cliArgs; config = baseConfig; constructor(userConfigPath, cliArgs) { this.baseConfiguration = baseConfig; this.userConfigPath = userConfigPath; this.cliArgs = cliArgs; } async createConfig() { let config = null; config = await createConfiguration( this.baseConfiguration, this.userConfigPath, this.cliArgs ); validateConfig(config); this.config = config; return this.getConfig(); } getConfig() { return this.config; } }; // bin/usecases/interactors/common/createPage.ts function createPage(figmaPages, matchingPageName) { if (!figmaPages || figmaPages.length === 0) throw Error(ErrorCreatePage); const page = figmaPages.filter( (page2) => page2.name.toLowerCase().replace(/ /g, "") === matchingPageName.toLowerCase().replace(/ /g, "") ); if (page.length > 0 && page[0].children) return page[0].children; return []; } // bin/entities/FigmagicElement/index.ts var import_crypto = require("crypto"); // bin/entities/FigmagicElement/logic/parseCssFromElement.ts var path2 = __toESM(require("path"), 1); // bin/entities/FigmagicElement/logic/getFileContents.ts var path = __toESM(require("path"), 1); // bin/entities/FigmagicElement/logic/sliceOutObjectFromFile.ts var import_fs2 = __toESM(require("fs"), 1); var sliceOutObjectFromFile = (path7) => { if (!path7) throw Error(ErrorSliceOutObjectFromFile); const data = import_fs2.default.readFileSync(path7, "utf8"); if (!data) throw Error(ErrorSliceOutObjectFromFile); const slicedData = data.slice(data.indexOf("{"), data.indexOf("}") + 1); if (isJson(slicedData)) return JSON.parse(slicedData); return slicedData; }; var isJson = (input) => { if (typeof input !== "string") return false; try { JSON.parse(input); return true; } catch (_e) { return false; } }; // bin/entities/FigmagicElement/logic/getFileContents.ts function getFileContents(filepath, filename, format) { if (!filepath || !filename || !format) throw Error(ErrorGetFileContents); const file = path.join(`${process.cwd()}`, filepath, `${filename}.${format}`); return sliceOutObjectFromFile(file); } // bin/frameworks/string/roundNumber.ts function roundNumber(num, decimals = 6) { const number = num.toFixed(decimals); return parseFloat(number); } // bin/frameworks/string/calculateDegree2Point.ts function calculateDegree2Point(point1, point2) { if (!point1 || !point2) throw Error(ErrorCalculateDegree2Point); const deltaY = point2.x - point1.x; const deltaX = point2.y - point1.y; const angleInRadians = Math.atan2(deltaY, deltaX); let angleInDegrees = 180 - angleInRadians * 180 / Math.PI; if (angleInDegrees < 0) angleInDegrees += 360; return roundNumber(angleInDegrees, 2); } // bin/frameworks/string/roundColorValue.ts function roundColorValue(quantity = 0, scale = 255) { if (scale < 0 || scale > 255) throw Error(ErrorRoundColorValue); const minValue = 0; const maxValue = 1; if (quantity < minValue) quantity = minValue; if (quantity > maxValue) quantity = maxValue; if (scale <= 1) return parseFloat(quantity.toFixed(2)); return parseFloat((quantity * scale).toFixed(0)); } // bin/frameworks/string/createLinearGradientString.ts function createLinearGradientString(fills) { if (!fills) throw Error(ErrorCreateLinearGradientString); if (!fills.gradientHandlePositions) throw Error(ErrorCreateLinearGradientString); let str = `linear-gradient(`; const gradientStops = fills.gradientStops ? fills.gradientStops : null; if (!gradientStops) throw Error(); const gradientHandlePositions = fills.gradientHandlePositions; const degree = calculateDegree2Point( gradientHandlePositions[0], gradientHandlePositions[1] ); if (degree) str += `${degree}deg, `; gradientStops.forEach((fill, index) => { const R = roundColorValue(fill.color?.r, 255); const G = roundColorValue(fill.color?.g, 255); const B = roundColorValue(fill.color?.b, 255); const A = roundColorValue(fill.opacity ? fill.opacity : fill.color?.a, 1); const position = roundColorValue( // @ts-ignore parseFloat(fill.position ? fill.position : "0"), 100 ); if (index > 0) str += ` `; str += `rgba(${R}, ${G}, ${B}, ${A}) ${position}%`; if (index < gradientStops.length - 1) str += `,`; if (index >= gradientStops.length - 1) str += `)`; }); return str; } // bin/frameworks/string/convertRgbaToHex.ts function convertRgbaToHex(color) { if (!color) throw Error(ErrorConvertRgbaToHex); const values = color.replace(/rgba?\(/, "").replace(/\)/, "").replace(/[\s+]/g, "").split(","); const [r, g, b, a] = values; return rgbaToHex(parseInt(r), parseInt(g), parseInt(b), parseFloat(a)); } function rgbaToHex(r, g, b, a) { const toHex = (number) => { const hex = Math.round(number).toString(16); return hex.length === 1 ? "0" + hex : hex; }; const alpha = a >= 0 && a <= 1 ? toHex(a * 255) : "ff"; return "#" + toHex(r) + toHex(g) + toHex(b) + alpha; } // bin/frameworks/string/createSolidColorString.ts function createSolidColorString(fills, outputFormatColors) { if (!fills) throw Error(ErrorCreateSolidColorString); const useHex = outputFormatColors === "hex"; const R = roundColorValue(fills.color?.r, 255); const G = roundColorValue(fills.color?.g, 255); const B = roundColorValue(fills.color?.b, 255); const A = roundColorValue(fills.opacity ? fills.opacity : fills.color?.a, 1); const rgbaString = `rgba(${R}, ${G}, ${B}, ${A})`; return useHex ? convertRgbaToHex(rgbaString) : rgbaString; } // bin/entities/FigmagicElement/logic/parsers/getBackgroundColor.ts function getBackgroundColor(element, outputFormatColors) { if (!element) throw Error(ErrorGetBackgroundColor); if (!element.fills || !element.fills[0] || !element.fills[0].type || element.type === "TEXT") return null; const fills = element.fills[0]; if (fills.type === "SOLID") return createSolidColorString(fills, outputFormatColors); if (fills.type === "GRADIENT_LINEAR") return createLinearGradientString(fills); return null; } // bin/entities/FigmagicElement/logic/parsers/getBorderColor.ts function getBorderColor(element) { if (!element) throw Error(ErrorGetBorderColor); if (!(element.strokes && element.strokes.length > 0 && element.strokes[0].type === "SOLID")) return null; if (!element.strokes[0].color) throw Error(ErrorGetBorderColor); const R = roundColorValue(element.strokes[0].color.r); const G = roundColorValue(element.strokes[0].color.g); const B = roundColorValue(element.strokes[0].color.b); const A = roundColorValue(element.strokes[0].color.a, 1); return `rgba(${R}, ${G}, ${B}, ${A})`; } // bin/entities/FigmagicElement/logic/parsers/getPaddingX.ts function getPaddingX(textElement, element) { if (!textElement || !element) return null; if (!textElement.absoluteBoundingBox || !element.absoluteBoundingBox) throw Error(ErrorGetPaddingX); const parentWidth = element.absoluteBoundingBox.width; const textWidth = textElement.absoluteBoundingBox.width; const paddingLeft = ( // @ts-ignore textElement.absoluteBoundingBox.x - element.absoluteBoundingBox.x ); const paddingRight = parentWidth - (paddingLeft + textWidth); return { left: Math.round(paddingLeft), right: Math.round(paddingRight) }; } // bin/entities/FigmagicElement/logic/parsers/getPaddingY.ts function getPaddingY(textElement, element) { if (!textElement) return null; if (!element.absoluteBoundingBox || !element.absoluteBoundingBox.height || !textElement.absoluteBoundingBox || !textElement.absoluteBoundingBox.height) throw Error(ErrorGetPaddingY); const parentHeight = element.absoluteBoundingBox.height; const textHeight = textElement.absoluteBoundingBox.height; const paddingTop = ( // @ts-ignore textElement.absoluteBoundingBox.y - element.absoluteBoundingBox.y ); const paddingBottom = parentHeight - (paddingTop + textHeight); return { top: Math.round(paddingTop), bottom: Math.round(paddingBottom) }; } // bin/entities/FigmagicElement/logic/parsers/getShadow.ts function getShadow(element) { if (!element) throw Error(ErrorGetShadow); if (!(element.effects && element.effects[0] && element.effects[0].type === "DROP_SHADOW")) return null; const dropShadow = element.effects[0]; const X = dropShadow.offset.x; const Y = dropShadow.offset.y; const radius = dropShadow.radius; const R = roundColorValue(dropShadow.color.r); const G = roundColorValue(dropShadow.color.g); const B = roundColorValue(dropShadow.color.b); const A = roundColorValue(dropShadow.color.a, 1); return `${X}px ${Y}px ${radius}px rgba(${R}, ${G}, ${B}, ${A})`; } // bin/frameworks/string/getAlphaInPercent.ts var getAlphaInPercent = (color) => { if (!color) throw Error(ErrorGetAlphaInPercent); const sectioned = color.split(","); return ( // @ts-ignore sectioned[sectioned.length - 1].replace(/ /gi, "").replace(")", "") * 100 + "%" ); }; // bin/frameworks/string/normalizeUnits.ts function normalizeUnits(value, currentUnit, newUnit, remSize) { if (!value || !currentUnit || !newUnit) throw Error(ErrorNormalizeUnits); const rootSize = setRootSize(currentUnit); const unitSize = setUnitSize(value, newUnit, remSize); if (rootSize === void 0 || unitSize === void 0) throw Error(ErrorNormalizeUnitsUndefined); return getAdjustedValues(value, rootSize, unitSize, newUnit); } function setRootSize(currentUnit) { if (currentUnit === "px" || currentUnit === "percent") return 1; return void 0; } function setUnitSize(value, newUnit, remSize) { if (newUnit === "unitless") return value / 100; else if (newUnit === "rem" || newUnit === "em" || newUnit === "px") { if (!remSize) throw Error(ErrorNormalizeUnitsNoRemSize); return remSize; } else return void 0; } function getAdjustedValues(value, rootSize, unitSize, newUnit) { if (newUnit === "unitless") return `${unitSize}`; else if (newUnit === "px") return `${value}${newUnit}`; else { const adjustedValue = rootSize && unitSize ? value * (rootSize / unitSize) : value; return `${adjustedValue}${newUnit}`; } } // bin/frameworks/string/convertHexToRgba.ts function convertHexToRgba(color) { if (!color) throw Error(ErrorConvertHexToRgba); const R = parseInt(color.slice(1, 3), 16); const G = parseInt(color.slice(3, 5), 16); const B = parseInt(color.slice(5, 7), 16); const A = 1; return `rgba(${R}, ${G}, ${B}, ${A})`; } // bin/entities/FigmagicElement/logic/getTokenMatch.ts function getTokenMatch(tokens, tokenFileName, property, expectedValue, remSize, outputFormatColors) { if (!tokenFileName || !property || !expectedValue) throw Error(ErrorGetTokenMatch); let css = ``; let imports = []; if (!tokens) return { updatedCss: css, updatedImports: imports }; if (property === "padding") { const PADDING_MATCH = matchPadding( expectedValue, remSize, tokens, tokenFileName, property, css, imports ); if (PADDING_MATCH) { css = PADDING_MATCH.css; imports = PADDING_MATCH.imports; } } else { const OTHER_MATCH = matchOther( expectedValue, remSize, outputFormatColors || "rgba", tokens, tokenFileName, property, css, imports ); css = OTHER_MATCH.css; imports = OTHER_MATCH.imports; } return { updatedCss: css, updatedImports: imports }; } function matchPadding(expectedValue, remSize, tokens, tokenFileName, property, css, imports) { const keys = Object.keys(expectedValue); if (typeof expectedValue !== "object") return; keys.forEach((key) => { let foundMatch = false; const keyValue = expectedValue[key]; if (keyValue) { if (!remSize) throw Error(ErrorGetTokenMatchNoRemSize); const parsedValue = getParsedValue(keyValue); const value = normalizeUnits(parsedValue, "px", "rem", remSize); Object.entries(tokens).forEach((token) => { if (token[1] === value) { css += `${property}-${key}: \${${tokenFileName}['${token[0]}']}; `; foundMatch = true; } }); if (!foundMatch) { console.log(`${MsgGetTokenMatchNoMatch} ${property}: ${value}`); css += `${property}-${key}: ${value}; `; } } }); imports.push(tokenFileName); return { css, imports }; } function matchOther(expectedValue, remSize, outputFormatColors, tokens, tokenFileName, property, css, imports) { let foundMatch = false; Object.entries(tokens).forEach((token) => { const tokenValue = token[1]; const isTokenMatch = checkIfTokenMatch( property, tokenValue, expectedValue, remSize ); if (isTokenMatch) { css += `${property}: \${${tokenFileName}['${token[0]}']}; `; imports.push(tokenFileName); foundMatch = true; } }); if (!foundMatch) { const notFoundMessage = createNotFoundMessage(property, expectedValue); if (property === "height" || property === "font-size") expectedValue += `px`; const useHex = outputFormatColors && outputFormatColors === "hex"; console.log(notFoundMessage); css += `${property}: ${useHex ? convertRgbaToHex(expectedValue) : expectedValue}; `; } return { css, imports }; } function getParsedValue(key) { if (typeof key !== "number") return parseFloat(key); return key; } function checkIfTokenMatch(property, tokenValue, expectedValue, remSize) { if (property.includes("color") && tokenValue[0] === "#") return convertHexToRgba(tokenValue) === expectedValue; const val = valueThroughRem(tokenValue, property, remSize); if (val) return val === expectedValue; return tokenValue == expectedValue; } function valueThroughRem(tokenValue, property, remSize) { if (tokenValue && typeof tokenValue === "string") { if (property === "letter-spacing") return tokenValue; if (tokenValue.match("rem") || tokenValue.match("em")) return parseFloat(tokenValue) * remSize; } return null; } function createNotFoundMessage(property, expectedValue) { let notFoundMessage = `${MsgGetTokenMatchNoMatch} ${property}: ${expectedValue}`; if (property.includes("color")) notFoundMessage += ` (HEX: ${convertRgbaToHex(expectedValue)}, ${getAlphaInPercent( expectedValue )})`; if (property === "height" || property === "font-size") notFoundMessage += `px`; return notFoundMessage; } // bin/entities/FigmagicElement/logic/parsers/updateParsing.ts function updateParsing(css, updatedCss, imports, updatedImports) { if (!css || !imports) throw Error(ErrorUpdateParsing); return { css: updatedCss ? css += updatedCss : css, imports: updatedImports ? updatedImports.forEach((i) => imports.push(i)) : imports }; } // bin/entities/FigmagicElement/logic/parsers/parseBackgroundColor.ts function parseBackgroundColor(css, imports, params) { if (!css || !imports || !params) throw Error(ErrorParseBackgroundColor); const { colors: colors2, backgroundColor, remSize, outputFormatColors } = params; const property = backgroundColor.includes("gradient") ? "background" : "background-color"; const { updatedCss, updatedImports } = getTokenMatch( colors2, "colors", property, backgroundColor, remSize, outputFormatColors ); return updateParsing(css, updatedCss, imports, updatedImports); } // bin/entities/FigmagicElement/logic/parsers/parseBorderColor.ts function parseBorderColor(css, imports, params) { if (!css || !imports || !params) throw Error(ErrorParseBorderColor); const { colors: colors2, borderColor, remSize, outputFormatColors } = params; const { updatedCss, updatedImports } = getTokenMatch( colors2, "colors", "border-color", borderColor, remSize, outputFormatColors ); return updateParsing(css, updatedCss, imports, updatedImports); } // bin/entities/FigmagicElement/logic/parsers/parseBorderRadius.ts function parseBorderRadius(css, imports, params) { if (!css || !imports || !params) throw Error(ErrorParseBorderRadius); const { radii, borderRadius, remSize, outputFormatColors } = params; const { updatedCss, updatedImports } = getTokenMatch( radii, "radii", "border-radius", borderRadius, remSize, outputFormatColors ); return updateParsing(css, updatedCss, imports, updatedImports); } // bin/entities/FigmagicElement/logic/parsers/parseBorderWidth.ts function parseBorderWidth(css, imports, params) { if (!css || !imports || !params) throw Error(ErrorParseBorderWidth); const { borderWidths, borderWidth, remSize, outputFormatColors } = params; const { updatedCss, updatedImports } = getTokenMatch( borderWidths, "borderWidths", "border-width", borderWidth, remSize, outputFormatColors ); return updateParsing(css, updatedCss, imports, updatedImports); } // bin/entities/FigmagicElement/logic/parsers/parseHeight.ts function parseHeight(css, imports, params) { if (!css || !imports || !params) throw Error(ErrorParseHeight); const { spacing, height, remSize, outputFormatColors } = params; const { updatedCss, updatedImports } = getTokenMatch( spacing, "spacing", "height", height, remSize, outputFormatColors ); return updateParsing(css, updatedCss, imports, updatedImports); } // bin/entities/FigmagicElement/logic/parsers/parsePadding.ts function parsePadding(css, imports, params) { if (!css || !imports || !params) throw Error(ErrorParsePadding); const { padding, spacing, remSize } = params; if (!(padding && Object.keys(padding).length > 0)) return { css, imports }; const paddings = Object.values(padding).map((p) => p); if (paddings.every((item) => item === 0)) return updateParsing(css, null, imports, null); const { updatedCss, updatedImports } = getTokenMatch( spacing, "spacing", "padding", padding, remSize ); return updateParsing(css, updatedCss, imports, updatedImports); } // bin/entities/FigmagicElement/logic/parsers/parseShadow.ts function parseShadow(css, imports, params) { if (!css || !imports || !params) throw Error(ErrorParseShadow); const { shadows, shadow, remSize, outputFormatColors } = params; const { updatedCss, updatedImports } = getTokenMatch( shadows, "shadows", "box-shadow", shadow, remSize, outputFormatColors ); return updateParsing(css, updatedCss, imports, updatedImports); } // bin/entities/FigmagicElement/logic/parseCssFromElement.ts function parseCssFromElement(layoutElement, textElement, remSize, outputFormatToken, outputFolderTokens) { if (!layoutElement || !remSize || !outputFormatToken || !outputFolderTokens) throw Error(ErrorParseCssFromElement); const tokenPath = process.env.IS_TEST ? path2.join(`testdata`, `tokens`) : outputFolderTokens; const { borderWidths, colors: colors2, radii, shadows, spacing } = getFiles( tokenPath, outputFormatToken ); let css = `width: 100%; box-sizing: border-box; border: 0; border-style: solid; `; if (layoutElement.fills && layoutElement.fills.some((fill) => fill["type"] === "IMAGE")) css += `object-fit: cover; `; let imports = []; const padding = calcPadding( { textElement, layoutElement, css, imports, remSize }, spacing ); css = padding.css; imports = padding.imports; const height = calcHeight( { layoutElement, css, imports, remSize }, spacing ); css = height.css; imports = height.imports; const bgColor = calcBackgroundColor( { layoutElement, css, imports, remSize }, colors2 ); css = bgColor.css; imports = bgColor.imports; const borderWidth = calcBorderWidth( { layoutElement, css, imports, remSize }, borderWidths ); css = borderWidth.css; imports = borderWidth.imports; const borderColor = calcBorderColor( { layoutElement, css, imports, remSize }, colors2 ); css = borderColor.css; imports = borderColor.imports; const borderRadius = calcBorderRadius( { layoutElement, css, imports, remSize }, radii ); css = borderRadius.css; imports = borderRadius.imports; const shadow = calcShadows( { layoutElement, css, imports, remSize }, shadows ); css = shadow.css; imports = shadow.imports; const NEW_CSS = reduceDuplicates(css); return { updatedCss: NEW_CSS, updatedImports: imports }; } var reduceDuplicates = (str) => Array.from(new Set(str.split(/;/gi))).toString().replace(/,\n/gi, ";\n"); var getFiles = (filePath, outputFormatToken) => { const borderWidths = getFileContents( filePath, "borderWidths", outputFormatToken ); const colors2 = getFileContents(filePath, "colors", outputFormatToken); const radii = getFileContents(filePath, "radii", outputFormatToken); const shadows = getFileContents(filePath, "shadows", outputFormatToken); const spacing = getFileContents(filePath, "spacing", outputFormatToken); return { borderWidths, colors: colors2, radii, shadows, spacing }; }; function calcPadding(calcData, spacing) { const { textElement, layoutElement, remSize } = calcData; let { css, imports } = calcData; const paddingY = textElement ? getPaddingY(textElement, layoutElement) : null; const paddingX = textElement ? getPaddingX(textElement, layoutElement) : null; if (paddingY && paddingX) { const padding = { ...paddingY, ...paddingX }; const parsedPadding = parsePadding(css, imports, { padding, spacing, remSize }); css += parsedPadding.css; if (parsedPadding.imports) imports = imports.concat(parsedPadding.imports); } return { css, imports }; } function calcHeight(calcData, spacing) { const { layoutElement, remSize, outputFormatColors } = calcData; let { css, imports } = calcData; const height = layoutElement.absoluteBoundingBox ? layoutElement.absoluteBoundingBox.height : null; if (height) { const parsedValue = parseHeight(css, imports, { spacing, height, remSize, outputFormatColors }); css += parsedValue.css; if (parsedValue.imports) imports = imports.concat(parsedValue.imports); } return { css, imports }; } function calcBackgroundColor(calcData, colors2) { const { layoutElement, remSize, outputFormatColors } = calcData; let { css, imports } = calcData; const backgroundColor = getBackgroundColor(layoutElement, outputFormatColors); if (backgroundColor) { const parsedValue = parseBackgroundColor(css, imports, { colors: colors2, backgroundColor, remSize, outputFormatColors }); css += parsedValue.css; if (parsedValue.imports) imports = imports.concat(parsedValue.imports); } return { css, imports }; } function calcBorderWidth(calcData, borderWidths) { const { layoutElement, remSize, outputFormatColors } = calcData; let { css, imports } = calcData; const borderWidth = layoutElement.strokeWeight ? `${layoutElement.strokeWeight}px` : null; if (borderWidth) { const parsedValue = parseBorderWidth(css, imports, { borderWidths, borderWidth, remSize, outputFormatColors }); css += parsedValue.css; if (parsedValue.imports) imports = imports.concat(parsedValue.imports); } return { css, imports }; } function calcBorderColor(calcData, colors2) { const { layoutElement, remSize, outputFormatColors } = calcData; let { css, imports } = calcData; const borderColor = getBorderColor(layoutElement); if (borderColor) { const parsedValue = parseBorderColor(css, imports, { colors: colors2, borderColor, remSize, outputFormatColors }); css += parsedValue.css; if (parsedValue.imports) imports = imports.concat(parsedValue.imports); } return { css, imports }; } function calcBorderRadius(calcData, radii) { const { layoutElement, remSize, outputFormatColors } = calcData; let { css, imports } = calcData; const borderRadius = layoutElement.cornerRadius ? `${layoutElement.cornerRadius}px` : null; if (borderRadius) { const parsedValue = parseBorderRadius(css, imports, { radii, borderRadius, remSize, outputFormatColors }); css += parsedValue.css; if (parsedValue.imports) imports = imports.concat(parsedValue.imports); } return { css, imports }; } function calcShadows(calcData, shadows) { const { layoutElement, remSize, outputFormatColors } = calcData; let { css, imports } = calcData; const shadow = getShadow(layoutElement); if (shadow) { const parsedValue = parseShadow(css, imports, { shadows, shadow, remSize, outputFormatColors }); css += parsedValue.css; if (parsedValue.imports) imports = imports.concat(parsedValue.imports); } return { css, imports }; } // bin/entities/FigmagicElement/logic/parseTypographyStylingFromElement.ts var path3 = __toESM(require("path"), 1); function parseTypographyStylingFromElement(typographyElement) { const { textElement, remSize, outputFormatTokens, outputFormatColors, letterSpacingUnit, outputFolderTokens, usePostscriptFontNames } = typographyElement; if (!textElement || !remSize) throw Error(ErrorParseTypographyStylingFromElement); const tokenPath = process.env.IS_TEST ? path3.join("testdata", "tokens") : outputFolderTokens; const { colors: colors2, fontFamilies, fontSizes, fontWeights, letterSpacings, lineHeights } = getFiles2(tokenPath, outputFormatTokens); let css = ``; let imports = []; const fontColor = calcFontColor( { textElement, css, imports, remSize }, colors2 ); css = fontColor.css; imports = fontColor.imports; const calcedFontSize = calcFontSize( { textElement, css, imports, remSize }, fontSizes ); css = calcedFontSize.css; imports = calcedFontSize.imports; const fontSize = calcedFontSize.fontSize; const fontFamily = calcFontFamily( { textElement, css, imports, remSize, outputFormatColors, usePostscriptFontNames }, fontFamilies ); css = fontFamily.css; imports = fontFamily.imports; const fontWeight = calcFontWeight( { textElement, css, imports, remSize }, fontWeights ); css = fontWeight.css; imports = fontWeight.imports; const fontLineHeight = calcFontLineHeight( { textElement, css, imports, remSize }, lineHeights ); css = fontLineHeight.css; imports = fontLineHeight.imports; const fontLetterSpacing = calcLetterSpacing( { textElement, css, imports, remSize }, letterSpacings, letterSpacingUnit, fontSize ); css = fontLetterSpacing.css; imports = fontLetterSpacing.imports; css = calcFontAlignment({ textElement, css, imports, remSize }); css = calcFontCase({ textElement, css, imports, remSize }); const updatedCss = reduceCssDuplicates(css); return { updatedCss, updatedImports: imports }; } var getFiles2 = (filePath, outputFormatTokens) => { const colors2 = getFileContents(filePath, "colors", outputFormatTokens); const fontFamilies = getFileContents( filePath, "fontFamilies", outputFormatTokens ); const fontSizes = getFileContents(filePath, "fontSizes", outputFormatTokens); const fontWeights = getFileContents( filePath, "fontWeights", outputFormatTokens ); const letterSpacings = getFileContents( filePath, "letterSpacings", outputFormatTokens ); const lineHeights = getFileContents( filePath, "lineHeights", outputFormatTokens ); return { colors: colors2, fontFamilies, fontSizes, fontWeights, letterSpacings, lineHeights }; }; var reduceCssDuplicates = (css) => Array.from(new Set(css.split(/;/gi))).toString().replace(/,\n/gi, ";\n"); var getFontColor = (textElement) => { if (textElement.fills) { if (textElement.fills[0] && textElement.fills[0].type === "SOLID") { if (!textElement.fills[0].color) throw Error(ErrorGetFontColor); const R = roundColorValue(textElement.fills[0].color.r); const G = roundColorValue(textElement.fills[0].color.g); const B = roundColorValue(textElement.fills[0].color.b); const A = roundColorValue(textElement.fills[0].color.a, 1); return `rgba(${R}, ${G}, ${B}, ${A})`; } } return null; }; var getFontSize = (textElement) => { if (textElement.type === "TEXT" && textElement.style) return parseFloat(textElement.style.fontSize); return null; }; var getFontFamily = (textElement, usePostscriptFontNames = false) => { if (textElement.type === "TEXT" && textElement.style) return usePostscriptFontNames ? textElement.style.fontPostScriptName : textElement.style.fontFamily; return null; }; var getFontWeight = (textElement) => { if (textElement.type === "TEXT" && textElement.style) return textElement.style.fontWeight; return null; }; var getFontLineHeight = (textElement) => { if (textElement.type === "TEXT") { if (textElement.style) { if (textElement.style.lineHeightPercentFontSize) { return textElement.style.lineHeightPercentFontSize / 100; } else return 1; } } return null; }; var getFontAlignment = (textElement) => { if (textElement.type === "TEXT" && textElement.style) return textElement.style.textAlignHorizontal; return null; }; var getFontLetterSpacing = (textElement) => { if (textElement.type === "TEXT" && textElement.style && textElement.style.letterSpacing) return parseFloat(textElement.style.letterSpacing); return null; }; var getFontCase = (textElement) => { if (textElement.type === "TEXT" && textElement.style && textElement.style.textCase) { if (textElement.style.textCase === "LOWER") return "lowercase"; if (textElement.style.textCase === "UPPER") return "uppercase"; if (textElement.style.textCase === "TITLE") return "capitalize"; } return null; }; function calcFontColor(calcData, colors2) { const { textElement, remSize, outputFormatColors, imports } = calcData; let { css } = calcData; const FONT_COLOR = getFontColor(textElement); if (FONT_COLOR && colors2) { const { updatedCss, updatedImports } = getTokenMatch( colors2, "colors", "color", FONT_COLOR, remSize, outputFormatColors ); css += updatedCss; updatedImports.forEach((i) => imports.push(i)); } return { css, imports }; } function calcFontSize(calcData, fontSizes) { const { textElement, remSize, outputFormatColors, imports } = calcData; let { css } = calcData; const fontSize = getFontSize(textElement); if (fontSize && fontSizes) { const { updatedCss, updatedImports } = getTokenMatch( fontSizes, "fontSizes", "font-size", fontSize, remSize, outputFormatColors ); css += updatedCss; updatedImports.forEach((i) => imports.push(i)); } return { css, imports, fontSize }; } function calcFontFamily(calcData, fontFamilies) { const { textElement, remSize, outputFormatColors, usePostscriptFontNames, imports } = calcData; let { css } = calcData; const fontFamily = getFontFamily(textElement, usePostscriptFontNames); if (fontFamily && fontFamilies) { const { updatedCss, updatedImports } = getTokenMatch( fontFamilies, "fontFamilies", "font-family", fontFamily, remSize, outputFormatColors ); css += updatedCss; updatedImports.forEach((i) => imports.push(i)); } return { css, imports }; } function calcFontWeight(calcData, fontWeights) { const { textElement, remSize, outputFormatColors, imports } = calcData; let { css } = calcData; const fontWeight = getFontWeight(textElement); if (fontWeight && fontWeights) { const { updatedCss, updatedImports } = getTokenMatch( fontWeights, "fontWeights", "font-weight", fontWeight, remSize, outputFormatColors ); css += updatedCss; updatedImports.forEach((i) => imports.push(i)); } return { css, imports }; } function calcFontLineHeight(calcData, lineHeights) { const { textElement, remSize, outputFormatColors, imports } = calcData; let { css } = calcData; const fontLineHeight = getFontLineHeight(textElement); if (fontLineHeight && lineHeights) { const { updatedCss, updatedImports } = getTokenMatch( lineHeights, "lineHeights", "line-height", fontLineHeight, remSize, outputFormatColors ); css += updatedCss; updatedImports.forEach((i) => imports.push(i)); } return { css, imports }; } function calcLetterSpacing(calcData, letterSpacings, letterSpacingUnit, fontSize) { const { textElement, remSize, outputFormatColors, imports } = calcData; let { css } = calcData; const letterSpacing = getFontLetterSpacing(textElement); if (letterSpacing && fontSize && letterSpacings) { const size = letterSpacing / fontSize; const sizeString = `${size}${letterSpacingUnit}`; const { updatedCss, updatedImports } = getTokenMatch( letterSpacings, "letterSpacings", "letter-spacing", sizeString, remSize, outputFormatColors ); css += updatedCss; updatedImports.forEach((i) => imports.push(i)); } return { css, imports }; } function calcFontAlignment(calcData) { const { textElement } = calcData; let { css } = calcData; const fontAlignment = getFontAlignment(textElement); if (fontAlignment) { const alignment = fontAlignment.toLowerCase(); css += `text-align: ${alignment}; `; } return css; } function calcFontCase(calcData) { const { textElement } = calcData; let { css } = calcData; const fontCase = getFontCase(textElement); if (fontCase) css += `text-transform: ${fontCase}; `; return css; } // bin/entities/FigmagicElement/logic/classRepresentsTextOnlyElement.ts var classRepresentsTextOnlyElement = (className, textOnlySubchildren = []) => { const cleanedName = className.replace(" {", ""); const rootClassName = cleanedName.slice(1, cleanedName.length - 11); let result = false; textOnlySubchildren.forEach((name) => { if (name.startsWith(`${rootClassName}`)) result = true; }); return result; }; // bin/entities/FigmagicElement/logic/cleanArrays.ts function cleanArrays(classNames, classContent, textOnlySubchildren) { if (!classNames || !classContent) throw Error(ErrorCleanArrays); const classes = []; let skipNext = false; classContent.forEach((currentClassContent, index) => { if (skipNext) { skipNext = false; return; } const className = classNames[index]; const isNextClassSameLogicalClass = className === classNames[index + 1]; const isTextOnly = classRepresentsTextOnlyElement( className, textOnlySubchildren ); const layout = (() => { if (isTextOnly) return []; return currentClassContent.split(/\n/gi).filter((item) => item).filter((item) => item !== "}"); })(); const typography = (() => { const content = (() => { if (!isNextClassSameLogicalClass) return currentClassContent; skipNext = true; return classContent[index + 1]; })(); return content.split(/\n/gi).filter((item) => item).filter((item) => item !== "}"); })(); classes.push({ className, css: [...layout, ...typography] }); }); return classes; } // bin/frameworks/string/getId.ts function getId(str) { const match = str.match(/__#(.*?) /gi); if (match) return match[0].replace("__#", ""); return null; } // bin/frameworks/string/removeAllIds.ts function removeAllIds(str) { return str.replace(/__#(.*?) /gi, " "); } // bin/entities/FigmagicElement/logic/createCssString.ts function createCssString(intersections, uniqueValues) { if (!intersections || !uniqueValues) throw Error(ErrorCreateCssString); uniqueValues.reverse(); let nestingDepth = 0; let cssString = ` `; intersections.forEach((i) => cssString += ` ${i} `); cssString += ` `; uniqueValues.forEach((cssItem, index) => { const { css, className } = cssItem; const fixedClassName = getFixedClassName(className); const space = getSpacing(nestingDepth); const innerSpace = getSpacing(nestingDepth + 1); cssString += `${space}${fixedClassName} `; css.forEach((item) => cssString += `${innerSpace}${item} `); const isLastElementWithClass = !uniqueValues[index + 1] ? true : checkIfLastElementWithClassname( className, uniqueValues[index + 1].className ); if (nestingDepth !== 0 && !isLastElementWithClass) cssString += `${space}} `; if (isLastElementWithClass) { for (let i = 0; i <= nestingDepth + 1; i++) { const _space = getSpacing(nestingDepth); cssString += `${_space}} `; nestingDepth--; } cssString += ` `; nestingDepth = 0; return; } if (nestingDepth < 1) nestingDepth++; }); if (hasOpenBracketAtEnd(cssString)) { const splitString = cssString.split(";"); cssString = cssString.replace(splitString[splitString.length - 1], "\n"); } cssString = removeAllIds(cssString); return cssString; } function hasOpenBracketAtEnd(str) { return str.slice(str.length - 5, str.length).includes("{"); } function getFixedClassName(className) { if (className.includes(".:")) return className.replace(".:", "&:"); else if (className.includes(".")) return `&${className}`; return ""; } function checkIfLastElementWithClassname(className, nextClassName) { if (getId(className) !== getId(nextClassName)) return true; return false; } function getSpacing(depth) { let spaces = ``; for (let i = 0; i <= depth; i++) { spaces += ` `; } return spaces; } // bin/entities/FigmagicElement/logic/getIntersectingValues.ts function getIntersectingValues(arrays) { if (!arrays) throw Error(ErrorGetIntersectingValues); const cssArrays = arrays.map((a) => a.css); const reducedValues = cssArrays.reduce( (prev, curr) => prev.filter((val) => curr.includes(val)) ); const intersectingValues = [...new Set(reducedValues)]; return intersectingValues; } // bin/entities/FigmagicElement/logic/getUniqueValues.ts function getUniqueValues(arrays, intersections) { if (!arrays || !intersections) throw Error(ErrorGetUniqueValues); const cssArrays = arrays.map((arr) => arr.css); const nonIntersectingValues = cssArrays.map( (arr) => arr.filter((val) => !intersections.includes(val)) ); const fixedUniqueValues = []; const values = nonIntersectingValues.map((arr) => [ ...new Set(arr) ]); values.forEach((item, index) => { const usedProperties = []; const deduplicatedCssRows = item.filter((cssRow) => { const property = cssRow.split(":")[0]; if (!usedProperties.includes(property)) { usedProperties.push(property); return cssRow; } }); if (deduplicatedCssRows.length > 0) fixedUniqueValues.push({ css: deduplicatedCssRows, className: arrays[index].className }); }); return fixedUniqueValues; } // bin/frameworks/string/checkIfStringOnlyContainsReturnsOrSpaces.ts function checkIfStringOnlyContainsReturnsOrSpaces(str) { if (!str) throw Error(ErrorCheckIfStringOnlyContainsReturnsOrSpaces); const hasReturns = str.match(/\n/gi); const hasSpaces = str.match(/ /gi); if (hasReturns && hasSpaces) return false; str = str.replace(/\n/gi, "").replace(/ /gi, ""); if (str.length > 0) return false; return true; } // bin/entities/FigmagicElement/logic/processNestedCss.ts function processNestedCss(css, textOnlySubchildren = []) { if (!css) throw Error(ErrorProcessNestedCss); const classNames = css.match(/\..* {/gi); const classContent = css.split(/\..* {/gi); if (checkIfStringOnlyContainsReturnsOrSpaces(classContent[0])) classContent.shift(); const arrays = cleanArrays(classNames, classContent, textOnlySubchildren); const intersectingValues = getIntersectingValues(arrays); const uniqueValues = getUniqueValues(arrays, intersectingValues); return createCssString(intersectingValues, uniqueValues); } // bin/entities/FigmagicElement/index.ts var makeFigmagicElement = (element, config, description = "", isGraphicElement = false) => { return new FigmagicElement(element, config, description, isGraphicElement); }; var FigmagicElement = class { id; name; children; type; isGraphicElement; config; description; element; css; html; extraProps; text; imports; acceptedTypes = ["GROUP", "FRAME", "INSTANCE"]; constructor(element, config, description = "", isGraphicElement) { this.id = element.id; this.name = element.name; this.children = element.children; this.type = element.type; this.config = config; this.description = description; this.isGraphicElement = isGraphicElement; this.element = ``; this.css = ``; this.html = ``; this.extraProps = ``; this.text = ``; this.imports = []; this.init(); } init() { this.setElement(); this.setElementType(); this.setPlaceholderText(); this.setText(); this.setDescription(); if (!this.isGraphicElement) { const { updatedCss, updatedImports } = this.handleElements(); this.setCss(updatedCss); this.imports = [...new Set(updatedImports)]; } } /** * @description Controller to funnel elements to the correct handler. */ handleElements() { const filteredElements = this.children.filter( (child) => child.name[0] !== "_" ); if (filteredElements?.some( (element) => this.acceptedTypes.includes(element.type) )) return this.handleNestedElements(filteredElements); else return this.handleFlatElements(filteredElements); } setCss(css) { this.css = css; } replaceHtml(match, replacement) { this.html = this.html.replace(match, replacement); } addExtraProps(extraProps) { this.extraProps += extraProps; } /** * @description Try setting Figmagic element text to the * characters of an element-root-level layer going by the name ":text". */ setText() { const textChild = this.children?.filter((c) => c.name === ":text")[0]; if (textChild && textChild.characters) this.text = textChild.characters; } /** * @description Set the element type (i.e "div", "input"...). */ setElement() { const elementType = (() => { const element = this.description.match(/element=(.*)/); if (element && element[1]) return element[1]; return "div"; })(); const html = `<${elementType}>{{TEXT}}`; this.html = html; this.element = elementType; } /** * @description Set description for the Figmagic element. * This is later output to the description file. */ setDescription() { let description = this.description; const handleMatch = (regexMatch, currentDescription) => { const match = regexMatch ? regexMatch[0] : null; if (match) return currentDescription.replace(match, ""); return currentDescription; }; if (description.match(/element=(.*)/)) { const regexMatch = description.match(/element=(.*)/); description = handleMatch(regexMatch, description); } if (description.match(/type=(.*)/)) { const regexMatch = description.match(/type=(.*)/); description = handleMatch(regexMatch, description); } if (description.match(/description=(.*)/)) { const regexMatch = description.match(/description=(.*)/); description = handleMatch(regexMatch, description); } this.description = description; } /** * @description Set element's placeholder text value, if we * find an element-root-level layer going by the name ":placeholder". */ setPlaceholderText() { const placeholderText = this.children?.filter( (child) => child.name.toLowerCase() === ":placeholder" )[0]; if (placeholderText) this.addExtraProps(`placeholder="${placeholderText.characters}"`); } /** * @description Set element type (such as "type=checkbox"). * This attribute is specified by the designer in Figma's description box. */ setElementType() { const type = this.description.match(/type=(.*)/)?.[0]; if (type) this.addExtraProps(`type="${type.split("type=")[1]}" `); } /** * @description Handle nested, multi-level elements. * To correctly calculate elements we need both a * "main" (layout) element and a "text" element. */ handleNestedElements(elements) { let css = ``; let imports = []; const childElements = elements.filter( (el) => this.acceptedTypes.includes(el.type) && el.name[0] !== "_" ); const textOnlySubchildren = []; childElements.forEach((childElement) => { const parsedCss = this.parseNestedCss(childElement, this.config); css += parsedCss.css; imports = imports.concat(parsedCss.imports); const subChildElements = childElement.children?.filter( (el) => el.name[0] !== "_" ); if (subChildElements?.every((subChild) => subChild.type === "TEXT")) textOnlySubchildren.push(parsedCss.fixedName); }); return { updatedCss: processNestedCss(css, textOnlySubchildren), updatedImports: imports }; } /** * @description Handle flat, single-layer elements. * To correctly calculate elements we need both a * "main" (layout) element and a "text" element. */ handleFlatElements(elements) { let css = ` `; let imports = []; this.replaceHtml("{{TEXT}}", this.text || ""); const mainElement = elements?.filter( (element) => element.name.toLowerCase() === this.name.toLowerCase() )[0]; const textElement = elements?.filter( (element) => element.type === "TEXT" )[0]; if (textElement) { const { updatedCss, updatedImports } = parseTypographyStylingFromElement({ textElement, remSize: this.config.remSize, usePostscriptFontNames: this.config.usePostscriptFontNames, outputFormatTokens: this.config.outputFormatTokens, outputFormatColors: this.config.outputFormatColors, letterSpacingUnit: this.config.letterSpacingUnit, outputFolderTokens: this.config.outputFolderTokens }); css += updatedCss; imports = imports.concat(updatedImports); this.text = textElement.characters || ""; } if (mainElement) { const { updatedCss, updatedImports } = this.parseFlatCss( mainElement, textElement ); css = this.processFlatCss(css + updatedCss); imports = imports.concat(updatedImports); } return { updatedCss: css, updatedImports: imports }; } /** * @description Process CSS for any nested elements * (i.e. grouped in groups/frames, in Figma). */ parseNestedCss(el, config, id) { let css = ` `; let imports = []; const ID = id || (0, import_crypto.randomUUID)().slice(0, 8); const mainElement = el.children?.filter( (e) => e.type === "RECTANGLE" && e.name[0] !== "_" )[0]; const textElement = el.children?.filter( (e) => e.type === "TEXT" && e.name[0] !== "_" )[0]; if (!mainElement && !textElement) throw Error("Missing both main and text element!"); const fixedName = el.name.replace(/\s/gi, ""); const childElements = el.children?.filter( (child) => this.acceptedTypes.includes(child.type) && child.name[0] !== "_" ); childElements?.forEach((state) => { const PARSED_CSS = this.parseNestedCss(state, config, ID); css += PARSED_CSS.css; imports = imports.concat(PARSED_CSS.imports); }); if (mainElement) { console.log( MsgProcessElementsCreatingElement(mainElement.name, fixedName) ); const { updatedCss, updatedImports } = parseCssFromElement( mainElement, textElement, config.remSize, config.outputFormatTokens, config.outputFolderTokens ); css += ` .${fixedName}__#${ID} { ${updatedCss}}`; imports = imports.concat(updatedImports); } if (textElement) { const { updatedCss, updatedImports } = parseTypographyStylingFromElement({ textElement, remSize: config.remSize, usePostscriptFontNames: config.usePostscriptFontNames, outputFormatTokens: config.outputFormatTokens, outputFormatColors: config.outputFormatColors, letterSpacingUnit: config.letterSpacingUnit, outputFolderTokens: config.outputFolderTokens }); css += ` .${fixedName}__#${ID} { ${updatedCss}}`; imports = imports.concat(updatedImports); } return { css, imports, fixedName }; } /** * @description Process CSS for any "flat" elements */ parseFlatCss(layoutElement, textElement = null) { let css = ``; let imports = []; if (layoutElement) { const fixedName = this.name.replace(/\s/gi, ""); console.log(MsgProcessElementsCreatingElement(this.name, fixedName)); const { updatedCss, updatedImports } = parseCssFromElement( layoutElement, textElement, this.config.remSize, this.config.outputFormatTokens, this.config.outputFolderTokens ); css += updatedCss; imports = imports.concat(updatedImports); } return { updatedCss: css, updatedImports: imports }; } /** * @description Process CSS for flat elements */ processFlatCss(css) { if (!css) throw Error("Missing CSS string when calling processCss()!"); let processedCss = Array.from(new Set(css.split(/\n/gi))).toString(); if (processedCss[0] === ",") processedCss = processedCss.slice(1, processedCss.length); processedCss = ` ` + processedCss; processedCss = processedCss.replace(/;,/gi, ";\n "); processedCss += ` `; return processedCss; } }; // bin/usecases/interactors/elements/processElements.ts function processElements(elementsPage, config, components, isGraphicElement = false) { if (!elementsPage || !components || !config) throw Error(ErrorProcessElements); const filteredElements = elementsPage.filter( (element) => element.type === "COMPONENT" && element.name[0] !== "_" ); const parsedElements = filteredElements.map( (element) => makeFigmagicElement( element, config, components[element.id].description, isGraphicElement ) ); return parsedElements; } // bin/usecases/interactors/elements/processGraphicElementsMap.ts function processGraphicElementsMap(graphics) { if (!graphics) throw Error(ErrorProcessGraphicElementsMap); if (graphics.length === 0) throw Error(ErrorProcessGraphicElementsMap); let imports = ""; graphics.forEach((graphic) => { const graphicName = getFixedGraphicName(graphic.name); imports += `import ${graphicName} from './${graphic.config.outputFolderElements}/${graphic.name.replace(/\s/g, "")}'; `; }); imports += "\n"; let exports2 = ""; graphics.forEach((graphic) => { const graphicName = getFixedGraphicName(graphic.name); exports2 += ` ${graphicName}, `; }); return imports + `export const Graphics = { ${exports2}}; `; } var getFixedGraphicName = (name) => name.split("/")[name.split("/").length - 1].trim().replace(/\s/g, ""); // bin/frameworks/filesystem/checkIfExists.ts var import_fs3 = __toESM(require("fs"), 1); var checkIfExists = (path7) => import_fs3.default.existsSync(path7); // bin/frameworks/filesystem/getSvgFileData.ts var import_fs4 = __toESM(require("fs"), 1); function getSvgFileData(filePath) { if (!filePath) throw Error(ErrorGetSvgFileData); if (!import_fs4.default.existsSync(`${process.cwd()}/${filePath}`)) return ""; return import_fs4.default.readFileSync(`${process.cwd()}/${filePath}`, "utf8"); } // bin/frameworks/filesystem/createFolder.ts var import_fs5 = __toESM(require("fs"), 1); function createFolder(dir) { if (!dir) throw Error(ErrorCreateFolder); if (!import_fs5.default.existsSync(dir)) import_fs5.default.mkdirSync(dir, { recursive: true }); } // bin/frameworks/filesystem/createMissingFoldersFromPath.ts var import_fs6 = __toESM(require("fs"), 1); function createMissingFoldersFromPath(filePath) { if (!filePath) throw Error(ErrorCreateMissingFoldersFromPath); const requiresFolder = filePath.includes("/"); if (!requiresFolder) return; const directoryPath = (() => { let folder = ""; filePath.split("/").forEach((pathSection) => { if (!pathSection.includes(".")) folder += `${pathSection}/`; }); return folder; })(); if (!import_fs6.default.existsSync(directoryPath)) import_fs6.default.mkdirSync(directoryPath, { recursive: true }); } // bin/frameworks/string/sanitizeString.ts function sanitizeString(str, camelize = true) { if (!str) throw Error(ErrorSanitizeString); const regexBasicNonMatch = /[^a-zA-Z0-9]+/g; const regexBasicMatch = /[a-zA-Z0-9]+/g; const regexDashesUnderscoresNonMatch = /[^a-zA-Z0-9-_]+/g; if (camelize) { return str.replace(/[A-Z]+/g, (word) => " " + word).replace(regexBasicNonMatch, " ").trim().replace( regexBasicMatch, (word, index) => index === 0 ? word.toLowerCase() : word[0].toUpperCase() + word.slice(1).toLowerCase() ).replace(/ /g, ""); } else { return str.replace(regexDashesUnderscoresNonMatch, " ").trim().replace(/ /g, ""); } } function sanitizeStringPascalCase(str) { const regexNonMatch = /[^a-zA-Z0-9\/\\]+/g; const regexMatch = /[a-zA-Z0-9\/\\]+/g; return str.replace(/[A-Z]+/g, (word) => " " + word).replace(regexNonMatch, " ").trim().replace( regexMatch, (word) => word[0].toUpperCase() + word.slice(1).toLowerCase() ).replace(/ /g, ""); } // bin/frameworks/system/checkIfVoidElement.ts function checkIfVoidElement(elementName) { if (!elementName) return false; const elements = [ "area", "base", "basefont", "bgsound", "br", "col", "command", "embed", "frame", "hr", "image", "img", "input", "isindex", "keygen", "link", "menuitem", "meta", "nextid", "param", "source", "track", "wbr" ]; return elements.includes(elementName); } // bin/frameworks/filesystem/prepFile.ts var prepComponent = (data) => { if (!data) throw Error(ErrorPrepFileComponent); if (!data.name || !data.filePath || !data.format || !data.templates || !data.element) throw Error(ErrorPrepFileComponent); const { name, filePath, format, templates, text, extraProps, element } = data; const props = extraProps === "" || extraProps === " " ? `${extraProps}` : ` ${extraProps}`; const suffix = "Styled"; const path7 = `${templates.templatePathReact}.${format}`; let template = loadFile(path7); if (checkIfVoidElement(element)) template = template.replace(/{{NAME}}/gi, name).replace('>{children ? children : "{{TEXT}}"}', " />").replace( '>{props.children ? props.children : "{{TEXT}}"}', " />" ).replace(/{{NAME_STYLED}}/gi, `${name}${suffix}`); else template = template.replace(/{{NAME}}/gi, name).replace(/{{NAME_STYLED}}/gi, `${name}${suffix}`).replace(/\s>/gi, ">").replace(/{{TEXT}}/gi, text !== " " ? text : ""); template = template.replace(/{{EXTRA_PROPS}}/gi, props).replace(" >", ">").replace(" ", " "); return { fileContent: `${template}`, filePath: `${filePath}.${format}` }; }; var prepStyledComponents = (data) => { if (!data) throw Error(ErrorPrepFileStyledComponents); if (!data.name || !data.filePath || !data.format || !data.templates || !data.element) throw Error(ErrorPrepFileStyledComponents); const { name, filePath, format, templates, element } = data; const fixedName = sanitizeStringPascalCase(name); const suffix = "Styled"; const path7 = `${templates.templatePathStyled}.${format}`; let template = loadFile(path7); template = template.replace(/{{NAME}}/gi, fixedName).replace(/{{ELEMENT}}/gi, element).replace(/{{NAME_CSS}}/gi, `${fixedName}Css`).replace(/{{NAME_STYLED}}/gi, `${fixedName}${suffix}`); return { fileContent: `${template}`, filePath: `${filePath}${suffix}.${format}` }; }; var prepCss = (data) => { if (!data) throw Error(ErrorPrepFileCss); if (!data.name || !data.filePath || !data.format || !data.file) throw Error(ErrorPrepFileCss); const { name, filePath, format, imports, file } = data; const suffix = "Css"; const fileContent = `// ${MsgGeneratedFileWarning} ${imports} const ${name}${suffix} = \`${file}\`; export default ${name}${suffix};`; return { fileContent, filePath: `${filePath}${suffix}.${format}` }; }; var prepStorybook = (data) => { if (!data) throw Error(ErrorPrepFileStorybook); if (!data.name || !data.filePath || !data.format || !data.templates || !data.text) throw Error(ErrorPrepFileStorybook); const { name, filePath, format, templates, text } = data; const suffix = ".stories"; const path7 = `${templates.templatePathStorybook}.${format}`; let template = loadFile(path7); template = template.replace(/{{NAME}}/gi, name).replace(/{{TEXT}}/gi, text); return { fileContent: `${template}`, filePath: `${filePath}${suffix}.${format}` }; }; var prepDescription = (data) => { if (!data) throw Error(ErrorPrepFileDescription); if (!data.filePath || !data.file || !data.format) throw Error(ErrorPrepFileDescription); const { filePath, file, format } = data; const fileContent = ` ${file}`; return { fileContent, filePath: `${filePath}.description.${format}` }; }; var prepGraphicComponent = (data) => { if (!data) throw Error(ErrorPrepFileGraphicComponent); if (!data.name || !data.filePath || !data.format || !data.templates) throw Error(ErrorPrepFileGraphicComponent); const { name, filePath, format, templates, file } = data; const path7 = `${templates.templatePathGraphic}.${format}`; let template = loadFile(path7); template = template.replace(/{{NAME}}/gi, name).replace(/\s>/gi, ">").replace(/{{SVG}}/gi, file); return { fileContent: `${template}`, filePath: `${filePath}.${format}` }; }; // bin/frameworks/string/createEnumStringOutOfObject.ts function createEnumStringOutOfObject(obj) { if (!obj) throw Error(ErrorCreateEnumStringOutOfObject); return Object.entries(obj).reduce((acc, [key, value]) => { return `${acc} '${key}' = '${value}',`; }, ""); } // bin/frameworks/filesystem/getFileContentAndPath.ts function getFileContentAndPath(getFileContentAndPathOperation) { if (!getFileContentAndPathOperation) throw Error(ErrorGetFileContentAndPath); if (!checkIfFieldsExist(getFileContentAndPathOperation)) throw Error(ErrorGetFileContentAndPathMissingFields); const { type, file, path: path7, name, format, text, element, imports, extraProps, metadata, templates } = getFileContentAndPathOperation; let filePath = `${path7}/${format === "scss" ? "_" : ""}${name}`; const fileOperations = { raw: () => { return { fileContent: `${JSON.stringify(file, null, " ")}`, filePath }; }, token: () => { if (metadata?.dataType === "enum") return { fileContent: getTokenString(file, name, format, metadata.dataType), filePath }; filePath += `.${format}`; return { fileContent: getTokenString(file, name, format), filePath }; }, component: () => { if (type === "component" && templates) return prepComponent({ name, filePath, format, templates, text, extraProps, element }); }, styled: () => { if (type === "styled" && templates) return prepStyledComponents({ name, filePath, format, templates, element }); }, story: () => { if (type === "story" && templates) return prepStorybook({ name, filePath, format, templates, text }); }, css: () => prepCss({ name, filePath, format, imports, file }), description: () => prepDescription({ filePath, file, format }), graphic: () => prepGraphicComponent({ name, filePath, format, templates, file }) }; if (fileOperations.hasOwnProperty(type)) return fileOperations[type](); else throw Error(ErrorGetFileContentAndPathNoReturn); } var getTokenString = (file, name, format, dataType) => { const exportString = format === "js" ? `module.exports = ${name}` : `export default ${name}`; const constAssertion = format === "ts" ? " as const;" : ""; if (format === "json") return getTokenStringJSON(file); if (format === "css") return getTokenStringCSS(file, name); if (format === "scss") return getTokenStringSCSS(file); if (dataType === "enum") return getTokenStringEnum(file, name, exportString); return getTokenStringJS(file, name, exportString, constAssertion); }; function getTokenStringJSON(file) { return `${JSON.stringify(file, null, " ")}`; } function getTokenStringCSS(file, name) { const contents = file; let css = ":root {\n"; for (const key in contents) { const value = contents[key]; css += ` --${name}-${key}: ${value}; `; } css += "}\n"; return css; } function getTokenStringSCSS(file) { const contents = file; let scss = `// ${MsgGeneratedFileWarning} `; for (const key in contents) { const value = contents[key]; scss += `$${key}: ${value}; `; } return scss; } function getTokenStringEnum(file, name, exportString) { return `// ${MsgGeneratedFileWarning} enum ${name} {${createEnumStringOutOfObject( file )} } ${exportString};`; } function getTokenStringJS(file, name, exportString, constAssertion) { return `// ${MsgGeneratedFileWarning} const ${name} = ${JSON.stringify( file, null, " " )}${constAssertion} ${exportString};`; } var checkIfFieldsExist = (getFileContentAndPathOperation) => { if (!getFileContentAndPathOperation.type || !getFileContentAndPathOperation.file || !getFileContentAndPathOperation.path || !getFileContentAndPathOperation.name || !getFileContentAndPathOperation.format || !getFileContentAndPathOperation.element) return false; return true; }; // bin/frameworks/string/createImportStringFromList.ts function createImportStringFromList(importArray, outputFolderTokens = "tokens", tokensRelativeImportPrefix = "") { if (!importArray) throw Error(ErrorCreateImportStringFromList); if (importArray.length === 0) throw Error(ErrorCreateImportStringFromListZeroLength); let importString = ``; importArray.forEach((importItem) => { importString += `import ${importItem} from '${tokensRelativeImportPrefix}${outputFolderTokens}/${importItem}'; `; }); return importString; } // bin/frameworks/filesystem/getDataHelpers.ts var getElement = (metadata) => { if (metadata && metadata.element) return metadata.element; return "div"; }; var getText = (metadata) => { if (metadata && metadata.text) return metadata.text; return ""; }; var getExtraProps = (metadata) => { if (metadata && metadata.extraProps) return metadata.extraProps; return ""; }; var getImports = (metadata, outputFolderTokens, tokensRelativeImportPrefix) => { if (metadata && metadata.imports && metadata.imports.length > 0) return createImportStringFromList( metadata.imports, outputFolderTokens, tokensRelativeImportPrefix ); return ""; }; // bin/frameworks/filesystem/prepareWrite.ts function prepareWrite(writeOperation) { if (!writeOperation) throw Error(ErrorWriteFile); const { type, file, path: path7, name, format, outputFolderTokens, tokensRelativeImportPrefix, metadata, templates } = writeOperation; if ((type === "css" || type === "story" || type === "component") && !templates) throw Error(ErrorPrepareWrite); const getFileDataOperation = { type, file, path: path7, name: name.replace(/\s/g, ""), format, text: getText(metadata), element: getElement(metadata), imports: getImports( metadata, outputFolderTokens, tokensRelativeImportPrefix ), extraProps: getExtraProps(metadata), metadata, templates }; return getFileContentAndPath(getFileDataOperation); } // bin/frameworks/filesystem/write.ts var import_fs7 = __toESM(require("fs"), 1); function write(filePath, fileContent) { if (!filePath || !fileContent) throw Error(ErrorWrite); import_fs7.default.writeFileSync(filePath, fileContent, "utf-8"); } // bin/frameworks/system/acceptedFileTypes.ts var acceptedFileTypes = [ "raw", "token", "component", "styled", "css", "story", "description", "graphic" ]; // bin/frameworks/filesystem/writeFile.ts function writeFile(writeOperation) { if (!writeOperation) throw Error(ErrorWriteFile); const { type, file, path: path7, name, format, outputFolderTokens, overwrite, tokensRelativeImportPrefix, metadata, templates } = writeOperation; validate(file, path7, name, type); const fileType = typeof type === "string" ? type.toLowerCase() : "null"; if (!acceptedFileTypes.includes(fileType)) throw Error(ErrorWriteFileWrongType); if (fileType === "component" || fileType === "graphic") createMissingFoldersFromPath(path7); else createFolder(path7); const fixedName = name.split("/")[name.split("/").length - 1]; const prepareWriteOperation = { type: fileType, file, path: path7, name: fixedName, format, outputFolderTokens, overwrite, tokensRelativeImportPrefix, metadata, templates }; const { filePath, fileContent } = prepareWrite(prepareWriteOperation); write(filePath, fileContent); } function validate(file, path7, name, type) { if (!file || !path7 || !name || !type) throw Error(ErrorWriteFile); } // bin/frameworks/string/cleanSvgData.ts function cleanSvgData(svgData) { if (!svgData) throw Error(ErrorCleanSvgData); return svgData.replace(/width="\w." /gi, "").replace(/height="\w." /gi, ""); } // bin/usecases/interactors/elements/writeElements.ts function writeElements(elements, config, isGeneratingGraphics = false) { if (!elements || !config) throw Error(ErrorWriteElements); elements.forEach((element) => { const fixedConfig = makeFixedConfig(element, config); if (!config.skipFileGeneration.skipReact) { const path7 = `${fixedConfig.folder}/${fixedConfig.fixedName}.${fixedConfig.outputFormatElements}`; const type = isGeneratingGraphics ? "graphic" : "component"; writeFileHelper( fixedConfig, type, config.outputFormatElements, checkIfExists(path7) ); } if (!isGeneratingGraphics) { if (!config.skipFileGeneration.skipStorybook) { const path7 = `${fixedConfig.folder}/${fixedConfig.fixedName}.stories.${fixedConfig.outputFormatStorybook}`; writeFileHelper( fixedConfig, "story", config.outputFormatStorybook, checkIfExists(path7) ); } if (!config.skipFileGeneration.skipDescription) { const path7 = `${fixedConfig.folder}/${fixedConfig.fixedName}.description.${fixedConfig.outputFormatDescription}`; writeFileHelper( fixedConfig, "description", config.outputFormatDescription, checkIfExists(path7) ); } if (!config.skipFileGeneration.skipStyled) { const path7 = `${fixedConfig.folder}/${fixedConfig.fixedName}Styled.${fixedConfig.outputFormatElements}`; writeFileHelper( fixedConfig, "styled", config.outputFormatElements, checkIfExists(path7) ); } if (!config.skipFileGeneration.skipCss) { const path7 = `${fixedConfig.folder}/${fixedConfig.fixedName}Css.${fixedConfig.outputFormatCss}`; writeFileHelper( fixedConfig, "css", config.outputFormatCss, checkIfExists(path7) ); } } }); } var makeFixedConfig = (element, config) => { const html = element.html || " "; const css = element.css || " "; const description = element.description || " "; const name = sanitizeStringPascalCase(element.name); const folder = `${config.outputFolderElements}/${name}`; const { outputFormatCss, outputFormatDescription, outputFormatElements, outputFormatStorybook, outputFolderElements, outputFolderGraphics, outputFolderTokens, overwrite, tokensRelativeImportPrefix } = config; const metadata = { dataType: null, html: element.html, element: element.element, extraProps: element.extraProps, text: element.text || " ", imports: element.imports }; const templates = config.templates; const forceUpdate = config.skipFileGeneration.forceUpdate; const fixedName = name.trim().replace(/\s/g, ""); return { html, css, description, name, folder, outputFormatCss, outputFormatDescription, outputFormatElements, outputFormatStorybook, outputFolderElements, outputFolderGraphics, outputFolderTokens, overwrite, tokensRelativeImportPrefix, metadata, templates, forceUpdate, fixedName }; }; var writeFileHelper = (config, type, format, fileExists) => { const shouldOverwrite = config.overwrite[type] || false; const forceUpdate = config.forceUpdate; if (!fileExists || shouldOverwrite || forceUpdate) { const fileData = (() => { if (type === "graphic") { const svgData = getSvgFileData( `${config.outputFolderGraphics}/${config.fixedName}.svg` ); return cleanSvgData(svgData); } if (type === "description") return config.description; if (type === "css") return config.css; return config.html; })(); const { folder, fixedName, outputFolderElements, outputFolderGraphics, outputFolderTokens, tokensRelativeImportPrefix, metadata, templates } = config; writeFile({ type, file: fileData, path: folder, name: fixedName, format, outputFolderElements, outputFolderGraphics, outputFolderTokens, tokensRelativeImportPrefix, metadata, templates }); } }; // bin/usecases/interactors/elements/writeGraphicElementsMap.ts function writeGraphicElementsMap(folder, filePath, fileContent) { if (!folder || !filePath || !fileContent) throw Error(ErrorWriteGraphicElementsMap); createFolder(folder); write(filePath, fileContent); } // bin/frameworks/filesystem/refresh.ts var import_fs8 = __toESM(require("fs"), 1); var import_path = __toESM(require("path"), 1); function refresh(folderPath, trashExistingFolder = true) { if (!folderPath) throw Error(ErrorRefresh); const resolvedPath = import_path.default.resolve(process.cwd(), folderPath); if (trashExistingFolder && import_fs8.default.existsSync(resolvedPath)) { if (process.versions.node >= "14.14.0") import_fs8.default.rmSync(resolvedPath, { recursive: true }); else import_fs8.default.rmdirSync(resolvedPath, { recursive: true }); } createFolder(resolvedPath); return resolvedPath; } // bin/usecases/createElements.ts async function createElements(config, data) { if (!config || !data) throw Error(ErrorCreateElements); console.log(MsgSyncElements); const { outputFolderElements, outputFormatGraphics, outputGraphicElements, syncGraphics } = config; refresh(outputFolderElements, false); const { components } = data; await handleElements({ children: data.document.children, pageName: "Elements", config, components }); if (outputGraphicElements && outputFormatGraphics === "svg" && syncGraphics) { const GRAPHICS = await handleElements({ children: data.document.children, pageName: "Graphics", config, components, isGeneratingGraphics: true }); if (config.outputGraphicElementsMap) handleGraphicElementsMap({ config, graphics: GRAPHICS }); } } async function handleElements(element) { const { children, pageName, config, components, isGeneratingGraphics } = element; const PAGE = createPage(children, pageName); const ELEMENTS = processElements( PAGE, config, components, isGeneratingGraphics || false ); writeElements(ELEMENTS, config, isGeneratingGraphics); return ELEMENTS; } function handleGraphicElementsMap(graphicElementsMap) { const { config, graphics } = graphicElementsMap; const FOLDER = `${config.outputFolderElements}/Graphics`; const FILE_PATH = `${FOLDER}/index.${config.outputFormatElements}`; const FILE_CONTENT = processGraphicElementsMap(graphics); writeGraphicElementsMap(FOLDER, FILE_PATH, FILE_CONTENT); } // bin/usecases/interactors/graphics/getFileList.ts var getFileList = (response, ids, outputFormatGraphics) => { if (!response || !ids || !outputFormatGraphics) throw Error(ErrorGetFileList); return Object.entries(response.images).map((image) => { const match = ids.filter((id) => id.id === image[0]); const filePath = match[0].name.trim().replace(/ /g, "") + `.${outputFormatGraphics}`; return { url: image[1], file: filePath }; }); }; // bin/usecases/interactors/graphics/getIdString.ts var getIdString = (ids) => { if (!ids) throw Error(ErrorGetIdstring); let idString = ""; ids.forEach((item) => idString += `${item.id},`); return idString.slice(0, idString.length - 1); }; // bin/usecases/interactors/graphics/getIds.ts var getIds = (graphicsPage) => { if (!graphicsPage || graphicsPage.length === 0) throw Error(ErrorGetIds); const ids = []; const componentIds = getComponents(graphicsPage); ids.push(...ids.concat(componentIds)); const frames = graphicsPage.filter((item) => item.type === "FRAME"); for (const frame of frames) { const frameLocalComponentIds = getComponents(frame.children || [], frame); ids.push(...ids.concat(frameLocalComponentIds)); } const deduplicatedIds = []; ids.forEach( (item) => !deduplicatedIds.find((element) => element.id === item.id) ? deduplicatedIds.push(item) : null ); return deduplicatedIds; }; var getComponents = (children, parent) => { const parentName = parent?.name ? `${parent.name}/` : ""; if (!children || children.length === 0) return []; return children.filter((item) => { return item.type === "COMPONENT" || item.type === "INSTANCE"; }).map((item) => ({ id: item.id, name: `${parentName}${item.name}` })); }; // bin/frameworks/network/request.ts var import_fs9 = __toESM(require("fs"), 1); var import_https = __toESM(require("https"), 1); async function request(urlPath, figmaToken) { const options = { hostname: "api.figma.com", path: urlPath, port: 443, method: "GET", headers: { "Content-Type": "application/json", "Accept-Charset": "UTF-8" } }; if (urlPath.includes("https://") || urlPath.includes("http://")) { const urlPathWithoutProtocol = urlPath.replace("https://", "").replace("http://", ""); const indexFirstSlash = urlPathWithoutProtocol.indexOf("/"); const hostname = urlPathWithoutProtocol.substring(0, indexFirstSlash); const path7 = urlPathWithoutProtocol.substring( indexFirstSlash, urlPathWithoutProtocol.length ); options.hostname = hostname; options.path = path7; } const keyPath = `${process.cwd()}/key.pem`; const certPath = `${process.cwd()}/cert.pem`; if (checkIfExists(keyPath)) options.key = getFile(keyPath); if (checkIfExists(certPath)) options.cert = getFile(certPath); if (figmaToken) options.headers = { ...options.headers, "X-Figma-Token": figmaToken }; let data = ""; return new Promise((resolve, reject) => { import_https.default.get(options, (resp) => { resp.on("data", (chunk) => { if (resp.statusCode >= 200 && resp.statusCode < 300) data += chunk; else reject(`Not OK: Status code is ${resp.statusCode}`); }); resp.on("end", () => { if (isJsonString(data)) resolve(JSON.parse(data)); resolve(data); }); }).on("error", (error) => reject(error)); }); } function getFile(filePath) { return import_fs9.default.readFileSync(filePath); } // bin/frameworks/network/getFromApi.ts async function getFromApi(figmaToken, figmaUrl, versionName, type = "files") { if (!figmaToken || !figmaUrl) throw Error(ErrorGetFromApiMissingValues); let endpoint = `/v1/${type}/${figmaUrl}`; if (versionName) { const versions = await request( `/v1/${type}/${figmaUrl}/versions`, figmaToken ).then((res) => { if (isJsonString(res)) return JSON.parse(res); return res; }).catch((error) => { throw Error(ErrorGetFromApi(error)); }); if (versions.versions) { const requestedVersion = versions.versions.filter( (_version) => _version.label === versionName ); const requestedVersionId = (() => { if (requestedVersion && requestedVersion.length > 0) { if (requestedVersion[0].id) { return requestedVersion[0].id; } } })(); endpoint = `/v1/${type}/${figmaUrl}?version=${requestedVersionId}`; } } return request(endpoint, figmaToken).then((res) => res).catch((error) => { throw Error(ErrorGetFromApi(error)); }); } // bin/usecases/interactors/graphics/processGraphics.ts async function processGraphics(graphicsPage, config) { if (!graphicsPage) throw Error(ErrorProcessGraphics); const { token, url, outputFormatGraphics, outputScaleGraphics, versionName } = config; if (!token) throw Error(ErrorProcessGraphics); if (graphicsPage.length === 0 || !graphicsPage[0].children) throw Error(ErrorProcessGraphics); const ids = getIds(graphicsPage); const settings = `&scale=${outputScaleGraphics}&format=${outputFormatGraphics}`; const fullUrl = `${url}?ids=${getIdString(ids)}${settings}`; const imageResponse = await getFromApi( token, fullUrl, versionName, "images" ); if (imageResponse.err) throw Error(ErrorProcessGraphicsImageError); if (!imageResponse.images) throw Error(ErrorProcessGraphicsNoImages); return getFileList(imageResponse, ids, outputFormatGraphics); } // bin/frameworks/network/downloadFile.ts var import_fs10 = __toESM(require("fs"), 1); var import_https2 = __toESM(require("https"), 1); async function downloadFile(url, filePath) { if (!url || !filePath) throw Error(ErrorDownloadFile); return new Promise((resolve, reject) => { const req = import_https2.default.get(url, (resp) => { if (resp.statusCode >= 200 && resp.statusCode < 300) { createMissingFoldersFromPath(filePath); const write2 = resp.pipe(import_fs10.default.createWriteStream(filePath)); write2.on("finish", resolve); } else reject(null); }); req.on("end", () => resolve()).on("error", (error) => reject(error)); }); } // bin/usecases/interactors/graphics/writeGraphics.ts async function writeGraphics(fileList, config) { if (!fileList || !config) throw Error(ErrorWriteGraphics); const { outputFolderGraphics } = config; createFolder(outputFolderGraphics); await Promise.all( fileList.map(async (file) => { return new Promise(async (resolve) => { await downloadFile(file.url, `${outputFolderGraphics}/${file.file}`); resolve(true); }); }) ); } // bin/usecases/createGraphics.ts async function createGraphics(config, data) { if (!config || !data) throw Error(ErrorCreateGraphics); console.log(MsgSyncGraphics); const { outputFolderGraphics } = config; refresh(outputFolderGraphics); const graphicsPage = createPage(data.document.children, "Graphics"); const fileList = await processGraphics(graphicsPage, config); await writeGraphics(fileList, config); } // bin/entities/Token/logic/makeBorderWidthTokens.ts function makeBorderWidthTokens(borderWidthFrame, borderWidthUnit, remSize, camelizeTokenNames) { if (!borderWidthFrame) throw Error(ErrorMakeBorderWidthTokensNoFrame); if (!borderWidthFrame.children) throw Error(ErrorMakeBorderWidthTokensNoChildren); const borderWidths = {}; const tokens = borderWidthFrame.children.reverse(); tokens.forEach( (item) => makeBorderWidthToken( item, borderWidths, remSize, borderWidthUnit, camelizeTokenNames ) ); return borderWidths; } function makeBorderWidthToken(item, borderWidths, remSize, borderWidthUnit, camelizeTokenNames) { if (!item.name || item.strokeWeight === void 0) throw Error(ErrorMakeBorderWidthTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); const borderWidth = (() => { if (borderWidthUnit === "px") return item.strokeWeight + borderWidthUnit; else return item.strokeWeight / remSize + borderWidthUnit; })(); borderWidths[name] = borderWidth; } // bin/frameworks/string/createRadialGradientString.ts function createRadialGradientString(fills) { if (!fills) throw Error(ErrorCreateRadialGradientString); if (!fills.gradientHandlePositions) throw Error(ErrorCreateRadialGradientString); const position = (() => { const pos1 = fills.gradientHandlePositions[0]; const pos2 = fills.gradientHandlePositions[1]; const pos3 = fills.gradientHandlePositions[2]; const start = (pos1.x * 100 - pos3.x * 100).toFixed(1); const end = (pos2.y * 100 - pos1.y * 100).toFixed(1); const x = (pos1.x * 100).toFixed(1); const y = (pos1.y * 100).toFixed(1); return `${start}% ${end}% at ${x}% ${y}%`; })(); let str = `radial-gradient(${position}, `; const gradientStops = fills.gradientStops || null; if (!gradientStops) throw Error(); gradientStops.forEach((fill, index) => { const R = roundColorValue(fill.color?.r, 255); const G = roundColorValue(fill.color?.g, 255); const B = roundColorValue(fill.color?.b, 255); const A = roundColorValue(fill.opacity ? fill.opacity : fill.color?.a, 1); const position2 = roundColorValue( // @ts-ignore parseFloat(fill.position ? fill.position : "0"), 100 ); if (index > 0) str += ` `; str += `rgba(${R}, ${G}, ${B}, ${A}) ${position2}%`; if (index < gradientStops.length - 1) str += `,`; if (index >= gradientStops.length - 1) str += `)`; }); return str; } // bin/entities/Token/logic/makeColorTokens.ts function makeColorTokens(colorFrame, outputFormatColors, camelizeTokenNames, depth = 0) { if (!colorFrame) throw Error(ErrorMakeColorTokensNoFrame); if (!colorFrame.children) throw Error(ErrorMakeColorTokensNoChildren); const colors2 = {}; const tokens = colorFrame.children.reverse(); tokens.forEach((item) => { if (depth === 0 && item.type === "FRAME") { colors2[item.name] = makeColorTokens( item, outputFormatColors, camelizeTokenNames, depth + 1 ); } else { makeColorToken(item, colors2, outputFormatColors, camelizeTokenNames); } }); return colors2; } function makeColorToken(item, colors2, outputFormatColors, camelizeTokenNames) { if (!item.fills || item.fills.length === 0) return; const name = sanitizeString(item.name, camelizeTokenNames); const fills = item.fills[0]; if (fills.type === "SOLID") colors2[name] = createSolidColorString(fills, outputFormatColors); else if (fills.type === "GRADIENT_LINEAR") colors2[name] = createLinearGradientString(fills); else if (fills.type === "GRADIENT_RADIAL") colors2[name] = createRadialGradientString(fills); } // bin/entities/Token/logic/makeDelayTokens.ts function makeDelayTokens(delayFrame, camelizeTokenNames) { if (!delayFrame) throw Error(ErrorMakeDelayTokensNoFrame); if (!delayFrame.children) throw Error(ErrorMakeDelayTokensNoChildren); const delays = {}; const tokens = delayFrame.children.reverse(); tokens.forEach( (item) => makeDelayToken(item, delays, camelizeTokenNames) ); return delays; } function makeDelayToken(item, delays, camelizeTokenNames) { if (!item.name || !item.characters) throw Error(ErrorMakeDelayTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); delays[name] = parseFloat(item.characters); } // bin/entities/Token/logic/makeDurationTokens.ts function makeDurationTokens(durationFrame, durationUnit, camelizeTokenNames) { if (!durationFrame) throw Error(ErrorMakeDurationTokensNoFrame); if (!durationFrame.children) throw Error(ErrorMakeDurationTokensNoChildren); const durations = {}; const tokens = durationFrame.children.reverse(); tokens.forEach( (item) => makeDurationToken(item, durations, durationUnit, camelizeTokenNames) ); return durations; } function makeDurationToken(item, durations, durationUnit, camelizeTokenNames) { if (!item.name || !item.characters) throw Error(ErrorMakeDurationTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); durations[name] = parseFloat(item.characters) + durationUnit; } // bin/entities/Token/logic/makeEasingTokens.ts function makeEasingTokens(easingFrame, camelizeTokenNames) { if (!easingFrame) throw Error(ErrorMakeEasingTokensNoFrame); if (!easingFrame.children) throw Error(ErrorMakeEasingTokensNoChildren); const easings = {}; const tokens = easingFrame.children.reverse(); tokens.forEach( (item) => makeEasingToken(item, easings, camelizeTokenNames) ); return easings; } function makeEasingToken(item, easings, camelizeTokenNames) { if (!item.name || !item.characters) throw Error(ErrorMakeEasingTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); easings[name] = item.characters.trim(); } // bin/entities/Token/logic/makeFontSizeTokens.ts function makeFontSizeTokens(fontSizeFrame, fontUnit, remSize, camelizeTokenNames) { if (!fontSizeFrame) throw Error(ErrorMakeFontSizeTokensNoFrame); if (!fontSizeFrame.children) throw Error(ErrorMakeFontSizeTokensNoChildren); if (!fontUnit || !remSize) throw Error(ErrorMakeFontSizeTokensNoSizing); const fontSizes = {}; const tokens = fontSizeFrame.children.reverse(); tokens.forEach( (item) => makeFontSizeToken(item, fontSizes, remSize, fontUnit, camelizeTokenNames) ); return fontSizes; } function makeFontSizeToken(item, fontSizes, remSize, fontUnit, camelizeTokenNames) { if (!item.name || !item.style) throw Error(ErrorMakeFontSizeTokensMissingProps); if (!item.style.fontSize) throw Error(ErrorMakeFontSizeTokensMissingSize); const name = sanitizeString(item.name, camelizeTokenNames); const fontSize = (() => { if (fontUnit === "px") return item.style.fontSize + fontUnit; else return item.style.fontSize / remSize + fontUnit; })(); fontSizes[name] = fontSize; } // bin/entities/Token/logic/makeFontTokens.ts function makeFontTokens(fontFrame, usePostscriptFontNames = false, useLiteralFontFamilies = false, camelizeTokenNames) { if (!fontFrame) throw Error(ErrorMakeFontTokensNoFrame); if (!fontFrame.children) throw Error(ErrorMakeFontTokensNoChildren); const fonts = {}; const tokens = fontFrame.children.reverse(); tokens.forEach((item) => { useLiteralFontFamilies ? makeLiteralFontFamilyToken(item, fonts, camelizeTokenNames) : makeFontToken(item, fonts, usePostscriptFontNames, camelizeTokenNames); }); return fonts; } function makeFontToken(item, fonts, usePostscriptFontNames, camelizeTokenNames) { if (!item.name || !item.style) throw Error(ErrorMakeFontTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); fonts[name] = usePostscriptFontNames ? item.style.fontPostScriptName : item.style.fontFamily; } function makeLiteralFontFamilyToken(item, fonts, camelizeTokenNames) { if (!item.name || !item.style) throw Error(ErrorMakeFontTokensMissingProps); if (!item.characters) throw Error(ErrorMakeLiteralFontTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); fonts[name] = item.characters.trim(); } // bin/entities/Token/logic/makeFontWeightTokens.ts function makeFontWeightTokens(fontWeightFrame, camelizeTokenNames) { if (!fontWeightFrame) throw Error(ErrorMakeFontWeightTokensNoFrame); if (!fontWeightFrame.children) throw Error(ErrorMakeFontWeightTokensNoChildren); const fontWeights = {}; const tokens = fontWeightFrame.children.reverse(); tokens.forEach( (item) => makeFontWeightToken(item, fontWeights, camelizeTokenNames) ); return fontWeights; } function makeFontWeightToken(item, fontWeights, camelizeTokenNames) { if (!item.name || !item.style) throw Error(ErrorMakeFontWeightTokensMissingProps); if (!item.style.fontWeight) throw Error(ErrorMakeFontWeightTokensMissingWeight); const name = sanitizeString(item.name, camelizeTokenNames); fontWeights[name] = item.style.fontWeight; } // bin/entities/Token/logic/makeLetterSpacingTokens.ts function makeLetterSpacingTokens(letterSpacingFrame, letterSpacingUnit, camelizeTokenNames) { if (!letterSpacingFrame) throw Error(ErrorMakeLetterSpacingTokensNoFrame); if (!letterSpacingFrame.children) throw Error(ErrorMakeLetterSpacingTokensNoChildren); const tokens = letterSpacingFrame.children.reverse(); const letterSpacings = tokens.reduce( (_tokens, item) => { if (!item.name || !item.style) throw Error(ErrorMakeLetterSpacingTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); const fontSize = item.style.fontSize; const letterSpacingValueInPx = typeof item.style.letterSpacing !== "undefined" ? Math.round(item.style.letterSpacing * 1e3) / 1e3 : 0; let value = "0"; switch (letterSpacingUnit) { case "px": value = `${letterSpacingValueInPx}px`; break; case "em": default: if (!fontSize) { throw Error(ErrorMakeLetterSpacingTokensMissingProps); } const valueCalc = Math.round(1e4 * letterSpacingValueInPx / fontSize) / 1e4; value = `${valueCalc}em`; break; } _tokens[name] = value; return _tokens; }, {} ); return letterSpacings; } // bin/entities/Token/logic/makeLineHeightTokens.ts function makeLineHeightTokens(lineHeightFrame, remSize, unitlessPrecision, lineHeightUnit, camelizeTokenNames) { if (!lineHeightFrame) throw Error(ErrorMakeLineHeightTokensNoFrame); if (!lineHeightFrame.children) throw Error(ErrorMakeLineHeightTokensNoChildren); const tokens = lineHeightFrame.children.reverse(); return tokens.reduce((tokensDictionary, item) => { if (!item.name) throw Error(ErrorMakeLineHeightTokensNoName); if (!item.style) throw Error(ErrorMakeLineHeightTokensNoStyle); const { name, value } = makeLineHeightToken( item, remSize, unitlessPrecision, lineHeightUnit, camelizeTokenNames ); tokensDictionary[name] = value; return tokensDictionary; }, {}); } function makeLineHeightToken(item, remSize, unitlessPrecision = 2, lineHeightUnit, camelizeTokenNames) { const name = sanitizeString(item.name, camelizeTokenNames); const fontSize = item.style.fontSize; const lineHeightValueInPx = typeof item.style.lineHeightPx !== "undefined" ? Math.round(item.style.lineHeightPx * 1e3) / 1e3 : 0; let value = "0"; switch (lineHeightUnit) { case "px": value = `${lineHeightValueInPx}px`; break; case "em": if (!fontSize) { throw Error(ErrorMakeLineHeightTokensMissingProps); } const valueCalcEm = Math.round(1e4 * lineHeightValueInPx / fontSize) / 1e4; value = `${valueCalcEm}em`; break; case "rem": const valueCalcRem = Math.round(1e4 * lineHeightValueInPx / remSize) / 1e4; value = `${valueCalcRem}rem`; break; default: value = typeof item.style.lineHeightPercentFontSize !== "undefined" ? parseFloat( normalizeUnits( item.style.lineHeightPercentFontSize, "percent", "unitless", remSize ) ).toFixed(unitlessPrecision) : ( // Assuming this means Figma's "Auto" line-height was used, fallback to CSS "normal" keyword "normal" ); } return { name, value }; } // bin/entities/Token/logic/makeMediaQueryTokens.ts function makeMediaQueryTokens(mediaQueryFrame, camelizeTokenNames) { if (!mediaQueryFrame) throw Error(ErrorSetupMediaQueryTokensNoFrame); if (!mediaQueryFrame.children) throw Error(ErrorSetupMediaQueryTokensNoChildren); const mediaQueries = {}; const tokens = mediaQueryFrame.children.reverse(); tokens.forEach( (item) => makeMediaQueryToken(item, mediaQueries, camelizeTokenNames) ); return mediaQueries; } function makeMediaQueryToken(item, mediaQueries, camelizeTokenNames) { if (!item.name || !item.absoluteBoundingBox) throw Error(ErrorSetupMediaQueryTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); mediaQueries[name] = `${item.absoluteBoundingBox.width}px`; } // bin/entities/Token/logic/makeOpacityTokens.ts function makeOpacityTokens(opacitiesFrame, opacitiesUnit, camelizeTokenNames) { if (!opacitiesFrame) throw Error(ErrorMakeOpacityTokensNoFrame); if (!opacitiesFrame.children) throw Error(ErrorMakeOpacityTokensNoChildren); const tokens = opacitiesFrame.children.reverse(); const opacityTokens = tokens.reduce( (_tokens, item) => { if (!item.name) throw Error(ErrorMakeOpacityTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); const opacity = (() => { let opacity2 = 1; if (typeof item.opacity !== "undefined") opacity2 = Math.round(item.opacity * 100) / 100; if (opacitiesUnit === "percent") opacity2 = `${opacity2 * 100}%`; return opacity2; })(); _tokens[name] = opacity; return _tokens; }, {} ); return opacityTokens; } // bin/entities/Token/logic/makeRadiusTokens.ts function makeRadiusTokens(radiusFrame, radiusUnit, remSize, camelizeTokenNames) { if (!radiusFrame) throw Error(ErrorMakeRadiusTokensNoFrame); if (!radiusFrame.children) throw Error(ErrorMakeRadiusTokensNoChildren); const cornerRadii = {}; const tokens = radiusFrame.children.reverse(); tokens.forEach( (item) => makeRadiusToken(item, cornerRadii, radiusUnit, remSize, camelizeTokenNames) ); return cornerRadii; } function makeRadiusToken(item, cornerRadii, radiusUnit, remSize, camelizeTokenNames) { if (!item.name) throw Error(ErrorMakeRadiusTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); const cornerRadius = item.cornerRadius ? normalizeUnits(item.cornerRadius, "px", radiusUnit, remSize) : `0${radiusUnit}`; cornerRadii[name] = cornerRadius; } // bin/entities/Token/logic/makeShadowTokens.ts function makeShadowTokens(shadowFrame, shadowUnit, remSize, camelizeTokenNames) { if (!shadowFrame) throw Error(ErrorMakeShadowTokensNoFrame); if (!shadowFrame.children) throw Error(ErrorMakeShadowTokensNoChildren); const shadows = {}; const tokens = shadowFrame.children.reverse(); tokens.forEach( (item) => makeShadowToken(item, shadows, shadowUnit, remSize, camelizeTokenNames) ); return shadows; } function makeShadowToken(item, shadows, shadowUnit, remSize, camelizeTokenNames) { if (!item.name || !item.effects) throw Error(ErrorMakeShadowTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); let effects = item.effects.map((effect) => { if (effect.type === "DROP_SHADOW") return effect; return null; }); effects = effects.reverse(); shadows[name] = ``; if (effects.length > 0) { effects.forEach((effect, index) => { if (effect) { const X = getShadowXY(shadowUnit, effect.offset.x, remSize); const Y = getShadowXY(shadowUnit, effect.offset.y, remSize); const radius = getShadowRadius(shadowUnit, effect.radius, remSize); const R = roundColorValue(effect.color.r); const G = roundColorValue(effect.color.g); const B = roundColorValue(effect.color.b); const A = roundColorValue(effect.color.a, 1); shadows[name] += `${X} ${Y} ${radius} rgba(${R}, ${G}, ${B}, ${A})`; if (index !== effects.length - 1) shadows[name] += `, `; } }); } } function getShadowXY(shadowUnit, offset, remSize) { if (shadowUnit === "px") return offset + shadowUnit; else return offset / remSize + shadowUnit; } function getShadowRadius(shadowUnit, radius, remSize) { if (shadowUnit === "px") return radius + shadowUnit; else return radius / remSize + shadowUnit; } // bin/entities/Token/logic/makeSpacingTokens.ts function makeSpacingTokens(spacingFrame, spacingUnit, remSize, camelizeTokenNames) { if (!spacingFrame) throw Error(ErrorMakeSpacingTokensNoFrame); if (!spacingFrame.children) throw Error(ErrorMakeSpacingTokensNoChildren); if (!spacingUnit || !remSize) throw Error(ErrorMakeSpacingTokensNoUnits); const spacings = {}; const tokens = spacingFrame.children.reverse(); tokens.forEach( (item) => makeSpacingToken(item, spacings, spacingUnit, remSize, camelizeTokenNames) ); return spacings; } function makeSpacingToken(item, spacings, spacingUnit, remSize, camelizeTokenNames) { const name = sanitizeString(item.name, camelizeTokenNames); if (!item.absoluteBoundingBox || !item.absoluteBoundingBox.width) throw Error(ErrorMakeSpacingTokensNoFrame); const width = item.absoluteBoundingBox.width; const spacing = (() => { if (spacingUnit === "px") return width + spacingUnit; else return normalizeUnits(width, "px", spacingUnit, remSize); })(); spacings[name] = spacing; } // bin/entities/Token/logic/makeZindexTokens.ts function makeZindexTokens(zIndexFrame, camelizeTokenNames) { if (!zIndexFrame) throw Error(ErrorMakeZindexTokensNoFrame); if (!zIndexFrame.children) throw Error(ErrorMakeZindexTokensNoChildren); const zIndex = {}; const tokens = zIndexFrame.children.reverse(); tokens.forEach( (item) => makeZindexToken(item, zIndex, camelizeTokenNames) ); return zIndex; } function makeZindexToken(item, zIndex, camelizeTokenNames) { if (!item.name || !item.characters) throw Error(ErrorMakeZindexTokensMissingProps); const name = sanitizeString(item.name, camelizeTokenNames); zIndex[name] = parseInt(item.characters); } // bin/frameworks/system/ignoreElementsKeywords.ts var ignoreElementsKeywords = ["ignore"]; // bin/entities/Token/index.ts var makeToken = (token, tokenName, config) => new Token(token, tokenName, config); var Token = class { token; tokenName; config; writeOperation; constructor(token, tokenName, config) { this.token = token; this.tokenName = tokenName; this.config = config; this.writeOperation = null; const processedToken = this.extractTokens( this.token, this.tokenName, this.config ); this.setWriteOperation(processedToken, tokenName); } extractTokens(frame, tokenName, config) { if (!frame || !tokenName) throw Error(ErrorExtractTokens); frame.children = this.getChildren(frame); return this.getTokens(frame, tokenName.toLowerCase(), config); } getChildren = (frame) => { if (frame.children && frame.children.length > 0) { return frame.children.filter((item) => { let shouldInclude = true; for (let i = 0; i < ignoreElementsKeywords.length; i++) { const keywordToIgnore = ignoreElementsKeywords[i]; if (item.name.toLowerCase().indexOf(keywordToIgnore) >= 0 || item.name[0] === "_") { shouldInclude = false; break; } } return shouldInclude; }); } return []; }; getTokens = (frame, name, config) => { const { borderWidthUnit, camelizeTokenNames, fontUnit, letterSpacingUnit, lineHeightUnit, opacitiesUnit, outputFormatColors, radiusUnit, remSize, shadowUnit, durationUnit, spacingUnit, unitlessPrecision, usePostscriptFontNames, useLiteralFontFamilies } = config; const tokenOperations = { borderwidths: () => makeBorderWidthTokens( frame, borderWidthUnit, remSize, camelizeTokenNames ), color: () => makeColorTokens(frame, outputFormatColors, camelizeTokenNames), colors: () => makeColorTokens(frame, outputFormatColors, camelizeTokenNames), delays: () => makeDelayTokens(frame, camelizeTokenNames), durations: () => makeDurationTokens(frame, durationUnit, camelizeTokenNames), easings: () => makeEasingTokens(frame, camelizeTokenNames), fontfamilies: () => { if (!config) throw Error(ErrorExtractTokensNoConfig); return makeFontTokens( frame, usePostscriptFontNames, useLiteralFontFamilies, camelizeTokenNames ); }, fontsizes: () => { if (!config) throw Error(ErrorExtractTokensNoConfig); return makeFontSizeTokens(frame, fontUnit, remSize, camelizeTokenNames); }, fontweights: () => makeFontWeightTokens(frame, camelizeTokenNames), letterspacings: () => { if (!config) throw Error(ErrorExtractTokensNoConfig); return makeLetterSpacingTokens( frame, letterSpacingUnit, camelizeTokenNames ); }, lineheights: () => makeLineHeightTokens( frame, remSize, unitlessPrecision, lineHeightUnit, camelizeTokenNames ), mediaqueries: () => makeMediaQueryTokens(frame, camelizeTokenNames), opacities: () => { if (!config) throw Error(ErrorExtractTokensNoConfig); return makeOpacityTokens(frame, opacitiesUnit, camelizeTokenNames); }, radii: () => makeRadiusTokens(frame, radiusUnit, remSize, camelizeTokenNames), shadows: () => makeShadowTokens(frame, shadowUnit, remSize, camelizeTokenNames), spacing: () => { if (!config) throw Error(ErrorExtractTokensNoConfig); return makeSpacingTokens( frame, spacingUnit, remSize, camelizeTokenNames ); }, spacings: () => { if (!config) throw Error(ErrorExtractTokensNoConfig); return makeSpacingTokens( frame, spacingUnit, remSize, camelizeTokenNames ); }, zindices: () => makeZindexTokens(frame, camelizeTokenNames) }; if (tokenOperations.hasOwnProperty(name)) return tokenOperations[name](); return {}; }; setWriteOperation = (processedToken, tokenName) => { this.writeOperation = { type: "token", file: processedToken, path: this.config.outputFolderTokens, name: tokenName, format: this.config.outputFormatTokens, overwrite: this.config.overwrite }; }; getWriteOperation = () => { if (this.writeOperation) return this.writeOperation; return null; }; }; // bin/frameworks/system/acceptedTokenTypes.ts var acceptedTokenTypes = [ "borderwidths", "color", "colors", "delays", "durations", "easings", "fontfamilies", "fontsizes", "fontweights", "letterspacings", "lineheights", "mediaqueries", "opacities", "radii", "shadows", "spacing", "spacings", "zindices" ]; // bin/usecases/interactors/tokens/processTokens.ts function processTokens(tokens, config) { if (!config) throw Error(ErrorWriteTokensNoSettings); if (!tokens) return []; const processedTokens = []; tokens.forEach((tokenFrame) => { const tokenName = sanitizeString(tokenFrame.name); if (tokenFrame.type.toUpperCase() === "FRAME" && tokenName[0] === "_") return; if (acceptedTokenTypes.includes(tokenName.toLowerCase()) && tokenName[0] !== "_") { const token = makeToken(tokenFrame, tokenName, config); const writeOperation = token.getWriteOperation(); if (writeOperation) processedTokens.push(writeOperation); } }); return processedTokens; } // bin/usecases/interactors/tokens/writeTokens.ts function writeTokens(processedTokens) { if (!processedTokens) throw Error(ErrorWriteTokens); processedTokens.forEach((token) => writeFile(token)); } // bin/usecases/createTokens.ts async function createTokens(config, data) { if (!config || !data) throw Error(ErrorCreateTokens); console.log(MsgWriteTokens); const { outputFolderTokens } = config; refresh(outputFolderTokens); const tokensPage = createPage( data.document.children, "Design Tokens" ); const processedTokens = processTokens(tokensPage, config); if (processedTokens && processedTokens.length > 0) writeTokens(processedTokens); else console.warn(MsgNoTokensFound); } // bin/controllers/FigmagicController.ts async function FigmagicController(config, data) { if (!config || !data) throw Error(ErrorFigmagicController); if (config.syncGraphics) await createGraphics(config, data); if (config.syncTokens) await createTokens(config, data); if (config.syncElements) await createElements(config, data); console.log(MsgJobComplete); return MsgJobComplete; } // bin/frameworks/system/loadEnv.ts var import_fs11 = __toESM(require("fs"), 1); function loadEnv() { const filePath = `${process.cwd()}/.env`; if (import_fs11.default.existsSync(filePath)) { const file = import_fs11.default.readFileSync(filePath, "utf-8"); const variables = file.toString().split("\n").filter( (i) => i.startsWith("FIGMA_TOKEN") || i.startsWith("FIGMA_URL") ); variables.forEach((variable) => { const [key, value] = variable.split("="); process.env[key] = value; }); } } // bin/frameworks/network/getDataLocal.ts var path5 = __toESM(require("path"), 1); function getDataLocal(figmagicFolder, figmaData) { if (!figmagicFolder || !figmaData) throw Error(ErrorGetDataLocal); console.log(MsgSetDataFromLocal); return loadFile( path5.join(`${figmagicFolder}`, `${figmaData}`) ); } // bin/frameworks/network/getDataRemote.ts async function getDataRemote(token, url, versionName) { if (!token || !url) throw Error(ErrorGetDataNoTokenOrUrl); console.log(MsgSetDataFromApi); let data = null; data = await getFromApi(token, url, versionName); if (!data || data.status === 403) throw Error(ErrorGetData); return data; } // bin/frameworks/network/getData.ts async function getData(recompileLocal, figmagicFolder, figmaData, token, url, versionName) { if (!recompileLocal && (!token || !url)) throw Error(ErrorGetData); if (recompileLocal && (!figmagicFolder || !figmaData)) throw Error(ErrorGetDataNoTokenOrUrl); const _data = (async () => { if (recompileLocal) return getDataLocal(figmagicFolder, figmaData); else if (token && url) return getDataRemote(token, url, versionName); throw Error(ErrorGetDataFailedLocalAndRemote); })(); const data = await _data; if (!recompileLocal && !data.document) throw Error(ErrorGetDataNoData); if (recompileLocal && !data) throw Error(ErrorGetDataNoData); return data; } // bin/frameworks/filesystem/writeBaseJson.ts async function writeBaseJson(figmagicFolder, figmaData, data) { if (!figmagicFolder || !figmaData || !data) throw Error(ErrorWriteBaseJson); console.log(MsgWriteBaseFile); refresh(figmagicFolder); write(`${figmagicFolder}/${figmaData}`, JSON.stringify(data)); } // bin/frameworks/system/configToInit.ts var configToInit = { templates: { templatePathGraphic: "./node_modules/figmagic/templates/graphic", templatePathReact: "./node_modules/figmagic/templates/react", templatePathStorybook: "./node_modules/figmagic/templates/story", templatePathStyled: "./node_modules/figmagic/templates/styled" } }; // index.ts var RC_FILES = ["figmagic.json", ".figmagicrc"]; async function main() { try { loadEnv(); const configFilePath = RC_FILES.filter((configFile) => { if (checkIfExists(configFile)) return configFile; })[0]; const [, , ...CLI_ARGS] = process.argv; if (CLI_ARGS[0]?.toLowerCase() === "init") initConfig(configToInit, RC_FILES[0]); else { const userConfigPath = configFilePath ? path6.join(`${process.cwd()}`, configFilePath) : ""; const config = await makeConfiguration(userConfigPath, ...CLI_ARGS); const { recompileLocal, figmagicFolder, figmaData, token, url, versionName } = config; const data = await getData( recompileLocal, figmagicFolder, figmaData, token, url, versionName ); if (!recompileLocal) await writeBaseJson(figmagicFolder, figmaData, data); await FigmagicController(config, data); } } catch (error) { console.error(`${colors.FgRed}${error.message}`); } } function initConfig(file, configFilePath) { const FILE_EXISTS = checkIfExists(configFilePath); if (!FILE_EXISTS) { write(configFilePath, JSON.stringify(file, null, " ")); console.log(MsgJobCompleteInit); return; } console.log(MsgJobCompleteInitStopped); } main();