From 85b8a2f7ccaccc6d2158188d0d6e6aeed6d65b4f Mon Sep 17 00:00:00 2001
From: Ahmed Shendy <dev.ahmed.shendy@gmail.com>
Date: Thu, 25 Jan 2024 18:23:41 +0200
Subject: [PATCH] Any other lint violations that are not 'Missing Docs
 Violation' (#68)

* lint-fixes: any voilation that is not 'Missing Docs Violation'

* fixup! Merge branch 'v0.4.0-STRICT-changes' into v0.4.0-STRICT-others

---------

Co-authored-by: leogdion <leogdion@brightdigit.com>
---
 Sources/SyndiKit/Common/Author.swift          |   2 +-
 .../Decoding/DateFormatterDecoder.swift       |   4 -
 Sources/SyndiKit/Decoding/DecodingError.swift |  12 ++
 Sources/SyndiKit/Decoding/SynDecoder.swift    |   1 +
 .../Formats/Blogs/SiteDirectory.swift         |   1 +
 .../Formats/Feeds/RSS/Enclosure.swift         |  14 +-
 .../Formats/Feeds/RSS/RSSItem+decodings.swift | 117 ++++++++++
 .../Formats/Feeds/RSS/RSSItem+inits.swift     |  91 ++++++++
 .../SyndiKit/Formats/Feeds/RSS/RSSItem.swift  | 200 ------------------
 .../Media/Podcast/PodcastEpisode.swift        |  24 +--
 .../Podcast/PodcastLocation+GeoURI.swift      |  19 +-
 .../Podcast/PodcastLocation+OsmQuery.swift    |  16 +-
 .../Podcast/PodcastTranscript+MimeType.swift  |   1 +
 .../Wordpress/WordPressPost+RSSItem.swift     |  83 ++++++++
 .../Media/Wordpress/WordPressPost.swift       | 130 ------------
 15 files changed, 340 insertions(+), 375 deletions(-)
 create mode 100644 Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+decodings.swift
 create mode 100644 Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+inits.swift
 create mode 100644 Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+RSSItem.swift

