Allow header selection for pages

This commit is contained in:
Christoph Hagen 2022-09-04 20:36:43 +02:00
parent a7e7bc21fc
commit 1c13f4fc60
6 changed files with 65 additions and 20 deletions

View File

@ -38,6 +38,7 @@
E2C5A5E528A03A6500102A25 /* BackNavigationTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2C5A5E428A03A6500102A25 /* BackNavigationTemplate.swift */; }; E2C5A5E528A03A6500102A25 /* BackNavigationTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2C5A5E428A03A6500102A25 /* BackNavigationTemplate.swift */; };
E2C5A5E928A0451C00102A25 /* LocalizedSiteTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2C5A5E828A0451C00102A25 /* LocalizedSiteTemplate.swift */; }; E2C5A5E928A0451C00102A25 /* LocalizedSiteTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2C5A5E828A0451C00102A25 /* LocalizedSiteTemplate.swift */; };
E2D4225128BD242200400E64 /* Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2D4225028BD242200400E64 /* Configuration.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 */; }; E2D55EDB28A2511D00B9453E /* OverviewSectionCleanTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2D55EDA28A2511D00B9453E /* OverviewSectionCleanTemplate.swift */; };
E2F8FA1E28A539C500632026 /* MarkdownProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8FA1D28A539C500632026 /* MarkdownProcessor.swift */; }; E2F8FA1E28A539C500632026 /* MarkdownProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8FA1D28A539C500632026 /* MarkdownProcessor.swift */; };
E2F8FA2028AB72D900632026 /* PlaceholderTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8FA1F28AB72D900632026 /* PlaceholderTemplate.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 = "<group>"; }; E2C5A5E428A03A6500102A25 /* BackNavigationTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackNavigationTemplate.swift; sourceTree = "<group>"; };
E2C5A5E828A0451C00102A25 /* LocalizedSiteTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedSiteTemplate.swift; sourceTree = "<group>"; }; E2C5A5E828A0451C00102A25 /* LocalizedSiteTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedSiteTemplate.swift; sourceTree = "<group>"; };
E2D4225028BD242200400E64 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; }; E2D4225028BD242200400E64 /* Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Configuration.swift; sourceTree = "<group>"; };
E2D4225228C5219D00400E64 /* HeaderType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderType.swift; sourceTree = "<group>"; };
E2D55EDA28A2511D00B9453E /* OverviewSectionCleanTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverviewSectionCleanTemplate.swift; sourceTree = "<group>"; }; E2D55EDA28A2511D00B9453E /* OverviewSectionCleanTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverviewSectionCleanTemplate.swift; sourceTree = "<group>"; };
E2F8FA1D28A539C500632026 /* MarkdownProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownProcessor.swift; sourceTree = "<group>"; }; E2F8FA1D28A539C500632026 /* MarkdownProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownProcessor.swift; sourceTree = "<group>"; };
E2F8FA1F28AB72D900632026 /* PlaceholderTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderTemplate.swift; sourceTree = "<group>"; }; E2F8FA1F28AB72D900632026 /* PlaceholderTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderTemplate.swift; sourceTree = "<group>"; };
@ -255,6 +257,7 @@
E2F8FA3328AD6F3400632026 /* Element.swift */, E2F8FA3328AD6F3400632026 /* Element.swift */,
E2F8FA3528AE233600632026 /* Element+LocalizedMetadata.swift */, E2F8FA3528AE233600632026 /* Element+LocalizedMetadata.swift */,
E22E876B289D855D00E51191 /* ThumbnailStyle.swift */, E22E876B289D855D00E51191 /* ThumbnailStyle.swift */,
E2D4225228C5219D00400E64 /* HeaderType.swift */,
); );
path = Content; path = Content;
sourceTree = "<group>"; sourceTree = "<group>";
@ -357,6 +360,7 @@
E2F8FA2628ACD64500632026 /* PageVideoTemplate.swift in Sources */, E2F8FA2628ACD64500632026 /* PageVideoTemplate.swift in Sources */,
E2C5A5DB28A02F9000102A25 /* TopBarTemplate.swift in Sources */, E2C5A5DB28A02F9000102A25 /* TopBarTemplate.swift in Sources */,
E2C5A5E928A0451C00102A25 /* LocalizedSiteTemplate.swift in Sources */, E2C5A5E928A0451C00102A25 /* LocalizedSiteTemplate.swift in Sources */,
E2D4225328C5219D00400E64 /* HeaderType.swift in Sources */,
E2C5A5E128A0373300102A25 /* ThumbnailTemplate.swift in Sources */, E2C5A5E128A0373300102A25 /* ThumbnailTemplate.swift in Sources */,
E22E8795289E81D700E51191 /* URL+Extensions.swift in Sources */, E22E8795289E81D700E51191 /* URL+Extensions.swift in Sources */,
E2C5A5D928A023FA00102A25 /* PageHeadTemplate.swift in Sources */, E2C5A5D928A023FA00102A25 /* PageHeadTemplate.swift in Sources */,

