Continue progress on porting OPML code to Swift.

This commit is contained in:
Brent Simmons 2024-08-25 22:00:27 -07:00
parent 466fd78297
commit 0f8c529d0d
5 changed files with 50 additions and 27 deletions

View File

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

View File

@ -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]?) {

View File

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

View File

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

View File

@ -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 cant be parsed (if its 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("<opml")
}
func pushItem(_ item: OPMLItem) {
itemStack.append(item)
}
func popItem() {
assert(itemStack.count > 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? {
}
}