diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d862b33..8ca95b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: linux: name: Linux - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v2 - name: Ruby diff --git a/Demo/.figmagen.yml b/Demo/.figmagen.yml index ecf3b1c..a027a90 100644 --- a/Demo/.figmagen.yml +++ b/Demo/.figmagen.yml @@ -39,6 +39,10 @@ shadowStyles: tokens: file: https://www.figma.com/file/W6dy4CFSZWUVpVnSzNZIxA/FigmaGen-Tokens-Demo + themes: + - hh-day + - hh-night + fallbackTheme: hh-day templates: colors: - destination: FigmaGenDemo/Generated/ColorTokens.swift @@ -66,6 +70,10 @@ tokens: destination: FigmaGenDemo/Generated/SpacingTokens.swift templateOptions: publicAccess: true + borders: + destination: FigmaGenDemo/Generated/BorderTokens.swift + templateOptions: + publicAccess: true theme: destination: FigmaGenDemo/Generated/Theme.swift templateOptions: diff --git a/Demo/FigmaGenDemo/Generated/BorderTokens.swift b/Demo/FigmaGenDemo/Generated/BorderTokens.swift new file mode 100644 index 0000000..93c9748 --- /dev/null +++ b/Demo/FigmaGenDemo/Generated/BorderTokens.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/BoxShadowTokens.swift b/Demo/FigmaGenDemo/Generated/BoxShadowTokens.swift index 83bf8dd..99d68fc 100644 --- a/Demo/FigmaGenDemo/Generated/BoxShadowTokens.swift +++ b/Demo/FigmaGenDemo/Generated/BoxShadowTokens.swift @@ -8,25 +8,34 @@ import AppKit public struct BoxShadowTokens { - /// level-1 - /// - /// Offset: day – x 0; y 4 / night – x 0; y 4 - /// Radius: day – 12 / night – 12 - /// Color: day – #7090b029 / night – #7090b029 + /// - hh-day: + /// Offset: x 0; y 4 + /// Radius: 12 + /// Color: #7090b029 + /// - hh-night: + /// Offset: x 0; y 4 + /// Radius: 12 + /// Color: #7090b029 public let level1: ShadowToken - /// level-2 - /// - /// Offset: day – x 0; y 8 / night – x 0; y 8 - /// Radius: day – 16 / night – 16 - /// Color: day – #7090b03d / night – #7090b03d + /// - hh-day: + /// Offset: x 0; y 8 + /// Radius: 16 + /// Color: #7090b03d + /// - hh-night: + /// Offset: x 0; y 8 + /// Radius: 16 + /// Color: #7090b03d public let level2: ShadowToken - /// level-3 - /// - /// Offset: day – x 0; y 12 / night – x 0; y 12 - /// Radius: day – 24 / night – 24 - /// Color: day – #7090b052 / night – #7090b052 + /// - hh-day: + /// Offset: x 0; y 12 + /// Radius: 24 + /// Color: #7090b052 + /// - hh-night: + /// Offset: x 0; y 12 + /// Radius: 24 + /// Color: #7090b052 public let level3: ShadowToken } diff --git a/Demo/FigmaGenDemo/Generated/ColorTokens.swift b/Demo/FigmaGenDemo/Generated/ColorTokens.swift index edb82ef..5d84619 100644 --- a/Demo/FigmaGenDemo/Generated/ColorTokens.swift +++ b/Demo/FigmaGenDemo/Generated/ColorTokens.swift @@ -11,18 +11,18 @@ public struct ColorTokens { public struct Accent { /// accent.bg /// - /// Day: #c3dafe - /// Night: #434190 + /// hh-day: #c3dafe + /// hh-night: #434190 public let bg: UIColor /// accent.default /// - /// Day: #7f9cf5 - /// Night: #5a67d8 + /// hh-day: #7f9cf5 + /// hh-night: #5a67d8 public let `default`: UIColor /// accent.onAccent /// - /// Day: #ffffff - /// Night: #ffffff + /// hh-day: #ffffff + /// hh-night: #ffffff public let onAccent: UIColor } @@ -30,18 +30,18 @@ public struct ColorTokens { public struct Bg { /// bg.default /// - /// Day: #ffffff - /// Night: #1a202c + /// hh-day: #ffffff + /// hh-night: #1a202c public let `default`: UIColor /// bg.muted /// - /// Day: #f7fafc - /// Night: #4a5568 + /// hh-day: #f7fafc + /// hh-night: #4a5568 public let muted: UIColor /// bg.subtle /// - /// Day: #edf2f7 - /// Night: #718096 + /// hh-day: #edf2f7 + /// hh-night: #718096 public let subtle: UIColor } @@ -49,18 +49,18 @@ public struct ColorTokens { public struct Fg { /// fg.default /// - /// Day: #000000 - /// Night: #ffffff + /// hh-day: #000000 + /// hh-night: #ffffff public let `default`: UIColor /// fg.muted /// - /// Day: #4a5568 - /// Night: #e2e8f0 + /// hh-day: #4a5568 + /// hh-night: #e2e8f0 public let muted: UIColor /// fg.subtle /// - /// Day: #a0aec0 - /// Night: #a0aec0 + /// hh-day: #a0aec0 + /// hh-night: #a0aec0 public let subtle: UIColor } @@ -68,8 +68,8 @@ public struct ColorTokens { public struct Shadows { /// shadows.default /// - /// Day: #1a202c - /// Night: #00000000 + /// hh-day: #1a202c + /// hh-night: #00000000 public let `default`: UIColor } diff --git a/Demo/FigmaGenDemo/Generated/Theme.swift b/Demo/FigmaGenDemo/Generated/Theme.swift index b5b9966..c159b81 100644 --- a/Demo/FigmaGenDemo/Generated/Theme.swift +++ b/Demo/FigmaGenDemo/Generated/Theme.swift @@ -26,7 +26,7 @@ public struct Theme { extension Theme { - public static let defaultLight = Self( + public static let hhDay = Self( colors: ColorTokens( accent: ColorTokens.Accent( bg: UIColor(hex: 0xC3DAFEFF), @@ -68,8 +68,7 @@ extension Theme { ) ) ) - - public static let defaultDark = Self( + public static let hhNight = Self( colors: ColorTokens( accent: ColorTokens.Accent( bg: UIColor(hex: 0x434190FF), diff --git a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Contents.json b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Contents.json index 2fa43f1..a274db6 100644 --- a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Colors.xcassets/DaisyBush.colorset/Contents.json b/Demo/FigmaGenDemo/Resources/Colors.xcassets/DaisyBush.colorset/Contents.json index f8733e3..023f364 100644 --- a/Demo/FigmaGenDemo/Resources/Colors.xcassets/DaisyBush.colorset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Colors.xcassets/DaisyBush.colorset/Contents.json @@ -1,20 +1,20 @@ { - "info" : { - "version" : 1, - "author" : "FigmaGen" - }, "colors" : [ { "color" : { "color-space" : "srgb", "components" : { - "red" : "0.35686275362968445", "alpha" : "0.75", "blue" : "0.5882353186607361", - "green" : "0.25882354378700256" + "green" : "0.25882354378700256", + "red" : "0.35686275362968445" } }, "idiom" : "universal" } - ] + ], + "info" : { + "author" : "FigmaGen", + "version" : 1 + } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Eclipse.colorset/Contents.json b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Eclipse.colorset/Contents.json index 99772d6..4e15a0f 100644 --- a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Eclipse.colorset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Eclipse.colorset/Contents.json @@ -1,20 +1,20 @@ { - "info" : { - "version" : 1, - "author" : "FigmaGen" - }, "colors" : [ { "color" : { "color-space" : "srgb", "components" : { - "red" : "0.2235294133424759", "alpha" : "1.0", "blue" : "0.2235294133424759", - "green" : "0.2235294133424759" + "green" : "0.2235294133424759", + "red" : "0.2235294133424759" } }, "idiom" : "universal" } - ] + ], + "info" : { + "author" : "FigmaGen", + "version" : 1 + } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Colors.xcassets/JellyBean.colorset/Contents.json b/Demo/FigmaGenDemo/Resources/Colors.xcassets/JellyBean.colorset/Contents.json index e9f6133..ede2d36 100644 --- a/Demo/FigmaGenDemo/Resources/Colors.xcassets/JellyBean.colorset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Colors.xcassets/JellyBean.colorset/Contents.json @@ -1,20 +1,20 @@ { - "info" : { - "version" : 1, - "author" : "FigmaGen" - }, "colors" : [ { "color" : { "color-space" : "srgb", "components" : { - "red" : "0.25882354378700256", "alpha" : "1.0", "blue" : "0.5882353186607361", - "green" : "0.4901960790157318" + "green" : "0.4901960790157318", + "red" : "0.25882354378700256" } }, "idiom" : "universal" } - ] + ], + "info" : { + "author" : "FigmaGen", + "version" : 1 + } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Lochinvar.colorset/Contents.json b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Lochinvar.colorset/Contents.json index a245923..ed5f229 100644 --- a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Lochinvar.colorset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Lochinvar.colorset/Contents.json @@ -1,20 +1,20 @@ { - "info" : { - "version" : 1, - "author" : "FigmaGen" - }, "colors" : [ { "color" : { "color-space" : "srgb", "components" : { - "red" : "0.25882354378700256", "alpha" : "1.0", "blue" : "0.4901960790157318", - "green" : "0.5882353186607361" + "green" : "0.5882353186607361", + "red" : "0.25882354378700256" } }, "idiom" : "universal" } - ] + ], + "info" : { + "author" : "FigmaGen", + "version" : 1 + } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Razzmatazz.colorset/Contents.json b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Razzmatazz.colorset/Contents.json index 105793d..89cf210 100644 --- a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Razzmatazz.colorset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Razzmatazz.colorset/Contents.json @@ -1,20 +1,20 @@ { - "info" : { - "version" : 1, - "author" : "FigmaGen" - }, "colors" : [ { "color" : { "color-space" : "srgb", "components" : { - "red" : "0.8901960849761963", "alpha" : "1.0", "blue" : "0.3607843220233917", - "green" : "0.04313725605607033" + "green" : "0.04313725605607033", + "red" : "0.8901960849761963" } }, "idiom" : "universal" } - ] + ], + "info" : { + "author" : "FigmaGen", + "version" : 1 + } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Colors.xcassets/SnowDrift.colorset/Contents.json b/Demo/FigmaGenDemo/Resources/Colors.xcassets/SnowDrift.colorset/Contents.json index 996ea25..92e03d7 100644 --- a/Demo/FigmaGenDemo/Resources/Colors.xcassets/SnowDrift.colorset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Colors.xcassets/SnowDrift.colorset/Contents.json @@ -1,20 +1,20 @@ { - "info" : { - "version" : 1, - "author" : "FigmaGen" - }, "colors" : [ { "color" : { "color-space" : "srgb", "components" : { - "red" : "0.8549019694328308", "alpha" : "1.0", "blue" : "0.8509804010391235", - "green" : "0.8549019694328308" + "green" : "0.8549019694328308", + "red" : "0.8549019694328308" } }, "idiom" : "universal" } - ] + ], + "info" : { + "author" : "FigmaGen", + "version" : 1 + } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Submarine.colorset/Contents.json b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Submarine.colorset/Contents.json index 08104a1..caa4f87 100644 --- a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Submarine.colorset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Submarine.colorset/Contents.json @@ -1,20 +1,20 @@ { - "info" : { - "version" : 1, - "author" : "FigmaGen" - }, "colors" : [ { "color" : { "color-space" : "srgb", "components" : { - "red" : "0.5803921818733215", "alpha" : "1.0", "blue" : "0.5960784554481506", - "green" : "0.5921568870544434" + "green" : "0.5921568870544434", + "red" : "0.5803921818733215" } }, "idiom" : "universal" } - ] + ], + "info" : { + "author" : "FigmaGen", + "version" : 1 + } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Whisper.colorset/Contents.json b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Whisper.colorset/Contents.json index ebd40e9..bd3b527 100644 --- a/Demo/FigmaGenDemo/Resources/Colors.xcassets/Whisper.colorset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Colors.xcassets/Whisper.colorset/Contents.json @@ -1,20 +1,20 @@ { - "info" : { - "version" : 1, - "author" : "FigmaGen" - }, "colors" : [ { "color" : { "color-space" : "srgb", "components" : { - "red" : "0.9137254953384399", "alpha" : "1.0", "blue" : "0.9137254953384399", - "green" : "0.9137254953384399" + "green" : "0.9137254953384399", + "red" : "0.9137254953384399" } }, "idiom" : "universal" } - ] + ], + "info" : { + "author" : "FigmaGen", + "version" : 1 + } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Cloud.imageset/Cloud.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Cloud.imageset/Cloud.pdf index cc48f85..407cae7 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Cloud.imageset/Cloud.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Cloud.imageset/Cloud.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Cloud.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Cloud.imageset/Contents.json index 540d7c3..30f7efc 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Cloud.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Cloud.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "Cloud.pdf" + "filename" : "Cloud.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Contents.json index 2fa43f1..a274db6 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Geo.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Geo.imageset/Contents.json index 870c4d1..4019aa5 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Geo.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Geo.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "Geo.pdf" + "filename" : "Geo.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Geo.imageset/Geo.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Geo.imageset/Geo.pdf index 96ec68b..74c668e 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Geo.imageset/Geo.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Geo.imageset/Geo.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Phone.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Phone.imageset/Contents.json index 75988d7..548d826 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Phone.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Phone.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "Phone.pdf" + "filename" : "Phone.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Phone.imageset/Phone.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Phone.imageset/Phone.pdf index b3450cc..315cf7b 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Phone.imageset/Phone.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Phone.imageset/Phone.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Share.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Share.imageset/Contents.json index da64a08..6104ffb 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Share.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Share.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "Share.pdf" + "filename" : "Share.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Share.imageset/Share.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Share.imageset/Share.pdf index 6c123b5..832da6c 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Share.imageset/Share.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Share.imageset/Share.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Snapchat.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Snapchat.imageset/Contents.json index 9de5ea2..b638a4d 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Snapchat.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Snapchat.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "Snapchat.pdf" + "filename" : "Snapchat.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Snapchat.imageset/Snapchat.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Snapchat.imageset/Snapchat.pdf index 68ea315..867bfbe 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Snapchat.imageset/Snapchat.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Snapchat.imageset/Snapchat.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Star.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Star.imageset/Contents.json index 55e412b..a25926c 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Star.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Star.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "Star.pdf" + "filename" : "Star.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Star.imageset/Star.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Star.imageset/Star.pdf index 19d3c56..874d71c 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Star.imageset/Star.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Star.imageset/Star.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Telegram.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Telegram.imageset/Contents.json index 601eec2..6e13865 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Telegram.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Telegram.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "Telegram.pdf" + "filename" : "Telegram.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Telegram.imageset/Telegram.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Telegram.imageset/Telegram.pdf index 6e540a4..fcd5216 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Telegram.imageset/Telegram.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Telegram.imageset/Telegram.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Viber.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Viber.imageset/Contents.json index ea5af11..797325b 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Viber.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Viber.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "Viber.pdf" + "filename" : "Viber.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Viber.imageset/Viber.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Viber.imageset/Viber.pdf index f749571..5944614 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Viber.imageset/Viber.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/Viber.imageset/Viber.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WeChat.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WeChat.imageset/Contents.json index 94bced4..3c32904 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WeChat.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WeChat.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "WeChat.pdf" + "filename" : "WeChat.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WeChat.imageset/WeChat.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WeChat.imageset/WeChat.pdf index bed1d06..32e406f 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WeChat.imageset/WeChat.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WeChat.imageset/WeChat.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WhatsApp.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WhatsApp.imageset/Contents.json index 6fefb11..7fc8745 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WhatsApp.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WhatsApp.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "WhatsApp.pdf" + "filename" : "WhatsApp.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WhatsApp.imageset/WhatsApp.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WhatsApp.imageset/WhatsApp.pdf index 9f5be91..726c054 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WhatsApp.imageset/WhatsApp.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Icon/WhatsApp.imageset/WhatsApp.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/Contents.json index 2fa43f1..a274db6 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleFilled.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleFilled.imageset/Contents.json index 010ab1c..5346105 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleFilled.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleFilled.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialBehanceStyleFilled.pdf" + "filename" : "InterfaceEssentialBehanceStyleFilled.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleFilled.imageset/InterfaceEssentialBehanceStyleFilled.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleFilled.imageset/InterfaceEssentialBehanceStyleFilled.pdf index 6189715..b204451 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleFilled.imageset/InterfaceEssentialBehanceStyleFilled.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleFilled.imageset/InterfaceEssentialBehanceStyleFilled.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleOutlined.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleOutlined.imageset/Contents.json index a411805..bd0f26f 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleOutlined.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleOutlined.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialBehanceStyleOutlined.pdf" + "filename" : "InterfaceEssentialBehanceStyleOutlined.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleOutlined.imageset/InterfaceEssentialBehanceStyleOutlined.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleOutlined.imageset/InterfaceEssentialBehanceStyleOutlined.pdf index b021183..ebc0ff1 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleOutlined.imageset/InterfaceEssentialBehanceStyleOutlined.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialBehance/InterfaceEssentialBehanceStyleOutlined.imageset/InterfaceEssentialBehanceStyleOutlined.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/Contents.json index 2fa43f1..a274db6 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleFilled.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleFilled.imageset/Contents.json index f76e387..8faeda0 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleFilled.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleFilled.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialDribbbleStyleFilled.pdf" + "filename" : "InterfaceEssentialDribbbleStyleFilled.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleFilled.imageset/InterfaceEssentialDribbbleStyleFilled.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleFilled.imageset/InterfaceEssentialDribbbleStyleFilled.pdf index d89ec07..029d1a6 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleFilled.imageset/InterfaceEssentialDribbbleStyleFilled.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleFilled.imageset/InterfaceEssentialDribbbleStyleFilled.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleOutlined.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleOutlined.imageset/Contents.json index 18ec5d9..a929d6d 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleOutlined.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleOutlined.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialDribbbleStyleOutlined.pdf" + "filename" : "InterfaceEssentialDribbbleStyleOutlined.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleOutlined.imageset/InterfaceEssentialDribbbleStyleOutlined.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleOutlined.imageset/InterfaceEssentialDribbbleStyleOutlined.pdf index e6b7904..ead62ce 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleOutlined.imageset/InterfaceEssentialDribbbleStyleOutlined.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialDribbble/InterfaceEssentialDribbbleStyleOutlined.imageset/InterfaceEssentialDribbbleStyleOutlined.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/Contents.json index 2fa43f1..a274db6 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookOutlined.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookOutlined.imageset/Contents.json index 64c430a..197a1ab 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookOutlined.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookOutlined.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialFacebookOutlined.pdf" + "filename" : "InterfaceEssentialFacebookOutlined.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookOutlined.imageset/InterfaceEssentialFacebookOutlined.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookOutlined.imageset/InterfaceEssentialFacebookOutlined.pdf index 5a0ac39..7aaaf6e 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookOutlined.imageset/InterfaceEssentialFacebookOutlined.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookOutlined.imageset/InterfaceEssentialFacebookOutlined.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookStyleFilled.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookStyleFilled.imageset/Contents.json index 7f55f7a..2e78276 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookStyleFilled.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookStyleFilled.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialFacebookStyleFilled.pdf" + "filename" : "InterfaceEssentialFacebookStyleFilled.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookStyleFilled.imageset/InterfaceEssentialFacebookStyleFilled.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookStyleFilled.imageset/InterfaceEssentialFacebookStyleFilled.pdf index ddfc61f..3515883 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookStyleFilled.imageset/InterfaceEssentialFacebookStyleFilled.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFacebook/InterfaceEssentialFacebookStyleFilled.imageset/InterfaceEssentialFacebookStyleFilled.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/Contents.json index 2fa43f1..a274db6 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleFilled.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleFilled.imageset/Contents.json index a439fee..556c5dd 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleFilled.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleFilled.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialFigmaStyleFilled.pdf" + "filename" : "InterfaceEssentialFigmaStyleFilled.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleFilled.imageset/InterfaceEssentialFigmaStyleFilled.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleFilled.imageset/InterfaceEssentialFigmaStyleFilled.pdf index 7889687..47e4236 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleFilled.imageset/InterfaceEssentialFigmaStyleFilled.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleFilled.imageset/InterfaceEssentialFigmaStyleFilled.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleOutlined.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleOutlined.imageset/Contents.json index 30947c8..c8142e0 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleOutlined.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleOutlined.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialFigmaStyleOutlined.pdf" + "filename" : "InterfaceEssentialFigmaStyleOutlined.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleOutlined.imageset/InterfaceEssentialFigmaStyleOutlined.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleOutlined.imageset/InterfaceEssentialFigmaStyleOutlined.pdf index 83e8da7..bd46b51 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleOutlined.imageset/InterfaceEssentialFigmaStyleOutlined.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialFigma/InterfaceEssentialFigmaStyleOutlined.imageset/InterfaceEssentialFigmaStyleOutlined.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/Contents.json index 2fa43f1..a274db6 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleFilled.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleFilled.imageset/Contents.json index d193700..f54934c 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleFilled.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleFilled.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialGoogleStyleFilled.pdf" + "filename" : "InterfaceEssentialGoogleStyleFilled.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleFilled.imageset/InterfaceEssentialGoogleStyleFilled.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleFilled.imageset/InterfaceEssentialGoogleStyleFilled.pdf index a61c097..65a433c 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleFilled.imageset/InterfaceEssentialGoogleStyleFilled.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleFilled.imageset/InterfaceEssentialGoogleStyleFilled.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleOutlined.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleOutlined.imageset/Contents.json index ababe39..b5a12f5 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleOutlined.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleOutlined.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialGoogleStyleOutlined.pdf" + "filename" : "InterfaceEssentialGoogleStyleOutlined.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleOutlined.imageset/InterfaceEssentialGoogleStyleOutlined.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleOutlined.imageset/InterfaceEssentialGoogleStyleOutlined.pdf index 1305fae..fc205ce 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleOutlined.imageset/InterfaceEssentialGoogleStyleOutlined.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialGoogle/InterfaceEssentialGoogleStyleOutlined.imageset/InterfaceEssentialGoogleStyleOutlined.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/Contents.json index 2fa43f1..a274db6 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleFilled.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleFilled.imageset/Contents.json index 3ad0337..400c8d1 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleFilled.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleFilled.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialInstagramStyleFilled.pdf" + "filename" : "InterfaceEssentialInstagramStyleFilled.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleFilled.imageset/InterfaceEssentialInstagramStyleFilled.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleFilled.imageset/InterfaceEssentialInstagramStyleFilled.pdf index 13ef550..d2cc1c7 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleFilled.imageset/InterfaceEssentialInstagramStyleFilled.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleFilled.imageset/InterfaceEssentialInstagramStyleFilled.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleOutlined.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleOutlined.imageset/Contents.json index e9f94ae..2f671e1 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleOutlined.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleOutlined.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialInstagramStyleOutlined.pdf" + "filename" : "InterfaceEssentialInstagramStyleOutlined.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleOutlined.imageset/InterfaceEssentialInstagramStyleOutlined.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleOutlined.imageset/InterfaceEssentialInstagramStyleOutlined.pdf index e079314..7af15fc 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleOutlined.imageset/InterfaceEssentialInstagramStyleOutlined.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialInstagram/InterfaceEssentialInstagramStyleOutlined.imageset/InterfaceEssentialInstagramStyleOutlined.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/Contents.json index 2fa43f1..a274db6 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleFilled.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleFilled.imageset/Contents.json index 600db9f..60af618 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleFilled.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleFilled.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialLinkedinStyleFilled.pdf" + "filename" : "InterfaceEssentialLinkedinStyleFilled.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleFilled.imageset/InterfaceEssentialLinkedinStyleFilled.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleFilled.imageset/InterfaceEssentialLinkedinStyleFilled.pdf index f4905d7..b307d47 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleFilled.imageset/InterfaceEssentialLinkedinStyleFilled.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleFilled.imageset/InterfaceEssentialLinkedinStyleFilled.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleOutlined.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleOutlined.imageset/Contents.json index 77be0a9..675ae28 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleOutlined.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleOutlined.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialLinkedinStyleOutlined.pdf" + "filename" : "InterfaceEssentialLinkedinStyleOutlined.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleOutlined.imageset/InterfaceEssentialLinkedinStyleOutlined.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleOutlined.imageset/InterfaceEssentialLinkedinStyleOutlined.pdf index efe7372..b14dddf 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleOutlined.imageset/InterfaceEssentialLinkedinStyleOutlined.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialLinkedin/InterfaceEssentialLinkedinStyleOutlined.imageset/InterfaceEssentialLinkedinStyleOutlined.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/Contents.json index 2fa43f1..a274db6 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 } } \ No newline at end of file diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleFilled.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleFilled.imageset/Contents.json index f1b277e..977fa91 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleFilled.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleFilled.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialTwitterStyleFilled.pdf" + "filename" : "InterfaceEssentialTwitterStyleFilled.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleFilled.imageset/InterfaceEssentialTwitterStyleFilled.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleFilled.imageset/InterfaceEssentialTwitterStyleFilled.pdf index 767bf8d..7488b13 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleFilled.imageset/InterfaceEssentialTwitterStyleFilled.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleFilled.imageset/InterfaceEssentialTwitterStyleFilled.pdf differ diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleOutlined.imageset/Contents.json b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleOutlined.imageset/Contents.json index b852483..5e6f3ec 100644 --- a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleOutlined.imageset/Contents.json +++ b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleOutlined.imageset/Contents.json @@ -1,13 +1,13 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "InterfaceEssentialTwitterStyleOutlined.pdf" + "filename" : "InterfaceEssentialTwitterStyleOutlined.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "FigmaGen" + "author" : "FigmaGen", + "version" : 1 }, "properties" : { "preserves-vector-representation" : false diff --git a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleOutlined.imageset/InterfaceEssentialTwitterStyleOutlined.pdf b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleOutlined.imageset/InterfaceEssentialTwitterStyleOutlined.pdf index a6a977b..a73f317 100644 Binary files a/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleOutlined.imageset/InterfaceEssentialTwitterStyleOutlined.pdf and b/Demo/FigmaGenDemo/Resources/Images.xcassets/Generated/Service/InterfaceEssentialTwitter/InterfaceEssentialTwitterStyleOutlined.imageset/InterfaceEssentialTwitterStyleOutlined.pdf differ diff --git a/Sources/FigmaGen/Commands/TokensCommand.swift b/Sources/FigmaGen/Commands/TokensCommand.swift index d2ba276..0266c79 100644 --- a/Sources/FigmaGen/Commands/TokensCommand.swift +++ b/Sources/FigmaGen/Commands/TokensCommand.swift @@ -68,6 +68,20 @@ final class TokensCommand: AsyncExecutableCommand { """ ) + 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: """ @@ -236,6 +250,54 @@ final class TokensCommand: AsyncExecutableCommand { """ ) + 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. + """ + ) + // MARK: - Initializers init(generator: TokensGenerator) { @@ -265,6 +327,7 @@ extension TokensCommand { file: resolveFileConfiguration(), remoteRepoConfig: resolveRemoteRepoConfiguration(), accessToken: resolveAccessTokenConfiguration(), + themesConfiguration: resolveTokenThemesConfiguration(), templates: TokensTemplateConfiguration( colors: [ TemplateConfiguration( @@ -314,6 +377,20 @@ extension TokensCommand { templateOptions: resolveTemplateOptions(spacingTemplateOptions.value), destination: spacingDestination.value ) + ], + borders: [ + TemplateConfiguration( + template: bordersTemplate.value, + templateOptions: resolveTemplateOptions(bordersTemplateOptions.value), + destination: bordersDestination.value + ) + ], + gradients: [ + TemplateConfiguration( + template: gradientTemplate.value, + templateOptions: resolveTemplateOptions(gradientTemplateOptions.value), + destination: gradientDestination.value + ) ] ) ) @@ -375,4 +452,18 @@ extension TokensCommand { return templateOptions } + + private func resolveTokenThemesConfiguration() -> TokenThemesConfiguration? { + let themes = themes.value + let fallbackTheme = fallbackTheme.value + + guard let fallbackTheme, !themes.isEmpty else { + return nil + } + + return TokenThemesConfiguration( + themes: themes.map { Theme($0) }, + fallbackTheme: Theme(fallbackTheme) + ) + } } diff --git a/Sources/FigmaGen/Dependencies.swift b/Sources/FigmaGen/Dependencies.swift index 502aea2..05b0312 100644 --- a/Sources/FigmaGen/Dependencies.swift +++ b/Sources/FigmaGen/Dependencies.swift @@ -83,6 +83,10 @@ enum Dependencies { static let boxShadowTokensContextProvider: BoxShadowTokensContextProvider = DefaultBoxShadowTokensContextProvider() + static let gradientTokensContextProvider: ColorTokensContextProvider = DefaultGradientTokensContextProvider( + tokensResolver: tokensResolver + ) + // MARK: - static let templateContextCoder: TemplateContextCoder = DefaultTemplateContextCoder() @@ -105,7 +109,8 @@ enum Dependencies { StencilCollectionDropLastModificator(), StencilCollectionRemovingFirstModificator(), StencilHexToAlphaFilter(), - StencilFullHexModificator() + StencilFullHexModificator(), + StencilRecursiveTokenFindModicator() ] static let templateRenderer: TemplateRenderer = DefaultTemplateRenderer( @@ -170,6 +175,7 @@ enum Dependencies { static let themeTokensGenerator: ThemeTokensGenerator = DefaultThemeTokensGenerator( colorTokensContextProvider: colorTokensContextProvider, + gradientTokensContextProvider: gradientTokensContextProvider, boxShadowsContextProvider: boxShadowTokensContextProvider, templateRenderer: templateRenderer ) @@ -179,6 +185,16 @@ enum Dependencies { templateRenderer: templateRenderer ) + static let borderTokensGenerator: BorderTokensGenerator = DefaultBorderTokensGenerator( + tokensResolver: tokensResolver, + templateRenderer: templateRenderer + ) + + static let gradientTokensGenerator: GradientTokensGenerator = DefaultGradientTokensGenerator( + templateRenderer: templateRenderer, + gradientProvider: gradientTokensContextProvider + ) + static let tokensGenerator: TokensGenerator = DefaultTokensGenerator( tokensProvider: tokensProvider, tokensGenerationParametersResolver: tokensGenerationParametersResolver, @@ -188,7 +204,9 @@ enum Dependencies { typographyTokensGenerator: typographyTokensGenerator, boxShadowTokensGenerator: boxShadowTokensGenerator, themeTokensGenerator: themeTokensGenerator, - spacingTokensGenerator: spacingTokensGenerator + spacingTokensGenerator: spacingTokensGenerator, + bordersTokensGenerator: borderTokensGenerator, + gradientTokensGenerator: gradientTokensGenerator ) static let libraryGenerator: LibraryGenerator = DefaultLibraryGenerator( diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/BorderToken.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/BorderToken.swift new file mode 100644 index 0000000..bf16663 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/BorderToken.swift @@ -0,0 +1,8 @@ +import Foundation + +struct BorderToken { + + let path: [String] + let width: String + let style: String +} diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/BorderWidthToken.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/BorderWidthToken.swift new file mode 100644 index 0000000..a0df264 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/BorderWidthToken.swift @@ -0,0 +1,3 @@ +import Foundation + +typealias BorderWidthToken = ContextToken diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/BoxShadowToken.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/BoxShadowToken.swift index 99a35f9..cc2e156 100644 --- a/Sources/FigmaGen/Generators/Tokens/Contexts/BoxShadowToken.swift +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/BoxShadowToken.swift @@ -2,24 +2,14 @@ import Foundation struct BoxShadowToken { - // MARK: - Nested Types - - struct Theme { - - // MARK: - Instance Properties - - let color: String - let type: String - let x: String - let y: String - let blur: String - let spread: String - } - // MARK: - Instance Properties let path: [String] - let dayTheme: Theme - let nightTheme: Theme - let zpDayTheme: Theme + + let color: String + let type: String + let x: String + let y: String + let blur: String + let spread: String } diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/ColorToken.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/ColorToken.swift index 2a6e788..6538217 100644 --- a/Sources/FigmaGen/Generators/Tokens/Contexts/ColorToken.swift +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/ColorToken.swift @@ -1,22 +1,11 @@ import Foundation -struct ColorToken: Encodable { - - // MARK: - Nested Types - - struct Theme: Encodable { - - // MARK: - Instance Properties - - let value: String - let reference: String - } +struct ColorToken: TokenProtocol, Encodable { // MARK: - Instance Properties - let dayTheme: Theme - let nightTheme: Theme - let zpDayTheme: Theme let name: String let path: [String] + let value: String + let reference: String } diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/LinearGradientToken.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/LinearGradientToken.swift new file mode 100644 index 0000000..f517621 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/LinearGradientToken.swift @@ -0,0 +1,21 @@ +import Foundation + +struct LinearGradientToken: TokenProtocol, Encodable { + + struct ColorStop: Encodable { + let color: String + let percentage: CGFloat + } + + // Нужен, т.к CGPoint нельзя использовать корректно в stencil шаблоне + struct Point: Encodable { + let x: CGFloat + let y: CGFloat + } + + let path: [String] + let name: String + let stops: [ColorStop] + let startPoint: Point + let endPoint: Point +} diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/TokenProtocol.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/TokenProtocol.swift new file mode 100644 index 0000000..d9198f3 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/TokenProtocol.swift @@ -0,0 +1,12 @@ +import Foundation + +protocol TokenProtocol { + var name: String { get } + var path: [String] { get } +} + +extension TokenProtocol { + var name: String { + path.joined(separator: ".") + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Contexts/TokenThemeValue.swift b/Sources/FigmaGen/Generators/Tokens/Contexts/TokenThemeValue.swift new file mode 100644 index 0000000..45d6127 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Contexts/TokenThemeValue.swift @@ -0,0 +1,12 @@ +import Foundation + +struct TokenThemeValue { + + let themeName: String + let value: T + + init(theme: String, value: T) { + self.themeName = theme + self.value = value + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/DefaultTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/DefaultTokensGenerator.swift index 6f6f45c..9994435 100644 --- a/Sources/FigmaGen/Generators/Tokens/DefaultTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/DefaultTokensGenerator.swift @@ -15,6 +15,8 @@ final class DefaultTokensGenerator: TokensGenerator { let boxShadowTokensGenerator: BoxShadowTokensGenerator let themeTokensGenerator: ThemeTokensGenerator let spacingTokensGenerator: SpacingTokensGenerator + let bordersTokensGenerator: BorderTokensGenerator + let gradientTokensGenerator: GradientTokensGenerator // MARK: - Initializers @@ -27,7 +29,9 @@ final class DefaultTokensGenerator: TokensGenerator { typographyTokensGenerator: TypographyTokensGenerator, boxShadowTokensGenerator: BoxShadowTokensGenerator, themeTokensGenerator: ThemeTokensGenerator, - spacingTokensGenerator: SpacingTokensGenerator + spacingTokensGenerator: SpacingTokensGenerator, + bordersTokensGenerator: BorderTokensGenerator, + gradientTokensGenerator: GradientTokensGenerator ) { self.tokensProvider = tokensProvider self.tokensGenerationParametersResolver = tokensGenerationParametersResolver @@ -38,6 +42,8 @@ final class DefaultTokensGenerator: TokensGenerator { self.boxShadowTokensGenerator = boxShadowTokensGenerator self.themeTokensGenerator = themeTokensGenerator self.spacingTokensGenerator = spacingTokensGenerator + self.bordersTokensGenerator = bordersTokensGenerator + self.gradientTokensGenerator = gradientTokensGenerator } // MARK: - Instance Methods @@ -52,6 +58,8 @@ final class DefaultTokensGenerator: TokensGenerator { try generateBoxShadowTokens(parameters: parameters, tokenValues: tokenValues) try generateThemeTokens(parameters: parameters, tokenValues: tokenValues) try generateSpacingTokens(parameters: parameters, tokenValues: tokenValues) + try generateBorderTokens(parameters: parameters, tokenValues: tokenValues) + try generateGradientTokens(parameters: parameters, tokenValues: tokenValues) } private func fetchTokens(from parameters: TokensGenerationParameters) async throws -> TokenValues { @@ -67,69 +75,118 @@ final class DefaultTokensGenerator: TokensGenerator { private func generateSpacingTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { try generateTokens( spacingTokensGenerator, + tokensName: "spacings", renderParameters: parameters.tokens.spacingRenderParameters, - tokenValues: tokenValues + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme ) } private func generateThemeTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { try generateTokens( themeTokensGenerator, + tokensName: "theme", renderParameters: parameters.tokens.themeRenderParameters, - tokenValues: tokenValues + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme ) } private func generateBoxShadowTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { try generateTokens( boxShadowTokensGenerator, + tokensName: "box shadow", renderParameters: parameters.tokens.boxShadowRenderParameters, - tokenValues: tokenValues + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme ) } private func generateTypographyTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { try generateTokens( typographyTokensGenerator, + tokensName: "typogrphy", renderParameters: parameters.tokens.typographyRenderParameters, - tokenValues: tokenValues + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme ) } private func generateFontFamilyTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { try generateTokens( fontFamilyTokensGenerator, + tokensName: "font family", renderParameters: parameters.tokens.fontFamilyRenderParameters, - tokenValues: tokenValues + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme ) } private func generateBaseColorsTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { try generateTokens( baseColorTokensGenerator, + tokensName: "base colors", renderParameters: parameters.tokens.baseColorRenderParameters, - tokenValues: tokenValues + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme ) } private func generateColorsTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { try generateTokens( colorTokensGenerator, + tokensName: "colors", renderParameters: parameters.tokens.colorRenderParameters, - tokenValues: tokenValues + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme + ) + } + + private func generateBorderTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { + try generateTokens( + bordersTokensGenerator, + tokensName: "border", + renderParameters: parameters.tokens.bordersRenderParameters, + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme + ) + } + + private func generateGradientTokens(parameters: TokensGenerationParameters, tokenValues: TokenValues) throws { + try generateTokens( + gradientTokensGenerator, + tokensName: "gradients", + renderParameters: parameters.tokens.gradientsRenderParameters, + tokenValues: tokenValues, + themes: parameters.themes, + fallbackTheme: parameters.fallbackTheme ) } private func generateTokens( _ generator: BaseTokenGenerator, + tokensName: String, renderParameters: [RenderParameters]?, - tokenValues: TokenValues + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme ) throws { if let renderParametersList = renderParameters { for params in renderParametersList { + logger.info("📦 Generating \(tokensName) tokens...", highlighted: true) try generator.generate( renderParameters: params, - tokenValues: tokenValues + tokenValues: tokenValues, + themes: themes, + fallbackTheme: fallbackTheme ) } } diff --git a/Sources/FigmaGen/Generators/Tokens/GenerationParametersResolver/DefaultTokensGenerationParametersResolver.swift b/Sources/FigmaGen/Generators/Tokens/GenerationParametersResolver/DefaultTokensGenerationParametersResolver.swift index 5f4c646..68a5667 100644 --- a/Sources/FigmaGen/Generators/Tokens/GenerationParametersResolver/DefaultTokensGenerationParametersResolver.swift +++ b/Sources/FigmaGen/Generators/Tokens/GenerationParametersResolver/DefaultTokensGenerationParametersResolver.swift @@ -50,6 +50,9 @@ final class DefaultTokensGenerationParametersResolver: TokensGenerationParameter ) } + let themes = configuration.themesConfiguration?.themes ?? [.light, .dark] + let fallbackTheme = configuration.themesConfiguration?.fallbackTheme ?? .light + if file.isNil && remoteFile.isNil { throw GenerationParametersError.invalidFileConfiguration } @@ -89,9 +92,21 @@ final class DefaultTokensGenerationParametersResolver: TokensGenerationParameter defaultTemplateType: .native(name: "SpacingTokens") ) + let borderRenderParameters = renderParametersResolver.resolveRenderParameters( + templates: configuration.templates?.borders, + defaultTemplateType: .native(name: "BorderTokens") + ) + + let gradientRenderParameters = renderParametersResolver.resolveRenderParameters( + templates: configuration.templates?.gradients, + defaultTemplateType: .native(name: "GradientTokens") + ) + return TokensGenerationParameters( file: file, remoteFile: remoteFile, + themes: themes, + fallbackTheme: fallbackTheme, tokens: TokensGenerationParameters.TokensParameters( colorRenderParameters: colorRenderParameters, baseColorRenderParameters: baseColorRenderParameters, @@ -99,7 +114,9 @@ final class DefaultTokensGenerationParametersResolver: TokensGenerationParameter typographyRenderParameters: typographyRenderParameters, boxShadowRenderParameters: boxShadowRenderParameters, themeRenderParameters: themeRenderParameters, - spacingRenderParameters: spacingRenderParameters + spacingRenderParameters: spacingRenderParameters, + bordersRenderParameters: borderRenderParameters, + gradientsRenderParameters: gradientRenderParameters ) ) } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/BaseColor/DefaultBaseColorTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/BaseColor/DefaultBaseColorTokensGenerator.swift index 099fb13..2084589 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/BaseColor/DefaultBaseColorTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/BaseColor/DefaultBaseColorTokensGenerator.swift @@ -23,19 +23,31 @@ final class DefaultBaseColorTokensGenerator: BaseColorTokensGenerator { return BaseColorToken( path: token.name.components(separatedBy: "."), - value: try tokensResolver.resolveHexColorValue(value, tokenValues: tokenValues, theme: .undefined) + value: try tokensResolver.resolveHexColorValue( + value, + tokenValues: tokenValues, + theme: nil + ) ) } // MARK: - - func generate(renderParameters: RenderParameters, tokenValues: TokenValues) throws { + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { let colors = try tokenValues.colors.compactMap { try makeBaseColorToken(from: $0, tokenValues: tokenValues) } try templateRenderer.renderTemplate( renderParameters.template, to: renderParameters.destination, - context: ["colors": colors] + context: [ + "colors": colors, + "themes": themes + ] ) } } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/BaseTokenGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/BaseTokenGenerator.swift index 78792b3..01fbe5e 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/BaseTokenGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/BaseTokenGenerator.swift @@ -4,5 +4,10 @@ protocol BaseTokenGenerator { // MARK: - Instance Methods - func generate(renderParameters: RenderParameters, tokenValues: TokenValues) throws + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Borders/BorderTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Borders/BorderTokensGenerator.swift new file mode 100644 index 0000000..f142449 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Borders/BorderTokensGenerator.swift @@ -0,0 +1,3 @@ +import Foundation + +protocol BorderTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Borders/DefaultBorderTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Borders/DefaultBorderTokensGenerator.swift new file mode 100644 index 0000000..34b9a45 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Borders/DefaultBorderTokensGenerator.swift @@ -0,0 +1,97 @@ +import Foundation + +struct DefaultBorderTokensGenerator: BorderTokensGenerator { + + // 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 getBorderToken( + from token: TokenValue, + tokens: TokenValues + ) throws -> BorderToken? { + guard case .border(let value) = token.type else { + return nil + } + + return BorderToken( + path: token.name.components(separatedBy: "."), + width: try tokensResolver.resolveValue( + value.width, + tokenValues: tokens, + theme: nil + ), + style: value.style + ) + } + + private func getBorderWidth( + from token: TokenValue, + tokens: TokenValues + ) throws -> BorderWidthToken? { + guard case .borderWidth(let value) = token.type else { + return nil + } + + return BorderWidthToken( + path: token.name.components(separatedBy: "."), + value: try tokensResolver.resolveValue( + value, + tokenValues: tokens, + theme: nil + ) + ) + } + + private func extractBorderData( + from tokens: [TokenValue], + tokenValues: TokenValues + ) throws -> (borders: [BorderToken], borderWidth: [BorderWidthToken]) { + try tokens.reduce((borders: [BorderToken](), borderWidth: [BorderWidthToken]())) { partialResult, value in + var result = partialResult + + if let borderToken = try getBorderToken(from: value, tokens: tokenValues) { + result.borders.append(borderToken) + } + + if let borderWidth = try getBorderWidth(from: value, tokens: tokenValues) { + result.borderWidth.append(borderWidth) + } + + return result + } + } + + // MARK: - BorderTokensGenerator + + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { + let coreBorderData = try extractBorderData(from: tokenValues.core, tokenValues: tokenValues) + let semanticBorderData = try extractBorderData(from: tokenValues.semantic, tokenValues: tokenValues) + + try templateRenderer.renderTemplate( + renderParameters.template, + to: renderParameters.destination, + context: [ + "coreBorders": coreBorderData.borders, + "semanticBorders": semanticBorderData.borders, + "coreBorderWidth": coreBorderData.borderWidth, + "semanticBorderWidth": semanticBorderData.borderWidth + ] + ) + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/BoxShadow/DefaultBoxShadowTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/BoxShadow/DefaultBoxShadowTokensGenerator.swift index 14847a6..602cae0 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/BoxShadow/DefaultBoxShadowTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/BoxShadow/DefaultBoxShadowTokensGenerator.swift @@ -16,13 +16,29 @@ final class DefaultBoxShadowTokensGenerator: BoxShadowTokensGenerator { // MARK: - Instance Methods - func generate(renderParameters: RenderParameters, tokenValues: TokenValues) throws { - let boxShadows = try boxShadowTokensContextProvider.fetchBoxShadowTokensContext(from: tokenValues) + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { + let boxShadows = try boxShadowTokensContextProvider.fetchBoxShadowTokensContext( + from: tokenValues, + themes: themes, + fallbackTheme: fallbackTheme + ) + + let dictBoxShadows = Dictionary(uniqueKeysWithValues: boxShadows.map { ($0.themeName, $0.value) }) try templateRenderer.renderTemplate( renderParameters.template, to: renderParameters.destination, - context: ["boxShadows": boxShadows] + context: [ + "themedBoxShadows": boxShadows, + "dictThemedBoxShadows": dictBoxShadows, + "themes": themes, + "fallbackTheme": fallbackTheme.name + ] ) } } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Color/DefaultColorTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Color/DefaultColorTokensGenerator.swift index 88014fb..f9dac3d 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/Color/DefaultColorTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Color/DefaultColorTokensGenerator.swift @@ -19,13 +19,34 @@ final class DefaultColorTokensGenerator: ColorTokensGenerator { // MARK: - Instance Methods - func generate(renderParameters: RenderParameters, tokenValues: TokenValues) throws { - let context = try colorTokensContextProvider.fetchColorTokensContext(from: tokenValues) + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { + let colorsContext = try colorTokensContextProvider.extractTokenContext( + from: tokenValues, + themes: themes, + fallbackTheme: fallbackTheme + ) + + let dictColorsContext = Dictionary( + uniqueKeysWithValues: colorsContext + .map { + ($0.themeName, $0.value) + } + ) try templateRenderer.renderTemplate( renderParameters.template, to: renderParameters.destination, - context: ["colors": context] + context: [ + "themedColors": colorsContext, + "dictThemedColors": dictColorsContext, + "themes": themes, + "fallbackTheme": fallbackTheme.name + ] ) } } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/FontFamily/DefaultFontFamilyTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/FontFamily/DefaultFontFamilyTokensGenerator.swift index 6d4d997..a821550 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/FontFamily/DefaultFontFamilyTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/FontFamily/DefaultFontFamilyTokensGenerator.swift @@ -24,7 +24,11 @@ final class DefaultFontFamilyTokensGenerator: FontFamilyTokensGenerator { return FontFamilyToken( path: tokenValue.name.components(separatedBy: "."), - value: try tokensResolver.resolveValue(value, tokenValues: tokenValues, theme: .undefined) + value: try tokensResolver.resolveValue( + value, + tokenValues: tokenValues, + theme: nil + ) ) } } @@ -37,14 +41,23 @@ final class DefaultFontFamilyTokensGenerator: FontFamilyTokensGenerator { return FontWeightToken( path: tokenValue.name.components(separatedBy: "."), - value: try tokensResolver.resolveValue(value, tokenValues: tokenValues, theme: .undefined) + value: try tokensResolver.resolveValue( + value, + tokenValues: tokenValues, + theme: nil + ) ) } } // MARK: - - func generate(renderParameters: RenderParameters, tokenValues: TokenValues) throws { + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { let fontFamilyTokens = try makeFontFamilyTokens(tokenValues: tokenValues) let fontWeightTokens = try makeFontWightTokens(tokenValues: tokenValues) diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Gradient/DefaultGradientTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Gradient/DefaultGradientTokensGenerator.swift new file mode 100644 index 0000000..0940cff --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Gradient/DefaultGradientTokensGenerator.swift @@ -0,0 +1,50 @@ +import Foundation + +struct DefaultGradientTokensGenerator: GradientTokensGenerator { + + // MARK: - Instance properties + + private let templateRenderer: TemplateRenderer + private let provider: ColorTokensContextProvider + + init( + templateRenderer: TemplateRenderer, + gradientProvider: ColorTokensContextProvider + ) { + self.templateRenderer = templateRenderer + self.provider = gradientProvider + } + + // MARK: - GradientTokensGenerator + + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { + let gradientsContext = try provider.extractTokenContext( + from: tokenValues, + themes: themes, + fallbackTheme: fallbackTheme + ) + + let dictGradientsContext = Dictionary( + uniqueKeysWithValues: gradientsContext + .map { + ($0.themeName, $0.value) + } + ) + + try templateRenderer.renderTemplate( + renderParameters.template, + to: renderParameters.destination, + context: [ + "themedGradients": gradientsContext, + "dictThemedGradients": dictGradientsContext, + "themes": themes, + "fallbackTheme": fallbackTheme.name + ] + ) + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Gradient/GradientTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Gradient/GradientTokensGenerator.swift new file mode 100644 index 0000000..0cb5b79 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Gradient/GradientTokensGenerator.swift @@ -0,0 +1,3 @@ +import Foundation + +protocol GradientTokensGenerator: BaseTokenGenerator { } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Spacing/DefaultSpacingTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Spacing/DefaultSpacingTokensGenerator.swift index 13f4c2d..8c978f1 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/Spacing/DefaultSpacingTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Spacing/DefaultSpacingTokensGenerator.swift @@ -23,13 +23,18 @@ final class DefaultSpacingTokensGenerator: SpacingTokensGenerator { return SpacingToken( path: token.name.components(separatedBy: "."), - value: try tokensResolver.resolveValue(value, tokenValues: tokenValues, theme: .undefined) + value: try tokensResolver.resolveValue(value, tokenValues: tokenValues, theme: nil) ) } // MARK: - - func generate(renderParameters: RenderParameters, tokenValues: TokenValues) throws { + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { let coreSpacings = try tokenValues.core.compactMap { value in try makeSpacingToken(from: value, tokenValues: tokenValues) } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Theme/DefaultThemeTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Theme/DefaultThemeTokensGenerator.swift index 5795c5f..6ab74f4 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/Theme/DefaultThemeTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Theme/DefaultThemeTokensGenerator.swift @@ -5,6 +5,7 @@ final class DefaultThemeTokensGenerator: ThemeTokensGenerator { // MARK: - Instance Properties let colorTokensContextProvider: ColorTokensContextProvider + let gradientTokensContextProvider: ColorTokensContextProvider let boxShadowsContextProvider: BoxShadowTokensContextProvider let templateRenderer: TemplateRenderer @@ -12,26 +13,56 @@ final class DefaultThemeTokensGenerator: ThemeTokensGenerator { init( colorTokensContextProvider: ColorTokensContextProvider, + gradientTokensContextProvider: ColorTokensContextProvider, boxShadowsContextProvider: BoxShadowTokensContextProvider, templateRenderer: TemplateRenderer ) { self.colorTokensContextProvider = colorTokensContextProvider + self.gradientTokensContextProvider = gradientTokensContextProvider self.boxShadowsContextProvider = boxShadowsContextProvider self.templateRenderer = templateRenderer } // MARK: - Instance Methods - func generate(renderParameters: RenderParameters, tokenValues: TokenValues) throws { - let colorsContext = try colorTokensContextProvider.fetchColorTokensContext(from: tokenValues) - let boxShadowsContext = try boxShadowsContextProvider.fetchBoxShadowTokensContext(from: tokenValues) + func dictionaryValue(from tokens: [TokenThemeValue]) -> [String: T] { + Dictionary(uniqueKeysWithValues: tokens.map { ($0.themeName, $0.value) }) + } + + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { + let colorsContext = try colorTokensContextProvider.extractTokenContext( + from: tokenValues, + themes: themes, + fallbackTheme: fallbackTheme + ) + let gradientsContext = try gradientTokensContextProvider.extractTokenContext( + from: tokenValues, + themes: themes, + fallbackTheme: fallbackTheme + ) + let boxShadowsContext = try boxShadowsContextProvider.fetchBoxShadowTokensContext( + from: tokenValues, + themes: themes, + fallbackTheme: fallbackTheme + ) try templateRenderer.renderTemplate( renderParameters.template, to: renderParameters.destination, context: [ - "colors": colorsContext, - "boxShadows": boxShadowsContext + "themedColors": colorsContext, + "themedBoxShadows": boxShadowsContext, + "themedGradients": gradientsContext, + "dictThemedColors": dictionaryValue(from: colorsContext), + "dictThemedGradients": dictionaryValue(from: gradientsContext), + "dictThemedBoxShadows": dictionaryValue(from: boxShadowsContext), + "themes": themes, + "fallbackTheme": fallbackTheme.name ] ) } diff --git a/Sources/FigmaGen/Generators/Tokens/Generators/Typography/DefaultTypographyTokensGenerator.swift b/Sources/FigmaGen/Generators/Tokens/Generators/Typography/DefaultTypographyTokensGenerator.swift index ecd8a12..ea3d501 100644 --- a/Sources/FigmaGen/Generators/Tokens/Generators/Typography/DefaultTypographyTokensGenerator.swift +++ b/Sources/FigmaGen/Generators/Tokens/Generators/Typography/DefaultTypographyTokensGenerator.swift @@ -24,7 +24,7 @@ final class DefaultTypographyTokensGenerator: TypographyTokensGenerator { let lineHeightResolvedValue = try tokensResolver.resolveValue( lineHeightValue, tokenValues: tokenValues, - theme: .undefined + theme: nil ) guard lineHeightResolvedValue.hasSuffix("%") else { @@ -35,7 +35,7 @@ final class DefaultTypographyTokensGenerator: TypographyTokensGenerator { } let fontSize = Double( - try tokensResolver.resolveValue(value.fontSize, tokenValues: tokenValues, theme: .undefined) + try tokensResolver.resolveValue(value.fontSize, tokenValues: tokenValues, theme: nil) ) let lineHeight = Double(lineHeightResolvedValue.dropLast()).map { $0 / 100.0 } @@ -65,12 +65,12 @@ final class DefaultTypographyTokensGenerator: TypographyTokensGenerator { let letterSpacing = Double( try tokensResolver - .resolveValue(letterSpacingValue, tokenValues: tokenValues, theme: .undefined) + .resolveValue(letterSpacingValue, tokenValues: tokenValues, theme: nil) .removingFirst("%") ).map { $0 / 100.0 } let fontSize = Double( - try tokensResolver.resolveValue(value.fontSize, tokenValues: tokenValues, theme: .undefined) + try tokensResolver.resolveValue(value.fontSize, tokenValues: tokenValues, theme: nil) ) guard let fontSize else { @@ -92,7 +92,7 @@ final class DefaultTypographyTokensGenerator: TypographyTokensGenerator { private func makeContextToken(value: String, tokenValues: TokenValues) throws -> ContextToken { ContextToken( path: value.components(separatedBy: "."), - value: try tokensResolver.resolveValue(value, tokenValues: tokenValues, theme: .undefined) + value: try tokensResolver.resolveValue(value, tokenValues: tokenValues, theme: nil) ) } @@ -164,7 +164,12 @@ final class DefaultTypographyTokensGenerator: TypographyTokensGenerator { // MARK: - - func generate(renderParameters: RenderParameters, tokenValues: TokenValues) throws { + func generate( + renderParameters: RenderParameters, + tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws { let tokens = try makeTypographyTokens(tokenValues: tokenValues) try templateRenderer.renderTemplate( diff --git a/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/BoxShadowTokensContextProvider.swift b/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/BoxShadowTokensContextProvider.swift index a4a9597..eb56669 100644 --- a/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/BoxShadowTokensContextProvider.swift +++ b/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/BoxShadowTokensContextProvider.swift @@ -4,5 +4,9 @@ protocol BoxShadowTokensContextProvider { // MARK: - Instance Methods - func fetchBoxShadowTokensContext(from tokenValues: TokenValues) throws -> [BoxShadowToken] + func fetchBoxShadowTokensContext( + from tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws -> [TokenThemeValue<[BoxShadowToken]>] } diff --git a/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/BoxShadowTokensContextProviderError.swift b/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/BoxShadowTokensContextProviderError.swift index e38f8a6..780c938 100644 --- a/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/BoxShadowTokensContextProviderError.swift +++ b/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/BoxShadowTokensContextProviderError.swift @@ -8,8 +8,7 @@ struct BoxShadowTokensContextProviderError: Error, CustomStringConvertible { // MARK: - Enumeration Cases - case nightValueNotFound(tokenName: String) - case zpValueNotFound(tokenName: String) + case valueNotFound(tokenName: String, theme: String) } // MARK: - Instance Properties @@ -20,10 +19,8 @@ struct BoxShadowTokensContextProviderError: Error, CustomStringConvertible { var description: String { switch code { - case .nightValueNotFound(let tokenName): - return "Night value for token '\(tokenName)' not found" - case .zpValueNotFound(let tokenName): - return "ZpDay value for token '\(tokenName)' not found" + case let .valueNotFound(tokenName, theme): + return "\(theme) value for token '\(tokenName)' not found" } } } diff --git a/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/DefaultBoxShadowTokensContextProvider.swift b/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/DefaultBoxShadowTokensContextProvider.swift index 4f5b353..6565122 100644 --- a/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/DefaultBoxShadowTokensContextProvider.swift +++ b/Sources/FigmaGen/Generators/Tokens/Providers/BoxShadowTokensContext/DefaultBoxShadowTokensContextProvider.swift @@ -4,54 +4,75 @@ final class DefaultBoxShadowTokensContextProvider: BoxShadowTokensContextProvide // MARK: - Instance Methods - private func makeTheme(value: TokenBoxShadowValue) -> BoxShadowToken.Theme { - BoxShadowToken.Theme( - color: value.color, - type: value.type, - x: value.x, - y: value.y, - blur: value.blur, - spread: value.spread + private func resolveBoxShadowToken( + token: TokenValue, + values: TokenValues, + theme: Theme + ) throws -> BoxShadowToken? { + let tokens = values.tokens(for: theme) + + guard let themedToken = tokens.first(where: { $0.name == token.name }) else { + return nil + } + + guard case let .boxShadow(boxShadowValue) = themedToken.type else { + return nil + } + + return BoxShadowToken( + path: token.name.components(separatedBy: "."), + color: boxShadowValue.color, + type: boxShadowValue.type, + x: boxShadowValue.x, + y: boxShadowValue.y, + blur: boxShadowValue.blur, + spread: boxShadowValue.spread ) } private func makeBoxShadowToken( - from dayTokenValue: TokenValue, - tokenValues: TokenValues + from token: TokenValue, + tokenValues: TokenValues, + theme: Theme, + fallbackTheme: Theme ) throws -> BoxShadowToken? { - guard case let .boxShadow(dayValue) = dayTokenValue.type else { + guard case .boxShadow(_) = token.type else { return nil } - guard let nightTokenValue = tokenValues.hhNight.first(where: { $0.name == dayTokenValue.name }) else { - throw BoxShadowTokensContextProviderError(code: .nightValueNotFound(tokenName: dayTokenValue.name)) - } - - guard case let .boxShadow(nightValue) = nightTokenValue.type else { - throw BoxShadowTokensContextProviderError(code: .nightValueNotFound(tokenName: dayTokenValue.name)) - } + let fallbackToken = try resolveBoxShadowToken(token: token, values: tokenValues, theme: fallbackTheme) + let resolvedToken = try resolveBoxShadowToken(token: token, values: tokenValues, theme: theme) - guard let zpDayTokenValue = tokenValues.zpDay.first(where: { $0.name == dayTokenValue.name }) else { - throw BoxShadowTokensContextProviderError(code: .nightValueNotFound(tokenName: dayTokenValue.name)) + guard let fallbackToken else { + logger.warning("Fallback token not found for \(token.name)", isVerbose: true) + return nil } - guard case let .boxShadow(zpDayValue) = zpDayTokenValue.type else { - throw BoxShadowTokensContextProviderError(code: .zpValueNotFound(tokenName: dayTokenValue.name)) + if resolvedToken.isNil { + logger.warning( + "\(theme.name) value for token '\(token.name)' not found, using \(fallbackTheme.name)", + isVerbose: true + ) } - return BoxShadowToken( - path: dayTokenValue.name.components(separatedBy: "."), - dayTheme: makeTheme(value: dayValue), - nightTheme: makeTheme(value: nightValue), - zpDayTheme: makeTheme(value: zpDayValue) - ) + return resolvedToken ?? fallbackToken } // MARK: - - func fetchBoxShadowTokensContext(from tokenValues: TokenValues) throws -> [BoxShadowToken] { - try tokenValues.hhDay - .compactMap { try makeBoxShadowToken(from: $0, tokenValues: tokenValues) } - .sorted { $0.path.joined() < $1.path.joined() } + func fetchBoxShadowTokensContext( + from tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws -> [TokenThemeValue<[BoxShadowToken]>] { + return try themes.map { theme in + let shadows = try tokenValues.tokens(for: fallbackTheme) + .compactMap { + try makeBoxShadowToken(from: $0, tokenValues: tokenValues, theme: theme, fallbackTheme: fallbackTheme) + } + .sorted { $0.path.joined() < $1.path.joined() } + + return TokenThemeValue(theme: theme.name, value: shadows) + } } } diff --git a/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/ColorTokensContextProvider+Extensions.swift b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/ColorTokensContextProvider+Extensions.swift new file mode 100644 index 0000000..55de38d --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/ColorTokensContextProvider+Extensions.swift @@ -0,0 +1,42 @@ +import Foundation + +extension ColorTokensContextProvider { + + func structure( + tokens: [T], + atNamePath namePath: [String] = [], + contextName: String = "tokens" + ) -> [String: Any] { + var structuredTokens: [String: Any] = [:] + + if let name = namePath.last { + structuredTokens["name"] = name + } + + if !namePath.isEmpty { + structuredTokens["path"] = namePath + } + + let filteredTokens = tokens + .filter { $0.path.count == namePath.count + 1 } + .sorted { $0.name.lowercased() < $1.name.lowercased() } + + if !filteredTokens.isEmpty { + structuredTokens[contextName] = filteredTokens + } + + let childTokens = tokens.filter { $0.path.count > namePath.count + 1 } + + let children = Dictionary(grouping: childTokens) { $0.path[namePath.count] } + .sorted { $0.key < $1.key } + .map { name, tokens in + structure(tokens: tokens, atNamePath: namePath + [name], contextName: contextName) + } + + if !children.isEmpty { + structuredTokens["children"] = children + } + + return structuredTokens + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/ColorTokensContextProvider.swift b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/ColorTokensContextProvider.swift index cbdfbce..8f49706 100644 --- a/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/ColorTokensContextProvider.swift +++ b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/ColorTokensContextProvider.swift @@ -4,5 +4,9 @@ protocol ColorTokensContextProvider { // MARK: - Instance Methods - func fetchColorTokensContext(from tokenValues: TokenValues) throws -> [String: Any] + func extractTokenContext( + from tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws -> [TokenThemeValue<[String: Any]>] } diff --git a/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/Colors/DefaultColorTokensContextProvider.swift b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/Colors/DefaultColorTokensContextProvider.swift new file mode 100644 index 0000000..b8608b5 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/Colors/DefaultColorTokensContextProvider.swift @@ -0,0 +1,112 @@ +import Foundation + +final class DefaultColorTokensContextProvider: ColorTokensContextProvider { + + // MARK: - Instance Properties + + let tokensResolver: TokensResolver + + // MARK: - Initializers + + init(tokensResolver: TokensResolver) { + self.tokensResolver = tokensResolver + } + + // MARK: - Instance Methods + + private func fallbackWarning(warningPrefix: String, tokenName: String, fallbackTheme: String) { + logger.warning("\(warningPrefix) value for token '\(tokenName)' not found, using \(fallbackTheme)", isVerbose: true) + } + + private func resolveColorToken( + token: TokenValue, + theme: Theme, + tokenValues: TokenValues + ) throws -> ColorToken? { + let tokens = tokenValues.tokens(for: theme) + + guard let themeToken = tokens.first(where: { $0.name == token.name }) else { + return nil + } + + guard case .color(let themeValue) = themeToken.type else { + return nil + } + + // Resolve hex color value + let themeHexColorValue = try tokensResolver.resolveHexColorValue( + themeValue, + tokenValues: tokenValues, + theme: theme + ) + + // Resolve reference + let themeReference = try tokensResolver.resolveBaseReference(themeValue, tokenValues: tokens) + + let path = token.name.components(separatedBy: ".") + + return ColorToken( + name: token.name, + path: path, + value: themeHexColorValue, + reference: themeReference + ) + } + + func makeColorToken( + using token: TokenValue, + values: TokenValues, + theme: Theme, + fallbackTheme: Theme + ) throws -> ColorToken? { + guard case .color(let dayValue) = token.type else { + return nil + } + + let path = token.name.components(separatedBy: ".") + + guard path.first != "gradient" && !dayValue.contains("gradient") else { + return nil + } + + let fallbackToken = try resolveColorToken(token: token, theme: fallbackTheme, tokenValues: values) + let resolvedToken = try resolveColorToken(token: token, theme: theme, tokenValues: values) + + guard let fallbackToken else { + logger.warning("Fallback token not found for \(token.name)", isVerbose: true) + return nil + } + + if resolvedToken.isNil { + fallbackWarning(warningPrefix: theme.name, tokenName: token.name, fallbackTheme: fallbackTheme.name) + } + + return resolvedToken ?? fallbackToken + } + + // MARK: - + + func extractTokenContext( + from tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws -> [TokenThemeValue<[String: Any]>] { + return try themes.map { theme in + let colors = try tokenValues + .tokens(for: fallbackTheme) + .compactMap { token in + try makeColorToken( + using: token, + values: tokenValues, + theme: theme, + fallbackTheme: fallbackTheme + ) + } + + return TokenThemeValue( + theme: theme.name, + value: structure(tokens: colors, contextName: "colors") + ) + } + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/DefaultColorTokensContextProvider.swift b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/DefaultColorTokensContextProvider.swift deleted file mode 100644 index 8973278..0000000 --- a/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/DefaultColorTokensContextProvider.swift +++ /dev/null @@ -1,162 +0,0 @@ -import Foundation - -final class DefaultColorTokensContextProvider: ColorTokensContextProvider { - - // MARK: - Instance Properties - - let tokensResolver: TokensResolver - - // MARK: - Initializers - - init(tokensResolver: TokensResolver) { - self.tokensResolver = tokensResolver - } - - // MARK: - Instance Methods - - private func fallbackWarning(warningPrefix: String, tokenName: String) { - logger.warning("\(warningPrefix) value for token '\(tokenName)' not found, using day value.") - } - - private func resolveColorToken( - tokenName: String, - fallbackColorToken: ColorToken.Theme, - tokenValues: TokenValues, - theme: Theme - ) throws -> ColorToken.Theme { - // Resolve theme data - let themeData: (tokenValues: [TokenValue], warningPrefix: String) - switch theme { - case .night: - themeData = (tokenValues.hhNight, "Night") - - case .zpDay: - themeData = (tokenValues.zpDay, "ZpDay") - - case .day, .undefined: - themeData = ([], "") - } - - // Resolve token and value - guard let themeToken = themeData.tokenValues.first(where: { $0.name == tokenName }) else { - fallbackWarning(warningPrefix: themeData.warningPrefix, tokenName: tokenName) - return fallbackColorToken - } - - guard case .color(let themeValue) = themeToken.type else { - fallbackWarning(warningPrefix: themeData.warningPrefix, tokenName: tokenName) - return fallbackColorToken - } - - // Resolve hex color value - let themeHexColorValue = try tokensResolver.resolveHexColorValue( - themeValue, - tokenValues: tokenValues, - theme: theme - ) - - // Resolve reference - let themeReference = try tokensResolver.resolveBaseReference(themeValue, tokenValues: themeData.tokenValues) - - return ColorToken.Theme(value: themeHexColorValue, reference: themeReference) - } - - private func makeColorToken( - dayValue: String, - tokenName: String, - tokenValues: TokenValues, - path: [String] - ) throws -> ColorToken { - let dayColorToken = ColorToken.Theme( - value: try tokensResolver.resolveHexColorValue( - dayValue, - tokenValues: tokenValues, - theme: .day - ), - reference: try tokensResolver.resolveBaseReference( - dayValue, - tokenValues: tokenValues.hhDay - ) - ) - - let nightColorToken = try resolveColorToken( - tokenName: tokenName, - fallbackColorToken: dayColorToken, - tokenValues: tokenValues, - theme: .night - ) - let zpDayColorToken = try resolveColorToken( - tokenName: tokenName, - fallbackColorToken: dayColorToken, - tokenValues: tokenValues, - theme: .zpDay - ) - - return ColorToken( - dayTheme: dayColorToken, - nightTheme: nightColorToken, - zpDayTheme: zpDayColorToken, - name: tokenName, - path: path - ) - } - - private func structure(tokenColors: [ColorToken], atNamePath namePath: [String] = []) -> [String: Any] { - var structuredColors: [String: Any] = [:] - - if let name = namePath.last { - structuredColors["name"] = name - } - - if !namePath.isEmpty { - structuredColors["path"] = namePath - } - - let colors = tokenColors - .filter { $0.path.count == namePath.count + 1 } - .sorted { $0.name.lowercased() < $1.name.lowercased() } - - if !colors.isEmpty { - structuredColors["colors"] = colors - } - - let childTokenColors = tokenColors.filter { $0.path.count > namePath.count + 1 } - - let children = Dictionary(grouping: childTokenColors) { $0.path[namePath.count] } - .sorted { $0.key < $1.key } - .map { name, colors in - structure(tokenColors: colors, atNamePath: namePath + [name]) - } - - if !children.isEmpty { - structuredColors["children"] = children - } - - return structuredColors - } - - // MARK: - - - func fetchColorTokensContext(from tokenValues: TokenValues) throws -> [String: Any] { - let colors: [ColorToken] = try tokenValues.hhDay.compactMap { (token: TokenValue) in - guard case .color(let dayValue) = token.type else { - return nil - } - - let path = token.name.components(separatedBy: ".") - - guard path[0] != "gradient" && !dayValue.contains("gradient") else { - return nil - } - - return try makeColorToken( - dayValue: dayValue, - tokenName: token.name, - tokenValues: tokenValues, - path: path - ) - } - - return structure(tokenColors: colors) - } -} diff --git a/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/Gradient/DefaultGradientTokensContextProvider.swift b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/Gradient/DefaultGradientTokensContextProvider.swift new file mode 100644 index 0000000..dedc523 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/Gradient/DefaultGradientTokensContextProvider.swift @@ -0,0 +1,159 @@ +import Foundation + +struct DefaultGradientTokensContextProvider: ColorTokensContextProvider { + + let tokensResolver: TokensResolver + + init(tokensResolver: TokensResolver) { + self.tokensResolver = tokensResolver + } + + // MARK: - Private methods + + private func resolvePoints(angle: CGFloat) -> (start: CGPoint, end: CGPoint)? { + let start = 3.0 * .pi / 2 + let u = start + angle + + let ucos = cos(u) + let usin = sin(u) + + let xedge = ucos > 0 ? 1.0 : 0 + let yedge = usin > 0 ? 1.0 : 0 + + let tx = ucos == 0 ? nil : (xedge - 0.5) / ucos + let ty = usin == 0 ? nil : (yedge - 0.5) / usin + + let t = [tx, ty] + .compactMap { $0 } + .filter { $0 > 0 } + .min() + + guard let t else { + // Невозможно вычислить пересечение с границей + return nil + } + + let endPoint = CGPoint( + x: round((0.5 + t * ucos) * 1000) / 1000, + y: round((0.5 + t * usin) * 1000) / 1000 + ) + let startPoint = CGPoint( + x: round((0.5 - t * ucos) * 1000) / 1000, + y: round((0.5 - t * usin) * 1000) / 1000 + ) + + return (start: startPoint, end: endPoint) + } + + private func resolveGradientToken( + for token: TokenValue, + theme: Theme, + values: TokenValues + ) throws -> LinearGradientToken? { + let tokens = values.tokens(for: theme) + + guard let themeToken = tokens.first(where: { $0.name == token.name }) else { + return nil + } + + guard case .color(let themeValue) = themeToken.type else { + return nil + } + + let gradient = try tokensResolver.resolveLinearGradientValue( + themeValue, + tokenValues: values, + theme: theme + ) + + let path = token.name.components(separatedBy: ".") + + guard let points = resolvePoints(angle: gradient.radians) else { + throw DefaultGradientTokensContextProviderError.invalidAngle(token.name) + } + + return LinearGradientToken( + path: path, + name: token.name, + stops: gradient.colorStopList.compactMap { stop in + let percentage = stop.percentage.replacingOccurrences(of: "%", with: "") + guard let percentage = Double(percentage) else { + return nil + } + + return .init( + color: stop.color.hexString, + percentage: percentage / 100 + ) + }, + startPoint: LinearGradientToken.Point( + x: points.start.x, + y: points.start.y + ), + endPoint: LinearGradientToken.Point( + x: points.end.x, + y: points.end.y + ) + ) + } + + private func makeGradientToken( + from token: TokenValue, + tokenValues: TokenValues, + theme: Theme, + fallbackTheme: Theme + ) throws -> LinearGradientToken? { + let path = token.name.components(separatedBy: ".") + + guard + case .color(let fallbackTokenValue) = token.type, + fallbackTokenValue.contains("gradient"), + path.first != "color" + else { + return nil + } + + let fallbackToken = try resolveGradientToken(for: token, theme: fallbackTheme, values: tokenValues) + let resolvedToken = try resolveGradientToken(for: token, theme: theme, values: tokenValues) + + guard let fallbackToken else { + logger.warning("Fallback token not found for \(token.name)", isVerbose: true) + return nil + } + + if resolvedToken.isNil { + logger.warning( + "\(theme.name) value for token '\(token.name)' not found, using \(fallbackTheme.name)", + isVerbose: true + ) + } + + return resolvedToken ?? fallbackToken + } + + // MARK: - GradientTokensContextProvider + + func extractTokenContext( + from tokenValues: TokenValues, + themes: [Theme], + fallbackTheme: Theme + ) throws -> [TokenThemeValue<[String: Any]>] { + return try themes.map { theme in + let gradients = try tokenValues + .tokens(for: fallbackTheme) + .compactMap { token in + try makeGradientToken( + from: token, + tokenValues: tokenValues, + theme: theme, + fallbackTheme: fallbackTheme + ) + } + + return TokenThemeValue( + theme: theme.name, + value: structure(tokens: gradients, contextName: "gradients") + ) + } + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/Gradient/DefaultGradientTokensContextProviderError.swift b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/Gradient/DefaultGradientTokensContextProviderError.swift new file mode 100644 index 0000000..1ae5169 --- /dev/null +++ b/Sources/FigmaGen/Generators/Tokens/Providers/ColorTokensContext/Gradient/DefaultGradientTokensContextProviderError.swift @@ -0,0 +1,15 @@ +import Foundation + +enum DefaultGradientTokensContextProviderError: Error, CustomStringConvertible { + case invalidAngle(String) + case fallbackTokenNotFound(String) + + var description: String { + switch self { + case .invalidAngle(let tokenName): + "Invalid agnle in gradient token: \(tokenName)" + case .fallbackTokenNotFound(let tokenName): + "Fallback token not found for \(tokenName)" + } + } +} diff --git a/Sources/FigmaGen/Generators/Tokens/Resolver/DefaultTokensResolver.swift b/Sources/FigmaGen/Generators/Tokens/Resolver/DefaultTokensResolver.swift index c4bd3f2..9595a54 100644 --- a/Sources/FigmaGen/Generators/Tokens/Resolver/DefaultTokensResolver.swift +++ b/Sources/FigmaGen/Generators/Tokens/Resolver/DefaultTokensResolver.swift @@ -60,7 +60,7 @@ final class DefaultTokensResolver: TokensResolver { } } - private func resolveColorValue(_ value: String, tokenValues: TokenValues, theme: Theme) throws -> Color { + private func resolveColorValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> Color { if value.hasPrefix("rgba") { return try resolveRGBAColorValue(value, tokenValues: tokenValues, theme: theme) } @@ -68,9 +68,48 @@ final class DefaultTokensResolver: TokensResolver { return try makeColor(hex: value, alpha: 1.0) } + private func resolveRGBAWithHex( + hex: String, + alphaPercent: String, + value: String + ) throws -> Color { + let alpha = alphaPercent.replacingOccurrences(of: "%", with: "") + guard let alpha = Double(alpha) else { + throw TokensGeneratorError(code: .invalidAlphaComponent(alpha: alphaPercent + value)) + } + + return try makeColor(hex: hex, alpha: alpha / 100.0) + } + + private func resolveRGBA( + red: String, + green: String, + blue: String, + alpha: String, + rgbaValue: String + ) throws -> Color { + guard + let red = Double(red), + let green = Double(green), + let blue = Double(blue), + let alpha = Double(alpha) + else { + throw TokensGeneratorError(code: .invalidRGBAColorValue(rgba: rgbaValue)) + } + + let normalizationFactor: CGFloat = 255.0 + + return Color( + red: CGFloat(red) / normalizationFactor, + green: CGFloat(green) / normalizationFactor, + blue: CGFloat(blue) / normalizationFactor, + alpha: alpha + ) + } + // MARK: - TokensResolver - func resolveValue(_ value: String, tokenValues: TokenValues, theme: Theme) throws -> String { + func resolveValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> String { let themeTokens = tokenValues.getThemeTokenValues(theme: theme) let resolvedValue = try value.replacingOccurrences(matchingPattern: #"\{.*?\}"#) { referenceName in @@ -122,26 +161,36 @@ final class DefaultTokensResolver: TokensResolver { } } - func resolveRGBAColorValue(_ value: String, tokenValues: TokenValues, theme: Theme) throws -> Color { + func resolveRGBAColorValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> Color { let components = try resolveValue(value, tokenValues: tokenValues, theme: theme) .slice(from: "(", to: ")", includingBounds: false)? .components(separatedBy: ", ") - guard let components, components.count == 2 else { + guard let components else { throw TokensGeneratorError(code: .invalidRGBAColorValue(rgba: value)) } - let hex = components[0] - let alphaPercent = components[1] - - guard let alpha = Double(alphaPercent.dropLast()) else { - throw TokensGeneratorError(code: .invalidAlphaComponent(alpha: alphaPercent)) + switch components.count { + case .rgbaWithHex: + return try resolveRGBAWithHex( + hex: components[0], + alphaPercent: components[1], + value: value + ) + case .rgba: + return try resolveRGBA( + red: components[0], + green: components[1], + blue: components[2], + alpha: components[3], + rgbaValue: value + ) + default: + throw TokensGeneratorError(code: .invalidRGBAColorValue(rgba: value)) } - - return try makeColor(hex: hex, alpha: alpha / 100.0) } - func resolveHexColorValue(_ value: String, tokenValues: TokenValues, theme: Theme) throws -> String { + func resolveHexColorValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> String { let resolvedValue = try resolveValue(value, tokenValues: tokenValues, theme: theme) if resolvedValue.hasPrefix("#") { @@ -150,7 +199,7 @@ final class DefaultTokensResolver: TokensResolver { return try resolveColorValue(resolvedValue, tokenValues: tokenValues, theme: theme).hexString } - func resolveLinearGradientValue(_ value: String, tokenValues: TokenValues, theme: Theme) throws -> LinearGradient { + func resolveLinearGradientValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> LinearGradient { let value = try resolveValue(value, tokenValues: tokenValues, theme: theme) guard let startFunctionIndex = value.firstIndex(of: "("), let endFunctionIndex = value.lastIndex(of: ")") else { @@ -193,4 +242,6 @@ extension Int { fileprivate static let rgb = 3 fileprivate static let rrggbb = 6 + fileprivate static let rgbaWithHex = 2 + fileprivate static let rgba = 4 } diff --git a/Sources/FigmaGen/Generators/Tokens/Resolver/TokensResolver.swift b/Sources/FigmaGen/Generators/Tokens/Resolver/TokensResolver.swift index 81f7eb0..94ed17b 100644 --- a/Sources/FigmaGen/Generators/Tokens/Resolver/TokensResolver.swift +++ b/Sources/FigmaGen/Generators/Tokens/Resolver/TokensResolver.swift @@ -15,7 +15,7 @@ protocol TokensResolver { /// - tokenValues: All token values /// - theme: Theme /// - Returns: Resolved value. - func resolveValue(_ value: String, tokenValues: TokenValues, theme: Theme) throws -> String + func resolveValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> String /// Resolving `reference` from `tokenValues`. /// @@ -34,6 +34,7 @@ protocol TokensResolver { /// /// Supported formats: /// - `rgba(hex_color, alpha-value-percentage)` + /// – `rgba(red, green, blue, alpha-value-percentage)` /// - TO DO: Support more formats /// /// [Color tokens examples and should be supported later](https://docs.tokens.studio/available-tokens/color-tokens#solid-colors) @@ -49,7 +50,7 @@ protocol TokensResolver { /// - tokenValues: All token values /// - theme: Theme /// - Returns: ``Color`` object with values resolved from `rgba()` - func resolveRGBAColorValue(_ value: String, tokenValues: TokenValues, theme: Theme) throws -> Color + func resolveRGBAColorValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> Color /// Resolving references and mathematical expressions in `value` using ``resolveValue(_:tokenValues:)`` /// and convert `rgba()` to hex value @@ -68,7 +69,7 @@ protocol TokensResolver { /// - tokenValues: All token values /// - theme: Theme /// - Returns: Hex value of the color - func resolveHexColorValue(_ value: String, tokenValues: TokenValues, theme: Theme) throws -> String + func resolveHexColorValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> String /// Resolving references and mathematical expressions in `value` using ``resolveValue(_:tokenValues:)`` /// and convert `linear-gradient()` to ``LinearGradient`` object @@ -90,5 +91,5 @@ protocol TokensResolver { /// - tokenValues: All token values /// - theme: Theme /// - Returns: ``LinearGradient`` object with values resolved from `linear-gradient()` - func resolveLinearGradientValue(_ value: String, tokenValues: TokenValues, theme: Theme) throws -> LinearGradient + func resolveLinearGradientValue(_ value: String, tokenValues: TokenValues, theme: Theme?) throws -> LinearGradient } diff --git a/Sources/FigmaGen/Logger/Logger.swift b/Sources/FigmaGen/Logger/Logger.swift index c00cac1..0f5a3b9 100644 --- a/Sources/FigmaGen/Logger/Logger.swift +++ b/Sources/FigmaGen/Logger/Logger.swift @@ -43,9 +43,15 @@ struct Logger { print(message, terminator: terminator, isVerbose: isVerbose) } - func info(_ items: Any..., separator: String = " ", terminator: String = "\n", isVerbose: Bool = false) { + func info( + _ items: Any..., + separator: String = " ", + terminator: String = "\n", + highlighted: Bool = false, + isVerbose: Bool = false + ) { let message = items.joinedDescription(separator: separator) - print(message, terminator: terminator, isVerbose: isVerbose) + print(highlighted ? message.blue : message, terminator: terminator, isVerbose: isVerbose) } func warning(_ items: Any..., separator: String = " ", terminator: String = "\n", isVerbose: Bool = false) { diff --git a/Sources/FigmaGen/Models/Configuration/Tokens/TokenThemesConfiguration.swift b/Sources/FigmaGen/Models/Configuration/Tokens/TokenThemesConfiguration.swift new file mode 100644 index 0000000..e721d50 --- /dev/null +++ b/Sources/FigmaGen/Models/Configuration/Tokens/TokenThemesConfiguration.swift @@ -0,0 +1,11 @@ +import Foundation + +struct TokenThemesConfiguration: Codable { + let themes: [Theme] + let fallbackTheme: Theme + + init(themes: [Theme], fallbackTheme: Theme) { + self.themes = themes + self.fallbackTheme = fallbackTheme + } +} diff --git a/Sources/FigmaGen/Models/Configuration/Tokens/TokensConfiguration.swift b/Sources/FigmaGen/Models/Configuration/Tokens/TokensConfiguration.swift index d8c64a6..f2f1f09 100644 --- a/Sources/FigmaGen/Models/Configuration/Tokens/TokensConfiguration.swift +++ b/Sources/FigmaGen/Models/Configuration/Tokens/TokensConfiguration.swift @@ -14,6 +14,7 @@ struct TokensConfiguration: Decodable { let file: FileConfiguration? let remoteRepoConfig: RemoteRepoConfiguration? let accessToken: AccessTokenConfiguration? + let themesConfiguration: TokenThemesConfiguration? let templates: TokensTemplateConfiguration? // MARK: - Initializers @@ -28,17 +29,20 @@ struct TokensConfiguration: Decodable { self.remoteRepoConfig = try container.decodeIfPresent(forKey: .remoteRepoConfig) self.templates = try container.decodeIfPresent(forKey: .templates) + self.themesConfiguration = try TokenThemesConfiguration(from: decoder) } init( file: FileConfiguration?, remoteRepoConfig: RemoteRepoConfiguration?, accessToken: AccessTokenConfiguration?, + themesConfiguration: TokenThemesConfiguration?, templates: TokensTemplateConfiguration? ) { self.file = file self.remoteRepoConfig = remoteRepoConfig self.accessToken = accessToken + self.themesConfiguration = themesConfiguration self.templates = templates } @@ -53,6 +57,7 @@ struct TokensConfiguration: Decodable { file: file ?? base.file, remoteRepoConfig: remoteRepoConfig, accessToken: accessToken ?? base.accessToken, + themesConfiguration: themesConfiguration, templates: templates ) } diff --git a/Sources/FigmaGen/Models/Configuration/Tokens/TokensTemplateConfiguration.swift b/Sources/FigmaGen/Models/Configuration/Tokens/TokensTemplateConfiguration.swift index a267946..a3c9ec9 100644 --- a/Sources/FigmaGen/Models/Configuration/Tokens/TokensTemplateConfiguration.swift +++ b/Sources/FigmaGen/Models/Configuration/Tokens/TokensTemplateConfiguration.swift @@ -12,6 +12,8 @@ struct TokensTemplateConfiguration { let boxShadows: [TemplateConfiguration]? let theme: [TemplateConfiguration]? let spacing: [TemplateConfiguration]? + let borders: [TemplateConfiguration]? + let gradients: [TemplateConfiguration]? } // MARK: - Decodable @@ -28,6 +30,8 @@ extension TokensTemplateConfiguration: Decodable { case boxShadows case theme case spacing + case borders + case gradients } // MARK: - Initializers @@ -48,5 +52,7 @@ extension TokensTemplateConfiguration: Decodable { boxShadows = try container.decodeIfPresent(TemplateConfigurationWrapper.self, forKey: .boxShadows)?.templates theme = try container.decodeIfPresent(TemplateConfigurationWrapper.self, forKey: .theme)?.templates 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 } } diff --git a/Sources/FigmaGen/Models/LinearGradient.swift b/Sources/FigmaGen/Models/LinearGradient.swift index 92a0120..c97b708 100644 --- a/Sources/FigmaGen/Models/LinearGradient.swift +++ b/Sources/FigmaGen/Models/LinearGradient.swift @@ -17,3 +17,18 @@ struct LinearGradient: Codable, Hashable { let angle: String let colorStopList: [LinearColorStop] } + +extension LinearGradient { + + var radians: Double { + if angle.hasSuffix("deg"), let deg = Double(angle.replacingOccurrences(of: "deg", with: "")) { + return deg * .pi / 180 + } + + if angle.hasSuffix("rad"), let rad = Double(angle.replacingOccurrences(of: "rad", with: "")) { + return rad + } + + return Double(angle) ?? .zero + } +} diff --git a/Sources/FigmaGen/Models/Parameters/TokensGenerationParameters.swift b/Sources/FigmaGen/Models/Parameters/TokensGenerationParameters.swift index 224cef9..248a679 100644 --- a/Sources/FigmaGen/Models/Parameters/TokensGenerationParameters.swift +++ b/Sources/FigmaGen/Models/Parameters/TokensGenerationParameters.swift @@ -15,11 +15,15 @@ struct TokensGenerationParameters { let boxShadowRenderParameters: [RenderParameters]? let themeRenderParameters: [RenderParameters]? let spacingRenderParameters: [RenderParameters]? + let bordersRenderParameters: [RenderParameters]? + let gradientsRenderParameters: [RenderParameters]? } // MARK: - Instance Properties let file: FileParameters? let remoteFile: RemoteFileParameters? + let themes: [Theme] + let fallbackTheme: Theme let tokens: TokensParameters } diff --git a/Sources/FigmaGen/Models/Token/Theme.swift b/Sources/FigmaGen/Models/Token/Theme.swift index e8ec3e3..f45f279 100644 --- a/Sources/FigmaGen/Models/Token/Theme.swift +++ b/Sources/FigmaGen/Models/Token/Theme.swift @@ -1,8 +1,31 @@ import Foundation -enum Theme: Codable { - case day - case night - case zpDay - case undefined +struct Theme: Codable, Hashable { + + enum CodingKeys: CodingKey { + case name + } + + let name: String + + init(_ name: String) { + self.name = name + } + + init(from decoder: any Decoder) throws { + let container = try decoder.singleValueContainer() + + if let name = try? container.decode(String.self) { + self.name = name + } else { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.name = try container.decode(String.self, forKey: .name) + } + } +} + +extension Theme { + + static let light = Theme("light") + static let dark = Theme("dark") } diff --git a/Sources/FigmaGen/Models/Token/TokenValues.swift b/Sources/FigmaGen/Models/Token/TokenValues.swift index b2db6ed..27b74ca 100644 --- a/Sources/FigmaGen/Models/Token/TokenValues.swift +++ b/Sources/FigmaGen/Models/Token/TokenValues.swift @@ -8,38 +8,14 @@ struct TokenValues: Hashable { let semantic: [TokenValue] let colors: [TokenValue] let typography: [TokenValue] - let hhDay: [TokenValue] - let hhNight: [TokenValue] - let zpDay: [TokenValue] - - // MARK: - Instance Properties - - /// Возвращает набор токенов для определенной темы. - /// Для undefined возвращается полный набор токенов. Нужен для Spacer, Font и других независимых от темы параметров. - func getThemeTokenValues(theme: Theme) -> [TokenValue] { - switch theme { - case .day: - return [hhDay, core, semantic, colors, typography].flatMap { $0 } - - case .night: - return [hhNight, core, semantic, colors, typography].flatMap { $0 } - - case .zpDay: - return [zpDay, core, semantic, colors, typography].flatMap { $0 } - - case .undefined: - return [core, semantic, colors, typography, hhDay, hhNight, zpDay].flatMap { $0 } - } - } + let themedTokens: [Theme: [TokenValue]] } // MARK: - Codable extension TokenValues: Codable { - // MARK: - Nested Types - - private enum CodingKeys: String, CodingKey { + private enum CodingKeys: String, CodingKey, CaseIterable { // MARK: - Enumeration Cases @@ -47,8 +23,45 @@ extension TokenValues: Codable { case semantic case colors case typography - case hhDay = "hh-day" - case hhNight = "hh-night" - case zpDay = "zp-day" + } + + init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let staticKeys = CodingKeys.allCases.map { $0.rawValue } + let themedContainer = try decoder.container(keyedBy: AnyKey.self) + + self.core = try container.decode(forKey: .core) + self.semantic = try container.decode(forKey: .semantic) + self.colors = try container.decode(forKey: .colors) + self.typography = try container.decode(forKey: .typography) + self.themedTokens = Dictionary( + uniqueKeysWithValues: try themedContainer + .allKeys + .filter { key in + !staticKeys.contains(key.stringValue) + } + .map { key in + let tokens = try themedContainer.decode([TokenValue].self, forKey: key) + let theme = Theme(key.stringValue) + return (theme, tokens) + } + ) + } +} + +extension TokenValues { + + func tokens(for theme: Theme) -> [TokenValue] { + themedTokens[theme] ?? [] + } + + /// Возвращает набор токенов для определенной темы. + /// Для undefined возвращается полный набор токенов. Нужен для Spacer, Font и других независимых от темы параметров. + func getThemeTokenValues(theme: Theme?) -> [TokenValue] { + let allThemedTokens = themedTokens.values.flatMap { $0 } + let themeTokens = theme.map { themedTokens[$0] ?? [] } ?? allThemedTokens + let tokens = [core, semantic, colors, typography, themeTokens] + + return tokens.flatMap { $0 } } } diff --git a/Sources/FigmaGen/Render/DefaultTemplateRenderer.swift b/Sources/FigmaGen/Render/DefaultTemplateRenderer.swift index 27b4ed4..bcac67c 100644 --- a/Sources/FigmaGen/Render/DefaultTemplateRenderer.swift +++ b/Sources/FigmaGen/Render/DefaultTemplateRenderer.swift @@ -62,7 +62,7 @@ final class DefaultTemplateRenderer: TemplateRenderer { try filePath.write(output) case .console: - print(output) + logger.info(output) } } diff --git a/Sources/FigmaGen/Render/StencilExtensions/Tokens/StencilRecursiveTokenFindModicator.swift b/Sources/FigmaGen/Render/StencilExtensions/Tokens/StencilRecursiveTokenFindModicator.swift new file mode 100644 index 0000000..d98044b --- /dev/null +++ b/Sources/FigmaGen/Render/StencilExtensions/Tokens/StencilRecursiveTokenFindModicator.swift @@ -0,0 +1,72 @@ +import Foundation + +struct StencilRecursiveTokenFindModicator: StencilModificator { + + // MARK: - Instance Properties + + let name = "findTokenInThemes" + + // MARK: - Instance Methods + + func modify(input: Any, withArguments arguments: [Any?]) throws -> Any { + guard arguments.count > 1 else { + throw StencilModificatorError(code: .invalidArguments(arguments), filter: name) + } + + guard + let themesDict = input as? [String: [String: Any]], + let pathString = arguments[0] as? String, + let key = arguments[1] as? String + else { + return input + } + + let pathComponents = pathString.split(separator: ".").map(String.init) + var result: [String: Any] = [:] + + for (themeName, structuredDict) in themesDict { + if let token = findToken( + in: structuredDict, + name: pathString, + path: pathComponents, + key: key + ) { + result[themeName] = token + } + } + + return result + } + + private func findToken( + in dict: [String: Any], + name: String, + path: [String], + key: String + ) -> Any? { + if let tokens = dict[key] as? [TokenProtocol], let found = tokens.first(where: { $0.name == name }) { + return found + } + + guard !path.isEmpty else { + return nil + } + + guard let children = dict["children"] as? [[String: Any]] else { + return nil + } + + for child in children { + if let childName = child["name"] as? String, childName == path[0] { + return findToken( + in: child, + name: name, + path: Array(path.dropFirst()), + key: key + ) + } + } + + return nil + } +} diff --git a/Sources/FigmaGen/Resolvers/RenderParameters/DefaultRenderParametersResolver.swift b/Sources/FigmaGen/Resolvers/RenderParameters/DefaultRenderParametersResolver.swift index f3ac399..49d1506 100644 --- a/Sources/FigmaGen/Resolvers/RenderParameters/DefaultRenderParametersResolver.swift +++ b/Sources/FigmaGen/Resolvers/RenderParameters/DefaultRenderParametersResolver.swift @@ -31,16 +31,8 @@ final class DefaultRenderParametersResolver: RenderParametersResolver { defaultTemplateType: RenderTemplateType, defaultDestination: RenderDestination ) -> [RenderParameters] { - let defaultRenderParameters = RenderParameters( - template: RenderTemplate( - type: defaultTemplateType, - options: [:] - ), - destination: defaultDestination - ) - guard let templates else { - return [defaultRenderParameters] + return [] } return templates.map { template in diff --git a/Templates/BorderTokens.stencil b/Templates/BorderTokens.stencil new file mode 100644 index 0000000..40c2203 --- /dev/null +++ b/Templates/BorderTokens.stencil @@ -0,0 +1,49 @@ +{% include "FileHeader.stencil" %} +{% if semanticBorders or coreBorders -%} +{% set accessModifier %}{% if options.publicAccess %}public{% else %}internal{% endif %}{% endset %} +{% set tokenTypeName %}{{ options.tokenTypeName|default:"BorderTokens" }}{% endset %} +{% macro propertyName name %}{{ name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords }}{% endmacro %} +{% macro borderProperty border -%} + /// {{ border.path|join:"." }} + /// + /// Width: {{ border.width }} + /// Style: {{ border.style|default:"solid" }} + {{ accessModifier }} var {% call propertyName border.path|join:"_" %}: BorderToken { + BorderToken( + width: {{ border.width }}, + style: "{{ border.style|default:"solid" }}" + ) + } +{%- endmacro %} + +#if canImport(UIKit) +import UIKit +#else +import AppKit +#endif + +public struct BorderToken: Hashable { + public let width: CGFloat + public let style: String + + public init(width: CGFloat, style: String) { + self.width = width + self.style = style + } +} + +{{ accessModifier }} struct {{ tokenTypeName }} { + + // MARK: - Instance Properties + {% for border in semanticBorders %} + + {% call borderProperty border %} + {% endfor %} + {% for border in coreBorders %} + + {% call borderProperty border %} + {% endfor %} +} +{%- else -%} +// No border tokens found +{%- endif %} diff --git a/Templates/BoxShadowTokens.stencil b/Templates/BoxShadowTokens.stencil index 42e2364..4f02db5 100644 --- a/Templates/BoxShadowTokens.stencil +++ b/Templates/BoxShadowTokens.stencil @@ -1,5 +1,5 @@ {% include "FileHeader.stencil" %} -{% if boxShadows %} +{% if dictThemedBoxShadows[fallbackTheme] %} {% set accessModifier %}{% if options.publicAccess %}public{% else %}internal{% endif %}{% endset %} {% set tokenTypeName %}{{ options.tokenTypeName|default:"BoxShadowTokens" }}{% endset %} {% set shadowTypeName %}{{ options.shadowTypeName|default:"Shadow" }}{% endset %} @@ -14,13 +14,18 @@ import AppKit #endif {{ accessModifier }} struct {{ tokenTypeName }} { - {% for boxShadow in boxShadows %} - - /// {{ boxShadow.path|dropFirst|join:" " }} - /// - /// Offset: day – x {{ boxShadow.dayTheme.x }}; y {{ boxShadow.nightTheme.y }} / night – x {{ boxShadow.nightTheme.x }}; y {{ boxShadow.nightTheme.y }} - /// Radius: day – {{ boxShadow.dayTheme.blur }} / night – {{ boxShadow.nightTheme.blur }} - /// Color: day – {{ boxShadow.dayTheme.color }} / night – {{ boxShadow.nightTheme.color }} + {% outer: for boxShadow in dictThemedBoxShadows[fallbackTheme] %} + + {% for themedValue in themedBoxShadows %} + {% for shadowToken in themedValue.value %} + {% if forloop.outer.counter == forloop.counter %} + /// - {{ themedValue.themeName }}: + /// Offset: x {{ shadowToken.x }}; y {{ shadowToken.y }} + /// Radius: {{ shadowToken.blur }} + /// Color: {{ shadowToken.color }} + {% endif %} + {% endfor %} + {% endfor %} {{ accessModifier }} let {% call propertyName boxShadow.path.last %}: {{ shadowTypeName }} {% endfor %} } diff --git a/Templates/ColorTokens.stencil b/Templates/ColorTokens.stencil index eb9359d..f947781 100644 --- a/Templates/ColorTokens.stencil +++ b/Templates/ColorTokens.stencil @@ -1,5 +1,5 @@ {% include "FileHeader.stencil" %} -{% if colors %} +{% if dictThemedColors[fallbackTheme] %} {% set colorTypeName %}{{ options.colorTypeName|default:"UIColor" }}{% endset %} {% set accessModifier %}{% if options.publicAccess %}public{% else %}internal{% endif %}{% endset %} {% set tokenTypeName %}{{ options.tokenTypeName|default:"ColorTokens" }}{% endset %} @@ -9,8 +9,9 @@ {% for color in item.colors %} /// {{ color.name }} /// - /// Day: {{ color.dayTheme.value }} - /// Night: {{ color.nightTheme.value }} + {% for theme, token in dictThemedColors|findTokenInThemes:color.name,"colors" %} + /// {{ theme }}: {{ token.value }} + {% endfor %} {{ accessModifier }} let {% call propertyName color.path.last %}: {{ colorTypeName }} {% endfor %} {% for child in item.children %} @@ -31,7 +32,7 @@ import AppKit #endif {{ accessModifier }} struct {{ tokenTypeName }} { - {% call recursiveBlock colors %} + {% call recursiveBlock dictThemedColors[fallbackTheme] %} } {% else %} // No color tokens found diff --git a/Templates/GradientTokens.stencil b/Templates/GradientTokens.stencil new file mode 100644 index 0000000..7f25690 --- /dev/null +++ b/Templates/GradientTokens.stencil @@ -0,0 +1,41 @@ +{% include "FileHeader.stencil" %} +{% if dictThemedGradients[fallbackTheme] %} +{% set gradientTypeName %}{{ options.colorTypeName|default:"LinearGradient" }}{% endset %} +{% macro propertyName name %}{{ name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords }}{% endmacro %} +{% macro typeName name %}{{ name|swiftIdentifier:"pretty"|upperFirstLetter|escapeReservedKeywords }}{% endmacro %} +{% macro recursiveBlock item %} + {% for gradient in item.gradients %} + + /// {{ gradient.name }} + /// + {% for theme, token in dictThemedGradients|findTokenInThemes:gradient.name,"gradients" %} + /// {{ theme }}: + {% for stop in token.stops %} + /// - {{ stop.color }} {{ stop.percentage }} + {% endfor %} + {% endfor %} + public let {% call propertyName gradient.path.last %}: {{ gradientTypeName }} + {% endfor %} + {% for child in item.children %} + {% if child.name == "gradient" %} + {% call recursiveBlock child %} + {% else %} + public struct {% call typeName child.name %} { + {% filter indent:4 %} + {% call recursiveBlock child %} + {% endfilter %} + } + + public let {% call propertyName child.name %}: {% call typeName child.name %} + {% endif %} + {% endfor %} +{% endmacro %} + +import SwiftUI + +public struct Gradients { + {% call recursiveBlock dictThemedGradients[fallbackTheme] %} +} +{% else %} +// No color tokens found +{% endif %} diff --git a/Templates/Theme.stencil b/Templates/Theme.stencil index 5362449..4311be6 100644 --- a/Templates/Theme.stencil +++ b/Templates/Theme.stencil @@ -11,7 +11,7 @@ {% macro hexColor color %}{{ color|fullHex|uppercase|replace:"#","0x" }}{% endmacro %} {% macro argumentsBlock item theme parentTypeName %} {% for color in item.colors %} -{% call propertyName color.path.last %}: {{ colorTypeName }}(hex: {% call hexColor color[theme].value %}){% if not forloop.last %},{% endif %} +{% call propertyName color.path.last %}: {{ colorTypeName }}(hex: {% call hexColor color.value %}){% if not forloop.last %},{% endif %} {% endfor %} {% for child in item.children %} {% set childTypeName %}{% if parentTypeName %}{{ parentTypeName }}.{% endif %}{% call typeName child.name %}{% endset %} @@ -36,9 +36,9 @@ colors: {{ colorTokensTypeName }}( shadows: {{ boxShadowTokensTypeName }}( {% for boxShadow in boxShadows %} {% call propertyName boxShadow.path.last %}: {{ shadowTypeName }}( - offset: CGSize(width: {{ boxShadow[theme].x }}, height: {{ boxShadow[theme].y }}), - radius: {{ boxShadow[theme].blur }}, - color: {{ colorTypeName }}(hex: {% call hexColor boxShadow[theme].color %}), + offset: CGSize(width: {{ boxShadow.x }}, height: {{ boxShadow.y }}), + radius: {{ boxShadow.blur }}, + color: {{ colorTypeName }}(hex: {% call hexColor boxShadow.color %}), opacity: 1.0 ){% if not forloop.last %},{% endif %} {% endfor %} @@ -54,27 +54,27 @@ import AppKit {{ accessModifier }} struct {{ themeTypeName }} { - {% if colors %} + {% if dictThemedColors[fallbackTheme] %} {{ accessModifier }} let colors: {{ colorTokensTypeName }} {% endif %} - {% if boxShadows %} + {% if dictThemedBoxShadows[fallbackTheme] %} {{ accessModifier }} let shadows: {{ boxShadowTokensTypeName }} {% endif %} {{ accessModifier }} let typographies: {{ typographyTokensTypeName }} init( - {% if colors %} + {% if dictThemedColors[fallbackTheme] %} colors: {{ colorTokensTypeName }}, {% endif %} - {% if boxShadows %} + {% if dictThemedBoxShadows[fallbackTheme] %} shadows: {{ boxShadowTokensTypeName }}, {% endif %} typographies: {{ typographyTokensTypeName }} = {{ typographyTokensTypeName }}() ) { - {% if colors %} + {% if dictThemedColors[fallbackTheme] %} self.colors = colors {% endif %} - {% if boxShadows %} + {% if dictThemedBoxShadows[fallbackTheme] %} self.shadows = shadows {% endif %} self.typographies = typographies @@ -83,22 +83,18 @@ import AppKit extension {{ themeTypeName }} { - {{ accessModifier }} static let defaultLight = Self( + {% for theme in themes %} + {% set themePropertyName %}{{ theme.name||swiftIdentifier:"pretty"|lowerFirstWord }}{% endset %} + {{ accessModifier }} static let {{ themePropertyName }} = Self( {% filter indent:8 %} - {% call colorsArgumentsBlock colors "dayTheme" %} - {% call shadowsArgumentsBlock boxShadows "dayTheme" %} - {% endfilter %} - ) - - {{ accessModifier }} static let defaultDark = Self( - {% filter indent:8 %} - {% call colorsArgumentsBlock colors "nightTheme" %} - {% call shadowsArgumentsBlock boxShadows "nightTheme" %} + {% call colorsArgumentsBlock dictThemedColors[theme.name] theme.name %} + {% call shadowsArgumentsBlock dictThemedBoxShadows[theme.name] theme.name %} {% endfilter %} ) + {% endfor %} } -{% if colors or boxShadows %} +{% if dictThemedColors or dictThemedBoxShadows %} private extension {{ colorTypeName }} { convenience init(hex: UInt32) { diff --git a/Tests/FigmaGenTests/TokensResolverTests.swift b/Tests/FigmaGenTests/TokensResolverTests.swift index 8957fbd..84f1b58 100644 --- a/Tests/FigmaGenTests/TokensResolverTests.swift +++ b/Tests/FigmaGenTests/TokensResolverTests.swift @@ -20,15 +20,13 @@ final class TokensResolverTests: XCTestCase { semantic: [], colors: [], typography: [], - hhDay: [], - hhNight: [], - zpDay: [] + themedTokens: [:] ) let value = "{core.space.1-x} + {core.space.1-x} / 2" let expectedValue = "6" - let actualValue = try tokensResolver.resolveValue(value, tokenValues: tokenValues, theme: .day) + let actualValue = try tokensResolver.resolveValue(value, tokenValues: tokenValues, theme: .light) XCTAssertEqual(actualValue, expectedValue) } @@ -40,11 +38,11 @@ final class TokensResolverTests: XCTestCase { let pixelValue = "0px" let colorValue = "#ffffff" - let actualNumberValue = try tokensResolver.resolveValue(numberValue, tokenValues: .empty, theme: .day) - let actualPercentValue = try tokensResolver.resolveValue(percentValue, tokenValues: .empty, theme: .day) - let actualTextValue = try tokensResolver.resolveValue(textValue, tokenValues: .empty, theme: .day) - let actualPixelValue = try tokensResolver.resolveValue(pixelValue, tokenValues: .empty, theme: .day) - let actualColorValue = try tokensResolver.resolveValue(colorValue, tokenValues: .empty, theme: .day) + let actualNumberValue = try tokensResolver.resolveValue(numberValue, tokenValues: .empty, theme: .light) + let actualPercentValue = try tokensResolver.resolveValue(percentValue, tokenValues: .empty, theme: .light) + let actualTextValue = try tokensResolver.resolveValue(textValue, tokenValues: .empty, theme: .light) + let actualPixelValue = try tokensResolver.resolveValue(pixelValue, tokenValues: .empty, theme: .light) + let actualColorValue = try tokensResolver.resolveValue(colorValue, tokenValues: .empty, theme: .light) XCTAssertEqual(actualNumberValue, numberValue) XCTAssertEqual(actualPercentValue, percentValue) @@ -65,15 +63,13 @@ final class TokensResolverTests: XCTestCase { TokenValue(type: .core(value: "#ffffff"), name: "color.base.white") ], typography: [], - hhDay: [], - hhNight: [], - zpDay: [] + themedTokens: [:] ) let value = "rgba({color.base.white}, {semantic.opacity.disabled})" let expectedColor = Color(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.48) - let actualColor = try tokensResolver.resolveRGBAColorValue(value, tokenValues: tokenValues, theme: .day) + let actualColor = try tokensResolver.resolveRGBAColorValue(value, tokenValues: tokenValues, theme: .light) XCTAssertEqual(actualColor, expectedColor) } @@ -82,7 +78,7 @@ final class TokensResolverTests: XCTestCase { let value = "rgba(#FFFFFF, 48%)" let expectedColor = Color(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.48) - let actualColor = try tokensResolver.resolveRGBAColorValue(value, tokenValues: .empty, theme: .day) + let actualColor = try tokensResolver.resolveRGBAColorValue(value, tokenValues: .empty, theme: .light) XCTAssertEqual(actualColor, expectedColor) } @@ -99,9 +95,7 @@ final class TokensResolverTests: XCTestCase { TokenValue(type: .color(value: "#d64030"), name: "color.base.red.50") ], typography: [], - hhDay: [], - hhNight: [], - zpDay: [] + themedTokens: [:] ) let firstColor = "rgba({color.base.red.50}, {semantic.opacity.transparent})" @@ -135,7 +129,7 @@ final class TokensResolverTests: XCTestCase { let actualLinearGradient = try tokensResolver.resolveLinearGradientValue( value, tokenValues: tokenValues, - theme: .day + theme: .light ) XCTAssertEqual(actualLinearGradient, expectedLinearGradient) @@ -171,7 +165,7 @@ final class TokensResolverTests: XCTestCase { let actualLinearGradient = try tokensResolver.resolveLinearGradientValue( value, tokenValues: .empty, - theme: .day + theme: .light ) XCTAssertEqual(actualLinearGradient, expectedLinearGradient) @@ -190,9 +184,7 @@ final class TokensResolverTests: XCTestCase { TokenValue(type: .color(value: "#111"), name: "color.base.gray.5") ], typography: [], - hhDay: [], - hhNight: [], - zpDay: [] + themedTokens: [:] ) let value1 = "rgba({color.base.white}, {semantic.opacity.disabled})" @@ -201,8 +193,8 @@ final class TokensResolverTests: XCTestCase { let value2 = "rgba( {color.base.gray.5} , {semantic.opacity.disabled})" let expectedHexColor2 = "#1111117A" - let actualHexColor1 = try tokensResolver.resolveHexColorValue(value1, tokenValues: tokenValues, theme: .day) - let actualHexColor2 = try tokensResolver.resolveHexColorValue(value2, tokenValues: tokenValues, theme: .day) + let actualHexColor1 = try tokensResolver.resolveHexColorValue(value1, tokenValues: tokenValues, theme: .light) + let actualHexColor2 = try tokensResolver.resolveHexColorValue(value2, tokenValues: tokenValues, theme: .light) XCTAssertEqual(actualHexColor1, expectedHexColor1) XCTAssertEqual(actualHexColor2, expectedHexColor2) @@ -212,7 +204,7 @@ final class TokensResolverTests: XCTestCase { let value = "rgba(#FFFFFF, 48%)" let expectedHexColor = "#FFFFFF7A" - let actualHexColor = try tokensResolver.resolveHexColorValue(value, tokenValues: .empty, theme: .day) + let actualHexColor = try tokensResolver.resolveHexColorValue(value, tokenValues: .empty, theme: .light) XCTAssertEqual(actualHexColor, expectedHexColor) } @@ -225,18 +217,18 @@ final class TokensResolverTests: XCTestCase { TokenValue(type: .color(value: "#000000"), name: "color.base.black") ], typography: [], - hhDay: [], - hhNight: [ - TokenValue(type: .color(value: "{color.base.black}"), name: "color.background.primary"), - TokenValue(type: .color(value: "{color.background.primary}"), name: "color.background.primary.nested") - ], - zpDay: [] + themedTokens: [ + .dark: [ + TokenValue(type: .color(value: "{color.base.black}"), name: "color.background.primary"), + TokenValue(type: .color(value: "{color.background.primary}"), name: "color.background.primary.nested") + ] + ] ) let value = "{color.background.primary.nested}" let expectedBaseReference = "{color.base.black}" - let actualBaseReference = try tokensResolver.resolveBaseReference(value, tokenValues: tokenValues.hhNight) + let actualBaseReference = try tokensResolver.resolveBaseReference(value, tokenValues: tokenValues.tokens(for: .dark)) XCTAssertEqual(actualBaseReference, expectedBaseReference) } @@ -253,18 +245,18 @@ final class TokensResolverTests: XCTestCase { TokenValue(type: .color(value: "#000000"), name: "color.base.black") ], typography: [], - hhDay: [], - hhNight: [ - TokenValue(type: .color(value: "{color.base.black}"), name: "color.background.primary"), - TokenValue(type: .color(value: "{color.background.primary}"), name: "color.background.primary.nested") - ], - zpDay: [] + themedTokens: [ + .dark: [ + TokenValue(type: .color(value: "{color.base.black}"), name: "color.background.primary"), + TokenValue(type: .color(value: "{color.background.primary}"), name: "color.background.primary.nested") + ] + ] ) let value = "rgba( {color.background.primary.nested}, {semantic.opacity.disabled})" let expectedBaseReference = "rgba( {color.base.black}, {semantic.opacity.disabled})" - let actualBaseReference = try tokensResolver.resolveBaseReference(value, tokenValues: tokenValues.hhNight) + let actualBaseReference = try tokensResolver.resolveBaseReference(value, tokenValues: tokenValues.tokens(for: .dark)) XCTAssertEqual(actualBaseReference, expectedBaseReference) } @@ -279,9 +271,7 @@ extension TokenValues { semantic: [], colors: [], typography: [], - hhDay: [], - hhNight: [], - zpDay: [] + themedTokens: [:] ) } #endif