Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .hugo/hugo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ ignoreFiles = ["quickstart/shared", "quickstart/python", "quickstart/js", "quick
github_subdir = "docs"
offlineSearch = true
version_menu = "Releases"
releases_url = "/genai-toolbox/releases.releases"
global_logo_url = "/genai-toolbox/"
[params.ui]
ul_show = 100
showLightDarkModeMenu = true
Expand Down
24 changes: 24 additions & 0 deletions .hugo/layouts/docs/section.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{{ define "main" }}
<div class="td-content">
<h1>{{ .Title }}</h1>
{{ with .Params.description }}<div class="lead">{{ . | markdownify }}</div>{{ end }}
<header class="article-meta">
{{ partial "taxonomy_terms_article_wrapper.html" . }}
{{ if (and (not .Params.hide_readingtime) (.Site.Params.ui.readingtime.enable)) }}
{{ partial "reading-time.html" . }}
{{ end }}
</header>
{{ .Content }}
{{ partial "section-index.html" . }}
{{ partial "pager.html" . }}
{{ if (and (not .Params.hide_feedback) (.Site.Params.ui.feedback.enable) (.Site.GoogleAnalytics)) }}
{{ partial "feedback.html" .Site.Params.ui.feedback }}
<br />
{{ end }}
{{ if (.Site.Params.DisqusShortname) }}
<br />
{{ partial "disqus-comment.html" . }}
{{ end }}
{{ partial "page-meta-lastmod.html" . }}
</div>
{{ end }}
24 changes: 24 additions & 0 deletions .hugo/layouts/docs/single.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{{ define "main" }}
<div class="td-content">
<h1>{{ .Title }}</h1>
{{ with .Params.description }}<div class="lead">{{ . | markdownify }}</div>{{ end }}
<header class="article-meta">
{{ partial "taxonomy_terms_article_wrapper.html" . }}
{{ if (and (not .Params.hide_readingtime) (.Site.Params.ui.readingtime.enable)) }}
{{ partial "reading-time.html" . }}
{{ end }}
</header>
{{ .Content }}
{{ partial "section-index.html" . }}
{{ partial "pager.html" . }}
{{ if (and (not .Params.hide_feedback) (.Site.Params.ui.feedback.enable) (.Site.GoogleAnalytics)) }}
{{ partial "feedback.html" .Site.Params.ui.feedback }}
<br />
{{ end }}
{{ if (.Site.Params.DisqusShortname) }}
<br />
{{ partial "disqus-comment.html" . }}
{{ end }}
{{ partial "page-meta-lastmod.html" . }}
</div>
{{ end }}
8 changes: 8 additions & 0 deletions .hugo/layouts/partials/hooks/body-end.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script>
document.addEventListener("DOMContentLoaded", function() {
const logoLink = document.querySelector('.navbar-brand');
if (logoLink) {
logoLink.href = "{{ .Site.Params.global_logo_url | default "/" }}";
}
});
</script>
5 changes: 4 additions & 1 deletion .hugo/layouts/partials/hooks/head-end.html
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
<script src='{{ .Site.BaseURL }}js/w3.js' type="application/x-javascript"></script>
<script src='{{ "js/w3.js" | relURL }}'></script>
{{ if not .Site.Params.disableMigrationBanner }}
<script src="{{ "js/migration-banner.js" | relURL }}"></script>
{{ end }}
63 changes: 59 additions & 4 deletions .hugo/layouts/partials/navbar-version-selector.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,66 @@
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
{{ .Site.Params.version_menu }}
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div w3-include-html="/genai-toolbox/releases.releases" w3-include-html-default='<a class="dropdown-item" href="/genai-toolbox/dev/">Dev</a>'></div>
<div class="dropdown-menu" id="version-dropdown-menu" aria-labelledby="navbarDropdown">
<div w3-include-html="{{ .Site.Params.releases_url }}" w3-include-html-default='<a class="dropdown-item" href="{{ .Site.Params.global_logo_url }}dev/">Dev</a>'></div>

<script>
// This must run after the w3.js script has loaded.
w3.includeHTML();
w3.includeHTML(function() {
const basePath = "{{ site.BaseURL | relURL }}";

function stripBase(path) {
if (path.startsWith(basePath)) return path.substring(basePath.length);
if (basePath === "/" && path.startsWith("/")) return path.substring(1);
return path.replace(/^\//, '');
}

document.getElementById('version-dropdown-menu').addEventListener('click', function(e) {
const link = e.target.closest('a.dropdown-item');
if (!link) return;
e.preventDefault();

let targetPath = link.pathname;
if (!targetPath.endsWith('/')) targetPath += '/';

let cleanCurrentPath = stripBase(window.location.pathname);
const allLinks = document.querySelectorAll('#version-dropdown-menu a.dropdown-item');
let currentVersionPrefix = "";

allLinks.forEach(a => {
let cleanVPath = stripBase(a.pathname);
if (!cleanVPath.endsWith('/')) cleanVPath += '/';
if (cleanVPath !== "" && cleanVPath !== "/" && cleanCurrentPath.startsWith(cleanVPath)) {
if (cleanVPath.length > currentVersionPrefix.length) {
currentVersionPrefix = cleanVPath;
}
}
});

let deepPath = cleanCurrentPath;
if (currentVersionPrefix !== "") {
deepPath = cleanCurrentPath.substring(currentVersionPrefix.length);
}
deepPath = deepPath.replace(/^\//, '');

const fullTargetPath = targetPath + deepPath;

// Perform a HEAD request to check if the deep route exists
fetch(fullTargetPath, { method: 'HEAD' })
.then(response => {
if (response.ok) {
// Page exists! Redirect to deep path
window.location.href = fullTargetPath;
} else {
// 404 or other error: Fallback to the version root
window.location.href = targetPath;
}
})
.catch(() => {
// If the fetch fails entirely, fallback to root
window.location.href = targetPath;
});
});
});
</script>
</div>
{{ end -}}
103 changes: 103 additions & 0 deletions .hugo/layouts/partials/pager.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{{ $curr := . }}
{{ $next := "" }}
{{ $prev := "" }}

{{/* 1. Calculate PREVIOUS */}}
{{ if .Parent }}
{{ $siblings := .Parent.Pages.ByWeight }}
{{ $currIndex := -1 }}

{{ range $index, $page := $siblings }}
{{ if eq $page.RelPermalink $curr.RelPermalink }}
{{ $currIndex = $index }}
{{ end }}
{{ end }}

{{ if gt $currIndex 0 }}
{{/* Preceding sibling (if it's a folder, this naturally points to its _index.md!) */}}
{{ $prev = index $siblings (sub $currIndex 1) }}
{{ else }}
{{/* First child, so Previous points up to the Parent folder */}}
{{ if ne .Parent.Type "home" }}
{{ $prev = .Parent }}
{{ end }}
{{ end }}
{{ end }}


{{/* 2. Calculate NEXT */}}
{{ if and .IsNode (gt (len .Pages) 0) }}
{{/* If it's a folder with children, Next dives into the first child */}}
{{ $next = index .Pages.ByWeight 0 }}
{{ else }}
{{/* Leaf page, or empty folder */}}
{{ if .Parent }}
{{ $siblings := .Parent.Pages.ByWeight }}
{{ $currIndex := -1 }}

{{ range $index, $page := $siblings }}
{{ if eq $page.RelPermalink $curr.RelPermalink }}
{{ $currIndex = $index }}
{{ end }}
{{ end }}

{{ if lt $currIndex (sub (len $siblings) 1) }}
{{/* Next sibling in the same folder */}}
{{ $next = index $siblings (add $currIndex 1) }}
{{ else }}
{{/* Last item in folder, step out and find the Parent's next sibling */}}
{{ $p := .Parent }}
{{ $foundNext := false }}

{{/* Check up to 3 directory levels up to find the next section */}}
{{ range seq 3 }}
{{ if and (not $foundNext) $p }}
{{ if $p.Parent }}
{{ $pSiblings := $p.Parent.Pages.ByWeight }}
{{ $pIndex := -1 }}
{{ range $index, $page := $pSiblings }}
{{ if eq $page.RelPermalink $p.RelPermalink }}
{{ $pIndex = $index }}
{{ end }}
{{ end }}

{{ if and (ge $pIndex 0) (lt $pIndex (sub (len $pSiblings) 1)) }}
{{ $next = index $pSiblings (add $pIndex 1) }}
{{ $foundNext = true }}
{{ else }}
{{ $p = $p.Parent }}
{{ end }}
{{ else }}
{{ $p = false }}
{{ end }}
{{ end }}
{{ end }}

{{ end }}
{{ end }}
{{ end }}

<!-- 3. Render the Buttons -->
{{ if or $prev $next }}
<nav class="mt-5 pt-4 border-top d-flex justify-content-between" aria-label="Page navigation">

<div>
{{ with $prev }}
<a href="{{ .RelPermalink }}" class="text-decoration-none">
<small class="text-muted d-block mb-1">&laquo; Previous</small>
<span class="text-body">{{ .Title }}</span>
</a>
{{ end }}
</div>

<div class="text-end">
{{ with $next }}
<a href="{{ .RelPermalink }}" class="text-decoration-none">
<small class="text-muted d-block mb-1">Next &raquo;</small>
<span class="text-body">{{ .Title }}</span>
</a>
{{ end }}
</div>

</nav>
{{ end }}
98 changes: 98 additions & 0 deletions .hugo/static/js/migration-banner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
document.addEventListener('DOMContentLoaded', function() {

// Setup CSS for the wrapper and the banner
var styleTag = document.createElement('style');
styleTag.innerHTML = `
.td-navbar .dropdown-menu {
z-index: 9999 !important;
}

.theme-banner-wrapper {
position: sticky;
z-index: 20;
padding-top: 15px; /* This is your gap! */
padding-bottom: 5px; /* Breathing room below the banner */
/* Uses Bootstrap's native body background variable, with white as fallback */
background-color: var(--bs-body-bg, #ffffff);
}

.theme-migration-banner {
background-color: #ebf3fc;
border: 1px solid #80a7e9;
color: #1c3a6b;
border-radius: 4px;
padding: 15px;
text-align: center;
width: 100%;
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
}

.theme-migration-banner a {
color: #4484f4;
text-decoration: underline;
font-weight: bold;
}

/* DARK MODE STYLING */
html[data-bs-theme="dark"] .theme-banner-wrapper,
body.dark .theme-banner-wrapper,
html.dark-mode .theme-banner-wrapper {
/* Uses Docsy's dark mode background fallback if var fails */
background-color: var(--bs-body-bg, #20252b);
}

html[data-bs-theme="dark"] .theme-migration-banner,
body.dark .theme-migration-banner,
html.dark-mode .theme-migration-banner {
background-color: #1a273b;
color: #e6efff;
box-shadow: 0 4px 6px rgba(0,0,0,0.3);
}

html[data-bs-theme="dark"] .theme-migration-banner a,
body.dark .theme-migration-banner a,
html.dark-mode .theme-migration-banner a {
color: #80a7e9;
}

/* Fallback for OS-level dark mode */
@media (prefers-color-scheme: dark) {
html:not([data-bs-theme="light"]):not(.light) .theme-banner-wrapper {
background-color: var(--bs-body-bg, #20252b);
}
html:not([data-bs-theme="light"]):not(.light) .theme-migration-banner {
background-color: #1a273b;
color: #e6efff;
box-shadow: 0 4px 6px rgba(0,0,0,0.3);
}
html:not([data-bs-theme="light"]):not(.light) .theme-migration-banner a {
color: #80a7e9;
}
}
`;
document.head.appendChild(styleTag);

// Create the Wrapper
var wrapper = document.createElement('div');
wrapper.id = 'migration-banner-wrapper';
wrapper.className = 'theme-banner-wrapper';

// Create the Banner
var banner = document.createElement('div');
banner.className = 'theme-migration-banner';
banner.innerHTML = '⚠️ <strong>Archived Docs:</strong> Visit <a href="https://mcp-toolbox.dev/">mcp-toolbox.dev</a> for the latest version.';
wrapper.appendChild(banner);

// Inject the wrapper into the center information column
var contentArea = document.querySelector('.td-content') || document.querySelector('main');
if (contentArea) {
contentArea.prepend(wrapper);
} else {
console.warn("Could not find the main content column to inject the banner.");
}

// Calculate navbar height synchronously to correctly offset the sticky wrapper
var navbar = document.querySelector('.td-navbar');
var navbarHeight = navbar ? navbar.offsetHeight : 64;
wrapper.style.top = navbarHeight + 'px';
});
Loading