Rework storage structs, link preview

This commit is contained in:
Christoph Hagen
2025-01-08 14:59:04 +01:00
parent b99c064d10
commit a7197b9628
75 changed files with 1365 additions and 1454 deletions

View File

@ -38,9 +38,14 @@ struct PageLinkCommand: CommandProcessor {
let localized = page.localized(in: language)
let url = page.absoluteUrl(in: language)
let title = localized.linkPreviewTitle ?? localized.title
let description = localized.linkPreviewDescription ?? ""
let image = makePageImage(item: localized)
let title = localized.linkPreview.title ?? localized.title
let description = localized.linkPreview.description ?? ""
let image = localized.linkPreview.image.map {
let size = content.settings.pages.pageLinkImageSize
let imageSet = $0.imageSet(width: size, height: size, language: language)
results.require(imageSet: imageSet)
return imageSet
}
return RelatedPageLink(
title: title,
@ -49,13 +54,4 @@ struct PageLinkCommand: CommandProcessor {
image: image)
.content
}
private func makePageImage(item: LinkPreviewItem) -> ImageSet? {
item.linkPreviewImage.map { image in
let size = content.settings.pages.pageLinkImageSize
let imageSet = image.imageSet(width: size, height: size, language: language)
results.require(imageSet: imageSet)
return imageSet
}
}
}

View File

@ -33,8 +33,13 @@ struct TagLinkCommand: CommandProcessor {
let localized = tag.localized(in: language)
let url = tag.absoluteUrl(in: language)
let title = localized.name
let description = localized.linkPreviewDescription ?? ""
let image = makePageImage(item: localized)
let description = localized.linkPreview.description ?? ""
let image = localized.linkPreview.image.map {
let size = content.settings.pages.pageLinkImageSize
let imageSet = $0.imageSet(width: size, height: size, language: language)
results.require(imageSet: imageSet)
return imageSet
}
return RelatedPageLink(
title: title,
@ -43,13 +48,4 @@ struct TagLinkCommand: CommandProcessor {
image: image)
.content
}
private func makePageImage(item: LinkPreviewItem) -> ImageSet? {
item.linkPreviewImage.map { image in
let size = content.settings.pages.pageLinkImageSize
let imageSet = image.imageSet(width: size, height: size, language: language)
results.require(imageSet: imageSet)
return imageSet
}
}
}

View File

