- CLAUDE.md: correct WASM raw size gate from 3 MB to 3.5 MB (matches size_test.go) - CLAUDE.md: document error handling (log.E) and file I/O (coreio.Local) conventions - Makefile: sync WASM_RAW_LIMIT to 3670016 (3.5 MB) to match size_test.go - Tests: add coverage for NewContextWithService, Attr through wrapper nodes, Unless(true), and Text.Render with i18n service — core package 95.8% → 99.4% No fmt.Errorf or os.ReadFile/os.WriteFile violations found. Co-Authored-By: Virgil <virgil@lethean.io>
3.6 KiB
3.6 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Agent instructions for go-html. Module path: forge.lthn.ai/core/go-html
Commands
go test ./... # Run all tests
go test -run TestName ./... # Single test
go test -short ./... # Skip slow WASM build test
go test -bench . ./... # Benchmarks
go test -bench . -benchmem ./... # Benchmarks with alloc stats
go vet ./... # Static analysis
GOOS=js GOARCH=wasm go build -ldflags="-s -w" -o gohtml.wasm ./cmd/wasm/ # WASM build
make wasm # WASM build with size gate
echo '{"H":"nav-bar","C":"main-content"}' | go run ./cmd/codegen/ # Codegen CLI
Architecture
See docs/architecture.md for full detail. Summary:
- Node interface:
Render(ctx *Context) string— El, Text, Raw, If, Unless, Each[T], EachSeq[T], Switch, Entitled - HLCRF Layout: Header/Left/Content/Right/Footer compositor with ARIA roles and deterministic
data-blockIDs. Variant string (e.g. "HCF", "HLCRF", "C") controls which slots render. Layouts nest via clone-on-render (thread-safe). - Responsive: Multi-variant breakpoint wrapper (
data-variantattributes), renders all variants in insertion order - Pipeline: Render → StripTags → go-i18n/reversal Tokenise → GrammarImprint (server-side only)
- Codegen: Web Component classes with closed Shadow DOM, generated at build time by
cmd/codegen/ - WASM:
cmd/wasm/exportsrenderToString()only — size gate: < 3.5 MB raw, < 1 MB gzip
Server/Client Split
Files guarded with //go:build !js are excluded from WASM:
pipeline.go— Imprint/CompareVariants usego-i18n/reversal(server-side only)cmd/wasm/register.go— encoding/json + codegen (replaced bycmd/codegen/CLI)
Critical WASM constraint: Never import encoding/json, text/template, or fmt in WASM-linked code (files without a !js build tag). Use string concatenation instead of fmt.Sprintf in layout.go, node.go, responsive.go, render.go, path.go, and context.go. The fmt package alone adds ~500 KB to the WASM binary.
Dependencies
forge.lthn.ai/core/go-i18n(replace directive →../go-i18n)forge.lthn.ai/core/go-inference(indirect, via go-i18n)- Both
go-i18nandgo-inferencemust be cloned alongside this repo for builds - Go 1.26+ required (uses
rangeover integers,iter.Seq,maps.Keys,slices.Collect)
Coding Standards
- UK English (colour, organisation, centre, behaviour, licence, serialise)
- All types annotated; use
anynotinterface{} - Tests use
testifyassert/require - Licence: EUPL-1.2 — add
// SPDX-Licence-Identifier: EUPL-1.2to new files - Safe-by-default: HTML escaping via
html.EscapeString()on Text nodes and attribute values, void element handling, entitlement deny-by-default - Deterministic output: sorted attributes on El nodes, reproducible block ID paths
- Errors: use
log.E("scope", "message", err)fromgo-log, neverfmt.Errorf - File I/O: use
coreio.Localfromgo-io, neveros.ReadFile/os.WriteFile - Commits: conventional commits +
Co-Authored-By: Virgil <virgil@lethean.io>
Test Conventions
Use table-driven subtests with t.Run(). Integration tests that use Text nodes must initialise i18n before rendering:
svc, _ := i18n.New()
i18n.SetDefault(svc)