diff --git a/src/autocomplete/QueryMatcher.ts b/src/autocomplete/QueryMatcher.ts index 7a0219e264..2a44f20fe3 100644 --- a/src/autocomplete/QueryMatcher.ts +++ b/src/autocomplete/QueryMatcher.ts @@ -18,16 +18,15 @@ limitations under the License. import _at from 'lodash/at'; import _uniq from 'lodash/uniq'; - -function stripDiacritics(str: string): string { - return str.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); -} +import {removeHiddenChars} from "matrix-js-sdk/src/utils"; interface IOptions { keys: Array; funcs?: Array<(T) => string>; shouldMatchWordsOnly?: boolean; shouldMatchPrefix?: boolean; + // whether to apply unhomoglyph and strip diacritics to fuzz up the search. Defaults to true + fuzzy?: boolean; } /** @@ -46,14 +45,10 @@ interface IOptions { */ export default class QueryMatcher { private _options: IOptions; - private _keys: IOptions["keys"]; - private _funcs: Required["funcs"]>; private _items: Map; constructor(objects: T[], options: IOptions = { keys: [] }) { this._options = options; - this._keys = options.keys; - this._funcs = options.funcs || []; this.setObjects(objects); @@ -78,15 +73,17 @@ export default class QueryMatcher { // type for their values. We assume that those values who's keys have // been specified will be string. Also, we cannot infer all the // types of the keys of the objects at compile. - const keyValues = _at(object, this._keys); + const keyValues = _at(object, this._options.keys); - for (const f of this._funcs) { - keyValues.push(f(object)); + if (this._options.funcs) { + for (const f of this._options.funcs) { + keyValues.push(f(object)); + } } for (const [index, keyValue] of Object.entries(keyValues)) { if (!keyValue) continue; // skip falsy keyValues - const key = stripDiacritics(keyValue).toLowerCase(); + const key = this.processQuery(keyValue); if (!this._items.has(key)) { this._items.set(key, []); } @@ -99,7 +96,7 @@ export default class QueryMatcher { } match(query: string): T[] { - query = stripDiacritics(query).toLowerCase(); + query = this.processQuery(query); if (this._options.shouldMatchWordsOnly) { query = query.replace(/[^\w]/g, ''); } @@ -142,4 +139,11 @@ export default class QueryMatcher { // Now map the keys to the result objects. Also remove any duplicates. return _uniq(matches.map((match) => match.object)); } + + private processQuery(query: string): string { + if (this._options.fuzzy !== false) { + return removeHiddenChars(query).toLowerCase(); + } + return query.toLowerCase(); + } }