@ -10,11 +10,11 @@ struct ImageSet: HtmlProducer {
let quality: CGFloat
let description: String
let description: String?
let extraAttributes: String
init(image: FileResource, maxWidth: Int, maxHeight: Int, description: String, quality: CGFloat = 0.7, extraAttributes: String? = nil) {
init(image: FileResource, maxWidth: Int, maxHeight: Int, description: String?, quality: CGFloat = 0.7, extraAttributes: String? = nil) {
self.image = image
self.maxWidth = maxWidth
self.maxHeight = maxHeight
@ -39,6 +39,13 @@ struct ImageSet: HtmlProducer {
]
}
private var imageAltText: String {
guard let description else {
return ""
}
return " alt='\(description.htmlEscaped())'"
}
func populate(_ result: inout String) {
let fileExtension = image.type.fileExtension.map { "." + $0 } ?? ""
@ -48,7 +55,7 @@ struct ImageSet: HtmlProducer {
result += "<picture>"
result += "<source type='image/avif' srcset='\(prefix1x).avif 1x, \(prefix2x).avif 2x'/>"
result += "<source type='image/webp' srcset='\(prefix1x).webp 1x, \(prefix1x).webp 2x'/>"
result += "<img srcset='\(prefix2x)\(fileExtension) 2x' src='\(prefix1x)\(fileExtension)' loading='lazy' alt='\(description.htmlEscaped())'\(extraAttributes)/>"
result += "<img srcset='\(prefix2x)\(fileExtension) 2x' src='\(prefix1x)\(fileExtension)' loading='lazy'\(imageAltText)\(extraAttributes)/>"
result += "</picture>"
}
}

View File

@ -58,8 +58,8 @@ final class PageGenerator {
let pageHeader = PageHeader(
language: language,
title: localized.linkPreviewTitle ?? localized.title,
description: localized.linkPreviewDescription,
title: localized.linkPreview.title ?? localized.title,
description: localized.linkPreview.description,
iconUrl: iconUrl,
languageButton: languageButton,
links: content.navigationBar(in: language),

View File

@ -10,7 +10,7 @@ private struct TagData {
init(tag: Tag, language: ContentLanguage) {
let localized = tag.localized(in: language)
self.url = tag.absoluteUrl(in: language)
self.title = localized.linkPreviewTitle ?? localized.name
self.title = localized.linkPreview.title ?? localized.name
self.localized = localized
}
}
@ -81,12 +81,12 @@ final class TagOverviewGenerator {
self.results = results
}
func generatePages(tags: [Tag], overview: TagOverviewPage) {
func generatePages(tags: [Tag], overview: Tag) {
let localized = overview.localized(in: language)
let header = TagHeaderContent(
language: language,
title: localized.linkPreviewTitle ?? localized.title,
description: localized.linkPreviewDescription,
title: localized.linkPreview.title ?? localized.title,
description: localized.linkPreview.description,
iconUrl: content.settings.navigation.localized(in: language).rootUrl,
links: content.navigationBar(in: language),
headers: content.postPageHeaders,
@ -123,8 +123,13 @@ final class TagOverviewGenerator {
additionalFooter: "") { content in
content += "<h1 class='separated-headline'>\(header.title)</h1>"
for tag in tags {
let description = tag.localized.linkPreviewDescription ?? ""
let image = self.makePageImage(item: tag.localized)
let description = tag.localized.linkPreview.description ?? ""
let image = tag.localized.linkPreview.image.map {
let size = self.content.settings.pages.pageLinkImageSize
let imageSet = $0.imageSet(width: size, height: size, language: self.language)
self.results.require(imageSet: imageSet)
return imageSet
}
content += RelatedPageLink(
title: tag.title,
@ -148,13 +153,4 @@ final class TagOverviewGenerator {
return
}
}
private func makePageImage(item: LinkPreviewItem) -> ImageSet? {
item.linkPreviewImage.map { image in
let size = content.settings.pages.pageLinkImageSize
let imageSet = image.imageSet(width: size, height: size, language: language)
results.require(imageSet: imageSet)
return imageSet
}
}
}

View File

@ -22,7 +22,7 @@ struct TagPageGeneratorSource: PostListPageGeneratorSource {
}
var pageDescription: String {
tag.localized(in: language).linkPreviewDescription ?? ""
tag.localized(in: language).linkPreview.description ?? ""
}
func pageUrlPrefix(for language: ContentLanguage) -> String {

View File

@ -56,7 +56,7 @@ final class GenerationResults: ObservableObject {
var redirects: [String : String] = [:]
/// The cache of previously used GenerationResults
private var cache: [ItemId : PageGenerationResults] = [:]
private var cache: [LocalizedItemId : PageGenerationResults] = [:]
private(set) var general: PageGenerationResults!
@ -66,14 +66,14 @@ final class GenerationResults: ObservableObject {
// MARK: Life cycle
init() {
let id = ItemId(language: .english, itemType: .general)
let id = LocalizedItemId(language: .english, itemType: .general)
let general = PageGenerationResults(itemId: id, delegate: self)
self.general = general
cache[id] = general
self.resultCount = 1
}
func makeResults(_ itemId: ItemId) -> PageGenerationResults {
func makeResults(_ itemId: LocalizedItemId) -> PageGenerationResults {
guard let result = cache[itemId] else {
let result = PageGenerationResults(itemId: itemId, delegate: self)
cache[itemId] = result
@ -83,18 +83,18 @@ final class GenerationResults: ObservableObject {
return result
}
func makeResults(for type: ItemType, in language: ContentLanguage) -> PageGenerationResults {
let itemId = ItemId(language: language, itemType: type)
func makeResults(for type: ItemReference, in language: ContentLanguage) -> PageGenerationResults {
let itemId = LocalizedItemId(language: language, itemType: type)
return makeResults(itemId)
}
func makeResults(for page: Page, in language: ContentLanguage) -> PageGenerationResults {
let itemId = ItemId(language: language, itemType: .page(page))
let itemId = LocalizedItemId(language: language, itemType: .page(page))
return makeResults(itemId)
}
func makeResults(for tag: Tag, in language: ContentLanguage) -> PageGenerationResults {
let itemId = ItemId(language: language, itemType: .tagPage(tag))
let itemId = LocalizedItemId(language: language, itemType: .tagPage(tag))
return makeResults(itemId)
}
@ -209,9 +209,9 @@ final class GenerationResults: ObservableObject {
}
}
private extension Dictionary where Value == Set<ItemId> {
private extension Dictionary where Value == Set<LocalizedItemId> {
mutating func remove<S>(keys: S, of item: ItemId) where S: Sequence, S.Element == Key {
mutating func remove<S>(keys: S, of item: LocalizedItemId) where S: Sequence, S.Element == Key {
for key in keys {
guard var value = self[key] else { continue }
value.remove(item)

View File

@ -17,7 +17,7 @@ extension ImageToGenerate: Hashable {
final class PageGenerationResults: ObservableObject {
let itemId: ItemId
let itemId: LocalizedItemId
private unowned let delegate: GenerationResults
@ -73,13 +73,13 @@ final class PageGenerationResults: ObservableObject {
private(set) var warnings: Set<String>
/// The files that could not be saved to the output folder
private(set) var unsavedOutputFiles: [String: Set<ItemType>] = [:]
private(set) var unsavedOutputFiles: [String: Set<ItemReference>] = [:]
private(set) var pageIsEmpty: Bool
private(set) var redirect: (originalUrl: String, newUrl: String)?
init(itemId: ItemId, delegate: GenerationResults) {
init(itemId: LocalizedItemId, delegate: GenerationResults) {
self.itemId = itemId
self.delegate = delegate
inaccessibleFiles = []
@ -245,7 +245,7 @@ final class PageGenerationResults: ObservableObject {
delegate.warning(warning)
}
func unsavedOutput(_ path: String, source: ItemType) {
func unsavedOutput(_ path: String, source: ItemReference) {
unsavedOutputFiles[path, default: []].insert(source)
delegate.unsaved(path)
}