44 lines
1.6 KiB
TypeScript
44 lines
1.6 KiB
TypeScript
/**
|
||||
|
|
* همان الگوریتم جستجوی سرور (apps/api/src/common/search.ts) برای فیلترهای سمت کاربر:
|
|||
|
|
* کلمهبهکلمه، بخشی از کلمه کافی است، حروف عربی/فارسی و ارقام فارسی/لاتین یکساناند.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
function toAsciiDigits(s: string): string {
|
|||
|
|
return s.replace(/[۰-۹]/g, (d) => String('۰۱۲۳۴۵۶۷۸۹'.indexOf(d))).replace(
|
|||
|
|
/[٠-٩]/g,
|
|||
|
|
(d) => String('٠١٢٣٤٥٦٧٨٩'.indexOf(d)),
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function normalizeSearchText(raw: unknown): string {
|
|||
|
|
return toAsciiDigits(String(raw ?? ''))
|
|||
|
|
.toLowerCase()
|
|||
|
|
.replace(/[يىئ]/g, 'ی')
|
|||
|
|
.replace(/ك/g, 'ک')
|
|||
|
|
.replace(/ة/g, 'ه')
|
|||
|
|
.replace(/[أإٱ]/g, 'ا')
|
|||
|
|
.replace(/ؤ/g, 'و')
|
|||
|
|
.replace(/[\u064B-\u065F\u0670]/g, '')
|
|||
|
|
.replace(/[\u200c\u200f\u200e]/g, ' ')
|
|||
|
|
.replace(/\s+/g, ' ')
|
|||
|
|
.trim();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function phoneCore(token: string): string | null {
|
|||
|
|
if (!/^\+?[0-9]+$/.test(token)) return null;
|
|||
|
|
const core = token.replace(/^\+/, '').replace(/^(0098|98|0)/, '');
|
|||
|
|
return core.length >= 3 ? core : null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/** آیا همه کلمات عبارت جستجو در یکی از فیلدها پیدا میشوند؟ عبارت خالی = true */
|
|||
|
|
export function matchesSearch(query: string, fields: unknown[]): boolean {
|
|||
|
|
const q = normalizeSearchText(query);
|
|||
|
|
if (!q) return true;
|
|||
|
|
const hay = normalizeSearchText(fields.filter((f) => f != null && f !== '').join(' \u0001 '));
|
|||
|
|
return q.split(' ').every((token) => {
|
|||
|
|
if (hay.includes(token)) return true;
|
|||
|
|
const core = phoneCore(token);
|
|||
|
|
return core ? hay.includes(core) : false;
|
|||
|
|
});
|
|||
|
|
}
|