PageSourceSearch

https://liuchang.men/js/third-party/search/local-search.js

js liuchang.men collected 2026-09-25 22:36:29 UTC 3,572 bytes, 98 lines download raw bytes

vendor: 3,572 bytes, lines 1-98
1/* global CONFIG, NexT, pjax, LocalSearch */
2
3document.addEventListener('DOMContentLoaded', () => {
4  if (!CONFIG.path) {
5    // Search DB path
6    console.warn('`hexo-generator-searchdb` plugin is not installed!');
7    return;
8  }
9  const localSearch = new LocalSearch({
10    path             : CONFIG.path,
11    top_n_per_article: CONFIG.localsearch.top_n_per_article,
12    unescape         : CONFIG.localsearch.unescape
13  });
14
15  const input = document.querySelector('.search-input');
16  const container = document.querySelector('.search-result-container');
17
18  const inputEventFunction = () => {
19    if (!localSearch.isfetched) return;
20    const searchText = input.value.trim().toLowerCase();
21    const keywords = searchText.split(/[-\s]+/);
22    let resultItems = [];
23    if (searchText.length > 0) {
24      // Perform local searching
25      resultItems = localSearch.getResultItems(keywords);
26    }
27    if (keywords.length === 1 && keywords[0] === '') {
28      container.innerHTML = '<div class="search-result-icon"><i class="fa fa-search fa-5x"></i></div>';
29    } else if (resultItems.length === 0) {
30      container.innerHTML = '<div class="search-result-icon"><i class="far fa-frown fa-5x"></i></div>';
31    } else {
32      resultItems.sort((left, right) => {
33        if (left.includedCount !== right.includedCount) {
34          return right.includedCount - left.includedCount;
35        } else if (left.hitCount !== right.hitCount) {
36          return right.hitCount - left.hitCount;
37        }
38        return right.id - left.id;
39      });
40      const stats = CONFIG.i18n.hits.replace('${hits}', resultItems.length);
41
42      container.innerHTML = `<div class="search-stats">${stats}</div>
43        <hr>
44        <ul class="search-result-list">${resultItems.map(result => result.item).join('')}</ul>`;
45      if (typeof pjax === 'object') pjax.refresh(container);
46    }
47  };
48
49  localSearch.highlightSearchWords(document.querySelector('.post-body'));
50  if (CONFIG.localsearch.preload) {
51    localSearch.fetchData();
52  }
53
54  input.addEventListener('input', inputEventFunction);
55  window.addEventListener('search:loaded', inputEventFunction);
56
57  // Handle and trigger popup window
58  document.querySelectorAll('.popup-trigger').forEach(element => {
59    element.addEventListener('click', () => {
60      NexT.utils.setGutter();
61      document.body.classList.add('search-active');
62      // Wait for search-popup animation to complete
63      setTimeout(() => input.focus(), 500);
64      if (!localSearch.isfetched) localSearch.fetchData();
65    });
66  });
67
68  // Monitor main search box
69  const onPopupClose = () => {
70    NexT.utils.setGutter('0');
71    document.body.classList.remove('search-active');
72  };
73
74  document.querySelector('.search-pop-overlay').addEventListener('click', event => {
75    if (event.target === document.querySelector('.search-pop-overlay')) {
76      onPopupClose();
77    }
78  });
79  document.querySelector('.popup-btn-close').addEventListener('click', onPopupClose);
80  document.addEventListener('pjax:success', () => {
81    localSearch.highlightSearchWords(document.querySelector('.post-body'));
82    onPopupClose();
83  });
84  window.addEventListener('keydown', event => {
85    if ((event.ctrlKey || event.metaKey) && event.key === 'k') {
86      event.preventDefault();
87      NexT.utils.setGutter();
88      document.body.classList.add('search-active');
89      setTimeout(() => input.focus(), 500);
90      if (!localSearch.isfetched) localSearch.fetchData();
91    }
92  });
93  window.addEventListener('keyup', event => {
94    if (event.key === 'Escape') {
95      onPopupClose();
96    }
97  });
98});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.