100 lines
3.6 KiB
Swift
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
|
|
}
|
|
}
|