Generate navigation links

This commit is contained in:
Christoph Hagen 2022-09-25 22:07:34 +02:00
parent 756629d2dc
commit 152a76935b
5 changed files with 87 additions and 21 deletions

View File

@ -126,6 +126,20 @@ extension Element {
This property is mandatory at root level, and is propagated to child elements.
*/
let relatedContentText: String
/**
The text to display on the navigation element pointing to this element as the next page.
This property is mandatory at root level, and is propagated to child elements.
*/
let navigationTextAsNextPage: String
/**
The text to display on a navigation element pointing to this element as the previous page.
This property is mandatory at root level, and is propagated to child elements.
*/
let navigationTextAsPreviousPage: String
}
}
@ -171,6 +185,10 @@ extension Element.LocalizedMetadata {
self.externalUrl = log.unexpected(data.externalUrl, name: "externalUrl", source: source)
self.relatedContentText = log
.required(data.relatedContentText, name: "relatedContentText", source: source) ?? ""
self.navigationTextAsNextPage = log
.required(data.navigationTextAsNextPage, name: "navigationTextAsNextPage", source: source) ?? ""
self.navigationTextAsPreviousPage = log
.required(data.navigationTextAsPreviousPage, name: "navigationTextAsPreviousPage", source: source) ?? ""
guard isComplete else {
return nil
@ -207,6 +225,8 @@ extension Element.LocalizedMetadata {
self.cornerText = data.cornerText
self.externalUrl = data.externalUrl
self.relatedContentText = data.relatedContentText ?? parent.relatedContentText
self.navigationTextAsPreviousPage = data.navigationTextAsPreviousPage ?? parent.navigationTextAsPreviousPage
self.navigationTextAsNextPage = data.navigationTextAsNextPage ?? parent.navigationTextAsNextPage
guard isComplete else {
return nil

View File

@ -310,6 +310,15 @@ extension Element {
elements.filter { $0.state.isShownInOverview }
}
var linkedElements: [LinkedElement] {
let items = sortedItems
return items.enumerated().map { i, element in
let previous = i+1 < items.count ? items[i+1] : nil
let next = i > 0 ? items[i-1] : nil
return (previous, element, next)
}
}
/**
The url of the top-level section of the element.
*/

View File

@ -119,6 +119,20 @@ extension GenericMetadata {
This property is mandatory at root level, and is propagated to child elements.
*/
let relatedContentText: String?
/**
The text to display on a navigation element pointing to this element as the previous page.
This property is mandatory at root level, and is propagated to child elements.
*/
let navigationTextAsPreviousPage: String?
/**
The text to display on the navigation element pointing to this element as the next page.
This property is mandatory at root level, and is propagated to child elements.
*/
let navigationTextAsNextPage: String?
}
}
@ -142,6 +156,8 @@ extension GenericMetadata.LocalizedMetadata: Codable {
.cornerText,
.externalUrl,
.relatedContentText,
.navigationTextAsPreviousPage,
.navigationTextAsNextPage,
]
}
@ -172,7 +188,9 @@ extension GenericMetadata.LocalizedMetadata {
thumbnailSuffix: nil,
cornerText: nil,
externalUrl: nil,
relatedContentText: nil)
relatedContentText: nil,
navigationTextAsPreviousPage: nil,
navigationTextAsNextPage: nil)
}
/**
@ -194,7 +212,9 @@ extension GenericMetadata.LocalizedMetadata {
thumbnailSuffix: nil,
cornerText: nil,
externalUrl: nil,
relatedContentText: "")
relatedContentText: "",
navigationTextAsPreviousPage: "",
navigationTextAsNextPage: "")
}
static var full: GenericMetadata.LocalizedMetadata {
@ -213,6 +233,8 @@ extension GenericMetadata.LocalizedMetadata {
thumbnailSuffix: "",
cornerText: "",
externalUrl: "",
relatedContentText: "")
relatedContentText: "",
navigationTextAsPreviousPage: "",
navigationTextAsNextPage: "")
}
}

View File

@ -3,20 +3,13 @@ import Ink
struct PageGenerator {
struct NavigationLink {
let link: String
let text: String
}
private let factory: LocalizedSiteTemplate
init(factory: LocalizedSiteTemplate) {
self.factory = factory
}
func generate(page: Element, language: String, nextPage: NavigationLink?, previousPage: NavigationLink?) {
func generate(page: Element, language: String, previousPage: Element?, nextPage: Element?) {
guard !page.isExternalPage else {
return
}
@ -35,10 +28,10 @@ struct PageGenerator {
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
content[.nextPageLinkText] = nextPage.unwrapped { factory.factory.html.makeNextText($0.text) }
content[.nextPageUrl] = nextPage?.link
content[.previousPageLinkText] = previousText(for: previousPage, language: language)
content[.previousPageUrl] = navLink(from: page, to: previousPage, language: language)
content[.nextPageLinkText] = nextText(for: nextPage, language: language)
content[.nextPageUrl] = navLink(from: page, to: nextPage, language: language)
content[.footer] = page.customFooterContent()
if pageIncludesCode {
@ -58,6 +51,27 @@ struct PageGenerator {
files.generated(page: path)
}
private func navLink(from element: Element, to destination: Element?, language: String) -> String? {
guard let fullPath = destination?.fullPageUrl(for: language) else {
return nil
}
return element.relativePathToOtherSiteElement(file: fullPath)
}
private func previousText(for element: Element?, language: String) -> String? {
guard let text = element?.localized(for: language).navigationTextAsPreviousPage else {
return nil
}
return factory.factory.html.makePrevText(text)
}
private func nextText(for element: Element?, language: String) -> String? {
guard let text = element?.localized(for: language).navigationTextAsNextPage else {
return nil
}
return factory.factory.html.makeNextText(text)
}
private func makeContent(page: Element, metadata: Element.LocalizedMetadata, language: String, path: String) -> (content: String, includesCode: Bool, isEmpty: Bool) {
let create = configuration.createMdFilesIfMissing
if let raw = files.contentOfOptionalFile(atPath: path, source: page.path, createEmptyFileIfMissing: create)?

View File

@ -1,5 +1,7 @@
import Foundation
typealias LinkedElement = (previous: Element?, element: Element, next: Element?)
struct SiteGenerator {
let templates: TemplateFactory
@ -26,22 +28,21 @@ struct SiteGenerator {
let overviewGenerator = OverviewPageGenerator(factory: template)
let pageGenerator = PageGenerator(factory: template)
var elementsToProcess: [Element] = [site]
while let element = elementsToProcess.popLast() {
var elementsToProcess: [LinkedElement] = [(nil, site, nil)]
while let (previous, element, next) = elementsToProcess.popLast() {
// Move recursively down to all pages
elementsToProcess.append(contentsOf: element.elements)
elementsToProcess.append(contentsOf: element.linkedElements)
processAllFiles(for: element)
if !element.elements.isEmpty {
overviewGenerator.generate(section: element, language: language)
} else {
#warning("Determine previous and next pages (with relative links)")
pageGenerator.generate(
page: element,
language: language,
nextPage: nil,
previousPage: nil)
previousPage: previous,
nextPage: next)
}
}
}