UNPKG

@gechiui/block-editor

Version:
189 lines (155 loc) 5.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getItemSearchRank = getItemSearchRank; exports.searchItems = exports.searchBlockItems = exports.getNormalizedSearchTerms = void 0; var _lodash = require("lodash"); /** * External dependencies */ // Default search helpers const defaultGetName = item => item.name || ''; const defaultGetTitle = item => item.title; const defaultGetDescription = item => item.description || ''; const defaultGetKeywords = item => item.keywords || []; const defaultGetCategory = item => item.category; const defaultGetCollection = () => null; /** * Sanitizes the search input string. * * @param {string} input The search input to normalize. * * @return {string} The normalized search input. */ function normalizeSearchInput() { let input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; // Disregard diacritics. // Input: "média" input = (0, _lodash.deburr)(input); // Accommodate leading slash, matching autocomplete expectations. // Input: "/media" input = input.replace(/^\//, ''); // Lowercase. // Input: "MEDIA" input = input.toLowerCase(); return input; } /** * Converts the search term into a list of normalized terms. * * @param {string} input The search term to normalize. * * @return {string[]} The normalized list of search terms. */ const getNormalizedSearchTerms = function () { let input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; // Extract words. return (0, _lodash.words)(normalizeSearchInput(input)); }; exports.getNormalizedSearchTerms = getNormalizedSearchTerms; const removeMatchingTerms = (unmatchedTerms, unprocessedTerms) => { return (0, _lodash.differenceWith)(unmatchedTerms, getNormalizedSearchTerms(unprocessedTerms), (unmatchedTerm, unprocessedTerm) => unprocessedTerm.includes(unmatchedTerm)); }; const searchBlockItems = (items, categories, collections, searchInput) => { const normalizedSearchTerms = getNormalizedSearchTerms(searchInput); if (normalizedSearchTerms.length === 0) { return items; } const config = { getCategory: item => { var _find; return (_find = (0, _lodash.find)(categories, { slug: item.category })) === null || _find === void 0 ? void 0 : _find.title; }, getCollection: item => { var _collections$item$nam; return (_collections$item$nam = collections[item.name.split('/')[0]]) === null || _collections$item$nam === void 0 ? void 0 : _collections$item$nam.title; } }; return searchItems(items, searchInput, config); }; /** * Filters an item list given a search term. * * @param {Array} items Item list * @param {string} searchInput Search input. * @param {Object} config Search Config. * * @return {Array} Filtered item list. */ exports.searchBlockItems = searchBlockItems; const searchItems = function () { let items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; let searchInput = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; let config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; const normalizedSearchTerms = getNormalizedSearchTerms(searchInput); if (normalizedSearchTerms.length === 0) { return items; } const rankedItems = items.map(item => { return [item, getItemSearchRank(item, searchInput, config)]; }).filter(_ref => { let [, rank] = _ref; return rank > 0; }); rankedItems.sort((_ref2, _ref3) => { let [, rank1] = _ref2; let [, rank2] = _ref3; return rank2 - rank1; }); return rankedItems.map(_ref4 => { let [item] = _ref4; return item; }); }; /** * Get the search rank for a given item and a specific search term. * The better the match, the higher the rank. * If the rank equals 0, it should be excluded from the results. * * @param {Object} item Item to filter. * @param {string} searchTerm Search term. * @param {Object} config Search Config. * * @return {number} Search Rank. */ exports.searchItems = searchItems; function getItemSearchRank(item, searchTerm) { let config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; const { getName = defaultGetName, getTitle = defaultGetTitle, getDescription = defaultGetDescription, getKeywords = defaultGetKeywords, getCategory = defaultGetCategory, getCollection = defaultGetCollection } = config; const name = getName(item); const title = getTitle(item); const description = getDescription(item); const keywords = getKeywords(item); const category = getCategory(item); const collection = getCollection(item); const normalizedSearchInput = normalizeSearchInput(searchTerm); const normalizedTitle = normalizeSearchInput(title); let rank = 0; // Prefers exact matches // Then prefers if the beginning of the title matches the search term // name, keywords, categories, collection, variations match come later. if (normalizedSearchInput === normalizedTitle) { rank += 30; } else if (normalizedTitle.startsWith(normalizedSearchInput)) { rank += 20; } else { const terms = [name, title, description, ...keywords, category, collection].join(' '); const normalizedSearchTerms = (0, _lodash.words)(normalizedSearchInput); const unmatchedTerms = removeMatchingTerms(normalizedSearchTerms, terms); if (unmatchedTerms.length === 0) { rank += 10; } } // Give a better rank to "core" namespaced items. if (rank !== 0 && name.startsWith('core/')) { rank++; } return rank; } //# sourceMappingURL=search-items.js.map