UNCLASSIFIED - NO CUI

Skip to content
Snippets Groups Projects
search.js 5.81 KiB
import lunr from "lunr";
import searchData from "@/assets/data/search-data.json";
import searchIndexData from "@/assets/data/search-index.json";
import { registerAcronymAliases } from "@/plugins/search/lunr-pipelines";

/**
 * Search api.  Provides search and context capabilities.
 *   @example
 *   import Search from "@/api/search";
 *   const searchApi = new Search();
 *   const results = searchApi.search("cnap");
 *   console.debug("search results:", results);
 *   console.debug("search context of first result:", searchApi.getContext(results[0]));
 */
export default class Search {
  constructor() {
    // reconstitute the search index in memory
    registerAcronymAliases();
    this.index = lunr.Index.load(searchIndexData);
    // hash the context data by id (page path) for faster lookups over array
    this.contextData = searchData.reduce((all, data) => {
      all[data.id] = data;
      return all;
    }, {});
  }

  /**
   * Performs a search on the search index.  See https://lunrjs.com/guides/searching.html
   * @param {String} query the string to search on
   * @returns {Array[Object]} search results, including match position metadata
   *   @example
   *   [{
   *    "ref": "/resources",
   *    "score": 1.21,
   *    "matchData": {
   *      "metadata": {
   *        "cloud native access point": {
   *          "content": {
   *            "position": [
   *              [
   *                42,
   *                4
   *              ]
   *            ]
   *          }
   *        }
   *      }
   *    }
   *  }]
   */
  search(query) {
    return this.index.search(query);
  }

  _getContextForPosition(matchValueField, dataMatchField, surroundChars) {
    const contextData = [];
    // translate lunrjs match position indexes to actual characters
    for (const position of matchValueField.position) {
      const matchStart = position[0];
      const matchEnd = matchStart + position[1];
      const contextStart = Math.max(0, matchStart - surroundChars);
      const contextEnd = Math.min(
        dataMatchField.length,
        matchEnd + surroundChars
      );
      contextData.push({
        match: dataMatchField.substring(matchStart, matchEnd),
        context: dataMatchField.substring(contextStart, contextEnd),
      });
    }