'use strict'; var dictionary = []; // Define a global variable for spell-check suggestions {{ $searchDataFile := printf "%s.search-data.json" .Language.Lang }} {{ $searchData := resources.Get "search-data.json" | resources.ExecuteAsTemplate $searchDataFile . | resources.Minify | resources.Fingerprint }} (function () { const searchDataURL = '{{ $searchData.RelPermalink }}'; const input = document.querySelector('#book-search-input input'); const searchOverlay = document.querySelector('#search-overlay') const resultsContainer = document.querySelector('#book-search-hits'); const results = document.querySelector('#book-search-results ul'); const LIMIT_RESULTS = Infinity const MIN_INPUT_SIZE = 2 // SDK ✅ const documents = new Map() if (!input) { return } // Listeners input.addEventListener('focus', init); input.addEventListener('keyup', search); document.addEventListener('keypress', focusSearchFieldOnKeyPress); searchOverlay.addEventListener('click', () => { hideSearchBox() }) /** * @param {Event} event */ function focusSearchFieldOnKeyPress(event) { if (event.target.value !== undefined) { return; } if (input === document.activeElement) { return; } const characterPressed = String.fromCharCode(event.charCode); if (!isHotkey(characterPressed)) { return; } input.focus(); event.preventDefault(); } /** * @param {String} character * @returns {Boolean} */ function isHotkey(character) { const dataHotkeys = input.getAttribute('data-hotkeys') || ''; return dataHotkeys.indexOf(character) >= 0; } function init() { input.removeEventListener('focus', init); // init once input.required = true; fetch(searchDataURL) .then(pages => pages.json()) .then(pages => { window.lunrIdx = lunr(function() { this.ref('id') this.field('title', { boost: 10 }) this.field('content') this.field('href') this.metadataWhitelist = ['position'] for (const page of pages) { documents.set(page.id, page) this.add(page); } }) }) .then(() => input.required = false) .then(search); } function search() { const value = input.value?.trim(); if (input.required) { return; } while (results.firstChild) { results.removeChild(results.firstChild); } if (!value || value.length <= MIN_INPUT_SIZE) { hideSearchBox(); return; } // Split search terms and filter out very short terms for complex searches const terms = value.split(' '); const filteredTerms = terms.filter(term => { // If it's a single term search, use the original MIN_INPUT_SIZE if (terms.length === 1) return term.length > MIN_INPUT_SIZE; // For complex searches, require at least 3 characters return term.length > 2; }); // If all terms were filtered out, show no results if (!filteredTerms.length) { showSearchBox(); resultCard(`Not Found`, `Please use at least ${MIN_INPUT_SIZE} characters for single word searches, or 3 characters for complex searches`); return; } // Try different search strategies and combine results function getAllHits(terms, fuzzy) { const allHits = new Map(); // Use Map to avoid duplicates // Strategy 0: Exact title match (highest priority) // This ensures we find documents with exact title matches const titleQuery = terms.map(term => `+title:${term}`).join(' '); try { const titleHits = window.lunrIdx.search(titleQuery); titleHits.forEach(hit => { allHits.set(hit.ref, { ...hit, score: hit.score * 4.0, // Higher score than allWords matchType: 'title' }); }); } catch (e) { console.log('Title search error:', e); } // Strategy 1: All words match (high priority) // This ensures we find documents containing all search terms const allWordsQuery = terms.map(term => `+${term}`).join(' '); try { const allWordsHits = window.lunrIdx.search(allWordsQuery); allWordsHits.forEach(hit => { if (!allHits.has(hit.ref)) { allHits.set(hit.ref, { ...hit, score: hit.score * 3.0, matchType: 'allWords' }); } }); } catch (e) { console.log('All words search error:', e); } // Strategy 2: Word boundary match (high priority) // This ensures we match whole words const boundaryQuery = terms.map(term => `+${term}\\b`).join(' '); try { const boundaryHits = window.lunrIdx.search(boundaryQuery); boundaryHits.forEach(hit => { if (!allHits.has(hit.ref)) { allHits.set(hit.ref, { ...hit, score: hit.score * 2.0, matchType: 'boundary' }); } }); } catch (e) { console.log('Boundary search error:', e); } // Strategy 3: Prefix match (medium priority) // This helps with partial word matches const prefixQuery = terms.map(term => `+${term}*`).join(' '); try { const prefixHits = window.lunrIdx.search(prefixQuery); prefixHits.forEach(hit => { if (!allHits.has(hit.ref)) { allHits.set(hit.ref, { ...hit, score: hit.score * 1.5, matchType: 'prefix' }); } }); } catch (e) { console.log('Prefix search error:', e); } // Strategy 4: Fuzzy match (lowest priority) // This helps with typos and variations if (fuzzy) { const fuzzyQuery = terms.map(term => `+${term}~1`).join(' '); try { const fuzzyHits = window.lunrIdx.search(fuzzyQuery); fuzzyHits.forEach(hit => { if (!allHits.has(hit.ref)) { allHits.set(hit.ref, { ...hit, score: hit.score * 0.8, matchType: 'fuzzy' }); } }); } catch (e) { console.log('Fuzzy search error:', e); } } // Convert Map to Array and sort by score and match type return Array.from(allHits.values()) .sort((a, b) => { // First sort by score if (b.score !== a.score) { return b.score - a.score; } // If scores are equal, prioritize by match type const matchTypePriority = { 'title': 5, // Added title as highest priority 'allWords': 4, 'boundary': 3, 'prefix': 2, 'fuzzy': 1 }; return matchTypePriority[b.matchType] - matchTypePriority[a.matchType]; }) .slice(0, LIMIT_RESULTS); } // Try exact and prefix matches first let searchHits = getAllHits(filteredTerms, false); // If no results, try with fuzzy search if (!searchHits.length) { searchHits = getAllHits(filteredTerms, true); } const currentPathname = window.location.pathname; const filterSDK6 = isSdk6(currentPathname) ? searchHits : searchHits.filter($ => { const document = documents.get(Number($.ref)); if (!document || isSdk6(document.href)) return false; return true; }); showSearchBox(); if (!filterSDK6.length) { const suggestions = getSuggestionsForMisspelling(filteredTerms[0], dictionary); if (suggestions.length) { resultCard('Did you mean?', suggestions.map(s => `${s}`).join(', ')); } else { resultCard(`Not Found`, `Sorry, we couldn't find any matches. Try searching for a different keyword`); } return; } filterSDK6.forEach((hit) => { const document = documents.get(Number(hit.ref)); if (!document) return; if ((isSdk6(currentPathname) && isSdk7(document.href)) || (isSdk7(currentPathname) && isSdk6(document.href))) return; const highlightedContent = highlightContent(document.content, hit); resultCard(document.title, highlightedContent, document.href); }); } function isSdk6(href) { return href && href.includes('creator/development-guide') && !href.includes('sdk7') } function isSdk7(href) { return href && href.includes('creator/development-guide/sdk7') } function resultCard(title, content, href) { const li = element('