mirror of
https://github.com/samsonjs/samhuri.net.git
synced 2026-04-27 14:57:40 +00:00
Roll the feed plugins into PostsPlugin
You can't have feeds without posts that they link to. Doesn't make sense to have feeds without posts.
This commit is contained in:
parent
23b3d2d625
commit
0748053a82
10 changed files with 57 additions and 139 deletions
|
|
@ -1,48 +0,0 @@
|
||||||
//
|
|
||||||
// JSONFeedPlugin.swift
|
|
||||||
// SiteGenerator
|
|
||||||
//
|
|
||||||
// Created by Sami Samhuri on 2019-12-10.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
final class JSONFeedPlugin: Plugin {
|
|
||||||
let postRepo: PostRepo
|
|
||||||
let jsonFeedWriter: JSONFeedWriter
|
|
||||||
|
|
||||||
init(
|
|
||||||
postRepo: PostRepo = PostRepo(),
|
|
||||||
jsonFeedWriter: JSONFeedWriter = JSONFeedWriter()
|
|
||||||
) {
|
|
||||||
self.postRepo = postRepo
|
|
||||||
self.jsonFeedWriter = jsonFeedWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Plugin methods
|
|
||||||
|
|
||||||
convenience init(options: [String: Any]) {
|
|
||||||
if let feedPath = options["feed_path"] as? String {
|
|
||||||
self.init(jsonFeedWriter: JSONFeedWriter(feedPath: feedPath))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUp(site: Site, sourceURL: URL) throws {
|
|
||||||
guard postRepo.postDataExists(at: sourceURL) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try postRepo.readPosts(sourceURL: sourceURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
func render(site: Site, targetURL: URL, templateRenderer: TemplateRenderer) throws {
|
|
||||||
guard !postRepo.isEmpty else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try jsonFeedWriter.writeFeed(postRepo.postsForFeed, site: site, to: targetURL, with: templateRenderer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
//
|
|
||||||
// PostRepo+Feeds.swift
|
|
||||||
// SiteGenerator
|
|
||||||
//
|
|
||||||
// Created by Sami Samhuri on 2019-12-10.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
extension PostRepo {
|
|
||||||
var feedPostsCount: Int { 30 }
|
|
||||||
|
|
||||||
var postsForFeed: [Post] {
|
|
||||||
Array(sortedPosts.prefix(feedPostsCount))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
//
|
|
||||||
// RSSFeedPlugin.swift
|
|
||||||
// SiteGenerator
|
|
||||||
//
|
|
||||||
// Created by Sami Samhuri on 2019-12-10.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
final class RSSFeedPlugin: Plugin {
|
|
||||||
let postRepo: PostRepo
|
|
||||||
let rssFeedWriter: RSSFeedWriter
|
|
||||||
|
|
||||||
init(
|
|
||||||
postRepo: PostRepo = PostRepo(),
|
|
||||||
rssFeedWriter: RSSFeedWriter = RSSFeedWriter()
|
|
||||||
) {
|
|
||||||
self.postRepo = postRepo
|
|
||||||
self.rssFeedWriter = rssFeedWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Plugin methods
|
|
||||||
|
|
||||||
convenience init(options: [String: Any]) {
|
|
||||||
if let feedPath = options["feed_path"] as? String {
|
|
||||||
self.init(rssFeedWriter: RSSFeedWriter(feedPath: feedPath))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setUp(site: Site, sourceURL: URL) throws {
|
|
||||||
guard postRepo.postDataExists(at: sourceURL) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try postRepo.readPosts(sourceURL: sourceURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
func render(site: Site, targetURL: URL, templateRenderer: TemplateRenderer) throws {
|
|
||||||
guard !postRepo.isEmpty else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try rssFeedWriter.writeFeed(postRepo.postsForFeed, site: site, to: targetURL, with: templateRenderer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -45,10 +45,6 @@ public final class Generator {
|
||||||
return ProjectsPlugin(options: options)
|
return ProjectsPlugin(options: options)
|
||||||
case .posts:
|
case .posts:
|
||||||
return PostsPlugin(options: options)
|
return PostsPlugin(options: options)
|
||||||
case .jsonFeed:
|
|
||||||
return JSONFeedPlugin(options: options)
|
|
||||||
case .rssFeed:
|
|
||||||
return RSSFeedPlugin(options: options)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for plugin in plugins {
|
for plugin in plugins {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,4 @@ import Foundation
|
||||||
public enum SitePlugin: String, Codable {
|
public enum SitePlugin: String, Codable {
|
||||||
case posts
|
case posts
|
||||||
case projects
|
case projects
|
||||||
case jsonFeed = "json_feed"
|
|
||||||
case rssFeed = "rss_feed"
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,16 +15,15 @@ struct RawPost {
|
||||||
final class PostRepo {
|
final class PostRepo {
|
||||||
let postsPath = "posts"
|
let postsPath = "posts"
|
||||||
let recentPostsCount = 10
|
let recentPostsCount = 10
|
||||||
|
let feedPostsCount = 30
|
||||||
|
|
||||||
let fileManager: FileManager
|
let fileManager: FileManager
|
||||||
let postTransformer: PostTransformer
|
|
||||||
let outputPath: String
|
let outputPath: String
|
||||||
|
|
||||||
private(set) var posts: PostsByYear!
|
private(set) var posts: PostsByYear!
|
||||||
|
|
||||||
init(fileManager: FileManager = .default, postTransformer: PostTransformer = PostTransformer(), outputPath: String = "posts") {
|
init(fileManager: FileManager = .default, outputPath: String = "posts") {
|
||||||
self.fileManager = fileManager
|
self.fileManager = fileManager
|
||||||
self.postTransformer = postTransformer
|
|
||||||
self.outputPath = outputPath
|
self.outputPath = outputPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,28 +39,22 @@ final class PostRepo {
|
||||||
Array(sortedPosts.prefix(recentPostsCount))
|
Array(sortedPosts.prefix(recentPostsCount))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var postsForFeed: [Post] {
|
||||||
|
Array(sortedPosts.prefix(feedPostsCount))
|
||||||
|
}
|
||||||
|
|
||||||
func postDataExists(at sourceURL: URL) -> Bool {
|
func postDataExists(at sourceURL: URL) -> Bool {
|
||||||
let postsURL = sourceURL.appendingPathComponent(postsPath)
|
let postsURL = sourceURL.appendingPathComponent(postsPath)
|
||||||
return fileManager.fileExists(atPath: postsURL.path)
|
return fileManager.fileExists(atPath: postsURL.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func readPosts(sourceURL: URL) throws {
|
func readPosts(sourceURL: URL) throws {
|
||||||
|
let postTransformer = PostTransformer(outputPath: outputPath)
|
||||||
let posts = try readRawPosts(sourceURL: sourceURL)
|
let posts = try readRawPosts(sourceURL: sourceURL)
|
||||||
.map { try postTransformer.makePost(from: $0, makePath: urlPathForPost) }
|
.map(postTransformer.makePost)
|
||||||
self.posts = PostsByYear(posts: posts, path: "/\(outputPath)")
|
self.posts = PostsByYear(posts: posts, path: "/\(outputPath)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func urlPathForPost(date: Date, slug: String) -> String {
|
|
||||||
// format: /posts/2019/12/first-post
|
|
||||||
[
|
|
||||||
"",
|
|
||||||
outputPath,
|
|
||||||
"\(date.year)",
|
|
||||||
Month(date.month).padded,
|
|
||||||
slug,
|
|
||||||
].joined(separator: "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
private func readRawPosts(sourceURL: URL) throws -> [RawPost] {
|
private func readRawPosts(sourceURL: URL) throws -> [RawPost] {
|
||||||
let postsURL = sourceURL.appendingPathComponent(postsPath)
|
let postsURL = sourceURL.appendingPathComponent(postsPath)
|
||||||
return try enumerateMarkdownFiles(directory: postsURL)
|
return try enumerateMarkdownFiles(directory: postsURL)
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,17 @@ import Ink
|
||||||
|
|
||||||
final class PostTransformer {
|
final class PostTransformer {
|
||||||
let markdownParser: MarkdownParser
|
let markdownParser: MarkdownParser
|
||||||
|
let outputPath: String
|
||||||
|
|
||||||
init(markdownParser: MarkdownParser = MarkdownParser()) {
|
init(markdownParser: MarkdownParser = MarkdownParser(), outputPath: String = "posts") {
|
||||||
self.markdownParser = markdownParser
|
self.markdownParser = markdownParser
|
||||||
|
self.outputPath = outputPath
|
||||||
}
|
}
|
||||||
|
|
||||||
func makePost(from rawPost: RawPost, makePath: (Date, _ slug: String) -> String) throws -> Post {
|
func makePost(from rawPost: RawPost) throws -> Post {
|
||||||
let result = markdownParser.parse(rawPost.markdown)
|
let result = markdownParser.parse(rawPost.markdown)
|
||||||
let metadata = try parseMetadata(result.metadata)
|
let metadata = try parseMetadata(result.metadata)
|
||||||
let path = makePath(metadata.date, rawPost.slug)
|
let path = pathForPost(date: metadata.date, slug: rawPost.slug)
|
||||||
return Post(
|
return Post(
|
||||||
slug: rawPost.slug,
|
slug: rawPost.slug,
|
||||||
title: metadata.title,
|
title: metadata.title,
|
||||||
|
|
@ -31,6 +33,17 @@ final class PostTransformer {
|
||||||
path: path
|
path: path
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pathForPost(date: Date, slug: String) -> String {
|
||||||
|
// format: /posts/2019/12/first-post
|
||||||
|
[
|
||||||
|
"",
|
||||||
|
outputPath,
|
||||||
|
"\(date.year)",
|
||||||
|
Month(date.month).padded,
|
||||||
|
slug,
|
||||||
|
].joined(separator: "/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ParsedMetadata {
|
struct ParsedMetadata {
|
||||||
|
|
|
||||||
|
|
@ -10,24 +10,52 @@ import Foundation
|
||||||
final class PostsPlugin: Plugin {
|
final class PostsPlugin: Plugin {
|
||||||
let postRepo: PostRepo
|
let postRepo: PostRepo
|
||||||
let postWriter: PostWriter
|
let postWriter: PostWriter
|
||||||
|
let jsonFeedWriter: JSONFeedWriter?
|
||||||
|
let rssFeedWriter: RSSFeedWriter?
|
||||||
|
|
||||||
init(
|
init(
|
||||||
postRepo: PostRepo = PostRepo(),
|
postRepo: PostRepo = PostRepo(),
|
||||||
postWriter: PostWriter = PostWriter()
|
postWriter: PostWriter = PostWriter(),
|
||||||
|
jsonFeedWriter: JSONFeedWriter?,
|
||||||
|
rssFeedWriter: RSSFeedWriter?
|
||||||
) {
|
) {
|
||||||
self.postRepo = postRepo
|
self.postRepo = postRepo
|
||||||
self.postWriter = postWriter
|
self.postWriter = postWriter
|
||||||
|
self.jsonFeedWriter = jsonFeedWriter
|
||||||
|
self.rssFeedWriter = rssFeedWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Plugin methods
|
// MARK: - Plugin methods
|
||||||
|
|
||||||
convenience init(options: [String: Any]) {
|
convenience init(options: [String: Any]) {
|
||||||
|
let postRepo: PostRepo
|
||||||
|
let postWriter: PostWriter
|
||||||
if let outputPath = options["path"] as? String {
|
if let outputPath = options["path"] as? String {
|
||||||
self.init(postWriter: PostWriter(outputPath: outputPath))
|
postRepo = PostRepo(outputPath: outputPath)
|
||||||
|
postWriter = PostWriter(outputPath: outputPath)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.init()
|
postRepo = PostRepo()
|
||||||
|
postWriter = PostWriter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let jsonFeedWriter: JSONFeedWriter?
|
||||||
|
if let jsonFeedPath = options["json_feed"] as? String {
|
||||||
|
jsonFeedWriter = JSONFeedWriter(feedPath: jsonFeedPath)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jsonFeedWriter = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let rssFeedWriter: RSSFeedWriter?
|
||||||
|
if let rssFeedPath = options["rss_feed"] as? String {
|
||||||
|
rssFeedWriter = RSSFeedWriter(feedPath: rssFeedPath)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rssFeedWriter = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.init(postRepo: postRepo, postWriter: postWriter, jsonFeedWriter: jsonFeedWriter, rssFeedWriter: rssFeedWriter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setUp(site: Site, sourceURL: URL) throws {
|
func setUp(site: Site, sourceURL: URL) throws {
|
||||||
|
|
@ -48,5 +76,7 @@ final class PostsPlugin: Plugin {
|
||||||
try postWriter.writeArchive(posts: postRepo.posts, to: targetURL, with: templateRenderer)
|
try postWriter.writeArchive(posts: postRepo.posts, to: targetURL, with: templateRenderer)
|
||||||
try postWriter.writeYearIndexes(posts: postRepo.posts, to: targetURL, with: templateRenderer)
|
try postWriter.writeYearIndexes(posts: postRepo.posts, to: targetURL, with: templateRenderer)
|
||||||
try postWriter.writeMonthRollups(posts: postRepo.posts, to: targetURL, with: templateRenderer)
|
try postWriter.writeMonthRollups(posts: postRepo.posts, to: targetURL, with: templateRenderer)
|
||||||
|
try jsonFeedWriter?.writeFeed(postRepo.postsForFeed, site: site, to: targetURL, with: templateRenderer)
|
||||||
|
try rssFeedWriter?.writeFeed(postRepo.postsForFeed, site: site, to: targetURL, with: templateRenderer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue