docs: add sticky header support for documentation pages
- Add CSS rules to web/static/input.css for header positioning - Header is sticky only on /docs pages via .page-docs body class - Add page-docs class to body element in templates/docs.templ - Non-docs pages have static header position
This commit is contained in:
1 parent
d9c6be1429
commit
79373dd225
5 files changed
+41
-527
No files matched your search
+11
-162
@@ -18,7 +18,7 @@ templ DocsLayout(nav Navigation, doc Document, user User, currentPath string) {
|
||||
<script src="/static/lunr-flex.min.js"></script>
|
||||
<script src="/static/header.js"></script>
|
||||
</head>
|
||||
<body class={ "theme-" + user.Theme + " bg-background-primary text-text-primary font-sans antialiased" }>
|
||||
<body class={ "theme-" + user.Theme + " page-docs bg-background-primary text-text-primary font-sans antialiased" }>
|
||||
@Header(user, currentPath)
|
||||
<!-- Mobile Menu Button -->
|
||||
<button
|
||||
@@ -35,7 +35,7 @@ templ DocsLayout(nav Navigation, doc Document, user User, currentPath string) {
|
||||
<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 z-40 mt-16 lg:translate-x-0 transition-transform duration-300 ease-in-out">
|
||||
<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
|
||||
@@ -96,11 +96,14 @@ templ DocsLayout(nav Navigation, doc Document, user User, currentPath string) {
|
||||
|
||||
<!-- Title -->
|
||||
<h1 class="text-4xl font-bold mb-8 text-text-primary">{ doc.Title }</h1>
|
||||
|
||||
|
||||
<!-- Table of Contents -->
|
||||
if len(doc.TOC) > 0 {
|
||||
<div class="toc bg-background-secondary p-4 rounded-lg mb-8 border border-border">
|
||||
<strong class="block mb-2 text-text-primary font-semibold">On this page</strong>
|
||||
<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>
|
||||
for _, item := range doc.TOC {
|
||||
<a
|
||||
href={ "#" + item.Anchor }
|
||||
@@ -110,7 +113,7 @@ templ DocsLayout(nav Navigation, doc Document, user User, currentPath string) {
|
||||
{ item.Title }
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</details>
|
||||
}
|
||||
|
||||
<!-- Content -->
|
||||
@@ -143,14 +146,6 @@ templ DocsLayout(nav Navigation, doc Document, user User, currentPath string) {
|
||||
sidebar.classList.toggle('open');
|
||||
}
|
||||
|
||||
// Close sidebar when clicking main content on mobile
|
||||
document.querySelector('.main-content')?.addEventListener('click', () => {
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
if (window.innerWidth < 1024) {
|
||||
sidebar.classList.remove('open');
|
||||
}
|
||||
});
|
||||
|
||||
// Highlight current page in nav
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const currentPath = window.location.pathname;
|
||||
@@ -163,7 +158,7 @@ templ DocsLayout(nav Navigation, doc Document, user User, currentPath string) {
|
||||
// Initialize syntax highlighting
|
||||
if (typeof hljs !== 'undefined') {
|
||||
hljs.highlightAll();
|
||||
|
||||
|
||||
// Add copy buttons to all code blocks
|
||||
document.querySelectorAll('pre code').forEach((block) => {
|
||||
const pre = block.parentElement;
|
||||
@@ -331,160 +326,14 @@ templ DocsLayout(nav Navigation, doc Document, user User, currentPath string) {
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
|
||||
templ DocsLayoutWithExplorer(nav Navigation, doc Document, user User, explorer APIExplorerData, currentPath string) {
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{ doc.Title } - Bookhoard Documentation</title>
|
||||
<link href="/static/style.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/static/highlight-dark.min.css">
|
||||
<script src="/static/highlight.min.js"></script>
|
||||
<script src="/static/lunr.min.js"></script>
|
||||
<script src="/static/lunr-flex.min.js"></script>
|
||||
<script src="/static/header.js"></script>
|
||||
</head>
|
||||
<body class={ "theme-" + user.Theme + " bg-background-primary text-text-primary font-sans antialiased" }>
|
||||
@Header(user, currentPath)
|
||||
<!-- 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-4 lg: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 z-40 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 -->
|
||||
for _, section := range nav.Sections {
|
||||
<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>{ section.Title }</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 section.Collapsed {
|
||||
<div class="nav-items hidden" data-collapsed="true">
|
||||
for _, item := range section.Items {
|
||||
<a href={ item.URL } 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">{ item.Icon }</span>{ item.Title }
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
} else {
|
||||
<div class="nav-items" data-collapsed="false">
|
||||
for _, item := range section.Items {
|
||||
<a href={ item.URL } 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">{ item.Icon }</span>{ item.Title }
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content lg:ml-72 p-4 lg:p-8 max-w-4xl mx-auto">
|
||||
<!-- Breadcrumb -->
|
||||
if len(doc.Breadcrumb) > 0 {
|
||||
<nav class="breadcrumb flex flex-wrap gap-2 text-sm text-text-secondary mb-8" aria-label="Breadcrumb">
|
||||
for i, crumb := range doc.Breadcrumb {
|
||||
if i > 0 {
|
||||
<span class="text-text-secondary/50">›</span>
|
||||
}
|
||||
<a href={ crumb.URL } class="text-accent hover:underline no-underline">{ crumb.Title }</a>
|
||||
}
|
||||
</nav>
|
||||
}
|
||||
|
||||
<!-- Title -->
|
||||
<h1 class="text-3xl lg:text-4xl font-bold mb-6 lg:mb-8 text-text-primary">{ doc.Title }</h1>
|
||||
|
||||
<!-- Table of Contents -->
|
||||
if len(doc.TOC) > 0 {
|
||||
<div class="toc bg-background-secondary p-4 rounded-lg mb-6 lg:mb-8 border border-border lg:static">
|
||||
<strong class="block mb-2 text-text-primary font-semibold">On this page</strong>
|
||||
for _, item := range doc.TOC {
|
||||
<a
|
||||
href={ "#" + item.Anchor }
|
||||
class="toc-item block py-1 text-text-secondary hover:text-accent text-sm no-underline"
|
||||
style={ "margin-left: " + fmt.Sprintf("%drem", item.Level) }
|
||||
>
|
||||
{ item.Title }
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Content -->
|
||||
<div class="prose prose-invert prose-sm lg:prose-base max-w-none">
|
||||
@UnsafeHTML(doc.Content).ToComponent()
|
||||
</div>
|
||||
|
||||
<!-- API Explorer -->
|
||||
@APIExplorer(explorer)
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// Toggle sidebar section
|
||||
function toggleSection(el) {
|
||||
const items = el.nextElementSibling;
|
||||
const arrow = el.querySelector('.section-arrow');
|
||||
const isCollapsed = items.getAttribute('data-collapsed') === 'true';
|
||||
|
||||
if (isCollapsed) {
|
||||
items.classList.remove('hidden');
|
||||
items.setAttribute('data-collapsed', 'false');
|
||||
arrow.style.transform = 'rotate(0deg)';
|
||||
} else {
|
||||
items.classList.add('hidden');
|
||||
items.setAttribute('data-collapsed', 'true');
|
||||
arrow.style.transform = 'rotate(-90deg)';
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle sidebar on mobile
|
||||
function toggleSidebar() {
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
sidebar.classList.toggle('open');
|
||||
}
|
||||
|
||||
// Close sidebar when clicking main content on mobile
|
||||
document.querySelector('.main-content')?.addEventListener('click', () => {
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
if (window.innerWidth < 1024) {
|
||||
sidebar.classList.remove('open');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Highlight current page in nav
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const currentPath = window.location.pathname;
|
||||
|
||||
+8
-356
@@ -50,7 +50,7 @@ func DocsLayout(nav Navigation, doc Document, user User, currentPath string) tem
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 = []any{"theme-" + user.Theme + " bg-background-primary text-text-primary font-sans antialiased"}
|
||||
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
|
||||
@@ -76,7 +76,7 @@ func DocsLayout(nav Navigation, doc Document, user User, currentPath string) tem
|
||||
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 z-40 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 -->")
|
||||
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
|
||||
}
|
||||
@@ -282,7 +282,7 @@ func DocsLayout(nav Navigation, doc Document, user User, currentPath string) tem
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if len(doc.TOC) > 0 {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "<div class=\"toc bg-background-secondary p-4 rounded-lg mb-8 border border-border\"><strong class=\"block mb-2 text-text-primary font-semibold\">On this page</strong> ")
|
||||
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
|
||||
}
|
||||
@@ -294,7 +294,7 @@ func DocsLayout(nav Navigation, doc Document, user User, currentPath string) tem
|
||||
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: `docs.templ`, Line: 106, Col: 32}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 109, Col: 32}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -307,7 +307,7 @@ func DocsLayout(nav Navigation, doc Document, user User, currentPath string) tem
|
||||
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: `docs.templ`, Line: 108, Col: 66}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 111, Col: 66}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -320,7 +320,7 @@ func DocsLayout(nav Navigation, doc Document, user User, currentPath string) tem
|
||||
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: `docs.templ`, Line: 110, Col: 20}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 113, Col: 20}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
@@ -331,7 +331,7 @@ func DocsLayout(nav Navigation, doc Document, user User, currentPath string) tem
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "</details>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@@ -344,355 +344,7 @@ func DocsLayout(nav Navigation, doc Document, user User, currentPath string) tem
|
||||
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// Close sidebar when clicking main content on mobile\n\t\t\t\tdocument.querySelector('.main-content')?.addEventListener('click', () => {\n\t\t\t\t\tconst sidebar = document.querySelector('.sidebar');\n\t\t\t\t\tif (window.innerWidth < 1024) {\n\t\t\t\t\t\tsidebar.classList.remove('open');\n\t\t\t\t\t}\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('text-accent', 'bg-accent/10', 'border-r-2', 'border-accent');\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// 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\t\t\t\t\t\t\n\t\t\t\t\t\tconst button = document.createElement('button');\n\t\t\t\t\t\tbutton.className = '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\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\t\t\t\t\t\t\n\t\t\t\t\t\tconst button = document.createElement('button');\n\t\t\t\t\t\tbutton.className = '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\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\t\t\t\t\t\t\n\t\t\t\t\t\tconst button = document.createElement('button');\n\t\t\t\t\t\tbutton.className = '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\tLine truncated
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func DocsLayoutWithExplorer(nav Navigation, doc Document, user User, explorer APIExplorerData, 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_Var18 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var18 == nil {
|
||||
templ_7745c5c3_Var18 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "<!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_Var19 string
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(doc.Title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 344, Col: 21}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, " - Bookhoard Documentation</title><link href=\"/static/style.css\" rel=\"stylesheet\"><link rel=\"stylesheet\" href=\"/static/highlight-dark.min.css\"><script src=\"/static/highlight.min.js\"></script><script src=\"/static/lunr.min.js\"></script><script src=\"/static/lunr-flex.min.js\"></script><script src=\"/static/header.js\"></script></head>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var20 = []any{"theme-" + user.Theme + " bg-background-primary text-text-primary font-sans antialiased"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var20...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<body class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var21 string
|
||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var20).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "\">")
|
||||
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, 42, "<!-- 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-4 lg: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 z-40 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, 43, "<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_Var22 string
|
||||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(section.Title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 388, Col: 28}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "</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, 45, "<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, 46, "<a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var23 templ.SafeURL
|
||||
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinURLErrs(item.URL)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 396, Col: 27}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "\" 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_Var24 string
|
||||
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(item.Icon)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 397, Col: 40}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "</span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var25 string
|
||||
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 397, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "</a>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "<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, 52, "<a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var26 templ.SafeURL
|
||||
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinURLErrs(item.URL)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 404, Col: 27}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "\" 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_Var27 string
|
||||
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(item.Icon)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 405, Col: 40}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "</span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var28 string
|
||||
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 405, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "</a>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "</div><!-- Main Content --><main class=\"main-content lg:ml-72 p-4 lg: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, 59, "<nav class=\"breadcrumb flex flex-wrap 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, 60, "<span class=\"text-text-secondary/50\">›</span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, " <a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var29 templ.SafeURL
|
||||
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinURLErrs(crumb.URL)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 423, Col: 26}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "\" class=\"text-accent hover:underline no-underline\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var30 string
|
||||
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(crumb.Title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 423, Col: 91}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "</a>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "</nav>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "<!-- Title --><h1 class=\"text-3xl lg:text-4xl font-bold mb-6 lg:mb-8 text-text-primary\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var31 string
|
||||
templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(doc.Title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 429, Col: 89}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "</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, 67, "<div class=\"toc bg-background-secondary p-4 rounded-lg mb-6 lg:mb-8 border border-border lg:static\"><strong class=\"block mb-2 text-text-primary font-semibold\">On this page</strong> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, item := range doc.TOC {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, "<a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var32 templ.SafeURL
|
||||
templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinURLErrs("#" + item.Anchor)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 437, Col: 32}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 69, "\" 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_Var33 string
|
||||
templ_7745c5c3_Var33, 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: `docs.templ`, Line: 439, Col: 66}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 70, "\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var34 string
|
||||
templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(item.Title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `docs.templ`, Line: 441, Col: 20}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 71, "</a>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 72, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 73, "<!-- Content --><div class=\"prose prose-invert prose-sm lg:prose-base 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, 74, "</div><!-- API Explorer -->")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = APIExplorer(explorer).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 75, "</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// Close sidebar when clicking main content on mobile\n\t\t\t\tdocument.querySelector('.main-content')?.addEventListener('click', () => {\n\t\t\t\t\tconst sidebar = document.querySelector('.sidebar');\n\t\t\t\t\tif (window.innerWidth < 1024) {\n\t\t\t\t\t\tsidebar.classList.remove('open');\n\t\t\t\t\t}\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('text-accent', 'bg-accent/10', 'border-r-2', 'border-accent');\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// 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\t\t\t\t\t\t\n\t\t\t\t\t\tconst button = document.createElement('button');\n\t\t\t\t\t\tbutton.className = '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\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\t\t\t\t\t\t\n\t\t\t\t\t\tconst button = document.createElement('button');\n\t\t\t\t\t\tbutton.className = '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\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\t\t\t\t\t\t\n\t\t\t\t\t\tconst button = document.createElement('button');\n\t\t\t\t\t\tbutton.className = '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\tLine truncated
|
||||
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('text-accent', 'bg-accent/10', 'border-r-2', 'border-accent');\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\t\t\t\t\t\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\t\t\t\t\t\t\n\t\t\t\t\t\tconst button = document.createElement('button');\n\t\t\t\t\t\tbutton.className = '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\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\t\t\t\t\t\t\n\t\t\t\t\t\tconst button = document.createElement('button');\n\t\t\t\t\t\tbutton.className = '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\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\t\t\t\t\t\t\n\t\t\t\t\t\tconst button = document.createElement('button');\n\t\t\t\t\t\tbutton.className = '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\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\tthisLine truncated
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user