This allows @import statements to be resolved in a set of user provided resources (e.g. from resources.FromString or css.ChromaStyles) before the assets filesystem.
The option also applies to css.PostCSS via the shared import inlining, and css.Sass requires the dartsass transpiler. The import context is part of the transformation cache key.
Fixes#15103
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Encode photo/picture hints (and the default) as YUV420 instead of YUV444,
keeping 444 for text/icon/drawing. Lossless stays 444.
This roughly halves the encoder's peak memory (42 -> 27 MiB/MP) and the
output size, while 444 remains available for sharp-edged content. A
3000x3000 image now needs ~239 MiB to encode, down from ~381 MiB (which
sat right at the 384 MiB WASM cap).
Closes#14987
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Before this commit, lossy compression with 100 quality meant lossless compression, leading to a big gap between 99 and 100.
This commit caps the lossy quality at 99, ensuring that lossy compression is always lossy.
Fixes#14981
The encode/decode is implemented in a WebAssembly module built from a
small C wrapper around libavif. Bundled libraries (statically linked,
compiled with the WASI SDK):
* libavif v1.4.1 (container + codec glue)
* libaom v3.14.1 (AV1 encoder + decoder)
* dav1d 1.5.3 (AV1 decoder)
* libyuv (Chromium pin) for color conversion
* parson for JSON message passing across the wasm boundary
HDR handling on the encoder:
* SDR images are written as BT.709 / sRGB / BT.601 (8-bit).
* 10-bit and up are written as BT.2020 primaries with PQ (SMPTE
ST 2084) transfer and BT.2020-NCL matrix coefficients, signalled
via CICP.
* Adobe-style SDR+gainmap inputs (e.g. Lightroom HDR exports) are
baked into a single true-HDR image in BT.2020/PQ at 10-bit, with
the CLLI (Content Light Level Information) box carried through so
HDR-capable clients can tone-map correctly.
Limitations:
* Animated input (animated WebP/GIF) is collapsed to its first frame
when re-encoded as AVIF; animated AVIF output is not yet supported.
Fixes#7837
A stale or removed resource used by js.Batch could panic while the esbuild import loader read its content during a rebuild. Return the read error through the loader so esbuild reports a normal build error and a later rebuild can recover when the file returns.
Closes#13737
When CSS imports assets via the file loader (fonts, images), the emitted
URLs were relative to the CSS output directory. That broke when the CSS
was inlined into HTML, since browsers then resolved the URLs against the
page rather than the CSS file.
Set esbuild's PublicPath to the CSS output directory joined with the
site base path so URLs work whether the CSS is published as a file or
inlined.
Fixes#14849
And be specific about which commit we use.
Hugo treat this as an upstream dependency, so we would appreciate that any bugs will be reported and fixed upstream.
See #14823
Allow CSS variables to be grouped under sub-paths and imported via
@import "hugo:vars/mobile" (or @use for Dart Sass), so callers can pass
nested dicts like:
{{ dict "primary-color" "blue" "mobile" (dict "primary-color" "red") }}
Top-level "hugo:vars" now skips nested map entries instead of emitting
garbage for them.
Fixes#14705
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Before this commit, we did dynamic loader resolution for CSS bundling for resources resolved by Hugo while any fallback to ESBuild would fall back to a (potentially) empty loaders config.
This revises the logic to always use a static list (see below) if `loaders` is not set. This should be easier do document and less confusing for the end user.
````
".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".avif",
".woff", ".woff2", ".ttf", ".eot", ".otf"
````
Fixes#14619
*- Dynamic pool sizing for WebP and Katex based on CPU count
- WebP decode: use RGB (3 bytes) for opaque images instead of RGBA (4 bytes)
- Add new imaging.config with new encoder method option; this is default 4 (what we had before), if have tested with value 2 for a 30% speedup on my MacBook, but that does sacrifice quality in some cases (quality/speed trade-off 0-6)
- Track hasAlpha in decode response to enable RGB optimization
- Scale image processing workers (1->2) on high-core machines
- Add WebP benchmark test
On my MacBook Pro M1 Pro, I now get these numbers compared to Hugo v0.152.0:
```
goos: darwin
goarch: arm64
pkg: github.com/gohugoio/hugo/internal/warpc
cpu: Apple M1 Pro
│ cmp152.bench │ fix-webpbench.bench │
│ sec/op │ sec/op vs base │
Webp-10 162.6m ± 32% 145.3m ± 21% -10.60% (p=0.026 n=6)
│ cmp152.bench │ fix-webpbench.bench │
│ B/op │ B/op vs base │
Webp-10 41.69Mi ± 0% 123.79Mi ± 0% +196.92% (p=0.002 n=6)
│ cmp152.bench │ fix-webpbench.bench │
│ allocs/op │ allocs/op vs base │
Webp-10 9.963k ± 3% 18.797k ± 2% +88.67% (p=0.002 n=6)
```
For general image resize benchmarks compared to Hugo v0.152.0 (note that that's not the result of this branch):
```bash
goos: darwin
goarch: arm64
pkg: github.com/gohugoio/hugo/resources/images
cpu: Apple M1 Pro
│ cmp152.bench │ fix-webpbench.bench │
│ sec/op │ sec/op vs base │
ImageResize-10 84.12m ± ∞ ¹ 40.70m ± ∞ ¹ -51.61% (p=0.029 n=4)
¹ need >= 6 samples for confidence interval at level 0.95
│ cmp152.bench │ fix-webpbench.bench │
│ B/op │ B/op vs base │
ImageResize-10 32.37Mi ± ∞ ¹ 29.25Mi ± ∞ ¹ -9.64% (p=0.029 n=4)
¹ need >= 6 samples for confidence interval at level 0.95
│ cmp152.bench │ fix-webpbench.bench │
│ allocs/op │ allocs/op vs base │
ImageResize-10 11.34k ± ∞ ¹ 12.03k ± ∞ ¹ +6.07% (p=0.029 n=4)
¹ need >= 6 samples for confidence interval at level 0.95
```
Closes#14370
Go's stdlid now has a maps package, which is very useful. We have been using imports on the form `xmaps "maps"`, but auto import tools doesn't handle this, which is annoying.
I have been thinking about this for some time, but have been holding back because of all the import changes. However, now is a good time to do this, with very little unmerged code.
The original idea of setting quality to 0 for lossless WebP was didn't allow a setting that made sense for both JPEG and WebP.
Note that the above didn't really work at all, so this should not break anything.