diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Feeds/JSONFeed.swift b/samhuri.net/Sources/samhuri.net/Posts/JSONFeed/JSONFeed.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Feeds/JSONFeed.swift rename to samhuri.net/Sources/samhuri.net/Posts/JSONFeed/JSONFeed.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Feeds/JSONFeedWriter.swift b/samhuri.net/Sources/samhuri.net/Posts/JSONFeed/JSONFeedWriter.swift similarity index 91% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Feeds/JSONFeedWriter.swift rename to samhuri.net/Sources/samhuri.net/Posts/JSONFeed/JSONFeedWriter.swift index bf1c403..9fed7c6 100644 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Feeds/JSONFeedWriter.swift +++ b/samhuri.net/Sources/samhuri.net/Posts/JSONFeed/JSONFeedWriter.swift @@ -7,6 +7,10 @@ import Foundation +protocol JSONFeedRendering { + func renderJSONFeedPost(_ post: Post, site: Site) throws -> String +} + final class JSONFeedWriter { let fileWriter: FileWriting let jsonFeed: JSONFeed @@ -16,7 +20,7 @@ final class JSONFeedWriter { self.fileWriter = fileWriter } - func writeFeed(_ posts: [Post], for site: Site, to targetURL: URL, with templateRenderer: PostsTemplateRenderer) throws { + func writeFeed(_ posts: [Post], for site: Site, to targetURL: URL, with renderer: JSONFeedRendering) throws { let feed = Feed( title: site.title, home_page_url: site.url.absoluteString, @@ -37,7 +41,7 @@ final class JSONFeedWriter { url: url.absoluteString, external_url: post.link?.absoluteString, author: FeedAuthor(name: post.author, avatar: nil, url: nil), - content_html: try templateRenderer.renderFeedPost(post, site: site), + content_html: try renderer.renderJSONFeedPost(post, site: site), tags: post.tags ) } diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Month.swift b/samhuri.net/Sources/samhuri.net/Posts/Model/Month.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Month.swift rename to samhuri.net/Sources/samhuri.net/Posts/Model/Month.swift diff --git a/samhuri.net/Sources/samhuri.net/Posts/Model/MonthPosts.swift b/samhuri.net/Sources/samhuri.net/Posts/Model/MonthPosts.swift new file mode 100644 index 0000000..4e57cd8 --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Posts/Model/MonthPosts.swift @@ -0,0 +1,26 @@ +// +// MonthPosts.swift +// samhuri.net +// +// Created by Sami Samhuri on 2020-01-01. +// + +import Foundation + +struct MonthPosts { + let month: Month + var posts: [Post] + let path: String + + var title: String { + month.padded + } + + var isEmpty: Bool { + posts.isEmpty + } + + var year: Int { + posts[0].date.year + } +} diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Post.swift b/samhuri.net/Sources/samhuri.net/Posts/Model/Post.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Post.swift rename to samhuri.net/Sources/samhuri.net/Posts/Model/Post.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsByYear.swift b/samhuri.net/Sources/samhuri.net/Posts/Model/PostsByYear.swift similarity index 55% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsByYear.swift rename to samhuri.net/Sources/samhuri.net/Posts/Model/PostsByYear.swift index 6c40788..61466a7 100644 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsByYear.swift +++ b/samhuri.net/Sources/samhuri.net/Posts/Model/PostsByYear.swift @@ -7,55 +7,6 @@ import Foundation -struct MonthPosts { - let month: Month - var posts: [Post] - let path: String - - var title: String { - month.padded - } - - var isEmpty: Bool { - posts.isEmpty - } - - var year: Int { - posts[0].date.year - } -} - -// MARK: - - -struct YearPosts { - let year: Int - var byMonth: [Month: MonthPosts] - let path: String - - var title: String { - "\(year)" - } - - var isEmpty: Bool { - byMonth.isEmpty || byMonth.values.allSatisfy { $0.isEmpty } - } - - var months: [Month] { - Array(byMonth.keys) - } - - subscript(month: Month) -> MonthPosts { - get { - byMonth[month, default: MonthPosts(month: month, posts: [], path: "\(path)/\(month.padded)")] - } - set { - byMonth[month] = newValue - } - } -} - -// MARK: - - struct PostsByYear { private(set) var byYear: [Int: YearPosts] let path: String diff --git a/samhuri.net/Sources/samhuri.net/Posts/Model/YearPosts.swift b/samhuri.net/Sources/samhuri.net/Posts/Model/YearPosts.swift new file mode 100644 index 0000000..8353040 --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Posts/Model/YearPosts.swift @@ -0,0 +1,35 @@ +// +// YearPosts.swift +// samhuri.net +// +// Created by Sami Samhuri on 2020-01-01. +// + +import Foundation + +struct YearPosts { + let year: Int + var byMonth: [Month: MonthPosts] + let path: String + + var title: String { + "\(year)" + } + + var isEmpty: Bool { + byMonth.isEmpty || byMonth.values.allSatisfy { $0.isEmpty } + } + + var months: [Month] { + Array(byMonth.keys) + } + + subscript(month: Month) -> MonthPosts { + get { + byMonth[month, default: MonthPosts(month: month, posts: [], path: "\(path)/\(month.padded)")] + } + set { + byMonth[month] = newValue + } + } +} diff --git a/samhuri.net/Sources/samhuri.net/Posts/PageRenderer+Posts.swift b/samhuri.net/Sources/samhuri.net/Posts/PageRenderer+Posts.swift deleted file mode 100644 index b466823..0000000 --- a/samhuri.net/Sources/samhuri.net/Posts/PageRenderer+Posts.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// PageRenderer+Posts.swift -// samhuri.net -// -// Created by Sami Samhuri on 2019-12-22. -// - -import Foundation -import Plot - -extension PageRenderer: PostsTemplateRenderer { - func renderArchive(postsByYear: PostsByYear, site: Site) throws -> String { - let context = SiteContext(site: site, subtitle: "Archive") - return render(.archive(postsByYear), context: context) - } - - func renderYearPosts(_ yearPosts: YearPosts, site: Site) throws -> String { - let context = SiteContext(site: site, subtitle: yearPosts.title) - return render(.yearPosts(yearPosts), context: context) - } - - func renderMonthPosts(_ posts: MonthPosts, site: Site) throws -> String { - let assets = posts.posts.templateAssets - let context = SiteContext(site: site, subtitle: "\(posts.month.name) \(posts.year)", templateAssets: assets) - return render(.monthPosts(posts), context: context) - } - - func renderPost(_ post: Post, site: Site) throws -> String { - let context = SiteContext(site: site, subtitle: post.title, templateAssets: post.templateAssets) - return render(.post(post, articleClass: "container"), context: context) - } - - func renderRecentPosts(_ posts: [Post], site: Site) throws -> String { - let context = SiteContext(site: site, subtitle: nil, templateAssets: posts.templateAssets) - return render(.recentPosts(posts), context: context) - } - - // MARK: - Feeds - - func renderFeedPost(_ post: Post, site: Site) throws -> String { - let context = SiteContext(site: site, subtitle: post.title, templateAssets: post.templateAssets) - let url = site.url.appendingPathComponent(post.path) - // Turn relative URLs into absolute ones. - return Node.feedPost(post, url: url, styles: context.styles) - .render(indentedBy: .spaces(2)) - .replacingOccurrences(of: "href=\"/", with: "href=\"\(site.url)/") - .replacingOccurrences(of: "src=\"/", with: "src=\"\(site.url)/") - } - - func renderRSSFeed(posts: [Post], feedURL: URL, site: Site) throws -> String { - try RSS( - .title(site.title), - .if(site.description != nil, .description(site.description!)), - .link(site.url), - .pubDate(posts[0].date), - .atomLink(feedURL), - .group(posts.map { post in - let url = site.url.appendingPathComponent(post.path) - return .item( - .title(post.isLink ? "→ \(post.title)" : post.title), - .pubDate(post.date), - .element(named: "author", text: post.author), - .link(url), - .guid(.text(url.absoluteString), .isPermaLink(true)), - .content(try renderFeedPost(post, site: site)) - ) - }) - ).render(indentedBy: .spaces(2)) - } -} diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostRepo.swift b/samhuri.net/Sources/samhuri.net/Posts/PostRepo.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostRepo.swift rename to samhuri.net/Sources/samhuri.net/Posts/PostRepo.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostTransformer.swift b/samhuri.net/Sources/samhuri.net/Posts/PostTransformer.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostTransformer.swift rename to samhuri.net/Sources/samhuri.net/Posts/PostTransformer.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostWriter.swift b/samhuri.net/Sources/samhuri.net/Posts/PostWriter.swift similarity index 74% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostWriter.swift rename to samhuri.net/Sources/samhuri.net/Posts/PostWriter.swift index 8f54f34..dc0ffac 100644 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostWriter.swift +++ b/samhuri.net/Sources/samhuri.net/Posts/PostWriter.swift @@ -20,9 +20,9 @@ final class PostWriter { // MARK: - Post pages extension PostWriter { - func writePosts(_ posts: [Post], for site: Site, to targetURL: URL, with templateRenderer: PostsTemplateRenderer) throws { + func writePosts(_ posts: [Post], for site: Site, to targetURL: URL, with renderer: PostsRendering) throws { for post in posts { - let postHTML = try templateRenderer.renderPost(post, site: site) + let postHTML = try renderer.renderPost(post, site: site) let postURL = targetURL .appendingPathComponent(outputPath) .appendingPathComponent(filePath(date: post.date, slug: post.slug)) @@ -38,8 +38,8 @@ extension PostWriter { // MARK: - Recent posts page extension PostWriter { - func writeRecentPosts(_ recentPosts: [Post], for site: Site, to targetURL: URL, with templateRenderer: PostsTemplateRenderer) throws { - let recentPostsHTML = try templateRenderer.renderRecentPosts(recentPosts, site: site) + func writeRecentPosts(_ recentPosts: [Post], for site: Site, to targetURL: URL, with renderer: PostsRendering) throws { + let recentPostsHTML = try renderer.renderRecentPosts(recentPosts, site: site) let fileURL = targetURL.appendingPathComponent("index.html") try fileWriter.write(string: recentPostsHTML, to: fileURL) } @@ -48,8 +48,8 @@ extension PostWriter { // MARK: - Post archive page extension PostWriter { - func writeArchive(posts: PostsByYear, for site: Site, to targetURL: URL, with templateRenderer: PostsTemplateRenderer) throws { - let archiveHTML = try templateRenderer.renderArchive(postsByYear: posts, site: site) + func writeArchive(posts: PostsByYear, for site: Site, to targetURL: URL, with renderer: PostsRendering) throws { + let archiveHTML = try renderer.renderArchive(postsByYear: posts, site: site) let archiveURL = targetURL.appendingPathComponent(outputPath).appendingPathComponent("index.html") try fileWriter.write(string: archiveHTML, to: archiveURL) } @@ -58,10 +58,10 @@ extension PostWriter { // MARK: - Yearly post index pages extension PostWriter { - func writeYearIndexes(posts: PostsByYear, for site: Site, to targetURL: URL, with templateRenderer: PostsTemplateRenderer) throws { + func writeYearIndexes(posts: PostsByYear, for site: Site, to targetURL: URL, with renderer: PostsRendering) throws { for yearPosts in posts.byYear.values { let yearDir = targetURL.appendingPathComponent(yearPosts.path) - let yearHTML = try templateRenderer.renderYearPosts(yearPosts, site: site) + let yearHTML = try renderer.renderYearPosts(yearPosts, site: site) let yearURL = yearDir.appendingPathComponent("index.html") try fileWriter.write(string: yearHTML, to: yearURL) } @@ -71,11 +71,11 @@ extension PostWriter { // MARK: - Monthly post roll-up pages extension PostWriter { - func writeMonthRollups(posts: PostsByYear, for site: Site, to targetURL: URL, with templateRenderer: PostsTemplateRenderer) throws { + func writeMonthRollups(posts: PostsByYear, for site: Site, to targetURL: URL, with renderer: PostsRendering) throws { for yearPosts in posts.byYear.values { for monthPosts in yearPosts.byMonth.values { let monthDir = targetURL.appendingPathComponent(monthPosts.path) - let monthHTML = try templateRenderer.renderMonthPosts(monthPosts, site: site) + let monthHTML = try renderer.renderMonthPosts(monthPosts, site: site) let monthURL = monthDir.appendingPathComponent("index.html") try fileWriter.write(string: monthHTML, to: monthURL) } diff --git a/samhuri.net/Sources/samhuri.net/Posts/PostsPlugin+Builder.swift b/samhuri.net/Sources/samhuri.net/Posts/PostsPlugin+Builder.swift new file mode 100644 index 0000000..431e305 --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Posts/PostsPlugin+Builder.swift @@ -0,0 +1,86 @@ +// +// PostsPlugin+Builder.swift +// samhuri.net +// +// Created by Sami Samhuri on 2019-12-15. +// + +import Foundation + +extension PostsPlugin { + final class Builder { + private let renderer: Renderer + private var path: String? + private var jsonFeed: JSONFeed? + private var rssFeed: RSSFeed? + + init(renderer: Renderer) { + self.renderer = renderer + } + + func path(_ path: String) -> Self { + precondition(self.path == nil, "path is already defined") + self.path = path + return self + } + + func jsonFeed( + path: String? = nil, + avatarPath: String? = nil, + iconPath: String? = nil, + faviconPath: String? = nil + ) -> Self { + precondition(jsonFeed == nil, "JSON feed is already defined") + jsonFeed = JSONFeed( + path: path ?? "feed.json", + avatarPath: avatarPath, + iconPath: iconPath, + faviconPath: faviconPath + ) + return self + } + + func rssFeed(path: String? = nil) -> Self { + precondition(rssFeed == nil, "RSS feed is already defined") + rssFeed = RSSFeed(path: path ?? "feed.xml") + return self + } + + func build() -> PostsPlugin { + let postRepo: PostRepo + let postWriter: PostWriter + if let outputPath = path { + postRepo = PostRepo(outputPath: outputPath) + postWriter = PostWriter(outputPath: outputPath) + } + else { + postRepo = PostRepo() + postWriter = PostWriter() + } + + let jsonFeedWriter: JSONFeedWriter? + if let jsonFeed = jsonFeed { + jsonFeedWriter = JSONFeedWriter(jsonFeed: jsonFeed) + } + else { + jsonFeedWriter = nil + } + + let rssFeedWriter: RSSFeedWriter? + if let rssFeed = rssFeed { + rssFeedWriter = RSSFeedWriter(rssFeed: rssFeed) + } + else { + rssFeedWriter = nil + } + + return PostsPlugin( + renderer: renderer, + postRepo: postRepo, + postWriter: postWriter, + jsonFeedWriter: jsonFeedWriter, + rssFeedWriter: rssFeedWriter + ) + } + } +} diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsPlugin.swift b/samhuri.net/Sources/samhuri.net/Posts/PostsPlugin.swift similarity index 75% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsPlugin.swift rename to samhuri.net/Sources/samhuri.net/Posts/PostsPlugin.swift index ca933de..eff11b9 100644 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsPlugin.swift +++ b/samhuri.net/Sources/samhuri.net/Posts/PostsPlugin.swift @@ -8,20 +8,22 @@ import Foundation final class PostsPlugin: Plugin { - let templateRenderer: PostsTemplateRenderer + typealias Renderer = PostsRendering & JSONFeedRendering & RSSFeedRendering + + let renderer: Renderer let postRepo: PostRepo let postWriter: PostWriter let jsonFeedWriter: JSONFeedWriter? let rssFeedWriter: RSSFeedWriter? init( - templateRenderer: PostsTemplateRenderer, + renderer: Renderer, postRepo: PostRepo = PostRepo(), postWriter: PostWriter = PostWriter(), jsonFeedWriter: JSONFeedWriter?, rssFeedWriter: RSSFeedWriter? ) { - self.templateRenderer = templateRenderer + self.renderer = renderer self.postRepo = postRepo self.postWriter = postWriter self.jsonFeedWriter = jsonFeedWriter @@ -43,12 +45,12 @@ final class PostsPlugin: Plugin { return } - try postWriter.writeRecentPosts(postRepo.recentPosts, for: site, to: targetURL, with: templateRenderer) - try postWriter.writePosts(postRepo.sortedPosts, for: site, to: targetURL, with: templateRenderer) - try postWriter.writeArchive(posts: postRepo.posts, for: site, to: targetURL, with: templateRenderer) - try postWriter.writeYearIndexes(posts: postRepo.posts, for: site, to: targetURL, with: templateRenderer) - try postWriter.writeMonthRollups(posts: postRepo.posts, for: site, to: targetURL, with: templateRenderer) - try jsonFeedWriter?.writeFeed(postRepo.postsForFeed, for: site, to: targetURL, with: templateRenderer) - try rssFeedWriter?.writeFeed(postRepo.postsForFeed, for: site, to: targetURL, with: templateRenderer) + try postWriter.writeRecentPosts(postRepo.recentPosts, for: site, to: targetURL, with: renderer) + try postWriter.writePosts(postRepo.sortedPosts, for: site, to: targetURL, with: renderer) + try postWriter.writeArchive(posts: postRepo.posts, for: site, to: targetURL, with: renderer) + try postWriter.writeYearIndexes(posts: postRepo.posts, for: site, to: targetURL, with: renderer) + try postWriter.writeMonthRollups(posts: postRepo.posts, for: site, to: targetURL, with: renderer) + try jsonFeedWriter?.writeFeed(postRepo.postsForFeed, for: site, to: targetURL, with: renderer) + try rssFeedWriter?.writeFeed(postRepo.postsForFeed, for: site, to: targetURL, with: renderer) } } diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsTemplateRenderer.swift b/samhuri.net/Sources/samhuri.net/Posts/PostsRendering.swift similarity index 66% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsTemplateRenderer.swift rename to samhuri.net/Sources/samhuri.net/Posts/PostsRendering.swift index 2ab2b35..0914839 100644 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsTemplateRenderer.swift +++ b/samhuri.net/Sources/samhuri.net/Posts/PostsRendering.swift @@ -1,5 +1,5 @@ // -// PostsTemplateRenderer.swift +// PostsRendering.swift // samhuri.net // // Created by Sami Samhuri on 2019-12-17. @@ -7,7 +7,7 @@ import Foundation -protocol PostsTemplateRenderer { +protocol PostsRendering { func renderArchive(postsByYear: PostsByYear, site: Site) throws -> String func renderYearPosts(_ yearPosts: YearPosts, site: Site) throws -> String @@ -17,10 +17,4 @@ protocol PostsTemplateRenderer { func renderPost(_ post: Post, site: Site) throws -> String func renderRecentPosts(_ posts: [Post], site: Site) throws -> String - - // MARK: - Feeds - - func renderFeedPost(_ post: Post, site: Site) throws -> String - - func renderRSSFeed(posts: [Post], feedURL: URL, site: Site) throws -> String } diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Feeds/RSSFeed.swift b/samhuri.net/Sources/samhuri.net/Posts/RSSFeed/RSSFeed.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Feeds/RSSFeed.swift rename to samhuri.net/Sources/samhuri.net/Posts/RSSFeed/RSSFeed.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Feeds/RSSFeedWriter.swift b/samhuri.net/Sources/samhuri.net/Posts/RSSFeed/RSSFeedWriter.swift similarity index 70% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Feeds/RSSFeedWriter.swift rename to samhuri.net/Sources/samhuri.net/Posts/RSSFeed/RSSFeedWriter.swift index 29bfca1..7659a12 100644 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/Feeds/RSSFeedWriter.swift +++ b/samhuri.net/Sources/samhuri.net/Posts/RSSFeed/RSSFeedWriter.swift @@ -7,6 +7,10 @@ import Foundation +protocol RSSFeedRendering { + func renderRSSFeed(posts: [Post], feedURL: URL, site: Site) throws -> String +} + final class RSSFeedWriter { let fileWriter: FileWriting let rssFeed: RSSFeed @@ -16,9 +20,9 @@ final class RSSFeedWriter { self.fileWriter = fileWriter } - func writeFeed(_ posts: [Post], for site: Site, to targetURL: URL, with templateRenderer: PostsTemplateRenderer) throws { + func writeFeed(_ posts: [Post], for site: Site, to targetURL: URL, with renderer: RSSFeedRendering) throws { let feedURL = site.url.appendingPathComponent(rssFeed.path) - let feedXML = try templateRenderer.renderRSSFeed(posts: posts, feedURL: feedURL, site: site) + let feedXML = try renderer.renderRSSFeed(posts: posts, feedURL: feedURL, site: site) let feedFileURL = targetURL.appendingPathComponent(rssFeed.path) try fileWriter.write(string: feedXML, to: feedFileURL) } diff --git a/samhuri.net/Sources/samhuri.net/Posts/FeedPostTemplate.swift b/samhuri.net/Sources/samhuri.net/Posts/Templates/FeedPostTemplate.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Posts/FeedPostTemplate.swift rename to samhuri.net/Sources/samhuri.net/Posts/Templates/FeedPostTemplate.swift diff --git a/samhuri.net/Sources/samhuri.net/Posts/MonthPostsTemplate.swift b/samhuri.net/Sources/samhuri.net/Posts/Templates/MonthPostsTemplate.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Posts/MonthPostsTemplate.swift rename to samhuri.net/Sources/samhuri.net/Posts/Templates/MonthPostsTemplate.swift diff --git a/samhuri.net/Sources/samhuri.net/Posts/Templates/PageRenderer+JSONFeed.swift b/samhuri.net/Sources/samhuri.net/Posts/Templates/PageRenderer+JSONFeed.swift new file mode 100644 index 0000000..dcbe5c9 --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Posts/Templates/PageRenderer+JSONFeed.swift @@ -0,0 +1,21 @@ +// +// PageRenderer+JSONFeed.swift +// samhuri.net +// +// Created by Sami Samhuri on 2020-01-01. +// + +import Foundation +import Plot + +extension PageRenderer: JSONFeedRendering { + func renderJSONFeedPost(_ post: Post, site: Site) throws -> String { + let context = SiteContext(site: site, subtitle: post.title, templateAssets: post.templateAssets) + let url = site.url.appendingPathComponent(post.path) + // Turn relative URLs into absolute ones. + return Node.feedPost(post, url: url, styles: context.styles) + .render(indentedBy: .spaces(2)) + .replacingOccurrences(of: "href=\"/", with: "href=\"\(site.url)/") + .replacingOccurrences(of: "src=\"/", with: "src=\"\(site.url)/") + } +} diff --git a/samhuri.net/Sources/samhuri.net/Posts/Templates/PageRenderer+Posts.swift b/samhuri.net/Sources/samhuri.net/Posts/Templates/PageRenderer+Posts.swift new file mode 100644 index 0000000..44418ff --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Posts/Templates/PageRenderer+Posts.swift @@ -0,0 +1,37 @@ +// +// PageRenderer+Posts.swift +// samhuri.net +// +// Created by Sami Samhuri on 2019-12-22. +// + +import Foundation +import Plot + +extension PageRenderer: PostsRendering { + func renderArchive(postsByYear: PostsByYear, site: Site) throws -> String { + let context = SiteContext(site: site, subtitle: "Archive") + return render(.archive(postsByYear), context: context) + } + + func renderYearPosts(_ yearPosts: YearPosts, site: Site) throws -> String { + let context = SiteContext(site: site, subtitle: yearPosts.title) + return render(.yearPosts(yearPosts), context: context) + } + + func renderMonthPosts(_ posts: MonthPosts, site: Site) throws -> String { + let assets = posts.posts.templateAssets + let context = SiteContext(site: site, subtitle: "\(posts.month.name) \(posts.year)", templateAssets: assets) + return render(.monthPosts(posts), context: context) + } + + func renderPost(_ post: Post, site: Site) throws -> String { + let context = SiteContext(site: site, subtitle: post.title, templateAssets: post.templateAssets) + return render(.post(post, articleClass: "container"), context: context) + } + + func renderRecentPosts(_ posts: [Post], site: Site) throws -> String { + let context = SiteContext(site: site, subtitle: nil, templateAssets: posts.templateAssets) + return render(.recentPosts(posts), context: context) + } +} diff --git a/samhuri.net/Sources/samhuri.net/Posts/Templates/PageRenderer+RSSFeed.swift b/samhuri.net/Sources/samhuri.net/Posts/Templates/PageRenderer+RSSFeed.swift new file mode 100644 index 0000000..7155d6c --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Posts/Templates/PageRenderer+RSSFeed.swift @@ -0,0 +1,32 @@ +// +// PageRenderer+RSSFeed.swift +// samhuri.net +// +// Created by Sami Samhuri on 2020-01-01. +// + +import Foundation +import Plot + +extension PageRenderer: RSSFeedRendering { + func renderRSSFeed(posts: [Post], feedURL: URL, site: Site) throws -> String { + try RSS( + .title(site.title), + .if(site.description != nil, .description(site.description!)), + .link(site.url), + .pubDate(posts[0].date), + .atomLink(feedURL), + .group(posts.map { post in + let url = site.url.appendingPathComponent(post.path) + return .item( + .title(post.isLink ? "→ \(post.title)" : post.title), + .pubDate(post.date), + .element(named: "author", text: post.author), + .link(url), + .guid(.text(url.absoluteString), .isPermaLink(true)), + .content(try renderJSONFeedPost(post, site: site)) + ) + }) + ).render(indentedBy: .spaces(2)) + } +} diff --git a/samhuri.net/Sources/samhuri.net/Posts/PostTemplate.swift b/samhuri.net/Sources/samhuri.net/Posts/Templates/PostTemplate.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Posts/PostTemplate.swift rename to samhuri.net/Sources/samhuri.net/Posts/Templates/PostTemplate.swift diff --git a/samhuri.net/Sources/samhuri.net/Posts/PostsArchiveTemplate.swift b/samhuri.net/Sources/samhuri.net/Posts/Templates/PostsArchiveTemplate.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Posts/PostsArchiveTemplate.swift rename to samhuri.net/Sources/samhuri.net/Posts/Templates/PostsArchiveTemplate.swift diff --git a/samhuri.net/Sources/samhuri.net/Posts/PostsAssets.swift b/samhuri.net/Sources/samhuri.net/Posts/Templates/PostsAssets.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Posts/PostsAssets.swift rename to samhuri.net/Sources/samhuri.net/Posts/Templates/PostsAssets.swift diff --git a/samhuri.net/Sources/samhuri.net/Posts/RecentPostsTemplate.swift b/samhuri.net/Sources/samhuri.net/Posts/Templates/RecentPostsTemplate.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Posts/RecentPostsTemplate.swift rename to samhuri.net/Sources/samhuri.net/Posts/Templates/RecentPostsTemplate.swift diff --git a/samhuri.net/Sources/samhuri.net/Posts/YearPostsTemplate.swift b/samhuri.net/Sources/samhuri.net/Posts/Templates/YearPostsTemplate.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Posts/YearPostsTemplate.swift rename to samhuri.net/Sources/samhuri.net/Posts/Templates/YearPostsTemplate.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/Project.swift b/samhuri.net/Sources/samhuri.net/Projects/Project.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/Project.swift rename to samhuri.net/Sources/samhuri.net/Projects/Project.swift diff --git a/samhuri.net/Sources/samhuri.net/Projects/ProjectsPlugin+Builder.swift b/samhuri.net/Sources/samhuri.net/Projects/ProjectsPlugin+Builder.swift new file mode 100644 index 0000000..6a8dc4f --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Projects/ProjectsPlugin+Builder.swift @@ -0,0 +1,51 @@ +// +// ProjectsPlugin+Builder.swift +// samhuri.net +// +// Created by Sami Samhuri on 2019-12-19. +// + +import Foundation + +extension ProjectsPlugin { + final class Builder { + let renderer: ProjectsRenderer + private var path: String? + private var projects: [PartialProject] = [] + private var assets: TemplateAssets? + + init(renderer: ProjectsRenderer) { + self.renderer = renderer + } + + func path(_ path: String) -> Self { + precondition(self.path == nil, "path is already defined") + self.path = path + return self + } + + func assets(_ assets: TemplateAssets) -> Self { + precondition(self.assets == nil, "assets are already defined") + self.assets = assets + return self + } + + func add(_ title: String, description: String) -> Self { + let project = PartialProject(title: title, description: description) + projects.append(project) + return self + } + + func build() -> ProjectsPlugin { + if projects.isEmpty { + print("WARNING: No projects have been added") + } + return ProjectsPlugin( + projects: projects, + renderer: renderer, + projectAssets: assets ?? .empty(), + outputPath: path + ) + } + } +} diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/ProjectsPlugin.swift b/samhuri.net/Sources/samhuri.net/Projects/ProjectsPlugin.swift similarity index 83% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/ProjectsPlugin.swift rename to samhuri.net/Sources/samhuri.net/Projects/ProjectsPlugin.swift index 74002f8..407d946 100644 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/ProjectsPlugin.swift +++ b/samhuri.net/Sources/samhuri.net/Projects/ProjectsPlugin.swift @@ -16,7 +16,7 @@ final class ProjectsPlugin: Plugin { let fileWriter: FileWriting let outputPath: String let partialProjects: [PartialProject] - let templateRenderer: ProjectsTemplateRenderer + let renderer: ProjectsRenderer let projectAssets: TemplateAssets var projects: [Project] = [] @@ -24,13 +24,13 @@ final class ProjectsPlugin: Plugin { init( projects: [PartialProject], - templateRenderer: ProjectsTemplateRenderer, + renderer: ProjectsRenderer, projectAssets: TemplateAssets, outputPath: String? = nil, fileWriter: FileWriting = FileWriter() ) { self.partialProjects = projects - self.templateRenderer = templateRenderer + self.renderer = renderer self.projectAssets = projectAssets self.outputPath = outputPath ?? "projects" self.fileWriter = fileWriter @@ -56,12 +56,12 @@ final class ProjectsPlugin: Plugin { let projectsDir = targetURL.appendingPathComponent(outputPath) let projectsURL = projectsDir.appendingPathComponent("index.html") - let projectsHTML = try templateRenderer.renderProjects(projects, site: site) + let projectsHTML = try renderer.renderProjects(projects, site: site) try fileWriter.write(string: projectsHTML, to: projectsURL) for project in projects { let projectURL = projectsDir.appendingPathComponent("\(project.title)/index.html") - let projectHTML = try templateRenderer.renderProject(project, site: site, assets: projectAssets) + let projectHTML = try renderer.renderProject(project, site: site, assets: projectAssets) try fileWriter.write(string: projectHTML, to: projectURL) } } diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/ProjectsTemplateRenderer.swift b/samhuri.net/Sources/samhuri.net/Projects/ProjectsRenderer.swift similarity index 89% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/ProjectsTemplateRenderer.swift rename to samhuri.net/Sources/samhuri.net/Projects/ProjectsRenderer.swift index ff43f4b..912c687 100644 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/ProjectsTemplateRenderer.swift +++ b/samhuri.net/Sources/samhuri.net/Projects/ProjectsRenderer.swift @@ -7,7 +7,8 @@ import Foundation -protocol ProjectsTemplateRenderer { +protocol ProjectsRenderer { func renderProjects(_ projects: [Project], site: Site) throws -> String + func renderProject(_ project: Project, site: Site, assets: TemplateAssets) throws -> String } diff --git a/samhuri.net/Sources/samhuri.net/Projects/PageRenderer+Projects.swift b/samhuri.net/Sources/samhuri.net/Projects/Templates/PageRenderer+Projects.swift similarity index 93% rename from samhuri.net/Sources/samhuri.net/Projects/PageRenderer+Projects.swift rename to samhuri.net/Sources/samhuri.net/Projects/Templates/PageRenderer+Projects.swift index 35df994..e8a1b0d 100644 --- a/samhuri.net/Sources/samhuri.net/Projects/PageRenderer+Projects.swift +++ b/samhuri.net/Sources/samhuri.net/Projects/Templates/PageRenderer+Projects.swift @@ -8,7 +8,7 @@ import Foundation import Plot -extension PageRenderer: ProjectsTemplateRenderer { +extension PageRenderer: ProjectsRenderer { func renderProjects(_ projects: [Project], site: Site) throws -> String { let context = SiteContext(site: site, subtitle: "Projects", templateAssets: .empty()) return render(.projects(projects), context: context) diff --git a/samhuri.net/Sources/samhuri.net/Projects/ProjectContext.swift b/samhuri.net/Sources/samhuri.net/Projects/Templates/ProjectContext.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Projects/ProjectContext.swift rename to samhuri.net/Sources/samhuri.net/Projects/Templates/ProjectContext.swift diff --git a/samhuri.net/Sources/samhuri.net/Projects/ProjectTemplate.swift b/samhuri.net/Sources/samhuri.net/Projects/Templates/ProjectTemplate.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Projects/ProjectTemplate.swift rename to samhuri.net/Sources/samhuri.net/Projects/Templates/ProjectTemplate.swift diff --git a/samhuri.net/Sources/samhuri.net/Projects/ProjectsTemplate.swift b/samhuri.net/Sources/samhuri.net/Projects/Templates/ProjectsTemplate.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Projects/ProjectsTemplate.swift rename to samhuri.net/Sources/samhuri.net/Projects/Templates/ProjectsTemplate.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/MarkdownRenderer.swift b/samhuri.net/Sources/samhuri.net/Site/MarkdownRenderer.swift similarity index 92% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/MarkdownRenderer.swift rename to samhuri.net/Sources/samhuri.net/Site/MarkdownRenderer.swift index efd1dc8..c4556c3 100644 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/MarkdownRenderer.swift +++ b/samhuri.net/Sources/samhuri.net/Site/MarkdownRenderer.swift @@ -12,9 +12,9 @@ final class MarkdownRenderer: Renderer { let fileManager: FileManager = .default let fileWriter: FileWriting let markdownParser = MarkdownParser() - let pageRenderer: MarkdownPageRenderer + let pageRenderer: PageRendering - init(pageRenderer: MarkdownPageRenderer, fileWriter: FileWriting = FileWriter()) { + init(pageRenderer: PageRendering, fileWriter: FileWriting = FileWriter()) { self.pageRenderer = pageRenderer self.fileWriter = fileWriter } diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/MarkdownPageRenderer.swift b/samhuri.net/Sources/samhuri.net/Site/PageRendering.swift similarity index 74% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/MarkdownPageRenderer.swift rename to samhuri.net/Sources/samhuri.net/Site/PageRendering.swift index 0de70b2..06162bd 100644 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/MarkdownPageRenderer.swift +++ b/samhuri.net/Sources/samhuri.net/Site/PageRendering.swift @@ -1,5 +1,5 @@ // -// MarkdownPageRenderer.swift +// PageRendering.swift // samhuri.net // // Created by Sami Samhuri on 2019-12-03. @@ -7,6 +7,6 @@ import Foundation -protocol MarkdownPageRenderer { +protocol PageRendering { func renderPage(site: Site, bodyHTML: String, metadata: [String: String]) throws -> String } diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Plugin.swift b/samhuri.net/Sources/samhuri.net/Site/Plugin.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Plugin.swift rename to samhuri.net/Sources/samhuri.net/Site/Plugin.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Renderer.swift b/samhuri.net/Sources/samhuri.net/Site/Renderer.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Renderer.swift rename to samhuri.net/Sources/samhuri.net/Site/Renderer.swift diff --git a/samhuri.net/Sources/samhuri.net/Site/Site+Builder.swift b/samhuri.net/Sources/samhuri.net/Site/Site+Builder.swift new file mode 100644 index 0000000..b87a175 --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Site/Site+Builder.swift @@ -0,0 +1,80 @@ +// +// Site+Builder.swift +// samhuri.net +// +// Created by Sami Samhuri on 2019-12-15. +// + +import Foundation + +extension Site { + final class Builder { + private let title: String + private let description: String? + private let author: String + private let email: String + private let url: URL + + private var styles: [String] = [] + private var scripts: [String] = [] + + private var plugins: [Plugin] = [] + private var renderers: [Renderer] = [] + + init( + title: String, + description: String? = nil, + author: String, + email: String, + url: URL + ) { + self.title = title + self.description = description + self.author = author + self.email = email + self.url = url + } + + func styles(_ styles: String...) -> Self { + self.styles.append(contentsOf: styles) + return self + } + + func scripts(_ scripts: String...) -> Self { + self.scripts.append(contentsOf: scripts) + return self + } + + func plugin(_ plugin: Plugin) -> Self { + plugins.append(plugin) + return self + } + + func renderer(_ renderer: Renderer) -> Self { + renderers.append(renderer) + return self + } + + func build() -> Site { + Site( + author: author, + email: email, + title: title, + description: description, + url: url, + styles: styles, + scripts: scripts, + renderers: renderers, + plugins: plugins + ) + } + } +} + +// MARK: - Markdown + +extension Site.Builder { + func renderMarkdown(pageRenderer: PageRendering) -> Self { + renderer(MarkdownRenderer(pageRenderer: pageRenderer)) + } +} diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Site.swift b/samhuri.net/Sources/samhuri.net/Site/Site.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/Site.swift rename to samhuri.net/Sources/samhuri.net/Site/Site.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/SiteGenerator.swift b/samhuri.net/Sources/samhuri.net/Site/SiteGenerator.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/SiteGenerator.swift rename to samhuri.net/Sources/samhuri.net/Site/SiteGenerator.swift diff --git a/samhuri.net/Sources/samhuri.net/Templates/HTMLElements.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/HTMLElements.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Templates/HTMLElements.swift rename to samhuri.net/Sources/samhuri.net/Site/Templates/HTMLElements.swift diff --git a/samhuri.net/Sources/samhuri.net/MetadataList.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/MetadataList.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/MetadataList.swift rename to samhuri.net/Sources/samhuri.net/Site/Templates/MetadataList.swift diff --git a/samhuri.net/Sources/samhuri.net/PageRenderer.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/PageRenderer.swift similarity index 94% rename from samhuri.net/Sources/samhuri.net/PageRenderer.swift rename to samhuri.net/Sources/samhuri.net/Site/Templates/PageRenderer.swift index 538be30..178e4e8 100644 --- a/samhuri.net/Sources/samhuri.net/PageRenderer.swift +++ b/samhuri.net/Sources/samhuri.net/Site/Templates/PageRenderer.swift @@ -14,7 +14,7 @@ final class PageRenderer { } } -extension PageRenderer: MarkdownPageRenderer { +extension PageRenderer: PageRendering { func renderPage(site: Site, bodyHTML: String, metadata: [String: String]) throws -> String { let pageTitle = metadata["Title"] let scripts = metadata.commaSeparatedList(key: "Scripts") diff --git a/samhuri.net/Sources/samhuri.net/Templates/PageTemplate.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/PageTemplate.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Templates/PageTemplate.swift rename to samhuri.net/Sources/samhuri.net/Site/Templates/PageTemplate.swift diff --git a/samhuri.net/Sources/samhuri.net/Templates/SiteContext.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/SiteContext.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Templates/SiteContext.swift rename to samhuri.net/Sources/samhuri.net/Site/Templates/SiteContext.swift diff --git a/samhuri.net/Sources/samhuri.net/Templates/SiteTemplate.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/SiteTemplate.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Templates/SiteTemplate.swift rename to samhuri.net/Sources/samhuri.net/Site/Templates/SiteTemplate.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/TemplateAssets.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/TemplateAssets.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/SiteGenerator/TemplateAssets.swift rename to samhuri.net/Sources/samhuri.net/Site/Templates/TemplateAssets.swift diff --git a/samhuri.net/Sources/samhuri.net/Templates/TemplateContext.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/TemplateContext.swift similarity index 100% rename from samhuri.net/Sources/samhuri.net/Templates/TemplateContext.swift rename to samhuri.net/Sources/samhuri.net/Site/Templates/TemplateContext.swift diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsPluginBuilder.swift b/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsPluginBuilder.swift deleted file mode 100644 index 7726b23..0000000 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/Posts/PostsPluginBuilder.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// PostsPluginBuilder.swift -// samhuri.net -// -// Created by Sami Samhuri on 2019-12-15. -// - -import Foundation - -final class PostsPluginBuilder { - private let templateRenderer: PostsTemplateRenderer - private var path: String? - private var jsonFeed: JSONFeed? - private var rssFeed: RSSFeed? - - init(templateRenderer: PostsTemplateRenderer) { - self.templateRenderer = templateRenderer - } - - func path(_ path: String) -> PostsPluginBuilder { - precondition(self.path == nil, "path is already defined") - self.path = path - return self - } - - func jsonFeed( - path: String? = nil, - avatarPath: String? = nil, - iconPath: String? = nil, - faviconPath: String? = nil - ) -> PostsPluginBuilder { - precondition(jsonFeed == nil, "JSON feed is already defined") - jsonFeed = JSONFeed( - path: path ?? "feed.json", - avatarPath: avatarPath, - iconPath: iconPath, - faviconPath: faviconPath - ) - return self - } - - func rssFeed(path: String? = nil) -> PostsPluginBuilder { - precondition(rssFeed == nil, "RSS feed is already defined") - rssFeed = RSSFeed(path: path ?? "feed.xml") - return self - } - - func build() -> PostsPlugin { - let postRepo: PostRepo - let postWriter: PostWriter - if let outputPath = path { - postRepo = PostRepo(outputPath: outputPath) - postWriter = PostWriter(outputPath: outputPath) - } - else { - postRepo = PostRepo() - postWriter = PostWriter() - } - - let jsonFeedWriter: JSONFeedWriter? - if let jsonFeed = jsonFeed { - jsonFeedWriter = JSONFeedWriter(jsonFeed: jsonFeed) - } - else { - jsonFeedWriter = nil - } - - let rssFeedWriter: RSSFeedWriter? - if let rssFeed = rssFeed { - rssFeedWriter = RSSFeedWriter(rssFeed: rssFeed) - } - else { - rssFeedWriter = nil - } - - return PostsPlugin( - templateRenderer: templateRenderer, - postRepo: postRepo, - postWriter: postWriter, - jsonFeedWriter: jsonFeedWriter, - rssFeedWriter: rssFeedWriter - ) - } -} diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/ProjectsPluginBuilder.swift b/samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/ProjectsPluginBuilder.swift deleted file mode 100644 index 6072185..0000000 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/Projects/ProjectsPluginBuilder.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// ProjectsPluginBuilder.swift -// samhuri.net -// -// Created by Sami Samhuri on 2019-12-19. -// - -import Foundation - -final class ProjectsPluginBuilder { - let templateRenderer: ProjectsTemplateRenderer - private var path: String? - private var projects: [PartialProject] = [] - private var assets: TemplateAssets? - - init(templateRenderer: ProjectsTemplateRenderer) { - self.templateRenderer = templateRenderer - } - - func path(_ path: String) -> ProjectsPluginBuilder { - precondition(self.path == nil, "path is already defined") - self.path = path - return self - } - - func assets(_ assets: TemplateAssets) -> ProjectsPluginBuilder { - precondition(self.assets == nil, "assets are already defined") - self.assets = assets - return self - } - - func add(_ title: String, description: String) -> ProjectsPluginBuilder { - let project = PartialProject(title: title, description: description) - projects.append(project) - return self - } - - func build() -> ProjectsPlugin { - if projects.isEmpty { - print("WARNING: No projects have been added") - } - return ProjectsPlugin( - projects: projects, - templateRenderer: templateRenderer, - projectAssets: assets ?? .empty(), - outputPath: path - ) - } -} diff --git a/samhuri.net/Sources/samhuri.net/SiteGenerator/SiteBuilder.swift b/samhuri.net/Sources/samhuri.net/SiteGenerator/SiteBuilder.swift deleted file mode 100644 index b8de1bd..0000000 --- a/samhuri.net/Sources/samhuri.net/SiteGenerator/SiteBuilder.swift +++ /dev/null @@ -1,78 +0,0 @@ -// -// SiteBuilder.swift -// samhuri.net -// -// Created by Sami Samhuri on 2019-12-15. -// - -import Foundation - -final class SiteBuilder { - private let title: String - private let description: String? - private let author: String - private let email: String - private let url: URL - - private var styles: [String] = [] - private var scripts: [String] = [] - - private var plugins: [Plugin] = [] - private var renderers: [Renderer] = [] - - init( - title: String, - description: String? = nil, - author: String, - email: String, - url: URL - ) { - self.title = title - self.description = description - self.author = author - self.email = email - self.url = url - } - - func styles(_ styles: String...) -> SiteBuilder { - self.styles.append(contentsOf: styles) - return self - } - - func scripts(_ scripts: String...) -> SiteBuilder { - self.scripts.append(contentsOf: scripts) - return self - } - - func plugin(_ plugin: Plugin) -> SiteBuilder { - plugins.append(plugin) - return self - } - - func renderer(_ renderer: Renderer) -> SiteBuilder { - renderers.append(renderer) - return self - } - - func build() -> Site { - Site( - author: author, - email: email, - title: title, - description: description, - url: url, - styles: styles, - scripts: scripts, - renderers: renderers, - plugins: plugins - ) - } -} - -// MARK: - Markdown - -extension SiteBuilder { - func renderMarkdown(pageRenderer: MarkdownPageRenderer) -> SiteBuilder { - renderer(MarkdownRenderer(pageRenderer: pageRenderer)) - } -} diff --git a/samhuri.net/Sources/samhuri.net/samhuri.net.swift b/samhuri.net/Sources/samhuri.net/samhuri.net.swift index 335b462..9f4bdcd 100644 --- a/samhuri.net/Sources/samhuri.net/samhuri.net.swift +++ b/samhuri.net/Sources/samhuri.net/samhuri.net.swift @@ -10,8 +10,15 @@ public extension samhuri { self.siteURLOverride = siteURLOverride } + public func generate(sourceURL: URL, targetURL: URL) throws { + let renderer = PageRenderer() + let site = buildSite(renderer: renderer) + let generator = try SiteGenerator(sourceURL: sourceURL, site: site) + try generator.generate(targetURL: targetURL) + } + func buildSite(renderer: PageRenderer) -> Site { - let projectsPlugin = ProjectsPluginBuilder(templateRenderer: renderer) + let projectsPlugin = ProjectsPlugin.Builder(renderer: renderer) .path("projects") .assets(TemplateAssets(scripts: [ "https://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js", @@ -35,7 +42,7 @@ public extension samhuri { .add("samhuri.net", description: "this site") .build() - let postsPlugin = PostsPluginBuilder(templateRenderer: renderer) + let postsPlugin = PostsPlugin.Builder(renderer: renderer) .path("posts") .jsonFeed( avatarPath: "images/me.jpg", @@ -45,7 +52,7 @@ public extension samhuri { .rssFeed() .build() - return SiteBuilder( + return Site.Builder( title: "samhuri.net", description: "just some blog", author: "Sami Samhuri", @@ -58,12 +65,5 @@ public extension samhuri { .plugin(postsPlugin) .build() } - - public func generate(sourceURL: URL, targetURL: URL) throws { - let renderer = PageRenderer() - let site = buildSite(renderer: renderer) - let generator = try SiteGenerator(sourceURL: sourceURL, site: site) - try generator.generate(targetURL: targetURL) - } } }