ChWebsiteApp/CHDataManagement/Generator/PostListPageGenerator.swift
2024-12-25 18:06:05 +01:00

115 lines
3.7 KiB
Swift

import Foundation
final class PostListPageGenerator {
private let language: ContentLanguage
private let content: Content
private let results: PageGenerationResults
private let showTitle: Bool
private let pageTitle: String
private let pageDescription: String
/// The url of the page, excluding the extension
private let pageUrlPrefix: String
init(language: ContentLanguage,
content: Content,
results: PageGenerationResults,
showTitle: Bool, pageTitle: String,
pageDescription: String,
pageUrlPrefix: String) {
self.language = language
self.content = content
self.results = results
self.showTitle = showTitle
self.pageTitle = pageTitle
self.pageDescription = pageDescription
self.pageUrlPrefix = pageUrlPrefix
}
private var mainContentMaximumWidth: Int {
content.settings.posts.contentWidth
}
private var postsPerPage: Int {
content.settings.posts.postsPerPage
}
func createPages(for posts: [Post]) {
let totalCount = posts.count
guard totalCount > 0 else {
return
}
let numberOfPages = (totalCount + postsPerPage - 1) / postsPerPage // Round up
for pageIndex in 1...numberOfPages {
let startIndex = (pageIndex - 1) * postsPerPage
let endIndex = min(pageIndex * postsPerPage, totalCount)
let postsOnPage = posts[startIndex..<endIndex]
createPostFeedPage(pageIndex, pageCount: numberOfPages, posts: postsOnPage)
}
}
private func createPostFeedPage(_ pageIndex: Int, pageCount: Int, posts: ArraySlice<Post>) {
let posts: [FeedEntryData] = posts.map { post in
let localized: LocalizedPost = post.localized(in: language)
let linkUrl = post.linkedPage.map {
FeedEntryData.Link(
url: $0.absoluteUrl(in: language),
text: language == .english ? "View" : "Anzeigen") // TODO: Add to settings
}
let tags: [FeedEntryData.Tag] = post.tags.filter { $0.isVisible }.map { tag in
.init(name: tag.localized(in: language).name,
url: content.absoluteUrlToTag(tag, language: language))
}
let images = localized.images.map(createFeedImage)
return FeedEntryData(
entryId: post.id,
title: localized.title,
textAboveTitle: post.dateText(in: language),
link: linkUrl,
tags: tags,
text: localized.text.components(separatedBy: "\n"),
images: images)
}
let feedPageGenerator = FeedPageGenerator(content: content)
let fileContent = feedPageGenerator.generatePage(
language: language,
posts: posts,
title: pageTitle,
description: pageDescription,
showTitle: showTitle,
pageNumber: pageIndex,
totalPages: pageCount)
let filePath = "\(pageUrlPrefix)/\(pageIndex).html"
guard save(fileContent, to: filePath) else {
results.unsavedOutput(filePath, source: .feed)
return
}
}
private func createFeedImage(for image: FileResource) -> FeedEntryData.Image {
results.requireImageSet(for: image, size: mainContentMaximumWidth)
return .init(
rawImagePath: image.absoluteUrl,
width: mainContentMaximumWidth,
height: mainContentMaximumWidth,
altText: image.localized(in: language))
}
private func save(_ content: String, to relativePath: String) -> Bool {
self.content.storage.write(content, to: relativePath)
}
}