--- /dev/null
+// Lazy-load search index from JSON file
+async function loadSearchIndex() {
+ if (window.searchIndex) {
+ return window.searchIndex;
+ }
+ try {
+ const response = await fetch('/search-index.json');
+ if (!response.ok) throw new Error('Failed to load search index');
+ window.searchIndex = await response.json();
+ return window.searchIndex;
+ } catch (error) {
+ console.error('Error loading search index:', error);
+ return [];
+ }
+}
+
+// Filter articles by query (case-insensitive, max 5 results)
+function filterArticles(query, articles) {
+ if (!query.trim()) {
+ return [];
+ }
+ const lowerQuery = query.toLowerCase();
+ return articles
+ .filter(article =>
+ article.title.toLowerCase().includes(lowerQuery) ||
+ article.summary.toLowerCase().includes(lowerQuery)
+ )
+ .slice(0, 5);
+}
+
+// Register Alpine.js components
+document.addEventListener('alpine:init', () => {
+ // Desktop search modal component
+ Alpine.data('searchOverlay', () => ({
+ isOpen: false,
+ searchQuery: '',
+ filteredArticles: [],
+ allArticles: [],
+ indexLoaded: false,
+
+ async open() {
+ this.isOpen = true;
+ await this.ensureIndexLoaded();
+ this.$nextTick(() => {
+ const input = this.$el.querySelector('#search-input-desktop');
+ if (input) input.focus();
+ });
+ },
+
+ close() {
+ this.isOpen = false;
+ this.searchQuery = '';
+ this.filteredArticles = [];
+ },
+
+ async ensureIndexLoaded() {
+ if (!this.indexLoaded) {
+ this.allArticles = await loadSearchIndex();
+ this.indexLoaded = true;
+ }
+ },
+
+ filterArticles(query) {
+ this.searchQuery = query;
+ this.filteredArticles = filterArticles(query, this.allArticles);
+ },
+
+ handleEscape(event) {
+ if (event.key === 'Escape') {
+ this.close();
+ }
+ }
+ }));
+
+ // Mobile search component (integrated into hamburger menu)
+ Alpine.data('mobileSearch', () => ({
+ searchQuery: '',
+ filteredArticles: [],
+ allArticles: [],
+ indexLoaded: false,
+
+ async ensureIndexLoaded() {
+ if (!this.indexLoaded) {
+ this.allArticles = await loadSearchIndex();
+ this.indexLoaded = true;
+ }
+ },
+
+ filterArticles(query) {
+ this.searchQuery = query;
+ this.filteredArticles = filterArticles(query, this.allArticles);
+ }
+ }));
+
+ // Refactored 404 page component
+ Alpine.data('notFoundPage', () => ({
+ showEasterEgg: false,
+ searchQuery: '',
+ filteredArticles: [],
+ allArticles: [],
+ indexLoaded: false,
+
+ async init() {
+ await this.ensureIndexLoaded();
+ },
+
+ async ensureIndexLoaded() {
+ if (!this.indexLoaded) {
+ this.allArticles = await loadSearchIndex();
+ this.indexLoaded = true;
+ }
+ },
+
+ filterArticles(query) {
+ this.searchQuery = query;
+ this.filteredArticles = filterArticles(query, this.allArticles);
+ },
+
+ toggleEasterEgg() {
+ this.showEasterEgg = !this.showEasterEgg;
+ },
+
+ goToRandomArticle() {
+ if (this.allArticles.length > 0) {
+ const randomArticle = this.allArticles[Math.floor(Math.random() * this.allArticles.length)];
+ window.location.href = randomArticle.url;
+ }
+ }
+ }));
+});