View File

@ -102,12 +102,13 @@ struct Element {
let overviewItemCount: Int 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 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 `false`. - 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. The localized metadata for each language.
@ -162,13 +163,16 @@ struct Element {
self.thumbnailStyle = log.unused(metadata.thumbnailStyle, "thumbnailStyle", source: source) ?? .large self.thumbnailStyle = log.unused(metadata.thumbnailStyle, "thumbnailStyle", source: source) ?? .large
self.useManualSorting = log.unused(metadata.useManualSorting, "useManualSorting", source: source) ?? true self.useManualSorting = log.unused(metadata.useManualSorting, "useManualSorting", source: source) ?? true
self.overviewItemCount = metadata.overviewItemCount ?? Element.overviewItemCountDefault 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)? self.languages = log.required(metadata.languages, name: "languages", source: source)?
.compactMap { language in .compactMap { language in
.init(atRoot: folder, data: language) .init(atRoot: folder, data: language)
} ?? [] } ?? []
// All properties initialized // All properties initialized
guard !languages.isEmpty else {
log.add(error: "No languages found", source: source)
return nil
}
files.add(page: path, id: id) files.add(page: path, id: id)
try self.readElements(in: folder, source: nil) try self.readElements(in: folder, source: nil)
@ -214,9 +218,10 @@ struct Element {
log.add(warning: "Set 'endDate', but no 'date'", source: source) 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 { 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) 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.thumbnailStyle = log.thumbnailStyle(metadata.thumbnailStyle, source: source)
self.useManualSorting = metadata.useManualSorting ?? false self.useManualSorting = metadata.useManualSorting ?? false
self.overviewItemCount = metadata.overviewItemCount ?? parent.overviewItemCount 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 self.languages = parent.languages.compactMap { parentData in
guard let data = metadata.languages?.first(where: { $0.language == parentData.language }) else { guard let data = metadata.languages?.first(where: { $0.language == parentData.language }) else {
log.add(info: "Language '\(parentData.language)' not found", source: source) log.add(info: "Language '\(parentData.language)' not found", source: source)

View File

@ -101,12 +101,13 @@ struct GenericMetadata {
let overviewItemCount: Int? 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 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 `false`. - 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. The localized metadata for each language.
@ -130,7 +131,7 @@ extension GenericMetadata: Codable {
.thumbnailStyle, .thumbnailStyle,
.useManualSorting, .useManualSorting,
.overviewItemCount, .overviewItemCount,
.useCustomHeader, .headerType,
.languages, .languages,
] ]
} }
@ -200,7 +201,7 @@ extension GenericMetadata {
thumbnailStyle: "", thumbnailStyle: "",
useManualSorting: false, useManualSorting: false,
overviewItemCount: 6, overviewItemCount: 6,
useCustomHeader: false, headerType: "left",
languages: [.full]) languages: [.full])
} }
} }

View File

@ -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
}

View File

@ -93,6 +93,17 @@ final class ValidationLog {
return state 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 { func thumbnailStyle(_ raw: String?, source: String) -> ThumbnailStyle {
guard let raw = raw else { guard let raw = raw else {
return .large return .large

View File

@ -33,9 +33,7 @@ struct PageGenerator {
content[.topBar] = factory.topBar.generate(sectionUrl: sectionUrl, languageButton: nextLanguage, page: page) content[.topBar] = factory.topBar.generate(sectionUrl: sectionUrl, languageButton: nextLanguage, page: page)
content[.contentClass] = "content" 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[.content] = pageContent
content[.previousPageLinkText] = previousPage.unwrapped { factory.factory.html.makePrevText($0.text) } content[.previousPageLinkText] = previousPage.unwrapped { factory.factory.html.makePrevText($0.text) }
content[.previousPageUrl] = previousPage?.link 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) let content = factory.makeHeaderContent(page: page, metadata: metadata, language: language)
switch page.headerType {
case .none:
return nil
case .left:
return factory.factory.leftHeader.generate(content) return factory.factory.leftHeader.generate(content)
case .center:
return factory.factory.centeredHeader.generate(content)
}
} }
} }