Files
bookhoard/templates/docs_templ.go
T
john-okeefe 647644fdce refactor: Consolidate script imports and update Alpine.js syntax in templates
This commit updates all generated template files and the header.templ source
to use consolidated script bundles and modern Alpine.js syntax.

Changes to templates/*.go (generated from .templ source files):
- Replace individual script imports (admin.js, toast.js, header.js, etc.)
  with single /static/main.js bundle
- Convert onclick attributes to Alpine.js @click directives for better
  integration with reactive components
- Add x-data attributes to body elements where needed for Alpine components
- Update event handlers to use Alpine.js syntax consistently

Changes to templates/header.templ source file:
- Add Alpine.js test div with x-data and x-init for debugging
- Reformat theme dropdown and user menu markup with proper indentation
- Maintain consistent Alpine.js directive formatting throughout

This change reduces the number of HTTP requests and ensures consistent
Alpine.js integration across all pages.
2026-03-09 20:58:46 -04:00

354 lines
34 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.977
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "fmt"
func DocsLayout(nav Navigation, doc Document, user User, currentPath string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\" class=\"dark\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(doc.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 11, Col: 21}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " - Bookhoard Documentation</title><link href=\"/static/style.css\" rel=\"stylesheet\"><link rel=\"stylesheet\" href=\"/static/highlight-dark.min.css\"><script src=\"/static/main.js\"></script></head>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 = []any{"theme-" + user.Theme + " page-docs bg-background-primary text-text-primary font-sans antialiased"}
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<body class=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var3).String())
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 1, Col: 0}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = Header(user, currentPath).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<!-- Mobile Menu Button --><button class=\"lg:hidden fixed top-4 left-4 z-50 bg-background-secondary border border-border rounded p-2 text-text-primary hover:bg-background-secondary/80\" onclick=\"toggleSidebar()\" aria-label=\"Toggle menu\"><svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\"></path></svg></button><!-- Search Results Overlay --><div id=\"search-results\" class=\"hidden fixed inset-0 bg-black/95 z-50 overflow-y-auto p-8 transition-opacity duration-200 ease-in-out\"></div><!-- Sidebar --><div class=\"sidebar fixed left-0 top-0 bottom-0 w-72 bg-background-secondary border-r border-border overflow-y-auto mt-16 lg:translate-x-0 transition-transform duration-300 ease-in-out\"><!-- Search --><div class=\"p-4 border-b border-border\"><input type=\"text\" class=\"search-input w-full px-3 py-2 rounded bg-background-primary text-text-primary border border-border focus:outline-none focus:ring-2 focus:ring-accent text-sm\" placeholder=\"Search documentation...\" id=\"docs-search\"></div><!-- Navigation Sections -->")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, section := range nav.Sections {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"nav-section mb-6\"><div class=\"nav-section-title font-semibold text-xs uppercase tracking-wider text-text-secondary px-4 py-3 cursor-pointer select-none flex items-center justify-between\" onclick=\"toggleSection(this)\"><span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(section.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 48, Col: 28}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</span> <svg class=\"w-4 h-4 transform transition-transform section-arrow\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\"></path></svg></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if section.Collapsed {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"nav-items hidden\" data-collapsed=\"true\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, item := range section.Items {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "<a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 templ.SafeURL
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinURLErrs(item.URL)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 56, Col: 27}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\" class=\"nav-item block py-2 px-4 pl-8 text-text-secondary hover:text-accent text-sm transition-colors no-underline\"><span class=\"mr-2\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(item.Icon)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 57, Col: 40}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 57, Col: 61}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<div class=\"nav-items\" data-collapsed=\"false\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, item := range section.Items {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 templ.SafeURL
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinURLErrs(item.URL)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 64, Col: 27}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "\" class=\"nav-item block py-2 px-4 pl-8 text-text-secondary hover:text-accent text-sm transition-colors no-underline\"><span class=\"mr-2\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(item.Icon)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 65, Col: 40}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 65, Col: 61}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</div><!-- Main Content --><main class=\"main-content lg:ml-72 p-8 max-w-4xl mx-auto\"><!-- Breadcrumb -->")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(doc.Breadcrumb) > 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "<nav class=\"breadcrumb flex gap-2 text-sm text-text-secondary mb-8\" aria-label=\"Breadcrumb\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for i, crumb := range doc.Breadcrumb {
if i > 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<span class=\"text-text-secondary/50\"></span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, " <a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var12 templ.SafeURL
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(crumb.URL)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 82, Col: 26}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "\" class=\"text-accent hover:underline no-underline\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(crumb.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 82, Col: 91}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</nav>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "<!-- Title --><h1 class=\"text-4xl font-bold mb-8 text-text-primary\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(doc.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 87, Col: 69}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "</h1><!-- Table of Contents -->")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(doc.TOC) > 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<details class=\"toc bg-background-secondary p-4 rounded-lg mb-8 border border-border\"><summary class=\"cursor-pointer hover:opacity-80 transition-opacity\"><strong class=\"text-text-primary font-semibold\">On this page</strong> <span class=\"ml-2 text-text-secondary text-xs\">▼</span></summary> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, item := range doc.TOC {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "<a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 templ.SafeURL
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinURLErrs("#" + item.Anchor)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 97, Col: 32}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\" class=\"toc-item block py-1 text-text-secondary hover:text-accent text-sm no-underline\" style=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templruntime.SanitizeStyleAttributeValues("margin-left: " + fmt.Sprintf("%drem", item.Level))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 99, Col: 66}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/docs.templ`, Line: 101, Col: 20}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</details>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "<!-- Content --><div class=\"prose prose-invert max-w-none\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = UnsafeHTML(doc.Content).ToComponent().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "</div></main><script>\n\t\t\t\t// Toggle sidebar section\n\t\t\t\tfunction toggleSection(el) {\n\t\t\t\t\tconst items = el.nextElementSibling;\n\t\t\t\t\tconst arrow = el.querySelector(\".section-arrow\");\n\t\t\t\t\tconst isCollapsed = items.getAttribute(\"data-collapsed\") === \"true\";\n\n\t\t\t\t\tif (isCollapsed) {\n\t\t\t\t\t\titems.classList.remove(\"hidden\");\n\t\t\t\t\t\titems.setAttribute(\"data-collapsed\", \"false\");\n\t\t\t\t\t\tarrow.style.transform = \"rotate(0deg)\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\titems.classList.add(\"hidden\");\n\t\t\t\t\t\titems.setAttribute(\"data-collapsed\", \"true\");\n\t\t\t\t\t\tarrow.style.transform = \"rotate(-90deg)\";\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Toggle sidebar on mobile\n\t\t\t\tfunction toggleSidebar() {\n\t\t\t\t\tconst sidebar = document.querySelector(\".sidebar\");\n\t\t\t\t\tsidebar.classList.toggle(\"open\");\n\t\t\t\t}\n\n\t\t\t\t// Highlight current page in nav\n\t\t\t\tdocument.addEventListener(\"DOMContentLoaded\", function () {\n\t\t\t\t\tconst currentPath = window.location.pathname;\n\t\t\t\t\tdocument.querySelectorAll(\".nav-item\").forEach((item) => {\n\t\t\t\t\t\tif (item.getAttribute(\"href\") === currentPath) {\n\t\t\t\t\t\t\titem.classList.add(\n\t\t\t\t\t\t\t\t\"text-accent\",\n\t\t\t\t\t\t\t\t\"bg-accent/10\",\n\t\t\t\t\t\t\t\t\"border-r-2\",\n\t\t\t\t\t\t\t\t\"border-accent\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t// Initialize syntax highlighting\n\t\t\t\t\tif (typeof hljs !== \"undefined\") {\n\t\t\t\t\t\thljs.highlightAll();\n\n\t\t\t\t\t\t// Add copy buttons to all code blocks\n\t\t\t\t\t\tdocument.querySelectorAll(\"pre code\").forEach((block) => {\n\t\t\t\t\t\t\tconst pre = block.parentElement;\n\t\t\t\t\t\t\tconst wrapper = document.createElement(\"div\");\n\t\t\t\t\t\t\twrapper.className = \"relative group\";\n\t\t\t\t\t\t\tpre.parentNode.insertBefore(wrapper, pre);\n\t\t\t\t\t\t\twrapper.appendChild(pre);\n\n\t\t\t\t\t\t\tconst button = document.createElement(\"button\");\n\t\t\t\t\t\t\tbutton.className =\n\t\t\t\t\t\t\t\t\"absolute top-2 right-2 bg-background-secondary text-text-secondary px-2 py-1 rounded text-xs opacity-0 group-hover:opacity-100 transition-opacity border border-border hover:text-accent\";\n\t\t\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\t\t\tbutton.onclick = async () => {\n\t\t\t\t\t\t\t\tawait navigator.clipboard.writeText(block.textContent);\n\t\t\t\t\t\t\t\tbutton.textContent = \"Copied!\";\n\t\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\t\t\t\t}, 2000);\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\twrapper.appendChild(button);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add copy buttons to all code blocks\n\t\t\t\t\tdocument.querySelectorAll(\"pre code\").forEach((block) => {\n\t\t\t\t\t\tconst pre = block.parentElement;\n\t\t\t\t\t\tconst wrapper = document.createElement(\"div\");\n\t\t\t\t\t\twrapper.className = \"relative group\";\n\t\t\t\t\t\tpre.parentNode.insertBefore(wrapper, pre);\n\t\t\t\t\t\twrapper.appendChild(pre);\n\n\t\t\t\t\t\tconst button = document.createElement(\"button\");\n\t\t\t\t\t\tbutton.className =\n\t\t\t\t\t\t\t\"absolute top-2 right-2 bg-background-secondary text-text-secondary px-2 py-1 rounded text-xs opacity-0 group-hover:opacity-100 transition-opacity border border-border hover:text-accent\";\n\t\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\t\tbutton.onclick = async () => {\n\t\t\t\t\t\t\tawait navigator.clipboard.writeText(block.textContent);\n\t\t\t\t\t\t\tbutton.textContent = \"Copied!\";\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\t\t\t}, 2000);\n\t\t\t\t\t\t};\n\t\t\t\t\t\twrapper.appendChild(button);\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// Add copy buttons to all code blocks\n\t\t\t\tdocument.querySelectorAll(\"pre code\").forEach((block) => {\n\t\t\t\t\tconst pre = block.parentElement;\n\t\t\t\t\tconst wrapper = document.createElement(\"div\");\n\t\t\t\t\twrapper.className = \"relative group\";\n\t\t\t\t\tpre.parentNode.insertBefore(wrapper, pre);\n\t\t\t\t\twrapper.appendChild(pre);\n\n\t\t\t\t\tconst button = document.createElement(\"button\");\n\t\t\t\t\tbutton.className =\n\t\t\t\t\t\t\"absolute top-2 right-2 bg-background-secondary text-text-secondary px-2 py-1 rounded text-xs opacity-0 group-hover:opacity-100 transition-opacity border border-border hover:text-accent\";\n\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\tbutton.onclick = async () => {\n\t\t\t\t\t\tawait navigator.clipboard.writeText(block.textContent);\n\t\t\t\t\t\tbutton.textContent = \"Copied!\";\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\t\t}, 2000);\n\t\t\t\t\t};\n\t\t\t\t\twrapper.appendChild(button);\n\t\t\t\t});\n\n\t\t\t\t// Search state\n\t\t\t\tlet idx;\n\t\t\t\tlet searchDocs = [];\n\n\t\t\t\t// Load index on page load\n\t\t\t\tfetch(\"/docs/search-index.json\")\n\t\t\t\t\t.then((r) => r.json())\n\t\t\t\t\t.then((data) => {\n\t\t\t\t\t\tidx = lunr(function () {\n\t\t\t\t\t\t\tthis.use(lunr.flex);\n\t\t\t\t\t\t\tthis.ref(\"id\");\n\t\t\t\t\t\t\tthis.field(\"title\", { boost: 10 });\n\t\t\t\t\t\t\tthis.field(\"content\", { boost: 1 });\n\t\t\t\t\t\t\tdata.forEach((doc) => this.add(doc));\n\t\t\t\t\t\t});\n\t\t\t\t\t\tsearchDocs = data;\n\t\t\t\t\t\tconsole.log(\"Search index loaded:\", data.length, \"documents\");\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => console.error(\"Failed to load search index:\", err));\n\n\t\t\t\t// Search input with debounce\n\t\t\t\tconst searchInput = document.getElementById(\"docs-search\");\n\t\t\t\tconst searchResultsDiv = document.getElementById(\"search-results\");\n\n\t\t\t\tlet debounceTimer;\n\n\t\t\t\tsearchInput.addEventListener(\"input\", (e) => {\n\t\t\t\t\tclearTimeout(debounceTimer);\n\t\t\t\t\tdebounceTimer = setTimeout(() => {\n\t\t\t\t\t\tconst query = e.target.value.trim();\n\n\t\t\t\t\t\tif (query.length < 2) {\n\t\t\t\t\t\t\tsearchResultsDiv.classList.add(\"hidden\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Search with fuzzy matching\n\t\t\t\t\t\tconst results = idx.search(query, {\n\t\t\t\t\t\t\tfields: { title: { boost: 10 }, content: 1 },\n\t\t\t\t\t\t\texpand: true,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Render results\n\t\t\t\t\t\trenderSearchResults(results, query);\n\t\t\t\t\t}, 150);\n\t\t\t\t});\n\n\t\t\t\t// Render search results\n\t\t\t\tfunction renderSearchResults(results, query) {\n\t\t\t\t\tif (results.length === 0) {\n\t\t\t\t\t\tsearchResultsDiv.innerHTML =\n\t\t\t\t\t\t\t'<div class=\"text-center py-8 text-text-secondary\">No results found</div>';\n\t\t\t\t\t\tsearchResultsDiv.classList.remove(\"hidden\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tsearchResultsDiv.innerHTML = results\n\t\t\t\t\t\t.map((r) => {\n\t\t\t\t\t\t\tconst doc = searchDocs.find((d) => d.id === r.ref);\n\t\t\t\t\t\t\tif (!doc) return \"\";\n\n\t\t\t\t\t\t\tconst snippet = getSnippet(doc.content, query);\n\n\t\t\t\t\t\t\treturn `\n\t\t\t\t\t\t\t<a href=\"${doc.url}\" class=\"block p-4 border-b border-border hover:bg-background-secondary text-text-primary no-underline\">\n\t\t\t\t\t\t\t\t<div class=\"font-semibold mb-2\">${doc.title}</div>\n\t\t\t\t\t\t\t\t<div class=\"text-sm text-text-secondary\">${snippet}...</div>\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t`;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join(\"\");\n\n\t\t\t\t\tsearchResultsDiv.classList.remove(\"hidden\");\n\t\t\t\t}\n\n\t\t\t\tfunction getSnippet(content, query) {\n\t\t\t\t\tconst words = query.toLowerCase().split(/\\s+/);\n\t\t\t\t\tconst contentLower = content.toLowerCase();\n\n\t\t\t\t\tfor (const word of words) {\n\t\t\t\t\t\tconst idx = contentLower.indexOf(word);\n\t\t\t\t\t\tif (idx !== -1) {\n\t\t\t\t\t\t\tconst start = Math.max(0, idx - 50);\n\t\t\t\t\t\t\tconst end = Math.min(content.length, idx + 100);\n\t\t\t\t\t\t\treturn \"...\" + content.substring(start, end) + \"...\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn content.substring(0, 150) + \"...\";\n\t\t\t\t}\n\n\t\t\t\t// Close search results when clicking outside\n\t\t\t\tdocument.addEventListener(\"click\", (e) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!searchResultsDiv.contains(e.target) &&\n\t\t\t\t\t\te.target !== searchInput\n\t\t\t\t\t) {\n\t\t\t\t\t\tsearchResultsDiv.classList.add(\"hidden\");\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// Close search on Escape key\n\t\t\t\tdocument.addEventListener(\"keydown\", (e) => {\n\t\t\t\t\tif (e.key === \"Escape\") {\n\t\t\t\t\t\tsearchResultsDiv.classList.add(\"hidden\");\n\t\t\t\t\t\tsearchInput.blur();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t</script><script>\n\t\t\t\t// Toggle sidebar on mobile\n\t\t\t\tfunction toggleSidebar() {\n\t\t\t\t\tconst sidebar = document.querySelector(\".sidebar\");\n\t\t\t\t\tsidebar.classList.toggle(\"open\");\n\t\t\t\t}\n\n\t\t\t\t// Highlight current page in nav\n\t\t\t\tdocument.addEventListener(\"DOMContentLoaded\", function () {\n\t\t\t\t\tconst currentPath = window.location.pathname;\n\t\t\t\t\tdocument.querySelectorAll(\".nav-item\").forEach((item) => {\n\t\t\t\t\t\tif (item.getAttribute(\"href\") === currentPath) {\n\t\t\t\t\t\t\titem.classList.add(\n\t\t\t\t\t\t\t\t\"text-accent\",\n\t\t\t\t\t\t\t\t\"bg-accent/10\",\n\t\t\t\t\t\t\t\t\"border-r-2\",\n\t\t\t\t\t\t\t\t\"border-accent\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t// Initialize syntax highlighting\n\t\t\t\t\tif (typeof hljs !== \"undefined\") {\n\t\t\t\t\t\thljs.highlightAll();\n\n\t\t\t\t\t\t// Add copy buttons to all code blocks\n\t\t\t\t\t\tdocument.querySelectorAll(\"pre code\").forEach((block) => {\n\t\t\t\t\t\t\tconst pre = block.parentElement;\n\t\t\t\t\t\t\tconst wrapper = document.createElement(\"div\");\n\t\t\t\t\t\t\twrapper.className = \"relative group\";\n\t\t\t\t\t\t\tpre.parentNode.insertBefore(wrapper, pre);\n\t\t\t\t\t\t\twrapper.appendChild(pre);\n\n\t\t\t\t\t\t\tconst button = document.createElement(\"button\");\n\t\t\t\t\t\t\tbutton.className =\n\t\t\t\t\t\t\t\t\"absolute top-2 right-2 bg-background-secondary text-text-secondary px-2 py-1 rounded text-xs opacity-0 group-hover:opacity-100 transition-opacity border border-border hover:text-accent\";\n\t\t\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\t\t\tbutton.onclick = async () => {\n\t\t\t\t\t\t\t\tawait navigator.clipboard.writeText(block.textContent);\n\t\t\t\t\t\t\t\tbutton.textContent = \"Copied!\";\n\t\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\t\t\t\t}, 2000);\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\twrapper.appendChild(button);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add copy buttons to all code blocks\n\t\t\t\t\tdocument.querySelectorAll(\"pre code\").forEach((block) => {\n\t\t\t\t\t\tconst pre = block.parentElement;\n\t\t\t\t\t\tconst wrapper = document.createElement(\"div\");\n\t\t\t\t\t\twrapper.className = \"relative group\";\n\t\t\t\t\t\tpre.parentNode.insertBefore(wrapper, pre);\n\t\t\t\t\t\twrapper.appendChild(pre);\n\n\t\t\t\t\t\tconst button = document.createElement(\"button\");\n\t\t\t\t\t\tbutton.className =\n\t\t\t\t\t\t\t\"absolute top-2 right-2 bg-background-secondary text-text-secondary px-2 py-1 rounded text-xs opacity-0 group-hover:opacity-100 transition-opacity border border-border hover:text-accent\";\n\t\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\t\tbutton.onclick = async () => {\n\t\t\t\t\t\t\tawait navigator.clipboard.writeText(block.textContent);\n\t\t\t\t\t\t\tbutton.textContent = \"Copied!\";\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\t\t\t}, 2000);\n\t\t\t\t\t\t};\n\t\t\t\t\t\twrapper.appendChild(button);\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\t// Add copy buttons to all code blocks\n\t\t\t\tdocument.querySelectorAll(\"pre code\").forEach((block) => {\n\t\t\t\t\tconst pre = block.parentElement;\n\t\t\t\t\tconst wrapper = document.createElement(\"div\");\n\t\t\t\t\twrapper.className = \"relative group\";\n\t\t\t\t\tpre.parentNode.insertBefore(wrapper, pre);\n\t\t\t\t\twrapper.appendChild(pre);\n\n\t\t\t\t\tconst button = document.createElement(\"button\");\n\t\t\t\t\tbutton.className =\n\t\t\t\t\t\t\"absolute top-2 right-2 bg-background-secondary text-text-secondary px-2 py-1 rounded text-xs opacity-0 group-hover:opacity-100 transition-opacity border border-border hover:text-accent\";\n\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\tbutton.onclick = async () => {\n\t\t\t\t\t\tawait navigator.clipboard.writeText(block.textContent);\n\t\t\t\t\t\tbutton.textContent = \"Copied!\";\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tbutton.textContent = \"Copy\";\n\t\t\t\t\t\t}, 2000);\n\t\t\t\t\t};\n\t\t\t\t\twrapper.appendChild(button);\n\t\t\t\t});\n\n\t\t\t\t// Search state\n\t\t\t\tlet idx;\n\t\t\t\tlet searchDocs = [];\n\n\t\t\t\t// Load index on page load\n\t\t\t\tfetch(\"/docs/search-index.json\")\n\t\t\t\t\t.then((r) => r.json())\n\t\t\t\t\t.then((data) => {\n\t\t\t\t\t\tidx = lunr(function () {\n\t\t\t\t\t\t\tthis.use(lunr.flex);\n\t\t\t\t\t\t\tthis.ref(\"id\");\n\t\t\t\t\t\t\tthis.field(\"title\", { boost: 10 });\n\t\t\t\t\t\t\tthis.field(\"content\", { boost: 1 });\n\t\t\t\t\t\t\tdata.forEach((doc) => this.add(doc));\n\t\t\t\t\t\t});\n\t\t\t\t\t\tsearchDocs = data;\n\t\t\t\t\t\tconsole.log(\"Search index loaded:\", data.length, \"documents\");\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err) => console.error(\"Failed to load search index:\", err));\n\n\t\t\t\t// Search input with debounce\n\t\t\t\tconst searchInput = document.getElementById(\"docs-search\");\n\t\t\t\tconst searchResultsDiv = document.getElementById(\"search-results\");\n\n\t\t\t\tlet debounceTimer;\n\n\t\t\t\tsearchInput.addEventListener(\"input\", (e) => {\n\t\t\t\t\tclearTimeout(debounceTimer);\n\t\t\t\t\tdebounceTimer = setTimeout(() => {\n\t\t\t\t\t\tconst query = e.target.value.trim();\n\n\t\t\t\t\t\tif (query.length < 2) {\n\t\t\t\t\t\t\tsearchResultsDiv.classList.add(\"hidden\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Search with fuzzy matching\n\t\t\t\t\t\tconst results = idx.search(query, {\n\t\t\t\t\t\t\tfields: { title: { boost: 10 }, content: 1 },\n\t\t\t\t\t\t\texpand: true,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Render results\n\t\t\t\t\t\trenderSearchResults(results, query);\n\t\t\t\t\t}, 150);\n\t\t\t\t});\n\n\t\t\t\t// Render search results\n\t\t\t\tfunction renderSearchResults(results, query) {\n\t\t\t\t\tif (results.length === 0) {\n\t\t\t\t\t\tsearchResultsDiv.innerHTML =\n\t\t\t\t\t\t\t'<div class=\"text-center py-8 text-text-secondary\">No results found</div>';\n\t\t\t\t\t\tsearchResultsDiv.classList.remove(\"hidden\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tsearchResultsDiv.innerHTML = results\n\t\t\t\t\t\t.map((r) => {\n\t\t\t\t\t\t\tconst doc = searchDocs.find((d) => d.id === r.ref);\n\t\t\t\t\t\t\tif (!doc) return \"\";\n\n\t\t\t\t\t\t\tconst snippet = getSnippet(doc.content, query);\n\n\t\t\t\t\t\t\treturn `\n\t\t\t\t\t\t\t<a href=\"${doc.url}\" class=\"block p-4 border-b border-border hover:bg-background-secondary text-text-primary no-underline\">\n\t\t\t\t\t\t\t\t<div class=\"font-semibold mb-2\">${doc.title}</div>\n\t\t\t\t\t\t\t\t<div class=\"text-sm text-text-secondary\">${snippet}...</div>\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t`;\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.join(\"\");\n\n\t\t\t\t\tsearchResultsDiv.classList.remove(\"hidden\");\n\t\t\t\t}\n\n\t\t\t\tfunction getSnippet(content, query) {\n\t\t\t\t\tconst words = query.toLowerCase().split(/\\s+/);\n\t\t\t\t\tconst contentLower = content.toLowerCase();\n\n\t\t\t\t\tfor (const word of words) {\n\t\t\t\t\t\tconst idx = contentLower.indexOf(word);\n\t\t\t\t\t\tif (idx !== -1) {\n\t\t\t\t\t\t\tconst start = Math.max(0, idx - 50);\n\t\t\t\t\t\t\tconst end = Math.min(content.length, idx + 100);\n\t\t\t\t\t\t\treturn \"...\" + content.substring(start, end) + \"...\";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn content.substring(0, 150) + \"...\";\n\t\t\t\t}\n\n\t\t\t\t// Close search results when clicking outside\n\t\t\t\tdocument.addEventListener(\"click\", (e) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!searchResultsDiv.contains(e.target) &&\n\t\t\t\t\t\te.target !== searchInput\n\t\t\t\t\t) {\n\t\t\t\t\t\tsearchResultsDiv.classList.add(\"hidden\");\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// Close search on Escape key\n\t\t\t\tdocument.addEventListener(\"keydown\", (e) => {\n\t\t\t\t\tif (e.key === \"Escape\") {\n\t\t\t\t\t\tsearchResultsDiv.classList.add(\"hidden\");\n\t\t\t\t\t\tsearchInput.blur();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t</script></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate