diff --git a/WebsiteGenerator.xcodeproj/project.pbxproj b/WebsiteGenerator.xcodeproj/project.pbxproj index 981a24d..e694dfd 100644 --- a/WebsiteGenerator.xcodeproj/project.pbxproj +++ b/WebsiteGenerator.xcodeproj/project.pbxproj @@ -38,6 +38,7 @@ E2C5A5E528A03A6500102A25 /* BackNavigationTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2C5A5E428A03A6500102A25 /* BackNavigationTemplate.swift */; }; E2C5A5E928A0451C00102A25 /* LocalizedSiteTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2C5A5E828A0451C00102A25 /* LocalizedSiteTemplate.swift */; }; E2D4225128BD242200400E64 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2D4225028BD242200400E64 /* Configuration.swift */; }; + E2D4225328C5219D00400E64 /* HeaderType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2D4225228C5219D00400E64 /* HeaderType.swift */; }; E2D55EDB28A2511D00B9453E /* OverviewSectionCleanTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2D55EDA28A2511D00B9453E /* OverviewSectionCleanTemplate.swift */; }; E2F8FA1E28A539C500632026 /* MarkdownProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8FA1D28A539C500632026 /* MarkdownProcessor.swift */; }; E2F8FA2028AB72D900632026 /* PlaceholderTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8FA1F28AB72D900632026 /* PlaceholderTemplate.swift */; }; @@ -99,6 +100,7 @@ E2C5A5E428A03A6500102A25 /* BackNavigationTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackNavigationTemplate.swift; sourceTree = ""; }; E2C5A5E828A0451C00102A25 /* LocalizedSiteTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedSiteTemplate.swift; sourceTree = ""; }; E2D4225028BD242200400E64 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = ""; }; + E2D4225228C5219D00400E64 /* HeaderType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderType.swift; sourceTree = ""; }; E2D55EDA28A2511D00B9453E /* OverviewSectionCleanTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverviewSectionCleanTemplate.swift; sourceTree = ""; }; E2F8FA1D28A539C500632026 /* MarkdownProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownProcessor.swift; sourceTree = ""; }; E2F8FA1F28AB72D900632026 /* PlaceholderTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderTemplate.swift; sourceTree = ""; }; @@ -255,6 +257,7 @@ E2F8FA3328AD6F3400632026 /* Element.swift */, E2F8FA3528AE233600632026 /* Element+LocalizedMetadata.swift */, E22E876B289D855D00E51191 /* ThumbnailStyle.swift */, + E2D4225228C5219D00400E64 /* HeaderType.swift */, ); path = Content; sourceTree = ""; @@ -357,6 +360,7 @@ E2F8FA2628ACD64500632026 /* PageVideoTemplate.swift in Sources */, E2C5A5DB28A02F9000102A25 /* TopBarTemplate.swift in Sources */, E2C5A5E928A0451C00102A25 /* LocalizedSiteTemplate.swift in Sources */, + E2D4225328C5219D00400E64 /* HeaderType.swift in Sources */, E2C5A5E128A0373300102A25 /* ThumbnailTemplate.swift in Sources */, E22E8795289E81D700E51191 /* URL+Extensions.swift in Sources */, E2C5A5D928A023FA00102A25 /* PageHeadTemplate.swift in Sources */, diff --git a/WebsiteGenerator/Content/Element.swift b/WebsiteGenerator/Content/Element.swift index 6ef71f3..a179ff0 100644 --- a/WebsiteGenerator/Content/Element.swift +++ b/WebsiteGenerator/Content/Element.swift @@ -102,12 +102,13 @@ struct Element { let overviewItemCount: Int /** - Indicate that no header should be generated automatically. + Indicate the header type to be generated automatically. - This option assumes that custom header code is present in the page source files - - Note: If not specified, this property defaults to `false`. + If this option is set to `none`, then custom header code should be present in the page source files + - Note: If not specified, this property defaults to `left`. + - Note: Overview pages are always using `center`. */ - let useCustomHeader: Bool + let headerType: HeaderType /** The localized metadata for each language. @@ -162,13 +163,16 @@ struct Element { self.thumbnailStyle = log.unused(metadata.thumbnailStyle, "thumbnailStyle", source: source) ?? .large self.useManualSorting = log.unused(metadata.useManualSorting, "useManualSorting", source: source) ?? true self.overviewItemCount = metadata.overviewItemCount ?? Element.overviewItemCountDefault - self.useCustomHeader = metadata.useCustomHeader ?? false + self.headerType = log.headerType(metadata.headerType, source: source) self.languages = log.required(metadata.languages, name: "languages", source: source)? .compactMap { language in .init(atRoot: folder, data: language) } ?? [] - // All properties initialized + guard !languages.isEmpty else { + log.add(error: "No languages found", source: source) + return nil + } files.add(page: path, id: id) try self.readElements(in: folder, source: nil) @@ -214,9 +218,10 @@ struct Element { log.add(warning: "Set 'endDate', but no 'date'", source: source) } } - self.state = log.state(metadata.state, source: source) + let state = log.state(metadata.state, source: source) + self.state = state self.sortIndex = metadata.sortIndex.ifNil { - if parent.useManualSorting { + if state != .hidden, parent.useManualSorting { log.add(error: "No 'sortIndex', but parent defines 'useManualSorting' = true", source: source) } } @@ -226,7 +231,7 @@ struct Element { self.thumbnailStyle = log.thumbnailStyle(metadata.thumbnailStyle, source: source) self.useManualSorting = metadata.useManualSorting ?? false self.overviewItemCount = metadata.overviewItemCount ?? parent.overviewItemCount - self.useCustomHeader = metadata.useCustomHeader ?? false + self.headerType = log.headerType(metadata.headerType, source: source) self.languages = parent.languages.compactMap { parentData in guard let data = metadata.languages?.first(where: { $0.language == parentData.language }) else { log.add(info: "Language '\(parentData.language)' not found", source: source) diff --git a/WebsiteGenerator/Content/GenericMetadata.swift b/WebsiteGenerator/Content/GenericMetadata.swift index 521b224..c548f61 100644 --- a/WebsiteGenerator/Content/GenericMetadata.swift +++ b/WebsiteGenerator/Content/GenericMetadata.swift @@ -101,12 +101,13 @@ struct GenericMetadata { let overviewItemCount: Int? /** - Indicate that no header should be generated automatically. + Indicate the header type to be generated automatically. - This option assumes that custom header code is present in the page source files - - Note: If not specified, this property defaults to `false`. + If this option is set to `none`, then custom header code should be present in the page source files + - Note: If not specified, this property defaults to `left`. + - Note: Overview pages are always using `center`. */ - let useCustomHeader: Bool? + let headerType: String? /** The localized metadata for each language. @@ -130,7 +131,7 @@ extension GenericMetadata: Codable { .thumbnailStyle, .useManualSorting, .overviewItemCount, - .useCustomHeader, + .headerType, .languages, ] } @@ -200,7 +201,7 @@ extension GenericMetadata { thumbnailStyle: "", useManualSorting: false, overviewItemCount: 6, - useCustomHeader: false, + headerType: "left", languages: [.full]) } } diff --git a/WebsiteGenerator/Content/HeaderType.swift b/WebsiteGenerator/Content/HeaderType.swift new file mode 100644 index 0000000..4a14837 --- /dev/null +++ b/WebsiteGenerator/Content/HeaderType.swift @@ -0,0 +1,19 @@ +import Foundation + +enum HeaderType: String { + + /** + The standard page header, left-aligned + */ + case left + + /** + The standard overview header, centered + */ + case center + + /** + The element provides it's own header, so don't generate any. + */ + case none +} diff --git a/WebsiteGenerator/Files/ValidationLog.swift b/WebsiteGenerator/Files/ValidationLog.swift index 2f81790..cddd293 100644 --- a/WebsiteGenerator/Files/ValidationLog.swift +++ b/WebsiteGenerator/Files/ValidationLog.swift @@ -93,6 +93,17 @@ final class ValidationLog { return state } + func headerType(_ raw: String?, source: String) -> HeaderType { + guard let raw = raw else { + return .left + } + guard let type = HeaderType(rawValue: raw) else { + add(warning: "Invalid 'headerType' '\(raw)', using 'left'", source: source) + return .left + } + return type + } + func thumbnailStyle(_ raw: String?, source: String) -> ThumbnailStyle { guard let raw = raw else { return .large diff --git a/WebsiteGenerator/Generators/PageGenerator.swift b/WebsiteGenerator/Generators/PageGenerator.swift index fd6b828..3391512 100644 --- a/WebsiteGenerator/Generators/PageGenerator.swift +++ b/WebsiteGenerator/Generators/PageGenerator.swift @@ -33,9 +33,7 @@ struct PageGenerator { content[.topBar] = factory.topBar.generate(sectionUrl: sectionUrl, languageButton: nextLanguage, page: page) content[.contentClass] = "content" - if !page.useCustomHeader { - content[.header] = makeHeader(page: page, metadata: metadata, language: language) - } + content[.header] = makeHeader(page: page, metadata: metadata, language: language) content[.content] = pageContent content[.previousPageLinkText] = previousPage.unwrapped { factory.factory.html.makePrevText($0.text) } content[.previousPageUrl] = previousPage?.link @@ -74,9 +72,16 @@ struct PageGenerator { } } - private func makeHeader(page: Element, metadata: Element.LocalizedMetadata, language: String) -> String { + private func makeHeader(page: Element, metadata: Element.LocalizedMetadata, language: String) -> String? { let content = factory.makeHeaderContent(page: page, metadata: metadata, language: language) - return factory.factory.leftHeader.generate(content) + switch page.headerType { + case .none: + return nil + case .left: + return factory.factory.leftHeader.generate(content) + case .center: + return factory.factory.centeredHeader.generate(content) + } } }