SwiftyTailwind 🍃

All Contributors

SwiftyTailwind

SwiftyTailwind 是一个 Swift 包,用于从 Swift 项目(例如 Vapor 应用或 Publish 项目)中延迟下载并运行 Tailwind CLI。

用法

首先,您需要在项目的 Package.swift 中添加 SwiftyTailwind 作为依赖项

.package(url: "https://github.com/tuist/SwiftyTailwind.git", .upToNextMinor(from: "0.5.0"))

添加后,您需要创建一个 SwiftyTailwind 实例,指定您想要使用的版本以及您希望将其下载到的位置。

let tailwind = SwiftyTailwind(version: .latest, directory: "./cache")

如果您不传递任何参数,它将默认为系统中默认临时目录中的最新版本。 如果您在团队中工作,我们建议固定版本,以最大限度地减少跨环境的不确定性。

初始化 tailwind.config.js

您可以通过在 SwiftyTailwind 实例上运行 initialize 函数来创建一个 tailwind.config.js 配置文件

try await tailwind.initialize()

查看 文档 中所有可用的选项。

运行 Tailwind

要针对项目运行 Tailwind,您可以使用 run 函数

try await subject.run(input: inputCSSPath, output: outputCSSPath, options: .content("views/**/*.html"))

如果您希望 Tailwind 持续监视文件更改,您可以传递 .watch 选项

try await subject.run(input: inputCSSPath, 
                      output: outputCSSPath, 
                      options: .watch, .content("views/**/*.html"))

查看 文档 中所有可用的选项。

与 Vapor 集成

您可以通过设置 tailwind.swift 来将其与 Vapor 集成

import SwiftyTailwind
import TSCBasic
import Vapor

func tailwind(_ app: Application) async throws {
  let resourcesDirectory = try AbsolutePath(validating: app.directory.resourcesDirectory)
  let publicDirectory = try AbsolutePath(validating: app.directory.publicDirectory)

  let tailwind = SwiftyTailwind()
  try await tailwind.run(
    input: .init(validating: "Styles/app.css", relativeTo: resourcesDirectory),
    output: .init(validating: "styles/app.generated.css", relativeTo: publicDirectory),
    options: .content("\(app.directory.viewsDirectory)**/*.leaf")
  )
}

然后在 configure.swift

try await tailwind(app)
app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))

并在您的 index.leaf

<link rel="stylesheet" href="/styles/app.generated.css" />

并行运行 Vapor 和 Tailwind 监视

在不重启 Vapor 服务器的情况下,让 Tailwind 监视和重建更改可能是很理想的。 最好也仅在开发环境中限制此行为。

您可以通过设置 tailwind.swift 来集成此行为

#if DEBUG
import SwiftyTailwind
import TSCBasic
import Vapor

func runTailwind(_ app: Application) async throws {
    let resourcesDirectory = try AbsolutePath(validating: app.directory.resourcesDirectory)
    let publicDirectory = try AbsolutePath(validating: app.directory.publicDirectory)
    let tailwind = SwiftyTailwind()
    
    async let runTailwind: () = tailwind.run(
        input: .init(validating: "Styles/app.css", relativeTo: resourcesDirectory),
        output: .init(validating: "styles/app.generated.css", relativeTo: publicDirectory),
        options: .watch, .content("\(app.directory.viewsDirectory)**/*.leaf"))
    return try await runTailwind
}
#endif

然后在 entrypoint.swift 中,将 try await app.execute() 替换为

#if DEBUG
        if (env.arguments.contains { arg in arg == "migrate" }) {
            try await app.execute()
        } else {
            async let runApp: () = try await app.execute()
            _ = await [try runTailwind(app), try await runApp]
        }
#else
        try await app.execute()
#endif

对参数中的 migrate 的检查将确保它不会在开发中进行迁移时运行。 此外,最好设置一个脚本,以便在部署到生产环境之前缩小 CSS。

贡献者 ✨

感谢这些出色的人们 (emoji key)

Chris
Chris

🖋
William Sedlacek
William Sedlacek

📖
Brady Klein
Brady Klein

💻

该项目遵循 all-contributors 规范。 欢迎任何形式的贡献!