feat(wasm): add registerComponents export for WC codegen

Exposes gohtml.registerComponents(slotsJSON) to browser context.
Pure-Go buildComponentJS is testable without WASM; WASM glue uses
Function constructor for browser-side execution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude 2026-02-17 20:50:50 +00:00
parent 937c08d9ed
commit dcd55a434c
No known key found for this signature in database
GPG key ID: AF404715446AEB41
3 changed files with 62 additions and 1 deletions

View file

@ -50,9 +50,28 @@ func renderToString(_ js.Value, args []js.Value) any {
return layout.Render(ctx)
}
// registerComponentsJS wraps buildComponentJS for the WASM→JS bridge.
// Takes a JSON string of slot assignments, generates the WC bundle,
// and executes it in the browser via the Function constructor.
func registerComponentsJS(_ js.Value, args []js.Value) any {
if len(args) < 1 {
return js.ValueOf("error: slotsJSON argument required")
}
jsCode, err := buildComponentJS(args[0].String())
if err != nil {
return js.ValueOf("error: " + err.Error())
}
// Execute the generated WC definitions in the browser context.
// Uses the standard Function constructor — the normal Go WASM→JS pattern.
fn := js.Global().Call("Function", jsCode)
fn.Invoke()
return js.ValueOf(jsCode)
}
func main() {
js.Global().Set("gohtml", js.ValueOf(map[string]any{
"renderToString": js.FuncOf(renderToString),
"renderToString": js.FuncOf(renderToString),
"registerComponents": js.FuncOf(registerComponentsJS),
}))
select {}

18
cmd/wasm/register.go Normal file
View file

@ -0,0 +1,18 @@
package main
import (
"encoding/json"
"fmt"
"forge.lthn.ai/core/go-html/codegen"
)
// buildComponentJS takes a JSON slot map and returns the WC bundle JS string.
// This is the pure-Go part testable without WASM.
func buildComponentJS(slotsJSON string) (string, error) {
var slots map[string]string
if err := json.Unmarshal([]byte(slotsJSON), &slots); err != nil {
return "", fmt.Errorf("registerComponents: %w", err)
}
return codegen.GenerateBundle(slots)
}

24
cmd/wasm/register_test.go Normal file
View file

@ -0,0 +1,24 @@
//go:build !js
package main
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestBuildComponentJS_Good(t *testing.T) {
slotsJSON := `{"H":"nav-bar","C":"main-content"}`
js, err := buildComponentJS(slotsJSON)
require.NoError(t, err)
assert.Contains(t, js, "NavBar")
assert.Contains(t, js, "MainContent")
assert.Contains(t, js, "customElements.define")
}
func TestBuildComponentJS_Bad_InvalidJSON(t *testing.T) {
_, err := buildComponentJS("not json")
assert.Error(t, err)
}