Rename and simplify RSSFeedWriter

Also uses named references for escaped HTML entities
This commit is contained in:
Sami Samhuri 2019-12-10 22:10:24 -08:00
parent 885e5153ff
commit 1d0ffd52a2
2 changed files with 24 additions and 41 deletions

View file

@ -9,14 +9,14 @@ import Foundation
final class RSSFeedPlugin: Plugin { final class RSSFeedPlugin: Plugin {
let postRepo: PostRepo let postRepo: PostRepo
let rssWriter: RSSWriter let rssFeedWriter: RSSFeedWriter
init( init(
postRepo: PostRepo = PostRepo(), postRepo: PostRepo = PostRepo(),
rssWriter: RSSWriter = RSSWriter() rssFeedWriter: RSSFeedWriter = RSSFeedWriter()
) { ) {
self.postRepo = postRepo self.postRepo = postRepo
self.rssWriter = rssWriter self.rssFeedWriter = rssFeedWriter
} }
// MARK: - Plugin methods // MARK: - Plugin methods
@ -26,7 +26,7 @@ final class RSSFeedPlugin: Plugin {
return return
} }
try postRepo.readPosts(sourceURL: sourceURL, makePath: rssWriter.urlPathForPost) try postRepo.readPosts(sourceURL: sourceURL, makePath: rssFeedWriter.urlPathForPost)
} }
func render(site: Site, targetURL: URL, templateRenderer: TemplateRenderer) throws { func render(site: Site, targetURL: URL, templateRenderer: TemplateRenderer) throws {
@ -34,6 +34,6 @@ final class RSSFeedPlugin: Plugin {
return return
} }
try rssWriter.writeFeed(postRepo.postsForFeed, site: site, to: targetURL, with: templateRenderer) try rssFeedWriter.writeFeed(postRepo.postsForFeed, site: site, to: targetURL, with: templateRenderer)
} }
} }

View file

@ -1,5 +1,5 @@
// //
// RSSWriter.swift // RSSFeedWriter.swift
// SiteGenerator // SiteGenerator
// //
// Created by Sami Samhuri on 2019-12-10. // Created by Sami Samhuri on 2019-12-10.
@ -8,43 +8,19 @@
import HTMLEntities import HTMLEntities
import Foundation import Foundation
struct FeedSite { private struct FeedSite {
let title: String let title: String
let description: String? let description: String?
let url: String let url: String
init(title: String, description: String?, url: URL) {
self.title = title.htmlEscape()
self.description = description?.htmlEscape()
self.url = url.absoluteString.htmlEscape()
}
} }
struct FeedPost { private struct FeedPost {
let title: String let title: String
let date: String let date: String
let author: String let author: String
let isLink: Bool
let link: String let link: String
let guid: String let guid: String
let body: String let body: String
init(
title: String,
date: String,
author: String,
link: URL?,
url: URL,
body: String
) {
self.title = title.htmlEscape()
self.date = date.htmlEscape()
self.author = author.htmlEscape()
self.isLink = link != nil
self.link = (link ?? url).absoluteString.htmlEscape()
self.guid = url.absoluteString.htmlEscape()
self.body = body.htmlEscape()
}
} }
private let rfc822Formatter: DateFormatter = { private let rfc822Formatter: DateFormatter = {
@ -60,7 +36,7 @@ private extension Date {
} }
} }
final class RSSWriter { final class RSSFeedWriter {
let fileManager: FileManager let fileManager: FileManager
let feedPath: String let feedPath: String
let postsPath: String let postsPath: String
@ -88,21 +64,28 @@ final class RSSWriter {
} }
func writeFeed(_ posts: [Post], site: Site, to targetURL: URL, with templateRenderer: TemplateRenderer) throws { func writeFeed(_ posts: [Post], site: Site, to targetURL: URL, with templateRenderer: TemplateRenderer) throws {
let feedSite = FeedSite(
title: site.title.htmlEscape(useNamedReferences: true),
description: site.description?.htmlEscape(useNamedReferences: true),
url: site.url.absoluteString.htmlEscape(useNamedReferences: true)
)
let renderedPosts: [FeedPost] = try posts.map { post in let renderedPosts: [FeedPost] = try posts.map { post in
let title = post.isLink ? "\(post.title)" : post.title
let url = site.url.appendingPathComponent(post.path)
return FeedPost( return FeedPost(
title: post.title, title: title.htmlEscape(useNamedReferences: true),
date: post.date.rfc822, date: post.date.rfc822.htmlEscape(useNamedReferences: true),
author: "\(site.email) (\(post.author))", author: "\(site.email) (\(post.author))".htmlEscape(useNamedReferences: true),
link: post.link, link: (post.link ?? url).absoluteString.htmlEscape(useNamedReferences: true),
url: site.url.appendingPathComponent(post.path), guid: url.absoluteString.htmlEscape(useNamedReferences: true),
body: try templateRenderer.renderTemplate(name: "feed-post.html", context: [ body: try templateRenderer.renderTemplate(name: "feed-post.html", context: [
"post": post, "post": post,
]) ]).htmlEscape(useNamedReferences: true)
) )
} }
let feedXML = try templateRenderer.renderTemplate(name: "feed.xml", context: [ let feedXML = try templateRenderer.renderTemplate(name: "feed.xml", context: [
"site": FeedSite(title: site.title, description: site.description, url: site.url), "site": feedSite,
"feedURL": site.url.appendingPathComponent(feedPath).absoluteString.htmlEscape(), "feedURL": site.url.appendingPathComponent(feedPath).absoluteString.htmlEscape(useNamedReferences: true),
"posts": renderedPosts, "posts": renderedPosts,
]) ])
let feedURL = targetURL.appendingPathComponent(feedPath) let feedURL = targetURL.appendingPathComponent(feedPath)