Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Sources/FeedKit/FeedNamespace.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ enum FeedNamespace: CaseIterable {
/// Represents the Atom feed namespace, typically used for syndication
/// in the Atom format.
case atom
/// Represents the podcast namespace.
case podcast

// MARK: Internal

Expand All @@ -81,6 +83,8 @@ enum FeedNamespace: CaseIterable {
"xmlns:yt"
case .atom:
"xmlns:atom"
case .podcast:
"xmlns:podcast"
}
}

Expand All @@ -105,6 +109,8 @@ enum FeedNamespace: CaseIterable {
"http://www.youtube.com/xml/schemas/2015"
case .atom:
"http://www.w3.org/2005/Atom"
case .podcast:
"https://podcastindex.org/namespace/1.0"
}
}
}
Expand Down Expand Up @@ -145,6 +151,9 @@ extension FeedNamespace {

case .atom:
feed.channel?.atom != nil

case .podcast:
feed.channel?.podcast != nil
}
}

Expand Down
11 changes: 10 additions & 1 deletion Sources/FeedKit/Feeds/RSS/RSSFeedChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public struct RSSFeedChannel {
dublinCore: DublinCore? = nil,
iTunes: ITunes? = nil,
syndication: Syndication? = nil,
atom: Atom? = nil
atom: Atom? = nil,
podcast: Podcast? = nil
) {
self.title = title
self.link = link
Expand All @@ -86,6 +87,7 @@ public struct RSSFeedChannel {
self.iTunes = iTunes
self.syndication = syndication
self.atom = atom
self.podcast = podcast
}

// MARK: Public
Expand Down Expand Up @@ -307,6 +309,10 @@ public struct RSSFeedChannel {
/// and hub information.
/// See https://www.w3.org/TR/websub/#discovery
public var atom: Atom?

/// A wholistic RSS namespace for podcasting that is meant to synthesize the fragmented world of podcast namespaces.
/// See https://github.com/Podcastindex-org/podcast-namespace
public var podcast: Podcast?
}

// MARK: - Sendable
Expand Down Expand Up @@ -349,6 +355,7 @@ extension RSSFeedChannel: Codable {
case iTunes = "itunes"
case syndication = "sy"
case atom
case podcast
}

public init(from decoder: any Decoder) throws {
Expand Down Expand Up @@ -378,6 +385,7 @@ extension RSSFeedChannel: Codable {
iTunes = try container.decodeIfPresent(ITunes.self, forKey: CodingKeys.iTunes)
syndication = try container.decodeIfPresent(Syndication.self, forKey: CodingKeys.syndication)
atom = try container.decodeIfPresent(Atom.self, forKey: CodingKeys.atom)
podcast = try container.decodeIfPresent(Podcast.self, forKey: CodingKeys.podcast)
}

public func encode(to encoder: any Encoder) throws {
Expand Down Expand Up @@ -407,5 +415,6 @@ extension RSSFeedChannel: Codable {
try container.encodeIfPresent(iTunes, forKey: CodingKeys.iTunes)
try container.encodeIfPresent(syndication, forKey: CodingKeys.syndication)
try container.encodeIfPresent(atom, forKey: CodingKeys.atom)
try container.encodeIfPresent(podcast, forKey: CodingKeys.podcast)
}
}
58 changes: 58 additions & 0 deletions Sources/FeedKit/Namespaces/Podcast/Podcast.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Foundation
import XMLKit

/// The podcast namespace
///
/// See https://github.com/Podcastindex-org/podcast-namespace
public struct Podcast {
// MARK: Lifecycle

public init(
guid: String? = nil

) {
self.guid = guid
}

// MARK: Public
/// This element is used to declare a unique, global identifier for a podcast.
/// See https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/tags/guid.md
public var guid: String?
}

// MARK: - XMLNamespaceDecodable

extension Podcast: XMLNamespaceCodable {}

// MARK: - Sendable

extension Podcast: Sendable {}

// MARK: - Equatable

extension Podcast: Equatable {}

// MARK: - Hashable

extension Podcast: Hashable {}

// MARK: - Codable

extension Podcast: Codable {
private enum CodingKeys: String, CodingKey {
case guid = "podcast:guid"
}

public init(from decoder: any Decoder) throws {
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(
keyedBy: CodingKeys.self)

guid = try container.decodeIfPresent(String.self, forKey: CodingKeys.guid)
}

public func encode(to encoder: any Encoder) throws {
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)

try container.encodeIfPresent(guid, forKey: CodingKeys.guid)
}
}
Loading