Create public, Sendable ParsedOPML* structs to match what we do with feed parsing.
This commit is contained in:
parent
0127fd4d0b
commit
2d3c34f96a
@ -7,9 +7,8 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct OPMLDocument: Sendable {
|
||||
final class OPMLDocument: OPMLItem, @unchecked Sendable {
|
||||
|
||||
public let title: String
|
||||
public let url: String
|
||||
public let items: [OPMLItem]?
|
||||
var title: String?
|
||||
var url: String?
|
||||
}
|
||||
|
@ -8,17 +8,19 @@
|
||||
import Foundation
|
||||
import os
|
||||
|
||||
public struct OPMLItem: Sendable {
|
||||
class OPMLItem: @unchecked Sendable {
|
||||
|
||||
public let feedSpecifier: OPMLFeedSpecifier
|
||||
|
||||
public let attributes: [String: String]
|
||||
public let titleFromAttributes: String?
|
||||
|
||||
public let isFolder: Bool
|
||||
public let items: [OPMLItem]?
|
||||
public var items: [OPMLItem]?
|
||||
public var isFolder: Bool {
|
||||
items.count > 0
|
||||
}
|
||||
|
||||
init?(attributes: [String : String], items: [OPMLItem]?) {
|
||||
init?(attributes: [String : String]) {
|
||||
|
||||
guard let feedURL = attributes.opml_xmlUrl, !feedURL.isEmpty else {
|
||||
return nil
|
||||
@ -35,8 +37,13 @@ public struct OPMLItem: Sendable {
|
||||
self.feedSpecifier = OPMLFeedSpecifier(title: titleFromAttributes, feedDescription: attributes.opml_description, homePageURL: attributes.opml_htmlUrl, feedURL: feedURL)
|
||||
|
||||
self.attributes = attributes
|
||||
}
|
||||
|
||||
func addItem(_ item: OPMLItem) {
|
||||
|
||||
self.items = items
|
||||
self.isFolder = (items?.count ?? 0) > 0
|
||||
if items == nil {
|
||||
items = [OPMLItem]()
|
||||
}
|
||||
items?.append(item)
|
||||
}
|
||||
}
|
||||
|
60
Modules/Parser/Sources/Parser/OPML/OPMLParser.swift
Normal file
60
Modules/Parser/Sources/Parser/OPML/OPMLParser.swift
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// OPMLParser.swift
|
||||
//
|
||||
//
|
||||
// Created by Brent Simmons on 8/18/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public final class OPMLParser {
|
||||
|
||||
let url: String
|
||||
let data: Data
|
||||
|
||||
private var itemStack = [OPMLItem]()
|
||||
|
||||
enum OPMLParserError: Error {
|
||||
case notOPML
|
||||
}
|
||||
|
||||
init(parserData: ParserData) {
|
||||
|
||||
self.url = parserData.url
|
||||
self.data = parserData.data
|
||||
}
|
||||
|
||||
func parse() throws -> OPMLDocument? {
|
||||
|
||||
guard canParseData() else {
|
||||
throw OPMLParserError.notOPML
|
||||
}
|
||||
|
||||
let parser = SAXParser(delegate: self, data: data)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
extension OPMLParser: SAXParserDelegate {
|
||||
|
||||
func saxParser(_: SAXParser, xmlStartElement: XMLPointer, prefix: XMLPointer?, uri: XMLPointer?, namespaceCount: Int, namespaces: UnsafeMutablePointer<XMLPointer?>?, attributeCount: Int, attributesDefaultedCount: Int, attributes: UnsafeMutablePointer<XMLPointer?>?) {
|
||||
|
||||
}
|
||||
|
||||
func saxParser(_: SAXParser, xmlEndElement: XMLPointer, prefix: XMLPointer?, uri: XMLPointer?) {
|
||||
|
||||
}
|
||||
|
||||
func saxParser(_: SAXParser, xmlCharactersFound: XMLPointer, count: Int) {
|
||||
|
||||
}
|
||||
|
||||
func saxParser(_: SAXParser, internedStringForName: XMLPointer, prefix: XMLPointer?) -> String? {
|
||||
|
||||
}
|
||||
|
||||
func saxParser(_: SAXParser, internedStringForValue: XMLPointer, count: Int) -> String? {
|
||||
|
||||
}
|
||||
}
|
25
Modules/Parser/Sources/Parser/OPML/ParsedOPMLDocument.swift
Normal file
25
Modules/Parser/Sources/Parser/OPML/ParsedOPMLDocument.swift
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// ParsedOPMLDocument.swift
|
||||
//
|
||||
//
|
||||
// Created by Brent Simmons on 8/18/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public final class ParsedOPMLDocument: Sendable {
|
||||
|
||||
public let title: String?
|
||||
public let url: String?
|
||||
public let items: [ParsedOPMLItem]?
|
||||
|
||||
init(opmlDocument: OPMLDocument) {
|
||||
|
||||
self.title = opmlDocument.title
|
||||
self.url = opmlDocument.url
|
||||
|
||||
self.items = opmlDocument.items.map { opmlItem in
|
||||
ParsedOPMLItem(opmlItem: opmlItem)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
//
|
||||
// ParsedOPMLFeedSpecifier.swift
|
||||
//
|
||||
//
|
||||
// Created by Brent Simmons on 8/18/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct ParsedOPMLFeedSpecifier: Sendable {
|
||||
|
||||
public let title: String?
|
||||
public let feedDescription: String?
|
||||
public let homePageURL: String?
|
||||
public let feedURL: String
|
||||
|
||||
init(_ opmlFeedSpecifier: OPMLFeedSpecifier) {
|
||||
|
||||
self.title = opmlFeedSpecifier.title
|
||||
self.feedDescription = opmlFeedSpecifier.feedDescription
|
||||
self.homePageURL = opmlFeedSpecifier.homePageURL
|
||||
self.feedURL = opmlFeedSpecifier.feedURL
|
||||
}
|
||||
}
|
31
Modules/Parser/Sources/Parser/OPML/ParsedOPMLItem.swift
Normal file
31
Modules/Parser/Sources/Parser/OPML/ParsedOPMLItem.swift
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Brent Simmons on 8/18/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct ParsedOPMLItem: Sendable {
|
||||
|
||||
public let feedSpecifier: ParsedOPMLFeedSpecifier?
|
||||
|
||||
public let attributes: [String: String]?
|
||||
public let title: String?
|
||||
|
||||
public var items: [ParsedOPMLItem]?
|
||||
public var isFolder: Bool
|
||||
|
||||
init(opmlItem: OPMLItem) {
|
||||
|
||||
self.feedSpecifier = ParsedOPMLFeedSpecifier(opmlItem.feedSpecifier)
|
||||
self.attributes = opmlItem.attributes
|
||||
self.title = opmlItem.title
|
||||
|
||||
self.items = opmlItem.items.map { opmlItem in
|
||||
ParsedOPMLItem(opmlItem: opmlItem)
|
||||
}
|
||||
self.isFolder = (self.items?.count ?? 0) > 0
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user