// Language selector (function () { var btn = document.querySelector('.lang-btn'); var popup = document.querySelector('.lang-popup'); if (!btn || !popup) return; btn.addEventListener('click', function (e) { e.stopPropagation(); popup.classList.toggle('open'); }); document.addEventListener('click', function () { popup.classList.remove('open'); }); popup.addEventListener('click', function (e) { var link = e.target.closest('[data-lang]'); if (!link) return; e.preventDefault(); var lang = link.getAttribute('data-lang'); localStorage.setItem('preferred-lang', lang); var basePath = document.documentElement.getAttribute('data-base-path') || ''; var path = window.location.pathname; // Strip base path prefix, replace lang, then re-add base path var pathWithoutBase = path.slice(basePath.length); var newPath = basePath + pathWithoutBase.replace(/^\/[a-z]{2}\//, '/' + lang + '/'); window.location.href = newPath; }); })(); // Theme toggle (function () { var btn = document.querySelector('.theme-toggle'); if (!btn) return; // Feather Icons: sun (light mode) and moon (dark mode) var sunSVG = ''; var moonSVG = ''; function getTheme() { var stored = localStorage.getItem('preferred-theme'); if (stored) return stored; return window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'; } function applyTheme(theme) { if (theme === 'light') { document.documentElement.setAttribute('data-theme', 'light'); } else { document.documentElement.removeAttribute('data-theme'); } btn.innerHTML = theme === 'light' ? sunSVG : moonSVG; } applyTheme(getTheme()); btn.addEventListener('click', function () { var current = getTheme(); var next = current === 'dark' ? 'light' : 'dark'; localStorage.setItem('preferred-theme', next); applyTheme(next); }); })(); // Mobile sidebar toggle (function () { var toggle = document.querySelector('.sidebar-toggle'); var sidebar = document.querySelector('.sidebar'); if (!toggle || !sidebar) return; toggle.addEventListener('click', function () { sidebar.classList.toggle('open'); }); document.addEventListener('click', function (e) { if (!sidebar.contains(e.target) && e.target !== toggle) { sidebar.classList.remove('open'); } }); })(); // Site search (⌘K / Ctrl+K) (function () { var overlay = document.getElementById('search-overlay'); var input = document.getElementById('search-input'); var resultsList = document.getElementById('search-results'); if (!overlay || !input || !resultsList) return; var searchBtn = document.querySelector('.search-btn'); var pagesData = null; // cached pages-data.json var activeIndex = -1; function getCurrentLang() { return document.documentElement.getAttribute('lang') || 'en'; } function getBasePath() { return document.documentElement.getAttribute('data-base-path') || ''; } function openSearch() { overlay.classList.add('open'); input.value = ''; resultsList.innerHTML = ''; activeIndex = -1; input.focus(); loadPagesData(); } function closeSearch() { overlay.classList.remove('open'); input.value = ''; resultsList.innerHTML = ''; activeIndex = -1; } function loadPagesData() { if (pagesData) return; var basePath = getBasePath(); fetch(basePath + '/pages-data.json') .then(function (res) { return res.json(); }) .then(function (data) { pagesData = data; }) .catch(function () { pagesData = []; }); } function escapeRegExp(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } function highlightText(text, query) { if (!query) return text; var escaped = escapeRegExp(query); var re = new RegExp('(' + escaped + ')', 'gi'); return text.replace(re, '$1'); } function buildSnippet(body, query) { if (!query || !body) return ''; var lower = body.toLowerCase(); var idx = lower.indexOf(query.toLowerCase()); var start, end, snippet; if (idx === -1) { snippet = body.substring(0, 120); } else { start = Math.max(0, idx - 40); end = Math.min(body.length, idx + query.length + 80); snippet = (start > 0 ? '...' : '') + body.substring(start, end) + (end < body.length ? '...' : ''); } return highlightText(snippet, query); } function search(query) { if (!pagesData || !query) { resultsList.innerHTML = ''; activeIndex = -1; return; } var lang = getCurrentLang(); var q = query.toLowerCase(); // Score and filter var scored = []; for (var i = 0; i < pagesData.length; i++) { var page = pagesData[i]; if (page.lang !== lang) continue; var score = 0; var titleLower = page.title.toLowerCase(); var bodyLower = (page.body || '').toLowerCase(); if (titleLower.indexOf(q) !== -1) { score += 10; // Bonus for exact title match if (titleLower === q) score += 5; } if (bodyLower.indexOf(q) !== -1) { score += 3; } if (page.section.toLowerCase().indexOf(q) !== -1) { score += 1; } if (score > 0) { scored.push({ page: page, score: score }); } } // Sort by score descending scored.sort(function (a, b) { return b.score - a.score; }); // Limit results var results = scored.slice(0, 20); if (results.length === 0) { resultsList.innerHTML = '