import Foundation import Ink struct PageGenerator { private let factory: LocalizedSiteTemplate private let contentGenerator: PageContentGenerator private let results: GenerationResultsHandler init(factory: LocalizedSiteTemplate, siteRoot: Element, results: GenerationResultsHandler) { self.factory = factory self.results = results self.contentGenerator = PageContentGenerator(factory: factory.factory, siteRoot: siteRoot, results: results) } func generate(page: Element, language: String, previousPage: Element?, nextPage: Element?) { guard !page.isExternalPage else { results.didCompletePage() return } let path = page.fullPageUrl(for: language) let inputContentPath = page.path + "/\(language).md" let metadata = page.localized(for: language) let nextLanguage = page.nextLanguage(for: language) let (pageContent, pageIncludesCode) = makeContent( page: page, metadata: metadata, language: language, path: inputContentPath) var content = [PageTemplate.Key : String]() content[.head] = factory.pageHead.generate(page: page, language: language, includesCode: pageIncludesCode) let sectionUrl = page.sectionUrl(for: language) content[.topBar] = factory.topBar.generate(sectionUrl: sectionUrl, languageButton: nextLanguage, page: page) content[.contentClass] = "content" content[.header] = makeHeader(page: page, metadata: metadata, language: language) content[.content] = pageContent content[.previousPageLinkText] = previousText(for: previousPage, language: language) content[.previousPageUrl] = navLink(from: page, to: previousPage, language: language) content[.nextPageLinkText] = nextText(for: nextPage, language: language) content[.nextPageUrl] = navLink(from: page, to: nextPage, language: language) content[.footer] = results.getContentOfOptionalFile(at: page.additionalFooterContentPath, source: page.path) if pageIncludesCode { let highlightCode = factory.factory.html.codeHighlightFooter() content[.footer] = (content[.footer].unwrapped { $0 + "\n" } ?? "") + highlightCode } if page.state == .draft { results.markPageAsDraft(page: page.path) } factory.page.generate(content, to: path, source: page.path) } private func navLink(from element: Element, to destination: Element?, language: String) -> String? { guard let fullPath = destination?.fullPageUrl(for: language) else { return nil } return element.relativePathToOtherSiteElement(file: fullPath) } private func previousText(for element: Element?, language: String) -> String? { guard let text = element?.localized(for: language).navigationTextAsPreviousPage else { return nil } return factory.factory.html.makePrevText(text) } private func nextText(for element: Element?, language: String) -> String? { guard let text = element?.localized(for: language).navigationTextAsNextPage else { return nil } return factory.factory.html.makeNextText(text) } private func makeContent(page: Element, metadata: Element.LocalizedMetadata, language: String, path: String) -> (content: String, includesCode: Bool) { if let raw = results.getContentOfMdFile(at: path, source: page.path)?.trimmed.nonEmpty { let (content, includesCode) = contentGenerator.generate(page: page, language: language, content: raw) return (content, includesCode) } else { let (content, includesCode) = contentGenerator.generate(page: page, language: language, content: metadata.placeholderText) let placeholder = factory.factory.makePlaceholder(title: metadata.placeholderTitle, text: content) return (placeholder, includesCode) } } private func makeHeader(page: Element, metadata: Element.LocalizedMetadata, language: String) -> String? { let content = factory.makeHeaderContent(page: page, metadata: metadata, language: language) switch page.headerType { case .none: return nil case .left: return factory.factory.leftHeader.generate(content) case .center: return factory.factory.centeredHeader.generate(content) } } }