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

236 lines
6.8 KiB
Swift

import Foundation
struct ImageToGenerate {
let size: Int
let image: FileResource
}
extension ImageToGenerate: Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(size)
hasher.combine(image.id)
}
}
final class PageGenerationResults: ObservableObject {
let itemId: ItemId
private unowned let delegate: GenerationResults
/// The files that could not be accessed
private(set) var inaccessibleFiles: Set<FileResource>
/// The files that could not be parsed, with the error message produced
private(set) var unparsableFiles: [FileResource : Set<String>]
/// The missing files directly used by this page, and the source of the file
private(set) var missingFiles: [String: Set<String>]
/// The missing files linked to from other files.
private(set) var missingLinkedFiles: [String : Set<FileResource>]
/// The missing tags linked to by this page, and the source of the link
private(set) var missingLinkedTags: [String : Set<String>]
/// The missing pages linked to by this page, and the source of the link
private(set) var missingLinkedPages: [String : Set<String>]
/// The footer scripts or html to add to the end of the body
private(set) var requiredFooters: Set<String>
/// The known header elements to include in the page
private(set) var requiredHeaders: Set<KnownHeaderElement>
/// The known icons that need to be included as hidden SVGs
private(set) var requiredIcons: Set<PageIcon>
/// The pages linked to by the page
private(set) var linkedPages: Set<Page>
/// The tags linked to by this page
private(set) var linkedTags: Set<Tag>
/// The links to external content in this page
private(set) var externalLinks: Set<String>
/// The files used by this page, but not necessarily required in the output folder
private(set) var usedFiles: Set<FileResource>
/// The files that need to be copied
private(set) var requiredFiles: Set<FileResource>
/// The image versions required for this page
private(set) var imagesToGenerate: Set<ImageGenerationJob>
private(set) var invalidCommands: [(command: ShorthandMarkdownKey?, markdown: String)] = []
private(set) var warnings: Set<String>
/// The files that could not be saved to the output folder
private(set) var unsavedOutputFiles: [String: Set<ItemType>] = [:]
init(itemId: ItemId, delegate: GenerationResults) {
self.itemId = itemId
self.delegate = delegate
inaccessibleFiles = []
unparsableFiles = [:]
missingFiles = [:]
missingLinkedFiles = [:]
missingLinkedTags = [:]
missingLinkedPages = [:]
requiredHeaders = []
requiredFooters = []
requiredIcons = []
linkedPages = []
linkedTags = []
externalLinks = []
usedFiles = []
requiredFiles = []
imagesToGenerate = []
invalidCommands = []
warnings = []
unsavedOutputFiles = [:]
}
private init(other: PageGenerationResults) {
self.itemId = other.itemId
self.delegate = other.delegate
inaccessibleFiles = other.inaccessibleFiles
unparsableFiles = other.unparsableFiles
missingFiles = other.missingFiles
missingLinkedFiles = other.missingLinkedFiles
missingLinkedTags = other.missingLinkedTags
missingLinkedPages = other.missingLinkedPages
requiredHeaders = other.requiredHeaders
requiredFooters = other.requiredFooters
requiredIcons = other.requiredIcons
linkedPages = other.linkedPages
linkedTags = other.linkedTags
externalLinks = other.externalLinks
usedFiles = other.usedFiles
requiredFiles = other.requiredFiles
imagesToGenerate = other.imagesToGenerate
invalidCommands = other.invalidCommands
warnings = other.warnings
unsavedOutputFiles = other.unsavedOutputFiles
}
func copy() -> PageGenerationResults {
.init(other: self)
}
// MARK: Adding entries
func inaccessibleContent(file: FileResource) {
inaccessibleFiles.insert(file)
delegate.inaccessibleContent(file: file)
}
func invalid(command: ShorthandMarkdownKey?, _ markdown: Substring) {
let markdown = String(markdown)
invalidCommands.append((command, markdown))
delegate.invalidCommand(markdown)
}
func missing(page: String, source: String) {
missingLinkedPages[page, default: []].insert(source)
delegate.missing(page: page)
}
func missing(tag: String, source: String) {
missingLinkedTags[tag, default: []].insert(source)
delegate.missing(tag: tag)
}
func missing(file: String, source: String) {
missingFiles[file, default: []].insert(source)
delegate.missing(file: file)
}
func requireImageSet(for image: FileResource, size: Int) {
let jobs = ImageGenerationJob.imageSet(for: image.id, maxWidth: size, maxHeight: size)
imagesToGenerate.formUnion(jobs)
used(file: image)
delegate.generate(jobs)
}
func invalidFormat(file: FileResource, error: String) {
unparsableFiles[file, default: []].insert(error)
delegate.unparsable(file: file)
}
func missing(file: String, containedIn sourceFile: FileResource) {
missingLinkedFiles[file, default: []].insert(sourceFile)
delegate.missing(file: file)
}
func used(file: FileResource) {
usedFiles.insert(file)
// TODO: Notify delegate
}
func require(file: FileResource) {
requiredFiles.insert(file)
usedFiles.insert(file)
delegate.require(file: file)
}
func require(files: [FileResource]) {
requiredFiles.formUnion(files)
usedFiles.formUnion(files)
delegate.require(files: files)
}
func require(footer: String) {
requiredFooters.insert(footer)
}
func require(header: KnownHeaderElement) {
requiredHeaders.insert(header)
}
func require(headers: KnownHeaderElement...) {
requiredHeaders.formUnion(headers)
}
func require(icon: PageIcon) {
requiredIcons.insert(icon)
}
func require(icons: PageIcon...) {
requiredIcons.formUnion(icons)
}
func require(icons: [PageIcon]) {
requiredIcons.formUnion(icons)
}
func linked(to page: Page) {
linkedPages.insert(page)
}
func linked(to tag: Tag) {
linkedTags.insert(tag)
}
func externalLink(to url: String) {
externalLinks.insert(url)
delegate.externalLink(url)
}
func warning(_ warning: String) {
warnings.insert(warning)
delegate.warning(warning)
}
func unsavedOutput(_ path: String, source: ItemType) {
unsavedOutputFiles[path, default: []].insert(source)
delegate.unsaved(path)
}
}