File size: 2,318 Bytes
6111b2b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**

 * Türkçe-güvenli metin normalizasyonu, arama ve sıralama yardımcıları.

 *

 * JavaScript'in locale-bağımsız `toLowerCase()`'i Türkçe `İ/I/ı/i`

 * karakterlerini bozar: `"İ".toLowerCase()` → `"i̇"` (U+0069 U+0307

 * combining dot above). Bu, `toLowerCase().includes()` tabanlı aramada

 * Türkçe girdileri eşleşmez kılar.

 *

 * Saf fonksiyonlar — yan etki ve bağımlılık yok.

 *

 * @module shared/utils/turkishText

 */

/** NFD ile katlanmayan Türkçe harfler için açık eşleme. */
const TR_FOLD: Readonly<Record<string, string>> = {
  ı: "i",
  ş: "s",
  ğ: "g",
  ü: "u",
  ö: "o",
  ç: "c",
};

/**

 * Aksan-duyarsız, Türkçe-güvenli arama anahtarı üretir.

 * `"İstanbul"` ve `"istanbul"` → `"istanbul"`; `"Şarj"` → `"sarj"`.

 * Baştaki ve sondaki boşluklar kırpılır.

 */
export function normalizeForSearch(input: string | null | undefined): string {
  if (!input) return "";
  let s = input.toLocaleLowerCase("tr"); // İ→i, I→ı (Türkçe-güvenli)
  s = s.replace(/[ışğüöç]/g, (ch) => TR_FOLD[ch] ?? ch); // açık Türkçe fold
  s = s.normalize("NFD").replace(/[̀-ͯ]/g, ""); // kalan aksanları sil
  return s.trim();
}

/**

 * `text`, `query`'yi (aksan-duyarsız, Türkçe-güvenli) içeriyor mu?

 * Boş sorgu her zaman `true` döner.

 */
export function matchesSearch(

  text: string | null | undefined,

  query: string | null | undefined

): boolean {
  const q = normalizeForSearch(query);
  if (!q) return true;
  return normalizeForSearch(text).includes(q);
}

const trCollator = new Intl.Collator("tr", {
  sensitivity: "base",
  numeric: true,
});

/**

 * Kullanıcı-görünür listeler için Türkçe alfabe + sayısal-duyarlı

 * karşılaştırma. `Array.prototype.sort` ile doğrudan kullanılabilir.

 *

 * `sensitivity: "base"` kullanıldığından aksan/büyük-küçük harf varyantları

 * sıralama açısından eşit sayılır — örneğin `"Şehir"` ile `"şehir"` berabere

 * gelir. Bu karşılaştırıcı görsel liste sıralaması içindir, kesin

 * aksan-farklılaştırmalı sıralama için değil.

 */
export function compareTr(a: string | null | undefined, b: string | null | undefined): number {
  return trCollator.compare(a ?? "", b ?? "");
}