Thank you, I hadn’t seen that path was available. It isn’t ideal though, since there is no API to get the path back to a string (and no way to get the original relative path back). I could however use the same technique shown in issue 7555 to pass both the relative path (as a string) and the absolute path as a virtual path object.
I have a working workaround now. Is it a bug that asset only accepts a string as its first argument?
// template.typ
#let image(src, width: auto, height: auto, path-cb: none, ..attrs) = {
if (path-cb != none) { [#metadata((src: src, path: path-cb(src))) <asset-load>] }
let size-attrs = if (width == auto and height == auto) {
(:)
} else {
(width: width, height: height)
}
html.img(src: str(src), ..size-attrs, ..attrs.named())
}
// site.typ
#document("/blog/index.html", include("/blog/index.typ"))
#context {
query(<asset-load>)
.dedup(key: a => a.value.path)
.map(a => asset(
// parse the path representation to extract it as a string
repr(a.value.path).slice(6, -2),
read(a.value.path, encoding: none)
))
.join()
}
// blog/index.typ
#import "template.typ"
// Requires boilerplate
#let image = image.with(path-cb: x => path(x))
#image("./image.png", height: 500, width: 500)