diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 5efff76..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: CI - -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - test-linux: - name: Test on Linux - runs-on: ubuntu-latest - strategy: - matrix: - swift-version: ["6.1", "6.2"] - container: - image: swift:${{ matrix.swift-version }} - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Cache Swift packages - uses: actions/cache@v4 - with: - path: .build - key: ${{ runner.os }}-spm-${{ matrix.swift-version }}-${{ hashFiles('**/Package.resolved') }} - restore-keys: | - ${{ runner.os }}-spm-${{ matrix.swift-version }}- - ${{ runner.os }}-spm- - - - name: Build package - run: swift build --verbose - - - name: Run tests - run: swift test --verbose - - test-macos: - name: Test on macOS - runs-on: macos-latest - strategy: - matrix: - swift-version: ["6.1", "6.2"] - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Swift ${{ matrix.swift-version }} - uses: swift-actions/setup-swift@v2 - with: - swift-version: ${{ matrix.swift-version }} - - - name: Cache Swift packages - uses: actions/cache@v4 - with: - path: .build - key: ${{ runner.os }}-spm-${{ matrix.swift-version }}-${{ hashFiles('**/Package.resolved') }} - restore-keys: | - ${{ runner.os }}-spm-${{ matrix.swift-version }}- - ${{ runner.os }}-spm- - - - name: Build package - run: swift build --verbose - - - name: Run tests - run: swift test --verbose diff --git a/.github/workflows/release-tailwindcss-cli.yml b/.github/workflows/release-tailwindcss-cli.yml deleted file mode 100644 index 130cee9..0000000 --- a/.github/workflows/release-tailwindcss-cli.yml +++ /dev/null @@ -1,104 +0,0 @@ -name: Release TailwindCSS CLI Artifacts - -on: - workflow_dispatch: - inputs: - tailwind_version: - description: "TailwindCSS release version (e.g., v4.1.14)" - required: true - type: string - -jobs: - build-and-release: - name: Build and Release Artifacts - runs-on: macos-latest - permissions: - contents: write - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Swift - uses: swift-actions/setup-swift@v2 - with: - swift-version: "6.1" - - - name: Cache Swift packages - uses: actions/cache@v4 - with: - path: .build - key: ${{ runner.os }}-spm-release-${{ hashFiles('**/Package.resolved') }} - restore-keys: | - ${{ runner.os }}-spm-release- - ${{ runner.os }}-spm- - - - name: Validate version format - run: | - if [[ ! "${{ inputs.tailwind_version }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "Error: Version must be in format vX.Y.Z (e.g., v4.1.14)" - exit 1 - fi - echo "Version format is valid: ${{ inputs.tailwind_version }}" - - - name: Build artifact bundler - run: | - echo "Building TailwindCSSCLIArtifactBundler..." - swift build -c release --product TailwindCSSCLIArtifactBundler - - - name: Create artifact bundles - run: | - echo "Creating artifact bundles for TailwindCSS ${{ inputs.tailwind_version }}..." - mkdir -p ./artifacts - .build/release/TailwindCSSCLIArtifactBundler \ - --version "${{ inputs.tailwind_version }}" \ - --work-dir "${{ runner.temp }}/tailwindcss-bundles" \ - --output-dir ./artifacts - - - name: List generated artifacts - run: | - echo "Generated artifacts:" - ls -lh artifacts/ - - - name: Compute checksum - id: checksum - run: | - CHECKSUM=$(shasum -a 256 artifacts/tailwindcss.artifactbundleindex | awk '{print $1}') - echo "checksum=$CHECKSUM" >> $GITHUB_OUTPUT - echo "Artifact bundle index checksum: $CHECKSUM" - - - name: Create release - uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1 - with: - tag_name: TailwindCSSCLI-${{ inputs.tailwind_version }} - name: TailwindCSS CLI ${{ inputs.tailwind_version }} - body: | - ## TailwindCSS CLI Artifact Bundles - - This release contains Swift Package Manager artifact bundles for TailwindCSS CLI version `${{ inputs.tailwind_version }}`. - - ### Included Artifacts - - Linux x64 (`x86_64-unknown-linux-gnu`) - - macOS x64 (`x86_64-apple-darwin`) - - macOS ARM64 (`aarch64-apple-darwin`) - - ### Usage - Add the artifact bundle to your `Package.swift`: - ```swift - .binaryTarget( - name: "TailwindCSSCLI", - url: "https://github.com/${{ github.repository }}/releases/download/TailwindCSSCLI@${{ inputs.tailwind_version }}/tailwindcss.artifactbundleindex", - checksum: "${{ steps.checksum.outputs.checksum }}" - ) - ``` - - ### Checksum - ``` - ${{ steps.checksum.outputs.checksum }} - ``` - draft: false - prerelease: false - make_latest: false - files: | - artifacts/*.zip - artifacts/tailwindcss.artifactbundleindex diff --git a/.zed/settings.json b/.zed/settings.json deleted file mode 100644 index 7c708be..0000000 --- a/.zed/settings.json +++ /dev/null @@ -1,11 +0,0 @@ -// 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"] - } - } -} diff --git a/Package.resolved b/Package.resolved deleted file mode 100644 index e8c11be..0000000 --- a/Package.resolved +++ /dev/null @@ -1,33 +0,0 @@ -{ - "originHash" : "8e39da950f9cbe4c8126b1fabf0d3d6945ab547f7564fd7bb0921701f3269c14", - "pins" : [ - { - "identity" : "swift-argument-parser", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-argument-parser.git", - "state" : { - "revision" : "309a47b2b1d9b5e991f36961c983ecec72275be3", - "version" : "1.6.1" - } - }, - { - "identity" : "swift-asn1", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-asn1.git", - "state" : { - "revision" : "f70225981241859eb4aa1a18a75531d26637c8cc", - "version" : "1.4.0" - } - }, - { - "identity" : "swift-crypto", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-crypto.git", - "state" : { - "revision" : "95ba0316a9b733e92bb6b071255ff46263bbe7dc", - "version" : "3.15.1" - } - } - ], - "version" : 3 -} diff --git a/Package.swift b/Package.swift index ea0e1a8..b15c952 100644 --- a/Package.swift +++ b/Package.swift @@ -6,31 +6,19 @@ let package = Package( name: "SwiftTailwind", platforms: [.macOS(.v12)], products: [ - .plugin(name: "TailwindCSS", targets: ["TailwindCSS"]), - .executable(name: "TailwindCSSCLIArtifactBundler", targets: ["TailwindCSSCLIArtifactBundler"]), - ], - dependencies: [ - .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.0"), - .package(url: "https://github.com/apple/swift-crypto.git", from: "3.0.0"), + .plugin(name: "TailwindCSS", targets: ["TailwindCSS"]) ], targets: [ - .executableTarget( - name: "TailwindCSSCLIArtifactBundler", - dependencies: [ - .product(name: "ArgumentParser", package: "swift-argument-parser"), - .product(name: "Crypto", package: "swift-crypto"), - ] - ), .plugin(name: "TailwindCSS", capability: .buildTool(), dependencies: ["TailwindCSSCLI"]), .binaryTarget( name: "TailwindCSSCLI", url: - "https://github.com/laosb/SwiftTailwind/releases/download/1.1.0-test.4+tw.4.1.14/tailwindcss.artifactbundleindex", - checksum: "ec4df49e361db5fc3159c431e5661af2e1b22d8575c64ce0482a8e84cfd93d04" + "https://github.com/laosb/SwiftTailwind/releases/download/1.0.0+tw.4.1.12/tailwindcss.artifactbundle.zip", + checksum: "bfa96ef1d4d1b665bb40c89ec906044c9532b3cabf866fbe2bd3e5a95bf40bea" ), .target( name: "SwiftTailwindExample", - resources: [.copy("Views/Test.html")], + resources: [.copy("Folder")], plugins: ["TailwindCSS"] ), .testTarget(name: "SwiftTailwindTests", dependencies: ["SwiftTailwindExample"]), diff --git a/Plugins/TailwindCSS/TailwindCSSBuildPlugin.swift b/Plugins/TailwindCSS/TailwindCSSBuildPlugin.swift index fb3e4c7..d13cd10 100644 --- a/Plugins/TailwindCSS/TailwindCSSBuildPlugin.swift +++ b/Plugins/TailwindCSS/TailwindCSSBuildPlugin.swift @@ -30,7 +30,7 @@ struct TailwindCSSBuildPlugin: BuildToolPlugin { "@source" ZeroOrMore(.whitespace) "\"" - Capture { OneOrMore(CharacterClass.anyOf("\"").inverted) } + Capture(ZeroOrMore(.word)) "\"" ZeroOrMore(.whitespace) ";" @@ -48,12 +48,8 @@ struct TailwindCSSBuildPlugin: BuildToolPlugin { context: PluginContext, target: Target ) throws -> [Command] { - guard let sourceFileURLs = target.sourceModule?.sourceFiles.map({ $0.url }) else { - throw BuildError.notASourceModule - } - let tailwindCSSURL: URL = target.directoryURL.appending(component: "Tailwind.css") - guard let cssContent = try? String(contentsOf: tailwindCSSURL, encoding: .utf8) else { + guard let cssContent = try? String(contentsOf: tailwindCSSURL) else { throw BuildError.missingTailwindCSSFile } let matches = cssContent.matches(of: importStatementRegex) @@ -64,36 +60,27 @@ struct TailwindCSSBuildPlugin: BuildToolPlugin { throw BuildError.sourceNotDeclarationUnsupported } - let sourcePatterns = + let sourcePaths = cssContent .matches(of: sourceDeclarationRegex) .compactMap { String($0.output.1) } - let sourcePatternURLs: [URL] = sourcePatterns.map { path in - // 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 sourceURLs: [URL] = sourcePaths.map { path in + // Simplified handling: If ** is used, we just include everything in the directory. let globlessPath = path.replacing(/\*\*.*/, with: "") return target.directoryURL .appending(component: globlessPath, directoryHint: .inferFromPath) .resolvingSymlinksInPath() } - let includedSourceURLs = sourceFileURLs.filter { file in - sourcePatternURLs.contains { file.isOrIsDescendant(of: $0) } - } - let tailwindCLIURL: URL = try context.tool(named: "tailwindcss").url let outputBundleURL = context.pluginWorkDirectoryURL .appending(component: outputBundleName, directoryHint: .isDirectory) let outputURL = outputBundleURL.appending( component: outputCSSFilename, directoryHint: .notDirectory) - print("Tailwind CSS Build Plugin") - print("Tailwind.css: \(tailwindCSSURL.path)") - print("@source declarations: \(sourcePatterns)") - print("All source files: \(sourceFileURLs.map(\.path))") - print("Input files: \(includedSourceURLs.map(\.path))") + print("Tailwind CSS Build Plugin: \(tailwindCSSURL.path)") + print("Tailwind CSS File: \(tailwindCSSURL.path)") + print("Source files: \n -\(sourceURLs.map(\.path).joined(separator: "\n -"))") print("Output: \(outputURL.path)") return [ @@ -105,7 +92,7 @@ struct TailwindCSSBuildPlugin: BuildToolPlugin { "--output", outputURL.path, "--minify", ], - inputFiles: [tailwindCSSURL] + includedSourceURLs, + inputFiles: [tailwindCSSURL] + sourceURLs, outputFiles: [outputBundleURL] ) ] @@ -114,15 +101,12 @@ struct TailwindCSSBuildPlugin: BuildToolPlugin { extension TailwindCSSBuildPlugin { enum BuildError: Error { - case notASourceModule case missingTailwindCSSFile case missingImportStatement case sourceNotDeclarationUnsupported var localizedDescription: String { switch self { - case .notASourceModule: - "The target is not a source module." case .missingTailwindCSSFile: "Tailwind.css file not found in the target directory." case .missingImportStatement: diff --git a/Plugins/TailwindCSS/Utils.swift b/Plugins/TailwindCSS/Utils.swift deleted file mode 100644 index f18bcdc..0000000 --- a/Plugins/TailwindCSS/Utils.swift +++ /dev/null @@ -1,24 +0,0 @@ -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 - } -} diff --git a/Scripts/buildArtifactBundle.sh b/Scripts/buildArtifactBundle.sh new file mode 100755 index 0000000..3893187 --- /dev/null +++ b/Scripts/buildArtifactBundle.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +set -euo pipefail + +# Check if TAILWINDCSS_VERSION environment variable is set +if [[ -z "${TAILWINDCSS_VERSION:-}" ]]; then + echo "Error: TAILWINDCSS_VERSION environment variable is not set" + echo "Usage: TAILWINDCSS_VERSION=v3.4.0 $0" + exit 1 +fi + +VERSION="$TAILWINDCSS_VERSION" +echo "Building artifact bundle for TailwindCSS version: $VERSION" + +# Get the directory containing this script to find the template +TEMPLATE_FILE="$PWD/Scripts/info.template.json" + +# Check if template file exists +if [[ ! -f "$TEMPLATE_FILE" ]]; then + echo "Error: Template file not found at $TEMPLATE_FILE" + exit 1 +fi + +# Create working directory +WORK_DIR="/tmp/tailwindcss.artifactbundle" +echo "Creating working directory: $WORK_DIR" +rm -rf "$WORK_DIR" +mkdir -p "$WORK_DIR" +cd "$WORK_DIR" + +# GitHub release base URL +BASE_URL="https://github.com/tailwindlabs/tailwindcss/releases/download/$VERSION" + +# Download and place binaries +download_binary() { + local binary_name="$1" + local target_path="$2" + local target_dir + target_dir=$(dirname "$target_path") + + echo "Downloading $binary_name..." + mkdir -p "$target_dir" + + if curl -L "$BASE_URL/$binary_name" > "$target_path"; then + chmod +x "$target_path" + echo "✓ Downloaded and made executable: $target_path" + else + echo "✗ Failed to download $binary_name from $BASE_URL/$binary_name" + exit 1 + fi +} + +# Download each binary to its target location +download_binary "tailwindcss-linux-x64" "tailwindcss-$VERSION-linux-x64/bin/tailwindcss" +download_binary "tailwindcss-macos-x64" "tailwindcss-$VERSION-macos-x64/bin/tailwindcss" +download_binary "tailwindcss-macos-arm64" "tailwindcss-$VERSION-macos-arm64/bin/tailwindcss" + +# Create info.json from template, replacing %VERSION% with actual version +echo "Creating info.json from template..." +sed "s/%VERSION%/$VERSION/g" "$TEMPLATE_FILE" > "info.json" +echo "✓ Created info.json with version $VERSION" + +# Create ZIP file +ZIP_FILE="/tmp/tailwindcss.artifactbundle.zip" +echo "Creating ZIP file: $ZIP_FILE" + +# Remove existing ZIP file if it exists +rm -f "$ZIP_FILE" + +# Create ZIP with the artifact bundle as the only child in root +cd /tmp +zip -r "tailwindcss.artifactbundle.zip" "tailwindcss.artifactbundle" + +echo "✓ Created ZIP file: $ZIP_FILE" + +# Compute checksum using Swift Package Manager +echo "Computing checksum..." +CHECKSUM=$(swift package compute-checksum "$ZIP_FILE") + +echo "" +echo "=== BUILD COMPLETE ===" +echo "ZIP file path: $ZIP_FILE" +echo "Checksum: $CHECKSUM" diff --git a/Scripts/info.template.json b/Scripts/info.template.json new file mode 100644 index 0000000..ecdafef --- /dev/null +++ b/Scripts/info.template.json @@ -0,0 +1,23 @@ +{ + "schemaVersion": "1.0", + "artifacts": { + "tailwindcss": { + "version": "%VERSION%", + "type": "executable", + "variants": [ + { + "path": "tailwindcss-%VERSION%-macos-x64/bin/tailwindcss", + "supportedTriples": ["x86_64-apple-macosx"] + }, + { + "path": "tailwindcss-%VERSION%-macos-arm64/bin/tailwindcss", + "supportedTriples": ["arm64-apple-macosx"] + }, + { + "path": "tailwindcss-%VERSION%-linux-x64/bin/tailwindcss", + "supportedTriples": ["x86_64-unknown-linux-gnu"] + } + ] + } + } +} diff --git a/Sources/SwiftTailwindExample/Views/Template.swift b/Sources/SwiftTailwindExample/Folder/Template.swift similarity index 100% rename from Sources/SwiftTailwindExample/Views/Template.swift rename to Sources/SwiftTailwindExample/Folder/Template.swift diff --git a/Sources/SwiftTailwindExample/Views/Test.html b/Sources/SwiftTailwindExample/Folder/Test.html similarity index 100% rename from Sources/SwiftTailwindExample/Views/Test.html rename to Sources/SwiftTailwindExample/Folder/Test.html diff --git a/Sources/SwiftTailwindExample/NotIncluded.swift b/Sources/SwiftTailwindExample/NotIncluded.swift deleted file mode 100644 index 3cb7406..0000000 --- a/Sources/SwiftTailwindExample/NotIncluded.swift +++ /dev/null @@ -1,5 +0,0 @@ -// This file is not included in Tailwind.css, so TW classes here will not be generated. -let html = - """ - Swift - """ diff --git a/Sources/SwiftTailwindExample/Tailwind.css b/Sources/SwiftTailwindExample/Tailwind.css index 6b5a2bc..8fd853b 100644 --- a/Sources/SwiftTailwindExample/Tailwind.css +++ b/Sources/SwiftTailwindExample/Tailwind.css @@ -4,5 +4,5 @@ /** You must specify `source(none)` after `tailwindcss` import and add `@source` for each source file / folder you want to include. */ @import "tailwindcss" source(none); @source "./Example.swift"; -@source "./Views"; -@source "./Views/**/*.swift"; +@source "./Folder"; +@source "./Folder/**/*.swift"; diff --git a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+File Operations.swift b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+File Operations.swift deleted file mode 100644 index 19f43fd..0000000 --- a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+File Operations.swift +++ /dev/null @@ -1,41 +0,0 @@ -import Foundation - -extension ArtifactBundleBuilder { - func downloadFile(from urlString: String, to destination: String) throws { - guard let url = URL(string: urlString) else { - throw ArtifactBundleError.invalidURL(urlString) - } - - let data = try Data(contentsOf: url) - try data.write(to: URL(fileURLWithPath: destination)) - } - - func makeExecutable(path: String) throws { - let attributes = [FileAttributeKey.posixPermissions: 0o755] - try fileManager.setAttributes(attributes, ofItemAtPath: path) - } - - func createZipFile(bundleDir: String, zipPath: String) throws { - // Remove existing ZIP file if it exists - if fileManager.fileExists(atPath: zipPath) { - try fileManager.removeItem(atPath: zipPath) - } - - let bundleDirURL = URL(fileURLWithPath: bundleDir) - let workDirURL = bundleDirURL.deletingLastPathComponent() - let bundleName = bundleDirURL.lastPathComponent - - let process = Process() - process.executableURL = URL(fileURLWithPath: "/usr/bin/zip") - process.arguments = ["-r", zipPath, bundleName] - process.currentDirectoryURL = workDirURL - - try process.run() - process.waitUntilExit() - - guard process.terminationStatus == 0 else { - throw ArtifactBundleError.zipCreationFailed - } - } - -} diff --git a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+computeChecksum.swift b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+computeChecksum.swift deleted file mode 100644 index 7a5f906..0000000 --- a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+computeChecksum.swift +++ /dev/null @@ -1,46 +0,0 @@ -import Crypto -import Foundation - -extension ArtifactBundleBuilder { - /// Computes the SHA256 checksum of a file. - /// - /// If `usingSHA256Directly` is true, it uses Swift Crypto's SHA256 implementation. - /// This is to workaround https://github.com/swiftlang/swift-package-manager/issues/9219. - func computeChecksum( - filePath: String, - usingSHA256Directly: Bool = false - ) throws -> String { - if usingSHA256Directly { - // Use swift-crypto's SHA256 implementation - let fileURL = URL(fileURLWithPath: filePath) - let data = try Data(contentsOf: fileURL) - let hash = SHA256.hash(data: data) - return hash.compactMap { String(format: "%02x", $0) }.joined() - } else { - // Use swift package compute-checksum command - let process = Process() - process.executableURL = URL(fileURLWithPath: "/usr/bin/swift") - process.arguments = ["package", "compute-checksum", filePath] - - let pipe = Pipe() - process.standardOutput = pipe - - try process.run() - process.waitUntilExit() - - guard process.terminationStatus == 0 else { - throw ArtifactBundleError.checksumComputationFailed - } - - let data = pipe.fileHandleForReading.readDataToEndOfFile() - let output = String(data: data, encoding: .utf8)?.trimmingCharacters( - in: .whitespacesAndNewlines) - - guard let checksum = output, !checksum.isEmpty else { - throw ArtifactBundleError.checksumComputationFailed - } - - return checksum - } - } -} diff --git a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+expandingTriple.swift b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+expandingTriple.swift deleted file mode 100644 index 77146b1..0000000 --- a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder+expandingTriple.swift +++ /dev/null @@ -1,29 +0,0 @@ -extension ArtifactBundleBuilder { - /// Expands a list of triples into a stricter list of triples. - /// - /// To workaround https://github.com/swiftlang/swift-package-manager/issues/7362. - func expandingTriple(_ triple: String) -> [String] { - switch triple { - case "aarch64-apple-darwin": - [ - "aarch64-apple-darwin", - "arm64-apple-macosx12.0", - "arm64-apple-macosx13.0", - "arm64-apple-macosx14.0", - "arm64-apple-macosx15.0", - "arm64-apple-macosx26.0", - ] - case "x86_64-apple-darwin": - [ - "x86_64-apple-darwin", - "x86_64-apple-macosx12.0", - "x86_64-apple-macosx13.0", - "x86_64-apple-macosx14.0", - "x86_64-apple-macosx15.0", - "x86_64-apple-macosx26.0", - ] - // TODO: Does linux need more detailed triple variants? - default: [triple] - } - } -} diff --git a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder.swift b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder.swift deleted file mode 100644 index eef4027..0000000 --- a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleBuilder.swift +++ /dev/null @@ -1,158 +0,0 @@ -import Foundation - -class ArtifactBundleBuilder { - private let version: String - private let workDir: String - private let outputDir: String - let fileManager = FileManager.default - - private let binaryConfigurations: [BinaryConfiguration] = [ - BinaryConfiguration(binaryName: "tailwindcss-linux-x64", triple: "x86_64-unknown-linux-gnu"), - BinaryConfiguration(binaryName: "tailwindcss-macos-x64", triple: "x86_64-apple-darwin"), - BinaryConfiguration(binaryName: "tailwindcss-macos-arm64", triple: "aarch64-apple-darwin"), - ] - - init(version: String, workDir: String, outputDir: String) { - self.version = version - self.workDir = workDir - self.outputDir = outputDir - } - - func buildArtifactBundles() throws { - try setupWorkingDirectory() - - var bundleInfos: [BundleInfo] = [] - - print("Creating individual bundles...") - for config in binaryConfigurations { - let bundleInfo = try createBundle(for: config) - bundleInfos.append(bundleInfo) - } - - try generateArtifactBundleIndex(bundleInfos: bundleInfos) - - print("=== BUILD COMPLETE ===") - print("All bundles created successfully:") - print("") - print("Generated artifact bundle index: \(outputDir)/tailwindcss.artifactbundleindex") - print("") - - let indexChecksum = try computeChecksum( - filePath: "\(outputDir)/tailwindcss.artifactbundleindex", usingSHA256Directly: true) - print("Index checksum: \(indexChecksum)") - print("") - - for bundleInfo in bundleInfos { - print("Bundle: \(bundleInfo.fileName)") - print(" Checksum: \(bundleInfo.checksum)") - print(" Triple: \(bundleInfo.triple)") - print("") - } - } - - private func setupWorkingDirectory() throws { - print("Creating working directory: \(workDir)") - - if fileManager.fileExists(atPath: workDir) { - try fileManager.removeItem(atPath: workDir) - } - - try fileManager.createDirectory(atPath: workDir, withIntermediateDirectories: true) - } - - private func createBundle(for config: BinaryConfiguration) throws -> BundleInfo { - let bundleDirName = "tailwindcss-\(version)-\(config.triple).artifactbundle" - let bundleDir = "\(workDir)/\(bundleDirName)" - let binaryPath = "bin/tailwindcss" - - print("Creating bundle for \(config.triple)...") - - // Create bundle directory structure - let binDir = "\(bundleDir)/bin" - try fileManager.createDirectory(atPath: binDir, withIntermediateDirectories: true) - - // Download binary - print(" Downloading \(config.binaryName)...") - let binaryURL = - "https://github.com/tailwindlabs/tailwindcss/releases/download/\(version)/\(config.binaryName)" - let binaryDestination = "\(bundleDir)/\(binaryPath)" - - try downloadFile(from: binaryURL, to: binaryDestination) - try makeExecutable(path: binaryDestination) - print(" ✓ Downloaded and made executable: \(binaryDestination)") - - // Create info.json - print(" Creating info.json...") - try createInfoJSON(bundleDir: bundleDir, binaryPath: binaryPath, triple: config.triple) - print( - " ✓ Created info.json with version \(version), path \(binaryPath), triple \(config.triple)") - - // Create ZIP file - let zipFileName = "\(bundleDirName).zip" - let zipPath = "\(outputDir)/\(zipFileName)" - print(" Creating ZIP file: \(zipPath)") - - try createZipFile(bundleDir: bundleDir, zipPath: zipPath) - - // Compute checksum - print(" Computing checksum...") - let checksum = try computeChecksum(filePath: zipPath) - - print(" ✓ Bundle created: \(zipPath)") - print(" ✓ Checksum: \(checksum)") - print("") - - return BundleInfo(fileName: zipFileName, checksum: checksum, triple: config.triple) - } - - private func createInfoJSON(bundleDir: String, binaryPath: String, triple: String) throws { - let artifact = Artifact( - version: version, - type: "executable", - variants: [ - ArtifactVariant(path: binaryPath, supportedTriples: expandingTriple(triple)) - ] - ) - - let info = ArtifactBundleInfo( - schemaVersion: "1.0", - artifacts: ["tailwindcss": artifact] - ) - - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - - let jsonData = try encoder.encode(info) - let infoPath = "\(bundleDir)/info.json" - try jsonData.write(to: URL(fileURLWithPath: infoPath)) - } - - private func generateArtifactBundleIndex(bundleInfos: [BundleInfo]) throws { - print("Generating tailwindcss.artifactbundleindex...") - - // Create output directory if it doesn't exist - if !fileManager.fileExists(atPath: outputDir) { - try fileManager.createDirectory(atPath: outputDir, withIntermediateDirectories: true) - } - - let bundles = bundleInfos.map { bundleInfo in - Bundle( - fileName: bundleInfo.fileName, - checksum: bundleInfo.checksum, - supportedTriples: expandingTriple(bundleInfo.triple) - ) - } - - let index = ArtifactBundleIndex( - schemaVersion: "1.0", - archives: bundles - ) - - let encoder = JSONEncoder() - encoder.outputFormatting = [.prettyPrinted, .sortedKeys] - - let jsonData = try encoder.encode(index) - let indexPath = "\(outputDir)/tailwindcss.artifactbundleindex" - try jsonData.write(to: URL(fileURLWithPath: indexPath)) - } -} diff --git a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleError.swift b/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleError.swift deleted file mode 100644 index 4bb59e2..0000000 --- a/Sources/TailwindCSSCLIArtifactBundler/ArtifactBundleError.swift +++ /dev/null @@ -1,18 +0,0 @@ -import Foundation - -enum ArtifactBundleError: Error, LocalizedError { - case invalidURL(String) - case zipCreationFailed - case checksumComputationFailed - - var errorDescription: String? { - switch self { - case .invalidURL(let url): - return "Invalid URL: \(url)" - case .zipCreationFailed: - return "Failed to create ZIP file" - case .checksumComputationFailed: - return "Failed to compute checksum" - } - } -} diff --git a/Sources/TailwindCSSCLIArtifactBundler/Models.swift b/Sources/TailwindCSSCLIArtifactBundler/Models.swift deleted file mode 100644 index 79214ad..0000000 --- a/Sources/TailwindCSSCLIArtifactBundler/Models.swift +++ /dev/null @@ -1,53 +0,0 @@ -import Foundation - -// MARK: - Artifact Bundle Info Models - -/// Represents the info.json file structure for an artifact bundle -struct ArtifactBundleInfo: Codable { - let schemaVersion: String - let artifacts: [String: Artifact] - - enum CodingKeys: String, CodingKey { - case schemaVersion, artifacts - } -} - -struct Artifact: Codable { - let version: String - let type: String - let variants: [ArtifactVariant] -} - -struct ArtifactVariant: Codable { - let path: String - let supportedTriples: [String] -} - -// MARK: - Artifact Bundle Index Models - -/// Represents the .artifactbundleindex file structure -struct ArtifactBundleIndex: Codable { - let schemaVersion: String - let archives: [Bundle] // The proposal says it's "bundles" but the actual implementation uses "archives" -} - -struct Bundle: Codable { - let fileName: String - let checksum: String - let supportedTriples: [String] -} - -// MARK: - Internal Data Models - -/// Configuration for a binary platform -struct BinaryConfiguration { - let binaryName: String - let triple: String -} - -/// Information about a created bundle -struct BundleInfo { - let fileName: String - let checksum: String - let triple: String -} diff --git a/Sources/TailwindCSSCLIArtifactBundler/TailwindCSSCLIArtifactBundler.swift b/Sources/TailwindCSSCLIArtifactBundler/TailwindCSSCLIArtifactBundler.swift deleted file mode 100644 index ca14ef0..0000000 --- a/Sources/TailwindCSSCLIArtifactBundler/TailwindCSSCLIArtifactBundler.swift +++ /dev/null @@ -1,32 +0,0 @@ -import ArgumentParser -import Foundation - -@main -struct TailwindCSSCLIArtifactBundler: ParsableCommand { - static let configuration = CommandConfiguration( - commandName: "TailwindCSSCLIArtifactBundler", - abstract: "Build TailwindCSS CLI artifact bundles for Swift Package Manager", - version: "1.0.0" - ) - - @Option(name: .shortAndLong, help: "TailwindCSS version to build (e.g., v4.1.14)") - var version: String - - @Option(name: .shortAndLong, help: "Working directory for temporary files") - var workDir: String = "/tmp/tailwindcss-bundles" - - @Option(name: .shortAndLong, help: "Output directory for the artifact bundle index") - var outputDir: String = "." - - func run() throws { - print("Building artifact bundles for TailwindCSS version: \(version)") - - let bundler = ArtifactBundleBuilder( - version: version, - workDir: workDir, - outputDir: outputDir - ) - - try bundler.buildArtifactBundles() - } -} diff --git a/Tests/SwiftTailwindTests/Tests.swift b/Tests/SwiftTailwindTests/Tests.swift index 8a69f4e..008a9cf 100644 --- a/Tests/SwiftTailwindTests/Tests.swift +++ b/Tests/SwiftTailwindTests/Tests.swift @@ -21,10 +21,6 @@ struct SwiftTailwindExampleTests { generatedCSS?.contains("bg-red-100") == true, "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( generatedCSS?.contains("bg-blue-500") == false, "Class not used is not generated."