mirror of
https://github.com/laosb/SwiftTailwind.git
synced 2025-11-28 22:01:38 +00:00
Improve source file detection and tests
- Use SwiftPM-provided sourceFiles for filtering - Add Utils.swift with URL descendant check - Update example to use Views/ instead of Folder/ - Add test for non-included Swift file - Update .zed settings to disable VSCode CSS language server
This commit is contained in:
parent
cfb5d2a4a2
commit
8359d795eb
8 changed files with 68 additions and 9 deletions
11
.zed/settings.json
Normal file
11
.zed/settings.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Folder-specific settings
|
||||||
|
//
|
||||||
|
// For a full list of overridable settings, and general information on folder-specific settings,
|
||||||
|
// see the documentation: https://zed.dev/docs/configuring-zed#settings-files
|
||||||
|
{
|
||||||
|
"languages": {
|
||||||
|
"CSS": {
|
||||||
|
"language_servers": ["!vscode-css-language-server"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -48,6 +48,10 @@ struct TailwindCSSBuildPlugin: BuildToolPlugin {
|
||||||
context: PluginContext,
|
context: PluginContext,
|
||||||
target: Target
|
target: Target
|
||||||
) throws -> [Command] {
|
) throws -> [Command] {
|
||||||
|
guard let sourceFileURLs = target.sourceModule?.sourceFiles.map({ $0.url }) else {
|
||||||
|
throw BuildError.notASourceModule
|
||||||
|
}
|
||||||
|
|
||||||
let tailwindCSSURL: URL = target.directoryURL.appending(component: "Tailwind.css")
|
let tailwindCSSURL: URL = target.directoryURL.appending(component: "Tailwind.css")
|
||||||
guard let cssContent = try? String(contentsOf: tailwindCSSURL) else {
|
guard let cssContent = try? String(contentsOf: tailwindCSSURL) else {
|
||||||
throw BuildError.missingTailwindCSSFile
|
throw BuildError.missingTailwindCSSFile
|
||||||
|
|
@ -60,18 +64,25 @@ struct TailwindCSSBuildPlugin: BuildToolPlugin {
|
||||||
throw BuildError.sourceNotDeclarationUnsupported
|
throw BuildError.sourceNotDeclarationUnsupported
|
||||||
}
|
}
|
||||||
|
|
||||||
let sourcePaths =
|
let sourcePatterns =
|
||||||
cssContent
|
cssContent
|
||||||
.matches(of: sourceDeclarationRegex)
|
.matches(of: sourceDeclarationRegex)
|
||||||
.compactMap { String($0.output.1) }
|
.compactMap { String($0.output.1) }
|
||||||
let sourceURLs: [URL] = sourcePaths.map { path in
|
let sourcePatternURLs: [URL] = sourcePatterns.map { path in
|
||||||
// Simplified handling: If ** is used, we just include everything in the directory.
|
// Simplified handling: If `**` is used, we just include everything in the directory.
|
||||||
|
// It's unlikely we will have the same glob processing logic as Tailwind CSS CLI,
|
||||||
|
// so we may as well just expand the coverage.
|
||||||
|
// This only affects SwiftPM change detection: Tailwind CSS CLI will handle the globbing correctly.
|
||||||
let globlessPath = path.replacing(/\*\*.*/, with: "")
|
let globlessPath = path.replacing(/\*\*.*/, with: "")
|
||||||
return target.directoryURL
|
return target.directoryURL
|
||||||
.appending(component: globlessPath, directoryHint: .inferFromPath)
|
.appending(component: globlessPath, directoryHint: .inferFromPath)
|
||||||
.resolvingSymlinksInPath()
|
.resolvingSymlinksInPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let includedSourceURLs = sourceFileURLs.filter { file in
|
||||||
|
sourcePatternURLs.contains { file.isOrIsDescendant(of: $0) }
|
||||||
|
}
|
||||||
|
|
||||||
let tailwindCLIURL: URL = try context.tool(named: "tailwindcss").url
|
let tailwindCLIURL: URL = try context.tool(named: "tailwindcss").url
|
||||||
let outputBundleURL = context.pluginWorkDirectoryURL
|
let outputBundleURL = context.pluginWorkDirectoryURL
|
||||||
.appending(component: outputBundleName, directoryHint: .isDirectory)
|
.appending(component: outputBundleName, directoryHint: .isDirectory)
|
||||||
|
|
@ -79,9 +90,10 @@ struct TailwindCSSBuildPlugin: BuildToolPlugin {
|
||||||
component: outputCSSFilename, directoryHint: .notDirectory)
|
component: outputCSSFilename, directoryHint: .notDirectory)
|
||||||
|
|
||||||
print("Tailwind CSS Build Plugin")
|
print("Tailwind CSS Build Plugin")
|
||||||
print("Tailwind CSS File: \(tailwindCSSURL.path)")
|
print("Tailwind.css: \(tailwindCSSURL.path)")
|
||||||
print("@source declarations: \(sourcePaths)")
|
print("@source declarations: \(sourcePatterns)")
|
||||||
print("Source files: \(sourceURLs.map(\.path))")
|
print("All source files: \(sourceFileURLs.map(\.path))")
|
||||||
|
print("Input files: \(includedSourceURLs.map(\.path))")
|
||||||
print("Output: \(outputURL.path)")
|
print("Output: \(outputURL.path)")
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
@ -93,7 +105,7 @@ struct TailwindCSSBuildPlugin: BuildToolPlugin {
|
||||||
"--output", outputURL.path,
|
"--output", outputURL.path,
|
||||||
"--minify",
|
"--minify",
|
||||||
],
|
],
|
||||||
inputFiles: [tailwindCSSURL] + sourceURLs,
|
inputFiles: [tailwindCSSURL] + includedSourceURLs,
|
||||||
outputFiles: [outputBundleURL]
|
outputFiles: [outputBundleURL]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
@ -102,12 +114,15 @@ struct TailwindCSSBuildPlugin: BuildToolPlugin {
|
||||||
|
|
||||||
extension TailwindCSSBuildPlugin {
|
extension TailwindCSSBuildPlugin {
|
||||||
enum BuildError: Error {
|
enum BuildError: Error {
|
||||||
|
case notASourceModule
|
||||||
case missingTailwindCSSFile
|
case missingTailwindCSSFile
|
||||||
case missingImportStatement
|
case missingImportStatement
|
||||||
case sourceNotDeclarationUnsupported
|
case sourceNotDeclarationUnsupported
|
||||||
|
|
||||||
var localizedDescription: String {
|
var localizedDescription: String {
|
||||||
switch self {
|
switch self {
|
||||||
|
case .notASourceModule:
|
||||||
|
"The target is not a source module."
|
||||||
case .missingTailwindCSSFile:
|
case .missingTailwindCSSFile:
|
||||||
"Tailwind.css file not found in the target directory."
|
"Tailwind.css file not found in the target directory."
|
||||||
case .missingImportStatement:
|
case .missingImportStatement:
|
||||||
|
|
|
||||||
24
Plugins/TailwindCSS/Utils.swift
Normal file
24
Plugins/TailwindCSS/Utils.swift
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension URL {
|
||||||
|
func isOrIsDescendant(of ancestor: URL) -> Bool {
|
||||||
|
guard ancestor.isFileURL, self.isFileURL else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
let ancestorComponents = ancestor.pathComponents
|
||||||
|
let selfComponents = self.pathComponents
|
||||||
|
|
||||||
|
guard selfComponents.count >= ancestorComponents.count else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index, component) in ancestorComponents.enumerated() {
|
||||||
|
if selfComponents[index] != component {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
5
Sources/SwiftTailwindExample/NotIncluded.swift
Normal file
5
Sources/SwiftTailwindExample/NotIncluded.swift
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
// This file is not included in Tailwind.css, so TW classes here will not be generated.
|
||||||
|
let html =
|
||||||
|
"""
|
||||||
|
<a href="swift.org" class="text-sm">Swift</a>
|
||||||
|
"""
|
||||||
|
|
@ -4,5 +4,5 @@
|
||||||
/** You must specify `source(none)` after `tailwindcss` import and add `@source` for each source file / folder you want to include. */
|
/** You must specify `source(none)` after `tailwindcss` import and add `@source` for each source file / folder you want to include. */
|
||||||
@import "tailwindcss" source(none);
|
@import "tailwindcss" source(none);
|
||||||
@source "./Example.swift";
|
@source "./Example.swift";
|
||||||
@source "./Folder";
|
@source "./Views";
|
||||||
@source "./Folder/**/*.swift";
|
@source "./Views/**/*.swift";
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,10 @@ struct SwiftTailwindExampleTests {
|
||||||
generatedCSS?.contains("bg-red-100") == true,
|
generatedCSS?.contains("bg-red-100") == true,
|
||||||
"Arbitary value class used in Folder/Template.swift is generated."
|
"Arbitary value class used in Folder/Template.swift is generated."
|
||||||
)
|
)
|
||||||
|
#expect(
|
||||||
|
generatedCSS?.contains("text-sm") == false,
|
||||||
|
"Class used in other non-included Swift code is not generated."
|
||||||
|
)
|
||||||
#expect(
|
#expect(
|
||||||
generatedCSS?.contains("bg-blue-500") == false,
|
generatedCSS?.contains("bg-blue-500") == false,
|
||||||
"Class not used is not generated."
|
"Class not used is not generated."
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue