Customizable Pipes (especially for JS resources)

I’m attempting to build a process whereby I can easily mount hydratable Svelte components (but this could apply to any number of libraries) into my templates. While not directly related to the idea of an island, it is largely inspired by the demos in 11ty’s is-land plugin.

An example of such a component being loaded into an 11ty template can be found here: is-land/demo-svelte.html at main · 11ty/is-land · GitHub. What you can see there is the use of a custom filter in 11ty built to compile Svelte components.

I would love to do something similar with Hugo. My first thought was to use the js.Build. It’s so powerful, and provides really important features like shims, parameters, etc. The only problem is that I can’t customize the actual build process, as well as the results returned by the script.

For example, I imagine calling such a component as such:

{{ $calcComponent := resources.Get "components/Calculator.svelte" | js.Build (dict "params" (dict "strings" (dict "calculator" (i18n "calculator")))) }}

The custom build script would be required to return a consistent shape of some variety, one of which could be a generic details or metadata property which would be a dictionary with whatever non-conventional items the custom build script needed to return.

It would then be used in the template as such:

<script src="{{ $calcComponent.RelPermalink }}"></script>
<style>
  {{ $calcComponent.metadata.css | safeCSS }}
</style>
{{ $calcComponent.metadata.html | safeHTML }}

I’m not sure if js.Build would be immediately appropriate for this since I’m not sure that ESBuild provides this level of customization to the build output, but js.Build’s API is super close to what I’m imagining here, which is why I’ve used it as a starting point.

Several topics that seem related:

Here’s a blog post from someone wanting something similar: Hugo, Tailwind, Svelte - luit.eu

So, the current showstopper for this is that Hugo currently cannot execute JavaScript. So, while ESBuild is written with Go, it’s JavaScript plugins runs in … JavaScript (which I assume is the case with any plugin for Svelte, Vue etc.)

Off topic, but you might find value with AlpineJS

https://alpinejs.dev/start-here