diff --git a/Modules/Parser/Sources/Parser/Feeds/ParsedAuthor.swift b/Modules/Parser/Sources/Parser/Feeds/ParsedAuthor.swift index 3b97cba59..ded26d415 100644 --- a/Modules/Parser/Sources/Parser/Feeds/ParsedAuthor.swift +++ b/Modules/Parser/Sources/Parser/Feeds/ParsedAuthor.swift @@ -23,11 +23,11 @@ public struct ParsedAuthor: Hashable, Codable, Sendable { } /// Use when the actual property is unknown. Guess based on contents of the string. (This is common with RSS.) - convenience init(singleString: String) { + init(singleString: String) { if singleString.contains("@") { init(name: nil, url: nil, avatarURL: nil, emailAddress: singleString) - } else if singleString.lowercased.hasPrefix("http") { + } else if singleString.lowercased().hasPrefix("http") { init(name: nil, url: singleString, avatarURL: nil, emailAddress: nil) } else { init(name: singleString, url: nil, avatarURL: nil, emailAddress: nil) diff --git a/Modules/Parser/Sources/Parser/HTML/HTMLTag.swift b/Modules/Parser/Sources/Parser/HTML/HTMLTag.swift index 27acc83aa..1ef7f9ad6 100644 --- a/Modules/Parser/Sources/Parser/HTML/HTMLTag.swift +++ b/Modules/Parser/Sources/Parser/HTML/HTMLTag.swift @@ -9,12 +9,12 @@ import Foundation public struct HTMLTag: Sendable { - public enum HTMLTagType { + public enum TagType { case link case meta } - public let tagType: HTMLTagType + public let tagType: TagType public let attributes: [String: String]? public init(tagType: TagType, attributes: [String : String]?) { diff --git a/Modules/Parser/Sources/Parser/OPML/OPMLDocument.swift b/Modules/Parser/Sources/Parser/OPML/OPMLDocument.swift index 690d23155..020ad11d3 100644 --- a/Modules/Parser/Sources/Parser/OPML/OPMLDocument.swift +++ b/Modules/Parser/Sources/Parser/OPML/OPMLDocument.swift @@ -7,10 +7,10 @@ import Foundation -final class OPMLDocument: OPMLItem { +public final class OPMLDocument: OPMLItem { - var title: String? = nil - var url: String? = nil + public var title: String? = nil + public var url: String? = nil init(url: String?) { self.url = url diff --git a/Modules/Parser/Sources/Parser/OPML/OPMLItem.swift b/Modules/Parser/Sources/Parser/OPML/OPMLItem.swift index 7d1733fbb..35b2c3eac 100644 --- a/Modules/Parser/Sources/Parser/OPML/OPMLItem.swift +++ b/Modules/Parser/Sources/Parser/OPML/OPMLItem.swift @@ -8,9 +8,9 @@ import Foundation import os -class OPMLItem { +public class OPMLItem { - public let feedSpecifier: ParsedOPMLFeedSpecifier + public let feedSpecifier: OPMLFeedSpecifier public let attributes: [String: String] public let titleFromAttributes: String? diff --git a/Modules/Parser/Sources/Parser/OPML/OPMLParser.swift b/Modules/Parser/Sources/Parser/OPML/OPMLParser.swift index 28472fee7..59b972158 100644 --- a/Modules/Parser/Sources/Parser/OPML/OPMLParser.swift +++ b/Modules/Parser/Sources/Parser/OPML/OPMLParser.swift @@ -9,32 +9,63 @@ import Foundation public final class OPMLParser { - let url: String - let data: Data + private let url: String + private let data: Data private let opmlDocument: OPMLDocument + private var itemStack = [OPMLItem]() - - enum OPMLParserError: Error { - case notOPML + private var currentItem: OPMLItem? { + itemStack.last } - init(parserData: ParserData) { + /// Returns nil if data can’t be parsed (if it’s not OPML). + public static func document(with parserData: ParserData) -> OPMLDocument? { + + let opmlParser = OPMLParser(parserData) + return opmlParser.parse() + } + + init(_ parserData: ParserData) { self.url = parserData.url self.data = parserData.data self.opmlDocument = OPMLDocument(url: parserData.url) } +} - func parse() throws -> ParsedOPMLDocument { +private extension OPMLParser { + + func parse() -> OPMLDocument? { guard canParseData() else { - throw OPMLParserError.notOPML + return nil } - let parser = SAXParser(delegate: self, data: data) - + pushItem(opmlDocument) + let saxParser = SAXParser(delegate: self, data: data) + saxParser.parse() + } + + func canParseData() -> Bool { + + data.containsASCIIString(" 0) + guard itemStack.count > 0 else { + assertionFailure("itemStack.count must be > 0") + } + + itemStack.dropLast() } } @@ -51,12 +82,4 @@ extension OPMLParser: SAXParserDelegate { func saxParser(_: SAXParser, xmlCharactersFound: XMLPointer, count: Int) { } - - func saxParser(_: SAXParser, internedStringForName: XMLPointer, prefix: XMLPointer?) -> String? { - - } - - func saxParser(_: SAXParser, internedStringForValue: XMLPointer, count: Int) -> String? { - - } }