import Foundation struct OverviewSectionGenerator { private let factory: TemplateFactory private let generator: ThumbnailListGenerator private let siteRoot: Element private let results: GenerationResultsHandler init(factory: TemplateFactory, siteRoot: Element, results: GenerationResultsHandler) { self.factory = factory self.siteRoot = siteRoot self.results = results self.generator = ThumbnailListGenerator(factory: factory, results: results) } func generate(sections: [Element], in parent: Element, language: String, sectionItemCount: Int) -> String { let content = sectionsContent(sections, in: parent, language: language, sectionItemCount: sectionItemCount) let firstSection = firstSectionContent(for: parent, language: language, sectionItemCount: sectionItemCount) return firstSection + content } private func firstSectionContent(for element: Element, language: String, sectionItemCount: Int) -> String { guard element.needsFirstSection else { return "" } let metadata = element.localized(for: language) var result = "" if element.showMostRecentSection { let shownElements = element.mostRecentElements(4).enumerated().map { (number, child) in makeSlideshowItem(child, parent: element, language: language, number: number) } let title = metadata.mostRecentTitle ?? "Recent" result = factory.slideshow.generate([.content: shownElements.joined(separator: "\n"), .title: title]) } if !element.featuredPages.isEmpty { let elements = element.featuredPages.compactMap { id -> Element? in guard let linked = siteRoot.find(id) else { results.warning("Unknown id '\(id)' in 'featuredPages'", source: element.path) return nil } return linked }.prefix(4).enumerated().map { number, page in makeSlideshowItem(page, parent: element, language: language, number: number) } let title = metadata.featuredTitle ?? "Featured" result += factory.slideshow.generate([.content: elements.joined(separator: "\n"), .title: title]) } return factory.slideshows.generate([.content : result]) } private func makeSlideshowItem(_ item: Element, parent: Element, language: String, number: Int) -> String { let metadata = item.localized(for: language) var content = [SlideshowImageTemplate.Key : String]() content[.number] = "\(number + 1)" content[.altText] = metadata.linkPreviewDescription if item.state.hasThumbnailLink { let fullPageUrl = item.fullPageUrl(for: language) let relativePageUrl = parent.relativePathToFileWithPath(fullPageUrl) content[.url] = "href=\"\(relativePageUrl)\"" } // Image already assumed to be generated let (_, thumbnailDestPath) = item.thumbnailFilePath(for: language) let thumbnailDestNoExtension = thumbnailDestPath.dropAfterLast(".") content[.image] = parent.relativePathToFileWithPath(thumbnailDestNoExtension) if let suffix = metadata.thumbnailSuffix { content[.title] = factory.html.make(title: metadata.title, suffix: suffix) } else { content[.title] = metadata.title } let path = item.makePath(language: language, from: siteRoot) content[.subtitle] = factory.pageLink.makePath(components: path) return factory.slideshowImage.generate(content) } private func sectionsContent(_ sections: [Element], in parent: Element, language: String, sectionItemCount: Int) -> String { sections.map { section in let metadata = section.localized(for: language) let fullUrl = section.fullPageUrl(for: language) let relativeUrl = parent.relativePathToFileWithPath(fullUrl) var content = [OverviewSectionTemplate.Key : String]() content[.url] = relativeUrl content[.title] = metadata.title content[.items] = generator.generateContent( items: section.itemsForOverview(sectionItemCount), parent: parent, language: language, style: section.thumbnailStyle) content[.more] = metadata.moreLinkText return factory.overviewSection.generate(content) } .joined(separator: "\n") } func generate(section: Element, language: String) -> String { var content = [OverviewSectionCleanTemplate.Key : String]() content[.items] = generator.generateContent( items: section.itemsForOverview(), parent: section, language: language, style: section.thumbnailStyle) return factory.overviewSectionClean.generate(content) } }