From 4c7291ee605e5b3eb2d8b05e6d0de6b52e29739d Mon Sep 17 00:00:00 2001 From: Alessio Arsuffi Date: Mon, 26 May 2025 12:53:08 +0200 Subject: [PATCH 01/10] add Version model for Figma API --- Sources/FigmaAPI/Model/Version.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Sources/FigmaAPI/Model/Version.swift diff --git a/Sources/FigmaAPI/Model/Version.swift b/Sources/FigmaAPI/Model/Version.swift new file mode 100644 index 0000000..94f13b2 --- /dev/null +++ b/Sources/FigmaAPI/Model/Version.swift @@ -0,0 +1,15 @@ +import Foundation +#if os(Linux) +import FoundationNetworking +#endif + +public struct Version: Codable { + let id: String + public let createdAt: Date? + let label: String? + let description: String? +} + +public struct VersionResponse: Decodable { + public var versions: [Version] +} From c2f51a371a9ea89ca5fe7ef553499e37d4499ef1 Mon Sep 17 00:00:00 2001 From: Alessio Arsuffi Date: Mon, 26 May 2025 12:53:39 +0200 Subject: [PATCH 02/10] create files/:file_id/versions endpoint --- .../FigmaAPI/Endpoint/VersionEndpoint.swift | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Sources/FigmaAPI/Endpoint/VersionEndpoint.swift diff --git a/Sources/FigmaAPI/Endpoint/VersionEndpoint.swift b/Sources/FigmaAPI/Endpoint/VersionEndpoint.swift new file mode 100644 index 0000000..8d0e898 --- /dev/null +++ b/Sources/FigmaAPI/Endpoint/VersionEndpoint.swift @@ -0,0 +1,26 @@ +import Foundation +#if os(Linux) +import FoundationNetworking +#endif + +public struct VersionEndpoint: BaseEndpoint { + public typealias Content = [Version] + + private let fileId: String + + public init(fileId: String) { + self.fileId = fileId + } + + func content(from root: VersionResponse) -> Content { + root.versions + } + + public func makeRequest(baseURL: URL) -> URLRequest { + let url = baseURL + .appendingPathComponent("files") + .appendingPathComponent(fileId) + .appendingPathComponent("versions") + return URLRequest(url: url) + } +} From 238b7413e3e6604cfed07c1646f4a0ab013814ef Mon Sep 17 00:00:00 2001 From: Alessio Arsuffi Date: Mon, 26 May 2025 12:54:02 +0200 Subject: [PATCH 03/10] use dateDecodingStrategy as iso8601 --- Sources/FigmaAPI/Endpoint/BaseEndpoint.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/FigmaAPI/Endpoint/BaseEndpoint.swift b/Sources/FigmaAPI/Endpoint/BaseEndpoint.swift index 9b3c4f0..66585ae 100644 --- a/Sources/FigmaAPI/Endpoint/BaseEndpoint.swift +++ b/Sources/FigmaAPI/Endpoint/BaseEndpoint.swift @@ -39,6 +39,7 @@ extension JSONDecoder { internal static let `default`: JSONDecoder = { let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase + decoder.dateDecodingStrategy = .iso8601 return decoder }() } From cb16cd13d4ea91f30df9d3b18592f94c66d196dd Mon Sep 17 00:00:00 2001 From: Alessio Arsuffi Date: Mon, 26 May 2025 12:55:35 +0200 Subject: [PATCH 04/10] add shouldUpdateFigmaVersion --- .../FigmaExport/Output/VersionManager.swift | 63 +++++++++++++++++++ .../Subcommands/ExportColors.swift | 6 ++ .../FigmaExport/Subcommands/ExportIcons.swift | 6 ++ .../Subcommands/ExportImages.swift | 6 ++ .../Subcommands/ExportTypography.swift | 6 ++ .../shouldUpdateFigmaVersion.swift | 46 ++++++++++++++ 6 files changed, 133 insertions(+) create mode 100644 Sources/FigmaExport/Output/VersionManager.swift create mode 100644 Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift diff --git a/Sources/FigmaExport/Output/VersionManager.swift b/Sources/FigmaExport/Output/VersionManager.swift new file mode 100644 index 0000000..341762b --- /dev/null +++ b/Sources/FigmaExport/Output/VersionManager.swift @@ -0,0 +1,63 @@ +import Foundation +import Logging +#if os(Linux) +import FoundationNetworking +#endif + +class VersionManager { + private let versionFileURL: URL + private let dateFormatter = ISO8601DateFormatter() + private let logger = Logger(label: "com.redmadrobot.figma-export.version-manager") + + enum AssetKey: String, CaseIterable, Codable { + case images + case icons + case typography + case colors + } + + private var versionDates: [String: String] = [:] + + init(versionFilePath: String) { + self.versionFileURL = URL(fileURLWithPath: versionFilePath) + loadVersionDates() + } + + private func loadVersionDates() { + guard FileManager.default.fileExists(atPath: versionFileURL.path) else { return } + + do { + let data = try Data(contentsOf: versionFileURL) + let rawDict = try JSONDecoder().decode([String: String].self, from: data) + + for (key, dateString) in rawDict { + if let assetKey = AssetKey(rawValue: key) { + versionDates[assetKey.rawValue] = dateString + } + } + } catch { + logger.error("Failed to load version data: \(error)") + } + } + + private func saveVersionDates() { + do { + let jsonData = try JSONSerialization.data(withJSONObject: versionDates, options: .prettyPrinted) + try jsonData.write(to: versionFileURL, options: .atomic) + } catch { + logger.error("Failed to save version data: \(error)") + } + } + + func getVersionDate(for asset: AssetKey) -> Date? { + guard let dateString = versionDates[asset.rawValue] else { return nil } + return dateFormatter.date(from: dateString) + } + + func setVersionDate(_ date: Date, for asset: AssetKey) { + let dateString = dateFormatter.string(from: date) + versionDates[asset.rawValue] = dateString + saveVersionDates() + } +} + diff --git a/Sources/FigmaExport/Subcommands/ExportColors.swift b/Sources/FigmaExport/Subcommands/ExportColors.swift index 5277e5b..41cf495 100644 --- a/Sources/FigmaExport/Subcommands/ExportColors.swift +++ b/Sources/FigmaExport/Subcommands/ExportColors.swift @@ -25,6 +25,10 @@ extension FigmaExportCommand { var filter: String? func run() throws { + let versionManager = VersionManager(versionFilePath: "figma-versions.json") + let lastAvailableDate = shouldUpdateFigmaVersion(for: .colors, options: options, logger: logger, versionManager: versionManager) + guard let lastAvailableDate else { return } + logger.info("Using FigmaExport \(FigmaExportCommand.version) to export colors.") logger.info("Fetching colors. Please wait...") @@ -112,6 +116,8 @@ extension FigmaExportCommand { logger.info("Done!") } + + versionManager.setVersionDate(lastAvailableDate, for: .colors) } private func exportXcodeColors(colorPairs: [AssetPair], iosParams: Params.iOS) throws { diff --git a/Sources/FigmaExport/Subcommands/ExportIcons.swift b/Sources/FigmaExport/Subcommands/ExportIcons.swift index a98b064..43596cd 100644 --- a/Sources/FigmaExport/Subcommands/ExportIcons.swift +++ b/Sources/FigmaExport/Subcommands/ExportIcons.swift @@ -28,6 +28,10 @@ extension FigmaExportCommand { var filter: String? func run() throws { + let versionManager = VersionManager(versionFilePath: "figma-versions.json") + let lastAvailableDate = shouldUpdateFigmaVersion(for: .icons, options: options, logger: logger, versionManager: versionManager) + guard let lastAvailableDate else { return } + let client = FigmaClient(accessToken: options.accessToken, timeout: options.params.figma.timeout) if options.params.ios != nil { @@ -39,6 +43,8 @@ extension FigmaExportCommand { logger.info("Using FigmaExport \(FigmaExportCommand.version) to export icons to Android Studio project.") try exportAndroidIcons(client: client, params: options.params) } + + versionManager.setVersionDate(lastAvailableDate, for: .icons) } private func exportiOSIcons(client: Client, params: Params) throws { diff --git a/Sources/FigmaExport/Subcommands/ExportImages.swift b/Sources/FigmaExport/Subcommands/ExportImages.swift index 8dc5ded..e83c7ae 100644 --- a/Sources/FigmaExport/Subcommands/ExportImages.swift +++ b/Sources/FigmaExport/Subcommands/ExportImages.swift @@ -25,6 +25,10 @@ extension FigmaExportCommand { var filter: String? func run() throws { + let versionManager = VersionManager(versionFilePath: "figma-versions.json") + let lastAvailableDate = shouldUpdateFigmaVersion(for: .images, options: options, logger: logger, versionManager: versionManager) + guard let lastAvailableDate else { return } + let client = FigmaClient(accessToken: options.accessToken, timeout: options.params.figma.timeout) if let _ = options.params.ios { @@ -36,6 +40,8 @@ extension FigmaExportCommand { logger.info("Using FigmaExport \(FigmaExportCommand.version) to export images to Android Studio project.") try exportAndroidImages(client: client, params: options.params) } + + versionManager.setVersionDate(lastAvailableDate, for: .images) } private func exportiOSImages(client: Client, params: Params) throws { diff --git a/Sources/FigmaExport/Subcommands/ExportTypography.swift b/Sources/FigmaExport/Subcommands/ExportTypography.swift index 3a35713..18c3e5e 100644 --- a/Sources/FigmaExport/Subcommands/ExportTypography.swift +++ b/Sources/FigmaExport/Subcommands/ExportTypography.swift @@ -18,6 +18,10 @@ extension FigmaExportCommand { var options: FigmaExportOptions func run() throws { + let versionManager = VersionManager(versionFilePath: "figma-versions.json") + let lastAvailableDate = shouldUpdateFigmaVersion(for: .typography, options: options, logger: logger, versionManager: versionManager) + guard let lastAvailableDate else { return } + let client = FigmaClient(accessToken: options.accessToken, timeout: options.params.figma.timeout) logger.info("Using FigmaExport \(FigmaExportCommand.version) to export typography.") @@ -55,6 +59,8 @@ extension FigmaExportCommand { try exportAndroidTextStyles(textStyles: processedTextStyles, androidParams: android) logger.info("Done!") } + + versionManager.setVersionDate(lastAvailableDate, for: .typography) } private func createXcodeOutput(from iosParams: Params.iOS) -> XcodeTypographyOutput { diff --git a/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift b/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift new file mode 100644 index 0000000..1a25ceb --- /dev/null +++ b/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift @@ -0,0 +1,46 @@ +import ArgumentParser +import Foundation +import Logging +import FigmaAPI + +extension ParsableCommand { + + func shouldUpdateFigmaVersion( + for assetKey: VersionManager.AssetKey, + options: FigmaExportOptions, + timeout: TimeInterval? = nil, + logger: Logger, + versionManager: VersionManager + ) -> Date? { + let fileId = options.params.figma.lightFileId + let client = FigmaClient(accessToken: options.accessToken, timeout: timeout) + let endpoint = VersionEndpoint(fileId: fileId) + guard + let fileVersions = try? client.request(endpoint), + let lastVersion = fileVersions.first + else { + return nil + } + + let lastVersionDate = lastVersion.createdAt ?? Date() + let localVersionDate = versionManager.getVersionDate(for: assetKey) ?? Date(timeIntervalSince1970: 0) + if lastVersionDate > localVersionDate { + versionManager.setVersionDate(lastVersionDate, for: assetKey) + logger.info(""" + + ---------------------------------------------------------------------------------- + New version available for file: \(fileId)... downloading updates now... + ---------------------------------------------------------------------------------- + """) + return nil + } + + logger.info(""" + + ---------------------------------------------------------------------------- + You are on the latest file version, nothing to download. + ---------------------------------------------------------------------------- + """) + return lastVersionDate + } +} From 274ec20694e049d7225547c8defcef2784a94dc8 Mon Sep 17 00:00:00 2001 From: Alessio Arsuffi Date: Mon, 26 May 2025 14:11:58 +0200 Subject: [PATCH 05/10] small fix --- .../FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift b/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift index 1a25ceb..f6034b4 100644 --- a/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift +++ b/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift @@ -23,8 +23,8 @@ extension ParsableCommand { } let lastVersionDate = lastVersion.createdAt ?? Date() - let localVersionDate = versionManager.getVersionDate(for: assetKey) ?? Date(timeIntervalSince1970: 0) - if lastVersionDate > localVersionDate { + let localVersionDate = versionManager.getVersionDate(for: assetKey) + if let localVersionDate, lastVersionDate > localVersionDate { versionManager.setVersionDate(lastVersionDate, for: assetKey) logger.info(""" From adf2c3bbd0a37fd997735871053f38327aa20df1 Mon Sep 17 00:00:00 2001 From: Alessio Arsuffi Date: Mon, 26 May 2025 14:27:12 +0200 Subject: [PATCH 06/10] tab fix --- Sources/FigmaAPI/Endpoint/BaseEndpoint.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/FigmaAPI/Endpoint/BaseEndpoint.swift b/Sources/FigmaAPI/Endpoint/BaseEndpoint.swift index 66585ae..8612c0e 100644 --- a/Sources/FigmaAPI/Endpoint/BaseEndpoint.swift +++ b/Sources/FigmaAPI/Endpoint/BaseEndpoint.swift @@ -39,7 +39,7 @@ extension JSONDecoder { internal static let `default`: JSONDecoder = { let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase - decoder.dateDecodingStrategy = .iso8601 + decoder.dateDecodingStrategy = .iso8601 return decoder }() } From f014cbd2b5c855dcc29b41311f1f8ed47626eb19 Mon Sep 17 00:00:00 2001 From: Alessio Arsuffi Date: Mon, 26 May 2025 14:35:37 +0200 Subject: [PATCH 07/10] final fix --- .../Subcommands/shouldUpdateFigmaVersion.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift b/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift index f6034b4..686330e 100644 --- a/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift +++ b/Sources/FigmaExport/Subcommands/shouldUpdateFigmaVersion.swift @@ -24,22 +24,22 @@ extension ParsableCommand { let lastVersionDate = lastVersion.createdAt ?? Date() let localVersionDate = versionManager.getVersionDate(for: assetKey) - if let localVersionDate, lastVersionDate > localVersionDate { + if let localVersionDate, lastVersionDate >= localVersionDate { versionManager.setVersionDate(lastVersionDate, for: assetKey) logger.info(""" - ---------------------------------------------------------------------------------- - New version available for file: \(fileId)... downloading updates now... - ---------------------------------------------------------------------------------- + ---------------------------------------------------------------------------- + You are on the latest file version, nothing to download. + ---------------------------------------------------------------------------- """) return nil } logger.info(""" - ---------------------------------------------------------------------------- - You are on the latest file version, nothing to download. - ---------------------------------------------------------------------------- + ------------------------------------------------------------------------------------- + New version available for file: \(fileId)... downloading updates now... + ------------------------------------------------------------------------------------- """) return lastVersionDate } From 456dfd590f42d032453242bfb17d39028eb656a9 Mon Sep 17 00:00:00 2001 From: Alessio Arsuffi Date: Mon, 26 May 2025 14:54:03 +0200 Subject: [PATCH 08/10] enforce errors --- Sources/FigmaExport/Subcommands/ExportColors.swift | 3 +-- Sources/FigmaExport/Subcommands/ExportIcons.swift | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Sources/FigmaExport/Subcommands/ExportColors.swift b/Sources/FigmaExport/Subcommands/ExportColors.swift index 41cf495..7407ea6 100644 --- a/Sources/FigmaExport/Subcommands/ExportColors.swift +++ b/Sources/FigmaExport/Subcommands/ExportColors.swift @@ -122,8 +122,7 @@ extension FigmaExportCommand { private func exportXcodeColors(colorPairs: [AssetPair], iosParams: Params.iOS) throws { guard let colorParams = iosParams.colors else { - logger.error("Nothing to do. Add ios.colors parameters to the config file.") - return + throw FigmaExportError.custom(errorString: "Nothing to do. Add ios.colors parameters to the config file.") } var colorsURL: URL? diff --git a/Sources/FigmaExport/Subcommands/ExportIcons.swift b/Sources/FigmaExport/Subcommands/ExportIcons.swift index 43596cd..7dde09d 100644 --- a/Sources/FigmaExport/Subcommands/ExportIcons.swift +++ b/Sources/FigmaExport/Subcommands/ExportIcons.swift @@ -50,8 +50,7 @@ extension FigmaExportCommand { private func exportiOSIcons(client: Client, params: Params) throws { guard let ios = params.ios, let iconsParams = ios.icons else { - logger.info("Nothing to do. You haven’t specified ios.icons parameters in the config file.") - return + throw FigmaExportError.custom(errorString: "Nothing to do. You haven’t specified ios.icons parameter in the config file.") } logger.info("Fetching icons info from Figma. Please wait...") @@ -121,8 +120,7 @@ extension FigmaExportCommand { private func exportAndroidIcons(client: Client, params: Params) throws { guard let android = params.android, let androidIcons = android.icons else { - logger.info("Nothing to do. You haven’t specified android.icons parameter in the config file.") - return + throw FigmaExportError.custom(errorString: "Nothing to do. You haven’t specified android.icons parameter in the config file.") } // 1. Get Icons info From 27af2f9977b4e835f4939529a15b03e4240c2481 Mon Sep 17 00:00:00 2001 From: Alessio Arsuffi Date: Mon, 26 May 2025 15:05:30 +0200 Subject: [PATCH 09/10] enforce errors when export Images --- Sources/FigmaExport/Subcommands/ExportImages.swift | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Sources/FigmaExport/Subcommands/ExportImages.swift b/Sources/FigmaExport/Subcommands/ExportImages.swift index e83c7ae..0175f27 100644 --- a/Sources/FigmaExport/Subcommands/ExportImages.swift +++ b/Sources/FigmaExport/Subcommands/ExportImages.swift @@ -47,8 +47,7 @@ extension FigmaExportCommand { private func exportiOSImages(client: Client, params: Params) throws { guard let ios = params.ios, let imagesParams = ios.images else { - logger.info("Nothing to do. You haven’t specified ios.images parameters in the config file.") - return + throw FigmaExportError.custom(errorString: "Nothing to do. You haven’t specified ios.images parameters in the config file.") } logger.info("Fetching images info from Figma. Please wait...") @@ -116,8 +115,7 @@ extension FigmaExportCommand { private func exportAndroidImages(client: Client, params: Params) throws { guard let androidImages = params.android?.images else { - logger.info("Nothing to do. You haven’t specified android.images parameter in the config file.") - return + throw FigmaExportError.custom(errorString: "Nothing to do. You haven’t specified android.images parameters in the config file.") } logger.info("Fetching images info from Figma. Please wait...") @@ -150,8 +148,7 @@ extension FigmaExportCommand { private func exportAndroidSVGImages(images: [AssetPair], params: Params) throws { guard let android = params.android, let androidImages = android.images else { - logger.info("Nothing to do. You haven’t specified android.images parameter in the config file.") - return + throw FigmaExportError.custom(errorString: "Nothing to do. You haven’t specified android.images parameters in the config file.") } // Create empty temp directory @@ -230,8 +227,7 @@ extension FigmaExportCommand { private func exportAndroidRasterImages(images: [AssetPair], params: Params) throws { guard let android = params.android, let androidImages = android.images else { - logger.info("Nothing to do. You haven’t specified android.images parameter in the config file.") - return + throw FigmaExportError.custom(errorString: "Nothing to do. You haven’t specified android.images parameters in the config file.") } // Create empty temp directory From 44fe954c267fe23b44e6458bd5eed96f4737790d Mon Sep 17 00:00:00 2001 From: Alessio Arsuffi Date: Mon, 26 May 2025 15:40:33 +0200 Subject: [PATCH 10/10] enforce errors on Typography --- .../Subcommands/ExportTypography.swift | 72 +++++++++++-------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/Sources/FigmaExport/Subcommands/ExportTypography.swift b/Sources/FigmaExport/Subcommands/ExportTypography.swift index 18c3e5e..9ea68d3 100644 --- a/Sources/FigmaExport/Subcommands/ExportTypography.swift +++ b/Sources/FigmaExport/Subcommands/ExportTypography.swift @@ -24,45 +24,59 @@ extension FigmaExportCommand { let client = FigmaClient(accessToken: options.accessToken, timeout: options.params.figma.timeout) - logger.info("Using FigmaExport \(FigmaExportCommand.version) to export typography.") - logger.info("Fetching text styles. Please wait...") let loader = TextStylesLoader(client: client, params: options.params.figma) let textStyles = try loader.load() - if let ios = options.params.ios, - let typographyParams = ios.typography { - - logger.info("Processing typography...") - let processor = TypographyProcessor( - platform: .ios, - nameValidateRegexp: options.params.common?.typography?.nameValidateRegexp, - nameReplaceRegexp: options.params.common?.typography?.nameReplaceRegexp, - nameStyle: typographyParams.nameStyle - ) - let processedTextStyles = try processor.process(assets: textStyles).get() - logger.info("Saving text styles...") - try exportXcodeTextStyles(textStyles: processedTextStyles, iosParams: ios) - logger.info("Done!") + if let _ = options.params.ios { + logger.info("Using FigmaExport \(FigmaExportCommand.version) to export typography to Xcode project.") + try exportiOSIcons(params: options.params, textStyles: textStyles) } - - if let android = options.params.android { - logger.info("Processing typography...") - let processor = TypographyProcessor( - platform: .android, - nameValidateRegexp: options.params.common?.typography?.nameValidateRegexp, - nameReplaceRegexp: options.params.common?.typography?.nameReplaceRegexp, - nameStyle: options.params.android?.typography?.nameStyle - ) - let processedTextStyles = try processor.process(assets: textStyles).get() - logger.info("Saving text styles...") - try exportAndroidTextStyles(textStyles: processedTextStyles, androidParams: android) - logger.info("Done!") + + if let _ = options.params.android { + logger.info("Using FigmaExport \(FigmaExportCommand.version) to export typography to Android Studio project.") + try exportAndroidIcons(params: options.params, textStyles: textStyles) } versionManager.setVersionDate(lastAvailableDate, for: .typography) } + private func exportiOSIcons(params: Params, textStyles: [TextStyle]) throws { + guard let ios = options.params.ios, let typographyParams = ios.typography else { + throw FigmaExportError.custom(errorString: "Nothing to do. Add ios.typography parameters to the config file.") + } + + logger.info("Processing typography...") + let iOSProcessor = TypographyProcessor( + platform: .ios, + nameValidateRegexp: params.common?.typography?.nameValidateRegexp, + nameReplaceRegexp: params.common?.typography?.nameReplaceRegexp, + nameStyle: typographyParams.nameStyle + ) + let iOSProcessedTextStyles = try iOSProcessor.process(assets: textStyles).get() + logger.info("Saving text styles...") + try exportXcodeTextStyles(textStyles: iOSProcessedTextStyles, iosParams: ios) + logger.info("Done!") + } + + private func exportAndroidIcons(params: Params, textStyles: [TextStyle]) throws { + guard let android = options.params.android else { + throw FigmaExportError.custom(errorString: "Nothing to do. Add android.typography parameters to the config file.") + } + + logger.info("Processing typography...") + let androidProcessor = TypographyProcessor( + platform: .android, + nameValidateRegexp: params.common?.typography?.nameValidateRegexp, + nameReplaceRegexp: params.common?.typography?.nameReplaceRegexp, + nameStyle: params.android?.typography?.nameStyle + ) + let androidProcessedTextStyles = try androidProcessor.process(assets: textStyles).get() + logger.info("Saving text styles...") + try exportAndroidTextStyles(textStyles: androidProcessedTextStyles, androidParams: android) + logger.info("Done!") + } + private func createXcodeOutput(from iosParams: Params.iOS) -> XcodeTypographyOutput { let fontUrls = XcodeTypographyOutput.FontURLs( fontExtensionURL: iosParams.typography?.fontSwift,