diff --git a/Speculid.xcodeproj/project.pbxproj b/Speculid.xcodeproj/project.pbxproj index 7f44914b..07ed390a 100644 --- a/Speculid.xcodeproj/project.pbxproj +++ b/Speculid.xcodeproj/project.pbxproj @@ -21,6 +21,10 @@ B3E1707C24C1DBF700784D20 /* LabeledOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3E1707B24C1DBF700784D20 /* LabeledOption.swift */; }; B3E1707E24C1DC1100784D20 /* ResizeOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3E1707D24C1DC1100784D20 /* ResizeOption.swift */; }; B3E1708024C1DC6C00784D20 /* ClassicObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3E1707F24C1DC6C00784D20 /* ClassicObject.swift */; }; + B3E741E82530AF2500002110 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3E741E72530AF2500002110 /* main.swift */; }; + B3E741EE2530AF5A00002110 /* SpeculidKit in Frameworks */ = {isa = PBXBuildFile; productRef = B3E741ED2530AF5A00002110 /* SpeculidKit */; }; + B3E741F22530AFD500002110 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = B3E741F12530AFD500002110 /* ArgumentParser */; }; + B3E7420F2530B78F00002110 /* speculid in CopyFiles */ = {isa = PBXBuildFile; fileRef = B3E741E52530AF2500002110 /* speculid */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -37,12 +41,13 @@ }; B3796B7A2432C33600E5F5F9 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; - buildActionMask = 8; - dstPath = Contents/Helpers; - dstSubfolderSpec = 1; + buildActionMask = 12; + dstPath = ""; + dstSubfolderSpec = 12; files = ( + B3E7420F2530B78F00002110 /* speculid in CopyFiles */, ); - runOnlyForDeploymentPostprocessing = 1; + runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ @@ -68,6 +73,8 @@ B3E1707B24C1DBF700784D20 /* LabeledOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabeledOption.swift; sourceTree = ""; }; B3E1707D24C1DC1100784D20 /* ResizeOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResizeOption.swift; sourceTree = ""; }; B3E1707F24C1DC6C00784D20 /* ClassicObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassicObject.swift; sourceTree = ""; }; + B3E741E52530AF2500002110 /* speculid */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = speculid; sourceTree = BUILT_PRODUCTS_DIR; }; + B3E741E72530AF2500002110 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -80,6 +87,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + B3E741E22530AF2500002110 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B3E741F22530AFD500002110 /* ArgumentParser in Frameworks */, + B3E741EE2530AF5A00002110 /* SpeculidKit in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -116,6 +132,7 @@ B39F13FE243817AB00A69B85 /* packages */, B37A5236243500C900FEA6E9 /* command */, B3DB48092431642100B1DA4F /* Speculid */, + B3E741E62530AF2500002110 /* speculid */, B3DB48082431642100B1DA4F /* Products */, B303554824381F1200A8EAB9 /* Frameworks */, ); @@ -125,6 +142,7 @@ isa = PBXGroup; children = ( B3DB48072431642100B1DA4F /* Speculid.app */, + B3E741E52530AF2500002110 /* speculid */, ); name = Products; sourceTree = ""; @@ -158,6 +176,14 @@ path = "Preview Content"; sourceTree = ""; }; + B3E741E62530AF2500002110 /* speculid */ = { + isa = PBXGroup; + children = ( + B3E741E72530AF2500002110 /* main.swift */, + ); + path = speculid; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -184,18 +210,41 @@ productReference = B3DB48072431642100B1DA4F /* Speculid.app */; productType = "com.apple.product-type.application"; }; + B3E741E42530AF2500002110 /* speculid */ = { + isa = PBXNativeTarget; + buildConfigurationList = B3E741E92530AF2500002110 /* Build configuration list for PBXNativeTarget "speculid" */; + buildPhases = ( + B3E741E12530AF2500002110 /* Sources */, + B3E741E22530AF2500002110 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = speculid; + packageProductDependencies = ( + B3E741ED2530AF5A00002110 /* SpeculidKit */, + B3E741F12530AFD500002110 /* ArgumentParser */, + ); + productName = speculid; + productReference = B3E741E52530AF2500002110 /* speculid */; + productType = "com.apple.product-type.tool"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ B3DB47FD243162DA00B1DA4F /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1200; + LastSwiftUpdateCheck = 1220; LastUpgradeCheck = 1200; TargetAttributes = { B3DB48062431642100B1DA4F = { CreatedOnToolsVersion = 11.4; }; + B3E741E42530AF2500002110 = { + CreatedOnToolsVersion = 12.2; + }; }; }; buildConfigurationList = B3DB4800243162DA00B1DA4F /* Build configuration list for PBXProject "Speculid" */; @@ -207,11 +256,15 @@ Base, ); mainGroup = B3DB47FC243162DA00B1DA4F; + packageReferences = ( + B3E741F02530AFD500002110 /* XCRemoteSwiftPackageReference "swift-argument-parser" */, + ); productRefGroup = B3DB48082431642100B1DA4F /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( B3DB48062431642100B1DA4F /* Speculid */, + B3E741E42530AF2500002110 /* speculid */, ); }; /* End PBXProject section */ @@ -245,7 +298,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "swiftformat --lint . && swiftlint\n"; + shellScript = "# swiftformat --lint . && swiftlint\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -265,6 +318,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + B3E741E12530AF2500002110 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B3E741E82530AF2500002110 /* main.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ @@ -385,7 +446,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 15; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_ASSET_PATHS = "\"Speculid/Preview Content\""; DEVELOPMENT_TEAM = MLT7M394S7; @@ -485,7 +546,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 15; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = "\"Speculid/Preview Content\""; DEVELOPMENT_TEAM = MLT7M394S7; @@ -540,6 +601,87 @@ }; name = Release; }; + B3E741EA2530AF2500002110 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = speculid/speculid.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = MLT7M394S7; + ENABLE_HARDENED_RUNTIME = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + LD_RUNPATH_SEARCH_PATHS = .; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + B3E741EB2530AF2500002110 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = speculid/speculid.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = MLT7M394S7; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + LD_RUNPATH_SEARCH_PATHS = .; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -561,13 +703,42 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + B3E741E92530AF2500002110 /* Build configuration list for PBXNativeTarget "speculid" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B3E741EA2530AF2500002110 /* Debug */, + B3E741EB2530AF2500002110 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ +/* Begin XCRemoteSwiftPackageReference section */ + B3E741F02530AFD500002110 /* XCRemoteSwiftPackageReference "swift-argument-parser" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-argument-parser"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.3.1; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + /* Begin XCSwiftPackageProductDependency section */ B303554924381F1200A8EAB9 /* SpeculidKit */ = { isa = XCSwiftPackageProductDependency; productName = SpeculidKit; }; + B3E741ED2530AF5A00002110 /* SpeculidKit */ = { + isa = XCSwiftPackageProductDependency; + productName = SpeculidKit; + }; + B3E741F12530AFD500002110 /* ArgumentParser */ = { + isa = XCSwiftPackageProductDependency; + package = B3E741F02530AFD500002110 /* XCRemoteSwiftPackageReference "swift-argument-parser" */; + productName = ArgumentParser; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = B3DB47FD243162DA00B1DA4F /* Project object */; diff --git a/Speculid.xcodeproj/xcshareddata/xcschemes/speculid.xcscheme b/Speculid.xcodeproj/xcshareddata/xcschemes/speculid.xcscheme new file mode 100644 index 00000000..d5f51097 --- /dev/null +++ b/Speculid.xcodeproj/xcshareddata/xcschemes/speculid.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Speculid/Info.plist b/Speculid/Info.plist index fb4ac9f2..e270722f 100644 --- a/Speculid/Info.plist +++ b/Speculid/Info.plist @@ -46,7 +46,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 12 + $(CURRENT_PROJECT_VERSION) LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/Speculid/Speculid.entitlements b/Speculid/Speculid.entitlements index fceb94b9..251df823 100644 --- a/Speculid/Speculid.entitlements +++ b/Speculid/Speculid.entitlements @@ -2,15 +2,11 @@ - com.apple.security.app-sandbox - com.apple.security.application-groups $(TeamIdentifierPrefix)group.com.brightdigit.Speculid com.apple.security.cs.disable-library-validation - com.apple.security.files.user-selected.read-write - diff --git a/Speculid/main.swift b/Speculid/main.swift new file mode 100644 index 00000000..18f59c06 --- /dev/null +++ b/Speculid/main.swift @@ -0,0 +1,112 @@ +import ArgumentParser +import AssetLib +import Foundation +import SpeculidKit + +extension URL { + func relativePath(from base: URL) -> String? { + // Ensure that both URLs represent files: + guard isFileURL, base.isFileURL else { + return nil + } + + // Remove/replace "." and "..", make paths absolute: + let destComponents = standardized.pathComponents + let baseComponents = base.standardized.pathComponents + + // Find number of common path components: + var index = 0 + while index < destComponents.count, index < baseComponents.count, + destComponents[index] == baseComponents[index] { + index += 1 + } + + // Build relative path: + var relComponents = Array(repeating: "..", count: baseComponents.count - index) + relComponents.append(contentsOf: destComponents[index...]) + return relComponents.joined(separator: "/") + } +} + +struct Speculid: ParsableCommand { + static var configuration = CommandConfiguration( + subcommands: [Process.self, Initialize.self], + defaultSubcommand: Process.self + ) +} + +extension Speculid { + struct Initialize: ParsableCommand { + @Option + var assetDirectory: String + + @Option + var sourceImage: String + + @Argument + var destination: String + + func run() throws { + let assetDirectoryURL = URL(fileURLWithPath: assetDirectory) + let sourceImageFileURL = URL(fileURLWithPath: sourceImage) + let destinationSpecFileURL = URL(fileURLWithPath: destination) + + let decoder = JSONDecoder() + + let contentsJSON = assetDirectoryURL.appendingPathComponent("Contents.json") + let contentsData = try Data(contentsOf: contentsJSON) + let setDocument = try decoder.decode(AssetSpecificationDocument.self, from: contentsData) + + let encoder = JSONEncoder() + let outputFormatting: JSONEncoder.OutputFormatting + if #available(OSX 10.15, *) { + outputFormatting = [.prettyPrinted, .withoutEscapingSlashes] + } else { + outputFormatting = [.prettyPrinted] + } + encoder.outputFormatting = outputFormatting + + var file = SpeculidMutableSpecificationsFile(source: SpeculidSpecificationsFile()) + file.assetDirectoryRelativePath = assetDirectoryURL.relativePath(from: destinationSpecFileURL.deletingLastPathComponent())! + file.sourceImageRelativePath = sourceImageFileURL.relativePath(from: destinationSpecFileURL.deletingLastPathComponent())! + + let data = try encoder.encode(SpeculidSpecificationsFile(source: file)) + try data.write(to: destinationSpecFileURL) + } + } + + struct Process: ParsableCommand { + @Argument + var file: String = "" + + init() {} + + func run() throws { + let url = URL(fileURLWithPath: file) + let document = try SpeculidDocument(url: url, decoder: .init()) + let service = ServiceObject() + let imageSpecificationBuilder = SpeculidImageSpecificationBuilder() + let imageSpecs = try document.assetFile.document.images.map { + try imageSpecificationBuilder.imageSpecification( + forURL: document.destinationURL( + forFileName: $0.filename ?? document.destinationName(forImage: $0)), + withSpecifications: document.specificationsFile, + andAsset: $0 + ) + } + var result: Result? + DispatchQueue.global(qos: .userInitiated).async { + service.exportImageAtURL(document.sourceImageURL, toSpecifications: imageSpecs) { + result = $0.map(Result.failure) ?? .success(()) + } + } + while result == nil { + RunLoop.main.run(until: .distantPast) + } + + try result!.get() + } + } +} + +Speculid.main() diff --git a/_archive/examples/Assets/AppIcon.speculid b/_archive/examples/Assets/AppIcon.speculid index 3985adb2..5739ce92 100644 --- a/_archive/examples/Assets/AppIcon.speculid +++ b/_archive/examples/Assets/AppIcon.speculid @@ -1 +1,7 @@ -{"set":"Assets.xcassets\/AppIcon.appiconset","remove-alpha":true,"source":"geometry.svg","geometry":null,"background":"#FFFEFEFF"} \ No newline at end of file +{ + "set" : "/Users/leo/Documents/Projects/Speculid/_archive/examples/Assets/Assets.xcassets/macOS AppIcon.appiconset", + "remove-alpha" : true, + "source" : "geometry.svg", + "geometry" : null, + "background" : "#FCFBFBFF" +} \ No newline at end of file diff --git a/packages/SpeculidKit b/packages/SpeculidKit index a5ed9770..3e9907d5 160000 --- a/packages/SpeculidKit +++ b/packages/SpeculidKit @@ -1 +1 @@ -Subproject commit a5ed97704f864807c0bdc31189f577c256036a0e +Subproject commit 3e9907d506be4f8320bdb63043175bf733ea2396