Route bindings (ghtmx)

The five verb attributes accept a handler symbol (hx-post={ handlers.CreateUser }, zero-parameter routes, path folded statically) or a generated constructor (hx-get={ ghtmxgen.GetUser(id) }, parameters percent-encoded), resolved at build time against routes discovered from Go source (FR-020/FR-021). Registrations the discoverer cannot resolve use the escape hatch: //ghtmx:route GET /admin/users/{id} handlers.Show, whose symbol may also name a method โ€” Handlers.Show or pkg.Handlers.Show. Handlers registered as method values (r.Get("/users", h.ListUsers)) are discovered whenever the receiver's type is named in the same function. A method is not a symbol a template can name, so these routes bind through their generated central symbols, which fold the dot away: hx-get={ ghtmxgen.HandlersListUsersPath } for a route without parameters, hx-get={ ghtmxgen.HandlersGetUser(id) } for one with. A package whose routes are served under a mount prefix declares it once with //ghtmx:routeprefix /admin/user โ€” a sub-application mounted at a variable prefix cannot be recognised syntactically, so every route the package registers, discovered or annotated, is composed under the declared prefix (FR-013). The prefix must be static; one per package. Annotated paths are relative to it, so adopting the directive means shortening annotations that already spell the mount point โ€” an annotation left absolute composes twice. An annotation may carry a trailing nav marker (//ghtmx:route GET /audit handlers.AuditLog nav) declaring a navigation-only route โ€” reached by <a href> or a native form post โ€” which exempts it from the GHTMX-W0104 unbound-route warning. Other hx-* attributes are validated against the pinned htmx version's surface (internal/htmxsurface).

Verified by: examples/hx-bindings, examples/crud, internal/analyzer, internal/routes, conformance.