Fix RSS feed with custom XML escaping function

This commit is contained in:
Sami Samhuri 2019-12-12 23:59:10 -08:00
parent 5f2ca2e44d
commit d4299f66fa
5 changed files with 28 additions and 23 deletions

View file

@ -97,7 +97,7 @@ Execution, trying TDD for the first time:
- [ ] Consider using Swift for samhuri.net as well, and then making SiteGenerator a package that it uses ... then we can use Plot or pointfree.co's swift-html
- [ ] Replace remaining Ruby with Swift
- [x] Replace remaining Ruby with Swift
- [x] Generate RSS feed (ditch mustache templates)

View file

@ -36,15 +36,6 @@
"revision": "0e9a78d6584e3812cd9c09494d5c7b483e8f533c",
"version": "0.13.1"
}
},
{
"package": "HTMLEntities",
"repositoryURL": "https://github.com/IBM-Swift/swift-html-entities.git",
"state": {
"branch": null,
"revision": "744c094976355aa96ca61b9b60ef0a38e979feb7",
"version": "3.0.14"
}
}
]
},

View file

@ -9,13 +9,11 @@ let package = Package(
.macOS(.v10_15),
],
dependencies: [
.package(url: "https://github.com/IBM-Swift/swift-html-entities.git", from: "3.0.0"),
.package(url: "https://github.com/johnsundell/ink.git", from: "0.1.0"),
.package(url: "https://github.com/stencilproject/Stencil.git", from: "0.13.0"),
],
targets: [
.target( name: "SiteGenerator", dependencies: [
"HTMLEntities",
"Ink",
"Stencil",
]),

View file

@ -5,7 +5,6 @@
// Created by Sami Samhuri on 2019-12-10.
//
import HTMLEntities
import Foundation
private struct FeedSite {
@ -47,9 +46,9 @@ final class RSSFeedWriter {
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)
title: site.title.escapedForXML(),
description: site.description?.escapedForXML(),
url: site.url.absoluteString.escapedForXML()
)
let renderedPosts: [FeedPost] = try posts.map { post in
let title = post.isLink ? "\(post.title)" : post.title
@ -63,19 +62,19 @@ final class RSSFeedWriter {
}()
let url = site.url.appendingPathComponent(post.path)
return FeedPost(
title: title.htmlEscape(useNamedReferences: true),
date: post.date.rfc822.htmlEscape(useNamedReferences: true),
author: author.htmlEscape(useNamedReferences: true),
link: (post.link ?? url).absoluteString.htmlEscape(useNamedReferences: true),
guid: url.absoluteString.htmlEscape(useNamedReferences: true),
title: title.escapedForXML(),
date: post.date.rfc822.escapedForXML(),
author: author.escapedForXML(),
link: (post.link ?? url).absoluteString.escapedForXML(),
guid: url.absoluteString.escapedForXML(),
body: try templateRenderer.renderTemplate(name: "feed-post.html", context: [
"post": post,
]).htmlEscape(useNamedReferences: true)
]).escapedForXML()
)
}
let feedXML = try templateRenderer.renderTemplate(name: "feed.xml", context: [
"site": feedSite,
"feedURL": site.url.appendingPathComponent(feedPath).absoluteString.htmlEscape(useNamedReferences: true),
"feedURL": site.url.appendingPathComponent(feedPath).absoluteString.escapedForXML(),
"posts": renderedPosts,
])
let feedURL = targetURL.appendingPathComponent(feedPath)

View file

@ -0,0 +1,17 @@
//
// XMLEscape.swift
// SiteGenerator
//
// Created by Sami Samhuri on 2019-12-12.
//
import Foundation
extension String {
func escapedForXML() -> String {
replacingOccurrences(of: "&", with: "&")
.replacingOccurrences(of: "<", with: "&lt;")
.replacingOccurrences(of: ">", with: "&gt;")
.replacingOccurrences(of: "\"", with: "&quot;")
}
}