import Foundation typealias LinkedElement = (previous: Element?, element: Element, next: Element?) struct SiteGenerator { let templates: TemplateFactory init() throws { let templatesFolder = files.urlInContentFolder("templates") self.templates = try TemplateFactory(templateFolder: templatesFolder) } func generate(site: Element) { site.languages.forEach { generate(site: site, metadata: $0) } } private func generate(site: Element, metadata: Element.LocalizedMetadata) { let language = metadata.language let template = LocalizedSiteTemplate( factory: templates, language: language, site: site) // Generate sections let overviewGenerator = OverviewPageGenerator(factory: template) let pageGenerator = PageGenerator(factory: template) var elementsToProcess: [LinkedElement] = [(nil, site, nil)] while let (previous, element, next) = elementsToProcess.popLast() { // Move recursively down to all pages elementsToProcess.append(contentsOf: element.linkedElements) processAllFiles(for: element) if !element.elements.isEmpty { overviewGenerator.generate(section: element, language: language) } else { pageGenerator.generate( page: element, language: language, previousPage: previous, nextPage: next) } } } private func processAllFiles(for element: Element) { element.requiredFiles.forEach(files.require) element.externalFiles.forEach(files.exclude) element.images.forEach { files.requireSingleImage( source: $0.sourcePath, destination: $0.destinationPath, requiredBy: element.path, width: $0.desiredWidth, desiredHeight: $0.desiredHeight) } } }