Skip to content

Commit

Permalink
RSS: Add option to customize an item’s link (#84)
Browse files Browse the repository at this point in the history
This change makes it possible to specify a custom link for an item when
it appears in an RSS feed. This is useful for RSS items that link to
external resources, and enables those items to link directly to the target
URL. However, the website’s own internal URL is still used as a default
for each item’s GUID, in order to provide a stable identifier (as the
external URL might change). That can always be customized using `rss.guid`,
though.
  • Loading branch information
JohnSundell authored May 12, 2020
1 parent ddf73c2 commit efbfd49
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 4 deletions.
14 changes: 12 additions & 2 deletions Sources/Publish/API/ItemRSSProperties.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import Foundation
public struct ItemRSSProperties: Codable, Hashable {
/// Any specific GUID that should be added for the item. When `nil`,
/// the item's URL will be used and the `isPermaLink` attribute will
/// be set to `true`. If not `nil`, a non-permalink will be assumed.
/// be set to `true`, unless an explicit `link` was specified. If this
/// property is not `nil`, then a non-permalink GUID will be assumed.
public var guid: String?
/// Any prefix that should be added to the item's title within an RSS feed.
public var titlePrefix: String?
Expand All @@ -20,22 +21,31 @@ public struct ItemRSSProperties: Codable, Hashable {
public var bodyPrefix: String?
/// Any suffix that should be added to the item's body HTML within an RSS feed.
public var bodySuffix: String?
/// Any specific URL that the item should link to when inlcluded in an RSS
/// feed. By default, the item's location on its website will be used. Note that
/// this link won't be automatically used as the item's GUID, however, setting
/// this property to a non-`nil` value will set the GUID's `isPermaLink` attribute
/// to `false`.
public var link: URL? = nil

/// Initialize an instance of this type
/// - parameter guid: Any specific GUID that should be added for the item.
/// - parameter titlePrefix: Any prefix that should be added to the item's title.
/// - parameter titleSuffix: Any suffix that should be added to the item's title.
/// - parameter bodyPrefix: Any prefix that should be added to the item's body HTML.
/// - parameter bodySuffix: Any suffix that should be added to the item's body HTML.
/// - parameter link: Any specific URL that the item should link to, other than its location.
public init(guid: String? = nil,
titlePrefix: String? = nil,
titleSuffix: String? = nil,
bodyPrefix: String? = nil,
bodySuffix: String? = nil) {
bodySuffix: String? = nil,
link: URL? = nil) {
self.guid = guid
self.titlePrefix = titlePrefix
self.titleSuffix = titleSuffix
self.bodyPrefix = bodyPrefix
self.bodySuffix = bodySuffix
self.link = link
}
}
2 changes: 1 addition & 1 deletion Sources/Publish/API/PlotComponents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ internal extension Node where Context: RSSItemContext {
static func guid<T>(for item: Item<T>, site: T) -> Node {
return .guid(
.text(item.rssProperties.guid ?? site.url(for: item).absoluteString),
.isPermaLink(item.rssProperties.guid == nil)
.isPermaLink(item.rssProperties.guid == nil && item.rssProperties.link == nil)
)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/Publish/Internal/RSSFeedGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private extension RSSFeedGenerator {
.guid(for: item, site: context.site),
.title(item.rssTitle),
.description(item.description),
.link(context.site.url(for: item)),
.link(item.rssProperties.link ?? context.site.url(for: item)),
.pubDate(item.date, timeZone: context.dateFormatter.timeZone),
.content(for: item, site: context.site)
)
Expand Down
22 changes: 22 additions & 0 deletions Tests/PublishTests/Tests/RSSFeedGenerationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,27 @@ final class RSSFeedGenerationTests: PublishTestCase {
"""))
}

func testCustomItemLink() throws {
let folder = try Folder.createTemporary()

try generateFeed(in: folder, content: [
"one/item.md": """
---
rss.link: custom.link
---
Body
"""
])

let feed = try folder.file(at: "Output/feed.rss").readAsString()

XCTAssertTrue(feed.contains("<link>custom.link</link>"))

XCTAssertTrue(feed.contains("""
<guid isPermaLink="false">https://swiftbysundell.com/one/item</guid>
"""))
}

func testReusingPreviousFeedIfNoItemsWereModified() throws {
let folder = try Folder.createTemporary()
let contentFile = try folder.createFile(at: "Content/one/item.md")
Expand Down Expand Up @@ -160,6 +181,7 @@ extension RSSFeedGenerationTests {
("testConvertingRelativeLinksToAbsolute", testConvertingRelativeLinksToAbsolute),
("testItemTitlePrefixAndSuffix", testItemTitlePrefixAndSuffix),
("testItemBodyPrefixAndSuffix", testItemBodyPrefixAndSuffix),
("testCustomItemLink", testCustomItemLink),
("testReusingPreviousFeedIfNoItemsWereModified", testReusingPreviousFeedIfNoItemsWereModified),
("testNotReusingPreviousFeedIfConfigChanged", testNotReusingPreviousFeedIfConfigChanged),
("testNotReusingPreviousFeedIfItemWasAdded", testNotReusingPreviousFeedIfItemWasAdded)
Expand Down

0 comments on commit efbfd49

Please sign in to comment.