diff --git a/samhuri.net/Sources/samhuri.net/Posts/Model/HTMLRef.swift b/samhuri.net/Sources/samhuri.net/Posts/Model/HTMLRef.swift new file mode 100644 index 0000000..c2340e5 --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Posts/Model/HTMLRef.swift @@ -0,0 +1,37 @@ +// +// HTMLRef.swift +// samhuri.net +// +// Created by Sami Samhuri on 2020-01-02. +// + +import Foundation + +protocol HTMLRef: ExpressibleByStringLiteral { + // Concrete requirements, must be implemented + + var ref: String { get } + + // These all have default implementations + + init(ref: String) + + func url(dir: URL) -> URL +} + +extension HTMLRef { + init(stringLiteral value: String) { + self.init(ref: value) + } + + func url(dir: URL) -> URL { + // ref is either an absolute HTTP URL or path relative to the given directory. + isHTTPURL ? URL(string: ref)! : dir.appendingPathComponent(ref) + } +} + +private extension HTMLRef { + var isHTTPURL: Bool { + ref.hasPrefix("http:") || ref.hasPrefix("https:") + } +} diff --git a/samhuri.net/Sources/samhuri.net/Posts/Model/Post.swift b/samhuri.net/Sources/samhuri.net/Posts/Model/Post.swift index 2920440..c8316af 100644 --- a/samhuri.net/Sources/samhuri.net/Posts/Model/Post.swift +++ b/samhuri.net/Sources/samhuri.net/Posts/Model/Post.swift @@ -15,8 +15,8 @@ struct Post { let formattedDate: String let link: URL? let tags: [String] - let scripts: [String] - let styles: [String] + let scripts: [Script] + let styles: [Stylesheet] let body: String let path: String diff --git a/samhuri.net/Sources/samhuri.net/Posts/Model/Script.swift b/samhuri.net/Sources/samhuri.net/Posts/Model/Script.swift new file mode 100644 index 0000000..6083f20 --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Posts/Model/Script.swift @@ -0,0 +1,12 @@ +// +// Script.swift +// samhuri.net +// +// Created by Sami Samhuri on 2020-01-02. +// + +import Foundation + +struct Script: HTMLRef, Equatable { + let ref: String +} diff --git a/samhuri.net/Sources/samhuri.net/Posts/Model/Stylesheet.swift b/samhuri.net/Sources/samhuri.net/Posts/Model/Stylesheet.swift new file mode 100644 index 0000000..a0e91ba --- /dev/null +++ b/samhuri.net/Sources/samhuri.net/Posts/Model/Stylesheet.swift @@ -0,0 +1,12 @@ +// +// Stylesheet.swift +// samhuri.net +// +// Created by Sami Samhuri on 2020-01-02. +// + +import Foundation + +struct Stylesheet: HTMLRef, Equatable { + let ref: String +} diff --git a/samhuri.net/Sources/samhuri.net/Posts/PostMetadata.swift b/samhuri.net/Sources/samhuri.net/Posts/PostMetadata.swift index 2b96602..830a300 100644 --- a/samhuri.net/Sources/samhuri.net/Posts/PostMetadata.swift +++ b/samhuri.net/Sources/samhuri.net/Posts/PostMetadata.swift @@ -14,8 +14,8 @@ struct PostMetadata { let formattedDate: String let link: URL? let tags: [String] - let scripts: [String] - let styles: [String] + let scripts: [Script] + let styles: [Stylesheet] } extension PostMetadata { @@ -41,8 +41,8 @@ extension PostMetadata { formattedDate: dictionary["Date"]!, link: dictionary["Link"].flatMap { URL(string: $0) }, tags: dictionary.commaSeparatedList(key: "Tags"), - scripts: dictionary.commaSeparatedList(key: "Scripts"), - styles: dictionary.commaSeparatedList(key: "Styles") + scripts: dictionary.commaSeparatedList(key: "Scripts").map(Script.init(ref:)), + styles: dictionary.commaSeparatedList(key: "Styles").map(Stylesheet.init(ref:)) ) } } diff --git a/samhuri.net/Sources/samhuri.net/Site/Site+Builder.swift b/samhuri.net/Sources/samhuri.net/Site/Site+Builder.swift index 1625df4..97e1fca 100644 --- a/samhuri.net/Sources/samhuri.net/Site/Site+Builder.swift +++ b/samhuri.net/Sources/samhuri.net/Site/Site+Builder.swift @@ -15,8 +15,8 @@ extension Site { private let email: String private let url: URL - private var styles: [String] = [] - private var scripts: [String] = [] + private var scripts: [Script] = [] + private var styles: [Stylesheet] = [] private var plugins: [Plugin] = [] private var renderers: [Renderer] = [] @@ -35,13 +35,13 @@ extension Site { self.url = url } - func styles(_ styles: String...) -> Self { - self.styles.append(contentsOf: styles) + func scripts(_ scripts: String...) -> Self { + self.scripts.append(contentsOf: scripts.map(Script.init(ref:))) return self } - func scripts(_ scripts: String...) -> Self { - self.scripts.append(contentsOf: scripts) + func styles(_ styles: String...) -> Self { + self.styles.append(contentsOf: styles.map(Stylesheet.init(ref:))) return self } @@ -62,8 +62,8 @@ extension Site { title: title, description: description, url: url, - styles: styles, scripts: scripts, + styles: styles, renderers: renderers, plugins: plugins ) diff --git a/samhuri.net/Sources/samhuri.net/Site/Site.swift b/samhuri.net/Sources/samhuri.net/Site/Site.swift index 5fc5880..41722ab 100644 --- a/samhuri.net/Sources/samhuri.net/Site/Site.swift +++ b/samhuri.net/Sources/samhuri.net/Site/Site.swift @@ -13,8 +13,8 @@ struct Site { let title: String let description: String let url: URL - let styles: [String] - let scripts: [String] + let scripts: [Script] + let styles: [Stylesheet] let renderers: [Renderer] let plugins: [Plugin] } diff --git a/samhuri.net/Sources/samhuri.net/Site/Templates/PageRenderer.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/PageRenderer.swift index 178e4e8..ebe0345 100644 --- a/samhuri.net/Sources/samhuri.net/Site/Templates/PageRenderer.swift +++ b/samhuri.net/Sources/samhuri.net/Site/Templates/PageRenderer.swift @@ -17,8 +17,8 @@ final class PageRenderer { extension PageRenderer: PageRendering { func renderPage(site: Site, bodyHTML: String, metadata: [String: String]) throws -> String { let pageTitle = metadata["Title"] - let scripts = metadata.commaSeparatedList(key: "Scripts") - let styles = metadata.commaSeparatedList(key: "Styles") + let scripts = metadata.commaSeparatedList(key: "Scripts").map(Script.init(ref:)) + let styles = metadata.commaSeparatedList(key: "Styles").map(Stylesheet.init(ref:)) let assets = TemplateAssets(scripts: scripts, styles: styles) let context = SiteContext(site: site, subtitle: pageTitle, templateAssets: assets) return render(.page(title: pageTitle ?? "", bodyHTML: bodyHTML), context: context) diff --git a/samhuri.net/Sources/samhuri.net/Site/Templates/TemplateAssets.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/TemplateAssets.swift index 8cdf966..1c770ad 100644 --- a/samhuri.net/Sources/samhuri.net/Site/Templates/TemplateAssets.swift +++ b/samhuri.net/Sources/samhuri.net/Site/Templates/TemplateAssets.swift @@ -8,8 +8,8 @@ import Foundation struct TemplateAssets { - var scripts: [String] - var styles: [String] + var scripts: [Script] + var styles: [Stylesheet] static func empty() -> TemplateAssets { TemplateAssets(scripts: [], styles: []) diff --git a/samhuri.net/Sources/samhuri.net/Site/Templates/TemplateContext.swift b/samhuri.net/Sources/samhuri.net/Site/Templates/TemplateContext.swift index 00c1eff..1e9fda3 100644 --- a/samhuri.net/Sources/samhuri.net/Site/Templates/TemplateContext.swift +++ b/samhuri.net/Sources/samhuri.net/Site/Templates/TemplateContext.swift @@ -28,17 +28,17 @@ protocol TemplateContext { } extension TemplateContext { - var styles: [URL] { - let allStyles = site.styles + templateAssets.styles - return allStyles.map { style in - style.hasPrefix("http") ? URL(string: style)! : styleURL(style) - } - } - var scripts: [URL] { let allScripts = site.scripts + templateAssets.scripts return allScripts.map { script in - script.hasPrefix("http") ? URL(string: script)! : scriptURL(script) + script.url(dir: scriptDir) + } + } + + var styles: [URL] { + let allStyles = site.styles + templateAssets.styles + return allStyles.map { style in + style.url(dir: styleDir) } } @@ -57,14 +57,20 @@ extension TemplateContext { } func scriptURL(_ filename: String) -> URL { - site.url - .appendingPathComponent("js") - .appendingPathComponent(filename) + scriptDir.appendingPathComponent(filename) } func styleURL(_ filename: String) -> URL { - site.url - .appendingPathComponent("css") - .appendingPathComponent(filename) + styleDir.appendingPathComponent(filename) + } +} + +private extension TemplateContext { + var scriptDir: URL { + site.url.appendingPathComponent("js") + } + + var styleDir: URL { + site.url.appendingPathComponent("css") } }