Copy required files for pages
This commit is contained in:
parent
14b935249f
commit
02a3dd4007
@ -23,7 +23,7 @@
|
||||
E22E878C289E4A8900E51191 /* Ink in Frameworks */ = {isa = PBXBuildFile; productRef = E22E878B289E4A8900E51191 /* Ink */; };
|
||||
E22E8793289E7EC700E51191 /* Page+LocalizedMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = E22E8792289E7EC700E51191 /* Page+LocalizedMetadata.swift */; };
|
||||
E22E8795289E81D700E51191 /* FileSystem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E22E8794289E81D700E51191 /* FileSystem.swift */; };
|
||||
E22E8798289EA42C00E51191 /* ImageProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E22E8797289EA42C00E51191 /* ImageProcessor.swift */; };
|
||||
E22E8798289EA42C00E51191 /* FileProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E22E8797289EA42C00E51191 /* FileProcessor.swift */; };
|
||||
E22E879B289EE02F00E51191 /* Optional+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E22E879A289EE02F00E51191 /* Optional+Extensions.swift */; };
|
||||
E22E879E289EFDFC00E51191 /* OverviewPageGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E22E879D289EFDFC00E51191 /* OverviewPageGenerator.swift */; };
|
||||
E22E87A0289F008200E51191 /* ThumbnailListGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E22E879F289F008200E51191 /* ThumbnailListGenerator.swift */; };
|
||||
@ -82,7 +82,7 @@
|
||||
E22E8788289DDF5700E51191 /* Page+Metadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Page+Metadata.swift"; sourceTree = "<group>"; };
|
||||
E22E8792289E7EC700E51191 /* Page+LocalizedMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Page+LocalizedMetadata.swift"; sourceTree = "<group>"; };
|
||||
E22E8794289E81D700E51191 /* FileSystem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileSystem.swift; sourceTree = "<group>"; };
|
||||
E22E8797289EA42C00E51191 /* ImageProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageProcessor.swift; sourceTree = "<group>"; };
|
||||
E22E8797289EA42C00E51191 /* FileProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileProcessor.swift; sourceTree = "<group>"; };
|
||||
E22E879A289EE02F00E51191 /* Optional+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Extensions.swift"; sourceTree = "<group>"; };
|
||||
E22E879D289EFDFC00E51191 /* OverviewPageGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverviewPageGenerator.swift; sourceTree = "<group>"; };
|
||||
E22E879F289F008200E51191 /* ThumbnailListGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThumbnailListGenerator.swift; sourceTree = "<group>"; };
|
||||
@ -149,7 +149,7 @@
|
||||
E2C5A5D328A0222B00102A25 /* Templates */,
|
||||
E22E8799289EE02300E51191 /* Extensions */,
|
||||
E22E876B289D855D00E51191 /* ThumbnailStyle.swift */,
|
||||
E22E8797289EA42C00E51191 /* ImageProcessor.swift */,
|
||||
E22E8797289EA42C00E51191 /* FileProcessor.swift */,
|
||||
E22E8777289DA0E100E51191 /* GenerationError.swift */,
|
||||
E22E8794289E81D700E51191 /* FileSystem.swift */,
|
||||
);
|
||||
@ -315,7 +315,7 @@
|
||||
E22E876E289D868100E51191 /* Site+LocalizedMetadata.swift in Sources */,
|
||||
E2C5A5D528A0223C00102A25 /* OverviewPageTemplate.swift in Sources */,
|
||||
E22E876C289D855D00E51191 /* ThumbnailStyle.swift in Sources */,
|
||||
E22E8798289EA42C00E51191 /* ImageProcessor.swift in Sources */,
|
||||
E22E8798289EA42C00E51191 /* FileProcessor.swift in Sources */,
|
||||
E26555E428A2C4FA00BAF496 /* LinkPreviewMetadataProvider.swift in Sources */,
|
||||
E22E87AA289F1AEE00E51191 /* PageHeadGenerator.swift in Sources */,
|
||||
E2D55EDB28A2511D00B9453E /* OverviewSectionCleanTemplate.swift in Sources */,
|
||||
|
@ -3,7 +3,7 @@ import Foundation
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
final class ImageProcessor {
|
||||
final class FileProcessor {
|
||||
|
||||
struct ImageOutput: Hashable {
|
||||
|
||||
@ -32,12 +32,44 @@ final class ImageProcessor {
|
||||
|
||||
let outputFolder: URL
|
||||
|
||||
/**
|
||||
The files required by the site.
|
||||
|
||||
The content are the links to the files relative to the source root folder.
|
||||
The files will be placed at the same path relative to the output folder
|
||||
*/
|
||||
private var requiredFiles: Set<String> = []
|
||||
|
||||
private var tasks: [String : ImageOutput] = [:]
|
||||
|
||||
init(inputFolder: URL, outputFolder: URL) {
|
||||
self.inputFolder = inputFolder
|
||||
self.outputFolder = outputFolder
|
||||
}
|
||||
|
||||
private var tasks: [String : ImageOutput] = [:]
|
||||
// MARK: Files
|
||||
|
||||
/**
|
||||
Add a file as required, so that it will be copied to the output directory.
|
||||
*/
|
||||
func require(file: String) {
|
||||
requiredFiles.insert(file)
|
||||
}
|
||||
|
||||
func copyRequiredFiles() throws {
|
||||
var missingFiles = [String]()
|
||||
for file in requiredFiles {
|
||||
let sourceUrl = inputFolder.appendingPathComponent(file)
|
||||
guard sourceUrl.exists else {
|
||||
missingFiles.append(file)
|
||||
continue
|
||||
}
|
||||
let destinationUrl = outputFolder.appendingPathComponent(file)
|
||||
try FileSystem.copy(sourceUrl, to: destinationUrl)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Images
|
||||
|
||||
@discardableResult
|
||||
func requireImage(source: String, destination: String, width: Int, desiredHeight: Int? = nil, createDoubleVersion: Bool = false) throws -> NSSize {
|
@ -9,6 +9,9 @@ enum FileSystem {
|
||||
.filter { $0.isDirectory }
|
||||
}
|
||||
|
||||
/**
|
||||
Copy a file to the destination, creating the containing folder if needed
|
||||
*/
|
||||
static func copy(_ source: URL, to destination: URL) throws {
|
||||
try destination.ensureParentFolderExistence()
|
||||
try source.copy(to: destination)
|
||||
|
@ -20,7 +20,7 @@ struct IndexPageGenerator {
|
||||
|
||||
private let factory: LocalizedSiteTemplate
|
||||
|
||||
init(factory: LocalizedSiteTemplate, imageProcessor: ImageProcessor) {
|
||||
init(factory: LocalizedSiteTemplate) {
|
||||
self.factory = factory
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,10 @@ import Ink
|
||||
|
||||
struct PageContentGenerator {
|
||||
|
||||
private let imageProcessor: ImageProcessor
|
||||
private let files: FileProcessor
|
||||
|
||||
init(imageProcessor: ImageProcessor) {
|
||||
self.imageProcessor = imageProcessor
|
||||
init(files: FileProcessor) {
|
||||
self.files = files
|
||||
}
|
||||
|
||||
func generate(page: Page, language: String, at url: URL) throws -> String {
|
||||
@ -71,7 +71,7 @@ struct PageContentGenerator {
|
||||
let size: NSSize
|
||||
let imagePath = page.pathRelativeToRootForContainedInputFile(file)
|
||||
do {
|
||||
size = try imageProcessor.requireImage(
|
||||
size = try files.requireImage(
|
||||
source: imagePath,
|
||||
destination: imagePath,
|
||||
width: pageImageWidth,
|
||||
|
@ -6,9 +6,9 @@ struct OverviewPageGenerator {
|
||||
|
||||
let outputFolder: URL
|
||||
|
||||
init(factory: LocalizedSiteTemplate, imageProcessor: ImageProcessor) {
|
||||
init(factory: LocalizedSiteTemplate, files: FileProcessor) {
|
||||
self.factory = factory
|
||||
self.outputFolder = imageProcessor.outputFolder
|
||||
self.outputFolder = files.outputFolder
|
||||
}
|
||||
|
||||
func generate(
|
||||
|
@ -6,15 +6,15 @@ struct OverviewSectionGenerator {
|
||||
|
||||
private let singleSectionsTemplate: OverviewSectionCleanTemplate
|
||||
|
||||
let imageProcessor: ImageProcessor
|
||||
let files: FileProcessor
|
||||
|
||||
private let generator: ThumbnailListGenerator
|
||||
|
||||
init(factory: TemplateFactory, imageProcessor: ImageProcessor) {
|
||||
init(factory: TemplateFactory, files: FileProcessor) {
|
||||
self.multipleSectionsTemplate = factory.overviewSection
|
||||
self.singleSectionsTemplate = factory.overviewSectionClean
|
||||
self.imageProcessor = imageProcessor
|
||||
self.generator = ThumbnailListGenerator(factory: factory, imageProcessor: imageProcessor)
|
||||
self.files = files
|
||||
self.generator = ThumbnailListGenerator(factory: factory, files: files)
|
||||
}
|
||||
|
||||
func generate(sections: [Section], in parent: SiteElement, language: String, sectionItemCount: Int) throws -> String {
|
||||
|
@ -12,11 +12,11 @@ struct PageGenerator {
|
||||
|
||||
private let factory: LocalizedSiteTemplate
|
||||
|
||||
private let imageProcessor: ImageProcessor
|
||||
private let files: FileProcessor
|
||||
|
||||
init(factory: LocalizedSiteTemplate, imageProcessor: ImageProcessor) {
|
||||
init(factory: LocalizedSiteTemplate, files: FileProcessor) {
|
||||
self.factory = factory
|
||||
self.imageProcessor = imageProcessor
|
||||
self.files = files
|
||||
}
|
||||
|
||||
func generate(page: Page, language: String, backText: String, nextPage: NavigationLink?, previousPage: NavigationLink?) throws {
|
||||
@ -45,8 +45,8 @@ struct PageGenerator {
|
||||
content[.nextPageUrl] = nextPage?.link
|
||||
content[.footer] = try page.customFooterContent()
|
||||
|
||||
let url = imageProcessor.outputFolder.appendingPathComponent(path)
|
||||
try factory.contentPage.generate(content, to: url)
|
||||
let url = files.outputFolder.appendingPathComponent(path)
|
||||
}
|
||||
|
||||
private func makeContent(page: Page, language: String, url: URL) throws -> String {
|
||||
@ -55,7 +55,7 @@ struct PageGenerator {
|
||||
return factory.placeholder
|
||||
}
|
||||
print("Generated page \(page.path)")
|
||||
return try PageContentGenerator(imageProcessor: imageProcessor).generate(page: page, language: language, at: url)
|
||||
return try PageContentGenerator(files: files).generate(page: page, language: language, at: url)
|
||||
}
|
||||
|
||||
private func makeHead(page: Page, language: String) throws -> String {
|
||||
|
@ -30,11 +30,11 @@ struct PageHeadGenerator {
|
||||
|
||||
let template: PageHeadTemplate
|
||||
|
||||
let imageProcessor: ImageProcessor
|
||||
let files: FileProcessor
|
||||
|
||||
init(factory: TemplateFactory, imageProcessor: ImageProcessor) {
|
||||
init(factory: TemplateFactory, files: FileProcessor) {
|
||||
self.template = factory.pageHead
|
||||
self.imageProcessor = imageProcessor
|
||||
self.files = files
|
||||
}
|
||||
|
||||
func generate(page: PageHeadInfoProvider) throws -> String {
|
||||
@ -47,7 +47,7 @@ struct PageHeadGenerator {
|
||||
// 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 imageProcessor.requireImage(
|
||||
try files.requireImage(
|
||||
source: image,
|
||||
destination: linkPreviewImagePath,
|
||||
width: Site.linkPreviewDesiredImageWidth)
|
||||
|
@ -6,17 +6,17 @@ struct SiteGenerator {
|
||||
|
||||
let templates: TemplateFactory
|
||||
|
||||
private let imageProcessor: ImageProcessor
|
||||
private let files: FileProcessor
|
||||
|
||||
private var outputFolder: URL {
|
||||
imageProcessor.outputFolder
|
||||
files.outputFolder
|
||||
}
|
||||
|
||||
init(site: Site, imageProcessor: ImageProcessor) throws {
|
||||
init(site: Site, files: FileProcessor) throws {
|
||||
self.site = site
|
||||
let templatesFolder = site.inputFolder.appendingPathComponent("templates")
|
||||
self.templates = try TemplateFactory(templateFolder: templatesFolder)
|
||||
self.imageProcessor = imageProcessor
|
||||
self.files = files
|
||||
}
|
||||
|
||||
func generate() throws {
|
||||
@ -26,12 +26,12 @@ struct SiteGenerator {
|
||||
factory: templates,
|
||||
language: language,
|
||||
site: site,
|
||||
imageProcessor: imageProcessor)
|
||||
files: files)
|
||||
|
||||
|
||||
// Generate sections
|
||||
let overviewGenerator = OverviewPageGenerator(factory: template, imageProcessor: imageProcessor)
|
||||
let pageGenerator = PageGenerator(factory: template, imageProcessor: imageProcessor)
|
||||
let overviewGenerator = OverviewPageGenerator(factory: template, files: files)
|
||||
let pageGenerator = PageGenerator(factory: template, files: files)
|
||||
let backLinkText = try site.backLinkText(for: language)
|
||||
var elementsToProcess: [(element: SiteElement, backText: String?)] = site.elements.map { ($0, backLinkText) }
|
||||
while let (element, backText) = elementsToProcess.popLast() {
|
||||
@ -52,12 +52,14 @@ struct SiteGenerator {
|
||||
backText: backText ?? metadata.defaultBackLinkText,
|
||||
nextPage: nil,
|
||||
previousPage: nil)
|
||||
for file in page.metadata.requiredFiles {
|
||||
let relativePath = page.path + "/" + file
|
||||
files.require(file: relativePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let generator = IndexPageGenerator(
|
||||
factory: template,
|
||||
imageProcessor: imageProcessor)
|
||||
let generator = IndexPageGenerator(factory: template)
|
||||
|
||||
// Generate front page
|
||||
let relativeUrl = site.localizedPath(for: language)
|
||||
|
@ -4,11 +4,11 @@ struct ThumbnailListGenerator {
|
||||
|
||||
private let factory: TemplateFactory
|
||||
|
||||
let imageProcessor: ImageProcessor
|
||||
let files: FileProcessor
|
||||
|
||||
init(factory: TemplateFactory, imageProcessor: ImageProcessor) {
|
||||
init(factory: TemplateFactory, files: FileProcessor) {
|
||||
self.factory = factory
|
||||
self.imageProcessor = imageProcessor
|
||||
self.files = files
|
||||
}
|
||||
|
||||
func generateContent(items: [ThumbnailInfo], style: ThumbnailStyle) throws -> String {
|
||||
@ -26,7 +26,7 @@ struct ThumbnailListGenerator {
|
||||
factory.largeThumbnail.makeCorner(text: $0)
|
||||
}
|
||||
|
||||
try imageProcessor.requireImage(
|
||||
try files.requireImage(
|
||||
source: thumbnail.imageFilePath,
|
||||
destination: thumbnail.imageFilePath,
|
||||
width: style.width,
|
||||
|
@ -54,7 +54,7 @@ struct LocalizedSiteTemplate {
|
||||
factory.contentPage
|
||||
}
|
||||
|
||||
init(factory: TemplateFactory, language: String, site: Site, imageProcessor: ImageProcessor) throws {
|
||||
init(factory: TemplateFactory, language: String, site: Site, files: FileProcessor) throws {
|
||||
self.author = site.metadata.author
|
||||
self.factory = factory
|
||||
|
||||
@ -92,10 +92,10 @@ struct LocalizedSiteTemplate {
|
||||
topBarWebsiteTitle: title)
|
||||
self.pageHead = PageHeadGenerator(
|
||||
factory: factory,
|
||||
imageProcessor: imageProcessor)
|
||||
files: files)
|
||||
self.overviewSection = OverviewSectionGenerator(
|
||||
factory: factory,
|
||||
imageProcessor: imageProcessor)
|
||||
files: files)
|
||||
|
||||
self.placeholder = factory.placeholder.generate([
|
||||
.title: metadata.placeholderTitle,
|
||||
|
@ -2,7 +2,7 @@ import Foundation
|
||||
|
||||
let contentDirectory = URL(fileURLWithPath: "/Users/ch/Projects/MakerSpace")
|
||||
let outputDirectory = URL(fileURLWithPath: "/Users/ch/Projects/MakerSpace/Site")
|
||||
let imageProcessor = ImageProcessor(
|
||||
let files = FileProcessor(
|
||||
inputFolder: contentDirectory, outputFolder: outputDirectory)
|
||||
|
||||
// 1: Load all site content
|
||||
@ -10,11 +10,13 @@ guard let site = try Site(folder: contentDirectory) else {
|
||||
exit(0)
|
||||
}
|
||||
// site.printContents()
|
||||
let siteGenerator = try SiteGenerator(site: site, imageProcessor: imageProcessor)
|
||||
let siteGenerator = try SiteGenerator(site: site, files: files)
|
||||
try siteGenerator.generate()
|
||||
|
||||
print("Pages generated")
|
||||
try imageProcessor.createImages()
|
||||
try files.createImages()
|
||||
print("Images generated")
|
||||
try files.copyRequiredFiles()
|
||||
print("Required files copied")
|
||||
|
||||
#warning("Check that all metadata for each language is present")
|
||||
|
Loading…
Reference in New Issue
Block a user