diff --git a/Account/Package.swift b/Account/Package.swift index 7b65bd22b..eb4025247 100644 --- a/Account/Package.swift +++ b/Account/Package.swift @@ -19,7 +19,7 @@ let package = Package( .package(path: "../SyncDatabase"), .package(path: "../RSCore"), .package(path: "../RSDatabase"), - .package(path: "../RSParser"), + .package(path: "../Parser"), ], targets: [ .target( @@ -27,7 +27,7 @@ let package = Package( dependencies: [ "RSCore", "RSDatabase", - "RSParser", + "Parser", "RSWeb", "Articles", "ArticlesDatabase", diff --git a/Account/Sources/Account/Account.swift b/Account/Sources/Account/Account.swift index b5accfe6e..bd452173f 100644 --- a/Account/Sources/Account/Account.swift +++ b/Account/Sources/Account/Account.swift @@ -13,7 +13,7 @@ import UIKit import Foundation import RSCore import Articles -import RSParser +import Parser import RSDatabase import ArticlesDatabase import RSWeb @@ -484,14 +484,14 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, delegate.accountWillBeDeleted(self) } - func addOPMLItems(_ items: [RSOPMLItem]) { + func addOPMLItems(_ items: [OPMLItem]) { for item in items { if let feedSpecifier = item.feedSpecifier { addFeed(newFeed(with: feedSpecifier)) } else { if let title = item.titleFromAttributes, let folder = ensureFolder(with: title) { folder.externalID = item.attributes?["nnw_externalID"] as? String - item.children?.forEach { itemChild in + item.items?.forEach { itemChild in if let feedSpecifier = itemChild.feedSpecifier { folder.addFeed(newFeed(with: feedSpecifier)) } @@ -501,7 +501,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, } } - func loadOPMLItems(_ items: [RSOPMLItem]) { + func loadOPMLItems(_ items: [OPMLItem]) { addOPMLItems(OPMLNormalizer.normalize(items)) } @@ -567,7 +567,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, return folders?.first(where: { $0.externalID == externalID }) } - func newFeed(with opmlFeedSpecifier: RSOPMLFeedSpecifier) -> Feed { + func newFeed(with opmlFeedSpecifier: OPMLFeedSpecifier) -> Feed { let feedURL = opmlFeedSpecifier.feedURL let metadata = feedMetadata(feedURL: feedURL, feedID: feedURL) let feed = Feed(account: self, url: opmlFeedSpecifier.feedURL, metadata: metadata) diff --git a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift index a9738d63a..476448bc9 100644 --- a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift +++ b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift @@ -12,7 +12,7 @@ import SystemConfiguration import os.log import SyncDatabase import RSCore -import RSParser +import Parser import Articles import ArticlesDatabase import RSWeb @@ -147,21 +147,14 @@ final class CloudKitAccountDelegate: AccountDelegate { } let parserData = ParserData(url: opmlFile.absoluteString, data: opmlData) - var opmlDocument: RSOPMLDocument? - - do { - opmlDocument = try RSOPMLParser.parseOPML(with: parserData) - } catch { - completion(.failure(error)) - return - } - + let opmlDocument = OPMLParser.document(with: parserData) + guard let loadDocument = opmlDocument else { completion(.success(())) return } - guard let opmlItems = loadDocument.children, let rootExternalID = account.externalID else { + guard let opmlItems = loadDocument.items, let rootExternalID = account.externalID else { return } diff --git a/Account/Sources/Account/CloudKit/CloudKitAccountZone.swift b/Account/Sources/Account/CloudKit/CloudKitAccountZone.swift index 66709a7c7..cf5f96ec7 100644 --- a/Account/Sources/Account/CloudKit/CloudKitAccountZone.swift +++ b/Account/Sources/Account/CloudKit/CloudKitAccountZone.swift @@ -10,7 +10,7 @@ import Foundation import os.log import RSCore import RSWeb -import RSParser +import Parser import CloudKit enum CloudKitAccountZoneError: LocalizedError { @@ -55,11 +55,11 @@ final class CloudKitAccountZone: CloudKitZone { migrateChangeToken() } - func importOPML(rootExternalID: String, items: [RSOPMLItem], completion: @escaping (Result) -> Void) { + func importOPML(rootExternalID: String, items: [OPMLItem], completion: @escaping (Result) -> Void) { var records = [CKRecord]() var feedRecords = [String: CKRecord]() - func processFeed(feedSpecifier: RSOPMLFeedSpecifier, containerExternalID: String) { + func processFeed(feedSpecifier: OPMLFeedSpecifier, containerExternalID: String) { if let feedRecord = feedRecords[feedSpecifier.feedURL], var containerExternalIDs = feedRecord[CloudKitFeed.Fields.containerExternalIDs] as? [String] { containerExternalIDs.append(containerExternalID) feedRecord[CloudKitFeed.Fields.containerExternalIDs] = containerExternalIDs @@ -77,7 +77,7 @@ final class CloudKitAccountZone: CloudKitZone { if let title = item.titleFromAttributes { let containerRecord = newContainerCKRecord(name: title) records.append(containerRecord) - item.children?.forEach { itemChild in + item.items?.forEach { itemChild in if let feedSpecifier = itemChild.feedSpecifier { processFeed(feedSpecifier: feedSpecifier, containerExternalID: containerRecord.externalID) } @@ -344,7 +344,7 @@ final class CloudKitAccountZone: CloudKitZone { private extension CloudKitAccountZone { - func newFeedCKRecord(feedSpecifier: RSOPMLFeedSpecifier, containerExternalID: String) -> CKRecord { + func newFeedCKRecord(feedSpecifier: OPMLFeedSpecifier, containerExternalID: String) -> CKRecord { let record = CKRecord(recordType: CloudKitFeed.recordType, recordID: generateRecordID()) record[CloudKitFeed.Fields.url] = feedSpecifier.feedURL if let editedName = feedSpecifier.title { diff --git a/Account/Sources/Account/CloudKit/CloudKitArticlesZone.swift b/Account/Sources/Account/CloudKit/CloudKitArticlesZone.swift index 87cc57740..9ba65605e 100644 --- a/Account/Sources/Account/CloudKit/CloudKitArticlesZone.swift +++ b/Account/Sources/Account/CloudKit/CloudKitArticlesZone.swift @@ -9,7 +9,7 @@ import Foundation import os.log import RSCore -import RSParser +import Parser import RSWeb import CloudKit import Articles diff --git a/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift b/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift index 96ac57b5b..33bf6e075 100644 --- a/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift +++ b/Account/Sources/Account/CloudKit/CloudKitArticlesZoneDelegate.swift @@ -9,7 +9,7 @@ import Foundation import os.log import RSCore -import RSParser +import Parser import RSWeb import CloudKit import SyncDatabase diff --git a/Account/Sources/Account/DataExtensions.swift b/Account/Sources/Account/DataExtensions.swift index a503ea62d..0c505268b 100644 --- a/Account/Sources/Account/DataExtensions.swift +++ b/Account/Sources/Account/DataExtensions.swift @@ -8,7 +8,7 @@ import Foundation import Articles -import RSParser +import Parser public extension Notification.Name { static let FeedSettingDidChange = Notification.Name(rawValue: "FeedSettingDidChangeNotification") diff --git a/Account/Sources/Account/FeedFinder/FeedFinder.swift b/Account/Sources/Account/FeedFinder/FeedFinder.swift index e81c5160c..9975e2f94 100644 --- a/Account/Sources/Account/FeedFinder/FeedFinder.swift +++ b/Account/Sources/Account/FeedFinder/FeedFinder.swift @@ -7,7 +7,7 @@ // import Foundation -import RSParser +import Parser import RSWeb import RSCore @@ -44,7 +44,7 @@ class FeedFinder { return } - if FeedFinder.isFeed(data, url.absoluteString) { + if FeedFinder.isFeed(data) { let feedSpecifier = FeedSpecifier(title: nil, urlString: url.absoluteString, source: .UserEntered, orderFound: 1) completion(.success(Set([feedSpecifier]))) return @@ -149,7 +149,7 @@ private extension FeedFinder { group.enter() downloadUsingCache(url) { (data, response, error) in if let data = data, let response = response, response.statusIsOK, error == nil { - if self.isFeed(data, downloadFeedSpecifier.urlString) { + if self.isFeed(data) { addFeedSpecifier(downloadFeedSpecifier, feedSpecifiers: &resultFeedSpecifiers) } } @@ -163,8 +163,7 @@ private extension FeedFinder { } } - static func isFeed(_ data: Data, _ urlString: String) -> Bool { - let parserData = ParserData(url: urlString, data: data) - return FeedParser.canParse(parserData) + static func isFeed(_ data: Data) -> Bool { + return FeedParser.canParse(data) } } diff --git a/Account/Sources/Account/FeedFinder/HTMLFeedFinder.swift b/Account/Sources/Account/FeedFinder/HTMLFeedFinder.swift index 7e776f6c0..a35882f4b 100644 --- a/Account/Sources/Account/FeedFinder/HTMLFeedFinder.swift +++ b/Account/Sources/Account/FeedFinder/HTMLFeedFinder.swift @@ -7,7 +7,7 @@ // import Foundation -import RSParser +import Parser private let feedURLWordsToMatch = ["feed", "xml", "rss", "atom", "json"] @@ -20,18 +20,20 @@ class HTMLFeedFinder { private var feedSpecifiersDictionary = [String: FeedSpecifier]() init(parserData: ParserData) { - let metadata = RSHTMLMetadataParser.htmlMetadata(with: parserData) + let metadata = HTMLMetadataParser.metadata(with: parserData) var orderFound = 0 - - for oneFeedLink in metadata.feedLinks { - if let oneURLString = oneFeedLink.urlString?.normalizedURL { - orderFound = orderFound + 1 - let oneFeedSpecifier = FeedSpecifier(title: oneFeedLink.title, urlString: oneURLString, source: .HTMLHead, orderFound: orderFound) - addFeedSpecifier(oneFeedSpecifier) + + if let feedLinks = metadata.feedLinks { + for oneFeedLink in feedLinks { + if let oneURLString = oneFeedLink.urlString?.normalizedURL { + orderFound = orderFound + 1 + let oneFeedSpecifier = FeedSpecifier(title: oneFeedLink.title, urlString: oneURLString, source: .HTMLHead, orderFound: orderFound) + addFeedSpecifier(oneFeedSpecifier) + } } } - let bodyLinks = RSHTMLLinkParser.htmlLinks(with: parserData) + let bodyLinks = HTMLLinkParser.htmlLinks(with: parserData) for oneBodyLink in bodyLinks { if linkMightBeFeed(oneBodyLink), let normalizedURL = oneBodyLink.urlString?.normalizedURL { orderFound = orderFound + 1 @@ -69,7 +71,7 @@ private extension HTMLFeedFinder { return false } - func linkMightBeFeed(_ link: RSHTMLLink) -> Bool { + func linkMightBeFeed(_ link: HTMLLink) -> Bool { if let linkURLString = link.urlString, urlStringMightBeFeed(linkURLString) { return true } diff --git a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift index 4425d4276..95588028f 100644 --- a/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Account/Sources/Account/Feedbin/FeedbinAccountDelegate.swift @@ -6,10 +6,11 @@ // Copyright © 2019 Ranchero Software, LLC. All rights reserved. // +import Foundation import Articles import RSCore import RSDatabase -import RSParser +import Parser import RSWeb import SyncDatabase import os.log diff --git a/Account/Sources/Account/Feedbin/FeedbinEntry.swift b/Account/Sources/Account/Feedbin/FeedbinEntry.swift index 27e23a140..87e815f56 100644 --- a/Account/Sources/Account/Feedbin/FeedbinEntry.swift +++ b/Account/Sources/Account/Feedbin/FeedbinEntry.swift @@ -7,7 +7,7 @@ // import Foundation -import RSParser +import Parser import RSCore final class FeedbinEntry: Decodable { @@ -29,7 +29,7 @@ final class FeedbinEntry: Decodable { // and letting the one date fail when parsed. lazy var parsedDatePublished: Date? = { if let datePublished = datePublished { - return RSDateWithString(datePublished) + return DateParser.date(string: datePublished) } else { return nil diff --git a/Account/Sources/Account/Feedbin/FeedbinSubscription.swift b/Account/Sources/Account/Feedbin/FeedbinSubscription.swift index d789d1deb..d593f2bef 100644 --- a/Account/Sources/Account/Feedbin/FeedbinSubscription.swift +++ b/Account/Sources/Account/Feedbin/FeedbinSubscription.swift @@ -8,7 +8,7 @@ import Foundation import RSCore -import RSParser +import Parser struct FeedbinSubscription: Hashable, Codable { diff --git a/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift b/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift index d7cc77290..bbc1f1382 100644 --- a/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift +++ b/Account/Sources/Account/Feedly/FeedlyAccountDelegate.swift @@ -6,9 +6,10 @@ // Copyright © 2019 Ranchero Software, LLC. All rights reserved. // +import Foundation import Articles import RSCore -import RSParser +import Parser import RSWeb import SyncDatabase import os.log diff --git a/Account/Sources/Account/Feedly/Models/FeedlyEntryParser.swift b/Account/Sources/Account/Feedly/Models/FeedlyEntryParser.swift index 3e1149e25..3b0b9bc35 100644 --- a/Account/Sources/Account/Feedly/Models/FeedlyEntryParser.swift +++ b/Account/Sources/Account/Feedly/Models/FeedlyEntryParser.swift @@ -8,7 +8,7 @@ import Foundation import Articles -import RSParser +import Parser struct FeedlyEntryParser { let entry: FeedlyEntry diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyGetEntriesOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyGetEntriesOperation.swift index 87a17da28..46e78a087 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyGetEntriesOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyGetEntriesOperation.swift @@ -8,7 +8,7 @@ import Foundation import os.log -import RSParser +import Parser /// Get full entries for the entry identifiers. final class FeedlyGetEntriesOperation: FeedlyOperation, FeedlyEntryProviding, FeedlyParsedItemProviding { diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyGetStreamContentsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyGetStreamContentsOperation.swift index 7cdde6576..4d2b7ba7b 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyGetStreamContentsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyGetStreamContentsOperation.swift @@ -7,7 +7,7 @@ // import Foundation -import RSParser +import Parser import os.log protocol FeedlyEntryProviding { diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift index a06ebe0f5..fbadb88e9 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIdsOperation.swift @@ -8,7 +8,7 @@ import Foundation import os.log -import RSParser +import Parser import SyncDatabase import Secrets diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyOrganiseParsedItemsByFeedOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyOrganiseParsedItemsByFeedOperation.swift index a55ea1839..9246e38f0 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyOrganiseParsedItemsByFeedOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyOrganiseParsedItemsByFeedOperation.swift @@ -7,7 +7,7 @@ // import Foundation -import RSParser +import Parser import os.log protocol FeedlyParsedItemsByFeedProviding { diff --git a/Account/Sources/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift index ef1770967..3dadd607d 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift @@ -8,7 +8,7 @@ import Foundation import os.log -import RSParser +import Parser import RSCore import RSWeb import Secrets diff --git a/Account/Sources/Account/Feedly/Operations/FeedlyUpdateAccountFeedsWithItemsOperation.swift b/Account/Sources/Account/Feedly/Operations/FeedlyUpdateAccountFeedsWithItemsOperation.swift index ea8dcace4..9a38a46c9 100644 --- a/Account/Sources/Account/Feedly/Operations/FeedlyUpdateAccountFeedsWithItemsOperation.swift +++ b/Account/Sources/Account/Feedly/Operations/FeedlyUpdateAccountFeedsWithItemsOperation.swift @@ -7,7 +7,7 @@ // import Foundation -import RSParser +import Parser import os.log /// Combine the articles with their feeds for a specific account. diff --git a/Account/Sources/Account/LocalAccount/InitialFeedDownloader.swift b/Account/Sources/Account/LocalAccount/InitialFeedDownloader.swift index 34b1ddea3..8850ca8ff 100644 --- a/Account/Sources/Account/LocalAccount/InitialFeedDownloader.swift +++ b/Account/Sources/Account/LocalAccount/InitialFeedDownloader.swift @@ -7,7 +7,7 @@ // import Foundation -import RSParser +import Parser import RSWeb struct InitialFeedDownloader { @@ -20,9 +20,11 @@ struct InitialFeedDownloader { return } - let parserData = ParserData(url: url.absoluteString, data: data) - FeedParser.parse(parserData) { (parsedFeed, error) in - completion(parsedFeed) + Task.detached { + let parsedFeed = try? FeedParser.parse(urlString: url.absoluteString, data: data) + Task { @MainActor in + completion(parsedFeed) + } } } } diff --git a/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift b/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift index ddd60afb8..aebf6dd5f 100644 --- a/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift +++ b/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift @@ -9,7 +9,7 @@ import Foundation import os.log import RSCore -import RSParser +import Parser import Articles import ArticlesDatabase import RSWeb @@ -96,21 +96,13 @@ final class LocalAccountDelegate: AccountDelegate { } let parserData = ParserData(url: opmlFile.absoluteString, data: opmlData) - var opmlDocument: RSOPMLDocument? - - do { - opmlDocument = try RSOPMLParser.parseOPML(with: parserData) - } catch { - completion(.failure(error)) - return - } - + let opmlDocument = OPMLParser.document(with: parserData) guard let loadDocument = opmlDocument else { completion(.success(())) return } - guard let children = loadDocument.children else { + guard let children = loadDocument.items else { return } diff --git a/Account/Sources/Account/LocalAccount/LocalAccountRefresher.swift b/Account/Sources/Account/LocalAccount/LocalAccountRefresher.swift index 20af6aee4..c8ca9dbdf 100644 --- a/Account/Sources/Account/LocalAccount/LocalAccountRefresher.swift +++ b/Account/Sources/Account/LocalAccount/LocalAccountRefresher.swift @@ -8,7 +8,7 @@ import Foundation import RSCore -import RSParser +import Parser import RSWeb import Articles import ArticlesDatabase diff --git a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift b/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift index 6f58ffd11..7a905e7e9 100644 --- a/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift +++ b/Account/Sources/Account/NewsBlur/Internals/NewsBlurAccountDelegate+Internal.swift @@ -7,10 +7,11 @@ // Copyright (c) 2020 Ranchero Software, LLC. All rights reserved. // +import Foundation import Articles import RSCore import RSDatabase -import RSParser +import Parser import RSWeb import SyncDatabase import os.log diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurFeed.swift b/Account/Sources/Account/NewsBlur/Models/NewsBlurFeed.swift index f0b0300bb..74b484cfc 100644 --- a/Account/Sources/Account/NewsBlur/Models/NewsBlurFeed.swift +++ b/Account/Sources/Account/NewsBlur/Models/NewsBlurFeed.swift @@ -8,7 +8,7 @@ import Foundation import RSCore -import RSParser +import Parser typealias NewsBlurFolder = NewsBlurFeedsResponse.Folder diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurStory.swift b/Account/Sources/Account/NewsBlur/Models/NewsBlurStory.swift index e4878b287..45895e785 100644 --- a/Account/Sources/Account/NewsBlur/Models/NewsBlurStory.swift +++ b/Account/Sources/Account/NewsBlur/Models/NewsBlurStory.swift @@ -8,7 +8,7 @@ import Foundation import RSCore -import RSParser +import Parser typealias NewsBlurStory = NewsBlurStoriesResponse.Story diff --git a/Account/Sources/Account/NewsBlur/Models/NewsBlurStoryHash.swift b/Account/Sources/Account/NewsBlur/Models/NewsBlurStoryHash.swift index 48286df00..436b8a3cc 100644 --- a/Account/Sources/Account/NewsBlur/Models/NewsBlurStoryHash.swift +++ b/Account/Sources/Account/NewsBlur/Models/NewsBlurStoryHash.swift @@ -8,7 +8,7 @@ import Foundation import RSCore -import RSParser +import Parser typealias NewsBlurStoryHash = NewsBlurStoryHashesResponse.StoryHash diff --git a/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift b/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift index efd498d84..ae3698b80 100644 --- a/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift +++ b/Account/Sources/Account/NewsBlur/NewsBlurAccountDelegate.swift @@ -6,10 +6,11 @@ // Copyright (c) 2020 Ranchero Software, LLC. All rights reserved. // +import Foundation import Articles import RSCore import RSDatabase -import RSParser +import Parser import RSWeb import SyncDatabase import os.log diff --git a/Account/Sources/Account/OPMLFile.swift b/Account/Sources/Account/OPMLFile.swift index 134358c35..458ca5d2e 100644 --- a/Account/Sources/Account/OPMLFile.swift +++ b/Account/Sources/Account/OPMLFile.swift @@ -9,7 +9,7 @@ import Foundation import os.log import RSCore -import RSParser +import Parser final class OPMLFile { @@ -82,18 +82,15 @@ private extension OPMLFile { return fileData } - func parsedOPMLItems(fileData: Data) -> [RSOPMLItem]? { - let parserData = ParserData(url: fileURL.absoluteString, data: fileData) - var opmlDocument: RSOPMLDocument? + func parsedOPMLItems(fileData: Data) -> [OPMLItem]? { - do { - opmlDocument = try RSOPMLParser.parseOPML(with: parserData) - } catch { - os_log(.error, log: log, "OPML Import failed: %@.", error.localizedDescription) + let parserData = ParserData(url: fileURL.absoluteString, data: fileData) + guard let opmlDocument = OPMLParser.document(with: parserData) else { + os_log(.error, log: log, "OPML Import failed") return nil } - - return opmlDocument?.children + + return opmlDocument.items } func opmlDocument() -> String { diff --git a/Account/Sources/Account/OPMLNormalizer.swift b/Account/Sources/Account/OPMLNormalizer.swift index 77f6ee54b..2f5fa8b37 100644 --- a/Account/Sources/Account/OPMLNormalizer.swift +++ b/Account/Sources/Account/OPMLNormalizer.swift @@ -7,20 +7,20 @@ // import Foundation -import RSParser +import Parser final class OPMLNormalizer { - var normalizedOPMLItems = [RSOPMLItem]() + var normalizedOPMLItems = [OPMLItem]() - static func normalize(_ items: [RSOPMLItem]) -> [RSOPMLItem] { + static func normalize(_ items: [OPMLItem]) -> [OPMLItem] { let opmlNormalizer = OPMLNormalizer() opmlNormalizer.normalize(items) return opmlNormalizer.normalizedOPMLItems } - private func normalize(_ items: [RSOPMLItem], parentFolder: RSOPMLItem? = nil) { - var feedsToAdd = [RSOPMLItem]() + private func normalize(_ items: [OPMLItem], parentFolder: OPMLItem? = nil) { + var feedsToAdd = [OPMLItem]() items.forEach { (item) in @@ -33,14 +33,14 @@ final class OPMLNormalizer { guard let _ = item.titleFromAttributes else { // Folder doesn’t have a name, so it won’t be created, and its items will go one level up. - if let itemChildren = item.children { + if let itemChildren = item.items { normalize(itemChildren, parentFolder: parentFolder) } return } feedsToAdd.append(item) - if let itemChildren = item.children { + if let itemChildren = item.items { if let parentFolder = parentFolder { normalize(itemChildren, parentFolder: parentFolder) } else { @@ -51,8 +51,8 @@ final class OPMLNormalizer { if let parentFolder = parentFolder { for feed in feedsToAdd { - if !(parentFolder.children?.contains(where: { $0.feedSpecifier?.feedURL == feed.feedSpecifier?.feedURL}) ?? false) { - parentFolder.addChild(feed) + if !(parentFolder.items?.contains(where: { $0.feedSpecifier?.feedURL == feed.feedSpecifier?.feedURL}) ?? false) { + parentFolder.add(feed) } } } else { diff --git a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift index bc3743c99..c7c351f27 100644 --- a/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift +++ b/Account/Sources/Account/ReaderAPI/ReaderAPIAccountDelegate.swift @@ -6,9 +6,10 @@ // Copyright © 2019 Ranchero Software, LLC. All rights reserved. // +import Foundation import Articles import RSCore -import RSParser +import Parser import RSWeb import SyncDatabase import os.log diff --git a/Account/Sources/Account/ReaderAPI/ReaderAPIEntry.swift b/Account/Sources/Account/ReaderAPI/ReaderAPIEntry.swift index 93de146f8..9ca114bf6 100644 --- a/Account/Sources/Account/ReaderAPI/ReaderAPIEntry.swift +++ b/Account/Sources/Account/ReaderAPI/ReaderAPIEntry.swift @@ -7,7 +7,7 @@ // import Foundation -import RSParser +import Parser import RSCore struct ReaderAPIEntryWrapper: Codable { diff --git a/Account/Sources/Account/ReaderAPI/ReaderAPISubscription.swift b/Account/Sources/Account/ReaderAPI/ReaderAPISubscription.swift index e74491ca6..334251f98 100644 --- a/Account/Sources/Account/ReaderAPI/ReaderAPISubscription.swift +++ b/Account/Sources/Account/ReaderAPI/ReaderAPISubscription.swift @@ -8,7 +8,7 @@ import Foundation import RSCore -import RSParser +import Parser /* diff --git a/Account/Tests/AccountTests/Feedly/FeedlyOrganiseParsedItemsByFeedOperationTests.swift b/Account/Tests/AccountTests/Feedly/FeedlyOrganiseParsedItemsByFeedOperationTests.swift index 654e9a3b0..b7d2fce2c 100644 --- a/Account/Tests/AccountTests/Feedly/FeedlyOrganiseParsedItemsByFeedOperationTests.swift +++ b/Account/Tests/AccountTests/Feedly/FeedlyOrganiseParsedItemsByFeedOperationTests.swift @@ -8,7 +8,7 @@ import XCTest @testable import Account -import RSParser +import Parser import RSCore class FeedlyOrganiseParsedItemsByFeedOperationTests: XCTestCase { diff --git a/Account/Tests/AccountTests/Feedly/FeedlyTestSupport.swift b/Account/Tests/AccountTests/Feedly/FeedlyTestSupport.swift index 34432fcd9..70e7207a0 100644 --- a/Account/Tests/AccountTests/Feedly/FeedlyTestSupport.swift +++ b/Account/Tests/AccountTests/Feedly/FeedlyTestSupport.swift @@ -7,7 +7,7 @@ // import XCTest -import RSParser +import Parser import Secrets @testable import Account import os.log diff --git a/ArticlesDatabase/Package.swift b/ArticlesDatabase/Package.swift index aef384892..918b308cf 100644 --- a/ArticlesDatabase/Package.swift +++ b/ArticlesDatabase/Package.swift @@ -13,7 +13,7 @@ let package = Package( ], dependencies: [ .package(path: "../RSDatabase"), - .package(path: "../RSParser"), + .package(path: "../Parser"), .package(path: "../RSCore"), .package(path: "../Articles"), ], @@ -23,7 +23,7 @@ let package = Package( dependencies: [ "RSCore", "RSDatabase", - "RSParser", + "Parser", "Articles", ], swiftSettings: [.unsafeFlags(["-warnings-as-errors"])] diff --git a/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesDatabase.swift b/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesDatabase.swift index 2e7a36fac..93b025c2b 100644 --- a/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesDatabase.swift +++ b/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesDatabase.swift @@ -9,7 +9,7 @@ import Foundation import RSCore import RSDatabase -import RSParser +import Parser import Articles // This file is the entirety of the public API for ArticlesDatabase.framework. diff --git a/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesTable.swift b/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesTable.swift index 3c09d40a4..7ba0f274c 100644 --- a/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesTable.swift +++ b/ArticlesDatabase/Sources/ArticlesDatabase/ArticlesTable.swift @@ -10,7 +10,7 @@ import Foundation import RSCore import RSDatabase import RSDatabaseObjC -import RSParser +import Parser import Articles final class ArticlesTable: DatabaseTable { diff --git a/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/Article+Database.swift b/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/Article+Database.swift index 48063d9d5..4e1d4411e 100644 --- a/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/Article+Database.swift +++ b/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/Article+Database.swift @@ -10,7 +10,7 @@ import Foundation import RSDatabase import RSDatabaseObjC import Articles -import RSParser +import Parser extension Article { diff --git a/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/Author+Database.swift b/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/Author+Database.swift index 069642702..2707d6009 100644 --- a/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/Author+Database.swift +++ b/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/Author+Database.swift @@ -10,7 +10,7 @@ import Foundation import Articles import RSDatabase import RSDatabaseObjC -import RSParser +import Parser // MARK: - DatabaseObject diff --git a/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/ParsedArticle+Database.swift b/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/ParsedArticle+Database.swift index 271876057..220aa3db1 100644 --- a/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/ParsedArticle+Database.swift +++ b/ArticlesDatabase/Sources/ArticlesDatabase/Extensions/ParsedArticle+Database.swift @@ -7,7 +7,7 @@ // import Foundation -import RSParser +import Parser import Articles extension ParsedItem { diff --git a/ArticlesDatabase/Sources/ArticlesDatabase/SearchTable.swift b/ArticlesDatabase/Sources/ArticlesDatabase/SearchTable.swift index ed08439f4..4cf11fd35 100644 --- a/ArticlesDatabase/Sources/ArticlesDatabase/SearchTable.swift +++ b/ArticlesDatabase/Sources/ArticlesDatabase/SearchTable.swift @@ -11,7 +11,7 @@ import RSCore import RSDatabase import RSDatabaseObjC import Articles -import RSParser +import Parser final class ArticleSearchInfo: Hashable { @@ -34,7 +34,7 @@ final class ArticleSearchInfo: Hashable { } lazy var bodyForIndex: String = { - let s = preferredText.rsparser_stringByDecodingHTMLEntities() + let s = HTMLEntityDecoder.decodedString(preferredText) let sanitizedBody = s.strippingHTML().collapsingWhitespace if let authorsNames = authorsNames { diff --git a/Mac/MainWindow/AddFeed/AddFeedController.swift b/Mac/MainWindow/AddFeed/AddFeedController.swift index ade553250..09000604e 100644 --- a/Mac/MainWindow/AddFeed/AddFeedController.swift +++ b/Mac/MainWindow/AddFeed/AddFeedController.swift @@ -12,7 +12,7 @@ import RSCoreResources import RSTree import Articles import Account -import RSParser +import Parser // Run add-feed sheet. // If it returns with URL and optional name, diff --git a/Mac/Scriptability/WebFeed+Scriptability.swift b/Mac/Scriptability/WebFeed+Scriptability.swift index a45f7e8dc..59387c7ec 100644 --- a/Mac/Scriptability/WebFeed+Scriptability.swift +++ b/Mac/Scriptability/WebFeed+Scriptability.swift @@ -7,7 +7,7 @@ // import Foundation -import RSParser +import Parser import Account import Articles @@ -95,7 +95,7 @@ class ScriptableFeed: NSObject, UniqueIdScriptingObject, ScriptingObjectContaine let container: Container = folder != nil ? folder! : account // We need to download the feed and parse it. - // RSParser does the callback for the download on the main thread. + // Parser does the callback for the download on the main thread. // Because we can't wait here (on the main thread) for the callback, we have to return from this function. // Generally, returning from an AppleEvent handler function means that handling the Apple event is over, // but we don’t yet have the result of the event yet, so we prevent the Apple event from returning by calling diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index e9f960124..aab2c8386 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -414,7 +414,6 @@ 84C1ECEB2CDFE49100C7456A /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( - Images/FeaturedImageDownloader.swift, Resources/NewsFax.nnwtheme, Secrets.swift.gyb, ShareExtension/SafariExt.js, @@ -433,7 +432,6 @@ ExtensionPoints/SendToMarsEditCommand.swift, ExtensionPoints/SendToMicroBlogCommand.swift, "Extensions/NSView-Extensions.swift", - Images/FeaturedImageDownloader.swift, Secrets.swift.gyb, ShareExtension/SafariExt.js, ShareExtension/ShareDefaultContainer.swift, @@ -672,8 +670,8 @@ 51CD32C324D2CD57009ABAEF /* ArticlesDatabase */, 51CD32C724D2E06C009ABAEF /* Secrets */, 51CD32A824D2CB25009ABAEF /* SyncDatabase */, - 8417FA3E2CDF2E31005F989B /* RSDatabase */, 849E61B82CE85D09008AF514 /* Parser */, + 8417FA3E2CDF2E31005F989B /* RSDatabase */, 847C4C0C2CDF22DD008BF5FE /* RSTree */, 8413878C2CDC78EE00E8490F /* RSWeb */, 8413876B2CD896E000E8490F /* RSCore */, diff --git a/Parser/Sources/Parser/FeedParser/Feeds/FeedParser.swift b/Parser/Sources/Parser/FeedParser/Feeds/FeedParser.swift index ea91797bb..a8bc64c55 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/FeedParser.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/FeedParser.swift @@ -1,6 +1,6 @@ // // FeedParser.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/20/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. @@ -50,6 +50,22 @@ public struct FeedParser { } } + public static func parse(_ parserData: ParserData, _ completion: @Sendable @escaping (ParsedFeed?, Error?) -> Void) { + + Task { + do { + let parsedFeed = try await parseAsync(urlString: parserData.url, data: parserData.data) + Task { @MainActor in + completion(parsedFeed, nil) + } + } catch { + Task { @MainActor in + completion(nil, error) + } + } + } + } + public static func parseAsync(urlString: String, data: Data) async throws -> ParsedFeed? { try parse(urlString: urlString, data: data) diff --git a/Parser/Sources/Parser/FeedParser/Feeds/FeedParserError.swift b/Parser/Sources/Parser/FeedParser/Feeds/FeedParserError.swift index 01185b1b9..51d1bef20 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/FeedParserError.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/FeedParserError.swift @@ -1,6 +1,6 @@ // // FeedParserError.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/24/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/FeedType.swift b/Parser/Sources/Parser/FeedParser/Feeds/FeedType.swift index 21d70539d..40a535e2a 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/FeedType.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/FeedType.swift @@ -1,6 +1,6 @@ // // FeedType.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/20/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/JSON/JSONFeedParser.swift b/Parser/Sources/Parser/FeedParser/Feeds/JSON/JSONFeedParser.swift index a8665af2e..f0f2568f1 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/JSON/JSONFeedParser.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/JSON/JSONFeedParser.swift @@ -1,6 +1,6 @@ // // JSONFeedParser.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/25/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/JSON/RSSInJSONParser.swift b/Parser/Sources/Parser/FeedParser/Feeds/JSON/RSSInJSONParser.swift index df7507f67..5b685bb3c 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/JSON/RSSInJSONParser.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/JSON/RSSInJSONParser.swift @@ -1,6 +1,6 @@ // // RSSInJSONParser.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/24/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/ParsedAttachment.swift b/Parser/Sources/Parser/FeedParser/Feeds/ParsedAttachment.swift index a3c3cb4f5..febb32373 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/ParsedAttachment.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/ParsedAttachment.swift @@ -1,6 +1,6 @@ // // ParsedAttachment.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/20/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/ParsedAuthor.swift b/Parser/Sources/Parser/FeedParser/Feeds/ParsedAuthor.swift index 260eece16..67672655a 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/ParsedAuthor.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/ParsedAuthor.swift @@ -1,6 +1,6 @@ // // ParsedAuthor.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/20/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/ParsedFeed.swift b/Parser/Sources/Parser/FeedParser/Feeds/ParsedFeed.swift index b19e9b03c..38c589be9 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/ParsedFeed.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/ParsedFeed.swift @@ -1,6 +1,6 @@ // // ParsedFeed.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/20/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/ParsedHub.swift b/Parser/Sources/Parser/FeedParser/Feeds/ParsedHub.swift index abd687467..b959860b0 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/ParsedHub.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/ParsedHub.swift @@ -1,6 +1,6 @@ // // ParsedHub.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/20/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/ParsedItem.swift b/Parser/Sources/Parser/FeedParser/Feeds/ParsedItem.swift index 2c3057835..7ec988e8f 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/ParsedItem.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/ParsedItem.swift @@ -1,6 +1,6 @@ // // ParsedItem.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/20/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/XML/AtomParser.swift b/Parser/Sources/Parser/FeedParser/Feeds/XML/AtomParser.swift index 7b44dede8..223e0b027 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/XML/AtomParser.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/XML/AtomParser.swift @@ -1,6 +1,6 @@ // // AtomParser.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/25/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/XML/RSSFeedTransformer.swift b/Parser/Sources/Parser/FeedParser/Feeds/XML/RSSFeedTransformer.swift index 4264a12f5..e978687de 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/XML/RSSFeedTransformer.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/XML/RSSFeedTransformer.swift @@ -1,6 +1,6 @@ // // RSSFeedTransformer.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/25/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/Feeds/XML/RSSParser.swift b/Parser/Sources/Parser/FeedParser/Feeds/XML/RSSParser.swift index dee652fc1..57afcd803 100644 --- a/Parser/Sources/Parser/FeedParser/Feeds/XML/RSSParser.swift +++ b/Parser/Sources/Parser/FeedParser/Feeds/XML/RSSParser.swift @@ -1,6 +1,6 @@ // // RSSParser.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/25/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/JSON/JSONTypes.swift b/Parser/Sources/Parser/FeedParser/JSON/JSONTypes.swift index fa3039a31..f34e3c70a 100644 --- a/Parser/Sources/Parser/FeedParser/JSON/JSONTypes.swift +++ b/Parser/Sources/Parser/FeedParser/JSON/JSONTypes.swift @@ -1,6 +1,6 @@ // // JSONDictionary.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/24/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/FeedParser/JSON/JSONUtilities.swift b/Parser/Sources/Parser/FeedParser/JSON/JSONUtilities.swift index 2319e0389..a092074c6 100644 --- a/Parser/Sources/Parser/FeedParser/JSON/JSONUtilities.swift +++ b/Parser/Sources/Parser/FeedParser/JSON/JSONUtilities.swift @@ -1,6 +1,6 @@ // // JSONUtilities.swift -// RSParser +// Parser // // Created by Brent Simmons on 12/10/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Sources/Parser/SAX/Extensions/String+SAX.swift b/Parser/Sources/Parser/SAX/Extensions/String+SAX.swift index 8a5882498..8a90c80c2 100644 --- a/Parser/Sources/Parser/SAX/Extensions/String+SAX.swift +++ b/Parser/Sources/Parser/SAX/Extensions/String+SAX.swift @@ -1,6 +1,6 @@ // -// String+RSParser.swift -// RSParser +// String+Parser.swift +// Parser // // Created by Nate Weaver on 2020-01-19. // Copyright © 2020 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Tests/ParserTests/AtomParserTests.swift b/Parser/Tests/ParserTests/AtomParserTests.swift index 94fd6cbe0..d23930bbe 100644 --- a/Parser/Tests/ParserTests/AtomParserTests.swift +++ b/Parser/Tests/ParserTests/AtomParserTests.swift @@ -1,6 +1,6 @@ // // AtomParserTests.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/26/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Tests/ParserTests/EntityDecodingTests.swift b/Parser/Tests/ParserTests/EntityDecodingTests.swift index 04761ab35..7eb29816f 100644 --- a/Parser/Tests/ParserTests/EntityDecodingTests.swift +++ b/Parser/Tests/ParserTests/EntityDecodingTests.swift @@ -1,6 +1,6 @@ // // EntityDecodingTests.swift -// RSParserTests +// ParserTests // // Created by Brent Simmons on 12/30/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Tests/ParserTests/FeedParserTypeTests.swift b/Parser/Tests/ParserTests/FeedParserTypeTests.swift index 3649e5acd..2a072709f 100644 --- a/Parser/Tests/ParserTests/FeedParserTypeTests.swift +++ b/Parser/Tests/ParserTests/FeedParserTypeTests.swift @@ -1,6 +1,6 @@ // // FeedParserTypeTests.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/25/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Tests/ParserTests/HTMLLinkTests.swift b/Parser/Tests/ParserTests/HTMLLinkTests.swift index 7e7c69acc..e1cd6a8c8 100644 --- a/Parser/Tests/ParserTests/HTMLLinkTests.swift +++ b/Parser/Tests/ParserTests/HTMLLinkTests.swift @@ -1,6 +1,6 @@ // // HTMLLinkTests.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/25/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Tests/ParserTests/HTMLMetadataTests.swift b/Parser/Tests/ParserTests/HTMLMetadataTests.swift index 6adc5de7f..eb339fa29 100644 --- a/Parser/Tests/ParserTests/HTMLMetadataTests.swift +++ b/Parser/Tests/ParserTests/HTMLMetadataTests.swift @@ -1,6 +1,6 @@ // // HTMLMetadataTests.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/25/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Tests/ParserTests/JSONFeedParserTests.swift b/Parser/Tests/ParserTests/JSONFeedParserTests.swift index f96dde79e..9dfca7e53 100644 --- a/Parser/Tests/ParserTests/JSONFeedParserTests.swift +++ b/Parser/Tests/ParserTests/JSONFeedParserTests.swift @@ -1,6 +1,6 @@ // // JSONFeedParserTests.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/26/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Tests/ParserTests/OPMLTests.swift b/Parser/Tests/ParserTests/OPMLTests.swift index 563cd149e..1e7efb724 100644 --- a/Parser/Tests/ParserTests/OPMLTests.swift +++ b/Parser/Tests/ParserTests/OPMLTests.swift @@ -1,6 +1,6 @@ // // OPMLTests.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/25/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Tests/ParserTests/RSSInJSONParserTests.swift b/Parser/Tests/ParserTests/RSSInJSONParserTests.swift index 240076af2..9aaa3902d 100644 --- a/Parser/Tests/ParserTests/RSSInJSONParserTests.swift +++ b/Parser/Tests/ParserTests/RSSInJSONParserTests.swift @@ -1,6 +1,6 @@ // // RSSInJSONParserTests.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/26/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/Tests/ParserTests/RSSParserTests.swift b/Parser/Tests/ParserTests/RSSParserTests.swift index fef062e89..5b1344cad 100644 --- a/Parser/Tests/ParserTests/RSSParserTests.swift +++ b/Parser/Tests/ParserTests/RSSParserTests.swift @@ -1,6 +1,6 @@ // // RSSParserTests.swift -// RSParser +// Parser // // Created by Brent Simmons on 6/26/17. // Copyright © 2017 Ranchero Software, LLC. All rights reserved. diff --git a/Parser/.swiftpm/xcode/xcshareddata/xcschemes/Parser 1.xcscheme b/RSDatabase/.swiftpm/xcode/xcshareddata/xcschemes/RSDatabase.xcscheme similarity index 88% rename from Parser/.swiftpm/xcode/xcshareddata/xcschemes/Parser 1.xcscheme rename to RSDatabase/.swiftpm/xcode/xcshareddata/xcschemes/RSDatabase.xcscheme index 5fa516150..fa933c531 100644 --- a/Parser/.swiftpm/xcode/xcshareddata/xcschemes/Parser 1.xcscheme +++ b/RSDatabase/.swiftpm/xcode/xcshareddata/xcschemes/RSDatabase.xcscheme @@ -15,9 +15,9 @@ buildForAnalyzing = "YES"> @@ -50,9 +50,9 @@ diff --git a/Shared/Extensions/ArticleStringFormatter.swift b/Shared/Extensions/ArticleStringFormatter.swift index dac926b34..a331f4adf 100644 --- a/Shared/Extensions/ArticleStringFormatter.swift +++ b/Shared/Extensions/ArticleStringFormatter.swift @@ -8,7 +8,7 @@ import Foundation import Articles -import RSParser +import Parser struct ArticleStringFormatter { @@ -66,7 +66,7 @@ struct ArticleStringFormatter { s = s.replacingOccurrences(of: "\t", with: "") if !forHTML { - s = s.rsparser_stringByDecodingHTMLEntities() + s = HTMLEntityDecoder.decodedString(s) } s = s.trimmingWhitespace @@ -98,7 +98,7 @@ struct ArticleStringFormatter { if let cachedBody = summaryCache[key] { return cachedBody } - var s = body.rsparser_stringByDecodingHTMLEntities() + var s = HTMLEntityDecoder.decodedString(body) s = s.strippingHTML(maxCharacters: 250) s = s.trimmingWhitespace s = s.collapsingWhitespace diff --git a/Shared/Extensions/NSAttributedString+NetNewsWire.swift b/Shared/Extensions/NSAttributedString+NetNewsWire.swift index fc8b9e57d..4a65072ee 100644 --- a/Shared/Extensions/NSAttributedString+NetNewsWire.swift +++ b/Shared/Extensions/NSAttributedString+NetNewsWire.swift @@ -6,7 +6,7 @@ // Copyright © 2020 Ranchero Software. All rights reserved. // -import RSParser +import Parser #if canImport(AppKit) import AppKit @@ -310,6 +310,6 @@ private struct CountedSet where Element: Hashable { private extension String { var decodedEntity: String { // It's possible the implementation will change, but for now it just calls this. - (self as NSString).rsparser_stringByDecodingHTMLEntities() as String + HTMLEntityDecoder.decodedString(self) } } diff --git a/Shared/Favicons/FaviconURLFinder.swift b/Shared/Favicons/FaviconURLFinder.swift index 9203f16c4..a5beaafd1 100644 --- a/Shared/Favicons/FaviconURLFinder.swift +++ b/Shared/Favicons/FaviconURLFinder.swift @@ -8,7 +8,7 @@ import Foundation import CoreServices -import RSParser +import Parser import UniformTypeIdentifiers // The favicon URLs may be specified in the head section of the home page. @@ -20,7 +20,7 @@ struct FaviconURLFinder { /// - homePageURL: The page to search. /// - completion: A closure called when the links have been found. /// - urls: An array of favicon URLs as strings. - static func findFaviconURLs(with homePageURL: String, _ completion: @escaping (_ urls: [String]?) -> Void) { + static func findFaviconURLs(with homePageURL: String, _ completion: @escaping ([String]?) -> Void) { guard let _ = URL(string: homePageURL) else { completion(nil) @@ -29,7 +29,13 @@ struct FaviconURLFinder { // If the favicon has an explicit type, check that for an ignored type; otherwise, check the file extension. HTMLMetadataDownloader.downloadMetadata(for: homePageURL) { (htmlMetadata) in - let faviconURLs = htmlMetadata?.favicons.compactMap { + + guard let favicons = htmlMetadata?.favicons else { + completion(nil) + return + } + + let faviconURLs = favicons.compactMap { shouldAllowFavicon($0) ? $0.urlString : nil } @@ -39,7 +45,7 @@ struct FaviconURLFinder { private static let ignoredTypes = [UTType.svg] - private static func shouldAllowFavicon(_ favicon: RSHTMLMetadataFavicon) -> Bool { + private static func shouldAllowFavicon(_ favicon: HTMLMetadataFavicon) -> Bool { // Check mime type. if let mimeType = favicon.type, let utType = UTType(mimeType: mimeType) { diff --git a/Shared/HTMLMetadata/HTMLMetadataDownloader.swift b/Shared/HTMLMetadata/HTMLMetadataDownloader.swift index 40651d420..b3f5ec2b7 100644 --- a/Shared/HTMLMetadata/HTMLMetadataDownloader.swift +++ b/Shared/HTMLMetadata/HTMLMetadataDownloader.swift @@ -8,13 +8,13 @@ import Foundation import RSWeb -import RSParser +import Parser struct HTMLMetadataDownloader { static let serialDispatchQueue = DispatchQueue(label: "HTMLMetadataDownloader") - static func downloadMetadata(for url: String, _ completion: @escaping (RSHTMLMetadata?) -> Void) { + static func downloadMetadata(for url: String, _ completion: @escaping (HTMLMetadata?) -> Void) { guard let actualURL = URL(string: url) else { completion(nil) return @@ -32,9 +32,9 @@ struct HTMLMetadataDownloader { } } - private static func parseMetadata(with parserData: ParserData, _ completion: @escaping (RSHTMLMetadata?) -> Void) { + private static func parseMetadata(with parserData: ParserData, _ completion: @escaping (HTMLMetadata?) -> Void) { serialDispatchQueue.async { - let htmlMetadata = RSHTMLMetadataParser.htmlMetadata(with: parserData) + let htmlMetadata = HTMLMetadataParser.metadata(with: parserData) DispatchQueue.main.async { completion(htmlMetadata) } diff --git a/Shared/Images/FeedIconDownloader.swift b/Shared/Images/FeedIconDownloader.swift index c18b179ff..637332e78 100644 --- a/Shared/Images/FeedIconDownloader.swift +++ b/Shared/Images/FeedIconDownloader.swift @@ -11,7 +11,7 @@ import Articles import Account import RSCore import RSWeb -import RSParser +import Parser extension Notification.Name { @@ -214,7 +214,7 @@ private extension FeedIconDownloader { } } - func pullIconURL(from metadata: RSHTMLMetadata, homePageURL: String, feed: Feed) { + func pullIconURL(from metadata: HTMLMetadata, homePageURL: String, feed: Feed) { if let url = metadata.bestWebsiteIconURL() { cacheIconURL(for: homePageURL, url) diff --git a/Shared/Images/RSHTMLMetadata+Extension.swift b/Shared/Images/RSHTMLMetadata+Extension.swift index 82580ab37..bd72e1ff2 100644 --- a/Shared/Images/RSHTMLMetadata+Extension.swift +++ b/Shared/Images/RSHTMLMetadata+Extension.swift @@ -7,65 +7,32 @@ // import Foundation -import RSParser +import Parser -extension RSHTMLMetadata { - - func largestOpenGraphImageURL() -> String? { - let openGraphImages = openGraphProperties.images - - guard !openGraphImages.isEmpty else { - return nil - } - - var bestImage: RSHTMLOpenGraphImage? = nil - - for image in openGraphImages { - if image.width / image.height > 2 { - continue - } - if bestImage == nil { - bestImage = image - continue - } - if image.height > bestImage!.height && image.width > bestImage!.width { - bestImage = image - } - } - - guard let url = bestImage?.secureURL ?? bestImage?.url else { - return nil - } - - // Bad ones we should ignore. - let badURLs = Set(["https://s0.wp.com/i/blank.jpg"]) - guard !badURLs.contains(url) else { - return nil - } - - return url - } +extension HTMLMetadata { func largestAppleTouchIcon() -> String? { - let icons = appleTouchIcons - - guard !icons.isEmpty else { + guard let icons = appleTouchIcons, !icons.isEmpty else { return nil } - var bestImage: RSHTMLMetadataAppleTouchIcon? = nil + var bestImage: HTMLMetadataAppleTouchIcon? = nil for image in icons { - if image.size.width / image.size.height > 2 { - continue + if let size = image.size { + if size.width / size.height > 2 { + continue + } } if bestImage == nil { bestImage = image continue } - if image.size.height > bestImage!.size.height && image.size.width > bestImage!.size.width { - bestImage = image; + if let size = image.size, let bestImageSize = bestImage!.size { + if size.height > bestImageSize.height && size.width > bestImageSize.width { + bestImage = image; + } } } @@ -80,19 +47,10 @@ extension RSHTMLMetadata { return appleTouchIcon } - if let openGraphImageURL = largestOpenGraphImageURL() { + if let openGraphImageURL = openGraphProperties?.image?.url { return openGraphImageURL } - return twitterProperties.imageURL - } - - func bestFeaturedImageURL() -> String? { - - if let openGraphImageURL = largestOpenGraphImageURL() { - return openGraphImageURL - } - - return twitterProperties.imageURL + return twitterProperties?.imageURL } } diff --git a/Shared/ShareExtension/ExtensionContainersFile.swift b/Shared/ShareExtension/ExtensionContainersFile.swift index 094a5360d..13484dab2 100644 --- a/Shared/ShareExtension/ExtensionContainersFile.swift +++ b/Shared/ShareExtension/ExtensionContainersFile.swift @@ -9,7 +9,7 @@ import Foundation import os.log import RSCore -import RSParser +import Parser import Account final class ExtensionContainersFile { diff --git a/iOS/Add/AddFeedViewController.swift b/iOS/Add/AddFeedViewController.swift index 525a5b5f5..5b1e7a67a 100644 --- a/iOS/Add/AddFeedViewController.swift +++ b/iOS/Add/AddFeedViewController.swift @@ -10,7 +10,7 @@ import UIKit import Account import RSCore import RSTree -import RSParser +import Parser enum AddFeedType { case web