class

Hwaro::Content::Hooks::ImageHooks

Inherits Hwaro::Core::Lifecycle::Hookable < Reference < Object

Constants

CONCURRENCY = 8

Max number of concurrent image processing fibers

Class methods

encode_settings(quality : Int32, lqip_width : Int32, lqip_quality : Int32) : String

The encode settings a width variant set depends on (besides the source): the JPEG quality and the LQIP knobs. Each stamp is per file, so the output format is already in the name it is kept under.

Source
find_closest_variant(url : String, width : Int32, format : String | Nil = nil) : Tuple(Int32, String) | Nil

The chosen variant as {actual_width, url}.

The width matters to the caller, not just the URL: no variant is ever upscaled, so a 900px source asked for 1024 resolves to the 900px file. resize_image() reported the REQUESTED width, which is what a template writes into <img width=…> — a number the browser then uses to lay out an image that is a different size.

Source
find_lqip(url : String) : Hash(String, String) | Nil
Source
format_map_readonly(format : String) : Hash(String, Hash(Int32, String)) | Nil

The format variants by original URL, read-only like resize_map_readonly; nil when none were generated.

Source
intrinsic_size(source : String) : Tuple(Int32, Int32) | Nil

Intrinsic {width, height} of source, read from its header once per version of the file.

Source
op_variant(url : String, source : String, width : Int32, height : Int32, op : String, anchor : String, page_path : String | Nil, format : String | Nil = nil) : Tuple(String, Int32, Int32) | Nil

The fill/crop variant of url (backed by source) as {variant_url, width, height}, written into the output directory on first use and reused while it is newer than the source. The name carries size, op and anchor (photo_400x300_fill_center.jpg), so no two requests share a file. The file is claimed for the build and, when page_path names the rendering page, recorded as that page's derived output so a warm --cache build that skips the page keeps it. nil when ops are off for this build or the variant can't be made.

Source
processing_active?

Source file behind url as of the last image:resize run, or nil when no image job covered it.

Source
render_image_source_changed?(paths : Array(String)) : Bool

Did any of paths (project-relative) back a size or a variant a render printed? The serve watcher escalates such a change to a rebuild, like a load_data() source.

Source
reprocess_changed_images(changed_paths : Array(String), config : Models::Config, output_dir : String, pages : Array(Models::Page) | Nil = nil) : Int32

The image:resize hook only runs on full builds, so modified image BYTES under serve's :static / :content_files change paths left the resized variants (and LQIP data) stale — the watcher only re-copied the original. Re-runs the resize pipeline for exactly the changed images and folds the results into the class-level maps.

pages (when given) also covers page-bundle assets: an image inside a page bundle publishes its variants under the owning page's URL, not its content-relative path.

Returns the number of variant sets regenerated.

Source
reset_render_lookups(ctx : Core::Lifecycle::BuildContext) : Nil
Source
resize_map_readonly

Read-only access to the resize map for the render phase. The map is populated once by the BeforeRender image:resize hook and is never mutated during rendering, so render workers can read it directly instead of paying a full .dup of the (potentially large, site-wide) map per image-bearing page and serializing on the mutex. Concurrent reads of the unmutated Hash under -Dpreview_mt are safe.

Source
resolve_source(url : String, config : Models::Config | Nil = nil) : String | Nil

Source file published at the site-absolute, decoded url (no base_path), or nil: a page-bundle asset, a [content.files] copy, then a static/ file — the order the resize jobs claim URLs in. config defaults to the running build's.

Source
reusable_widths(source_path : String, dest_dir : String, widths : Array(Int32), authored : Proc(String, Bool) | Nil = nil, encode_settings : String | Nil = nil, variant_ext : String | Nil = nil) : Hash(Int32, String) | Nil

Returns a width => filename map when every expected destination file already exists on disk with an mtime at least as new as the source (i.e. decoding/resizing would produce bit-identical output). Returns nil when any destination is missing, stale, or empty — caller then processes the image normally. Empty is checked so a killed serve mid-write doesn't leave a zero-byte file that would pass an mtime check and get served as a broken image.

Caller must also verify LQIP cache separately; LQIP can't be reconstructed from disk bytes.

Source
safe_dest_path?(path : String, resolved_output : String) : Bool

Verify destination directory is within output (dest may not exist yet)

Source
safe_source_path?(path : String, base : String) : Bool

Verify that a source path resolves within the expected base directory. Uses File.realpath to resolve symlinks before the boundary check.

Source
source_path_for(url : String) : String | Nil
Source
watch_render_source(url : String, & : String -> ) : Nil

The file behind a site-absolute url that a render just printed image-derived data from (a srcset, an LQIP, a dominant colour): the resize job's source, else the static/ location an image that does not exist yet would appear at. Also registers it with the serve watcher (see render_image_source_changed?). Yields every path the caller records as a --cache render input: the source, then the files that would publish under one of its variant names (authored_variant_paths).

Source

Instance methods

register_hooks(manager : Core::Lifecycle::Manager)
Source