2025-02-16 14:53:00 +01:00

100 lines
3.6 KiB
Swift

import Foundation
final class PageGenerator {
private let content: Content
init(content: Content) {
self.content = content
}
private func makeHeaders(requiredItems: Set<KnownHeaderElement>, results: PageGenerationResults) -> Set<HeaderElement> {
var result = content.contentPageHeaders
for item in requiredItems {
guard let header = item.header(content: content) else {
results.warning("Header \(item) not configured in settings")
continue
}
result.insert(header)
}
return result
}
private func makeEmptyPageContent(in language: ContentLanguage) -> String {
let settings = content.settings.pages.localized(in: language)
return ContentBox(
title: settings.emptyPageTitle,
text: settings.emptyPageText).content
}
func generate(page: Page, language: ContentLanguage, results: PageGenerationResults, pageUrl: String) -> String? {
let contentGenerator = PageContentParser(
content: content,
language: language, results: results)
let rawPageContent: String
if let existing = content.storage.pageContent(for: page.id, language: language) {
rawPageContent = existing
} else {
rawPageContent = makeEmptyPageContent(in: language)
// Only mark non-draft pages as empty
if !page.isDraft {
results.markPageAsEmpty()
}
}
let pageContent = contentGenerator.generatePage(from: rawPageContent)
let localized = page.localized(in: language)
let tags: [FeedEntryData.Tag] = page.tags.map { tag in
.init(name: tag.localized(in: language).name,
url: tag.absoluteUrl(in: language))
}
let requiredHeaders = DispatchQueue.main.sync { results.requiredHeaders }
let headers = makeHeaders(requiredItems: requiredHeaders, results: results)
results.require(files: headers.compactMap { $0.requiredFile })
let iconUrl = content.settings.navigation.localized(in: language).rootUrl
let languageUrl = page.absoluteUrl(in: language.next)
let languageButton = NavigationBar.Link(
text: language.next.rawValue,
url: languageUrl)
let imageUrl = localized.linkPreview.image?.linkPreviewImage(results: results)
let icons = DispatchQueue.main.sync { results.requiredIcons }
let pageHeader = PageHeader(
language: language,
title: localized.linkPreview.title ?? localized.title,
description: localized.linkPreview.description,
image: imageUrl,
pageUrl: pageUrl,
iconUrl: iconUrl,
languageButton: languageButton,
links: content.navigationBar(in: language),
headers: headers,
icons: icons)
let footers = DispatchQueue.main.sync { results.requiredFooters }
let fullPage = GenericPage(
header: pageHeader,
additionalFooter: footers.sorted().joined()) { content in
content += "<article>"
if !localized.hideTitle {
if !page.hideDate {
content += "<h3>\(page.dateText(in: language))</h3>"
}
content += "<h1>\(localized.title)</h1>"
content += TagList(tags: tags).content
}
content += pageContent
content += "</article>"
}
return fullPage.content
}
}