Make your stylesheets classes strong-typed within powerful Swift enums 💥
Add the package to your SPM dependencies.
.package(name: "StrongTypedCSSPublishPlugin", url: "https://github.com/c0dedbear/StrongTypedCSSPublishPlugin", from: "0.1.0"),
- Put your stylesheets files (.css, .scss, .sass) at the "Resources/css" folder (it's default path, but you can changed it).
- Create your own enum(or enums) with String rawValue cases duplicating stylesheets class names and conform it to "StrongTypeCSS" and "CaseIterable" protocols.
import StrongTypedCSSPublishPlugin
...
enum CSS: String, CaseIterable {
case container
case myPost = "my-post"
case marginLeft = "margin-left"
}
extension CSS: StrongTypeCSS {
var classDescription: String { "CSS" }
}
enum CSSAnimation: String, CaseIterable {
case fadeIn
case fadeOut
}
extension CSSAnimation: StrongTypeCSS {
var classDescription: String { "CSSAnimation" }
}
- Install the plugin using publishing pipeline like this (better if you place it at a very beginning of pipeline):
import StrongTypedCSSPublishPlugin
...
try YourSite().publish(
withTheme: .foundation,
plugins: [
.checkStrongTypeCSS(of: CSS.allCases + CSSAnimation.allCases),
...
]
)
Note that if your css files not placed in the "Resources/css", you must change 'cssFilesFolderPath' parameter of 'checkStrongTypeCSS' method.
- Done! Use it in the .class Node context like this:
// Note that you don't need import plugin in places where you build your HTML
func makePageHTML(for page: Page, context: PublishingContext<Site>) throws -> HTML {
HTML(
.lang(context.site.language),
.head(for: page, on: context.site),
.body(
.header(for: context, selectedSection: nil),
.div(
// Strong typed CSS class node
.class(CSS.container),
.p(
// When you need a few classes, just put them together separated with comma
.class(CSS.myPost, CSS.marginLeft),
"Sample text"
),
.button(
.class(CSSAnimation.fadeIn),
.text("Tap me")
)
)
)
)
}
Plugin search match between each enum case and stylesheet files contents. If rawValue of StrongTypeCSS-conformed enum will not be found in stylesheet files contents - compiler will throw an error (with some description), and then interrupt execution.
Types of errors:
// Folder with css files not found (check 'cssFilesFolderPath' parameter when installing plugin)
"🔴 Folder with css files not found at '\(cssFilesFolderPath)'")
// Folder was found, but it's empty or without stylesheets files inside.
"🔴 There are no files found in '\(cssFilesFolderPath)'")
// Can't parse file
"🔴 Can't read \($0.name) as String"
// Enum case not found among your stylesheet files
"🔴 '\($0.classDescription).\($0.rawValue)' not found in files \(files.names()) contents. Please check it's name or add it in stylesheets")
Mikhail Medvedev | https://bearlogs.ru