twostraws / Ignite

A static site generator for Swift developers.
MIT License
1.55k stars 73 forks source link

Feature Request: Custom font support #70

Open Terabyte1385 opened 1 month ago

Terabyte1385 commented 1 month ago

I tried using a custom font on my website, and then I encountered issues. I'd be awesome to have something like var robotsConfiguration = Robots() but for fonts, and then a Font() object.

I was able to get it working by CSS, adding a .style to the Theme() and then another .style on the text I want to change the font, but it's not an ideal solution, clearly a workaround.

twostraws commented 1 month ago

Great idea! One helpful thing you could do would be to give us an example of what kind of API you'd like to see here? Just fantasyland stuff – if the API were ideal for you, what would it look like? I'm not saying we can make it happen, but it would give us a good starting point 🙂

Terabyte1385 commented 1 month ago

Hey, thanks for getting back!

I'm imagining an implementation similar to Robots() but I would make a few changes. I'm thinking of something like this:

import Foundation
import Ignite

struct CustomFont {
    var familyName: String
    var weight: Font.Weight? = .regular
    var typeface: String? = "sans-serif"
    var location: String? // required for custom locations of the fonts
}

enum CustomFontElement {
    case .spaceMonoBold = CustomFont(familyName: "Space Mono", weight: .bold, location: "https://fonts.googleapis.com/css2?family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap")
    // ...
}

struct MyCustomFonts: CustomFontsConfiguration {
    var fonts: [CustomFontElement]
}

In Site.swift, we add: var customFontsConfiguration = MyCustomFonts()

And finally, when we want to use one of our custom fonts, we do:

Text("The quick brown fox jumps over the lazy dog")
    .font(MyCustomFonts.spaceMonoBold)

... or ...

Text("The quick brown fox jumps over the lazy dog")
    .font(CustomFont(familyName: "SF Pro Display", weight: .regular, location: "/resources/sf_pro_display_regular.ttf"))

By doing this, we not only centralise all the custom fonts, but we can also detect when a font is needed or not and decide whether to load it.

I imagine this is tough. There is a lot to take into consideration: convenience of the developer, where the fonts are stored, what if the fonts are renamed, what happens when a font with a specific style or weight is overwritten by .fontWeight, and many others to take into consideration. Now that I found a workaround it's not mission-critical but it would be convenient.

P.S. Please don't judge the code too hard, it's actually one of my first contributions to such a project! I don't have much experience but I'm happy to give a hand!

twostraws commented 1 month ago

Zero judgement! Thank you for taking the time to spec things out nicely! I don't know where the final implementation will end up or how long it will take, but at least now we have a starting point 🙌