diff --git a/Package.resolved b/Package.resolved index 1365db01..f55b0a01 100644 --- a/Package.resolved +++ b/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/brightdigit/Contribute.git", "state" : { - "branch" : "contribute-wp", - "revision" : "2b2abb4261e545df04cdbe7a3c1912dc51532cea" + "revision" : "2dbdcdc99861f589639f1828b10ec3c459323639", + "version" : "1.0.0-alpha.2" } }, { diff --git a/Package.swift b/Package.swift index 6920dfc8..127e1d94 100644 --- a/Package.swift +++ b/Package.swift @@ -17,7 +17,7 @@ let package = Package( dependencies: [ .package( url: "https://github.com/brightdigit/Contribute.git", - branch: "contribute-wp" + from: "1.0.0-alpha.2" ), .package( url: "https://github.com/brightdigit/SyndiKit.git", diff --git a/Sources/ContributeWordPress/Decoder/PostsExportSynDecoder.swift b/Sources/ContributeWordPress/Decoder/PostsExportSynDecoder.swift index 50903b36..7dea67b2 100644 --- a/Sources/ContributeWordPress/Decoder/PostsExportSynDecoder.swift +++ b/Sources/ContributeWordPress/Decoder/PostsExportSynDecoder.swift @@ -50,7 +50,7 @@ public struct PostsExportSynDecoder: PostsExportDecoder { try (self.keyFromURL(url), Self.postsFromURL(url, using: decoder)) } - return Dictionary(uniqueKeysWithValues: feedPairs).compactMapValues{$0} + return Dictionary(uniqueKeysWithValues: feedPairs).compactMapValues { $0 } } } diff --git a/Sources/ContributeWordPress/Decoder/SynDecoder.swift b/Sources/ContributeWordPress/Decoder/SynDecoder.swift index 27db3b7f..112f71f5 100644 --- a/Sources/ContributeWordPress/Decoder/SynDecoder.swift +++ b/Sources/ContributeWordPress/Decoder/SynDecoder.swift @@ -5,51 +5,12 @@ import SyndiKit import FoundationNetworking #endif -public struct WordPressSite { - public init(title: String, link: URL, description: String? = nil, pubDate: Date? = nil, categories: [WordPressElements.Category], tags: [WordPressElements.Tag], baseSiteURL: URL? = nil, baseBlogURL: URL? = nil, posts: [WordPressPost]) { - self.title = title - self.link = link - self.description = description - self.pubDate = pubDate - self.categories = categories - self.tags = tags - self.baseSiteURL = baseSiteURL - self.baseBlogURL = baseBlogURL - self.posts = posts - } - - /// The name of the channel. - public let title: String - - /// The URL to the HTML website corresponding to the channel. - public let link: URL - - /// Phrase or sentence describing the channel. - public let description: String? - - - /// indicates the publication date and time of the feed's content - public let pubDate: Date? - - public let categories: [WordPressElements.Category] - public let tags: [WordPressElements.Tag] - public let baseSiteURL: URL? - public let baseBlogURL: URL? - - public let posts : [WordPressPost] -} - -extension WordPressSite { - public init (channel: RSSChannel) { - self.init(title: channel.title, link: channel.link - , categories: channel.wpCategories, tags: channel.wpTags, posts: channel.items.compactMap(\.wpPost)) - } -} - /// An extension that enables SynDecoder to decode WordPress posts. extension SynDecoder: WordPressDecoder { - - public func decodePosts(fromData data: Data, allowInvalidCharacters: Bool) throws -> WordPressSite? { + public func decodePosts( + fromData data: Data, + allowInvalidCharacters: Bool + ) throws -> WordPressSite? { let text = String(bytes: data, encoding: .utf8)? .replacingOccurrences(of: "\u{10}", with: "") .data(using: .utf8, allowLossyConversion: true) @@ -63,8 +24,9 @@ extension SynDecoder: WordPressDecoder { let feed = try decode(newData) let rss = feed as? RSSFeed - return rss.flatMap{$0.channel}.map(WordPressSite.init) + return try rss.map(\.channel).map(WordPressSite.init) } + /// Decodes an array of WordPress posts from the given data. /// /// - Parameters: diff --git a/Sources/ContributeWordPress/Decoder/WordPressDecoder.swift b/Sources/ContributeWordPress/Decoder/WordPressDecoder.swift index f3f7a143..7b882e26 100644 --- a/Sources/ContributeWordPress/Decoder/WordPressDecoder.swift +++ b/Sources/ContributeWordPress/Decoder/WordPressDecoder.swift @@ -7,7 +7,6 @@ import SyndiKit /// A protocol for decoding WordPress posts from raw data. public protocol WordPressDecoder { - /// Decodes an array of WordPress posts from the given data. /// /// - Parameters: diff --git a/Sources/ContributeWordPress/Decoder/WordPressSite.swift b/Sources/ContributeWordPress/Decoder/WordPressSite.swift new file mode 100644 index 00000000..898377e9 --- /dev/null +++ b/Sources/ContributeWordPress/Decoder/WordPressSite.swift @@ -0,0 +1,98 @@ +import Foundation +import SyndiKit + +public struct WordPressSite { + public static let wpContentUploadsRelativePath = "wp-content/uploads" + public init( + title: String, + link: URL, + description: String? = nil, + pubDate: Date? = nil, + categories: [WordPressElements.Category], + tags: [WordPressElements.Tag], + baseSiteURL: URL? = nil, + baseBlogURL: URL? = nil, + posts: [WordPressPost], + assetsImagesRegex: NSRegularExpression + ) { + self.title = title + self.link = link + self.description = description + self.pubDate = pubDate + self.categories = categories + self.tags = tags + self.baseSiteURL = baseSiteURL + self.baseBlogURL = baseBlogURL + self.posts = posts + self.assetsImagesRegex = assetsImagesRegex + } + + /// The name of the channel. + public let title: String + + /// The URL to the HTML website corresponding to the channel. + public let link: URL + + /// Phrase or sentence describing the channel. + public let description: String? + + /// indicates the publication date and time of the feed's content + public let pubDate: Date? + + public let categories: [WordPressElements.Category] + public let tags: [WordPressElements.Tag] + public let baseSiteURL: URL? + public let baseBlogURL: URL? + + public let posts: [WordPressPost] + + internal let assetsImagesRegex: NSRegularExpression +} + +extension WordPressSite { + public init(channel: RSSChannel) throws { + try self.init( + channel: channel, + relativeResourcePath: WordPressSite.wpContentUploadsRelativePath + ) + } + + public init( + channel: RSSChannel, + relativeResourcePath: String + ) throws { + let baseURL = channel.wpBaseBlogURL ?? channel.link + let assetsImagesRegex = try Self.defaultAssetsImagesRegex( + forAssetSiteURL: baseURL, + relativeResourcePath: relativeResourcePath + ) + self.init( + title: channel.title, + link: channel.link, + categories: channel.wpCategories, + tags: channel.wpTags, + baseSiteURL: channel.wpBaseSiteURL, + baseBlogURL: channel.wpBaseBlogURL, + posts: channel.items.compactMap(\.wpPost), + assetsImagesRegex: assetsImagesRegex + ) + } + + public static func defaultAssetsImagesRegex( + forAssetSiteURL assetSiteURL: URL, + relativeResourcePath: String = WordPressSite.wpContentUploadsRelativePath + ) throws -> NSRegularExpression { + try NSRegularExpression(pattern: "\(assetSiteURL)/\(relativeResourcePath)([^\"]+)") + } + + public var importDirectoryName: String { + baseBlogURL?.firstHostComponent ?? + link.firstHostComponent ?? + baseSiteURL?.firstHostComponent ?? + "default" + } + + public var baseURL: URL { + baseBlogURL ?? link + } +} diff --git a/Sources/ContributeWordPress/Extensions/Array.swift b/Sources/ContributeWordPress/Extensions/Array.swift deleted file mode 100644 index 07f59fb5..00000000 --- a/Sources/ContributeWordPress/Extensions/Array.swift +++ /dev/null @@ -1,22 +0,0 @@ -import Foundation - -/// This extension is used to combine two arrays of the same type. -extension Array { - /// Combines the given two optional arrays. - /// - /// - Parameters: - /// - lhs: The first optional array. - /// - rhs: The second optional array. - /// - Returns: A new array that is the combination of the two arrays. - internal static func combine(_ lhs: Self?, _ rhs: Self?) -> Self? { - guard let lhs = lhs else { - return rhs - } - - guard let rhs = rhs else { - return lhs - } - - return lhs + rhs - } -} diff --git a/Sources/ContributeWordPress/HTMLtoMarkdown.swift b/Sources/ContributeWordPress/HTMLtoMarkdown.swift index 5c07b306..c926736a 100644 --- a/Sources/ContributeWordPress/HTMLtoMarkdown.swift +++ b/Sources/ContributeWordPress/HTMLtoMarkdown.swift @@ -1,5 +1,5 @@ -import Foundation import Contribute +import Foundation public struct HTMLtoMarkdown: MarkdownGenerator { public init(_ markdownFromHTML: @escaping (String) throws -> String) { diff --git a/Sources/ContributeWordPress/Images/AssetImport.swift b/Sources/ContributeWordPress/Images/AssetImport.swift index 48a86614..51cfebbd 100644 --- a/Sources/ContributeWordPress/Images/AssetImport.swift +++ b/Sources/ContributeWordPress/Images/AssetImport.swift @@ -5,9 +5,6 @@ import SyndiKit import FoundationNetworking #endif -@available(*, deprecated, renamed: "AssetImport") -public typealias WordPressAssetImport = AssetImport - /// A type that holds information about an asset imported from a `WordPressPost`. public struct AssetImport: Hashable { /// The original URL of the asset. @@ -67,37 +64,22 @@ public struct AssetImport: Hashable { } extension URL { - var firstHostComponent : String? { - return self.host?.components(separatedBy: ".").first - } -} - -extension WordPressSite { - public var importDirectoryName : String { - self.baseBlogURL?.firstHostComponent ?? self.link.firstHostComponent ?? self.baseSiteURL?.firstHostComponent ?? "default" - } - - public var baseURL : URL { - - self.baseBlogURL ?? self.link + var firstHostComponent: String? { + host?.components(separatedBy: ".").first } } extension AssetImport { - public static func defaultAssetsImagesRegex( - forAssetSiteURL assetSiteURL: URL, - relativeResourcePath: String = "wp-content/uploads" - ) throws -> NSRegularExpression { - try NSRegularExpression(pattern: "\(assetSiteURL)/\(relativeResourcePath)([^\"]+)") - } - public static func extractAssetImports( from site: WordPressSite, using importSettings: ProcessorSettings ) -> [AssetImport] { - let assetRoot = ["", importSettings.assetRelativePath, site.importDirectoryName].joined(separator: "/") - let regex = try! Self.defaultAssetsImagesRegex(forAssetSiteURL: site.baseURL) - return regex + let assetRoot = [ + "", + importSettings.assetRelativePath, + site.importDirectoryName + ].joined(separator: "/") + return site.assetsImagesRegex .matchUrls(in: site.posts) .compactMap { match in AssetImport( diff --git a/Sources/ContributeWordPress/MarkdownProcessor.swift b/Sources/ContributeWordPress/MarkdownProcessor.swift index ee89d713..bab93c8b 100644 --- a/Sources/ContributeWordPress/MarkdownProcessor.swift +++ b/Sources/ContributeWordPress/MarkdownProcessor.swift @@ -7,9 +7,6 @@ import Yams import FoundationNetworking #endif -@available(*, deprecated, renamed: "MarkdownProcessor") -public typealias WordPressMarkdownProcessor = MarkdownProcessor - /// A type that processes WordPress posts and generates Markdown files for each. public struct MarkdownProcessor< ContentURLGeneratorType: ContentURLGenerator, @@ -105,11 +102,9 @@ public struct MarkdownProcessor< ) #warning("Should this just use `.filter(self.postFilters.postSatisfiesAll)`?") - - - + // 4. Build asset imports from all posts - let assetsImports: [AssetImport] = allPosts.values.flatMap{ + let assetsImports: [AssetImport] = allPosts.values.flatMap { assetImportFactory($0, settings) } diff --git a/Sources/ContributeWordPress/ProcessorSettings.swift b/Sources/ContributeWordPress/ProcessorSettings.swift index 7b3efeda..36d6e846 100644 --- a/Sources/ContributeWordPress/ProcessorSettings.swift +++ b/Sources/ContributeWordPress/ProcessorSettings.swift @@ -1,9 +1,6 @@ import Foundation import SyndiKit -@available(*, deprecated, renamed: "ProcessorSettings") -public typealias WordPressMarkdownProcessorSettings = ProcessorSettings - /// A protocol that defines the settings for the `WordPressMarkdownProcessor`. public protocol ProcessorSettings { /// The URL for the content path @@ -26,7 +23,6 @@ public protocol ProcessorSettings { /// Example: /..../WordPress/html/ var importAssetPathURL: URL? { get } - /// Whether to overwrite existing assets. var overwriteAssets: Bool { get } @@ -36,7 +32,6 @@ public protocol ProcessorSettings { /// Name of directory to store assets relative to ``resourcesPathURL`` var assetRelativePath: String { get } - /// Converts the given HTML to Markdown. /// /// - Parameter html: The HTML string to convert. @@ -48,18 +43,17 @@ public protocol ProcessorSettings { /// - Parameter html: The HTML string to convert. /// - Returns: The Markdown representation of the HTML. func htmlFromPost(_ site: WordPressSite) -> ((WordPressPost) -> String) - - - var uploadsRelativePath : String { + + var uploadsRelativePath: String { get } } extension ProcessorSettings { public var resourceAssetPathURL: URL { - return self.resourcesPathURL.appendingPathComponent(assetRelativePath) + resourcesPathURL.appendingPathComponent(assetRelativePath) } - + public func assetDirectoryPath(forSiteName siteName: String) -> String { let assetRelative = resourceAssetPathURL.relativePath( from: resourcesPathURL @@ -67,18 +61,21 @@ extension ProcessorSettings { return ["", assetRelative, siteName].joined(separator: "/") } - - public var uploadsRelativePath : String { - return "wp-content/uploads" + + public var uploadsRelativePath: String { + WordPressSite.wpContentUploadsRelativePath } - + public func htmlFromPost(_ site: WordPressSite) -> ((WordPressPost) -> String) { - let assetPostURLSearchPrefix = site.baseURL.appendingPathComponent(self.uploadsRelativePath).absoluteString + let assetPostURLSearchPrefix = site + .baseURL + .appendingPathComponent(uploadsRelativePath) + .absoluteString return { post in - post.body.replacingOccurrences( - of: assetPostURLSearchPrefix, - with: self.assetDirectoryPath(forSiteName: site.importDirectoryName) - ) + post.body.replacingOccurrences( + of: assetPostURLSearchPrefix, + with: self.assetDirectoryPath(forSiteName: site.importDirectoryName) + ) } } } diff --git a/Sources/ContributeWordPress/Redirects/Generators/DynamicRedirectGenerator.swift b/Sources/ContributeWordPress/Redirects/Generators/DynamicRedirectGenerator.swift index 8d1e45c9..e00ed766 100644 --- a/Sources/ContributeWordPress/Redirects/Generators/DynamicRedirectGenerator.swift +++ b/Sources/ContributeWordPress/Redirects/Generators/DynamicRedirectGenerator.swift @@ -49,7 +49,7 @@ public struct DynamicRedirectGenerator: RedirectListGenerator { ) -> [RedirectItem] { allPosts.flatMap { args -> [RedirectItem] in let (dir, site) = args - + return site.posts.filter(self.postFilter).map { post in RedirectItem( fromURLPath: post.link.path, diff --git a/Sources/ContributeWordPress/Source.swift b/Sources/ContributeWordPress/Source.swift index bae3ee5a..eacd33fa 100644 --- a/Sources/ContributeWordPress/Source.swift +++ b/Sources/ContributeWordPress/Source.swift @@ -2,9 +2,6 @@ import Contribute import Foundation import SyndiKit -@available(*, deprecated, renamed: "Source") -public typealias WordPressSource = Source - /// A type that represents a source for a WordPress post. public struct Source { /// The name of the section to which the post belongs.