let currentPage = 'home';
let searchIndex = [];
let isSearchOpen = false;
let searchResults = [];
const pages = {
'home': {
title: 'OSVM CLI - Home',
file: 'pages/home.html',
keywords: ['home', 'overview', 'introduction', 'getting started']
},
'installation': {
title: 'Installation Guide',
file: 'pages/installation.html',
keywords: ['install', 'setup', 'download', 'requirements']
},
'plugins': {
title: 'Plugin System',
file: 'pages/plugins.html',
keywords: ['plugins', 'extensions', 'commands', 'tools', 'themes']
},
'themes': {
title: 'Themes & Customization',
file: 'pages/themes.html',
keywords: ['themes', 'styling', 'customization', 'colors', 'appearance']
},
'ai-integration': {
title: 'AI Integration',
file: 'pages/ai.html',
keywords: ['ai', 'artificial intelligence', 'analysis', 'security', 'audit']
},
'mcp-servers': {
title: 'MCP Servers',
file: 'pages/mcp.html',
keywords: ['mcp', 'model context protocol', 'servers', 'blockchain', 'data']
},
'node-deployment': {
title: 'Node Deployment',
file: 'pages/deployment.html',
keywords: ['deployment', 'nodes', 'validators', 'rpc', 'ssh']
},
'api-reference': {
title: 'API Reference',
file: 'pages/api.html',
keywords: ['api', 'reference', 'commands', 'documentation']
}
};
function initNavigation() {
buildSearchIndex();
setupKeyboardShortcuts();
setupNavigationLinks();
setupSearchSystem();
const initialPage = getPageFromURL() || 'home';
navigateToPage(initialPage, false);
console.log('🧭 Navigation system initialized');
}
async function navigateToPage(pageId, addToHistory = true) {
if (!pages[pageId]) {
console.error(`Page not found: ${pageId}`);
return;
}
const page = pages[pageId];
if (addToHistory) {
const newURL = pageId === 'home' ? '/' : `/${pageId}`;
history.pushState({ page: pageId }, page.title, newURL);
}
document.title = page.title;
await startPageTransition();
try {
const content = await loadPageContent(page.file);
updatePageContent(content);
updateNavigationState(pageId);
await completePageTransition();
currentPage = pageId;
processPageCrossLinks();
console.log(`📄 Navigated to page: ${pageId}`);
} catch (error) {
console.error('Failed to load page:', error);
showErrorPage();
}
}
async function startPageTransition() {
const content = document.querySelector('.page-content');
if (content) {
content.classList.add('page-transition-out');
await new Promise(resolve => setTimeout(resolve, 150));
}
}
async function completePageTransition() {
const content = document.querySelector('.page-content');
if (content) {
content.classList.remove('page-transition-out');
content.classList.add('page-transition-in');
setTimeout(() => {
content.classList.remove('page-transition-in');
}, 300);
}
}
async function loadPageContent(filePath) {
const response = await fetch(filePath);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return await response.text();
}
function updatePageContent(content) {
const contentContainer = document.querySelector('.page-content');
if (contentContainer) {
contentContainer.innerHTML = content;
initializePageElements();
}
}
function updateNavigationState(activePageId) {
document.querySelectorAll('.nav-link').forEach(link => {
link.classList.remove('active');
if (link.dataset.page === activePageId) {
link.classList.add('active');
}
});
updateBreadcrumbs(activePageId);
}
function getPageFromURL() {
const path = window.location.pathname;
if (path === '/' || path === '/index.html') {
return 'home';
}
const pageId = path.replace(/^\//, '').replace(/\.html$/, '');
return pages[pageId] ? pageId : null;
}
function setupKeyboardShortcuts() {
document.addEventListener('keydown', (e) => {
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
e.preventDefault();
toggleSearch();
return;
}
if (e.key === 'Escape' && isSearchOpen) {
closeSearch();
return;
}
if (isSearchOpen) {
handleSearchKeyboard(e);
return;
}
if (e.altKey) {
switch (e.key) {
case '1':
e.preventDefault();
navigateToPage('home');
break;
case '2':
e.preventDefault();
navigateToPage('installation');
break;
case '3':
e.preventDefault();
navigateToPage('plugins');
break;
case '4':
e.preventDefault();
navigateToPage('themes');
break;
}
}
});
}
function setupNavigationLinks() {
document.addEventListener('click', (e) => {
const navLink = e.target.closest('[data-page]');
if (navLink) {
e.preventDefault();
const pageId = navLink.dataset.page;
navigateToPage(pageId);
}
const crossLink = e.target.closest('[data-cross-link]');
if (crossLink) {
e.preventDefault();
const pageId = crossLink.dataset.crossLink;
navigateToPage(pageId);
}
});
window.addEventListener('popstate', (e) => {
const pageId = e.state?.page || getPageFromURL() || 'home';
navigateToPage(pageId, false);
});
}
async function buildSearchIndex() {
searchIndex = [];
for (const [pageId, page] of Object.entries(pages)) {
try {
const content = await loadPageContent(page.file);
const tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
const textContent = tempDiv.textContent || tempDiv.innerText || '';
const entries = extractSearchEntries(textContent, pageId, page);
searchIndex.push(...entries);
} catch (error) {
console.warn(`Failed to index page ${pageId}:`, error);
}
}
console.log(`🔍 Search index built with ${searchIndex.length} entries`);
}
function extractSearchEntries(content, pageId, page) {
const entries = [];
entries.push({
title: page.title,
content: page.keywords.join(' '),
page: pageId,
type: 'page',
score: 100
});
const lines = content.split('\n');
let currentSection = '';
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
const headingMatch = line.match(/^#+\s+(.+)$/);
if (headingMatch) {
currentSection = headingMatch[1];
entries.push({
title: currentSection,
content: line,
page: pageId,
type: 'heading',
score: 80
});
continue;
}
const commandMatch = line.match(/\$\s+(osvm\s+.+?)(?:\s*#|$)/);
if (commandMatch) {
entries.push({
title: commandMatch[1],
content: `${currentSection} - ${line}`,
page: pageId,
type: 'command',
score: 90
});
continue;
}
if (line.length > 20 && line.length < 200) {
entries.push({
title: line.substring(0, 50) + (line.length > 50 ? '...' : ''),
content: line,
page: pageId,
type: 'content',
score: 50
});
}
}
return entries;
}
function initializePageElements() {
if (window.initCopyButtons) {
window.initCopyButtons();
}
if (window.initTabs) {
window.initTabs();
}
addMicroAnimations();
}
function addMicroAnimations() {
const animatedElements = document.querySelectorAll('.command-example, .feature-card, .code-block');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-in');
observer.unobserve(entry.target);
}
});
}, {
threshold: 0.1,
rootMargin: '50px'
});
animatedElements.forEach(el => {
el.classList.add('animate-ready');
observer.observe(el);
});
}
function processPageCrossLinks() {
const content = document.querySelector('.page-content');
if (!content) return;
const crossLinks = {
'plugin': 'plugins',
'plugins': 'plugins',
'theme': 'themes',
'themes': 'themes',
'AI': 'ai-integration',
'artificial intelligence': 'ai-integration',
'MCP': 'mcp-servers',
'Model Context Protocol': 'mcp-servers',
'deployment': 'node-deployment',
'install': 'installation',
'API': 'api-reference'
};
const walker = document.createTreeWalker(
content,
NodeFilter.SHOW_TEXT,
null,
false
);
const textNodes = [];
let node;
while (node = walker.nextNode()) {
if (node.parentElement.tagName !== 'A' &&
node.parentElement.tagName !== 'CODE' &&
node.parentElement.tagName !== 'PRE') {
textNodes.push(node);
}
}
textNodes.forEach(textNode => {
let content = textNode.textContent;
let hasChanges = false;
for (const [term, pageId] of Object.entries(crossLinks)) {
if (pageId !== currentPage && content.includes(term)) {
const regex = new RegExp(`\\b${term}\\b`, 'gi');
content = content.replace(regex, `<a href="#" data-cross-link="${pageId}" class="cross-link">$&</a>`);
hasChanges = true;
}
}
if (hasChanges) {
const wrapper = document.createElement('span');
wrapper.innerHTML = content;
textNode.parentNode.replaceChild(wrapper, textNode);
}
});
}
window.navigateToPage = navigateToPage;
window.initNavigation = initNavigation;