From 60417421b8490888eb899d36d7df593f7ebd7c20 Mon Sep 17 00:00:00 2001 From: Jason Morley Date: Fri, 8 Nov 2024 13:59:04 -1000 Subject: [PATCH 1/6] fix: Support images on Linux --- .gitignore | 1 + Package.resolved | 18 +++ Package.swift | 2 + README.md | 10 ++ .../InContextCore/Extensions/Dictionary.swift | 37 +++++- .../Importers/ImageImporter.swift | 112 ++++++++++++------ Sources/InContextCore/Utilities/EXIF.swift | 51 ++++++-- Sources/PlatformSupportLinux/UTType.swift | 4 + .../Tests/ImageImporterTests.swift | 4 +- 9 files changed, 184 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index fec4bf9..04048a5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /.build /.local /.swiftpm +/.vscode /_site /archives /build diff --git a/Package.resolved b/Package.resolved index 2919fae..a51752f 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,14 @@ { "pins" : [ + { + "identity" : "csqlite", + "kind" : "remoteSourceControl", + "location" : "https://github.com/stephencelis/CSQLite.git", + "state" : { + "revision" : "9106e983d5e3d5149ee35281ec089484b0def018", + "version" : "0.0.3" + } + }, { "identity" : "fseventswrapper", "kind" : "remoteSourceControl", @@ -180,6 +189,15 @@ "version" : "1.2.1" } }, + { + "identity" : "swiftexif", + "kind" : "remoteSourceControl", + "location" : "https://github.com/kradalby/SwiftExif.git", + "state" : { + "revision" : "ab83faa56618d14678279d3c93bb2fbc9070cb2b", + "version" : "0.0.7" + } + }, { "identity" : "swiftsoup", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 13952f7..1ab0b22 100644 --- a/Package.swift +++ b/Package.swift @@ -33,6 +33,7 @@ let package = Package( .package(url: "https://github.com/jwells89/Titlecaser.git", from: "1.0.0"), .package(url: "https://github.com/scinfu/SwiftSoup.git", from: "2.6.0"), .package(url: "https://github.com/stephencelis/SQLite.swift.git", from: "0.14.1"), + .package(url: "https://github.com/kradalby/SwiftExif.git", from: "0.0.7"), ], targets: [ .executableTarget( @@ -66,6 +67,7 @@ let package = Package( .product(name: "Tilt", package: "Tilt"), .product(name: "Titlecaser", package: "Titlecaser"), .product(name: "Yams", package: "Yams"), + .product(name: "SwiftExif", package: "SwiftExif"), ], resources: [ .process("Licenses"), diff --git a/README.md b/README.md index ea56db1..88446de 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,16 @@ brew install inseven/incontext/incontext See [https://incontext.app/docs](https://incontext.app/docs). +## Development + +### Linux + +Install third-party dependencies: + +```bash +sudo dnf install libexif-devel libiptcdata-devel +```` + ## Frontmatter Frontmatter is supported in Markdown files and image and video descriptions. InContext will pass through all unknown markdown fields, but puts type constraints on fields that have specific meaning: diff --git a/Sources/InContextCore/Extensions/Dictionary.swift b/Sources/InContextCore/Extensions/Dictionary.swift index 605ba39..73b5a85 100644 --- a/Sources/InContextCore/Extensions/Dictionary.swift +++ b/Sources/InContextCore/Extensions/Dictionary.swift @@ -22,6 +22,33 @@ import Foundation +protocol Transformable { + + // TODO: I think this might actually be returning an Any? + // TODO: ASK TOM WTF + static func transform(from value: Any) -> Self? + +} + +extension Int: Transformable { + + static func transform(from value: Any) -> Int? { + if let stringValue = value as? String { + return Int(stringValue) + } + return nil + } + +} + +extension String { + + func convert(type: T.Type) -> T? { + return nil + } + +} + extension Dictionary { func value(for key: Key, default defaultValue: T) throws -> T { @@ -51,10 +78,14 @@ extension Dictionary { guard let value = self[key] else { return nil } - guard let value = value as? T else { - throw InContextError.incorrectType(expected: T.Type.self, received: value) + if let value = value as? T { + return value } - return value + if let transformable = T.self as? Transformable.Type, + let value = transformable.transform(from: value) as? T { + return value + } + throw InContextError.incorrectType(expected: T.Type.self, received: value) } func requiredValue(for key: Key) throws -> T { diff --git a/Sources/InContextCore/Importers/ImageImporter.swift b/Sources/InContextCore/Importers/ImageImporter.swift index a8fa516..31c2571 100644 --- a/Sources/InContextCore/Importers/ImageImporter.swift +++ b/Sources/InContextCore/Importers/ImageImporter.swift @@ -32,8 +32,6 @@ import ImageIO import PlatformSupport -#if !os(Linux) - protocol _Test { // TODO: This needs to pass in the metadata func evaluate(fileURL: URL) -> Bool @@ -135,8 +133,8 @@ struct _Or: _Test { struct TransformContext { let fileURL: URL - let imageSource: CGImageSource - let exif: EXIF + let image: PlatformImage + let exif: EXIF // TODO: This is encapsulated in `PlatformImage` let assetsURL: URL @@ -178,19 +176,23 @@ struct _Resize: _Transform { let targetSize = size.fit(width: self.width) let maxPixelSize = max(targetSize.width, targetSize.height) - let options = [kCGImageSourceCreateThumbnailWithTransform: kCFBooleanTrue, - kCGImageSourceCreateThumbnailFromImageAlways: kCFBooleanTrue, - kCGImageSourceThumbnailMaxPixelSize: maxPixelSize as NSNumber] as CFDictionary - + // TODO: Honour the input format if we don't have one. guard let format = self.format ?? context.fileURL.type else { throw InContextError.internalInconsistency("Failed to detect output type for '\(context.fileURL.relativePath)'.") } + let destinationFilename = basename + "." + (format.preferredFilenameExtension ?? "") + let destinationURL = context.assetsURL.appending(component: destinationFilename) + +#if os(Linux) + +#else + + let options = [kCGImageSourceCreateThumbnailWithTransform: kCFBooleanTrue, + kCGImageSourceCreateThumbnailFromImageAlways: kCFBooleanTrue, + kCGImageSourceThumbnailMaxPixelSize: maxPixelSize as NSNumber] as CFDictionary let frameCount = CGImageSourceGetCount(context.imageSource) - // TODO: Honour the input format if we don't have one. - let destinationFilename = basename + "." + (format.preferredFilenameExtension ?? "") - let destinationURL = context.assetsURL.appending(component: destinationFilename) guard let destination = CGImageDestinationCreateWithURL(destinationURL as CFURL, format.identifier as CFString, frameCount, @@ -220,7 +222,10 @@ struct _Resize: _Transform { } CGImageDestinationFinalize(destination) // TODO: Handle error here? - context.assets.append(Asset(fileURL: destinationURL as URL)) + +#endif + + // context.assets.append(Asset(fileURL: destinationURL as URL)) // TODO: Why `as URL`? let details = [ "width": targetSize.width, @@ -250,6 +255,23 @@ struct _Resize: _Transform { context.metadata[set] = container } + print(context.metadata) + context.metadata["cheese"] = 12 + context.metadata["random"] = ["hello": 42] + + print(type(of: context.metadata["image"])) + + if var image = context.metadata["image"] as? [String: Any], + let width = image["width"] as? Int { + image["width"] = 12 + // print(width) + // print(type(of: width)) + // image["width"] = Int(width) + context.metadata["image"] = image + } + + context.metadata["foo"] = 1024 + } } @@ -316,8 +338,6 @@ let configuration = _Configuration { } -#endif - class ImageImporter { struct Settings: ImporterSettings { @@ -348,20 +368,42 @@ class ImageImporter { #if os(Linux) -extension ImageImporter: Importer { +class PlatformImage { - func process(file: File, - settings: Settings, - outputURL: URL) async throws -> ImporterResult { + let url: URL + let exif: EXIF - throw InContextError.internalInconsistency("Unsupported") - + init(url: URL) throws { + self.url = url + self.exif = try EXIF(url: url) } - + } #else +class PlatformImage { + + let url: URL + let source: CGImageSource + let exif: EXIF + + init(url: URL) throws { + guard let image = CGImageSourceCreateWithURL(url as CFURL, nil) else { + throw InContextError.internalInconsistency("Failed to open image file at '\(url.relativePath)'.") + } + guard let exif = try EXIF(image, 0) else { + throw InContextError.internalInconsistency("Failed to load properties for image at '\(url.relativePath)'.") + } + self.url = url + self.image = image + self.exif = exif + } + +} + +#endif + extension ImageImporter: Importer { func process(file: File, @@ -374,14 +416,8 @@ extension ImageImporter: Importer { let assetsURL = URL(filePath: fileURL.relevantRelativePath, relativeTo: outputURL) // TODO: Make this a utiltiy and test it try FileManager.default.createDirectory(at: assetsURL, withIntermediateDirectories: true) - // Load the original image. - guard let image = CGImageSourceCreateWithURL(fileURL as CFURL, nil) else { - throw InContextError.internalInconsistency("Failed to open image file at '\(fileURL.relativePath)'.") - } - - guard let exif = try EXIF(image, 0) else { - throw InContextError.internalInconsistency("Failed to load properties for image at '\(fileURL.relativePath)'.") - } + // Load the image. + let image = try PlatformImage(url: fileURL) let details = fileURL.basenameDetails() @@ -392,13 +428,13 @@ extension ImageImporter: Importer { metadata["scale"] = scale } - if let projectionType = try exif.projectionType { + if let projectionType = try image.exif.projectionType { metadata["projection"] = projectionType } // Content. var content: FrontmatterDocument? = nil - if let imageDescription = try exif.imageDescription { + if let imageDescription = try image.exif.imageDescription { let frontmatter = try FrontmatterDocument(contents: imageDescription, generateHTML: true) guard let contentMetadata = frontmatter.metadata as? [String: Any] else { throw InContextError.internalInconsistency("Unexpected key type for metadata") @@ -408,8 +444,8 @@ extension ImageImporter: Importer { } // Location. - if let latitude = try exif.signedLatitude, - let longitude = try exif.signedLongitude { + if let latitude = try image.exif.signedLatitude, + let longitude = try image.exif.signedLongitude { metadata["location"] = [ "latitude": latitude, "longitude": longitude, @@ -418,8 +454,8 @@ extension ImageImporter: Importer { // Perform the transforms. var context = TransformContext(fileURL: fileURL, - imageSource: image, - exif: exif, + image: image, + exif: image.exif, assetsURL: assetsURL, metadata: metadata, assets: []) @@ -438,8 +474,8 @@ extension ImageImporter: Importer { // N.B. The EXIF 'DateTimeOriginal' field sometimes appears to be invalid so we fall back on DateTimeDigitized. - let date = try (try? exif.dateTimeOriginal) ?? (try exif.dateTimeDigitized) ?? details.date - let title = try exif.firstTitle ?? content?.title ?? filenameTitle + let date = try (try? image.exif.dateTimeOriginal) ?? (try image.exif.dateTimeDigitized) ?? details.date + let title = try image.exif.firstTitle ?? content?.title ?? filenameTitle let document = try Document(url: fileURL.siteURL, parent: fileURL.parentURL, @@ -457,5 +493,3 @@ extension ImageImporter: Importer { } } - -#endif diff --git a/Sources/InContextCore/Utilities/EXIF.swift b/Sources/InContextCore/Utilities/EXIF.swift index 1e4e03e..534139c 100644 --- a/Sources/InContextCore/Utilities/EXIF.swift +++ b/Sources/InContextCore/Utilities/EXIF.swift @@ -20,11 +20,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#if !os(Linux) - import Foundation +#if !os(Linux) import ImageIO +#else +import SwiftExif +#endif // Metadata import details from Python. //METADATA_SCHEMA = Dictionary({ @@ -65,31 +67,52 @@ struct EXIF { }() let _properties: [String: Any] + +#if !os(Linux) let _metadata: CGImageMetadata +#endif + +// TODO: Use a protocol for the platform specific image to ensure it's clear what we're doing. - init?(_ imageSource: CGImageSource, _ index: Int) throws { +#if os(Linux) + + init(url: URL) throws { + let image = SwiftExif.Image(imagePath: url) + let exifRaw = image.ExifRaw() + guard !exifRaw.isEmpty else { + throw InContextError.internalInconsistency("Unable to load EXIF") + } + self._properties = exifRaw["EXIF"] ?? [:] + } + +#else + + init(_ imageSource: CGImageSource, _ index: Int) throws { guard let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, index, nil) else { - return nil + throw InContextError.internalInconsistency("Failed to load image properties") } guard let typedProperties = properties as? [String: Any] else { throw InContextError.internalInconsistency("Failed to load image properties") } - - // Image metadata, not image properties? guard let imageMetadata = CGImageSourceCopyMetadataAtIndex(imageSource, 0, nil) else { throw InContextError.internalInconsistency("Failed to load image metadata") } - self._properties = typedProperties self._metadata = imageMetadata } +#endif + var pixelWidth: Int? { - get throws { return try _properties.optionalValue(for: "PixelWidth") } + get throws { + return try _properties.optionalValue(for: "Pixel X Dimension") + } } var pixelHeight: Int? { - get throws { return try _properties.optionalValue(for: "PixelHeight") } + get throws { + return try _properties.optionalValue(for: "Pixel Y Dimension") + } } // TODO: Use EXIF timezones if they exist. @@ -151,6 +174,12 @@ struct EXIF { get throws { return try _properties.optionalRawRepresentable(for: ["{GPS}", "LongitudeRef"])} } +#if os(Linux) + + let projectionType: String? = nil + +#else + var projectionType: String? { get throws { guard let tag = CGImageMetadataCopyTagWithPath(_metadata, nil, "GPano:ProjectionType" as NSString) else { @@ -164,6 +193,8 @@ struct EXIF { } } +#endif + var signedLatitude: Double? { get throws { guard let latitude = try latitude, let latitudeRef = try latitudeRef else { @@ -187,5 +218,3 @@ struct EXIF { } } - -#endif diff --git a/Sources/PlatformSupportLinux/UTType.swift b/Sources/PlatformSupportLinux/UTType.swift index f837ad4..235952b 100644 --- a/Sources/PlatformSupportLinux/UTType.swift +++ b/Sources/PlatformSupportLinux/UTType.swift @@ -28,6 +28,10 @@ public class UTType { public static let tiff = UTType(filenameExtension: "tiff") public static let heic = UTType(filenameExtension: "heic") + public var preferredFilenameExtension: String { + return filenameExtension + } + let filenameExtension: String public init(filenameExtension: String) { diff --git a/Tests/InContextTests/Tests/ImageImporterTests.swift b/Tests/InContextTests/Tests/ImageImporterTests.swift index 8b7a676..2caca2c 100644 --- a/Tests/InContextTests/Tests/ImageImporterTests.swift +++ b/Tests/InContextTests/Tests/ImageImporterTests.swift @@ -25,7 +25,7 @@ import Foundation import XCTest @testable import InContextCore -#if !os(Linux) +// #if !os(Linux) class ImageImporterTests: ContentTestCase { @@ -109,4 +109,4 @@ steps: } -#endif +// #endif From d12a23376559434bab023fdd136078cd23a7eca2 Mon Sep 17 00:00:00 2001 From: Jason Morley Date: Sun, 24 Nov 2024 11:58:49 -1000 Subject: [PATCH 2/6] Match macOS implementation --- Sources/PlatformSupportLinux/UTType.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/PlatformSupportLinux/UTType.swift b/Sources/PlatformSupportLinux/UTType.swift index 235952b..3dcd787 100644 --- a/Sources/PlatformSupportLinux/UTType.swift +++ b/Sources/PlatformSupportLinux/UTType.swift @@ -28,7 +28,7 @@ public class UTType { public static let tiff = UTType(filenameExtension: "tiff") public static let heic = UTType(filenameExtension: "heic") - public var preferredFilenameExtension: String { + public var preferredFilenameExtension: String? { return filenameExtension } From e028627904a74aea16d2140f727a8072ea716867 Mon Sep 17 00:00:00 2001 From: Jason Morley Date: Sun, 24 Nov 2024 12:07:47 -1000 Subject: [PATCH 3/6] Current state of the art --- .../Importers/ImageImporter.swift | 55 ---------------- .../Importers/PlatformImage.swift | 63 +++++++++++++++++++ 2 files changed, 63 insertions(+), 55 deletions(-) create mode 100644 Sources/InContextCore/Importers/PlatformImage.swift diff --git a/Sources/InContextCore/Importers/ImageImporter.swift b/Sources/InContextCore/Importers/ImageImporter.swift index 31c2571..861276a 100644 --- a/Sources/InContextCore/Importers/ImageImporter.swift +++ b/Sources/InContextCore/Importers/ImageImporter.swift @@ -255,23 +255,6 @@ struct _Resize: _Transform { context.metadata[set] = container } - print(context.metadata) - context.metadata["cheese"] = 12 - context.metadata["random"] = ["hello": 42] - - print(type(of: context.metadata["image"])) - - if var image = context.metadata["image"] as? [String: Any], - let width = image["width"] as? Int { - image["width"] = 12 - // print(width) - // print(type(of: width)) - // image["width"] = Int(width) - context.metadata["image"] = image - } - - context.metadata["foo"] = 1024 - } } @@ -366,44 +349,6 @@ class ImageImporter { } -#if os(Linux) - -class PlatformImage { - - let url: URL - let exif: EXIF - - init(url: URL) throws { - self.url = url - self.exif = try EXIF(url: url) - } - -} - -#else - -class PlatformImage { - - let url: URL - let source: CGImageSource - let exif: EXIF - - init(url: URL) throws { - guard let image = CGImageSourceCreateWithURL(url as CFURL, nil) else { - throw InContextError.internalInconsistency("Failed to open image file at '\(url.relativePath)'.") - } - guard let exif = try EXIF(image, 0) else { - throw InContextError.internalInconsistency("Failed to load properties for image at '\(url.relativePath)'.") - } - self.url = url - self.image = image - self.exif = exif - } - -} - -#endif - extension ImageImporter: Importer { func process(file: File, diff --git a/Sources/InContextCore/Importers/PlatformImage.swift b/Sources/InContextCore/Importers/PlatformImage.swift new file mode 100644 index 0000000..14b86fe --- /dev/null +++ b/Sources/InContextCore/Importers/PlatformImage.swift @@ -0,0 +1,63 @@ +// MIT License +// +// Copyright (c) 2016-2024 Jason Morley +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation + +#if os(Linux) + +class PlatformImage { + + let url: URL + let exif: EXIF + + init(url: URL) throws { + self.url = url + self.exif = try EXIF(url: url) + } + +} + +#else + +import CoreGraphics + +class PlatformImage { + + let url: URL + let source: CGImageSource + let exif: EXIF + + init(url: URL) throws { + guard let image = CGImageSourceCreateWithURL(url as CFURL, nil) else { + throw InContextError.internalInconsistency("Failed to open image file at '\(url.relativePath)'.") + } + guard let exif = try EXIF(image, 0) else { + throw InContextError.internalInconsistency("Failed to load properties for image at '\(url.relativePath)'.") + } + self.url = url + self.image = image + self.exif = exif + } + +} + +#endif \ No newline at end of file From 9644886545ae7aa08d29b92f4f899bc707ea0d07 Mon Sep 17 00:00:00 2001 From: Jason Morley Date: Sun, 24 Nov 2024 15:16:33 -1000 Subject: [PATCH 4/6] Limit SwiftExif to Linux --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 1ab0b22..1b9a7d7 100644 --- a/Package.swift +++ b/Package.swift @@ -67,7 +67,7 @@ let package = Package( .product(name: "Tilt", package: "Tilt"), .product(name: "Titlecaser", package: "Titlecaser"), .product(name: "Yams", package: "Yams"), - .product(name: "SwiftExif", package: "SwiftExif"), + .product(name: "SwiftExif", package: "SwiftExif", condition: .when(platforms: [.linux])), ], resources: [ .process("Licenses"), From b5df58b3037425dbedb39caee8dc9b6b5c4138dc Mon Sep 17 00:00:00 2001 From: Jason Morley Date: Sun, 24 Nov 2024 15:37:11 -1000 Subject: [PATCH 5/6] Make things compile on macOS --- Sources/InContextCore/Importers/ImageImporter.swift | 10 +++++----- Sources/InContextCore/Importers/PlatformImage.swift | 12 +++++------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Sources/InContextCore/Importers/ImageImporter.swift b/Sources/InContextCore/Importers/ImageImporter.swift index 861276a..2c49398 100644 --- a/Sources/InContextCore/Importers/ImageImporter.swift +++ b/Sources/InContextCore/Importers/ImageImporter.swift @@ -185,13 +185,13 @@ struct _Resize: _Transform { #if os(Linux) -#else +#else let options = [kCGImageSourceCreateThumbnailWithTransform: kCFBooleanTrue, kCGImageSourceCreateThumbnailFromImageAlways: kCFBooleanTrue, kCGImageSourceThumbnailMaxPixelSize: maxPixelSize as NSNumber] as CFDictionary - let frameCount = CGImageSourceGetCount(context.imageSource) + let frameCount = CGImageSourceGetCount(context.image.source) guard let destination = CGImageDestinationCreateWithURL(destinationURL as CFURL, format.identifier as CFString, @@ -202,7 +202,7 @@ struct _Resize: _Transform { // Cherry-pick relevant image properties. var destinationProperties: [String: Any] = [:] - if let sourceProperties = CGImageSourceCopyProperties(context.imageSource, nil) as? [String: Any] { + if let sourceProperties = CGImageSourceCopyProperties(context.image.source, nil) as? [String: Any] { if let gifProperties = sourceProperties[kCGImagePropertyGIFDictionary as String] { destinationProperties[kCGImagePropertyGIFDictionary as String] = gifProperties } @@ -211,8 +211,8 @@ struct _Resize: _Transform { // Resize the frames. for i in 0.. Date: Sun, 24 Nov 2024 16:47:12 -1000 Subject: [PATCH 6/6] Guard against SwiftExif differently --- Package.swift | 56 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/Package.swift b/Package.swift index 1b9a7d7..46480f5 100644 --- a/Package.swift +++ b/Package.swift @@ -3,6 +3,44 @@ import PackageDescription +#if os(macOS) + +let coreDependencies: [Target.Dependency] = [ + "PlatformSupport", + "Hoedown", + .product(name: "Crypto", package: "swift-crypto"), + .product(name: "FSEventsWrapper", package: "FSEventsWrapper"), + .product(name: "Hummingbird", package: "hummingbird"), + .product(name: "HummingbirdFoundation", package: "hummingbird"), + .product(name: "Licensable", package: "licensable"), + .product(name: "Logging", package: "swift-log"), + .product(name: "SQLite", package: "SQLite.swift"), + .product(name: "SwiftSoup", package: "SwiftSoup"), + .product(name: "Tilt", package: "Tilt"), + .product(name: "Titlecaser", package: "Titlecaser"), + .product(name: "Yams", package: "Yams"), +] + +#else + +let coreDependencies: [Target.Dependency] = [ + "PlatformSupport", + "Hoedown", + .product(name: "Crypto", package: "swift-crypto"), + .product(name: "Hummingbird", package: "hummingbird"), + .product(name: "HummingbirdFoundation", package: "hummingbird"), + .product(name: "Licensable", package: "licensable"), + .product(name: "Logging", package: "swift-log"), + .product(name: "SQLite", package: "SQLite.swift"), + .product(name: "SwiftExif", package: "SwiftExif"), + .product(name: "SwiftSoup", package: "SwiftSoup"), + .product(name: "Tilt", package: "Tilt"), + .product(name: "Titlecaser", package: "Titlecaser"), + .product(name: "Yams", package: "Yams"), +] + +#endif + let package = Package( name: "incontext", platforms: [ @@ -52,23 +90,7 @@ let package = Package( ]), .target( name: "InContextCore", - dependencies: [ - "PlatformSupport", - "Hoedown", - .product(name: "Crypto", package: "swift-crypto"), - .product(name: "FSEventsWrapper", package: "FSEventsWrapper", condition: - .when(platforms: [.macOS])), - .product(name: "Hummingbird", package: "hummingbird"), - .product(name: "HummingbirdFoundation", package: "hummingbird"), - .product(name: "Licensable", package: "licensable"), - .product(name: "Logging", package: "swift-log"), - .product(name: "SQLite", package: "SQLite.swift"), - .product(name: "SwiftSoup", package: "SwiftSoup"), - .product(name: "Tilt", package: "Tilt"), - .product(name: "Titlecaser", package: "Titlecaser"), - .product(name: "Yams", package: "Yams"), - .product(name: "SwiftExif", package: "SwiftExif", condition: .when(platforms: [.linux])), - ], + dependencies: coreDependencies, resources: [ .process("Licenses"), ],