Continue progress on porting OPML code to Swift.
This commit is contained in:
parent
466fd78297
commit
0f8c529d0d
@ -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.)
|
/// 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("@") {
|
if singleString.contains("@") {
|
||||||
init(name: nil, url: nil, avatarURL: nil, emailAddress: singleString)
|
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)
|
init(name: nil, url: singleString, avatarURL: nil, emailAddress: nil)
|
||||||
} else {
|
} else {
|
||||||
init(name: singleString, url: nil, avatarURL: nil, emailAddress: nil)
|
init(name: singleString, url: nil, avatarURL: nil, emailAddress: nil)
|
||||||
|
@ -9,12 +9,12 @@ import Foundation
|
|||||||
|
|
||||||
public struct HTMLTag: Sendable {
|
public struct HTMLTag: Sendable {
|
||||||
|
|
||||||
public enum HTMLTagType {
|
public enum TagType {
|
||||||
case link
|
case link
|
||||||
case meta
|
case meta
|
||||||
}
|
}
|
||||||
|
|
||||||
public let tagType: HTMLTagType
|
public let tagType: TagType
|
||||||
public let attributes: [String: String]?
|
public let attributes: [String: String]?
|
||||||
|
|
||||||
public init(tagType: TagType, attributes: [String : String]?) {
|
public init(tagType: TagType, attributes: [String : String]?) {
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class OPMLDocument: OPMLItem {
|
public final class OPMLDocument: OPMLItem {
|
||||||
|
|
||||||
var title: String? = nil
|
public var title: String? = nil
|
||||||
var url: String? = nil
|
public var url: String? = nil
|
||||||
|
|
||||||
init(url: String?) {
|
init(url: String?) {
|
||||||
self.url = url
|
self.url = url
|
||||||
|
@ -8,9 +8,9 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import os
|
import os
|
||||||
|
|
||||||
class OPMLItem {
|
public class OPMLItem {
|
||||||
|
|
||||||
public let feedSpecifier: ParsedOPMLFeedSpecifier
|
public let feedSpecifier: OPMLFeedSpecifier
|
||||||
|
|
||||||
public let attributes: [String: String]
|
public let attributes: [String: String]
|
||||||
public let titleFromAttributes: String?
|
public let titleFromAttributes: String?
|
||||||
|
@ -9,32 +9,63 @@ import Foundation
|
|||||||
|
|
||||||
public final class OPMLParser {
|
public final class OPMLParser {
|
||||||
|
|
||||||
let url: String
|
private let url: String
|
||||||
let data: Data
|
private let data: Data
|
||||||
|
|
||||||
private let opmlDocument: OPMLDocument
|
private let opmlDocument: OPMLDocument
|
||||||
|
|
||||||
private var itemStack = [OPMLItem]()
|
private var itemStack = [OPMLItem]()
|
||||||
|
private var currentItem: OPMLItem? {
|
||||||
enum OPMLParserError: Error {
|
itemStack.last
|
||||||
case notOPML
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.url = parserData.url
|
||||||
self.data = parserData.data
|
self.data = parserData.data
|
||||||
self.opmlDocument = OPMLDocument(url: parserData.url)
|
self.opmlDocument = OPMLDocument(url: parserData.url)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func parse() throws -> ParsedOPMLDocument {
|
private extension OPMLParser {
|
||||||
|
|
||||||
|
func parse() -> OPMLDocument? {
|
||||||
|
|
||||||
guard canParseData() else {
|
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, xmlCharactersFound: XMLPointer, count: Int) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func saxParser(_: SAXParser, internedStringForName: XMLPointer, prefix: XMLPointer?) -> String? {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func saxParser(_: SAXParser, internedStringForValue: XMLPointer, count: Int) -> String? {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user