From 4ef9c946cbf7f7e71d29f49cda80a74e5d8abb84 Mon Sep 17 00:00:00 2001 From: Leo Dion Date: Thu, 25 Jan 2024 16:20:25 -0500 Subject: [PATCH] Fixing linting issues --- .swiftlint.yml | 6 + Sources/SyndiKit/Common/EntryCategory.swift | 1 + .../Formats/Blogs/CategoryDescriptor.swift | 12 ++ .../Formats/Blogs/CategoryLanguage.swift | 25 ++++ Sources/SyndiKit/Formats/Blogs/Site.swift | 20 ++++ .../SyndiKit/Formats/Blogs/SiteCategory.swift | 28 +++++ .../Formats/Blogs/SiteCategoryType.swift | 1 + .../Formats/Blogs/SiteCollection.swift | 1 + .../Formats/Blogs/SiteDirectory.swift | 112 +++++++++++------- .../Formats/Blogs/SiteDirectoryBuilder.swift | 20 ++++ .../SyndiKit/Formats/Blogs/SiteLanguage.swift | 25 ++++ .../Blogs/SiteLanguageCategory+Site.swift | 12 ++ .../Formats/Blogs/SiteLanguageCategory.swift | 16 +++ .../Formats/Blogs/SiteLanguageContent.swift | 18 +++ .../Formats/Blogs/SiteLanguageType.swift | 1 + .../Formats/Feeds/Atom/AtomEntry.swift | 32 ++--- .../Formats/Feeds/Atom/AtomFeed.swift | 2 +- .../SyndiKit/Formats/Feeds/RSS/RSSFeed.swift | 1 + .../SyndiKit/Formats/Media/MediaContent.swift | 9 ++ .../Podcast/PodcastChapters+MimeType.swift | 8 ++ .../Media/Podcast/PodcastChapters.swift | 5 + .../Media/Podcast/PodcastEpisode.swift | 52 +++++++- .../Media/Podcast/PodcastFunding.swift | 5 + .../Podcast/PodcastLocation+GeoURI.swift | 35 +++++- .../Podcast/PodcastLocation+OsmQuery.swift | 12 +- .../Media/Podcast/PodcastLocation.swift | 6 + .../Formats/Media/Podcast/PodcastLocked.swift | 11 +- .../Media/Podcast/PodcastPerson+Role.swift | 11 +- .../Formats/Media/Podcast/PodcastPerson.swift | 15 +++ .../Formats/Media/Podcast/PodcastSeason.swift | 5 + .../Media/Podcast/PodcastSoundbite.swift | 6 + .../Podcast/PodcastTranscript+MimeType.swift | 12 +- .../Media/Podcast/PodcastTranscript.swift | 10 ++ Sources/SyndiKit/Formats/Media/Video.swift | 6 + .../Formats/Media/Wordpress/WPCategory.swift | 21 ++++ .../Formats/Media/Wordpress/WPPostMeta.swift | 22 ++++ .../Formats/Media/Wordpress/WPTag.swift | 17 +++ .../Wordpress/WordPressPost+RSSItem.swift | 14 ++- .../Media/Wordpress/WordPressPost.swift | 55 +++++++++ .../Formats/Media/YouTube/YouTubeID.swift | 43 +++++-- .../Formats/Media/iTunes/iTunesDuration.swift | 22 +++- .../Formats/Media/iTunes/iTunesEpisode.swift | 8 +- .../Formats/Media/iTunes/iTunesImage.swift | 3 +- .../Formats/Media/iTunes/iTunesOwner.swift | 20 +++- 44 files changed, 686 insertions(+), 80 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index db96f2b..141707c 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -110,6 +110,12 @@ function_parameter_count: 8 line_length: - 90 - 90 +type_name: + excluded: + - iTunesDuration + - iTunesEpisode + - iTunesOwner + - iTunesImage identifier_name: excluded: - id diff --git a/Sources/SyndiKit/Common/EntryCategory.swift b/Sources/SyndiKit/Common/EntryCategory.swift index 4e39016..1ca3717 100644 --- a/Sources/SyndiKit/Common/EntryCategory.swift +++ b/Sources/SyndiKit/Common/EntryCategory.swift @@ -1,4 +1,5 @@ /// Abstract category type. public protocol EntryCategory { + /// Term used for the category var term: String { get } } diff --git a/Sources/SyndiKit/Formats/Blogs/CategoryDescriptor.swift b/Sources/SyndiKit/Formats/Blogs/CategoryDescriptor.swift index 55a8ca6..ee809ed 100644 --- a/Sources/SyndiKit/Formats/Blogs/CategoryDescriptor.swift +++ b/Sources/SyndiKit/Formats/Blogs/CategoryDescriptor.swift @@ -1,4 +1,16 @@ +/** + A descriptor for a category. + + - Note: This struct is publicly accessible. + + - Important: The `title` and `description` properties are read-only. + + - SeeAlso: `Category` + */ public struct CategoryDescriptor { + /// The title of the category. public let title: String + + /// The description of the category. public let description: String } diff --git a/Sources/SyndiKit/Formats/Blogs/CategoryLanguage.swift b/Sources/SyndiKit/Formats/Blogs/CategoryLanguage.swift index ea16201..6959283 100644 --- a/Sources/SyndiKit/Formats/Blogs/CategoryLanguage.swift +++ b/Sources/SyndiKit/Formats/Blogs/CategoryLanguage.swift @@ -1,8 +1,33 @@ +/** + A struct representing a category in a specific language. + + - Parameters: + - languageCategory: The category in a specific language. + - language: The language of the category. + + - Note: This struct is used internally. + + - SeeAlso: `SiteCategoryType` + - SeeAlso: `CategoryDescriptor` + - SeeAlso: `SiteLanguageType` + */ public struct CategoryLanguage { + /// The type of the category. public let type: SiteCategoryType + + /// The descriptor of the category. public let descriptor: CategoryDescriptor + + /// The language of the category. public let language: SiteLanguageType + /** + Initializes a `CategoryLanguage` instance. + + - Parameters: + - languageCategory: The category in a specific language. + - language: The language of the category. + */ internal init(languageCategory: SiteLanguageCategory, language: SiteLanguageType) { type = languageCategory.slug descriptor = CategoryDescriptor( diff --git a/Sources/SyndiKit/Formats/Blogs/Site.swift b/Sources/SyndiKit/Formats/Blogs/Site.swift index 92fde38..119d691 100644 --- a/Sources/SyndiKit/Formats/Blogs/Site.swift +++ b/Sources/SyndiKit/Formats/Blogs/Site.swift @@ -1,14 +1,34 @@ import Foundation +/// A struct representing a website. public struct Site { + /// The title of the website. public let title: String + + /// The author of the website. public let author: String + + /// The URL of the website. public let siteURL: URL + + /// The URL of the website's feed. public let feedURL: URL + + /// The URL of the website's Twitter page, if available. public let twitterURL: URL? + + /// The category of the website. public let category: SiteCategoryType + + /// The language of the website. public let language: SiteLanguageType + /// Initializes a new `Site` instance. + /// + /// - Parameters: + /// - site: The `SiteLanguageCategory.Site` instance to use as a base. + /// - categoryType: The category type of the website. + /// - languageType: The language type of the website. internal init( site: SiteLanguageCategory.Site, categoryType: SiteCategoryType, diff --git a/Sources/SyndiKit/Formats/Blogs/SiteCategory.swift b/Sources/SyndiKit/Formats/Blogs/SiteCategory.swift index 71282e5..068ca81 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteCategory.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteCategory.swift @@ -1,7 +1,35 @@ +/** + A struct representing a site category. + + - Note: This struct is used to categorize sites based on their type and descriptors. + + - Parameters: + - type: The type of the site category. + - descriptors: A dictionary mapping site language types to category descriptors. + + - Important: This struct should not be used directly. + Instead, use the `SiteCategoryBuilder` to create instances of `SiteCategory`. + + - SeeAlso: `SiteCategoryType` + - SeeAlso: `CategoryDescriptor` + - SeeAlso: `CategoryLanguage` + - SeeAlso: `SiteCategoryBuilder` + */ public struct SiteCategory { + /// The type of the site category. public let type: SiteCategoryType + + /// A dictionary mapping site language types to category descriptors. public let descriptors: [SiteLanguageType: CategoryDescriptor] + /** + Initializes a `SiteCategory` instance with the given languages. + + - Parameter languages: An array of `CategoryLanguage` instances. + + - Returns: A new `SiteCategory` instance + if at least one language is provided, `nil` otherwise. + */ internal init?(languages: [CategoryLanguage]) { guard let type = languages.first?.type else { return nil diff --git a/Sources/SyndiKit/Formats/Blogs/SiteCategoryType.swift b/Sources/SyndiKit/Formats/Blogs/SiteCategoryType.swift index dcaf6fc..311038b 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteCategoryType.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteCategoryType.swift @@ -1 +1,2 @@ +/// A type alias representing a site category. public typealias SiteCategoryType = String diff --git a/Sources/SyndiKit/Formats/Blogs/SiteCollection.swift b/Sources/SyndiKit/Formats/Blogs/SiteCollection.swift index c3c7980..3fd9523 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteCollection.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteCollection.swift @@ -1 +1,2 @@ +/// A collection of site language content. public typealias SiteCollection = [SiteLanguageContent] diff --git a/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift b/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift index b009695..c1c2fe5 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift @@ -1,55 +1,58 @@ import Foundation +/// A directory of site collections. public struct SiteCollectionDirectory: SiteDirectory { + /// A sequence of sites. public typealias SiteSequence = [Site] - public typealias LanguageSequence = - Dictionary.Values + /// A sequence of languages. + public typealias LanguageSequence = Dictionary.Values - public typealias CategorySequence = - Dictionary.Values + /// A sequence of categories. + public typealias CategorySequence = Dictionary.Values + /// The internal structure of the site collection directory. internal struct Instance { internal let allSites: [Site] internal let languageDictionary: [SiteLanguageType: SiteLanguage] internal let categoryDictionary: [SiteCategoryType: SiteCategory] - internal let languageIndicies: [SiteLanguageType: Set] - internal let categoryIndicies: [SiteCategoryType: Set] + internal let languageIndices: [SiteLanguageType: Set] + internal let categoryIndices: [SiteCategoryType: Set] // swiftlint:disable:next function_body_length internal func sites( withLanguage language: SiteLanguageType?, withCategory category: SiteCategoryType? ) -> [Site] { - let languageIndicies: Set? + let languageIndices: Set? if let language = language { - languageIndicies = self.languageIndicies[language] ?? .init() + languageIndices = self.languageIndices[language] ?? .init() } else { - languageIndicies = nil + languageIndices = nil } - let categoryIndicies: Set? + let categoryIndices: Set? if let category = category { - categoryIndicies = self.categoryIndicies[category] ?? .init() + categoryIndices = self.categoryIndices[category] ?? .init() } else { - categoryIndicies = nil + categoryIndices = nil } - var indicies: Set? + var indices: Set? - if let languageIndicies = languageIndicies { - indicies = languageIndicies + if let languageIndices = languageIndices { + indices = languageIndices } - if let categoryIndicies = categoryIndicies { - if let current = indicies { - indicies = current.intersection(categoryIndicies) + if let categoryIndices = categoryIndices { + if let current = indices { + indices = current.intersection(categoryIndices) } else { - indicies = categoryIndicies + indices = categoryIndices } } - if let current = indicies { + if let current = indices { return current.map { self.allSites[$0] } } else { return allSites @@ -61,14 +64,14 @@ public struct SiteCollectionDirectory: SiteDirectory { var categories = [CategoryLanguage]() var languages = [SiteLanguage]() var sites = [Site]() - var languageIndicies = [SiteLanguageType: Set]() - var categoryIndicies = [SiteCategoryType: Set]() + var languageIndices = [SiteLanguageType: Set]() + var categoryIndices = [SiteCategoryType: Set]() for languageContent in blogs { let language = SiteLanguage(content: languageContent) - var thisLanguageIndicies = [Int]() + var thisLanguageIndices = [Int]() for languageCategory in languageContent.categories { - var thisCategoryIndicies = [Int]() + var thisCategoryIndices = [Int]() let category = CategoryLanguage( languageCategory: languageCategory, language: language.type @@ -81,13 +84,13 @@ public struct SiteCollectionDirectory: SiteDirectory { languageType: language.type ) sites.append(site) - thisCategoryIndicies.append(index) - thisLanguageIndicies.append(index) + thisCategoryIndices.append(index) + thisLanguageIndices.append(index) } - categoryIndicies.formUnion(thisCategoryIndicies, key: category.type) + categoryIndices.formUnion(thisCategoryIndices, key: category.type) categories.append(category) } - languageIndicies.formUnion(thisLanguageIndicies, key: language.type) + languageIndices.formUnion(thisLanguageIndices, key: language.type) languages.append(language) } @@ -96,30 +99,37 @@ public struct SiteCollectionDirectory: SiteDirectory { languageDictionary = Dictionary( uniqueKeysWithValues: languages.map { ($0.type, $0) } ) - self.languageIndicies = languageIndicies - self.categoryIndicies = categoryIndicies + self.languageIndices = languageIndices + self.categoryIndices = categoryIndices allSites = sites } } private let instance: Instance - public var languages: Dictionary< - SiteLanguageType, SiteLanguage - >.Values { + /// A sequence of languages in the site collection directory. + public var languages: Dictionary.Values { instance.languageDictionary.values } - public var categories: Dictionary< - SiteCategoryType, SiteCategory - >.Values { + /// A sequence of categories in the site collection directory. + public var categories: Dictionary.Values { instance.categoryDictionary.values } + /// Initializes a new instance of the `SiteCollectionDirectory` struct. + /// + /// - Parameter blogs: The site collection to use. internal init(blogs: SiteCollection) { instance = .init(blogs: blogs) } + /// Retrieves a list of sites based on the specified language and category. + /// + /// - Parameters: + /// - language: The language of the sites to retrieve. + /// - category: The category of the sites to retrieve. + /// - Returns: A list of sites matching the specified language and category. public func sites( withLanguage language: SiteLanguageType?, withCategory category: SiteCategoryType? @@ -128,17 +138,27 @@ public struct SiteCollectionDirectory: SiteDirectory { } } +/// A protocol for site directories. public protocol SiteDirectory { - associatedtype SiteSequence: Sequence - where SiteSequence.Element == Site - associatedtype LanguageSequence: Sequence - where LanguageSequence.Element == SiteLanguage - associatedtype CategorySequence: Sequence - where CategorySequence.Element == SiteCategory - + /// List of Sites + associatedtype SiteSequence: Sequence where SiteSequence.Element == Site + /// List of Languages + associatedtype LanguageSequence: Sequence where LanguageSequence.Element == SiteLanguage + /// List of Categories + associatedtype CategorySequence: Sequence where CategorySequence.Element == SiteCategory + + /// A sequence of languages in the site directory. var languages: LanguageSequence { get } + + /// A sequence of categories in the site directory. var categories: CategorySequence { get } + /// Retrieves a list of sites based on the specified language and category. + /// + /// - Parameters: + /// - language: The language of the sites to retrieve. + /// - category: The category of the sites to retrieve. + /// - Returns: A list of sites matching the specified language and category. func sites( withLanguage language: SiteLanguageType?, withCategory category: SiteCategoryType? @@ -146,6 +166,12 @@ public protocol SiteDirectory { } extension SiteDirectory { + /// Retrieves a list of sites based on the specified language and category. + /// + /// - Parameters: + /// - language: The language of the sites to retrieve. + /// - category: The category of the sites to retrieve. + /// - Returns: A list of sites matching the specified language and category. public func sites( withLanguage language: SiteLanguageType? = nil, withCategory category: SiteCategoryType? = nil diff --git a/Sources/SyndiKit/Formats/Blogs/SiteDirectoryBuilder.swift b/Sources/SyndiKit/Formats/Blogs/SiteDirectoryBuilder.swift index 6273543..06dd060 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteDirectoryBuilder.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteDirectoryBuilder.swift @@ -1,13 +1,33 @@ import Foundation +/// A builder for creating a site collection directory. public struct SiteCollectionDirectoryBuilder: SiteDirectoryBuilder { + /// Initializes a new instance of `SiteCollectionDirectoryBuilder`. public init() {} + + /** + Creates a site collection directory from a site collection. + + - Parameter blogs: The site collection to build the directory from. + + - Returns: A new instance of `SiteCollectionDirectory`. + */ public func directory(fromCollection blogs: SiteCollection) -> SiteCollectionDirectory { SiteCollectionDirectory(blogs: blogs) } } +/// A protocol for building site directories. public protocol SiteDirectoryBuilder { + /// The type of site directory to build. associatedtype SiteDirectoryType: SiteDirectory + + /** + Creates a site directory from a site collection. + + - Parameter blogs: The site collection to build the directory from. + + - Returns: A new instance of `SiteDirectoryType`. + */ func directory(fromCollection blogs: SiteCollection) -> SiteDirectoryType } diff --git a/Sources/SyndiKit/Formats/Blogs/SiteLanguage.swift b/Sources/SyndiKit/Formats/Blogs/SiteLanguage.swift index 75733bb..81175b0 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteLanguage.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteLanguage.swift @@ -1,7 +1,32 @@ +/** + A struct representing a site language. + + Use this struct to define the type and title of a site language. + + - Note: This struct is used internally and should not be directly instantiated. + + - Parameters: + - content: The content of the site language. + + - SeeAlso: `SiteLanguageType` + + - Author: Your Name + */ public struct SiteLanguage { + /// The type of the site language. public let type: SiteLanguageType + + /// The title of the site language. public let title: String + /** + Initializes a new `SiteLanguage` instance. + + - Parameters: + - content: The content of the site language. + + - Returns: A new `SiteLanguage` instance. + */ internal init(content: SiteLanguageContent) { type = content.language title = content.title diff --git a/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory+Site.swift b/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory+Site.swift index 634511c..44978b5 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory+Site.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory+Site.swift @@ -2,13 +2,24 @@ import Foundation // swiftlint:disable nesting extension SiteLanguageCategory { + /// A `struct` representing a site. public struct Site: Codable { + /// The title of the site. public let title: String + + /// The author of the site. public let author: String + + /// The URL of the site. public let siteURL: URL + + /// The URL of the site's feed. public let feedURL: URL + + /// The URL of the site's Twitter page. public let twitterURL: URL? + /// Coding keys to map properties to JSON keys. internal enum CodingKeys: String, CodingKey { case title case author @@ -19,4 +30,5 @@ extension SiteLanguageCategory { } } +/// A type alias for `SiteLanguageCategory.Site`. public typealias SiteStub = SiteLanguageCategory.Site diff --git a/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory.swift b/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory.swift index d485780..4968b36 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory.swift @@ -1,6 +1,22 @@ +/** + A struct representing a category of site languages. + + - Note: This struct conforms to the `Codable` protocol. + + - Important: All properties of this struct are read-only. + + - SeeAlso: `Site` + */ public struct SiteLanguageCategory: Codable { + /// The title of the category. public let title: String + + /// The slug of the category. public let slug: String + + /// A description of the category. public let description: String + + /// An array of sites belonging to this category. public let sites: [Site] } diff --git a/Sources/SyndiKit/Formats/Blogs/SiteLanguageContent.swift b/Sources/SyndiKit/Formats/Blogs/SiteLanguageContent.swift index 4141712..9fa1f0e 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteLanguageContent.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteLanguageContent.swift @@ -1,5 +1,23 @@ +/** + A struct representing the content of a site in a specific language. + + - Note: This struct conforms to the `Codable` protocol. + + - Important: All properties of this struct are read-only. + + - SeeAlso: `SiteLanguageCategory` + + - Author: Your Name + + - Version: 1.0 + */ public struct SiteLanguageContent: Codable { + /// The language of the site content. public let language: String + + /// The title of the site. public let title: String + + /// The categories of the site. public let categories: [SiteLanguageCategory] } diff --git a/Sources/SyndiKit/Formats/Blogs/SiteLanguageType.swift b/Sources/SyndiKit/Formats/Blogs/SiteLanguageType.swift index 289a526..28fa6e6 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteLanguageType.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteLanguageType.swift @@ -1 +1,2 @@ +/// A type representing the language of a website. public typealias SiteLanguageType = String diff --git a/Sources/SyndiKit/Formats/Feeds/Atom/AtomEntry.swift b/Sources/SyndiKit/Formats/Feeds/Atom/AtomEntry.swift index 627ee94..c6cd3b7 100644 --- a/Sources/SyndiKit/Formats/Feeds/Atom/AtomEntry.swift +++ b/Sources/SyndiKit/Formats/Feeds/Atom/AtomEntry.swift @@ -2,6 +2,22 @@ import Foundation /// A struct representing an entry in an Atom feed. public struct AtomEntry: Codable { + /// The coding keys used for encoding and decoding. + public enum CodingKeys: String, CodingKey { + case id + case title + case published + case content + case updated + case links = "link" + case authors = "author" + case atomCategories = "category" + case youtubeVideoID = "yt:videoId" + case youtubeChannelID = "yt:channelId" + case creators = "dc:creator" + case mediaGroup = "media:group" + } + /// A permanent, universally unique identifier for an entry. public let id: EntryID @@ -37,22 +53,6 @@ public struct AtomEntry: Codable { /// The media group associated with the entry. public let mediaGroup: AtomMediaGroup? - - /// The coding keys used for encoding and decoding. - public enum CodingKeys: String, CodingKey { - case id - case title - case published - case content - case updated - case links = "link" - case authors = "author" - case atomCategories = "category" - case youtubeVideoID = "yt:videoId" - case youtubeChannelID = "yt:channelId" - case creators = "dc:creator" - case mediaGroup = "media:group" - } } extension AtomEntry: Entryable { diff --git a/Sources/SyndiKit/Formats/Feeds/Atom/AtomFeed.swift b/Sources/SyndiKit/Formats/Feeds/Atom/AtomFeed.swift index 3bcc522..c044499 100644 --- a/Sources/SyndiKit/Formats/Feeds/Atom/AtomFeed.swift +++ b/Sources/SyndiKit/Formats/Feeds/Atom/AtomFeed.swift @@ -3,7 +3,7 @@ import Foundation /** An XML-based Web content and metadata syndication format. - Based on the + Based on the [specifications here](https://datatracker.ietf.org/doc/html/rfc4287#section-4.1.2). */ public struct AtomFeed { diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSFeed.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSFeed.swift index 31f8b94..fd8fcd4 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/RSSFeed.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSFeed.swift @@ -16,6 +16,7 @@ import Foundation [W3 sepcifications.](https://validator.w3.org/feed/docs/rss2.html) */ public struct RSSFeed { + /// Root Channel of hte RSS Feed public let channel: RSSChannel } diff --git a/Sources/SyndiKit/Formats/Media/MediaContent.swift b/Sources/SyndiKit/Formats/Media/MediaContent.swift index 59593f1..97f431b 100644 --- a/Sources/SyndiKit/Formats/Media/MediaContent.swift +++ b/Sources/SyndiKit/Formats/Media/MediaContent.swift @@ -1,4 +1,13 @@ +/** + Represents different types of media content. + + - podcast: A podcast episode. + - video: A video. + */ public enum MediaContent { + /// A podcast episode. case podcast(PodcastEpisode) + + /// A video. case video(Video) } diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters+MimeType.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters+MimeType.swift index de3cac7..5163945 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters+MimeType.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters+MimeType.swift @@ -1,13 +1,16 @@ import Foundation extension PodcastChapters { + /// A private enum representing known MIME types for podcast chapters. private enum KnownMimeType: String, Codable { case json = "application/json+chapters" + /// Initializes a `KnownMimeType` from a case-insensitive string. init?(caseInsensitive: String) { self.init(rawValue: caseInsensitive) } + /// Initializes a `KnownMimeType` from a `MimeType`. init?(mimeType: MimeType) { switch mimeType { case .json: @@ -19,10 +22,12 @@ extension PodcastChapters { } } + /// An enum representing the MIME type of podcast chapters. public enum MimeType: Codable, Equatable, RawRepresentable { case json case unknown(String) + /// The raw value of the MIME type. public var rawValue: String { if let knownMimeType = KnownMimeType(mimeType: self) { return knownMimeType.rawValue @@ -36,10 +41,12 @@ extension PodcastChapters { } } + /// Initializes a `MimeType` from a raw value. public init?(rawValue: String) { self.init(caseInsensitive: rawValue) } + /// Initializes a `MimeType` from a case-insensitive string. public init(caseInsensitive: String) { if let knownMimeType = KnownMimeType(caseInsensitive: caseInsensitive) { self = .init(knownMimeType: knownMimeType) @@ -48,6 +55,7 @@ extension PodcastChapters { } } + /// Initializes a `MimeType` from a `KnownMimeType`. private init(knownMimeType: KnownMimeType) { switch knownMimeType { case .json: diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters.swift index e843458..a3ef7e5 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters.swift @@ -1,11 +1,16 @@ import Foundation +/// A struct representing chapters of a podcast. public struct PodcastChapters: Codable, Equatable { + /// The coding keys for encoding and decoding. public enum CodingKeys: String, CodingKey { case url case type } + /// The URL of the chapter file. public let url: URL + + /// The MIME type of the chapter file. public let type: MimeType } diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift index c868abd..c312061 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift @@ -1,17 +1,45 @@ import Foundation +/// A struct representing properties of a podcast episode. public struct PodcastEpisodeProperties: PodcastEpisode { + /// The title of the episode. public let title: String? + + /// The episode number. public let episode: Int? + + /// The author of the episode. public let author: String? + + /// The subtitle of the episode. public let subtitle: String? + + /// A summary of the episode. public let summary: String? + + /// Indicates if the episode contains explicit content. public let explicit: String? + + /// The duration of the episode. public let duration: TimeInterval? + + /// The image associated with the episode. public let image: iTunesImage? + + /// The enclosure of the episode. public let enclosure: Enclosure + + /// The people involved in the episode. public let people: [PodcastPerson] + /** + Initializes a `PodcastEpisodeProperties` instance from an `RSSItem`. + + - Parameter rssItem: The `RSSItem` to extract the properties from. + + - Returns: An initialized `PodcastEpisodeProperties` instance, + or `nil` if the `enclosure` property is missing. + */ public init?(rssItem: RSSItem) { guard let enclosure = rssItem.enclosure else { return nil @@ -29,15 +57,35 @@ public struct PodcastEpisodeProperties: PodcastEpisode { } } +/// A protocol representing a podcast episode. public protocol PodcastEpisode { + /// The title of the episode. var title: String? { get } + + /// The episode number. var episode: Int? { get } + + /// The author of the episode. var author: String? { get } - var subtitle: String? { get } + + /// A summary of the episode. var summary: String? { get } - var explicit: String? { get } + + /// The subtitle of the episode. + var subtitle: String? { get } + + /// The duration of the episode. var duration: TimeInterval? { get } + + /// The image associated with the episode. var image: iTunesImage? { get } + + /// Indicates if the episode contains explicit content. + var explicit: String? { get } + + /// The enclosure of the episode. var enclosure: Enclosure { get } + + /// The people involved in the episode. var people: [PodcastPerson] { get } } diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastFunding.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastFunding.swift index 61dd52b..ab8d23a 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastFunding.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastFunding.swift @@ -1,11 +1,16 @@ import Foundation +/// A struct representing funding information for a podcast. public struct PodcastFunding: Codable, Equatable { + /// The coding keys used for encoding and decoding. public enum CodingKeys: String, CodingKey { case url case description = "" } + /// The URL for the funding source. public let url: URL + + /// A description of the funding source. public let description: String? } diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift index 9e1e235..5089b0e 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift @@ -1,12 +1,21 @@ import Foundation extension PodcastLocation { + /// A `struct` representing a geographic URI for a podcast location. public struct GeoURI: Codable, Equatable, LosslessStringConvertible { + /// The latitude coordinate. public let latitude: Double + + /// The longitude coordinate. public let longitude: Double + + /// The altitude coordinate, if available. public let altitude: Double? + + /// The accuracy of the coordinates, if available. public let accuracy: Double? + /// A string representation of the geographic URI. public var description: String { var description = "geo:\(latitude),\(longitude)" @@ -21,6 +30,13 @@ extension PodcastLocation { return description } + /// Initializes a `GeoURI` instance with the specified coordinates. + /// + /// - Parameters: + /// - latitude: The latitude coordinate. + /// - longitude: The longitude coordinate. + /// - altitude: The altitude coordinate, if available. + /// - accuracy: The accuracy of the coordinates, if available. public init( latitude: Double, longitude: Double, @@ -33,11 +49,18 @@ extension PodcastLocation { self.accuracy = accuracy } + /// Initializes a `GeoURI` instance from a string representation. + /// + /// - Parameter description: The string representation of the geographic URI. public init?(_ description: String) { try? self.init(singleValue: description) } - // swiftlint:disable:next function_body_length + // swiftlint:disable function_body_length + /// Initializes a `GeoURI` instance from a single value string. + /// + /// - Parameter singleValue: The single value string representing the geographic URI. + /// - Throws: A `DecodingError` if the single value string is invalid. public init(singleValue: String) throws { let pathComponents = try Self.pathComponents(from: singleValue) @@ -66,6 +89,12 @@ extension PodcastLocation { ) } + // swiftlint:enable function_body_length + + /// Initializes a `GeoURI` instance from a decoder. + /// + /// - Parameter decoder: The decoder to read data from. + /// - Throws: A `DecodingError` if the decoding process fails. public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let singleValue = try container.decode(String.self) @@ -93,6 +122,10 @@ extension PodcastLocation { return geoPath.split(separator: ";") } + /// Encodes the `GeoURI` instance into the given encoder. + /// + /// - Parameter encoder: The encoder to write data to. + /// - Throws: An error if the encoding process fails. public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(description) diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift index 77abcc8..ffbcf1d 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift @@ -1,18 +1,28 @@ import Foundation extension PodcastLocation { + /// Represents a query for OpenStreetMap (OSM) data. public struct OsmQuery: Codable, Equatable { - // swiftlint:disable:next nesting + /// The type of OSM element. public enum OsmType: String, Codable, CaseIterable { case node = "N" case way = "W" case relation = "R" } + /// The ID of the OSM element. public let id: Int + + /// The type of the OSM element. public let type: OsmType + + /// The revision number of the OSM element. public let revision: Int? + /// Initializes an `OsmQuery` instance from a decoder. + /// + /// - Parameter decoder: The decoder to read data from. + /// - Throws: `DecodingError.dataCorrupted` if the data is invalid. public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation.swift index 4517282..1513654 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation.swift @@ -1,6 +1,8 @@ import Foundation +/// A struct representing the location of a podcast. public struct PodcastLocation: Codable, Equatable { + /// The geographic coordinates of the location. internal enum CodingKeys: String, CodingKey { case geo case osmQuery = "osm" @@ -8,8 +10,12 @@ public struct PodcastLocation: Codable, Equatable { case name = "" } + /// The geographic coordinates of the location. public let geo: GeoURI? + + /// The OpenStreetMap query for the location. public let osmQuery: OsmQuery? + /// The name of the location. public let name: String } diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocked.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocked.swift index c62cdf3..beb5e73 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocked.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocked.swift @@ -1,14 +1,23 @@ import Foundation +/// A struct representing a locked podcast. public struct PodcastLocked: Codable, Equatable { + /// Coding keys for encoding and decoding. public enum CodingKeys: String, CodingKey { case owner - case isLocked = "" + case isLocked = "is_locked" } + /// The owner of the podcast. public let owner: String? + + /// Indicates whether the podcast is locked. public let isLocked: Bool + /// Initializes a new instance of `PodcastLocked` from a decoder. + /// + /// - Parameter decoder: The decoder to read data from. + /// - Throws: An error if the decoding process fails. public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) owner = try container.decodeIfPresent(String.self, forKey: .owner) diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson+Role.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson+Role.swift index f292a2e..f6b3bbb 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson+Role.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson+Role.swift @@ -1,6 +1,7 @@ import Foundation extension PodcastPerson { + /// A private enum representing known roles for a podcast person. private enum KnownRole: String { case guest case host @@ -10,11 +11,13 @@ extension PodcastPerson { case composer case producer + /// Initializes a `KnownRole` with a case-insensitive string. init?(caseInsensitive: String) { self.init(rawValue: caseInsensitive.lowercased()) } - // swiftlint:disable:next function_body_length cyclomatic_complexity + // swiftlint:disable function_body_length cyclomatic_complexity + /// Initializes a `KnownRole` with a `Role` value. init?(role: Role) { switch role { case .guest: @@ -44,6 +47,9 @@ extension PodcastPerson { } } + // swiftlint:enable function_body_length cyclomatic_complexity + + /// An enum representing the role of a podcast person. public enum Role: Codable, Equatable, RawRepresentable { case guest case host @@ -54,6 +60,7 @@ extension PodcastPerson { case producer case unknown(String) + /// The raw value of the role. public var rawValue: String { if let knownRole = KnownRole(role: self) { return knownRole.rawValue @@ -67,10 +74,12 @@ extension PodcastPerson { } } + /// Initializes a `Role` with a raw value. public init?(rawValue: String) { self.init(caseInsensitive: rawValue) } + /// Initializes a `Role` with a case-insensitive string. public init(caseInsensitive: String) { if let knownRole = KnownRole(caseInsensitive: caseInsensitive) { self = .init(knownRole: knownRole) diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson.swift index dcdf454..6ada7b5 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson.swift @@ -1,6 +1,8 @@ import Foundation +/// A struct representing a person associated with a podcast. public struct PodcastPerson: Codable, Equatable { + /// The role of the person. public enum CodingKeys: String, CodingKey { case role case group @@ -9,13 +11,26 @@ public struct PodcastPerson: Codable, Equatable { case fullname = "" } + /// The role of the person. public let role: Role? + + /// The group the person belongs to. public let group: String? + + /// The URL associated with the person. public let href: URL? + + /// The URL of the person's image. public let img: URL? + /// The full name of the person. public let fullname: String + /// Initializes a new instance of `PodcastPerson` + /// by decoding data from the given decoder. + /// + /// - Parameter decoder: The decoder to read data from. + /// - Throws: An error if the decoding process fails. public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) role = try container.decodeIfPresent(Role.self, forKey: .role) diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastSeason.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastSeason.swift index 226bb36..69dd61c 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastSeason.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastSeason.swift @@ -1,11 +1,16 @@ import Foundation +/// A struct representing a season of a podcast. public struct PodcastSeason: Codable, Equatable { + /// The coding keys for the `PodcastSeason` struct. public enum CodingKeys: String, CodingKey { case name case number = "" } + /// The name of the season. public let name: String? + + /// The number of the season. public let number: Int } diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastSoundbite.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastSoundbite.swift index 02f709f..14740d3 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastSoundbite.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastSoundbite.swift @@ -1,6 +1,8 @@ import Foundation +/// A struct representing a soundbite from a podcast. public struct PodcastSoundbite: Codable, Equatable { + /// The coding keys used for encoding and decoding. public enum CodingKeys: String, CodingKey { case startTime case duration @@ -8,8 +10,12 @@ public struct PodcastSoundbite: Codable, Equatable { case title = "" } + /// The start time of the soundbite. public let startTime: TimeInterval + + /// The duration of the soundbite. public let duration: TimeInterval + /// The title of the soundbite. public let title: String? } diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift index 5f3d6e2..637900f 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift @@ -1,6 +1,7 @@ import Foundation extension PodcastTranscript { + /// A private enum representing known MIME types for the transcript. private enum KnownMimeType: String, Codable { case plain = "text/plain" case html = "text/html" @@ -9,11 +10,13 @@ extension PodcastTranscript { case json = "application/json" case subrip = "application/x-subrip" + /// Initializes a `KnownMimeType` with a case-insensitive string. init?(caseInsensitive: String) { self.init(rawValue: caseInsensitive) } - // swiftlint:disable:next cyclomatic_complexity + // swiftlint:disable cyclomatic_complexity + /// Initializes a `KnownMimeType` with a `MimeType`. init?(mimeType: MimeType) { switch mimeType { case .plain: @@ -38,8 +41,11 @@ extension PodcastTranscript { return nil } } + + // swiftlint:enable cyclomatic_complexity } + /// An enum representing the MIME type of the transcript. public enum MimeType: Codable, Equatable, RawRepresentable { case plain case html @@ -49,6 +55,7 @@ extension PodcastTranscript { case subrip case unknown(String) + /// The raw value of the MIME type. public var rawValue: String { if let knownMimeType = KnownMimeType(mimeType: self) { return knownMimeType.rawValue @@ -62,10 +69,12 @@ extension PodcastTranscript { } } + /// Initializes a `MimeType` with a raw value. public init?(rawValue: String) { self.init(caseInsensitive: rawValue) } + /// Initializes a `MimeType` with a case-insensitive string. public init(caseInsensitive: String) { if let knownMimeType = KnownMimeType(caseInsensitive: caseInsensitive) { self = .init(knownMimeType: knownMimeType) @@ -74,6 +83,7 @@ extension PodcastTranscript { } } + /// Initializes a `MimeType` with a `KnownMimeType`. private init(knownMimeType: KnownMimeType) { switch knownMimeType { case .plain: diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript.swift index 67f5eba..89bf654 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript.swift @@ -1,6 +1,8 @@ import Foundation +/// A struct representing a podcast transcript. public struct PodcastTranscript: Codable, Equatable { + /// The coding keys for the podcast transcript. public enum CodingKeys: String, CodingKey { case url case type @@ -8,12 +10,20 @@ public struct PodcastTranscript: Codable, Equatable { case rel } + /// The relationship between the podcast transcript and the podcast. public enum Relationship: String, Codable { case captions } + /// The URL of the podcast transcript. public let url: URL + + /// The MIME type of the podcast transcript. public let type: MimeType + + /// The language of the podcast transcript. public let language: String? + + /// The relationship of the podcast transcript. public let rel: Relationship? } diff --git a/Sources/SyndiKit/Formats/Media/Video.swift b/Sources/SyndiKit/Formats/Media/Video.swift index 5882919..60e7a7d 100644 --- a/Sources/SyndiKit/Formats/Media/Video.swift +++ b/Sources/SyndiKit/Formats/Media/Video.swift @@ -1,3 +1,9 @@ +/** + An enumeration representing different types of videos. + */ public enum Video { + /// A video from YouTube. + /// - Parameters: + /// - id: The ID of the YouTube video. case youtube(YouTubeID) } diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WPCategory.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WPCategory.swift index ae4bf37..4885501 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WPCategory.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WPCategory.swift @@ -1,10 +1,13 @@ import Foundation +/// A typealias for the `WordPressElements.Category` type. public typealias WPCategory = WordPressElements.Category // swiftlint:disable nesting extension WordPressElements { + /// A struct representing a category in WordPress. public struct Category: Codable { + /// The coding keys for the `Category` struct. internal enum CodingKeys: String, CodingKey { case termID = "wp:termId" case niceName = "wp:categoryNicename" @@ -12,10 +15,27 @@ extension WordPressElements { case name = "wp:catName" } + /// The unique identifier of the category. public let termID: Int + + /// The nice name of the category. public let niceName: CData + + /// The parent category of the category. public let parent: CData + + /// The name of the category. public let name: String + + /** + Initializes a new `Category` instance. + + - Parameters: + - termID: The unique identifier of the category. + - niceName: The nice name of the category. + - parent: The parent category of the category. + - name: The name of the category. + */ public init(termID: Int, niceName: CData, parent: CData, name: String) { self.termID = termID self.niceName = niceName @@ -26,6 +46,7 @@ extension WordPressElements { } extension WordPressElements.Category: Equatable { + /// Checks if two `Category` instances are equal. public static func == ( lhs: WordPressElements.Category, rhs: WordPressElements.Category diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WPPostMeta.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WPPostMeta.swift index f3537b3..e2a8692 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WPPostMeta.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WPPostMeta.swift @@ -1,18 +1,31 @@ import Foundation +/// A typealias for `WordPressElements.Category`. public typealias WPPostMeta = WordPressElements.Category // swiftlint:disable nesting extension WordPressElements { + /// A struct representing metadata for a WordPress post. public struct PostMeta: Codable { + /// The coding keys for encoding and decoding. internal enum CodingKeys: String, CodingKey { case key = "wp:metaKey" case value = "wp:metaValue" } + /// The key of the metadata. public let key: CData + + /// The value of the metadata. public let value: CData + /** + Initializes a new `PostMeta` instance. + + - Parameters: + - key: The key of the metadata. + - value: The value of the metadata. + */ public init(key: String, value: String) { self.key = .init(stringLiteral: key) self.value = .init(stringLiteral: value) @@ -21,6 +34,15 @@ extension WordPressElements { } extension WordPressElements.PostMeta: Equatable { + /** + Checks if two `PostMeta` instances are equal. + + - Parameters: + - lhs: The left-hand side `PostMeta` instance. + - rhs: The right-hand side `PostMeta` instance. + + - Returns: `true` if the two instances are equal, `false` otherwise. + */ public static func == ( lhs: WordPressElements.PostMeta, rhs: WordPressElements.PostMeta diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WPTag.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WPTag.swift index 1b82837..7764ce5 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WPTag.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WPTag.swift @@ -1,20 +1,36 @@ import Foundation +/// A typealias for `WordPressElements.Tag` public typealias WPTag = WordPressElements.Tag // swiftlint:disable nesting extension WordPressElements { + /// A struct representing a tag in WordPress. public struct Tag: Codable { + /// The term ID of the tag. internal enum CodingKeys: String, CodingKey { case termID = "wp:termId" case slug = "wp:tagSlug" case name = "wp:tagName" } + /// The term ID of the tag. public let termID: Int + + /// The slug of the tag. public let slug: CData + + /// The name of the tag. public let name: CData + /** + Initializes a new `Tag` instance. + + - Parameters: + - termID: The term ID of the tag. + - slug: The slug of the tag. + - name: The name of the tag. + */ public init(termID: Int, slug: CData, name: CData) { self.termID = termID self.slug = slug @@ -24,6 +40,7 @@ extension WordPressElements { } extension WordPressElements.Tag: Equatable { + /// Checks if two `Tag` instances are equal. public static func == (lhs: WordPressElements.Tag, rhs: WordPressElements.Tag) -> Bool { lhs.termID == rhs.termID && lhs.slug == rhs.slug diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+RSSItem.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+RSSItem.swift index d290a97..beb2bd6 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+RSSItem.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+RSSItem.swift @@ -1,7 +1,17 @@ import Foundation extension WordPressPost { - // swiftlint:disable:next cyclomatic_complexity function_body_length + // swiftlint:disable cyclomatic_complexity function_body_length + /** + Initializes a `WordPressPost` instance from an `RSSItem`. + + - Parameter item: The `RSSItem` to initialize from. + + - Throws: `WordPressError.missingField` if any required field is missing. + + - Note: This initializer is marked as `public` to allow external usage. + + */ public init(item: RSSItem) throws { guard let name = item.wpPostName else { throw WordPressError.missingField(.name) @@ -80,4 +90,6 @@ extension WordPressPost { self.modifiedDate = modifiedDate attachmentURL = item.wpAttachmentURL } + + // swiftlint:enable cyclomatic_complexity function_body_length } diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift index f2929e0..ff58fc1 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift @@ -1,17 +1,28 @@ import Foundation +/// A namespace for WordPress related elements. public enum WordPressElements {} +/// An error type representing a missing field in a WordPress post. public enum WordPressError: Error, Equatable { case missingField(WordPressPost.Field) } +/// A struct representing a WordPress post. public struct WordPressPost { + /// The type of the post. public typealias PostType = String + + /// The comment status of the post. public typealias CommentStatus = String + + /// The ping status of the post. public typealias PingStatus = String + + /// The status of the post. public typealias Status = String + /// An enum representing the fields of a WordPress post. public enum Field: Equatable { case name case title @@ -36,27 +47,70 @@ public struct WordPressPost { case modifiedDateGMT } + /// The name of the post. public let name: String + + /// The title of the post. public let title: String + + /// The type of the post. public let type: PostType + + /// The link of the post. public let link: URL + + /// The publication date of the post. public let pubDate: Date? + + /// The creator of the post. public let creator: String + + /// The body of the post. public let body: String + + /// The tags of the post. public let tags: [String] + + /// The categories of the post. public let categories: [String] + + /// The meta data of the post. public let meta: [String: String] + + /// The status of the post. public let status: Status + + /// The comment status of the post. public let commentStatus: CommentStatus + + /// The ping status of the post. public let pingStatus: PingStatus + + /// The parent ID of the post. public let parentID: Int? + + /// The menu order of the post. public let menuOrder: Int? + + /// The ID of the post. public let ID: Int + + /// A boolean indicating if the post is sticky. public let isSticky: Bool + + /// The post date of the post. public let postDate: Date + + /// The post date in GMT of the post. public let postDateGMT: Date? + + /// The modified date of the post. public let modifiedDate: Date + + /// The modified date in GMT of the post. public let modifiedDateGMT: Date? + + /// The attachment URL of the post. public let attachmentURL: URL? } @@ -71,6 +125,7 @@ extension WordPressPost: Hashable { } extension Entryable { + /// Returns a WordPress post if the entry is an RSS item. public var wpPost: WordPressPost? { guard let rssItem = self as? RSSItem else { return nil diff --git a/Sources/SyndiKit/Formats/Media/YouTube/YouTubeID.swift b/Sources/SyndiKit/Formats/Media/YouTube/YouTubeID.swift index b36ec27..734ff6e 100644 --- a/Sources/SyndiKit/Formats/Media/YouTube/YouTubeID.swift +++ b/Sources/SyndiKit/Formats/Media/YouTube/YouTubeID.swift @@ -1,8 +1,29 @@ +/** + A struct representing the properties of a YouTube ID. + + - Note: This struct conforms to the `YouTubeID` protocol. + + - SeeAlso: `YouTubeID` + + - Important: This struct is internal. + + - Parameters: + - videoID: The YouTube video ID. + - channelID: The YouTube channel ID. + */ internal struct YouTubeIDProperties: YouTubeID { internal let videoID: String - internal let channelID: String + /** + Initializes a `YouTubeIDProperties` instance with the given AtomEntry. + + - Parameters: + - entry: The AtomEntry containing the YouTube ID properties. + + - Returns: A new `YouTubeIDProperties` instance, + or `nil` if the required properties are missing. + */ internal init?(entry: AtomEntry) { guard let channelID = entry.youtubeChannelID, @@ -14,15 +35,21 @@ internal struct YouTubeIDProperties: YouTubeID { } } -/// Specific type abstracting the id properties a YouTube RSS Feed. -/// ```xml -/// 3hccNoPE59U -/// UCv75sKQFFIenWHrprnrR9aA -/// ``` +/** + A protocol abstracting the ID properties of a YouTube RSS Feed. + + - Note: This protocol is public. + + - SeeAlso: `YouTubeIDProperties` + + - Important: This protocol is specific to YouTube. + + - Requires: Conforming types must provide a `videoID` and a `channelID`. + */ public protocol YouTubeID { - /// YouTube video ID. + /// The YouTube video ID. var videoID: String { get } - /// YouTube channel ID. + /// The YouTube channel ID. var channelID: String { get } } diff --git a/Sources/SyndiKit/Formats/Media/iTunes/iTunesDuration.swift b/Sources/SyndiKit/Formats/Media/iTunes/iTunesDuration.swift index 98dc513..bdf6747 100644 --- a/Sources/SyndiKit/Formats/Media/iTunes/iTunesDuration.swift +++ b/Sources/SyndiKit/Formats/Media/iTunes/iTunesDuration.swift @@ -1,14 +1,25 @@ import Foundation -// swiftlint:disable:next type_name + +/// A struct representing the duration of an iTunes track. public struct iTunesDuration: Codable, ExpressibleByFloatLiteral { + /// The type used to represent a floating-point literal. public typealias FloatLiteralType = TimeInterval + /// The value of the duration in seconds. public let value: TimeInterval + /// Creates a new instance with the specified floating-point literal value. + /// + /// - Parameter value: The value of the duration in seconds. public init(floatLiteral value: TimeInterval) { self.value = value } + /// Creates a new instance by decoding from the given decoder. + /// + /// - Parameter decoder: The decoder to read data from. + /// - Throws: An error if reading from the decoder fails, + /// or if the data is corrupted or invalid. public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let stringValue = try container.decode(String.self) @@ -23,6 +34,10 @@ public struct iTunesDuration: Codable, ExpressibleByFloatLiteral { self.value = value } + /// Creates a new instance from the given description string. + /// + /// - Parameter description: The description string representing the duration. + /// - Returns: A new instance if the description is valid, otherwise `nil`. public init?(_ description: String) { guard let value = Self.timeInterval(description) else { return nil @@ -30,6 +45,11 @@ public struct iTunesDuration: Codable, ExpressibleByFloatLiteral { self.value = value } + /// Converts a time string to a `TimeInterval` value. + /// + /// - Parameter timeString: The time string to convert. + /// - Returns: The `TimeInterval` value representing the time string, + /// or `nil` if the string is invalid. internal static func timeInterval(_ timeString: String) -> TimeInterval? { let timeStrings = timeString.components(separatedBy: ":").prefix(3) let doubles = timeStrings.compactMap(Double.init) diff --git a/Sources/SyndiKit/Formats/Media/iTunes/iTunesEpisode.swift b/Sources/SyndiKit/Formats/Media/iTunes/iTunesEpisode.swift index 3e54ed2..dabfd0f 100644 --- a/Sources/SyndiKit/Formats/Media/iTunes/iTunesEpisode.swift +++ b/Sources/SyndiKit/Formats/Media/iTunes/iTunesEpisode.swift @@ -1,2 +1,8 @@ -// swiftlint:disable:next type_name +/** + A type alias for an iTunes episode. + + - Note: This type is an alias for `XMLStringInt`. + + - SeeAlso: `XMLStringInt` + */ public typealias iTunesEpisode = XMLStringInt diff --git a/Sources/SyndiKit/Formats/Media/iTunes/iTunesImage.swift b/Sources/SyndiKit/Formats/Media/iTunes/iTunesImage.swift index a4fac9f..0f34f66 100644 --- a/Sources/SyndiKit/Formats/Media/iTunes/iTunesImage.swift +++ b/Sources/SyndiKit/Formats/Media/iTunes/iTunesImage.swift @@ -1,3 +1,4 @@ import Foundation -// swiftlint:disable:next type_name + +/// A type alias for iTunes image links. public typealias iTunesImage = Link diff --git a/Sources/SyndiKit/Formats/Media/iTunes/iTunesOwner.swift b/Sources/SyndiKit/Formats/Media/iTunes/iTunesOwner.swift index b5e3383..1118fd5 100644 --- a/Sources/SyndiKit/Formats/Media/iTunes/iTunesOwner.swift +++ b/Sources/SyndiKit/Formats/Media/iTunes/iTunesOwner.swift @@ -1,10 +1,28 @@ -// swiftlint:disable:next type_name +/** + A struct representing the owner of an iTunes account. + + - Note: This struct conforms to the `Codable` protocol. + + - Warning: Do not modify the `CodingKeys` enum. + + - SeeAlso: `CodingKeys` + + - Remark: The `email` property is optional. + + - Important: The `name` property is required. + + - Version: 1.0 + */ public struct iTunesOwner: Codable { + /// The coding keys used to encode and decode the struct. internal enum CodingKeys: String, CodingKey { case name = "itunes:name" case email = "itunes:email" } + /// The name of the iTunes owner. public let name: String + + /// The email address of the iTunes owner. public let email: String? }