diff --git a/Sources/SyndiKit/Common/Author.swift b/Sources/SyndiKit/Common/Author.swift
index 75bce78..8c2933e 100644
--- a/Sources/SyndiKit/Common/Author.swift
+++ b/Sources/SyndiKit/Common/Author.swift
@@ -11,7 +11,7 @@ public struct Author: Codable, Equatable {
   /// Contains a home page for the person.
   public let uri: URL?
 
-  internal init(name: String) {
+  public init(name: String) {
     self.name = name
     email = nil
     uri = nil
diff --git a/Sources/SyndiKit/Decoding/DateFormatterDecoder.swift b/Sources/SyndiKit/Decoding/DateFormatterDecoder.swift
index 2cac0cc..56ffc21 100644
--- a/Sources/SyndiKit/Decoding/DateFormatterDecoder.swift
+++ b/Sources/SyndiKit/Decoding/DateFormatterDecoder.swift
@@ -16,10 +16,6 @@ internal struct DateFormatterDecoder {
 
   private let formatters: [DateFormatter]
 
-  internal init(formatters: [DateFormatter]) {
-    self.formatters = formatters
-  }
-
   internal init(basedOnFormats formats: [String]) {
     formatters = formats.map(Self.isoPOSIX(withFormat:))
   }
diff --git a/Sources/SyndiKit/Decoding/DecodingError.swift b/Sources/SyndiKit/Decoding/DecodingError.swift
index 3cc52f0..081a0fa 100644
--- a/Sources/SyndiKit/Decoding/DecodingError.swift
+++ b/Sources/SyndiKit/Decoding/DecodingError.swift
@@ -20,4 +20,16 @@ extension DecodingError {
     )
     return DecodingError.dataCorrupted(context)
   }
+
+  internal static func dataCorrupted(
+    codingKey: CodingKey,
+    debugDescription: String
+  ) -> Self {
+    DecodingError.dataCorrupted(
+      .init(
+        codingPath: [codingKey],
+        debugDescription: debugDescription
+      )
+    )
+  }
 }
diff --git a/Sources/SyndiKit/Decoding/SynDecoder.swift b/Sources/SyndiKit/Decoding/SynDecoder.swift
index ee7cb3a..9bc0cf6 100644
--- a/Sources/SyndiKit/Decoding/SynDecoder.swift
+++ b/Sources/SyndiKit/Decoding/SynDecoder.swift
@@ -34,6 +34,7 @@ public class SynDecoder {
     return decoder
   }()
 
+  // swiftlint:disable:next closure_body_length
   private lazy var decodings: [DecoderSource: [String: AnyDecoding]] = {
     let decodings = types.map { type -> (DecoderSource, AnyDecoding) in
       let source = type.source
diff --git a/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift b/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift
index 960183d..b009695 100644
--- a/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift
+++ b/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift
@@ -16,6 +16,7 @@ public struct SiteCollectionDirectory: SiteDirectory {
     internal let languageIndicies: [SiteLanguageType: Set<Int>]
     internal let categoryIndicies: [SiteCategoryType: Set<Int>]
 
+    // swiftlint:disable:next function_body_length
     internal func sites(
       withLanguage language: SiteLanguageType?,
       withCategory category: SiteCategoryType?
diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/Enclosure.swift b/Sources/SyndiKit/Formats/Feeds/RSS/Enclosure.swift
index 41d2ea3..23f711d 100644
--- a/Sources/SyndiKit/Formats/Feeds/RSS/Enclosure.swift
+++ b/Sources/SyndiKit/Formats/Feeds/RSS/Enclosure.swift
@@ -15,21 +15,27 @@ public struct Enclosure: Codable {
     let container = try decoder.container(keyedBy: Self.CodingKeys.self)
     url = try container.decode(UTF8EncodedURL.self, forKey: .url).value
     type = try container.decode(String.self, forKey: .type)
+    length = try Self.decodeLength(from: container)
+  }
+
+  private static func decodeLength(
+    from container: KeyedDecodingContainer<CodingKeys>
+  ) throws -> Int? {
     if container.contains(.length) {
       do {
-        length = try container.decode(Int.self, forKey: .length)
+        return try container.decode(Int.self, forKey: .length)
       } catch {
         let lengthString = try container.decode(String.self, forKey: .length)
         if lengthString.isEmpty {
-          length = nil
+          return nil
         } else if let length = Int(lengthString) {
-          self.length = length
+          return length
         } else {
           throw error
         }
       }
     } else {
-      length = nil
+      return nil
     }
   }
 }
diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+decodings.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+decodings.swift
new file mode 100644
index 0000000..b271175
--- /dev/null
+++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+decodings.swift
@@ -0,0 +1,117 @@
+import Foundation
+import XMLCoder
+
+extension RSSItem {
+  // swiftlint:disable:next function_body_length
+  public init(from decoder: Decoder) throws {
+    let container = try decoder.container(keyedBy: CodingKeys.self)
+    title = try container.decode(String.self, forKey: .title)
+    link = try container.decodeIfPresent(URL.self, forKey: .link)
+    description = try container.decodeIfPresent(CData.self, forKey: .description)
+    guid = try container.decode(EntryID.self, forKey: .guid)
+    pubDate = try container.decodeDateIfPresentAndValid(forKey: .pubDate)
+    contentEncoded = try container.decodeIfPresent(CData.self, forKey: .contentEncoded)
+    categoryTerms = try container.decode([RSSItemCategory].self, forKey: .categoryTerms)
+    content = try container.decodeIfPresent(String.self, forKey: .content)
+    itunesTitle = try container.decodeIfPresent(String.self, forKey: .itunesTitle)
+    itunesEpisode = try container.decodeIfPresent(
+      iTunesEpisode.self, forKey: .itunesEpisode
+    )
+    itunesAuthor = try container.decodeIfPresent(String.self, forKey: .itunesAuthor)
+    itunesSubtitle = try container.decodeIfPresent(String.self, forKey: .itunesSubtitle)
+    itunesSummary = try container.decodeIfPresent(CData.self, forKey: .itunesSummary)
+    itunesExplicit = try container.decodeIfPresent(String.self, forKey: .itunesExplicit)
+    itunesDuration = try container.decodeIfPresent(
+      iTunesDuration.self, forKey: .itunesDuration
+    )
+    itunesImage = try container.decodeIfPresent(iTunesImage.self, forKey: .itunesImage)
+
+    podcastPeople = try container.decodeIfPresent(
+      [PodcastPerson].self,
+      forKey: .podcastPeople
+    ) ?? []
+    podcastTranscripts = try container.decodeIfPresent(
+      [PodcastTranscript].self,
+      forKey: .podcastTranscripts
+    ) ?? []
+    podcastChapters = try container.decodeIfPresent(
+      PodcastChapters.self,
+      forKey: .podcastChapters
+    )
+    podcastSoundbites = try container.decodeIfPresent(
+      [PodcastSoundbite].self,
+      forKey: .podcastSoundbites
+    ) ?? []
+
+    podcastSeason = try container.decodeIfPresent(
+      PodcastSeason.self,
+      forKey: .podcastSeason
+    )
+
+    enclosure = try container.decodeIfPresent(Enclosure.self, forKey: .enclosure)
+    creators = try container.decode([String].self, forKey: .creators)
+
+    mediaContent =
+      try container.decodeIfPresent(AtomMedia.self, forKey: .mediaContent)
+    mediaThumbnail =
+      try container.decodeIfPresent(AtomMedia.self, forKey: .mediaThumbnail)
+
+    wpPostID = try container.decodeIfPresent(Int.self, forKey: .wpPostID)
+    wpPostDate = try container.decodeIfPresent(Date.self, forKey: .wpPostDate)
+    let wpPostDateGMT = try container.decodeIfPresent(
+      String.self, forKey: .wpPostDateGMT
+    )
+    if let wpPostDateGMT = wpPostDateGMT {
+      if wpPostDateGMT == "0000-00-00 00:00:00" {
+        self.wpPostDateGMT = nil
+      } else {
+        self.wpPostDateGMT = try container.decode(
+          Date.self, forKey: .wpPostDateGMT
+        )
+      }
+    } else {
+      self.wpPostDateGMT = nil
+    }
+
+    wpModifiedDate = try container.decodeIfPresent(
+      Date.self, forKey: .wpModifiedDate
+    )
+
+    let wpModifiedDateGMT = try container.decodeIfPresent(
+      String.self, forKey: .wpModifiedDateGMT
+    )
+    if let wpModifiedDateGMT = wpModifiedDateGMT {
+      if wpModifiedDateGMT == "0000-00-00 00:00:00" {
+        self.wpModifiedDateGMT = nil
+      } else {
+        self.wpModifiedDateGMT = try container.decode(
+          Date.self, forKey: .wpModifiedDateGMT
+        )
+      }
+    } else {
+      self.wpModifiedDateGMT = nil
+    }
+
+    let wpAttachmentURLCDData = try container.decodeIfPresent(
+      CData.self,
+      forKey: .wpAttachmentURL
+    )
+    wpAttachmentURL = wpAttachmentURLCDData.map { $0.value }.flatMap(URL.init(string:))
+
+    wpPostName = try container.decodeIfPresent(CData.self, forKey: .wpPostName)
+    wpPostType = try container.decodeIfPresent(CData.self, forKey: .wpPostType)
+    wpPostMeta = try container.decodeIfPresent(
+      [WordPressElements.PostMeta].self,
+      forKey: .wpPostMeta
+    ) ?? []
+    wpCommentStatus = try container.decodeIfPresent(CData.self, forKey: .wpCommentStatus)
+    wpPingStatus = try container.decodeIfPresent(CData.self, forKey: .wpPingStatus)
+    wpStatus = try container.decodeIfPresent(CData.self, forKey: .wpStatus)
+    wpPostParent = try container.decodeIfPresent(Int.self, forKey: .wpPostParent)
+    wpMenuOrder = try container.decodeIfPresent(Int.self, forKey: .wpMenuOrder)
+    wpIsSticky = try container.decodeIfPresent(Int.self, forKey: .wpIsSticky)
+    wpPostPassword = try container.decodeIfPresent(
+      CData.self, forKey: .wpPostPassword
+    )
+  }
+}
diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+inits.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+inits.swift
new file mode 100644
index 0000000..4431eea
--- /dev/null
+++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+inits.swift
@@ -0,0 +1,91 @@
+import Foundation
+import XMLCoder
+
+extension RSSItem {
+  // swiftlint:disable:next function_body_length
+  public init(
+    title: String,
+    link: URL,
+    description: String?,
+    guid: EntryID,
+    pubDate: Date? = nil,
+    contentEncoded: String? = nil,
+    categoryTerms: [RSSItemCategory] = [],
+    content: String? = nil,
+    itunesTitle: String? = nil,
+    itunesEpisode: Int? = nil,
+    itunesAuthor: String? = nil,
+    itunesSubtitle: String? = nil,
+    itunesSummary: CData? = nil,
+    itunesExplicit: String? = nil,
+    itunesDuration: TimeInterval? = nil,
+    itunesImage: iTunesImage? = nil,
+    podcastPeople: [PodcastPerson] = [],
+    podcastTranscripts: [PodcastTranscript] = [],
+    podcastChapters: PodcastChapters? = nil,
+    podcastSoundbites: [PodcastSoundbite] = [],
+    podcastSeason: PodcastSeason? = nil,
+    enclosure: Enclosure? = nil,
+    creators: [String] = [],
+    wpCommentStatus: String? = nil,
+    wpPingStatus: String? = nil,
+    wpStatus: String? = nil,
+    wpPostParent: Int? = nil,
+    wpMenuOrder: Int? = nil,
+    wpIsSticky: Int? = nil,
+    wpPostPassword: String? = nil,
+    wpPostID: Int? = nil,
+    wpPostDate: Date? = nil,
+    wpPostDateGMT: Date? = nil,
+    wpModifiedDate: Date? = nil,
+    wpModifiedDateGMT: Date? = nil,
+    wpPostName: String? = nil,
+    wpPostType: String? = nil,
+    wpPostMeta: [WordPressElements.PostMeta] = [],
+    wpAttachmentURL: URL? = nil,
+    mediaContent: AtomMedia? = nil,
+    mediaThumbnail: AtomMedia? = nil
+  ) {
+    self.title = title
+    self.link = link
+    self.description = description.map(CData.init)
+    self.guid = guid
+    self.pubDate = pubDate
+    self.contentEncoded = contentEncoded.map(CData.init)
+    self.categoryTerms = categoryTerms
+    self.content = content
+    self.itunesTitle = itunesTitle
+    self.itunesEpisode = itunesEpisode.map(iTunesEpisode.init)
+    self.itunesAuthor = itunesAuthor
+    self.itunesSubtitle = itunesSubtitle
+    self.itunesSummary = itunesSummary
+    self.itunesExplicit = itunesExplicit
+    self.itunesDuration = itunesDuration.map(iTunesDuration.init)
+    self.itunesImage = itunesImage
+    self.podcastPeople = podcastPeople
+    self.podcastTranscripts = podcastTranscripts
+    self.podcastChapters = podcastChapters
+    self.podcastSoundbites = podcastSoundbites
+    self.podcastSeason = podcastSeason
+    self.enclosure = enclosure
+    self.creators = creators
+    self.wpCommentStatus = wpCommentStatus.map(CData.init)
+    self.wpPingStatus = wpPingStatus.map(CData.init)
+    self.wpStatus = wpStatus.map(CData.init)
+    self.wpPostParent = wpPostParent
+    self.wpMenuOrder = wpMenuOrder
+    self.wpIsSticky = wpIsSticky
+    self.wpPostPassword = wpPostPassword.map(CData.init)
+    self.wpPostID = wpPostID
+    self.wpPostDate = wpPostDate
+    self.wpPostDateGMT = wpPostDateGMT
+    self.wpModifiedDate = wpModifiedDate
+    self.wpModifiedDateGMT = wpModifiedDateGMT
+    self.wpPostName = wpPostName.map(CData.init)
+    self.wpPostType = wpPostType.map(CData.init)
+    self.wpPostMeta = wpPostMeta
+    self.wpAttachmentURL = wpAttachmentURL
+    self.mediaContent = mediaContent
+    self.mediaThumbnail = mediaThumbnail
+  }
+}
diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem.swift
index 744515a..ab32f67 100644
--- a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem.swift
+++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem.swift
@@ -90,206 +90,6 @@ public struct RSSItem: Codable {
   public let wpAttachmentURL: URL?
   public let mediaContent: AtomMedia?
   public let mediaThumbnail: AtomMedia?
-
-  // swiftlint:disable:next function_body_length
-  public init(
-    title: String,
-    link: URL,
-    description: String?,
-    guid: EntryID,
-    pubDate: Date? = nil,
-    contentEncoded: String? = nil,
-    categoryTerms: [RSSItemCategory] = [],
-    content: String? = nil,
-    itunesTitle: String? = nil,
-    itunesEpisode: Int? = nil,
-    itunesAuthor: String? = nil,
-    itunesSubtitle: String? = nil,
-    itunesSummary: CData? = nil,
-    itunesExplicit: String? = nil,
-    itunesDuration: TimeInterval? = nil,
-    itunesImage: iTunesImage? = nil,
-    podcastPeople: [PodcastPerson] = [],
-    podcastTranscripts: [PodcastTranscript] = [],
-    podcastChapters: PodcastChapters? = nil,
-    podcastSoundbites: [PodcastSoundbite] = [],
-    podcastSeason: PodcastSeason? = nil,
-    enclosure: Enclosure? = nil,
-    creators: [String] = [],
-    wpCommentStatus: String? = nil,
-    wpPingStatus: String? = nil,
-    wpStatus: String? = nil,
-    wpPostParent: Int? = nil,
-    wpMenuOrder: Int? = nil,
-    wpIsSticky: Int? = nil,
-    wpPostPassword: String? = nil,
-    wpPostID: Int? = nil,
-    wpPostDate: Date? = nil,
-    wpPostDateGMT: Date? = nil,
-    wpModifiedDate: Date? = nil,
-    wpModifiedDateGMT: Date? = nil,
-    wpPostName: String? = nil,
-    wpPostType: String? = nil,
-    wpPostMeta: [WordPressElements.PostMeta] = [],
-    wpAttachmentURL: URL? = nil,
-    mediaContent: AtomMedia? = nil,
-    mediaThumbnail: AtomMedia? = nil
-  ) {
-    self.title = title
-    self.link = link
-    self.description = description.map(CData.init)
-    self.guid = guid
-    self.pubDate = pubDate
-    self.contentEncoded = contentEncoded.map(CData.init)
-    self.categoryTerms = categoryTerms
-    self.content = content
-    self.itunesTitle = itunesTitle
-    self.itunesEpisode = itunesEpisode.map(iTunesEpisode.init)
-    self.itunesAuthor = itunesAuthor
-    self.itunesSubtitle = itunesSubtitle
-    self.itunesSummary = itunesSummary
-    self.itunesExplicit = itunesExplicit
-    self.itunesDuration = itunesDuration.map(iTunesDuration.init)
-    self.itunesImage = itunesImage
-    self.podcastPeople = podcastPeople
-    self.podcastTranscripts = podcastTranscripts
-    self.podcastChapters = podcastChapters
-    self.podcastSoundbites = podcastSoundbites
-    self.podcastSeason = podcastSeason
-    self.enclosure = enclosure
-    self.creators = creators
-    self.wpCommentStatus = wpCommentStatus.map(CData.init)
-    self.wpPingStatus = wpPingStatus.map(CData.init)
-    self.wpStatus = wpStatus.map(CData.init)
-    self.wpPostParent = wpPostParent
-    self.wpMenuOrder = wpMenuOrder
-    self.wpIsSticky = wpIsSticky
-    self.wpPostPassword = wpPostPassword.map(CData.init)
-    self.wpPostID = wpPostID
-    self.wpPostDate = wpPostDate
-    self.wpPostDateGMT = wpPostDateGMT
-    self.wpModifiedDate = wpModifiedDate
-    self.wpModifiedDateGMT = wpModifiedDateGMT
-    self.wpPostName = wpPostName.map(CData.init)
-    self.wpPostType = wpPostType.map(CData.init)
-    self.wpPostMeta = wpPostMeta
-    self.wpAttachmentURL = wpAttachmentURL
-    self.mediaContent = mediaContent
-    self.mediaThumbnail = mediaThumbnail
-  }
-
-  // swiftlint:disable:next function_body_length
-  public init(from decoder: Decoder) throws {
-    let container = try decoder.container(keyedBy: CodingKeys.self)
-    title = try container.decode(String.self, forKey: .title)
-    link = try container.decodeIfPresent(URL.self, forKey: .link)
-    description = try container.decodeIfPresent(CData.self, forKey: .description)
-    guid = try container.decode(EntryID.self, forKey: .guid)
-    pubDate = try container.decodeDateIfPresentAndValid(forKey: .pubDate)
-    contentEncoded = try container.decodeIfPresent(CData.self, forKey: .contentEncoded)
-    categoryTerms = try container.decode([RSSItemCategory].self, forKey: .categoryTerms)
-    content = try container.decodeIfPresent(String.self, forKey: .content)
-    itunesTitle = try container.decodeIfPresent(String.self, forKey: .itunesTitle)
-    itunesEpisode = try container.decodeIfPresent(
-      iTunesEpisode.self, forKey: .itunesEpisode
-    )
-    itunesAuthor = try container.decodeIfPresent(String.self, forKey: .itunesAuthor)
-    itunesSubtitle = try container.decodeIfPresent(String.self, forKey: .itunesSubtitle)
-    itunesSummary = try container.decodeIfPresent(CData.self, forKey: .itunesSummary)
-    itunesExplicit = try container.decodeIfPresent(String.self, forKey: .itunesExplicit)
-    itunesDuration = try container.decodeIfPresent(
-      iTunesDuration.self, forKey: .itunesDuration
-    )
-    itunesImage = try container.decodeIfPresent(iTunesImage.self, forKey: .itunesImage)
-
-    podcastPeople = try container.decodeIfPresent(
-      [PodcastPerson].self,
-      forKey: .podcastPeople
-    ) ?? []
-    podcastTranscripts = try container.decodeIfPresent(
-      [PodcastTranscript].self,
-      forKey: .podcastTranscripts
-    ) ?? []
-    podcastChapters = try container.decodeIfPresent(
-      PodcastChapters.self,
-      forKey: .podcastChapters
-    )
-    podcastSoundbites = try container.decodeIfPresent(
-      [PodcastSoundbite].self,
-      forKey: .podcastSoundbites
-    ) ?? []
-
-    podcastSeason = try container.decodeIfPresent(
-      PodcastSeason.self,
-      forKey: .podcastSeason
-    )
-
-    enclosure = try container.decodeIfPresent(Enclosure.self, forKey: .enclosure)
-    creators = try container.decode([String].self, forKey: .creators)
-
-    mediaContent =
-      try container.decodeIfPresent(AtomMedia.self, forKey: .mediaContent)
-    mediaThumbnail =
-      try container.decodeIfPresent(AtomMedia.self, forKey: .mediaThumbnail)
-
-    wpPostID = try container.decodeIfPresent(Int.self, forKey: .wpPostID)
-    wpPostDate = try container.decodeIfPresent(Date.self, forKey: .wpPostDate)
-    let wpPostDateGMT = try container.decodeIfPresent(
-      String.self, forKey: .wpPostDateGMT
-    )
-    if let wpPostDateGMT = wpPostDateGMT {
-      if wpPostDateGMT == "0000-00-00 00:00:00" {
-        self.wpPostDateGMT = nil
-      } else {
-        self.wpPostDateGMT = try container.decode(
-          Date.self, forKey: .wpPostDateGMT
-        )
-      }
-    } else {
-      self.wpPostDateGMT = nil
-    }
-
-    wpModifiedDate = try container.decodeIfPresent(
-      Date.self, forKey: .wpModifiedDate
-    )
-
-    let wpModifiedDateGMT = try container.decodeIfPresent(
-      String.self, forKey: .wpModifiedDateGMT
-    )
-    if let wpModifiedDateGMT = wpModifiedDateGMT {
-      if wpModifiedDateGMT == "0000-00-00 00:00:00" {
-        self.wpModifiedDateGMT = nil
-      } else {
-        self.wpModifiedDateGMT = try container.decode(
-          Date.self, forKey: .wpModifiedDateGMT
-        )
-      }
-    } else {
-      self.wpModifiedDateGMT = nil
-    }
-
-    let wpAttachmentURLCDData = try container.decodeIfPresent(
-      CData.self,
-      forKey: .wpAttachmentURL
-    )
-    wpAttachmentURL = wpAttachmentURLCDData.map { $0.value }.flatMap(URL.init(string:))
-
-    wpPostName = try container.decodeIfPresent(CData.self, forKey: .wpPostName)
-    wpPostType = try container.decodeIfPresent(CData.self, forKey: .wpPostType)
-    wpPostMeta = try container.decodeIfPresent(
-      [WordPressElements.PostMeta].self,
-      forKey: .wpPostMeta
-    ) ?? []
-    wpCommentStatus = try container.decodeIfPresent(CData.self, forKey: .wpCommentStatus)
-    wpPingStatus = try container.decodeIfPresent(CData.self, forKey: .wpPingStatus)
-    wpStatus = try container.decodeIfPresent(CData.self, forKey: .wpStatus)
-    wpPostParent = try container.decodeIfPresent(Int.self, forKey: .wpPostParent)
-    wpMenuOrder = try container.decodeIfPresent(Int.self, forKey: .wpMenuOrder)
-    wpIsSticky = try container.decodeIfPresent(Int.self, forKey: .wpIsSticky)
-    wpPostPassword = try container.decodeIfPresent(
-      CData.self, forKey: .wpPostPassword
-    )
-  }
 }
 
 extension RSSItem: Entryable {
diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift
index 1624e14..c868abd 100644
--- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift
+++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift
@@ -1,18 +1,18 @@
 import Foundation
 
-internal struct PodcastEpisodeProperties: PodcastEpisode {
-  internal let title: String?
-  internal let episode: Int?
-  internal let author: String?
-  internal let subtitle: String?
-  internal let summary: String?
-  internal let explicit: String?
-  internal let duration: TimeInterval?
-  internal let image: iTunesImage?
-  internal let enclosure: Enclosure
-  internal let people: [PodcastPerson]
+public struct PodcastEpisodeProperties: PodcastEpisode {
+  public let title: String?
+  public let episode: Int?
+  public let author: String?
+  public let subtitle: String?
+  public let summary: String?
+  public let explicit: String?
+  public let duration: TimeInterval?
+  public let image: iTunesImage?
+  public let enclosure: Enclosure
+  public let people: [PodcastPerson]
 
-  internal init?(rssItem: RSSItem) {
+  public init?(rssItem: RSSItem) {
     guard let enclosure = rssItem.enclosure else {
       return nil
     }
diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift
index 6bc800b..9e1e235 100644
--- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift
+++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift
@@ -37,6 +37,7 @@ extension PodcastLocation {
       try? self.init(singleValue: description)
     }
 
+    // swiftlint:disable:next function_body_length
     public init(singleValue: String) throws {
       let pathComponents = try Self.pathComponents(from: singleValue)
 
@@ -46,10 +47,8 @@ extension PodcastLocation {
         let longitude = geoCoords[safe: 1]?.asDouble()
       else {
         throw DecodingError.dataCorrupted(
-          .init(
-            codingPath: [PodcastLocation.CodingKeys.geo],
-            debugDescription: "Invalid coordinates for geo attribute: \(singleValue)"
-          )
+          codingKey: PodcastLocation.CodingKeys.geo,
+          debugDescription: "Invalid coordinates for geo attribute: \(singleValue)"
         )
       }
 
@@ -80,18 +79,14 @@ extension PodcastLocation {
       guard
         components[safe: 0] == "geo" else {
         throw DecodingError.dataCorrupted(
-          .init(
-            codingPath: [PodcastLocation.CodingKeys.geo],
-            debugDescription: "Invalid prefix for geo attribute: \(string)"
-          )
+          codingKey: PodcastLocation.CodingKeys.geo,
+          debugDescription: "Invalid prefix for geo attribute: \(string)"
         )
       }
       guard let geoPath = components[safe: 1] else {
         throw DecodingError.dataCorrupted(
-          .init(
-            codingPath: [PodcastLocation.CodingKeys.geo],
-            debugDescription: "Invalid path for geo attribute: \(string)"
-          )
+          codingKey: PodcastLocation.CodingKeys.geo,
+          debugDescription: "Invalid path for geo attribute: \(string)"
         )
       }
 
diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift
index 2f14900..77abcc8 100644
--- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift
+++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift
@@ -7,10 +7,6 @@ extension PodcastLocation {
       case node = "N"
       case way = "W"
       case relation = "R"
-
-      internal static func isValid(_ rawValue: String) -> Bool {
-        OsmType(rawValue: rawValue) != nil
-      }
     }
 
     public let id: Int
@@ -24,18 +20,14 @@ extension PodcastLocation {
 
       guard let osmType = osmStr.removeFirst().asOsmType() else {
         throw DecodingError.dataCorrupted(
-          .init(
-            codingPath: [PodcastLocation.CodingKeys.osmQuery],
-            debugDescription: "Invalid type for osm attribute: \(osmStr)"
-          )
+          codingKey: PodcastLocation.CodingKeys.osmQuery,
+          debugDescription: "Invalid type for osm attribute: \(osmStr)"
         )
       }
       guard let osmID = osmStr.split(separator: "#")[safe: 0]?.asExactInt() else {
         throw DecodingError.dataCorrupted(
-          .init(
-            codingPath: [PodcastLocation.CodingKeys.osmQuery],
-            debugDescription: "Invalid id of type Int for osm attribute: \(osmStr)"
-          )
+          codingKey: PodcastLocation.CodingKeys.osmQuery,
+          debugDescription: "Invalid id of type Int for osm attribute: \(osmStr)"
         )
       }
       let osmRevision = osmStr.split(separator: "#")[safe: 1]?.asInt()
diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift
index 95f118b..5f3d6e2 100644
--- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift
+++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift
@@ -13,6 +13,7 @@ extension PodcastTranscript {
       self.init(rawValue: caseInsensitive)
     }
 
+    // swiftlint:disable:next cyclomatic_complexity
     init?(mimeType: MimeType) {
       switch mimeType {
       case .plain:
diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+RSSItem.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+RSSItem.swift
new file mode 100644
index 0000000..d290a97
--- /dev/null
+++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+RSSItem.swift
@@ -0,0 +1,83 @@
+import Foundation
+
+extension WordPressPost {
+  // swiftlint:disable:next cyclomatic_complexity function_body_length
+  public init(item: RSSItem) throws {
+    guard let name = item.wpPostName else {
+      throw WordPressError.missingField(.name)
+    }
+    guard let type = item.wpPostType else {
+      throw WordPressError.missingField(.type)
+    }
+    guard let creator = item.creators.first else {
+      throw WordPressError.missingField(.creator)
+    }
+    guard let body = item.contentEncoded else {
+      throw WordPressError.missingField(.body)
+    }
+    guard let status = item.wpStatus else {
+      throw WordPressError.missingField(.status)
+    }
+    guard let commentStatus = item.wpCommentStatus else {
+      throw WordPressError.missingField(.commentStatus)
+    }
+    guard let pingStatus = item.wpPingStatus else {
+      throw WordPressError.missingField(.pingStatus)
+    }
+    guard let parentID = item.wpPostParent else {
+      throw WordPressError.missingField(.parentID)
+    }
+    guard let menuOrder = item.wpMenuOrder else {
+      throw WordPressError.missingField(.menuOrder)
+    }
+    guard let id = item.wpPostID else {
+      throw WordPressError.missingField(.id)
+    }
+    guard let isSticky = item.wpIsSticky else {
+      throw WordPressError.missingField(.isSticky)
+    }
+    guard let postDate = item.wpPostDate else {
+      throw WordPressError.missingField(.postDate)
+    }
+    guard let modifiedDate = item.wpModifiedDate else {
+      throw WordPressError.missingField(.modifiedDate)
+    }
+    guard let link = item.link else {
+      throw WordPressError.missingField(.link)
+    }
+
+    let title = item.title
+    let categoryTerms = item.categoryTerms
+    let meta = item.wpPostMeta
+    let pubDate = item.pubDate
+
+    let categoryDictionary = Dictionary(
+      grouping: categoryTerms) {
+      $0.domain
+    }
+
+    modifiedDateGMT = item.wpModifiedDateGMT
+    self.name = name.value
+    self.title = title
+    self.type = type.value
+    self.link = link
+    self.pubDate = pubDate
+    self.creator = creator
+    self.body = body.value
+    tags = categoryDictionary["post_tag", default: []].map { $0.value }
+    categories = categoryDictionary["category", default: []].map { $0.value }
+    self.meta = Dictionary(grouping: meta) { $0.key.value }
+      .compactMapValues { $0.last?.value.value }
+    self.status = status.value
+    self.commentStatus = commentStatus.value
+    self.pingStatus = pingStatus.value
+    self.parentID = parentID
+    self.menuOrder = menuOrder
+    ID = id
+    self.isSticky = (isSticky != 0)
+    self.postDate = postDate
+    postDateGMT = item.wpPostDateGMT
+    self.modifiedDate = modifiedDate
+    attachmentURL = item.wpAttachmentURL
+  }
+}
diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift
index 40aab6f..f2929e0 100644
--- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift
+++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift
@@ -58,136 +58,6 @@ public struct WordPressPost {
   public let modifiedDate: Date
   public let modifiedDateGMT: Date?
   public let attachmentURL: URL?
-
-  internal init(
-    name: String,
-    title: String,
-    type: PostType,
-    link: URL,
-    pubDate: Date?,
-    creator: String,
-    body: String,
-    tags: [String],
-    categories: [String],
-    meta: [String: String],
-    status: Status,
-    commentStatus: CommentStatus,
-    pingStatus: PingStatus,
-    parentID: Int?,
-    menuOrder: Int?,
-    id: Int,
-    isSticky: Bool,
-    postDate: Date,
-    postDateGMT: Date?,
-    modifiedDate: Date,
-    modifiedDateGMT: Date?,
-    attachmentURL: URL?
-  ) {
-    self.name = name
-    self.title = title
-    self.type = type
-    self.link = link
-    self.pubDate = pubDate
-    self.creator = creator
-    self.body = body
-    self.tags = tags
-    self.categories = categories
-    self.meta = meta
-    self.status = status
-    self.commentStatus = commentStatus
-    self.pingStatus = pingStatus
-    self.parentID = parentID
-    self.menuOrder = menuOrder
-    ID = id
-    self.isSticky = isSticky
-    self.postDate = postDate
-    self.postDateGMT = postDateGMT
-    self.modifiedDate = modifiedDate
-    self.modifiedDateGMT = modifiedDateGMT
-    self.attachmentURL = attachmentURL
-  }
-}
-
-extension WordPressPost {
-  // swiftlint:disable:next cyclomatic_complexity function_body_length
-  public init(item: RSSItem) throws {
-    guard let name = item.wpPostName else {
-      throw WordPressError.missingField(.name)
-    }
-    guard let type = item.wpPostType else {
-      throw WordPressError.missingField(.type)
-    }
-    guard let creator = item.creators.first else {
-      throw WordPressError.missingField(.creator)
-    }
-    guard let body = item.contentEncoded else {
-      throw WordPressError.missingField(.body)
-    }
-    guard let status = item.wpStatus else {
-      throw WordPressError.missingField(.status)
-    }
-    guard let commentStatus = item.wpCommentStatus else {
-      throw WordPressError.missingField(.commentStatus)
-    }
-    guard let pingStatus = item.wpPingStatus else {
-      throw WordPressError.missingField(.pingStatus)
-    }
-    guard let parentID = item.wpPostParent else {
-      throw WordPressError.missingField(.parentID)
-    }
-    guard let menuOrder = item.wpMenuOrder else {
-      throw WordPressError.missingField(.menuOrder)
-    }
-    guard let id = item.wpPostID else {
-      throw WordPressError.missingField(.id)
-    }
-    guard let isSticky = item.wpIsSticky else {
-      throw WordPressError.missingField(.isSticky)
-    }
-    guard let postDate = item.wpPostDate else {
-      throw WordPressError.missingField(.postDate)
-    }
-    guard let modifiedDate = item.wpModifiedDate else {
-      throw WordPressError.missingField(.modifiedDate)
-    }
-    guard let link = item.link else {
-      throw WordPressError.missingField(.link)
-    }
-
-    let title = item.title
-    let categoryTerms = item.categoryTerms
-    let meta = item.wpPostMeta
-    let pubDate = item.pubDate
-
-    let categoryDictionary = Dictionary(
-      grouping: categoryTerms) {
-      $0.domain
-    }
-
-    modifiedDateGMT = item.wpModifiedDateGMT
-    self.name = name.value
-    self.title = title
-    self.type = type.value
-    self.link = link
-    self.pubDate = pubDate
-    self.creator = creator
-    self.body = body.value
-    tags = categoryDictionary["post_tag", default: []].map { $0.value }
-    categories = categoryDictionary["category", default: []].map { $0.value }
-    self.meta = Dictionary(grouping: meta) { $0.key.value }
-      .compactMapValues { $0.last?.value.value }
-    self.status = status.value
-    self.commentStatus = commentStatus.value
-    self.pingStatus = pingStatus.value
-    self.parentID = parentID
-    self.menuOrder = menuOrder
-    ID = id
-    self.isSticky = (isSticky != 0)
-    self.postDate = postDate
-    postDateGMT = item.wpPostDateGMT
-    self.modifiedDate = modifiedDate
-    attachmentURL = item.wpAttachmentURL
-  }
 }
 
 extension WordPressPost: Hashable {