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 @Published
var emptyPages: Set<LocalizedPageId> = [] 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 /// The cache of previously used GenerationResults
private var cache: [ItemId : PageGenerationResults] = [:] private var cache: [ItemId : PageGenerationResults] = [:]
@ -114,6 +123,8 @@ final class GenerationResults: ObservableObject {
update { self.warnings = warnings } update { self.warnings = warnings }
let unsavedOutputFiles = cache.values.map { $0.unsavedOutputFiles.keys }.union() let unsavedOutputFiles = cache.values.map { $0.unsavedOutputFiles.keys }.union()
update { self.unsavedOutputFiles = unsavedOutputFiles } 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) { private func update(_ operation: @escaping () -> Void) {
@ -185,7 +196,11 @@ final class GenerationResults: ObservableObject {
} }
func empty(_ page: LocalizedPageId) { 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 pageIsEmpty: Bool
private(set) var redirect: (originalUrl: String, newUrl: String)?
init(itemId: ItemId, delegate: GenerationResults) { init(itemId: ItemId, delegate: GenerationResults) {
self.itemId = itemId self.itemId = itemId
self.delegate = delegate self.delegate = delegate
@ -100,6 +102,7 @@ final class PageGenerationResults: ObservableObject {
warnings = [] warnings = []
unsavedOutputFiles = [:] unsavedOutputFiles = [:]
pageIsEmpty = false pageIsEmpty = false
redirect = nil
} }
func reset() { func reset() {
@ -123,6 +126,7 @@ final class PageGenerationResults: ObservableObject {
warnings = [] warnings = []
unsavedOutputFiles = [:] unsavedOutputFiles = [:]
pageIsEmpty = false pageIsEmpty = false
redirect = nil
} }
// MARK: Adding entries // MARK: Adding entries
@ -251,5 +255,10 @@ final class PageGenerationResults: ObservableObject {
pageIsEmpty = true pageIsEmpty = true
delegate.empty(.init(language: itemId.language, pageId: page.id)) 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.generateRequiredImages()
self.results.recalculate() self.results.recalculate()
self.generateListOfExternalFiles() self.generateListOfExternalFiles()
self.generateListOfUrlMappings()
self.status("Generation completed") self.status("Generation completed")
} }
} }
@ -240,6 +241,10 @@ extension Content {
tag: tag) tag: tag)
let generator = PostListPageGenerator(source: source) let generator = PostListPageGenerator(source: source)
generator.createPages(for: posts) 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 return
} }
let path = page.absoluteUrl(in: language) + ".html" let pageUrl = page.absoluteUrl(in: language)
guard storage.write(content, to: path) else { let filePath = pageUrl + ".html"
guard storage.write(content, to: filePath) else {
print("Failed to save page \(page.id)") print("Failed to save page \(page.id)")
return return
} }
if let originalUrl = page.localized(in: language).originalUrl {
results.redirect(from: originalUrl, to: pageUrl)
}
} }
// MARK: Additional infos // MARK: Additional infos
@ -303,4 +313,27 @@ extension Content {
storage.write(content, to: externalFileListName) 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)
}
} }