Allow custom thumbnail paths in metadata
This commit is contained in:
parent
9d2f1e4c90
commit
c82080db82
@ -233,27 +233,3 @@ extension Element.LocalizedMetadata {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Thumbnails
|
||||
|
||||
extension Element {
|
||||
|
||||
static let defaultThumbnailName = "thumbnail.jpg"
|
||||
|
||||
static func localizedThumbnailName(for language: String) -> String {
|
||||
"thumbnail-\(language).jpg"
|
||||
}
|
||||
|
||||
static func findThumbnail(for language: String, in folder: URL) -> String? {
|
||||
let localizedThumbnail = localizedThumbnailName(for: language)
|
||||
let localizedThumbnailUrl = folder.appendingPathComponent(localizedThumbnail)
|
||||
if localizedThumbnailUrl.exists {
|
||||
return localizedThumbnail
|
||||
}
|
||||
let defaultThumbnailUrl = folder.appendingPathComponent(defaultThumbnailName)
|
||||
if defaultThumbnailUrl.exists {
|
||||
return defaultThumbnailName
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -85,6 +85,15 @@ struct Element {
|
||||
*/
|
||||
let images: [ManualImage]
|
||||
|
||||
/**
|
||||
The path to the thumbnail file.
|
||||
|
||||
This property is optional, and defaults to ``GenericMetadata.defaultThumbnailName``.
|
||||
Note: The generator first looks for localized versions of the thumbnail by appending `-[lang]` to the file name,
|
||||
e.g. `customThumb-en.jpg`. If no file is found, then the specified file is tried.
|
||||
*/
|
||||
let thumbnailPath: String
|
||||
|
||||
/**
|
||||
The style of thumbnail to use when generating overviews.
|
||||
|
||||
@ -168,6 +177,7 @@ struct Element {
|
||||
self.externalFiles = metadata.externalFiles ?? []
|
||||
self.requiredFiles = metadata.requiredFiles ?? [] // Paths are already relative to root
|
||||
self.images = metadata.images?.compactMap { ManualImage(input: $0, path: "") } ?? []
|
||||
self.thumbnailPath = metadata.thumbnailPath ?? Element.defaultThumbnailName
|
||||
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
|
||||
@ -237,6 +247,7 @@ struct Element {
|
||||
self.externalFiles = Element.rootPaths(for: metadata.externalFiles, path: path)
|
||||
self.requiredFiles = Element.rootPaths(for: metadata.requiredFiles, path: path)
|
||||
self.images = metadata.images?.compactMap { ManualImage(input: $0, path: path) } ?? []
|
||||
self.thumbnailPath = metadata.thumbnailPath ?? Element.defaultThumbnailName
|
||||
self.thumbnailStyle = log.thumbnailStyle(metadata.thumbnailStyle, source: source)
|
||||
self.useManualSorting = metadata.useManualSorting ?? false
|
||||
self.overviewItemCount = metadata.overviewItemCount ?? parent.overviewItemCount
|
||||
@ -420,17 +431,6 @@ extension Element {
|
||||
|
||||
extension Element {
|
||||
|
||||
/**
|
||||
Get the full path of the thumbnail image for the language (relative to the root folder).
|
||||
*/
|
||||
func thumbnailFilePath(for language: String) -> String {
|
||||
guard let thumbnailFile = Element.findThumbnail(for: language, in: inputFolder) else {
|
||||
log.add(error: "Missing thumbnail", source: path)
|
||||
return Element.defaultThumbnailName
|
||||
}
|
||||
return pathRelativeToRootForContainedInputFile(thumbnailFile)
|
||||
}
|
||||
|
||||
/**
|
||||
The full url (relative to root) for the localized page
|
||||
- Parameter language: The language of the page where the url should point
|
||||
@ -497,7 +497,7 @@ extension Element {
|
||||
}
|
||||
|
||||
func linkPreviewImage(for language: String) -> String? {
|
||||
localized(for: language).linkPreviewImage
|
||||
localized(for: language).linkPreviewImage ?? thumbnailFileName(for: language)
|
||||
}
|
||||
}
|
||||
|
||||
@ -663,3 +663,57 @@ extension Element {
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Thumbnails
|
||||
|
||||
extension Element {
|
||||
|
||||
static let defaultThumbnailName = "thumbnail.jpg"
|
||||
|
||||
/**
|
||||
Find the thumbnail for the element.
|
||||
|
||||
This function uses either the custom thumbnail path from the metadata or the default name
|
||||
to find a thumbnail. It first checks if a localized version of the thumbnail exists, or returns the
|
||||
generic version. If no thumbnail image could be found on disk, then an error is logged and the
|
||||
generic path is returned.
|
||||
|
||||
- Parameter language: The language of the thumbnail
|
||||
- Returns: The thumbnail (either the localized or the generic version)
|
||||
*/
|
||||
func thumbnailFilePath(for language: String) -> (source: String, destination: String) {
|
||||
let localizedThumbnail = thumbnailPath.insert("-\(language)", beforeLast: ".")
|
||||
let localizedThumbnailUrl = inputFolder.appendingPathComponent(localizedThumbnail)
|
||||
|
||||
if localizedThumbnailUrl.exists {
|
||||
let source = pathRelativeToRootForContainedInputFile(localizedThumbnail)
|
||||
let ext = thumbnailPath.lastComponentAfter(".")
|
||||
let destination = pathRelativeToRootForContainedInputFile("thumbnail-\(language).\(ext)")
|
||||
return (source, destination)
|
||||
}
|
||||
let thumbnailUrl = inputFolder.appendingPathComponent(thumbnailPath)
|
||||
if !thumbnailUrl.exists {
|
||||
log.add(error: "Missing thumbnail", source: path)
|
||||
}
|
||||
let source = pathRelativeToRootForContainedInputFile(thumbnailPath)
|
||||
let ext = thumbnailPath.lastComponentAfter(".")
|
||||
let destination = pathRelativeToRootForContainedInputFile("thumbnail.\(ext)")
|
||||
return (source, destination)
|
||||
}
|
||||
|
||||
private func thumbnailFileName(for language: String) -> String? {
|
||||
let localizedThumbnailName = thumbnailPath.insert("-\(language)", beforeLast: ".")
|
||||
let localizedThumbnail = pathRelativeToRootForContainedInputFile(localizedThumbnailName)
|
||||
let localizedThumbnailUrl = inputFolder.appendingPathComponent(localizedThumbnail)
|
||||
|
||||
if localizedThumbnailUrl.exists {
|
||||
return localizedThumbnailName
|
||||
}
|
||||
|
||||
let thumbnailUrl = inputFolder.appendingPathComponent(thumbnailPath)
|
||||
if !thumbnailUrl.exists {
|
||||
return nil
|
||||
}
|
||||
return thumbnailPath
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,15 @@ struct GenericMetadata {
|
||||
*/
|
||||
let images: Set<String>?
|
||||
|
||||
/**
|
||||
The path to the thumbnail file.
|
||||
|
||||
This property is optional, and defaults to ``Element.defaultThumbnailName``.
|
||||
Note: The generator first looks for localized versions of the thumbnail by appending `-[lang]` to the file name,
|
||||
e.g. `customThumb-en.jpg`. If no file is found, then the specified file is tried.
|
||||
*/
|
||||
let thumbnailPath: String?
|
||||
|
||||
/**
|
||||
The style of thumbnail to use when generating overviews.
|
||||
|
||||
@ -136,6 +145,7 @@ extension GenericMetadata: Codable {
|
||||
.externalFiles,
|
||||
.requiredFiles,
|
||||
.images,
|
||||
.thumbnailPath,
|
||||
.thumbnailStyle,
|
||||
.useManualSorting,
|
||||
.overviewItemCount,
|
||||
@ -207,6 +217,7 @@ extension GenericMetadata {
|
||||
externalFiles: [],
|
||||
requiredFiles: [],
|
||||
images: [],
|
||||
thumbnailPath: "",
|
||||
thumbnailStyle: "",
|
||||
useManualSorting: false,
|
||||
overviewItemCount: 6,
|
||||
|
@ -116,24 +116,20 @@ final class ValidationLog {
|
||||
}
|
||||
|
||||
func linkPreviewThumbnail(customFile: String?, for language: String, in folder: URL, source: String) -> String? {
|
||||
if let customFile = customFile {
|
||||
let customFileUrl: URL
|
||||
if customFile.starts(with: "/") {
|
||||
customFileUrl = URL(fileURLWithPath: customFile)
|
||||
} else {
|
||||
customFileUrl = folder.appendingPathComponent(customFile)
|
||||
}
|
||||
guard customFileUrl.exists else {
|
||||
missing(customFile, requiredBy: "property 'linkPreviewImage' in metadata of \(source)")
|
||||
return nil
|
||||
}
|
||||
return customFile
|
||||
}
|
||||
guard let thumbnail = Element.findThumbnail(for: language, in: folder) else {
|
||||
// Link preview images are not necessarily required
|
||||
guard let customFile = customFile else {
|
||||
return nil
|
||||
}
|
||||
return thumbnail
|
||||
let customFileUrl: URL
|
||||
if customFile.starts(with: "/") {
|
||||
customFileUrl = URL(fileURLWithPath: customFile)
|
||||
} else {
|
||||
customFileUrl = folder.appendingPathComponent(customFile)
|
||||
}
|
||||
guard customFileUrl.exists else {
|
||||
missing(customFile, requiredBy: "property 'linkPreviewImage' in metadata of \(source)")
|
||||
return nil
|
||||
}
|
||||
return customFile
|
||||
}
|
||||
|
||||
func moreLinkText(_ elementText: String?, parent parentText: String?, source: String) -> String {
|
||||
|
@ -265,7 +265,7 @@ struct PageContentGenerator {
|
||||
|
||||
content[.title] = linkedPage.title(for: language)
|
||||
|
||||
let fullThumbnailPath = linkedPage.thumbnailFilePath(for: language)
|
||||
let fullThumbnailPath = linkedPage.thumbnailFilePath(for: language).destination
|
||||
let relativeImageUrl = page.relativePathToOtherSiteElement(file: fullThumbnailPath)
|
||||
let metadata = linkedPage.localized(for: language)
|
||||
|
||||
|
@ -21,7 +21,7 @@ struct PageHeadGenerator {
|
||||
// Note: Generate separate destination link for the image,
|
||||
// since we don't want a single large image for thumbnails.
|
||||
// Warning: Link preview source path must be relative to root
|
||||
let linkPreviewImageName = image.insert("-link", beforeLast: ".")
|
||||
let linkPreviewImageName = "thumbnail-link.\(image.lastComponentAfter("."))"
|
||||
let sourceImagePath = page.pathRelativeToRootForContainedInputFile(image)
|
||||
let destinationImagePath = page.pathRelativeToRootForContainedInputFile(linkPreviewImageName)
|
||||
files.requireImage(
|
||||
|
@ -14,8 +14,8 @@ struct ThumbnailListGenerator {
|
||||
}
|
||||
|
||||
private func itemContent(_ item: Element, parent: Element, language: String, style: ThumbnailStyle) -> String {
|
||||
let fullThumbnailPath = item.thumbnailFilePath(for: language)
|
||||
let relativeImageUrl = parent.relativePathToFileWithPath(fullThumbnailPath)
|
||||
let (thumbnailSourcePath, thumbnailDestPath) = item.thumbnailFilePath(for: language)
|
||||
let relativeImageUrl = parent.relativePathToFileWithPath(thumbnailDestPath)
|
||||
let metadata = item.localized(for: language)
|
||||
var content = [ThumbnailKey : String]()
|
||||
|
||||
@ -37,16 +37,16 @@ struct ThumbnailListGenerator {
|
||||
}
|
||||
|
||||
files.requireImage(
|
||||
source: fullThumbnailPath,
|
||||
destination: fullThumbnailPath,
|
||||
source: thumbnailSourcePath,
|
||||
destination: thumbnailDestPath,
|
||||
requiredBy: item.path,
|
||||
width: style.width,
|
||||
desiredHeight: style.height)
|
||||
|
||||
// Create image version for high-resolution screens
|
||||
files.requireImage(
|
||||
source: fullThumbnailPath,
|
||||
destination: fullThumbnailPath.insert("@2x", beforeLast: "."),
|
||||
source: thumbnailSourcePath,
|
||||
destination: thumbnailDestPath.insert("@2x", beforeLast: "."),
|
||||
requiredBy: item.path,
|
||||
width: style.width * 2,
|
||||
desiredHeight: style.height * 2)
|
||||
|
Loading…
Reference in New Issue
Block a user