How can I get all assets from a document?

I’m trying to make a minimal viable static site generator with typst. So far the problem I’ve ran into is that assets cannot be part of sub-documents, like so:

#document("index.html")[
    = Hello world!
    #asset("wave.png")
]

My workaround for this is adding a show rule that no longer renders the asset, which stops the compiler error. However, I would still like to include the file somehow. My idea there is something along the lines of:

#let exports = ()
#document("index.html")[
    #show asset: it => exports.push(it.path, it.data)
    ...
]
...

#for (path, data) in exports {
    asset(path, data)
}

But I’m not sure how to make this work properly, given typst state management is not something I am good at.

Assuming the concept works, you would introduce state like this into your code:

#let exports = state("exports", ())
#document("index.html")[
    #show asset: it => exports.update(exports => {
        exports.push(it.path, it.data)
        exports
    })
    ...
]
...

#context for (path, data) in exports.get() {
    asset(path, data)
}
  • exports was replaced by a state, initialized to an empty array
  • where exports was modified, we have instead a call to update. I named the parameter exports – it is the array inside the state – but the name can be anything you choose. After modifying it, it is returned and that becomes the new state value.
  • where exports was read, a context is added and exports is replaced with exports.get().

Yes, that seems to work, thanks!

Why is the #context and exports.get() needed exactly?