Switch to new Parser.

This commit is contained in:
Brent Simmons
2024-11-15 22:59:51 -08:00
parent c3f063ae4a
commit 85d1a8fe7a
79 changed files with 187 additions and 219 deletions

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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, Error>) -> Void) {
func importOPML(rootExternalID: String, items: [OPMLItem], completion: @escaping (Result<Void, Error>) -> 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 {

View File

@@ -9,7 +9,7 @@
import Foundation
import os.log
import RSCore
import RSParser
import Parser
import RSWeb
import CloudKit
import Articles

View File

@@ -9,7 +9,7 @@
import Foundation
import os.log
import RSCore
import RSParser
import Parser
import RSWeb
import CloudKit
import SyncDatabase

View File

@@ -8,7 +8,7 @@
import Foundation
import Articles
import RSParser
import Parser
public extension Notification.Name {
static let FeedSettingDidChange = Notification.Name(rawValue: "FeedSettingDidChangeNotification")

View File

@@ -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)
}
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View File

@@ -8,7 +8,7 @@
import Foundation
import RSCore
import RSParser
import Parser
struct FeedbinSubscription: Hashable, Codable {

View File

@@ -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

View File

@@ -8,7 +8,7 @@
import Foundation
import Articles
import RSParser
import Parser
struct FeedlyEntryParser {
let entry: FeedlyEntry

View File

@@ -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 {

View File

@@ -7,7 +7,7 @@
//
import Foundation
import RSParser
import Parser
import os.log
protocol FeedlyEntryProviding {

View File

@@ -8,7 +8,7 @@
import Foundation
import os.log
import RSParser
import Parser
import SyncDatabase
import Secrets

View File

@@ -7,7 +7,7 @@
//
import Foundation
import RSParser
import Parser
import os.log
protocol FeedlyParsedItemsByFeedProviding {

View File

@@ -8,7 +8,7 @@
import Foundation
import os.log
import RSParser
import Parser
import RSCore
import RSWeb
import Secrets

View File

@@ -7,7 +7,7 @@
//
import Foundation
import RSParser
import Parser
import os.log
/// Combine the articles with their feeds for a specific account.

View File

@@ -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)
}
}
}
}

View File

@@ -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
}

View File

@@ -8,7 +8,7 @@
import Foundation
import RSCore
import RSParser
import Parser
import RSWeb
import Articles
import ArticlesDatabase

View File

@@ -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

View File

@@ -8,7 +8,7 @@
import Foundation
import RSCore
import RSParser
import Parser
typealias NewsBlurFolder = NewsBlurFeedsResponse.Folder

View File

@@ -8,7 +8,7 @@
import Foundation
import RSCore
import RSParser
import Parser
typealias NewsBlurStory = NewsBlurStoriesResponse.Story

View File

@@ -8,7 +8,7 @@
import Foundation
import RSCore
import RSParser
import Parser
typealias NewsBlurStoryHash = NewsBlurStoryHashesResponse.StoryHash

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 doesnt have a name, so it wont 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 {

View File

@@ -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

View File

@@ -7,7 +7,7 @@
//
import Foundation
import RSParser
import Parser
import RSCore
struct ReaderAPIEntryWrapper: Codable {

View File

@@ -8,7 +8,7 @@
import Foundation
import RSCore
import RSParser
import Parser
/*