import Foundation protocol PageHeadInfoProvider { var author: String { get } var linkPreviewTitle: String { get } var linkPreviewDescription: String { get } var linkPreviewImage: String? { get } var customHeadContent: String? { get } } struct PageHeadInfo: PageHeadInfoProvider { let author: String let linkPreviewTitle: String let linkPreviewDescription: String let linkPreviewImage: String? let customHeadContent: String? } struct PageHeadGenerator { let template: PageHeadTemplate let files: FileProcessor init(factory: TemplateFactory, files: FileProcessor) { self.template = factory.pageHead self.files = files } func generate(page: PageHeadInfoProvider) throws -> String { var content = [PageHeadTemplate.Key : String]() content[.author] = page.author content[.title] = page.linkPreviewTitle content[.description] = page.linkPreviewDescription if let image = page.linkPreviewImage { // Note: Generate separate destination link for the image, // since we don't want a single large image for thumbnails. // Warning: Link preview source path must be relative to root let linkPreviewImagePath = image.insert("-link", beforeLast: ".") try files.requireImage( source: image, destination: linkPreviewImagePath, width: Site.linkPreviewDesiredImageWidth) #warning("Make link preview image path absolute") content[.image] = "" } content[.customPageContent] = page.customHeadContent return template.generate(content) } }