Add specific types for scripts and stylesheets

This commit is contained in:
Sami Samhuri 2020-01-02 18:27:36 -08:00
parent 9dfd5080ef
commit 96b249a21c
10 changed files with 100 additions and 33 deletions

View file

@ -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:")
}
}

View file

@ -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

View file

@ -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
}

View file

@ -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
}

View file

@ -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:))
)
}
}

View file

@ -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
)

View file

@ -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]
}

View file

@ -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)

View file

@ -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: [])

View file

@ -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")
}
}