import Foundation import Ink struct PageGenerator { private let factory: LocalizedSiteTemplate init(factory: LocalizedSiteTemplate) { self.factory = factory } func generate(page: Element, language: String, previousPage: Element?, nextPage: Element?) { guard !page.isExternalPage else { 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, pageIsEmpty) = 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] = page.customFooterContent() if pageIncludesCode { let highlightCode = factory.factory.html.codeHighlightFooter() content[.footer] = (content[.footer].unwrapped { $0 + "\n" } ?? "") + highlightCode } let url = files.urlInOutputFolder(path) if page.state == .draft { files.isDraft(path: page.path) } else if pageIsEmpty, page.state != .hidden { files.isEmpty(page: path) } guard factory.page.generate(content, to: url) else { return } files.generated(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, isEmpty: Bool) { let create = configuration.createMdFilesIfMissing if let raw = files.contentOfOptionalFile(atPath: path, source: page.path, createEmptyFileIfMissing: create)? .trimmed.nonEmpty { let (content, includesCode) = PageContentGenerator(factory: factory.factory) .generate(page: page, language: language, content: raw) return (content, includesCode, false) } else { let (content, includesCode) = PageContentGenerator(factory: factory.factory) .generate(page: page, language: language, content: metadata.placeholderText) let placeholder = factory.factory.makePlaceholder(title: metadata.placeholderTitle, text: content) return (placeholder, includesCode, true) } } 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) } } }