amzn / style-dictionary

A build system for creating cross-platform styles.
https://styledictionary.com
Apache License 2.0
3.88k stars 544 forks source link

[Question] Can I generate extensions in iOS Swift? #719

Open antoniogamiz opened 2 years ago

antoniogamiz commented 2 years ago

Hi, I have been using Style Dictionary and it's great! Thanks a lot for the hard work.

I have a question. I have the following configuration file to generate styles sheets on iOS Swift from design tokens hosted on Invision App:

{
  "source": [
    "tokens/**/*.json"
  ],
  "platforms": {
    "ios-swift-separate-enums": {
      "transformGroup": "ios-swift-separate",
      "buildPath": "build/ios-swift/",
      "files": [
        {
          "destination": "StyleDictionaryColor.swift",
          "format": "ios-swift/enum.swift",
          "className": "StyleDictionaryColor",
          "filter": {
            "attributes": {
              "category": "color"
            }
          }
        },
        {
          "destination": "StyleDictionarySize.swift",
          "format": "ios-swift/enum.swift",
          "className": "StyleDictionarySize",
          "type": "float",
          "filter": {
            "attributes": {
              "category": "size"
            }
          }
        }
      ]
    },
  }
}

The result is something like this:

import UIKit

public enum StyleDictionaryColor {
    public static let basicGrayDark = UIColor(red: 0.345, green: 0.345, blue: 0.345, alpha: 1)
    public static let basicGrayDark60 = UIColor(red: 0.000, green: 0.000, blue: 0.000, alpha: 0.6)
}

But, I would like to generate something like this:

extension Color {
    static let oldPrimaryColor = Color(UIColor.systemIndigo)
    static let darkGreyColor = Color("darkGrey")
}

Is that currently possible? Or would I need to create my own transformer? Thanks in advance (if this is not the place for this type of question, please redirect to the correct place if you which is, thanks! :))

dbanksdesign commented 2 years ago

Hi @antoniogamiz!

Unfortunately right now there is no built-in format to generate a Swift extension for iOS. But I think it would be a good idea considering it is pretty common practice and makes using those colors easier. It would be a pretty straight-forward format to add, follow the ios-swift/enum format: https://github.com/amzn/style-dictionary/blob/main/lib/common/templates/ios-swift/enum.swift.template. You could write a custom format, and if you had time I think it would be a good contribution to the built-in formats. If you would like any help with that let me know.

antoniogamiz commented 2 years ago

Okay, I will try to implement it in the near future! Thanks for the fast response :smiley: .

antoniogamiz commented 2 years ago

Hi again @dbanksdesign, I have already created a PR with what I think is the correct way to implement this (I'm still learning all of this). I have found the following problem: when using colors, the default transformer (the one that uses UIColor is used), so If I want to generate an extension of Color:

extension Color {
    static let oldPrimaryColor = Color(UIColor.systemIndigo)
    static let darkGreyColor = Color("darkGrey")
    static let greyColor = Color("grey")
    static let lightGreyColor = Color("lightGrey")
    static let greyBackgroundColor = Color("greyBackground")
    static let blueBackgroundColor = Color("blueBackground")
    static let darkRedColor = Color("darkRed")   
}

I would need to specify another transformer. As I have not found any transformer for Color on Swift, I suppose I would have to implement it too, right?

dbanksdesign commented 2 years ago

That is correct, we will need a SwiftUI Color transformer

antoniogamizbadger commented 2 years ago

PR made for the SwiftUI Color transformer, let me now if I need change something.

tfmart commented 2 years ago

In case anyone wants an example on how to create a Swift extension file, on your iOS swift file object in config.json, use ios-swift/any.swift as the format and add a options object, in which you can provide a objectType with a extension value. Here's an example:

{
  "source": [
    "tokens/**/*.json"
  ],
  "platforms": {
    "ios-swift": {
      "transforms": [
        "..."
      ],
      "buildPath": "files/ios-swift/",
      "files": [
        {
          "destination": "MyCustomSpacing.swift",
          "format": "ios-swift/any.swift",
          "className": "CGFloat",
          "filter": "foundation/spacing",
          "options": {
            "objectType": "extension"
          }
        }
      ]
    }
  }
}
colinhumber commented 2 years ago

@tfmart I'm doing the same thing and it's working great. Shouldn't need any custom formats or templates for this.