From f823e556590f7aed3a1ff4f342ee502cb1dbfd84 Mon Sep 17 00:00:00 2001 From: alexey1312 Date: Thu, 4 Apr 2024 22:18:13 +0500 Subject: [PATCH] Small refactoring --- .../Loaders/Colors/ColorsLoader.swift | 31 ++-- .../Loaders/Colors/ColorsLoaderProtocol.swift | 2 +- .../Colors/ColorsVariablesLoader.swift | 171 ++++++++++-------- .../Subcommands/ExportColors.swift | 18 +- 4 files changed, 134 insertions(+), 88 deletions(-) diff --git a/Sources/FigmaExport/Loaders/Colors/ColorsLoader.swift b/Sources/FigmaExport/Loaders/Colors/ColorsLoader.swift index 24de03f..eaf1ad8 100644 --- a/Sources/FigmaExport/Loaders/Colors/ColorsLoader.swift +++ b/Sources/FigmaExport/Loaders/Colors/ColorsLoader.swift @@ -7,30 +7,37 @@ final class ColorsLoader: ColorsLoaderProtocol { private let client: Client private let figmaParams: Params.Figma private let colorParams: Params.Common.Colors? + private let filter: String? - init(client: Client, figmaParams: Params.Figma, colorParams: Params.Common.Colors?) { + init( + client: Client, + figmaParams: Params.Figma, + colorParams: Params.Common.Colors?, + filter: String? + ) { self.client = client self.figmaParams = figmaParams self.colorParams = colorParams + self.filter = filter } - func load(filter: String?) throws -> ColorsLoaderOutput { + func load() throws -> ColorsLoaderOutput { guard let useSingleFile = colorParams?.useSingleFile, useSingleFile else { - return try loadColorsFromLightAndDarkFile(filter: filter) + return try loadColorsFromLightAndDarkFile() } - return try loadColorsFromSingleFile(filter: filter) + return try loadColorsFromSingleFile() } - private func loadColorsFromLightAndDarkFile(filter: String?) throws -> ColorsLoaderOutput { - let lightColors = try loadColors(fileId: figmaParams.lightFileId, filter: filter) - let darkColors = try figmaParams.darkFileId.map { try loadColors(fileId: $0, filter: filter) } - let lightHighContrastColors = try figmaParams.lightHighContrastFileId.map { try loadColors(fileId: $0, filter: filter) } - let darkHighContrastColors = try figmaParams.darkHighContrastFileId.map { try loadColors(fileId: $0, filter: filter) } + private func loadColorsFromLightAndDarkFile() throws -> ColorsLoaderOutput { + let lightColors = try loadColors(fileId: figmaParams.lightFileId) + let darkColors = try figmaParams.darkFileId.map { try loadColors(fileId: $0) } + let lightHighContrastColors = try figmaParams.lightHighContrastFileId.map { try loadColors(fileId: $0) } + let darkHighContrastColors = try figmaParams.darkHighContrastFileId.map { try loadColors(fileId: $0) } return (lightColors, darkColors, lightHighContrastColors, darkHighContrastColors) } - private func loadColorsFromSingleFile(filter: String?) throws -> ColorsLoaderOutput { - let colors = try loadColors(fileId: figmaParams.lightFileId, filter: filter) + private func loadColorsFromSingleFile() throws -> ColorsLoaderOutput { + let colors = try loadColors(fileId: figmaParams.lightFileId) let darkSuffix = colorParams?.darkModeSuffix ?? "_dark" let lightHCSuffix = colorParams?.lightHCModeSuffix ?? "_lightHC" @@ -59,7 +66,7 @@ final class ColorsLoader: ColorsLoaderProtocol { return filteredColors } - private func loadColors(fileId: String, filter: String?) throws -> [Color] { + private func loadColors(fileId: String) throws -> [Color] { var styles = try loadStyles(fileId: fileId) if let filter { diff --git a/Sources/FigmaExport/Loaders/Colors/ColorsLoaderProtocol.swift b/Sources/FigmaExport/Loaders/Colors/ColorsLoaderProtocol.swift index d07e772..74cb1a1 100644 --- a/Sources/FigmaExport/Loaders/Colors/ColorsLoaderProtocol.swift +++ b/Sources/FigmaExport/Loaders/Colors/ColorsLoaderProtocol.swift @@ -4,5 +4,5 @@ import FigmaExportCore typealias ColorsLoaderOutput = (light: [Color], dark: [Color]?, lightHC: [Color]?, darkHC: [Color]?) protocol ColorsLoaderProtocol { - func load(filter: String?) throws -> ColorsLoaderOutput + func load() throws -> ColorsLoaderOutput } diff --git a/Sources/FigmaExport/Loaders/Colors/ColorsVariablesLoader.swift b/Sources/FigmaExport/Loaders/Colors/ColorsVariablesLoader.swift index 16f1f2a..4db6ee9 100644 --- a/Sources/FigmaExport/Loaders/Colors/ColorsVariablesLoader.swift +++ b/Sources/FigmaExport/Loaders/Colors/ColorsVariablesLoader.swift @@ -1,85 +1,40 @@ import FigmaAPI import FigmaExportCore -/// Loads variables colors from Figma +/// Loads color variables from Figma final class ColorsVariablesLoader: ColorsLoaderProtocol { private let client: Client private let variableParams: Params.Common.VariablesColors? + private let filter: String? - init(client: Client, figmaParams: Params.Figma, variableParams: Params.Common.VariablesColors?) { + init( + client: Client, + figmaParams: Params.Figma, + variableParams: Params.Common.VariablesColors?, + filter: String? + ) { self.client = client self.variableParams = variableParams + self.filter = filter } - func load(filter: String?) throws -> ColorsLoaderOutput { + func load() throws -> ColorsLoaderOutput { guard let tokensFileId = variableParams?.tokensFileId, let tokensCollectionName = variableParams?.tokensCollectionName - else { throw FigmaExportError.custom(errorString: "tokensFileId or tokensLightCollectionName is nil") } + else { throw FigmaExportError.custom(errorString: "tokensFileId is nil") } - return try loadProcess( - colorTokensFileId: tokensFileId, - tokensCollectionName: tokensCollectionName, - filter: filter - ) - } + let meta = try loadVariables(fileId: tokensFileId) - private func loadProcess( - colorTokensFileId: String, - tokensCollectionName: String, - filter: String? - ) throws -> ColorsLoaderOutput { - // Load variables - let meta = try loadVariables(fileId: colorTokensFileId) - - guard let tokenCollection = meta.variableCollections.filter({ $0.value.name == tokensCollectionName }).first - else { throw FigmaExportError.custom(errorString: "tokensCollectionName is nil") } - - let tokensId = tokenCollection.value.variableIds - let modeIds = extractModeIds(from: tokenCollection.value) - let primitivesModeName = variableParams?.primitivesModeName - - let variables: [Variable] = tokensId.compactMap { tokenId in - guard let variableMeta = meta.variables[tokenId] - else { return nil } - - let values = Values( - light: variableMeta.valuesByMode[modeIds.lightModeId], - dark: variableMeta.valuesByMode[modeIds.darkModeId], - lightHC: variableMeta.valuesByMode[modeIds.lightHCModeId], - darkHC: variableMeta.valuesByMode[modeIds.darkHCModeId] - ) + guard let tokenCollection = meta.variableCollections.first(where: { $0.value.name == tokensCollectionName }) + else { throw FigmaExportError.custom(errorString: "tokensCollectionName not found" ) } - return Variable( - name: variableMeta.name, - description: variableMeta.description, - valuesByMode: values - ) + let variables: [Variable] = tokenCollection.value.variableIds.compactMap { tokenId in + guard let variableMeta = meta.variables[tokenId] else { return nil } + return mapVariableMetaToVariable(variableMeta: variableMeta, modeIds: extractModeIds(from: tokenCollection.value)) } - var colors = Colors() - func handleColorMode(variable: Variable, mode: ValuesByMode?, colorsArray: inout [Color]) { - if case let .color(color) = mode { - guard doesColorMatchFilter(from: variable, filter: filter) else { return } - colorsArray.append(createColor(from: variable, color: color)) - } else if case let .variableAlias(variableAlias) = mode { - guard - let variableMeta = meta.variables[variableAlias.id], - let variableCollectionId = meta.variableCollections[variableMeta.variableCollectionId] - else { return } - let modeId = variableCollectionId.modes - .filter { $0.name == primitivesModeName } - .first?.modeId ?? variableCollectionId.defaultModeId - handleColorMode(variable: variable, mode: variableMeta.valuesByMode[modeId], colorsArray: &colorsArray) - } - } - variables.forEach { value in - handleColorMode(variable: value, mode: value.valuesByMode.light, colorsArray: &colors.lightColors) - handleColorMode(variable: value, mode: value.valuesByMode.dark, colorsArray: &colors.darkColors) - handleColorMode(variable: value, mode: value.valuesByMode.lightHC, colorsArray: &colors.lightHCColors) - handleColorMode(variable: value, mode: value.valuesByMode.darkHC, colorsArray: &colors.darkHCColors) - } - return (colors.lightColors, colors.darkColors, colors.lightHCColors, colors.darkHCColors) + return mapVariablesToColorOutput(variables: variables, meta: meta) } private func loadVariables(fileId: String) throws -> VariablesEndpoint.Content { @@ -89,24 +44,98 @@ final class ColorsVariablesLoader: ColorsLoaderProtocol { private func extractModeIds(from collections: Dictionary.Values.Element) -> ModeIds { var modeIds = ModeIds() - collections.modes.forEach { - switch $0.name { + collections.modes.forEach { mode in + switch mode.name { case variableParams?.lightModeName: - modeIds.lightModeId = $0.modeId + modeIds.lightModeId = mode.modeId case variableParams?.darkModeName: - modeIds.darkModeId = $0.modeId + modeIds.darkModeId = mode.modeId case variableParams?.lightHCModeName: - modeIds.lightHCModeId = $0.modeId + modeIds.lightHCModeId = mode.modeId case variableParams?.darkHCModeName: - modeIds.darkHCModeId = $0.modeId + modeIds.darkHCModeId = mode.modeId default: - modeIds.lightModeId = $0.modeId + modeIds.lightModeId = mode.modeId } } return modeIds } - private func doesColorMatchFilter(from variable: Variable, filter: String?) -> Bool { + private func mapVariableMetaToVariable(variableMeta: VariableID, modeIds: ModeIds) -> Variable { + let values = Values( + light: variableMeta.valuesByMode[modeIds.lightModeId], + dark: variableMeta.valuesByMode[modeIds.darkModeId], + lightHC: variableMeta.valuesByMode[modeIds.lightHCModeId], + darkHC: variableMeta.valuesByMode[modeIds.darkHCModeId] + ) + + return Variable(name: variableMeta.name, description: variableMeta.description, valuesByMode: values) + } + + private func mapVariablesToColorOutput( + variables: [Variable], + meta: VariablesEndpoint.Content + ) -> ColorsLoaderOutput { + var colorOutput = Colors() + variables.forEach { variable in + handleColorMode( + variable: variable, + mode: variable.valuesByMode.light, + colorsArray: &colorOutput.lightColors, + filter: filter, + meta: meta + ) + handleColorMode( + variable: variable, + mode: variable.valuesByMode.dark, + colorsArray: &colorOutput.darkColors, + filter: filter, + meta: meta + ) + handleColorMode( + variable: variable, + mode: variable.valuesByMode.lightHC, + colorsArray: &colorOutput.lightHCColors, + filter: filter, + meta: meta + ) + handleColorMode( + variable: variable, + mode: variable.valuesByMode.darkHC, + colorsArray: &colorOutput.darkHCColors, + filter: filter, + meta: meta + ) + } + return (colorOutput.lightColors, colorOutput.darkColors, colorOutput.lightHCColors, colorOutput.darkHCColors) + } + + private func handleColorMode( + variable: Variable, + mode: ValuesByMode?, + colorsArray: inout [Color], + filter: String?, + meta: VariablesEndpoint.Content) + { + if case let .color(color) = mode, doesColorMatchFilter(from: variable) { + colorsArray.append(createColor(from: variable, color: color)) + } else if case let .variableAlias(variableAlias) = mode, + let variableMeta = meta.variables[variableAlias.id], + let variableCollectionId = meta.variableCollections[variableMeta.variableCollectionId] { + let modeId = variableCollectionId.modes.first(where: { + $0.name == variableParams?.primitivesModeName + })?.modeId ?? variableCollectionId.defaultModeId + handleColorMode( + variable: variable, + mode: variableMeta.valuesByMode[modeId], + colorsArray: &colorsArray, + filter: filter, + meta: meta + ) + } + } + + private func doesColorMatchFilter(from variable: Variable) -> Bool { guard let filter = filter else { return true } let assetsFilter = AssetsFilter(filter: filter) return assetsFilter.match(name: variable.name) diff --git a/Sources/FigmaExport/Subcommands/ExportColors.swift b/Sources/FigmaExport/Subcommands/ExportColors.swift index 27e4d0a..c73b2ab 100644 --- a/Sources/FigmaExport/Subcommands/ExportColors.swift +++ b/Sources/FigmaExport/Subcommands/ExportColors.swift @@ -42,14 +42,24 @@ extension FigmaExportCommand { var nameReplaceRegexp: String? if let colorParams = commonParams?.colors { - loader = ColorsLoader(client: client, figmaParams: figmaParams, colorParams: colorParams) - colors = try loader.load(filter: filter) + loader = ColorsLoader( + client: client, + figmaParams: figmaParams, + colorParams: colorParams, + filter: filter + ) + colors = try loader.load() nameValidateRegexp = options.params.common?.colors?.nameValidateRegexp nameReplaceRegexp = options.params.common?.colors?.nameReplaceRegexp } else if let variableParams = commonParams?.variablesColors { - loader = ColorsVariablesLoader(client: client, figmaParams: figmaParams, variableParams: variableParams) - colors = try loader.load(filter: filter) + loader = ColorsVariablesLoader( + client: client, + figmaParams: figmaParams, + variableParams: variableParams, + filter: filter + ) + colors = try loader.load() nameValidateRegexp = options.params.common?.variablesColors?.nameValidateRegexp nameReplaceRegexp = options.params.common?.variablesColors?.nameReplaceRegexp