Port RSOPMLAttributes and RSOPMLItem to Swift.
This commit is contained in:
parent
95ef280698
commit
ad00ee52ff
53
Modules/Parser/Sources/Parser/OPML/OPMLAttributes.swift
Normal file
53
Modules/Parser/Sources/Parser/OPML/OPMLAttributes.swift
Normal file
@ -0,0 +1,53 @@
|
||||
//
|
||||
// OPMLAttributes.swift
|
||||
//
|
||||
//
|
||||
// Created by Brent Simmons on 8/18/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// OPML allows for arbitrary attributes.
|
||||
// These are the common attributes in OPML files used as RSS subscription lists.
|
||||
|
||||
private static let opmlTextKey = "text"
|
||||
private static let opmlTitleKey = "title"
|
||||
private static let opmlDescriptionKey = "description"
|
||||
private static let opmlTypeKey = "type"
|
||||
private static let opmlVersionKey = "version"
|
||||
private static let opmlHMTLURLKey = "htmlUrl"
|
||||
private static let opmlXMLURLKey = "xmlUrl"
|
||||
|
||||
// A frequent error in OPML files is to mess up the capitalization,
|
||||
// so these do a case-insensitive lookup.
|
||||
|
||||
extension Dictionary where Key == String, Value == String {
|
||||
|
||||
var opml_text: String? {
|
||||
object(forCaseInsensitiveKey: opmlTextKey)
|
||||
}
|
||||
|
||||
var opml_title: String? {
|
||||
object(forCaseInsensitiveKey: opmlTitleKey)
|
||||
}
|
||||
|
||||
var opml_description: String? {
|
||||
object(forCaseInsensitiveKey: opmlDescriptionKey)
|
||||
}
|
||||
|
||||
var opml_type: String? {
|
||||
object(forCaseInsensitiveKey: opmlTypeKey)
|
||||
}
|
||||
|
||||
var opml_version: String? {
|
||||
object(forCaseInsensitiveKey: opmlVersionKey)
|
||||
}
|
||||
|
||||
var opml_htmlUrl: String? {
|
||||
object(forCaseInsensitiveKey: opmlHMTLURLKey)
|
||||
}
|
||||
|
||||
var opml_xmlUrl: String? {
|
||||
object(forCaseInsensitiveKey: opmlXMLURLKey)
|
||||
}
|
||||
}
|
42
Modules/Parser/Sources/Parser/OPML/OPMLItem.swift
Normal file
42
Modules/Parser/Sources/Parser/OPML/OPMLItem.swift
Normal file
@ -0,0 +1,42 @@
|
||||
//
|
||||
// OPMLItem.swift
|
||||
//
|
||||
//
|
||||
// Created by Brent Simmons on 8/18/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import os
|
||||
|
||||
public final class OPMLItem: Sendable {
|
||||
|
||||
public let feedSpecifier: OPMLFeedSpecifier
|
||||
|
||||
public let attributes: [String: String]
|
||||
public let titleFromAttributes: String?
|
||||
|
||||
public let isFolder: Bool
|
||||
public let children: [OPMLItem]?
|
||||
|
||||
init?(attributes: [String : String], children: [OPMLItem]?) {
|
||||
|
||||
guard let feedURL = attributes.opml_xmlUrl, !feedURL.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let titleFromAttributes = {
|
||||
if let title = attributes.opml_title {
|
||||
return title
|
||||
}
|
||||
return attributes.opml_text
|
||||
}()
|
||||
self.titleFromAttributes = titleFromAttributes
|
||||
|
||||
self.feedSpecifier = OPMLFeedSpecifier(title: titleFromAttributes, feedDescription: attributes.opml_description, homePageURL: attributes.opml_htmlUrl, feedURL: feedURL)
|
||||
|
||||
self.attributes = attributes
|
||||
|
||||
self.children = children
|
||||
self.isFolder = (children?.count ?? 0) > 0
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
//
|
||||
// Dictionary+Parser.swift
|
||||
//
|
||||
//
|
||||
// Created by Brent Simmons on 8/18/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Dictionary where Key == String, Value == String {
|
||||
|
||||
func object(forCaseInsensitiveKey key: String) -> String? {
|
||||
|
||||
if let object = self[key] {
|
||||
return object
|
||||
}
|
||||
|
||||
let lowercaseKey = key.lowercased()
|
||||
|
||||
for (oneKey, oneValue) in self {
|
||||
if lowercaseKey.caseInsensitiveCompare(oneKey) == .orderedSame {
|
||||
return oneValue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
//
|
||||
// RSOPMLAttributes.h
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 2/28/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
@import Foundation;
|
||||
|
||||
// OPML allows for arbitrary attributes.
|
||||
// These are the common attributes in OPML files used as RSS subscription lists.
|
||||
|
||||
extern NSString *OPMLTextKey; //text
|
||||
extern NSString *OPMLTitleKey; //title
|
||||
extern NSString *OPMLDescriptionKey; //description
|
||||
extern NSString *OPMLTypeKey; //type
|
||||
extern NSString *OPMLVersionKey; //version
|
||||
extern NSString *OPMLHMTLURLKey; //htmlUrl
|
||||
extern NSString *OPMLXMLURLKey; //xmlUrl
|
||||
|
||||
|
||||
@interface NSDictionary (RSOPMLAttributes)
|
||||
|
||||
// A frequent error in OPML files is to mess up the capitalization,
|
||||
// so these do a case-insensitive lookup.
|
||||
|
||||
@property (nonatomic, readonly) NSString *opml_text;
|
||||
@property (nonatomic, readonly) NSString *opml_title;
|
||||
@property (nonatomic, readonly) NSString *opml_description;
|
||||
@property (nonatomic, readonly) NSString *opml_type;
|
||||
@property (nonatomic, readonly) NSString *opml_version;
|
||||
@property (nonatomic, readonly) NSString *opml_htmlUrl;
|
||||
@property (nonatomic, readonly) NSString *opml_xmlUrl;
|
||||
|
||||
@end
|
@ -1,68 +0,0 @@
|
||||
//
|
||||
// RSOPMLAttributes.m
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 2/28/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RSOPMLAttributes.h"
|
||||
#import "RSParserInternal.h"
|
||||
|
||||
|
||||
|
||||
|
||||
NSString *OPMLTextKey = @"text";
|
||||
NSString *OPMLTitleKey = @"title";
|
||||
NSString *OPMLDescriptionKey = @"description";
|
||||
NSString *OPMLTypeKey = @"type";
|
||||
NSString *OPMLVersionKey = @"version";
|
||||
NSString *OPMLHMTLURLKey = @"htmlUrl";
|
||||
NSString *OPMLXMLURLKey = @"xmlUrl";
|
||||
|
||||
|
||||
@implementation NSDictionary (RSOPMLAttributes)
|
||||
|
||||
- (NSString *)opml_text {
|
||||
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLTextKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_title {
|
||||
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLTitleKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_description {
|
||||
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLDescriptionKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_type {
|
||||
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLTypeKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_version {
|
||||
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLVersionKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_htmlUrl {
|
||||
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLHMTLURLKey];
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)opml_xmlUrl {
|
||||
|
||||
return [self rsparser_objectForCaseInsensitiveKey:OPMLXMLURLKey];
|
||||
}
|
||||
|
||||
|
||||
@end
|
@ -1,30 +0,0 @@
|
||||
//
|
||||
// RSOPMLItem.h
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 2/28/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
@import Foundation;
|
||||
|
||||
@class RSOPMLFeedSpecifier;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface RSOPMLItem : NSObject
|
||||
|
||||
@property (nonatomic, nullable) NSDictionary *attributes;
|
||||
@property (nonatomic, nullable) NSArray <RSOPMLItem *> *children;
|
||||
|
||||
- (void)addChild:(RSOPMLItem *)child;
|
||||
|
||||
@property (nonatomic, nullable, readonly) RSOPMLFeedSpecifier *feedSpecifier;
|
||||
|
||||
@property (nonatomic, nullable, readonly) NSString *titleFromAttributes;
|
||||
@property (nonatomic, readonly) BOOL isFolder;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@ -1,87 +0,0 @@
|
||||
//
|
||||
// RSOPMLItem.m
|
||||
// RSParser
|
||||
//
|
||||
// Created by Brent Simmons on 2/28/16.
|
||||
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RSOPMLItem.h"
|
||||
#import "RSOPMLAttributes.h"
|
||||
#import "RSOPMLFeedSpecifier.h"
|
||||
#import "RSParserInternal.h"
|
||||
|
||||
|
||||
|
||||
@interface RSOPMLItem ()
|
||||
|
||||
@property (nonatomic) NSMutableArray *mutableChildren;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation RSOPMLItem
|
||||
|
||||
@synthesize children = _children;
|
||||
@synthesize feedSpecifier = _feedSpecifier;
|
||||
|
||||
|
||||
- (NSArray *)children {
|
||||
|
||||
return [self.mutableChildren copy];
|
||||
}
|
||||
|
||||
|
||||
- (void)setChildren:(NSArray *)children {
|
||||
|
||||
_children = children;
|
||||
self.mutableChildren = [_children mutableCopy];
|
||||
}
|
||||
|
||||
|
||||
- (void)addChild:(RSOPMLItem *)child {
|
||||
|
||||
if (!self.mutableChildren) {
|
||||
self.mutableChildren = [NSMutableArray new];
|
||||
}
|
||||
|
||||
[self.mutableChildren addObject:child];
|
||||
}
|
||||
|
||||
|
||||
- (RSOPMLFeedSpecifier *)feedSpecifier {
|
||||
|
||||
if (_feedSpecifier) {
|
||||
return _feedSpecifier;
|
||||
}
|
||||
|
||||
NSString *feedURL = self.attributes.opml_xmlUrl;
|
||||
if (RSParserObjectIsEmpty(feedURL)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_feedSpecifier = [[RSOPMLFeedSpecifier alloc] initWithTitle:self.titleFromAttributes feedDescription:self.attributes.opml_description homePageURL:self.attributes.opml_htmlUrl feedURL:feedURL];
|
||||
|
||||
return _feedSpecifier;
|
||||
}
|
||||
|
||||
- (NSString *)titleFromAttributes {
|
||||
|
||||
NSString *title = self.attributes.opml_title;
|
||||
if (title) {
|
||||
return title;
|
||||
}
|
||||
title = self.attributes.opml_text;
|
||||
if (title) {
|
||||
return title;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)isFolder {
|
||||
|
||||
return self.mutableChildren.count > 0;
|
||||
}
|
||||
|
||||
@end
|
Loading…
x
Reference in New Issue
Block a user