Generate list of redirects

This commit is contained in:
Christoph Hagen 2025-01-06 10:45:48 +01:00
parent cb9af225f0
commit 48cfa204e2
3 changed files with 60 additions and 3 deletions

View File

@ -46,6 +46,15 @@ final class GenerationResults: ObservableObject {
@Published
var emptyPages: Set<LocalizedPageId> = []
/**
The url redirects to install to prevent broken links.
The key is the original url, and the value the new url of the content, relative to the output folder.
The dictionary is used to create a map of redirects for Nginx.
*/
@Published
var redirects: [String : String] = [:]
/// The cache of previously used GenerationResults
private var cache: [ItemId : PageGenerationResults] = [:]
@ -114,6 +123,8 @@ final class GenerationResults: ObservableObject {
update { self.warnings = warnings }
let unsavedOutputFiles = cache.values.map { $0.unsavedOutputFiles.keys }.union()
update { self.unsavedOutputFiles = unsavedOutputFiles }
let redirects = cache.values.compactMap { $0.redirect }.reduce(into: [:]) { $0[$1.originalUrl] = $1.newUrl }
update { self.redirects = redirects }
}
private func update(_ operation: @escaping () -> Void) {
@ -185,7 +196,11 @@ final class GenerationResults: ObservableObject {
}
func empty(_ page: LocalizedPageId) {
update {self.emptyPages.insert(page) }
update { self.emptyPages.insert(page) }
}
func redirect(from originalUrl: String, to newUrl: String) {
update { self.redirects[originalUrl] = newUrl }
}
}

View File

@ -77,6 +77,8 @@ final class PageGenerationResults: ObservableObject {
private(set) var pageIsEmpty: Bool
private(set) var redirect: (originalUrl: String, newUrl: String)?
init(itemId: ItemId, delegate: GenerationResults) {
self.itemId = itemId
self.delegate = delegate
@ -100,6 +102,7 @@ final class PageGenerationResults: ObservableObject {
warnings = []
unsavedOutputFiles = [:]
pageIsEmpty = false
redirect = nil
}
func reset() {
@ -123,6 +126,7 @@ final class PageGenerationResults: ObservableObject {
warnings = []
unsavedOutputFiles = [:]
pageIsEmpty = false
redirect = nil
}
// MARK: Adding entries
@ -251,5 +255,10 @@ final class PageGenerationResults: ObservableObject {
pageIsEmpty = true
delegate.empty(.init(language: itemId.language, pageId: page.id))
}
func redirect(from originalUrl: String, to newUrl: String) {
redirect = (originalUrl, newUrl)
delegate.redirect(from: originalUrl, to: newUrl)
}
}

View File

@ -13,6 +13,7 @@ extension Content {
self.generateRequiredImages()
self.results.recalculate()
self.generateListOfExternalFiles()
self.generateListOfUrlMappings()
self.status("Generation completed")
}
}
@ -240,6 +241,10 @@ extension Content {
tag: tag)
let generator = PostListPageGenerator(source: source)
generator.createPages(for: posts)
if let originalUrl = tag.localized(in: language).originalUrl {
results.redirect(from: originalUrl, to: tag.absoluteUrl(in: language))
}
}
}
@ -274,11 +279,16 @@ extension Content {
return
}
let path = page.absoluteUrl(in: language) + ".html"
guard storage.write(content, to: path) else {
let pageUrl = page.absoluteUrl(in: language)
let filePath = pageUrl + ".html"
guard storage.write(content, to: filePath) else {
print("Failed to save page \(page.id)")
return
}
if let originalUrl = page.localized(in: language).originalUrl {
results.redirect(from: originalUrl, to: pageUrl)
}
}
// MARK: Additional infos
@ -303,4 +313,27 @@ extension Content {
storage.write(content, to: externalFileListName)
}
private var redirectsListFileName: String { "redirects.txt" }
private func generateListOfUrlMappings() {
let redirects = results.redirects.map { "\($0.key) \($0.value);" }
guard !redirects.isEmpty else {
if storage.hasFileInOutputFolder(redirectsListFileName) {
storage.deleteInOutputFolder(redirectsListFileName)
}
return
}
let list = redirects.sorted().joined(separator: "\n ")
let content =
"""
map $request_uri $redirect_uri {
\(list)
}
"""
storage.write(content, to: redirectsListFileName)
}
}