Added the ImageWidth enumeration to the Website library target.

This commit is contained in:
2026-08-25 17:23:29 +02:00
parent c09ac657ab
commit 3358946e3d
4 changed files with 135 additions and 0 deletions
@@ -0,0 +1,29 @@
/// A rendition an image asset is available at, from the narrowest up to the full-size file.
///
/// ``StaticFile`` names one file per rendition, and a page's `srcset` offers them all so the browser picks by rendered width.
/// The declaration order is the `srcset` order: narrowest first.
enum ImageWidth: CaseIterable {
/// The small rendition, 480 pixels wide.
case small
/// The medium rendition, 800 pixels wide.
case medium
/// The large rendition: the full-size file, 1200 pixels wide.
case large
}
// MARK: - Extensions
extension ImageWidth {
// MARK: Computed
/// The rendition's width in pixels: what the file is resampled to, and what its `srcset` descriptor states.
var width: Int {
switch self {
case .small: 480
case .medium: 800
case .large: 1200
}
}
}
@@ -14,18 +14,26 @@ struct StaticFile: Asset {
/// The file's name, without extension.
let fileName: String
/// The folder holding the file, or `nil` when it sits in its extensions' own folders.
///
/// Imagery sits in a folder per page `img/index`, `img/about` rather than in its extension's own.
let folder: String?
// MARK: Initializers
/// Declares a static file.
/// - Parameters:
/// - fileName: the file's name, without extension.
/// - folder: the folder holding the file, or `nil` (the default) to use each extension's own folder.
/// - fileExtensions: the extensions the file is available with, one file each.
init(
_ fileName: String,
in folder: String? = nil,
as fileExtensions: AssetExtension...
) {
self.fileExtensions = fileExtensions
self.fileName = fileName
self.folder = folder
}
}
@@ -55,6 +63,37 @@ extension StaticFile {
}
// MARK: - Methods
extension StaticFile {
/// The `srcset` value offering every rendition of a responsive image, narrowest first, ending on the full-size file.
///
/// The renditions are named by the given closure, which conventionally gives the `large` one the bare file name and the narrower ones their
/// width as `srcset` files are usually named:
///
/// ```swift
/// static func portrait(_ width: ImageWidth) -> Self {
/// Self(width == .large ? "portrait" : "portrait-\(width.width)", in: "img/about", as: .jpg, .webp)
/// }
/// ```
/// - Parameters:
/// - fileExtension: the format the renditions are named in.
/// - version: the version token appended to each URL, or `nil` (the default) to leave them unversioned.
/// - rendition: the file naming a given width.
/// - Returns: the `srcset` value for that format.
static func srcSet(
for fileExtension: AssetExtension,
version: String? = nil,
rendition: (ImageWidth) -> Self
) -> String {
ImageWidth.allCases
.map { "\(rendition($0).urlPath(for: fileExtension, version: version)) \($0.width)w" }
.joined(separator: ", ")
}
}
// MARK: - Constants
extension StaticFile {