diff --git a/Demo/.figmagen.yml b/Demo/.figmagen.yml index a027a90..8253f18 100644 --- a/Demo/.figmagen.yml +++ b/Demo/.figmagen.yml @@ -70,10 +70,18 @@ tokens: destination: FigmaGenDemo/Generated/SpacingTokens.swift templateOptions: publicAccess: true + blur: + destination: FigmaGenDemo/Generated/BlurTokens.swift + templateOptions: + publicAccess: true borders: destination: FigmaGenDemo/Generated/BorderTokens.swift templateOptions: publicAccess: true + borderRadiuses: + destination: FigmaGenDemo/Generated/BorderRadiusTokens.swift + templateOptions: + publicAccess: true theme: destination: FigmaGenDemo/Generated/Theme.swift templateOptions: diff --git a/Demo/FigmaGenDemo/Generated/BlurTokens.swift b/Demo/FigmaGenDemo/Generated/BlurTokens.swift new file mode 100644 index 0000000..93c9748 --- /dev/null +++ b/Demo/FigmaGenDemo/Generated/BlurTokens.swift @@ -0,0 +1,3 @@ +// swiftlint:disable all +// Generated using FigmaGen - https://github.com/hhru/FigmaGen +// No border tokens found diff --git a/Demo/FigmaGenDemo/Generated/BorderRadiusTokens.swift b/Demo/FigmaGenDemo/Generated/BorderRadiusTokens.swift new file mode 100644 index 0000000..32be22e --- /dev/null +++ b/Demo/FigmaGenDemo/Generated/BorderRadiusTokens.swift @@ -0,0 +1,20 @@ +// swiftlint:disable all +// Generated using FigmaGen - https://github.com/hhru/FigmaGen + +#if canImport(UIKit) +import UIKit +#else +import AppKit +#endif + +public struct BorderRadiusTokens { + + // MARK: - Instance Properties + + // Core + + public let borderRadiusSm: Double = 4 + public let borderRadiusLg: Double = 8 + public let borderRadiusXl: Double = 16 + public let borderRadiusMultiValue: Double = 4 8 +} diff --git a/Sources/FigmaGen/Commands/GenerateCommand.swift b/Sources/FigmaGen/Commands/GenerateCommand.swift index 9d08078..f2aa69b 100644 --- a/Sources/FigmaGen/Commands/GenerateCommand.swift +++ b/Sources/FigmaGen/Commands/GenerateCommand.swift @@ -21,7 +21,7 @@ final class GenerateCommand: AsyncExecutableCommand { let verbose = Flag( "--verbose", description: """ - Enable verbose logging for debuging. + Enable verbose logging for debugging. By default is disabled. """ ) diff --git a/Sources/FigmaGen/Commands/TokensCommand.swift b/Sources/FigmaGen/Commands/TokensCommand.swift index 0266c79..57ff352 100644 --- a/Sources/FigmaGen/Commands/TokensCommand.swift +++ b/Sources/FigmaGen/Commands/TokensCommand.swift @@ -11,292 +11,69 @@ final class TokensCommand: AsyncExecutableCommand { let name = "tokens" let shortDescription = "Generates code for tokens from a Figma file." - let fileKey = Key( - "--fileKey", - description: """ - Figma file key to generate text styles from. - """ - ) - - let fileVersion = Key( - "--fileVersion", - description: """ - Figma file version ID to generate color styles from. - """ - ) - - let remoteFileOwnerKey = Key( - "--remoteFileOwner", - description: """ - Remote Repo owner key to generate text styles from. - """ - ) - - let remoteFileRepoKey = Key( - "--remoteFileRepo", - description: """ - Remote Repo key to generate text styles from. - """ - ) - - let remoteFileBranchKey = Key( - "--remoteFileBranch", - description: """ - Remote Repo branch to generate text styles from. - """ - ) - - let remoteFilePathKey = Key( - "--remoteFilePath", - description: """ - Remote Repo file key to generate text styles from. - """ - ) - - let remoteRepoAccessTokenKey = Key( - "--remoteRepoAccessToken", - description: """ - Remote Repo personal access token to make requests to the GitHub. - """ - ) - - let accessToken = Key( - "--accessToken", - description: """ - A personal access token to make requests to the Figma API. - Get more info: https://www.figma.com/developers/api#access-tokens - """ - ) - - let themes = VariadicKey( - "--themes", - description: """ - An option that will be merged with template context. - """ - ) - - let fallbackTheme = Key( - "--fallbackTheme", - description: """ - the default theme used when the requested theme is unavailable. Must be one of the values listed in themes. - """ - ) - - let colorsTemplate = Key( - "--colors-template", - description: """ - Path to the template file. - If no template is passed a default template will be used. - """ - ) - - let colorsTemplateOptions = VariadicKey( - "--colors-options", - description: #""" - An option that will be merged with template context, and overwrite any values of the same name. - Can be repeated multiple times and must be in the format: -o "name:value". - """# - ) - - let colorsDestination = Key( - "--colors-destination", - description: """ - The path to the file to generate. - By default, generated code will be printed on stdout. - """ - ) - - let baseColorsTemplate = Key( - "--base-colors-template", - description: """ - Path to the template file. - If no template is passed a default template will be used. - """ - ) - - let baseColorsTemplateOptions = VariadicKey( - "--base-colors-options", - description: #""" - An option that will be merged with template context, and overwrite any values of the same name. - Can be repeated multiple times and must be in the format: -o "name:value". - """# - ) - - let baseColorsDestination = Key( - "--base-colors-destination", - description: """ - The path to the file to generate. - By default, generated code will be printed on stdout. - """ - ) - - let fontFamiliesTemplate = Key( - "--font-families-template", - description: """ - Path to the template file. - If no template is passed a default template will be used. - """ - ) - - let fontFamiliesTemplateOptions = VariadicKey( - "--font-families-options", - description: #""" - An option that will be merged with template context, and overwrite any values of the same name. - Can be repeated multiple times and must be in the format: -o "name:value". - """# - ) - - let fontFamiliesDestination = Key( - "--font-families-destination", - description: """ - The path to the file to generate. - By default, generated code will be printed on stdout. - """ - ) - - let typographiesTemplate = Key( - "--typographies-template", - description: """ - Path to the template file. - If no template is passed a default template will be used. - """ - ) - - let typographiesTemplateOptions = VariadicKey( - "--typographies-options", - description: #""" - An option that will be merged with template context, and overwrite any values of the same name. - Can be repeated multiple times and must be in the format: -o "name:value". - """# - ) - - let typographiesDestination = Key( - "--typographies-destination", - description: """ - The path to the file to generate. - By default, generated code will be printed on stdout. - """ - ) - - let boxShadowsTemplate = Key( - "--box-shadows-template", - description: """ - Path to the template file. - If no template is passed a default template will be used. - """ - ) - - let boxShadowsTemplateOptions = VariadicKey( - "--box-shadows-options", - description: #""" - An option that will be merged with template context, and overwrite any values of the same name. - Can be repeated multiple times and must be in the format: -o "name:value". - """# - ) - - let boxShadowsDestination = Key( - "--box-shadows-destination", - description: """ - The path to the file to generate. - By default, generated code will be printed on stdout. - """ - ) - - let themeTemplate = Key( - "--theme-template", - description: """ - Path to the template file. - If no template is passed a default template will be used. - """ - ) - - let themeTemplateOptions = VariadicKey( - "--theme-options", - description: #""" - An option that will be merged with template context, and overwrite any values of the same name. - Can be repeated multiple times and must be in the format: -o "name:value". - """# - ) - - let themeDestination = Key( - "--theme-destination", - description: """ - The path to the file to generate. - By default, generated code will be printed on stdout. - """ - ) - - let spacingTemplate = Key( - "--spacing-template", - description: """ - Path to the template file. - If no template is passed a default template will be used. - """ - ) - - let spacingTemplateOptions = VariadicKey( - "--spacing-options", - description: #""" - An option that will be merged with template context, and overwrite any values of the same name. - Can be repeated multiple times and must be in the format: -o "name:value". - """# - ) - - let spacingDestination = Key( - "--spacing-destination", - description: """ - The path to the file to generate. - By default, generated code will be printed on stdout. - """ - ) - - let bordersTemplate = Key( - "--borders-template", - description: """ - Path to the template file. - If no template is passed a default template will be used. - """ - ) - - let bordersTemplateOptions = VariadicKey( - "--borders-options", - description: """ - An option that will be merged with template context, and overwrite any values of the same name. - Can be repeated multiple times and must be in the format: -o "name:value". - """ - ) - - let bordersDestination = Key( - "--borders-destination", - description: """ - The path to the file to generate. - By default, generated code will be printed on stdout. - """ - ) - - let gradientTemplate = Key( - "--gradient-template", - description: """ - Path to the template file. - If no template is passed a default template will be used. - """ - ) - - let gradientTemplateOptions = VariadicKey( - "--gradient-options", - description: """ - An option that will be merged with template context, and overwrite any values of the same name. - Can be repeated multiple times and must be in the format: -o "name:value". - """ - ) - - let gradientDestination = Key( - "--gradient-destination", - description: """ - The path to the file to generate. - By default, generated code will be printed on stdout. - """ - ) + let fileKey = FigmaCommandKeys.fileKey + let fileVersion = FigmaCommandKeys.fileVersion + let accessToken = FigmaCommandKeys.accessToken + + let remoteFileOwnerKey = GitHubRemoteFileCommandKeys.ownerKey + let remoteFileRepoKey = GitHubRemoteFileCommandKeys.repoKey + let remoteFileBranchKey = GitHubRemoteFileCommandKeys.branchKey + let remoteFilePathKey = GitHubRemoteFileCommandKeys.pathKey + let remoteRepoAccessTokenKey = GitHubRemoteFileCommandKeys.repoAccessTokenKey + + let themes = ThemeCommandKeys.themes + let fallbackTheme = ThemeCommandKeys.fallbackTheme + let themeTemplate = ThemeCommandKeys.themeTemplate + let themeTemplateOptions = ThemeCommandKeys.themeTemplateOptions + let themeDestination = ThemeCommandKeys.themeDestination + + let colorsTemplate = ColorsCommandKeys.template + let colorsTemplateOptions = ColorsCommandKeys.templateOptions + let colorsDestination = ColorsCommandKeys.destination + + let baseColorsTemplate = ColorsCommandKeys.baseColorsTemplate + let baseColorsTemplateOptions = ColorsCommandKeys.baseColorsTemplateOptions + let baseColorsDestination = ColorsCommandKeys.baseColorsDestination + + let fontFamiliesTemplate = FontFamiliesCommandKeys.template + let fontFamiliesTemplateOptions = FontFamiliesCommandKeys.templateOptions + let fontFamiliesDestination = FontFamiliesCommandKeys.destination + + let typographiesTemplate = TypographiesCommandKeys.template + let typographiesTemplateOptions = TypographiesCommandKeys.templateOptions + let typographiesDestination = TypographiesCommandKeys.destination + + let boxShadowsTemplate = BoxShadowsCommandKeys.template + let boxShadowsTemplateOptions = BoxShadowsCommandKeys.templateOptions + let boxShadowsDestination = BoxShadowsCommandKeys.destination + + let spacingTemplate = SpacingCommandKeys.template + let spacingTemplateOptions = SpacingCommandKeys.templateOptions + let spacingDestination = SpacingCommandKeys.destination + + let bordersTemplate = BordersCommandKeys.template + let bordersTemplateOptions = BordersCommandKeys.templateOptions + let bordersDestination = BordersCommandKeys.destination + + let borderRadiusesTemplate = BordersRadiusCommandKeys.template + let borderRadiusesTemplateOptions = BordersRadiusCommandKeys.templateOptions + let borderRadiusesDestination = BordersRadiusCommandKeys.destination + + let gradientTemplate = GradientCommandKeys.template + let gradientTemplateOptions = GradientCommandKeys.templateOptions + let gradientDestination = GradientCommandKeys.destination + + let animationTimeTemplate = AnimationTimeCommandKeys.template + let animationTimeTemplateOptions = AnimationTimeCommandKeys.templateOptions + let animationTimeDestination = AnimationTimeCommandKeys.destination + + let animationEaseTemplate = AnimationEaseCommandKeys.template + let animationEaseTemplateOptions = AnimationEaseCommandKeys.templateOptions + let animationEaseDestination = AnimationEaseCommandKeys.destination + + let blurTemplate = BlurCommandKeys.template + let blurTemplateOptions = BlurCommandKeys.templateOptions + let blurDestination = BlurCommandKeys.destination // MARK: - Initializers @@ -385,12 +162,40 @@ extension TokensCommand { destination: bordersDestination.value ) ], + borderRadiuses: [ + TemplateConfiguration( + template: borderRadiusesTemplate.value, + templateOptions: resolveTemplateOptions(borderRadiusesTemplateOptions.value), + destination: borderRadiusesDestination.value + ) + ], gradients: [ TemplateConfiguration( template: gradientTemplate.value, templateOptions: resolveTemplateOptions(gradientTemplateOptions.value), destination: gradientDestination.value ) + ], + animationTimes: [ + TemplateConfiguration( + template: animationTimeTemplate.value, + templateOptions: resolveTemplateOptions(animationTimeTemplateOptions.value), + destination: animationTimeDestination.value + ) + ], + animationEases: [ + TemplateConfiguration( + template: animationEaseTemplate.value, + templateOptions: resolveTemplateOptions(animationEaseTemplateOptions.value), + destination: animationEaseDestination.value + ) + ], + blur: [ + TemplateConfiguration( + template: blurTemplate.value, + templateOptions: resolveTemplateOptions(blurTemplateOptions.value), + destination: blurDestination.value + ) ] ) ) diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/AnimationEaseCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/AnimationEaseCommandKeys.swift new file mode 100644 index 0000000..2391c74 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/AnimationEaseCommandKeys.swift @@ -0,0 +1,28 @@ +import SwiftCLI + +enum AnimationEaseCommandKeys { + + static let template = Key( + "--animationEase-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--animationEase-options", + description: """ + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """ + ) + + static let destination = Key( + "--animationEase-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/AnimationTimeCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/AnimationTimeCommandKeys.swift new file mode 100644 index 0000000..3a7dcb6 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/AnimationTimeCommandKeys.swift @@ -0,0 +1,28 @@ +import SwiftCLI + +enum AnimationTimeCommandKeys { + + static let template = Key( + "--animationTime-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--animationTime-options", + description: """ + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """ + ) + + static let destination = Key( + "--animationTime-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/BlurCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/BlurCommandKeys.swift new file mode 100644 index 0000000..077b4cb --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/BlurCommandKeys.swift @@ -0,0 +1,28 @@ +import SwiftCLI + +enum BlurCommandKeys { + + static let template = Key( + "--blur-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--blur-options", + description: """ + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """ + ) + + static let destination = Key( + "--blur-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/BordersCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/BordersCommandKeys.swift new file mode 100644 index 0000000..43e2984 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/BordersCommandKeys.swift @@ -0,0 +1,28 @@ +import SwiftCLI + +enum BordersCommandKeys { + + static let template = Key( + "--borders-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--borders-options", + description: """ + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """ + ) + + static let destination = Key( + "--borders-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/BordersRadiusCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/BordersRadiusCommandKeys.swift new file mode 100644 index 0000000..fa9d0d5 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/BordersRadiusCommandKeys.swift @@ -0,0 +1,28 @@ +import SwiftCLI + +enum BordersRadiusCommandKeys { + + static let template = Key( + "--borderRadius-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--borderRadius-options", + description: """ + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """ + ) + + static let destination = Key( + "--borderRadius-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/BoxShadowsCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/BoxShadowsCommandKeys.swift new file mode 100644 index 0000000..8abe68e --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/BoxShadowsCommandKeys.swift @@ -0,0 +1,28 @@ +import SwiftCLI + +enum BoxShadowsCommandKeys { + + static let template = Key( + "--box-shadows-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--box-shadows-options", + description: #""" + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """# + ) + + static let destination = Key( + "--box-shadows-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/ColorsCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/ColorsCommandKeys.swift new file mode 100644 index 0000000..ba5e593 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/ColorsCommandKeys.swift @@ -0,0 +1,52 @@ +import SwiftCLI + +enum ColorsCommandKeys { + + static let template = Key( + "--colors-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--colors-options", + description: #""" + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """# + ) + + static let destination = Key( + "--colors-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) + + static let baseColorsTemplate = Key( + "--base-colors-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let baseColorsTemplateOptions = VariadicKey( + "--base-colors-options", + description: #""" + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """# + ) + + static let baseColorsDestination = Key( + "--base-colors-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/FigmaCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/FigmaCommandKeys.swift new file mode 100644 index 0000000..49a9640 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/FigmaCommandKeys.swift @@ -0,0 +1,26 @@ +import SwiftCLI + +enum FigmaCommandKeys { + + static let fileKey = Key( + "--fileKey", + description: """ + Figma file key to generate text styles from. + """ + ) + + static let fileVersion = Key( + "--fileVersion", + description: """ + Figma file version ID to generate color styles from. + """ + ) + + static let accessToken = Key( + "--accessToken", + description: """ + A personal access token to make requests to the Figma API. + Get more info: https://www.figma.com/developers/api#access-tokens + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/FontCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/FontCommandKeys.swift new file mode 100644 index 0000000..1685c86 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/FontCommandKeys.swift @@ -0,0 +1,28 @@ +import SwiftCLI + +enum FontFamiliesCommandKeys { + + static let template = Key( + "--font-families-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--font-families-options", + description: #""" + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """# + ) + + static let destination = Key( + "--font-families-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/GitHubRemoteFileCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/GitHubRemoteFileCommandKeys.swift new file mode 100644 index 0000000..b1146d1 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/GitHubRemoteFileCommandKeys.swift @@ -0,0 +1,39 @@ +import SwiftCLI + +enum GitHubRemoteFileCommandKeys { + + static let ownerKey = Key( + "--remoteFileOwner", + description: """ + Remote Repo owner key to generate text styles from. + """ + ) + + static let repoKey = Key( + "--remoteFileRepo", + description: """ + Remote Repo key to generate text styles from. + """ + ) + + static let branchKey = Key( + "--remoteFileBranch", + description: """ + Remote Repo branch to generate text styles from. + """ + ) + + static let pathKey = Key( + "--remoteFilePath", + description: """ + Remote Repo file key to generate text styles from. + """ + ) + + static let repoAccessTokenKey = Key( + "--remoteRepoAccessToken", + description: """ + Remote Repo personal access token to make requests to the GitHub. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/GradientCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/GradientCommandKeys.swift new file mode 100644 index 0000000..e144133 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/GradientCommandKeys.swift @@ -0,0 +1,28 @@ +import SwiftCLI + +enum GradientCommandKeys { + + static let template = Key( + "--gradient-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--gradient-options", + description: """ + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """ + ) + + static let destination = Key( + "--gradient-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/SpacingCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/SpacingCommandKeys.swift new file mode 100644 index 0000000..0631f15 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/SpacingCommandKeys.swift @@ -0,0 +1,28 @@ +import SwiftCLI + +enum SpacingCommandKeys { + + static let template = Key( + "--spacing-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--spacing-options", + description: #""" + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """# + ) + + static let destination = Key( + "--spacing-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/ThemeCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/ThemeCommandKeys.swift new file mode 100644 index 0000000..372c520 --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/ThemeCommandKeys.swift @@ -0,0 +1,42 @@ +import SwiftCLI + +enum ThemeCommandKeys { + + static let themes = VariadicKey( + "--themes", + description: """ + An option that will be merged with template context. + """ + ) + + static let fallbackTheme = Key( + "--fallbackTheme", + description: """ + the default theme used when the requested theme is unavailable. Must be one of the values listed in themes. + """ + ) + + static let themeTemplate = Key( + "--theme-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let themeTemplateOptions = VariadicKey( + "--theme-options", + description: #""" + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """# + ) + + static let themeDestination = Key( + "--theme-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Commands/TokensCommandKeys/TypographiesCommandKeys.swift b/Sources/FigmaGen/Commands/TokensCommandKeys/TypographiesCommandKeys.swift new file mode 100644 index 0000000..8ed8c0f --- /dev/null +++ b/Sources/FigmaGen/Commands/TokensCommandKeys/TypographiesCommandKeys.swift @@ -0,0 +1,28 @@ +import SwiftCLI + +enum TypographiesCommandKeys { + + static let template = Key( + "--typographies-template", + description: """ + Path to the template file. + If no template is passed a default template will be used. + """ + ) + + static let templateOptions = VariadicKey( + "--typographies-options", + description: #""" + An option that will be merged with template context, and overwrite any values of the same name. + Can be repeated multiple times and must be in the format: -o "name:value". + """# + ) + + static let destination = Key( + "--typographies-destination", + description: """ + The path to the file to generate. + By default, generated code will be printed on stdout. + """ + ) +} diff --git a/Sources/FigmaGen/Dependencies.swift b/Sources/FigmaGen/Dependencies.swift index 05b0312..40971f1 100644 --- a/Sources/FigmaGen/Dependencies.swift +++ b/Sources/FigmaGen/Dependencies.swift @@ -190,11 +190,31 @@ enum Dependencies { templateRenderer: templateRenderer ) + static let borderRadiusTokensGenerator: BorderRadiusTokensGenerator = DefaultBorderRadiusTokensGenerator( + tokensResolver: tokensResolver, + templateRenderer: templateRenderer + ) + static let gradientTokensGenerator: GradientTokensGenerator = DefaultGradientTokensGenerator( templateRenderer: templateRenderer, gradientProvider: gradientTokensContextProvider ) + static let animationTimeTokensGenerator: AnimationTimeTokensGenerator = DefaultAnimationTimeTokensGenerator( + tokensResolver: tokensResolver, + templateRenderer: templateRenderer + ) + + static let animationEaseTokensGenerator: AnimationEaseTokensGenerator = DefaultAnimationEaseTokensGenerator( + tokensResolver: tokensResolver, + templateRenderer: templateRenderer + ) + + static let blurTokensGenerator: BlurTokensGenerator = DefaultBlurTokensGenerator( + tokensResolver: tokensResolver, + templateRenderer: templateRenderer + ) + static let tokensGenerator: TokensGenerator = DefaultTokensGenerator( tokensProvider: tokensProvider, tokensGenerationParametersResolver: tokensGenerationParametersResolver, @@ -206,7 +226,11 @@ enum Dependencies { themeTokensGenerator: themeTokensGenerator, spacingTokensGenerator: spacingTokensGenerator, bordersTokensGenerator: borderTokensGenerator, - gradientTokensGenerator: gradientTokensGenerator + borderRadiusesTokensGenerator: borderRadiusTokensGenerator, + gradientTokensGenerator: gradientTokensGenerator, + animationTimeTokensGenerator: animationTimeTokensGenerator, + animationEaseTokensGenerator: animationEaseTokensGenerator, + blurTokensGenerator: blurTokensGenerator ) static let libraryGenerator: LibraryGenerator = DefaultLibraryGenerator( diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/AnimationEase.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/AnimationEase.swift new file mode 100644 index 0000000..a884ba8 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/AnimationEase.swift @@ -0,0 +1,22 @@ +import Foundation + +struct AnimationEase { + + struct Base { + let path: [String] + let x1: String + let y1: String + let x2: String + let y2: String + } + + struct Spring { + let path: [String] + let stiffness: String + let damping: String + let mass: String + } + + let base: Base? + let spring: Spring? +} diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/AnimationTime.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/AnimationTime.swift new file mode 100644 index 0000000..05d930a --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/AnimationTime.swift @@ -0,0 +1,8 @@ +import Foundation + +struct AnimationTime { + + let path: [String] + let duration: Double + let durationMs: String +} diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/BlurToken.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/BlurToken.swift new file mode 100644 index 0000000..ab412bf --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/BlurToken.swift @@ -0,0 +1,3 @@ +import Foundation + +typealias BlurToken = ContextToken diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/BorderRadiusToken.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/BorderRadiusToken.swift new file mode 100644 index 0000000..9469585 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/BorderRadiusToken.swift @@ -0,0 +1,3 @@ +import Foundation + +typealias BorderRadiusToken = ContextToken diff --git a/Sources/FigmaGen/Generators/Tokens/DefaultTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/DefaultTokensGenerator.swift index 9994435..ebf186d 100644 --- a/Sources/FigmaGen/Generators/Tokens/DefaultTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/DefaultTokensGenerator.swift @@ -16,7 +16,11 @@ final class DefaultTokensGenerator: TokensGenerator { let themeTokensGenerator: ThemeTokensGenerator let spacingTokensGenerator: SpacingTokensGenerator let bordersTokensGenerator: BorderTokensGenerator + let borderRadiusesTokensGenerator: BorderRadiusTokensGenerator let gradientTokensGenerator: GradientTokensGenerator + let animationTimeTokensGenerator: AnimationTimeTokensGenerator + let animationEaseTokensGenerator: AnimationEaseTokensGenerator + let blurTokensGenerator: BlurTokensGenerator // MARK: - Initializers @@ -31,7 +35,11 @@ final class DefaultTokensGenerator: TokensGenerator { themeTokensGenerator: ThemeTokensGenerator, spacingTokensGenerator: SpacingTokensGenerator, bordersTokensGenerator: BorderTokensGenerator, - gradientTokensGenerator: GradientTokensGenerator + borderRadiusesTokensGenerator: BorderRadiusTokensGenerator, + gradientTokensGenerator: GradientTokensGenerator, + animationTimeTokensGenerator: AnimationTimeTokensGenerator, + animationEaseTokensGenerator: AnimationEaseTokensGenerator, + blurTokensGenerator: BlurTokensGenerator ) { self.tokensProvider = tokensProvider self.tokensGenerationParametersResolver = tokensGenerationParametersResolver @@ -43,7 +51,11 @@ final class DefaultTokensGenerator: TokensGenerator { self.themeTokensGenerator = themeTokensGenerator self.spacingTokensGenerator = spacingTokensGenerator self.bordersTokensGenerator = bordersTokensGenerator + self.borderRadiusesTokensGenerator = borderRadiusesTokensGenerator self.gradientTokensGenerator = gradientTokensGenerator + self.animationTimeTokensGenerator = animationTimeTokensGenerator + self.animationEaseTokensGenerator = animationEaseTokensGenerator + self.blurTokensGenerator = blurTokensGenerator } // MARK: - Instance Methods @@ -59,7 +71,11 @@ final class DefaultTokensGenerator: TokensGenerator { try generateThemeTokens(parameters: parameters, tokenValues: tokenValues) try generateSpacingTokens(parameters: parameters, tokenValues: tokenValues) try generateBorderTokens(parameters: parameters, tokenValues: tokenValues) + try generateBorderRadiusTokens(parameters: parameters, tokenValues: tokenValues) try generateGradientTokens(parameters: parameters, tokenValues: tokenValues) + try generateAnimationTimeTokens(parameters: parameters, tokenValues: tokenValues) + try generateAnimationEaseTokens(parameters: parameters, tokenValues: tokenValues) + try generateBlurTokens(parameters: parameters, tokenValues: tokenValues) } private func fetchTokens(from parameters: TokensGenerationParameters) async throws -> TokenValues { @@ -160,6 +176,17 @@ final class DefaultTokensGenerator: TokensGenerator { ) } + private func generateBorderRadiusTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { + try generateTokens( + borderRadiusesTokensGenerator, + tokensName: "borderRadius", + renderParameters: parameters.tokens.borderRadiusesRenderParameters, + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme + ) + } + private func generateGradientTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { try generateTokens( gradientTokensGenerator, @@ -171,6 +198,39 @@ final class DefaultTokensGenerator: TokensGenerator { ) } + private func generateAnimationTimeTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { + try generateTokens( + animationTimeTokensGenerator, + tokensName: "animationTime", + renderParameters: parameters.tokens.animationTimesRenderParameters, + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme + ) + } + + private func generateAnimationEaseTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { + try generateTokens( + animationEaseTokensGenerator, + tokensName: "animationEase", + renderParameters: parameters.tokens.animationEasesRenderParameters, + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme + ) + } + + private func generateBlurTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { + try generateTokens( + blurTokensGenerator, + tokensName: "blur", + renderParameters: parameters.tokens.blurRenderParameters, + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme + ) + } + private func generateTokens( _ generator: BaseTokenGenerator, tokensName: String, diff --git a/Sources/FigmaGen/Generators/Tokens/GenerationParametersResolver/DefaultTokensGenerationParametersResolver.swift b/Sources/FigmaGen/Generators/Tokens/GenerationParametersResolver/DefaultTokensGenerationParametersResolver.swift index 68a5667..540fa74 100644 --- a/Sources/FigmaGen/Generators/Tokens/GenerationParametersResolver/DefaultTokensGenerationParametersResolver.swift +++ b/Sources/FigmaGen/Generators/Tokens/GenerationParametersResolver/DefaultTokensGenerationParametersResolver.swift @@ -97,11 +97,31 @@ final class DefaultTokensGenerationParametersResolver: TokensGenerationParameter defaultTemplateType: .native(name: "BorderTokens") ) + let borderRadiusParameters = renderParametersResolver.resolveRenderParameters( + templates: configuration.templates?.borderRadiuses, + defaultTemplateType: .native(name: "BorderRadiusTokens") + ) + let gradientRenderParameters = renderParametersResolver.resolveRenderParameters( templates: configuration.templates?.gradients, defaultTemplateType: .native(name: "GradientTokens") ) + let animationTimesRenderParameters = renderParametersResolver.resolveRenderParameters( + templates: configuration.templates?.animationTimes, + defaultTemplateType: .native(name: "AnimationTimeTokens") + ) + + let animationEasesRenderParameters = renderParametersResolver.resolveRenderParameters( + templates: configuration.templates?.animationEases, + defaultTemplateType: .native(name: "AnimationEaseTokens") + ) + + let blurRenderParameters = renderParametersResolver.resolveRenderParameters( + templates: configuration.templates?.blur, + defaultTemplateType: .native(name: "BlurTokens") + ) + return TokensGenerationParameters( file: file, remoteFile: remoteFile, @@ -116,7 +136,11 @@ final class DefaultTokensGenerationParametersResolver: TokensGenerationParameter themeRenderParameters: themeRenderParameters, spacingRenderParameters: spacingRenderParameters, bordersRenderParameters: borderRenderParameters, - gradientsRenderParameters: gradientRenderParameters + borderRadiusesRenderParameters: borderRadiusParameters, + gradientsRenderParameters: gradientRenderParameters, + animationTimesRenderParameters: animationTimesRenderParameters, + animationEasesRenderParameters: animationEasesRenderParameters, + blurRenderParameters: blurRenderParameters ) ) } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/AnimationEase/AnimationEaseTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/AnimationEase/AnimationEaseTokensGenerator.swift new file mode 100644 index 0000000..49ef062 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/AnimationEase/AnimationEaseTokensGenerator.swift @@ -0,0 +1,3 @@ +import Foundation + +protocol AnimationEaseTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/AnimationEase/DefaultAnimationEaseTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/AnimationEase/DefaultAnimationEaseTokensGenerator.swift new file mode 100644 index 0000000..c2926f0 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/AnimationEase/DefaultAnimationEaseTokensGenerator.swift @@ -0,0 +1,111 @@ +import Foundation + +struct DefaultAnimationEaseTokensGenerator: AnimationEaseTokensGenerator { + + // MARK: - Instance properties + + private let tokensResolver: TokensResolver + private let templateRenderer: TemplateRenderer + + // MARK: - Initializers + + init(tokensResolver: TokensResolver, templateRenderer: TemplateRenderer) { + self.tokensResolver = tokensResolver + self.templateRenderer = templateRenderer + } + + // MARK: - Private instance methods + + private func makeAnimationEaseToken( + from token: TokenValue, + tokenValues: TokenValues + ) throws -> AnimationEase? { + if case .animationEaseBase(let value) = token.type { + return AnimationEase( + base: AnimationEase.Base( + path: token.name.components(separatedBy: "."), + x1: value.x1, + y1: value.y1, + x2: value.x2, + y2: value.y2 + ), + spring: nil + ) + } else if case .animationEaseSpring(let value) = token.type { + return AnimationEase( + base: nil, + spring: AnimationEase.Spring( + path: token.name.components(separatedBy: "."), + stiffness: value.stiffness, + damping: value.damping, + mass: value.mass + ) + ) + } else { + return nil + } + } + + private func makeAnimationTimeToken( + from token: TokenValue, + tokenValues: TokenValues + ) throws -> AnimationTime? { + guard case .animationTime(let value) = token.type else { + return nil + } + + return AnimationTime( + path: token.name.components(separatedBy: "."), + duration: try tokensResolver.resolveAnimationDurationValue( + value.duration, + tokenValues: tokenValues, + theme: nil + ), + durationMs: value.duration + ) + } + + // MARK: - AnimationTokensGenerator + + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { + let timesCore = try tokenValues.core.compactMap { value in + try makeAnimationTimeToken(from: value, tokenValues: tokenValues) + } + let timesSemantic = try tokenValues.semantic.compactMap { value in + try makeAnimationTimeToken(from: value, tokenValues: tokenValues) + } + + let coreAnimationEase = try tokenValues.core.compactMap { value in + try makeAnimationEaseToken(from: value, tokenValues: tokenValues) + } + let coreAnimationEaseBase = coreAnimationEase.compactMap { $0.base } + let coreAnimationEaseSpring = coreAnimationEase.compactMap { $0.spring } + + let semanticAnimationEase = try tokenValues.semantic.compactMap { value in + try makeAnimationEaseToken(from: value, tokenValues: tokenValues) + } + let semanticAnimationEaseBase = semanticAnimationEase.compactMap { $0.base } + let semanticAnimationEaseSpring = semanticAnimationEase.compactMap { $0.spring } + + let all = coreAnimationEase + semanticAnimationEase + + try templateRenderer.renderTemplate( + renderParameters.template, + to: renderParameters.destination, + context: [ + "allAnimations": all, + "animationTimesCore": timesCore, + "animationTimesSemantic": timesSemantic, + "coreAnimationEaseBase": coreAnimationEaseBase, + "coreAnimationEaseSpring": coreAnimationEaseSpring, + "semanticAnimationEaseBase": semanticAnimationEaseBase, + "semanticAnimationEaseSpring": semanticAnimationEaseSpring + ] + ) + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/AnimationTime/AnimationTimeTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/AnimationTime/AnimationTimeTokensGenerator.swift new file mode 100644 index 0000000..755cf1f --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/AnimationTime/AnimationTimeTokensGenerator.swift @@ -0,0 +1,3 @@ +import Foundation + +protocol AnimationTimeTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/AnimationTime/DefaultAnimationTimeTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/AnimationTime/DefaultAnimationTimeTokensGenerator.swift new file mode 100644 index 0000000..040885e --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/AnimationTime/DefaultAnimationTimeTokensGenerator.swift @@ -0,0 +1,63 @@ +import Foundation + +struct DefaultAnimationTimeTokensGenerator: AnimationTimeTokensGenerator { + + // MARK: - Instance properties + + private let tokensResolver: TokensResolver + private let templateRenderer: TemplateRenderer + + // MARK: - Initializers + + init(tokensResolver: TokensResolver, templateRenderer: TemplateRenderer) { + self.tokensResolver = tokensResolver + self.templateRenderer = templateRenderer + } + + // MARK: - Private instance methods + + private func makeAnimationTimeToken( + from token: TokenValue, + tokenValues: TokenValues + ) throws -> AnimationTime? { + guard case .animationTime(let value) = token.type else { + return nil + } + + return AnimationTime( + path: token.name.components(separatedBy: "."), + duration: try tokensResolver.resolveAnimationDurationValue( + value.duration, + tokenValues: tokenValues, + theme: nil + ), + durationMs: value.duration + ) + } + + // MARK: - AnimationTokensGenerator + + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { + let coreAnimationTimes = try tokenValues.core.compactMap { value in + try makeAnimationTimeToken(from: value, tokenValues: tokenValues) + } + + let semanticAnimationTimes = try tokenValues.semantic.compactMap { value in + try makeAnimationTimeToken(from: value, tokenValues: tokenValues) + } + + try templateRenderer.renderTemplate( + renderParameters.template, + to: renderParameters.destination, + context: [ + "coreAnimationTimes": coreAnimationTimes, + "semanticAnimationTimes": semanticAnimationTimes + ] + ) + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/BaseColor/BaseColorTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/BaseColor/BaseColorTokensGenerator.swift index abc6e1a..a72b9a7 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/BaseColor/BaseColorTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/BaseColor/BaseColorTokensGenerator.swift @@ -1,4 +1,3 @@ import Foundation -protocol BaseColorTokensGenerator: BaseTokenGenerator { -} +protocol BaseColorTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Blur/BlurTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Blur/BlurTokensGenerator.swift new file mode 100644 index 0000000..964c3d7 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Blur/BlurTokensGenerator.swift @@ -0,0 +1,3 @@ +import Foundation + +protocol BlurTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Blur/DefaultBlurTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Blur/DefaultBlurTokensGenerator.swift new file mode 100644 index 0000000..058febd --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Blur/DefaultBlurTokensGenerator.swift @@ -0,0 +1,65 @@ +import Foundation + +struct DefaultBlurTokensGenerator: BlurTokensGenerator { + + // MARK: - Instance properties + + private let tokensResolver: TokensResolver + private let templateRenderer: TemplateRenderer + + // MARK: - Initializers + + init(tokensResolver: TokensResolver, templateRenderer: TemplateRenderer) { + self.tokensResolver = tokensResolver + self.templateRenderer = templateRenderer + } + + // MARK: - Private instance methods + + private func makeToken( + from token: TokenValue, + tokenValues: TokenValues + ) throws -> BlurToken? { + guard case .blur(let value) = token.type else { + return nil + } + + return BlurToken( + path: token.name.components(separatedBy: "."), + value: try tokensResolver.resolveValue( + value, + tokenValues: tokenValues, + theme: nil + ) + ) + } + + // MARK: - BorderRadiusTokensGenerator + + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { + let coreBlurs = try tokenValues.core.compactMap { value in + try makeToken(from: value, tokenValues: tokenValues) + } + let semanticBlurs = try tokenValues.semantic.compactMap { value in + try makeToken(from: value, tokenValues: tokenValues) + } + + let semanticBlur = semanticBlurs.filter { !$0.path.contains("static") } + let staticBlur = semanticBlurs.filter { $0.path.contains("static") } + + try templateRenderer.renderTemplate( + renderParameters.template, + to: renderParameters.destination, + context: [ + "coreBlur": coreBlurs, + "semanticBlur": semanticBlur, + "staticBlur": staticBlur + ] + ) + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/BorderRadius/BorderRadiusTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/BorderRadius/BorderRadiusTokensGenerator.swift new file mode 100644 index 0000000..3a9b62b --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/BorderRadius/BorderRadiusTokensGenerator.swift @@ -0,0 +1,3 @@ +import Foundation + +protocol BorderRadiusTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/BorderRadius/DefaultBorderRadiusTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/BorderRadius/DefaultBorderRadiusTokensGenerator.swift new file mode 100644 index 0000000..7706029 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/BorderRadius/DefaultBorderRadiusTokensGenerator.swift @@ -0,0 +1,66 @@ +import Foundation + +struct DefaultBorderRadiusTokensGenerator: BorderRadiusTokensGenerator { + + // MARK: - Instance properties + + private let tokensResolver: TokensResolver + private let templateRenderer: TemplateRenderer + + // MARK: - Initializers + + init(tokensResolver: TokensResolver, templateRenderer: TemplateRenderer) { + self.tokensResolver = tokensResolver + self.templateRenderer = templateRenderer + } + + // MARK: - Private instance methods + + private func makeBorderRadiusToken( + from token: TokenValue, + tokenValues: TokenValues + ) throws -> BorderRadiusToken? { + guard case .borderRadius(let value) = token.type else { + return nil + } + + return BorderRadiusToken( + path: token.name.components(separatedBy: "."), + value: try tokensResolver.resolveValue( + value, + tokenValues: tokenValues, + theme: nil + ) + ) + } + + // MARK: - BorderRadiusTokensGenerator + + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { + let coreBorderRadius = try tokenValues.core.compactMap { value in + try makeBorderRadiusToken(from: value, tokenValues: tokenValues) + } + let semanticBorderRadiuses = try tokenValues.semantic.compactMap { value in + try makeBorderRadiusToken(from: value, tokenValues: tokenValues) + } + + let semanticBorderRadius = semanticBorderRadiuses.filter { !$0.path.contains("static") } + let staticBorderRadius = semanticBorderRadiuses.filter { $0.path.contains("static") } + + try templateRenderer.renderTemplate( + renderParameters.template, + to: renderParameters.destination, + context: [ + "coreBorderRadius": coreBorderRadius, + "allSemanticBorderRadiuses": semanticBorderRadiuses, + "semanticBorderRadius": semanticBorderRadius, + "staticBorderRadius": staticBorderRadius + ] + ) + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/BoxShadow/BoxShadowTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/BoxShadow/BoxShadowTokensGenerator.swift index 3ec3e11..9448fd4 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/BoxShadow/BoxShadowTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/BoxShadow/BoxShadowTokensGenerator.swift @@ -1,4 +1,3 @@ import Foundation -protocol BoxShadowTokensGenerator: BaseTokenGenerator { -} +protocol BoxShadowTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Color/ColorTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Color/ColorTokensGenerator.swift index 790b901..cb1f939 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/Color/ColorTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Color/ColorTokensGenerator.swift @@ -1,4 +1,3 @@ import Foundation -protocol ColorTokensGenerator: BaseTokenGenerator { -} +protocol ColorTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/FontFamily/FontFamilyTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/FontFamily/FontFamilyTokensGenerator.swift index 7991777..5ecec86 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/FontFamily/FontFamilyTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/FontFamily/FontFamilyTokensGenerator.swift @@ -1,4 +1,3 @@ import Foundation -protocol FontFamilyTokensGenerator: BaseTokenGenerator { -} +protocol FontFamilyTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Spacing/SpacingTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Spacing/SpacingTokensGenerator.swift index 6a8ebed..8eb4ef9 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/Spacing/SpacingTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Spacing/SpacingTokensGenerator.swift @@ -1,4 +1,3 @@ import Foundation -protocol SpacingTokensGenerator: BaseTokenGenerator { -} +protocol SpacingTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Theme/ThemeTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Theme/ThemeTokensGenerator.swift index 0bdc265..8814aac 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/Theme/ThemeTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Theme/ThemeTokensGenerator.swift @@ -1,4 +1,3 @@ import Foundation -protocol ThemeTokensGenerator: BaseTokenGenerator { -} +protocol ThemeTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Typography/TypographyTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Typography/TypographyTokensGenerator.swift index 7d1f55d..5dd6f20 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/Typography/TypographyTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Typography/TypographyTokensGenerator.swift @@ -1,4 +1,3 @@ import Foundation -protocol TypographyTokensGenerator: BaseTokenGenerator { -} +protocol TypographyTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Resolver/DefaultTokensResolver.swift b/Sources/FigmaGen/Generators/Tokens/Resolver/DefaultTokensResolver.swift index 9595a54..04dd9db 100644 --- a/Sources/FigmaGen/Generators/Tokens/Resolver/DefaultTokensResolver.swift +++ b/Sources/FigmaGen/Generators/Tokens/Resolver/DefaultTokensResolver.swift @@ -234,6 +234,15 @@ final class DefaultTokensResolver: TokensResolver { colorStopList: colorStopList ) } + + func resolveAnimationDurationValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> Double { + let resolvedValue = try resolveValue(value, tokenValues: tokenValues, theme: theme) + guard let value = Double(resolvedValue) else { + throw TokensGeneratorError(code: .unexpectedTokenValueType(name: "duration")) + } + + return value / 1000 + } } extension Int { diff --git a/Sources/FigmaGen/Generators/Tokens/Resolver/TokensResolver.swift b/Sources/FigmaGen/Generators/Tokens/Resolver/TokensResolver.swift index 94ed17b..916ffd2 100644 --- a/Sources/FigmaGen/Generators/Tokens/Resolver/TokensResolver.swift +++ b/Sources/FigmaGen/Generators/Tokens/Resolver/TokensResolver.swift @@ -92,4 +92,14 @@ protocol TokensResolver { /// - theme: Theme /// - Returns: ``LinearGradient`` object with values resolved from `linear-gradient()` func resolveLinearGradientValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> LinearGradient + + /// Resolving animation duration in `value` using ``resolveValue(_:tokenValues:)``, + /// convert `String` to `Double` value and convert milliseconds to seconds + /// + /// - Parameters: + /// - value: String value to resolve + /// - tokenValues: All token values + /// - theme: Theme + /// - Returns: Resolved value. + func resolveAnimationDurationValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> Double } diff --git a/Sources/FigmaGen/Models/Configuration/AccessTokenError.swift b/Sources/FigmaGen/Models/Configuration/AccessTokenError.swift deleted file mode 100644 index f80f9bf..0000000 --- a/Sources/FigmaGen/Models/Configuration/AccessTokenError.swift +++ /dev/null @@ -1,17 +0,0 @@ -import Foundation - -enum AccessTokenError: Error, CustomStringConvertible { - - // MARK: - Instance Properties - - case failedCreateAccessToken - - // MARK: - CustomStringConvertible - - var description: String { - switch self { - case .failedCreateAccessToken: - return "Failed to create access token" - } - } -} diff --git a/Sources/FigmaGen/Models/Configuration/Tokens/TokensTemplateConfiguration.swift b/Sources/FigmaGen/Models/Configuration/Tokens/TokensTemplateConfiguration.swift index a3c9ec9..64d4168 100644 --- a/Sources/FigmaGen/Models/Configuration/Tokens/TokensTemplateConfiguration.swift +++ b/Sources/FigmaGen/Models/Configuration/Tokens/TokensTemplateConfiguration.swift @@ -13,7 +13,11 @@ struct TokensTemplateConfiguration { let theme: [TemplateConfiguration]? let spacing: [TemplateConfiguration]? let borders: [TemplateConfiguration]? + let borderRadiuses: [TemplateConfiguration]? let gradients: [TemplateConfiguration]? + let animationTimes: [TemplateConfiguration]? + let animationEases: [TemplateConfiguration]? + let blur: [TemplateConfiguration]? } // MARK: - Decodable @@ -31,7 +35,11 @@ extension TokensTemplateConfiguration: Decodable { case theme case spacing case borders + case borderRadiuses case gradients + case animationTimes + case animationEases + case blur } // MARK: - Initializers @@ -54,5 +62,21 @@ extension TokensTemplateConfiguration: Decodable { spacing = try container.decodeIfPresent(TemplateConfigurationWrapper.self, forKey: .spacing)?.templates borders = try? container.decodeIfPresent(TemplateConfigurationWrapper.self, forKey: .borders)?.templates gradients = try? container.decodeIfPresent(TemplateConfigurationWrapper.self, forKey: .gradients)?.templates + animationTimes = try? container.decodeIfPresent( + TemplateConfigurationWrapper.self, + forKey: .animationTimes + )?.templates + animationEases = try? container.decodeIfPresent( + TemplateConfigurationWrapper.self, + forKey: .animationEases + )?.templates + borderRadiuses = try? container.decodeIfPresent( + TemplateConfigurationWrapper.self, + forKey: .borderRadiuses + )?.templates + blur = try? container.decodeIfPresent( + TemplateConfigurationWrapper.self, + forKey: .blur + )?.templates } } diff --git a/Sources/FigmaGen/Models/Parameters/TokensGenerationParameters.swift b/Sources/FigmaGen/Models/Parameters/TokensGenerationParameters.swift index 248a679..383c4c6 100644 --- a/Sources/FigmaGen/Models/Parameters/TokensGenerationParameters.swift +++ b/Sources/FigmaGen/Models/Parameters/TokensGenerationParameters.swift @@ -16,7 +16,11 @@ struct TokensGenerationParameters { let themeRenderParameters: [RenderParameters]? let spacingRenderParameters: [RenderParameters]? let bordersRenderParameters: [RenderParameters]? + let borderRadiusesRenderParameters: [RenderParameters]? let gradientsRenderParameters: [RenderParameters]? + let animationTimesRenderParameters: [RenderParameters]? + let animationEasesRenderParameters: [RenderParameters]? + let blurRenderParameters: [RenderParameters]? } // MARK: - Instance Properties diff --git a/Sources/FigmaGen/Models/Token/TokenAnimationEaseBaseValue.swift b/Sources/FigmaGen/Models/Token/TokenAnimationEaseBaseValue.swift new file mode 100644 index 0000000..dac1956 --- /dev/null +++ b/Sources/FigmaGen/Models/Token/TokenAnimationEaseBaseValue.swift @@ -0,0 +1,11 @@ +import Foundation + +struct TokenAnimationEaseBaseValue: Codable, Hashable { + + // MARK: - Instance Properties + + let x1: String + let y1: String + let x2: String + let y2: String +} diff --git a/Sources/FigmaGen/Models/Token/TokenAnimationEaseSpringValue.swift b/Sources/FigmaGen/Models/Token/TokenAnimationEaseSpringValue.swift new file mode 100644 index 0000000..b137c2d --- /dev/null +++ b/Sources/FigmaGen/Models/Token/TokenAnimationEaseSpringValue.swift @@ -0,0 +1,10 @@ +import Foundation + +struct TokenAnimationEaseSpringValue: Codable, Hashable { + + // MARK: - Instance Properties + + let stiffness: String + let damping: String + let mass: String +} diff --git a/Sources/FigmaGen/Models/Token/TokenAnimationTimeValue.swift b/Sources/FigmaGen/Models/Token/TokenAnimationTimeValue.swift new file mode 100644 index 0000000..40e3bfb --- /dev/null +++ b/Sources/FigmaGen/Models/Token/TokenAnimationTimeValue.swift @@ -0,0 +1,8 @@ +import Foundation + +struct TokenAnimationTimeValue: Codable, Hashable { + + // MARK: - Instance Properties + + let duration: String +} diff --git a/Sources/FigmaGen/Models/Token/TokenValue.swift b/Sources/FigmaGen/Models/Token/TokenValue.swift index 4d0985a..b6107ee 100644 --- a/Sources/FigmaGen/Models/Token/TokenValue.swift +++ b/Sources/FigmaGen/Models/Token/TokenValue.swift @@ -17,6 +17,10 @@ extension TokenValue: Decodable { private enum RawType: String, Decodable { case a11yScales case animation + case animationEaseBase + case animationEaseSpring + case animationTime + case blur case border case borderRadius case borderWidth @@ -65,6 +69,18 @@ extension TokenValue: Decodable { case .animation: self.type = .animation(value: try container.decode(forKey: .value)) + case .animationEaseBase: + self.type = .animationEaseBase(value: try container.decode(forKey: .value)) + + case .animationEaseSpring: + self.type = .animationEaseSpring(value: try container.decode(forKey: .value)) + + case .animationTime: + self.type = .animationTime(value: try container.decode(forKey: .value)) + + case .blur: + self.type = .blur(value: try container.decode(forKey: .value)) + case .border: self.type = .border(value: try container.decode(forKey: .value)) @@ -150,6 +166,18 @@ extension TokenValue: Encodable { case let .animation(value): try container.encode(value, forKey: .value) + case let .animationEaseBase(value): + try container.encode(value, forKey: .value) + + case let .animationEaseSpring(value): + try container.encode(value, forKey: .value) + + case let .animationTime(value): + try container.encode(value, forKey: .value) + + case let .blur(value): + try container.encode(value, forKey: .value) + case let .border(value): try container.encode(value, forKey: .value) diff --git a/Sources/FigmaGen/Models/Token/TokenValueType.swift b/Sources/FigmaGen/Models/Token/TokenValueType.swift index b7f5322..f6006dc 100644 --- a/Sources/FigmaGen/Models/Token/TokenValueType.swift +++ b/Sources/FigmaGen/Models/Token/TokenValueType.swift @@ -6,6 +6,10 @@ enum TokenValueType: Hashable { case a11yScales(value: String) case animation(value: TokenAnimationValue) + case animationEaseBase(value: TokenAnimationEaseBaseValue) + case animationEaseSpring(value: TokenAnimationEaseSpringValue) + case animationTime(value: TokenAnimationTimeValue) + case blur(value: String) case border(value: TokenBorderValue) case borderRadius(value: String) case borderWidth(value: String) @@ -34,6 +38,7 @@ enum TokenValueType: Hashable { var stringValue: String? { switch self { case let .a11yScales(value), + let .blur(value), let .borderWidth(value), let .borderRadius(value), let .color(value), @@ -53,7 +58,8 @@ enum TokenValueType: Hashable { let .textDecoration(value): return value - case .animation, .boxShadow, .typography, .unknown, .border: + case .animation, .animationEaseBase, .animationEaseSpring, .animationTime, + .boxShadow, .typography, .unknown, .border: return nil } } diff --git a/Sources/FigmaGen/Providers/GitHubApi/DTOs/GitHubError.swift b/Sources/FigmaGen/Providers/GitHubApi/DTOs/GitHubError.swift new file mode 100644 index 0000000..ddb09ef --- /dev/null +++ b/Sources/FigmaGen/Providers/GitHubApi/DTOs/GitHubError.swift @@ -0,0 +1,25 @@ +import FigmaGenTools +import Foundation + +struct GitHubError: Error, Hashable, CustomStringConvertible { + + // MARK: - Instance Properties + + let code: Int + let content: String + + // MARK: - CustomStringConvertible + + init(_ error: HTTPError) { + code = error.statusCode?.rawValue ?? 0 + content = error.statusCode?.httpErrorDescription ?? "" + } + + var description: String { + if 400...404 ~= code { + return "\(type(of: self)) \(content) (access token error)" + } + + return "\(type(of: self)) \(content)" + } +} diff --git a/Sources/FigmaGen/Providers/GitHubApi/DTOs/GitHubTokenValue.swift b/Sources/FigmaGen/Providers/GitHubApi/DTOs/GitHubTokenValue.swift index 003a769..209983b 100644 --- a/Sources/FigmaGen/Providers/GitHubApi/DTOs/GitHubTokenValue.swift +++ b/Sources/FigmaGen/Providers/GitHubApi/DTOs/GitHubTokenValue.swift @@ -27,6 +27,10 @@ extension GitHubTokenValue: Decodable { case a11yScales case animation + case animationTime + case animationEaseBase + case animationEaseSpring + case blur case border case borderRadius case borderWidth @@ -75,6 +79,18 @@ extension GitHubTokenValue: Decodable { case .animation: self.type = .animation(value: try container.decode(forKey: .value)) + case .animationEaseBase: + self.type = .animationEaseBase(value: try container.decode(forKey: .value)) + + case .animationEaseSpring: + self.type = .animationEaseSpring(value: try container.decode(forKey: .value)) + + case .animationTime: + self.type = .animationTime(value: try container.decode(forKey: .value)) + + case .blur: + self.type = .blur(value: try container.decode(forKey: .value)) + case .borderRadius: self.type = .borderRadius(value: try container.decode(forKey: .value)) @@ -161,6 +177,18 @@ extension GitHubTokenValue: Encodable { case let .animation(value): try container.encode(value, forKey: .value) + case let .animationEaseBase(value): + try container.encode(value, forKey: .value) + + case let .animationEaseSpring(value): + try container.encode(value, forKey: .value) + + case let .animationTime(value): + try container.encode(value, forKey: .value) + + case let .blur(value): + try container.encode(value, forKey: .value) + case let .borderRadius(value): try container.encode(value, forKey: .value) diff --git a/Sources/FigmaGen/Providers/GitHubApi/GitHubAPIProvider.swift b/Sources/FigmaGen/Providers/GitHubApi/GitHubAPIProvider.swift index 9147cdc..a36408c 100644 --- a/Sources/FigmaGen/Providers/GitHubApi/GitHubAPIProvider.swift +++ b/Sources/FigmaGen/Providers/GitHubApi/GitHubAPIProvider.swift @@ -62,15 +62,11 @@ final class GitHubAPIProvider: RemoteRepoProvider { } private func handleHTTPError(_ error: HTTPError) -> Error { - guard let errorData = error.data, error.reason is HTTPStatusCode else { + guard error.reason is HTTPStatusCode else { return error } - guard let apiError = try? responseDecoder.decode(FigmaError.self, from: errorData) else { - return error - } - - return apiError + return GitHubError(error) } } diff --git a/Templates/AnimationEaseTokens.stencil b/Templates/AnimationEaseTokens.stencil new file mode 100644 index 0000000..afae398 --- /dev/null +++ b/Templates/AnimationEaseTokens.stencil @@ -0,0 +1,70 @@ +{% include "FileHeader.stencil" %} +{% if semanticAnimationEaseBase or semanticAnimationEaseSpring or coreAnimationEaseBase or coreAnimationEaseSpring %} +{% macro propertyName name %}{{ name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords }}{% endmacro %} +{% macro makeBase baseAnimations %} +{% for animation in baseAnimations %} + public let {% call propertyName animation.path.last %} = AnimationEaseBase( + x1: {{ animation.x1 }}, + y1: {{ animation.y1 }}, + x2: {{ animation.x2 }}, + y2: {{ animation.y2 }} + ) +{% endfor %} +{% endmacro %} +{% macro makeSpring springAnimations %} +{% for animation in springAnimations %} + public let {% call propertyName animation.path.last %} = AnimationEaseSpring( + stiffness: {{ animation.stiffness }}, + damping: {{ animation.damping }}, + mass: {{ animation.mass }} + ) +{% endfor %} +{% endmacro %} + +import Foundation + +public struct AnimationEase: Sendable { + {% if semanticAnimationEaseBase or semanticAnimationEaseSpring %} + + // MARK: - Semantic + {% if semanticAnimationEaseBase %} + + {% call makeBase semanticAnimationEaseBase %} + {% endif %} + {% if semanticAnimationEaseSpring %} + + {% call makeSpring semanticAnimationEaseSpring %} + {% endif %} + {% endif %} + + {% if coreAnimationEaseBase or coreAnimationEaseSpring %} + + // MARK: - Core + {% if coreAnimationEaseBase %} + + {% call makeBase coreAnimationEaseBase %} + {% endif %} + {% if coreAnimationEaseSpring %} + + {% call makeSpring coreAnimationEaseSpring %} + {% endif %} + {% endif %} +} + +struct AnimationEaseBase { + let path: [String] + let x1: String + let y1: String + let x2: String + let y2: String +} + +struct AnimationEaseSpring { + let path: [String] + let stiffness: String + let damping: String + let mass: String +} +{% else %} +// No animation ease tokens found +{% endif %} \ No newline at end of file diff --git a/Templates/AnimationTimeTokens.stencil b/Templates/AnimationTimeTokens.stencil new file mode 100644 index 0000000..c3daed1 --- /dev/null +++ b/Templates/AnimationTimeTokens.stencil @@ -0,0 +1,28 @@ +{% include "FileHeader.stencil" %} +{% if semanticAnimationTimes or coreAnimationTimes %} +{% macro propertyName name %}{{ name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords }}{% endmacro %} + +import Foundation + +public struct MagritteAnimationTimes: Sendable { + + {% if semanticAnimationTimes %} + // MARK: - semantic + {% for time in semanticAnimationTimes %} + + public let {% call propertyName time.path.last %}: Double = {{ time.duration }} + {% endfor %} + {% endif %} + + {% if coreAnimationTimes %} + + // MARK: - core + {% for time in coreAnimationTimes %} + + public let {% call propertyName time.path.last %}: Double = {{ time.duration }} + {% endfor %} + {% endif %} +} +{% else %} +// No animation time tokens found +{% endif %} \ No newline at end of file diff --git a/Templates/BlurTokens.stencil b/Templates/BlurTokens.stencil new file mode 100644 index 0000000..f8730dc --- /dev/null +++ b/Templates/BlurTokens.stencil @@ -0,0 +1,46 @@ +{% include "FileHeader.stencil" %} +{% if coreBlur or semanticBlur or staticBlur -%} +{% set accessModifier %}{% if options.publicAccess %}public{% else %}internal{% endif %}{% endset %} +{% set tokenTypeName %}{{ options.tokenTypeName|default:"BlurTokens" }}{% endset %} +{% macro propertyName name %}{{ name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords }}{% endmacro %} +{% macro blurProperty blur -%} + {{ accessModifier }} let {% call propertyName blur.path|removingFirst:"static"|removingFirst:"semantic"|removingFirst:"core"|join:"_" %}: Double = {{ blur.value }}.0 +{%- endmacro %} + +#if canImport(UIKit) +import UIKit +#else +import AppKit +#endif + +{{ accessModifier }} struct {{ tokenTypeName }} { + + // MARK: - Instance Properties + {% if semanticBlur %} + + // Semantic + + {% for blur in semanticBlur %} + {% call blurProperty blur %} + {% endfor %} + {% endif %} + {% if staticBlur %} + + // Static + + {% for blur in staticBlur %} + {% call blurProperty blur %} + {% endfor %} + {% endif %} + {% if coreBlur %} + + // Core + + {% for blur in coreBlur %} + {% call blurProperty blur %} + {% endfor %} + {% endif %} +} +{%- else -%} +// No border tokens found +{%- endif %} diff --git a/Templates/BorderRadiusTokens.stencil b/Templates/BorderRadiusTokens.stencil new file mode 100644 index 0000000..a6d3995 --- /dev/null +++ b/Templates/BorderRadiusTokens.stencil @@ -0,0 +1,46 @@ +{% include "FileHeader.stencil" %} +{% if semanticBorderRadius or coreBorderRadius or staticBorderRadius -%} +{% set accessModifier %}{% if options.publicAccess %}public{% else %}internal{% endif %}{% endset %} +{% set tokenTypeName %}{{ options.tokenTypeName|default:"BorderRadiusTokens" }}{% endset %} +{% macro propertyName name %}{{ name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords }}{% endmacro %} +{% macro borderRadiusProperty borderRadius -%} + {{ accessModifier }} let {% call propertyName borderRadius.path|removingFirst:"static"|removingFirst:"semantic"|removingFirst:"core"|join:"_" %}: Double = {{ borderRadius.value }} +{%- endmacro %} + +#if canImport(UIKit) +import UIKit +#else +import AppKit +#endif + +{{ accessModifier }} struct {{ tokenTypeName }} { + + // MARK: - Instance Properties + {% if semanticBorderRadius %} + + // Semantic + + {% for borderRadius in semanticBorderRadius %} + {% call borderRadiusProperty borderRadius %} + {% endfor %} + {% endif %} + {% if staticBorderRadius %} + + // Static + + {% for borderRadius in staticBorderRadius %} + {% call borderRadiusProperty borderRadius %} + {% endfor %} + {% endif %} + {% if coreBorderRadius %} + + // Core + + {% for borderRadius in coreBorderRadius %} + {% call borderRadiusProperty borderRadius %} + {% endfor %} + {% endif %} +} +{%- else -%} +// No border tokens found +{%- endif %}