import { IndexInterface } from "./type.js"; import { create_object, get_keys } from "./common.js"; /** * @param {!string} str * @param {boolean|Array=} normalize * @param {boolean|string|RegExp=} split * @param {boolean=} _collapse * @returns {string|Array} * @this IndexInterface */ export function pipeline(str, normalize, split, _collapse) { if (str) { if (normalize) { str = replace(str, /** @type {Array} */normalize); } if (this.matcher) { str = replace(str, this.matcher); } if (this.stemmer && 1 < str.length) { str = replace(str, this.stemmer); } if (_collapse && 1 < str.length) { str = collapse(str); } if (split || "" === split) { const words = str.split( /** @type {string|RegExp} */split); return this.filter ? filter(words, this.filter) : words; } } return str; } // TODO improve normalize + remove non-delimited chars like in "I'm" + split on whitespace+ export const regex_whitespace = /[\p{Z}\p{S}\p{P}\p{C}]+/u; // https://github.com/nextapps-de/flexsearch/pull/414 //export const regex_whitespace = /[\s\xA0\u2000-\u200B\u2028\u2029\u3000\ufeff!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]/ const regex_normalize = /[\u0300-\u036f]/g; export function normalize(str) { if (str.normalize) { str = str.normalize("NFD").replace(regex_normalize, ""); } return str; } /** * @param {!string} str * @param {boolean|Array=} normalize * @param {boolean|string|RegExp=} split * @param {boolean=} _collapse * @returns {string|Array} */ // FlexSearch.prototype.pipeline = function(str, normalize, split, _collapse){ // // if(str){ // // if(normalize && str){ // // str = replace(str, /** @type {Array} */ (normalize)); // } // // if(str && this.matcher){ // // str = replace(str, this.matcher); // } // // if(this.stemmer && str.length > 1){ // // str = replace(str, this.stemmer); // } // // if(_collapse && str.length > 1){ // // str = collapse(str); // } // // if(str){ // // if(split || (split === "")){ // // const words = str.split(/** @type {string|RegExp} */ (split)); // // return this.filter ? filter(words, this.filter) : words; // } // } // } // // return str; // }; // export function pipeline(str, normalize, matcher, stemmer, split, _filter, _collapse){ // // if(str){ // // if(normalize && str){ // // str = replace(str, normalize); // } // // if(matcher && str){ // // str = replace(str, matcher); // } // // if(stemmer && str.length > 1){ // // str = replace(str, stemmer); // } // // if(_collapse && str.length > 1){ // // str = collapse(str); // } // // if(str){ // // if(split !== false){ // // str = str.split(split); // // if(_filter){ // // str = filter(str, _filter); // } // } // } // } // // return str; // } /** * @param {Array} words * @returns {Object} */ export function init_filter(words) { const filter = create_object(); for (let i = 0, length = words.length; i < length; i++) { filter[words[i]] = 1; } return filter; } /** * @param {!Object} obj * @param {boolean} is_stemmer * @returns {Array} */ export function init_stemmer_or_matcher(obj, is_stemmer) { const keys = get_keys(obj), length = keys.length, final = []; let removal = "", count = 0; for (let i = 0, key, tmp; i < length; i++) { key = keys[i]; tmp = obj[key]; if (tmp) { final[count++] = regex(is_stemmer ? "(?!\\b)" + key + "(\\b|_)" : key); final[count++] = tmp; } else { removal += (removal ? "|" : "") + key; } } if (removal) { final[count++] = regex(is_stemmer ? "(?!\\b)(" + removal + ")(\\b|_)" : "(" + removal + ")"); final[count] = ""; } return final; } /** * @param {!string} str * @param {Array} regexp * @returns {string} */ export function replace(str, regexp) { for (let i = 0, len = regexp.length; i < len; i += 2) { str = str.replace(regexp[i], regexp[i + 1]); if (!str) { break; } } return str; } /** * @param {!string} str * @returns {RegExp} */ export function regex(str) { return new RegExp(str, "g"); } /** * Regex: replace(/(?:(\w)(?:\1)*)/g, "$1") * @param {!string} string * @returns {string} */ export function collapse(string) { let final = "", prev = ""; for (let i = 0, len = string.length, char; i < len; i++) { if ((char = string[i]) !== prev) { final += prev = char; } } return final; } // TODO using fast-swap export function filter(words, map) { const length = words.length, filtered = []; for (let i = 0, count = 0; i < length; i++) { const word = words[i]; if (word && !map[word]) { filtered[count++] = word; } } return filtered; } // const chars = {a:1, e:1, i:1, o:1, u:1, y:1}; // // function collapse_repeating_chars(string){ // // let collapsed_string = "", // char_prev = "", // char_next = ""; // // for(let i = 0; i < string.length; i++){ // // const char = string[i]; // // if(char !== char_prev){ // // if(i && (char === "h")){ // // if((chars[char_prev] && chars[char_next]) || (char_prev === " ")){ // // collapsed_string += char; // } // } // else{ // // collapsed_string += char; // } // } // // char_next = ( // // (i === (string.length - 1)) ? // // "" // : // string[i + 1] // ); // // char_prev = char; // } // // return collapsed_string; // }