tdk-api-wrapper 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{chunk-SLNXKZKR.mjs → chunk-ACMGCL7T.mjs} +75 -19
- package/dist/cli.js +75 -19
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +25 -4
- package/dist/index.d.ts +25 -4
- package/dist/index.js +75 -19
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/src/tdk.ts +76 -15
package/README.md
CHANGED
|
@@ -97,9 +97,9 @@ Aşağıdaki metotlar `TDK` sınıfı üzerinden statik olarak erişilebilir dur
|
|
|
97
97
|
|
|
98
98
|
TDK dışındaki bu üç kaynak da her zaman kullanılabilir/dokümante edilmiş resmî API'ler değildir; her biri **fragile scraping** (kırılgan, dokümante edilmemiş entegrasyon) — kaynak taraflarında bir değişiklik olursa `null`/`[]` dönerler, hataya düşmezler. Verinin telif/kullanım koşulları kaynağa göre farklıdır: Wiktionary içeriği CC BY-SA lisanslıdır (açık); Nişanyan Sözlük ücretsiz, açık bir kişisel/akademik kaynaktır; **Kubbealtı Lugatı ise ticari bir sözlük ürünüdür** — bu kütüphane onu da dokümante edilmemiş bir uç noktadan çekebiliyor olsa da, kullanımınızı Kubbealtı'nın kendi kullanım şartlarına göre değerlendirmeniz önerilir.
|
|
99
99
|
|
|
100
|
-
- **`TDK.getKubbealti(word)`**: Kubbealtı Lugatı'nın ("Misalli Büyük Türkçe Sözlük") verilerini `{ kelime, anlam }` dizisi olarak döner (`anlam` zengin tipografi içeren ham HTML'dir). `getKubbealtiMeanings(word)` aynı veriyi düz metne çevirir. `getKubbealtiSuggestions(prefix)` Kubbealtı'nın kendi otomatik tamamlama uç noktasını kullanır (TDK'nin `getSuggestions()`'ından bağımsız, ayrı bir veri kaynağı). Not: Kubbealtı'nın veri sunucusu (`eski.lugatim.com`) sertifika zincirini eksik gönderiyor; bu kütüphane eksik ara sertifikaları ekleyerek zinciri düzgün doğruluyor (doğrulamayı kapatmıyor) — Let's Encrypt bu ara sertifikayı döndürürse bu entegrasyon `null` dönmeye başlar.
|
|
100
|
+
- **`TDK.getKubbealti(word)`**: Kubbealtı Lugatı'nın ("Misalli Büyük Türkçe Sözlük") verilerini `{ kelime, anlam }` dizisi olarak döner (`anlam` zengin tipografi içeren ham HTML'dir). `getKubbealtiMeanings(word)` aynı veriyi düz metne çevirir. `getKubbealtiSuggestions(prefix)` Kubbealtı'nın kendi otomatik tamamlama uç noktasını kullanır (TDK'nin `getSuggestions()`'ından bağımsız, ayrı bir veri kaynağı). Kubbealtı başlıkları klasik Türkçe imlayla (ü/ö/ç/ğ/ş, düzeltme işareti) indekslidir; düz ASCII'ye yakın bir sorgu (örn. `ruzgar`) boş dönerse, kütüphane tek harflik Türkçeleştirme varyasyonlarını (`rüzgâr`, `rûzgar` vb.) otomatik dener. Not: Kubbealtı'nın veri sunucusu (`eski.lugatim.com`) sertifika zincirini eksik gönderiyor; bu kütüphane eksik ara sertifikaları ekleyerek zinciri düzgün doğruluyor (doğrulamayı kapatmıyor) — Let's Encrypt bu ara sertifikayı döndürürse bu entegrasyon `null` dönmeye başlar.
|
|
101
101
|
- **`TDK.getNisanyan(word)`**: Nişanyan Sözlük'ten kelimenin etimoloji paragrafını düz metin olarak döner; kelime bulunamazsa `null`.
|
|
102
|
-
- **`TDK.getWiktionary(word)`**: Türkçe Vikisözlük'ten (`tr.wiktionary.org`) resmî MediaWiki API'si (`action=query&prop=extracts`) üzerinden veri çeker — bu üçü arasında scraping olmayan, resmî ve en kararlı olanı. `{ raw, sections }` döner; `sections` metni `== Köken ==`, `=== Söyleniş ===` gibi başlıklara göre bir sözlüğe ayırır. `getWiktionarySection(word, sectionName)` tek bir bölümü (örn. `"Köken"`) büyük/küçük harf duyarsız süzer.
|
|
102
|
+
- **`TDK.getWiktionary(word)`**: Türkçe Vikisözlük'ten (`tr.wiktionary.org`) resmî MediaWiki API'si (`action=query&prop=extracts`) üzerinden veri çeker — bu üçü arasında scraping olmayan, resmî ve en kararlı olanı. `{ raw, sections }` döner; `sections` metni `== Köken ==`, `=== Söyleniş ===` gibi başlıklara göre bir sözlüğe ayırır. `getWiktionarySection(word, sectionName)` tek bir bölümü (örn. `"Köken"`) büyük/küçük harf duyarsız süzer. Bu wiki'de başlık büyütme kapalı (`$wgCapitalLinks=false` — "Türkiye" ile bir küçük harfli kelime ayrı sayfalardır), o yüzden `TDK.getWiktionary("türkiye")` gibi tam eşleşmeyen aramalar otomatik olarak ilk harfi (Türkçe kurallarına göre, örn. `istanbul` → `İstanbul`) büyütülmüş hâliyle tekrar denenir.
|
|
103
103
|
|
|
104
104
|
## Hata Yönetimi
|
|
105
105
|
|
|
@@ -661,14 +661,46 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
661
661
|
req.end();
|
|
662
662
|
});
|
|
663
663
|
}
|
|
664
|
+
/**
|
|
665
|
+
* Kubbealtı indexes headwords with full classical Turkish orthography,
|
|
666
|
+
* including letters that a plain-ASCII-ish query tends to drop — most
|
|
667
|
+
* commonly ü/ö/ç/ğ/ş, but also the circumflex ("düzeltme işareti") used in
|
|
668
|
+
* Arabic/Persian loanwords like "rüzgâr". A search for "ruzgar" misses
|
|
669
|
+
* entirely (verified: even "ruzgâr" alone still misses — it's the missing
|
|
670
|
+
* ü, not the missing â, that actually breaks the match). This generates
|
|
671
|
+
* single-letter-substitution variants to retry, one substitution per
|
|
672
|
+
* variant (not combinatorial) — covers the overwhelmingly common case of
|
|
673
|
+
* one "de-Turkished" letter without an explosion of API calls for words
|
|
674
|
+
* with several.
|
|
675
|
+
*/
|
|
676
|
+
static TURKISH_DEASCII_MAP = {
|
|
677
|
+
a: ["\xE2"],
|
|
678
|
+
i: ["\u0131", "\xEE"],
|
|
679
|
+
o: ["\xF6"],
|
|
680
|
+
u: ["\xFC", "\xFB"],
|
|
681
|
+
c: ["\xE7"],
|
|
682
|
+
g: ["\u011F"],
|
|
683
|
+
s: ["\u015F"]
|
|
684
|
+
};
|
|
685
|
+
static generateTurkishVariants(word) {
|
|
686
|
+
const lower = word.trim().toLocaleLowerCase("tr-TR");
|
|
687
|
+
const variants = [];
|
|
688
|
+
for (let i = 0; i < lower.length; i++) {
|
|
689
|
+
for (const replacement of this.TURKISH_DEASCII_MAP[lower[i]] ?? []) {
|
|
690
|
+
variants.push(lower.slice(0, i) + replacement + lower.slice(i + 1));
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
return variants;
|
|
694
|
+
}
|
|
664
695
|
/**
|
|
665
696
|
* Returns Kubbealtı Lugatı ("Misalli Büyük Türkçe Sözlük") entries for a
|
|
666
697
|
* word, scraped from the site's own data API — undocumented, and Kubbealtı
|
|
667
698
|
* Lugatı is a commercial dictionary product, unlike TDK's or Wiktionary's
|
|
668
699
|
* openly-published data, so use this in line with their terms. `anlam` is
|
|
669
700
|
* raw HTML (rich typography markup); use `getKubbealtiMeanings()` for
|
|
670
|
-
* plain text.
|
|
671
|
-
*
|
|
701
|
+
* plain text. Falls back to `generateTurkishVariants()` if the exact query
|
|
702
|
+
* comes up empty (see its doc comment). Returns `null` on any fetch/parse
|
|
703
|
+
* failure, `[]` if no variant matches either.
|
|
672
704
|
*/
|
|
673
705
|
static async getKubbealti(word) {
|
|
674
706
|
if (!word || word.trim() === "")
|
|
@@ -676,7 +708,16 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
676
708
|
const data = await this.fetchKubbealtiJson(`/rest/s/${encodeURIComponent(word.trim())}/`);
|
|
677
709
|
if (!data || !Array.isArray(data.content))
|
|
678
710
|
return null;
|
|
679
|
-
|
|
711
|
+
if (data.content.length > 0) {
|
|
712
|
+
return data.content.map((entry) => ({ kelime: entry.kelime, anlam: entry.anlam }));
|
|
713
|
+
}
|
|
714
|
+
for (const variant of this.generateTurkishVariants(word)) {
|
|
715
|
+
const variantData = await this.fetchKubbealtiJson(`/rest/s/${encodeURIComponent(variant)}/`);
|
|
716
|
+
if (variantData && Array.isArray(variantData.content) && variantData.content.length > 0) {
|
|
717
|
+
return variantData.content.map((entry) => ({ kelime: entry.kelime, anlam: entry.anlam }));
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return [];
|
|
680
721
|
}
|
|
681
722
|
/**
|
|
682
723
|
* Same as `getKubbealti()` but with each entry's `anlam` HTML stripped to
|
|
@@ -730,21 +771,10 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
730
771
|
return null;
|
|
731
772
|
}
|
|
732
773
|
}
|
|
733
|
-
|
|
734
|
-
* Returns the Turkish Wiktionary (`tr.wiktionary.org`) entry for a word,
|
|
735
|
-
* via MediaWiki's official Action API (`action=query&prop=extracts`) — no
|
|
736
|
-
* scraping involved, this is a stable, documented public API. `sections`
|
|
737
|
-
* splits the plain-text extract on its `== Heading ==`/`=== Heading ===`
|
|
738
|
-
* markers (e.g. "Köken", "Söyleniş", "Ad") for convenience; `raw` has the
|
|
739
|
-
* unsplit text. Returns `null` if the page doesn't exist or the request
|
|
740
|
-
* fails.
|
|
741
|
-
*/
|
|
742
|
-
static async getWiktionary(word) {
|
|
743
|
-
if (!word || word.trim() === "")
|
|
744
|
-
return null;
|
|
774
|
+
static async fetchWiktionaryEntry(title) {
|
|
745
775
|
try {
|
|
746
776
|
const url = `https://tr.wiktionary.org/w/api.php?action=query&prop=extracts&titles=${encodeURIComponent(
|
|
747
|
-
|
|
777
|
+
title
|
|
748
778
|
)}&format=json&explaintext=1&formatversion=2`;
|
|
749
779
|
const response = await fetch(url, { headers: { "User-Agent": "TDK-API-Nodejs-Wrapper/1.0" } });
|
|
750
780
|
if (!response.ok)
|
|
@@ -757,16 +787,42 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
757
787
|
const sections = {};
|
|
758
788
|
const parts = raw.split(/\n(={2,4})\s*(.+?)\s*\1\n/);
|
|
759
789
|
for (let i = 1; i < parts.length; i += 3) {
|
|
760
|
-
const
|
|
790
|
+
const title2 = parts[i + 1]?.trim();
|
|
761
791
|
const content = parts[i + 2]?.trim();
|
|
762
|
-
if (
|
|
763
|
-
sections[
|
|
792
|
+
if (title2)
|
|
793
|
+
sections[title2] = content ?? "";
|
|
764
794
|
}
|
|
765
795
|
return { raw, sections };
|
|
766
796
|
} catch {
|
|
767
797
|
return null;
|
|
768
798
|
}
|
|
769
799
|
}
|
|
800
|
+
/**
|
|
801
|
+
* Returns the Turkish Wiktionary (`tr.wiktionary.org`) entry for a word,
|
|
802
|
+
* via MediaWiki's official Action API (`action=query&prop=extracts`) — no
|
|
803
|
+
* scraping involved, this is a stable, documented public API. `sections`
|
|
804
|
+
* splits the plain-text extract on its `== Heading ==`/`=== Heading ===`
|
|
805
|
+
* markers (e.g. "Köken", "Söyleniş", "Ad") for convenience; `raw` has the
|
|
806
|
+
* unsplit text. This wiki has title capitalization turned off
|
|
807
|
+
* ($wgCapitalLinks=false — common for Wiktionaries, since case is
|
|
808
|
+
* meaningful for a dictionary: "Türkiye" the country vs. a lowercase
|
|
809
|
+
* common word), so an exact-case miss retries with the first letter
|
|
810
|
+
* uppercased (Turkish-locale-aware, so "istanbul" tries "İstanbul", not
|
|
811
|
+
* "Istanbul") before giving up. Returns `null` if neither is found or the
|
|
812
|
+
* request fails.
|
|
813
|
+
*/
|
|
814
|
+
static async getWiktionary(word) {
|
|
815
|
+
if (!word || word.trim() === "")
|
|
816
|
+
return null;
|
|
817
|
+
const trimmed = word.trim();
|
|
818
|
+
const direct = await this.fetchWiktionaryEntry(trimmed);
|
|
819
|
+
if (direct)
|
|
820
|
+
return direct;
|
|
821
|
+
const capitalized = trimmed.charAt(0).toLocaleUpperCase("tr-TR") + trimmed.slice(1);
|
|
822
|
+
if (capitalized === trimmed)
|
|
823
|
+
return null;
|
|
824
|
+
return this.fetchWiktionaryEntry(capitalized);
|
|
825
|
+
}
|
|
770
826
|
/**
|
|
771
827
|
* Convenience filter over `getWiktionary()`: returns just one section's
|
|
772
828
|
* text (e.g. `getWiktionarySection(word, "Köken")` for etymology), matched
|
package/dist/cli.js
CHANGED
|
@@ -686,14 +686,46 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
686
686
|
req.end();
|
|
687
687
|
});
|
|
688
688
|
}
|
|
689
|
+
/**
|
|
690
|
+
* Kubbealtı indexes headwords with full classical Turkish orthography,
|
|
691
|
+
* including letters that a plain-ASCII-ish query tends to drop — most
|
|
692
|
+
* commonly ü/ö/ç/ğ/ş, but also the circumflex ("düzeltme işareti") used in
|
|
693
|
+
* Arabic/Persian loanwords like "rüzgâr". A search for "ruzgar" misses
|
|
694
|
+
* entirely (verified: even "ruzgâr" alone still misses — it's the missing
|
|
695
|
+
* ü, not the missing â, that actually breaks the match). This generates
|
|
696
|
+
* single-letter-substitution variants to retry, one substitution per
|
|
697
|
+
* variant (not combinatorial) — covers the overwhelmingly common case of
|
|
698
|
+
* one "de-Turkished" letter without an explosion of API calls for words
|
|
699
|
+
* with several.
|
|
700
|
+
*/
|
|
701
|
+
static TURKISH_DEASCII_MAP = {
|
|
702
|
+
a: ["\xE2"],
|
|
703
|
+
i: ["\u0131", "\xEE"],
|
|
704
|
+
o: ["\xF6"],
|
|
705
|
+
u: ["\xFC", "\xFB"],
|
|
706
|
+
c: ["\xE7"],
|
|
707
|
+
g: ["\u011F"],
|
|
708
|
+
s: ["\u015F"]
|
|
709
|
+
};
|
|
710
|
+
static generateTurkishVariants(word2) {
|
|
711
|
+
const lower = word2.trim().toLocaleLowerCase("tr-TR");
|
|
712
|
+
const variants = [];
|
|
713
|
+
for (let i = 0; i < lower.length; i++) {
|
|
714
|
+
for (const replacement of this.TURKISH_DEASCII_MAP[lower[i]] ?? []) {
|
|
715
|
+
variants.push(lower.slice(0, i) + replacement + lower.slice(i + 1));
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
return variants;
|
|
719
|
+
}
|
|
689
720
|
/**
|
|
690
721
|
* Returns Kubbealtı Lugatı ("Misalli Büyük Türkçe Sözlük") entries for a
|
|
691
722
|
* word, scraped from the site's own data API — undocumented, and Kubbealtı
|
|
692
723
|
* Lugatı is a commercial dictionary product, unlike TDK's or Wiktionary's
|
|
693
724
|
* openly-published data, so use this in line with their terms. `anlam` is
|
|
694
725
|
* raw HTML (rich typography markup); use `getKubbealtiMeanings()` for
|
|
695
|
-
* plain text.
|
|
696
|
-
*
|
|
726
|
+
* plain text. Falls back to `generateTurkishVariants()` if the exact query
|
|
727
|
+
* comes up empty (see its doc comment). Returns `null` on any fetch/parse
|
|
728
|
+
* failure, `[]` if no variant matches either.
|
|
697
729
|
*/
|
|
698
730
|
static async getKubbealti(word2) {
|
|
699
731
|
if (!word2 || word2.trim() === "")
|
|
@@ -701,7 +733,16 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
701
733
|
const data = await this.fetchKubbealtiJson(`/rest/s/${encodeURIComponent(word2.trim())}/`);
|
|
702
734
|
if (!data || !Array.isArray(data.content))
|
|
703
735
|
return null;
|
|
704
|
-
|
|
736
|
+
if (data.content.length > 0) {
|
|
737
|
+
return data.content.map((entry) => ({ kelime: entry.kelime, anlam: entry.anlam }));
|
|
738
|
+
}
|
|
739
|
+
for (const variant of this.generateTurkishVariants(word2)) {
|
|
740
|
+
const variantData = await this.fetchKubbealtiJson(`/rest/s/${encodeURIComponent(variant)}/`);
|
|
741
|
+
if (variantData && Array.isArray(variantData.content) && variantData.content.length > 0) {
|
|
742
|
+
return variantData.content.map((entry) => ({ kelime: entry.kelime, anlam: entry.anlam }));
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
return [];
|
|
705
746
|
}
|
|
706
747
|
/**
|
|
707
748
|
* Same as `getKubbealti()` but with each entry's `anlam` HTML stripped to
|
|
@@ -755,21 +796,10 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
755
796
|
return null;
|
|
756
797
|
}
|
|
757
798
|
}
|
|
758
|
-
|
|
759
|
-
* Returns the Turkish Wiktionary (`tr.wiktionary.org`) entry for a word,
|
|
760
|
-
* via MediaWiki's official Action API (`action=query&prop=extracts`) — no
|
|
761
|
-
* scraping involved, this is a stable, documented public API. `sections`
|
|
762
|
-
* splits the plain-text extract on its `== Heading ==`/`=== Heading ===`
|
|
763
|
-
* markers (e.g. "Köken", "Söyleniş", "Ad") for convenience; `raw` has the
|
|
764
|
-
* unsplit text. Returns `null` if the page doesn't exist or the request
|
|
765
|
-
* fails.
|
|
766
|
-
*/
|
|
767
|
-
static async getWiktionary(word2) {
|
|
768
|
-
if (!word2 || word2.trim() === "")
|
|
769
|
-
return null;
|
|
799
|
+
static async fetchWiktionaryEntry(title) {
|
|
770
800
|
try {
|
|
771
801
|
const url = `https://tr.wiktionary.org/w/api.php?action=query&prop=extracts&titles=${encodeURIComponent(
|
|
772
|
-
|
|
802
|
+
title
|
|
773
803
|
)}&format=json&explaintext=1&formatversion=2`;
|
|
774
804
|
const response = await fetch(url, { headers: { "User-Agent": "TDK-API-Nodejs-Wrapper/1.0" } });
|
|
775
805
|
if (!response.ok)
|
|
@@ -782,16 +812,42 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
782
812
|
const sections = {};
|
|
783
813
|
const parts = raw.split(/\n(={2,4})\s*(.+?)\s*\1\n/);
|
|
784
814
|
for (let i = 1; i < parts.length; i += 3) {
|
|
785
|
-
const
|
|
815
|
+
const title2 = parts[i + 1]?.trim();
|
|
786
816
|
const content = parts[i + 2]?.trim();
|
|
787
|
-
if (
|
|
788
|
-
sections[
|
|
817
|
+
if (title2)
|
|
818
|
+
sections[title2] = content ?? "";
|
|
789
819
|
}
|
|
790
820
|
return { raw, sections };
|
|
791
821
|
} catch {
|
|
792
822
|
return null;
|
|
793
823
|
}
|
|
794
824
|
}
|
|
825
|
+
/**
|
|
826
|
+
* Returns the Turkish Wiktionary (`tr.wiktionary.org`) entry for a word,
|
|
827
|
+
* via MediaWiki's official Action API (`action=query&prop=extracts`) — no
|
|
828
|
+
* scraping involved, this is a stable, documented public API. `sections`
|
|
829
|
+
* splits the plain-text extract on its `== Heading ==`/`=== Heading ===`
|
|
830
|
+
* markers (e.g. "Köken", "Söyleniş", "Ad") for convenience; `raw` has the
|
|
831
|
+
* unsplit text. This wiki has title capitalization turned off
|
|
832
|
+
* ($wgCapitalLinks=false — common for Wiktionaries, since case is
|
|
833
|
+
* meaningful for a dictionary: "Türkiye" the country vs. a lowercase
|
|
834
|
+
* common word), so an exact-case miss retries with the first letter
|
|
835
|
+
* uppercased (Turkish-locale-aware, so "istanbul" tries "İstanbul", not
|
|
836
|
+
* "Istanbul") before giving up. Returns `null` if neither is found or the
|
|
837
|
+
* request fails.
|
|
838
|
+
*/
|
|
839
|
+
static async getWiktionary(word2) {
|
|
840
|
+
if (!word2 || word2.trim() === "")
|
|
841
|
+
return null;
|
|
842
|
+
const trimmed = word2.trim();
|
|
843
|
+
const direct = await this.fetchWiktionaryEntry(trimmed);
|
|
844
|
+
if (direct)
|
|
845
|
+
return direct;
|
|
846
|
+
const capitalized = trimmed.charAt(0).toLocaleUpperCase("tr-TR") + trimmed.slice(1);
|
|
847
|
+
if (capitalized === trimmed)
|
|
848
|
+
return null;
|
|
849
|
+
return this.fetchWiktionaryEntry(capitalized);
|
|
850
|
+
}
|
|
795
851
|
/**
|
|
796
852
|
* Convenience filter over `getWiktionary()`: returns just one section's
|
|
797
853
|
* text (e.g. `getWiktionarySection(word, "Köken")` for etymology), matched
|
package/dist/cli.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -325,14 +325,29 @@ declare class TDK {
|
|
|
325
325
|
* `null` on any error — network, TLS, HTTP, or JSON parse.
|
|
326
326
|
*/
|
|
327
327
|
private static fetchKubbealtiJson;
|
|
328
|
+
/**
|
|
329
|
+
* Kubbealtı indexes headwords with full classical Turkish orthography,
|
|
330
|
+
* including letters that a plain-ASCII-ish query tends to drop — most
|
|
331
|
+
* commonly ü/ö/ç/ğ/ş, but also the circumflex ("düzeltme işareti") used in
|
|
332
|
+
* Arabic/Persian loanwords like "rüzgâr". A search for "ruzgar" misses
|
|
333
|
+
* entirely (verified: even "ruzgâr" alone still misses — it's the missing
|
|
334
|
+
* ü, not the missing â, that actually breaks the match). This generates
|
|
335
|
+
* single-letter-substitution variants to retry, one substitution per
|
|
336
|
+
* variant (not combinatorial) — covers the overwhelmingly common case of
|
|
337
|
+
* one "de-Turkished" letter without an explosion of API calls for words
|
|
338
|
+
* with several.
|
|
339
|
+
*/
|
|
340
|
+
private static readonly TURKISH_DEASCII_MAP;
|
|
341
|
+
private static generateTurkishVariants;
|
|
328
342
|
/**
|
|
329
343
|
* Returns Kubbealtı Lugatı ("Misalli Büyük Türkçe Sözlük") entries for a
|
|
330
344
|
* word, scraped from the site's own data API — undocumented, and Kubbealtı
|
|
331
345
|
* Lugatı is a commercial dictionary product, unlike TDK's or Wiktionary's
|
|
332
346
|
* openly-published data, so use this in line with their terms. `anlam` is
|
|
333
347
|
* raw HTML (rich typography markup); use `getKubbealtiMeanings()` for
|
|
334
|
-
* plain text.
|
|
335
|
-
*
|
|
348
|
+
* plain text. Falls back to `generateTurkishVariants()` if the exact query
|
|
349
|
+
* comes up empty (see its doc comment). Returns `null` on any fetch/parse
|
|
350
|
+
* failure, `[]` if no variant matches either.
|
|
336
351
|
*/
|
|
337
352
|
static getKubbealti(word: string): Promise<KubbealtiEntry[] | null>;
|
|
338
353
|
/**
|
|
@@ -354,14 +369,20 @@ declare class TDK {
|
|
|
354
369
|
* case) or the request fails.
|
|
355
370
|
*/
|
|
356
371
|
static getNisanyan(word: string): Promise<string | null>;
|
|
372
|
+
private static fetchWiktionaryEntry;
|
|
357
373
|
/**
|
|
358
374
|
* Returns the Turkish Wiktionary (`tr.wiktionary.org`) entry for a word,
|
|
359
375
|
* via MediaWiki's official Action API (`action=query&prop=extracts`) — no
|
|
360
376
|
* scraping involved, this is a stable, documented public API. `sections`
|
|
361
377
|
* splits the plain-text extract on its `== Heading ==`/`=== Heading ===`
|
|
362
378
|
* markers (e.g. "Köken", "Söyleniş", "Ad") for convenience; `raw` has the
|
|
363
|
-
* unsplit text.
|
|
364
|
-
*
|
|
379
|
+
* unsplit text. This wiki has title capitalization turned off
|
|
380
|
+
* ($wgCapitalLinks=false — common for Wiktionaries, since case is
|
|
381
|
+
* meaningful for a dictionary: "Türkiye" the country vs. a lowercase
|
|
382
|
+
* common word), so an exact-case miss retries with the first letter
|
|
383
|
+
* uppercased (Turkish-locale-aware, so "istanbul" tries "İstanbul", not
|
|
384
|
+
* "Istanbul") before giving up. Returns `null` if neither is found or the
|
|
385
|
+
* request fails.
|
|
365
386
|
*/
|
|
366
387
|
static getWiktionary(word: string): Promise<WiktionaryEntry | null>;
|
|
367
388
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -325,14 +325,29 @@ declare class TDK {
|
|
|
325
325
|
* `null` on any error — network, TLS, HTTP, or JSON parse.
|
|
326
326
|
*/
|
|
327
327
|
private static fetchKubbealtiJson;
|
|
328
|
+
/**
|
|
329
|
+
* Kubbealtı indexes headwords with full classical Turkish orthography,
|
|
330
|
+
* including letters that a plain-ASCII-ish query tends to drop — most
|
|
331
|
+
* commonly ü/ö/ç/ğ/ş, but also the circumflex ("düzeltme işareti") used in
|
|
332
|
+
* Arabic/Persian loanwords like "rüzgâr". A search for "ruzgar" misses
|
|
333
|
+
* entirely (verified: even "ruzgâr" alone still misses — it's the missing
|
|
334
|
+
* ü, not the missing â, that actually breaks the match). This generates
|
|
335
|
+
* single-letter-substitution variants to retry, one substitution per
|
|
336
|
+
* variant (not combinatorial) — covers the overwhelmingly common case of
|
|
337
|
+
* one "de-Turkished" letter without an explosion of API calls for words
|
|
338
|
+
* with several.
|
|
339
|
+
*/
|
|
340
|
+
private static readonly TURKISH_DEASCII_MAP;
|
|
341
|
+
private static generateTurkishVariants;
|
|
328
342
|
/**
|
|
329
343
|
* Returns Kubbealtı Lugatı ("Misalli Büyük Türkçe Sözlük") entries for a
|
|
330
344
|
* word, scraped from the site's own data API — undocumented, and Kubbealtı
|
|
331
345
|
* Lugatı is a commercial dictionary product, unlike TDK's or Wiktionary's
|
|
332
346
|
* openly-published data, so use this in line with their terms. `anlam` is
|
|
333
347
|
* raw HTML (rich typography markup); use `getKubbealtiMeanings()` for
|
|
334
|
-
* plain text.
|
|
335
|
-
*
|
|
348
|
+
* plain text. Falls back to `generateTurkishVariants()` if the exact query
|
|
349
|
+
* comes up empty (see its doc comment). Returns `null` on any fetch/parse
|
|
350
|
+
* failure, `[]` if no variant matches either.
|
|
336
351
|
*/
|
|
337
352
|
static getKubbealti(word: string): Promise<KubbealtiEntry[] | null>;
|
|
338
353
|
/**
|
|
@@ -354,14 +369,20 @@ declare class TDK {
|
|
|
354
369
|
* case) or the request fails.
|
|
355
370
|
*/
|
|
356
371
|
static getNisanyan(word: string): Promise<string | null>;
|
|
372
|
+
private static fetchWiktionaryEntry;
|
|
357
373
|
/**
|
|
358
374
|
* Returns the Turkish Wiktionary (`tr.wiktionary.org`) entry for a word,
|
|
359
375
|
* via MediaWiki's official Action API (`action=query&prop=extracts`) — no
|
|
360
376
|
* scraping involved, this is a stable, documented public API. `sections`
|
|
361
377
|
* splits the plain-text extract on its `== Heading ==`/`=== Heading ===`
|
|
362
378
|
* markers (e.g. "Köken", "Söyleniş", "Ad") for convenience; `raw` has the
|
|
363
|
-
* unsplit text.
|
|
364
|
-
*
|
|
379
|
+
* unsplit text. This wiki has title capitalization turned off
|
|
380
|
+
* ($wgCapitalLinks=false — common for Wiktionaries, since case is
|
|
381
|
+
* meaningful for a dictionary: "Türkiye" the country vs. a lowercase
|
|
382
|
+
* common word), so an exact-case miss retries with the first letter
|
|
383
|
+
* uppercased (Turkish-locale-aware, so "istanbul" tries "İstanbul", not
|
|
384
|
+
* "Istanbul") before giving up. Returns `null` if neither is found or the
|
|
385
|
+
* request fails.
|
|
365
386
|
*/
|
|
366
387
|
static getWiktionary(word: string): Promise<WiktionaryEntry | null>;
|
|
367
388
|
/**
|
package/dist/index.js
CHANGED
|
@@ -700,14 +700,46 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
700
700
|
req.end();
|
|
701
701
|
});
|
|
702
702
|
}
|
|
703
|
+
/**
|
|
704
|
+
* Kubbealtı indexes headwords with full classical Turkish orthography,
|
|
705
|
+
* including letters that a plain-ASCII-ish query tends to drop — most
|
|
706
|
+
* commonly ü/ö/ç/ğ/ş, but also the circumflex ("düzeltme işareti") used in
|
|
707
|
+
* Arabic/Persian loanwords like "rüzgâr". A search for "ruzgar" misses
|
|
708
|
+
* entirely (verified: even "ruzgâr" alone still misses — it's the missing
|
|
709
|
+
* ü, not the missing â, that actually breaks the match). This generates
|
|
710
|
+
* single-letter-substitution variants to retry, one substitution per
|
|
711
|
+
* variant (not combinatorial) — covers the overwhelmingly common case of
|
|
712
|
+
* one "de-Turkished" letter without an explosion of API calls for words
|
|
713
|
+
* with several.
|
|
714
|
+
*/
|
|
715
|
+
static TURKISH_DEASCII_MAP = {
|
|
716
|
+
a: ["\xE2"],
|
|
717
|
+
i: ["\u0131", "\xEE"],
|
|
718
|
+
o: ["\xF6"],
|
|
719
|
+
u: ["\xFC", "\xFB"],
|
|
720
|
+
c: ["\xE7"],
|
|
721
|
+
g: ["\u011F"],
|
|
722
|
+
s: ["\u015F"]
|
|
723
|
+
};
|
|
724
|
+
static generateTurkishVariants(word) {
|
|
725
|
+
const lower = word.trim().toLocaleLowerCase("tr-TR");
|
|
726
|
+
const variants = [];
|
|
727
|
+
for (let i = 0; i < lower.length; i++) {
|
|
728
|
+
for (const replacement of this.TURKISH_DEASCII_MAP[lower[i]] ?? []) {
|
|
729
|
+
variants.push(lower.slice(0, i) + replacement + lower.slice(i + 1));
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
return variants;
|
|
733
|
+
}
|
|
703
734
|
/**
|
|
704
735
|
* Returns Kubbealtı Lugatı ("Misalli Büyük Türkçe Sözlük") entries for a
|
|
705
736
|
* word, scraped from the site's own data API — undocumented, and Kubbealtı
|
|
706
737
|
* Lugatı is a commercial dictionary product, unlike TDK's or Wiktionary's
|
|
707
738
|
* openly-published data, so use this in line with their terms. `anlam` is
|
|
708
739
|
* raw HTML (rich typography markup); use `getKubbealtiMeanings()` for
|
|
709
|
-
* plain text.
|
|
710
|
-
*
|
|
740
|
+
* plain text. Falls back to `generateTurkishVariants()` if the exact query
|
|
741
|
+
* comes up empty (see its doc comment). Returns `null` on any fetch/parse
|
|
742
|
+
* failure, `[]` if no variant matches either.
|
|
711
743
|
*/
|
|
712
744
|
static async getKubbealti(word) {
|
|
713
745
|
if (!word || word.trim() === "")
|
|
@@ -715,7 +747,16 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
715
747
|
const data = await this.fetchKubbealtiJson(`/rest/s/${encodeURIComponent(word.trim())}/`);
|
|
716
748
|
if (!data || !Array.isArray(data.content))
|
|
717
749
|
return null;
|
|
718
|
-
|
|
750
|
+
if (data.content.length > 0) {
|
|
751
|
+
return data.content.map((entry) => ({ kelime: entry.kelime, anlam: entry.anlam }));
|
|
752
|
+
}
|
|
753
|
+
for (const variant of this.generateTurkishVariants(word)) {
|
|
754
|
+
const variantData = await this.fetchKubbealtiJson(`/rest/s/${encodeURIComponent(variant)}/`);
|
|
755
|
+
if (variantData && Array.isArray(variantData.content) && variantData.content.length > 0) {
|
|
756
|
+
return variantData.content.map((entry) => ({ kelime: entry.kelime, anlam: entry.anlam }));
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
return [];
|
|
719
760
|
}
|
|
720
761
|
/**
|
|
721
762
|
* Same as `getKubbealti()` but with each entry's `anlam` HTML stripped to
|
|
@@ -769,21 +810,10 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
769
810
|
return null;
|
|
770
811
|
}
|
|
771
812
|
}
|
|
772
|
-
|
|
773
|
-
* Returns the Turkish Wiktionary (`tr.wiktionary.org`) entry for a word,
|
|
774
|
-
* via MediaWiki's official Action API (`action=query&prop=extracts`) — no
|
|
775
|
-
* scraping involved, this is a stable, documented public API. `sections`
|
|
776
|
-
* splits the plain-text extract on its `== Heading ==`/`=== Heading ===`
|
|
777
|
-
* markers (e.g. "Köken", "Söyleniş", "Ad") for convenience; `raw` has the
|
|
778
|
-
* unsplit text. Returns `null` if the page doesn't exist or the request
|
|
779
|
-
* fails.
|
|
780
|
-
*/
|
|
781
|
-
static async getWiktionary(word) {
|
|
782
|
-
if (!word || word.trim() === "")
|
|
783
|
-
return null;
|
|
813
|
+
static async fetchWiktionaryEntry(title) {
|
|
784
814
|
try {
|
|
785
815
|
const url = `https://tr.wiktionary.org/w/api.php?action=query&prop=extracts&titles=${encodeURIComponent(
|
|
786
|
-
|
|
816
|
+
title
|
|
787
817
|
)}&format=json&explaintext=1&formatversion=2`;
|
|
788
818
|
const response = await fetch(url, { headers: { "User-Agent": "TDK-API-Nodejs-Wrapper/1.0" } });
|
|
789
819
|
if (!response.ok)
|
|
@@ -796,16 +826,42 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
796
826
|
const sections = {};
|
|
797
827
|
const parts = raw.split(/\n(={2,4})\s*(.+?)\s*\1\n/);
|
|
798
828
|
for (let i = 1; i < parts.length; i += 3) {
|
|
799
|
-
const
|
|
829
|
+
const title2 = parts[i + 1]?.trim();
|
|
800
830
|
const content = parts[i + 2]?.trim();
|
|
801
|
-
if (
|
|
802
|
-
sections[
|
|
831
|
+
if (title2)
|
|
832
|
+
sections[title2] = content ?? "";
|
|
803
833
|
}
|
|
804
834
|
return { raw, sections };
|
|
805
835
|
} catch {
|
|
806
836
|
return null;
|
|
807
837
|
}
|
|
808
838
|
}
|
|
839
|
+
/**
|
|
840
|
+
* Returns the Turkish Wiktionary (`tr.wiktionary.org`) entry for a word,
|
|
841
|
+
* via MediaWiki's official Action API (`action=query&prop=extracts`) — no
|
|
842
|
+
* scraping involved, this is a stable, documented public API. `sections`
|
|
843
|
+
* splits the plain-text extract on its `== Heading ==`/`=== Heading ===`
|
|
844
|
+
* markers (e.g. "Köken", "Söyleniş", "Ad") for convenience; `raw` has the
|
|
845
|
+
* unsplit text. This wiki has title capitalization turned off
|
|
846
|
+
* ($wgCapitalLinks=false — common for Wiktionaries, since case is
|
|
847
|
+
* meaningful for a dictionary: "Türkiye" the country vs. a lowercase
|
|
848
|
+
* common word), so an exact-case miss retries with the first letter
|
|
849
|
+
* uppercased (Turkish-locale-aware, so "istanbul" tries "İstanbul", not
|
|
850
|
+
* "Istanbul") before giving up. Returns `null` if neither is found or the
|
|
851
|
+
* request fails.
|
|
852
|
+
*/
|
|
853
|
+
static async getWiktionary(word) {
|
|
854
|
+
if (!word || word.trim() === "")
|
|
855
|
+
return null;
|
|
856
|
+
const trimmed = word.trim();
|
|
857
|
+
const direct = await this.fetchWiktionaryEntry(trimmed);
|
|
858
|
+
if (direct)
|
|
859
|
+
return direct;
|
|
860
|
+
const capitalized = trimmed.charAt(0).toLocaleUpperCase("tr-TR") + trimmed.slice(1);
|
|
861
|
+
if (capitalized === trimmed)
|
|
862
|
+
return null;
|
|
863
|
+
return this.fetchWiktionaryEntry(capitalized);
|
|
864
|
+
}
|
|
809
865
|
/**
|
|
810
866
|
* Convenience filter over `getWiktionary()`: returns just one section's
|
|
811
867
|
* text (e.g. `getWiktionarySection(word, "Köken")` for etymology), matched
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
package/src/tdk.ts
CHANGED
|
@@ -713,20 +713,65 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
713
713
|
});
|
|
714
714
|
}
|
|
715
715
|
|
|
716
|
+
/**
|
|
717
|
+
* Kubbealtı indexes headwords with full classical Turkish orthography,
|
|
718
|
+
* including letters that a plain-ASCII-ish query tends to drop — most
|
|
719
|
+
* commonly ü/ö/ç/ğ/ş, but also the circumflex ("düzeltme işareti") used in
|
|
720
|
+
* Arabic/Persian loanwords like "rüzgâr". A search for "ruzgar" misses
|
|
721
|
+
* entirely (verified: even "ruzgâr" alone still misses — it's the missing
|
|
722
|
+
* ü, not the missing â, that actually breaks the match). This generates
|
|
723
|
+
* single-letter-substitution variants to retry, one substitution per
|
|
724
|
+
* variant (not combinatorial) — covers the overwhelmingly common case of
|
|
725
|
+
* one "de-Turkished" letter without an explosion of API calls for words
|
|
726
|
+
* with several.
|
|
727
|
+
*/
|
|
728
|
+
private static readonly TURKISH_DEASCII_MAP: Record<string, string[]> = {
|
|
729
|
+
a: ["â"],
|
|
730
|
+
i: ["ı", "î"],
|
|
731
|
+
o: ["ö"],
|
|
732
|
+
u: ["ü", "û"],
|
|
733
|
+
c: ["ç"],
|
|
734
|
+
g: ["ğ"],
|
|
735
|
+
s: ["ş"],
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
private static generateTurkishVariants(word: string): string[] {
|
|
739
|
+
const lower = word.trim().toLocaleLowerCase("tr-TR");
|
|
740
|
+
const variants: string[] = [];
|
|
741
|
+
for (let i = 0; i < lower.length; i++) {
|
|
742
|
+
for (const replacement of this.TURKISH_DEASCII_MAP[lower[i]] ?? []) {
|
|
743
|
+
variants.push(lower.slice(0, i) + replacement + lower.slice(i + 1));
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
return variants;
|
|
747
|
+
}
|
|
748
|
+
|
|
716
749
|
/**
|
|
717
750
|
* Returns Kubbealtı Lugatı ("Misalli Büyük Türkçe Sözlük") entries for a
|
|
718
751
|
* word, scraped from the site's own data API — undocumented, and Kubbealtı
|
|
719
752
|
* Lugatı is a commercial dictionary product, unlike TDK's or Wiktionary's
|
|
720
753
|
* openly-published data, so use this in line with their terms. `anlam` is
|
|
721
754
|
* raw HTML (rich typography markup); use `getKubbealtiMeanings()` for
|
|
722
|
-
* plain text.
|
|
723
|
-
*
|
|
755
|
+
* plain text. Falls back to `generateTurkishVariants()` if the exact query
|
|
756
|
+
* comes up empty (see its doc comment). Returns `null` on any fetch/parse
|
|
757
|
+
* failure, `[]` if no variant matches either.
|
|
724
758
|
*/
|
|
725
759
|
public static async getKubbealti(word: string): Promise<KubbealtiEntry[] | null> {
|
|
726
760
|
if (!word || word.trim() === "") return null;
|
|
761
|
+
|
|
727
762
|
const data = await this.fetchKubbealtiJson(`/rest/s/${encodeURIComponent(word.trim())}/`);
|
|
728
763
|
if (!data || !Array.isArray(data.content)) return null;
|
|
729
|
-
|
|
764
|
+
if (data.content.length > 0) {
|
|
765
|
+
return data.content.map((entry: any) => ({ kelime: entry.kelime, anlam: entry.anlam }));
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
for (const variant of this.generateTurkishVariants(word)) {
|
|
769
|
+
const variantData = await this.fetchKubbealtiJson(`/rest/s/${encodeURIComponent(variant)}/`);
|
|
770
|
+
if (variantData && Array.isArray(variantData.content) && variantData.content.length > 0) {
|
|
771
|
+
return variantData.content.map((entry: any) => ({ kelime: entry.kelime, anlam: entry.anlam }));
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
return [];
|
|
730
775
|
}
|
|
731
776
|
|
|
732
777
|
/**
|
|
@@ -777,20 +822,10 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
777
822
|
}
|
|
778
823
|
}
|
|
779
824
|
|
|
780
|
-
|
|
781
|
-
* Returns the Turkish Wiktionary (`tr.wiktionary.org`) entry for a word,
|
|
782
|
-
* via MediaWiki's official Action API (`action=query&prop=extracts`) — no
|
|
783
|
-
* scraping involved, this is a stable, documented public API. `sections`
|
|
784
|
-
* splits the plain-text extract on its `== Heading ==`/`=== Heading ===`
|
|
785
|
-
* markers (e.g. "Köken", "Söyleniş", "Ad") for convenience; `raw` has the
|
|
786
|
-
* unsplit text. Returns `null` if the page doesn't exist or the request
|
|
787
|
-
* fails.
|
|
788
|
-
*/
|
|
789
|
-
public static async getWiktionary(word: string): Promise<WiktionaryEntry | null> {
|
|
790
|
-
if (!word || word.trim() === "") return null;
|
|
825
|
+
private static async fetchWiktionaryEntry(title: string): Promise<WiktionaryEntry | null> {
|
|
791
826
|
try {
|
|
792
827
|
const url = `https://tr.wiktionary.org/w/api.php?action=query&prop=extracts&titles=${encodeURIComponent(
|
|
793
|
-
|
|
828
|
+
title
|
|
794
829
|
)}&format=json&explaintext=1&formatversion=2`;
|
|
795
830
|
const response = await fetch(url, { headers: { "User-Agent": "TDK-API-Nodejs-Wrapper/1.0" } });
|
|
796
831
|
if (!response.ok) return null;
|
|
@@ -814,6 +849,32 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
814
849
|
}
|
|
815
850
|
}
|
|
816
851
|
|
|
852
|
+
/**
|
|
853
|
+
* Returns the Turkish Wiktionary (`tr.wiktionary.org`) entry for a word,
|
|
854
|
+
* via MediaWiki's official Action API (`action=query&prop=extracts`) — no
|
|
855
|
+
* scraping involved, this is a stable, documented public API. `sections`
|
|
856
|
+
* splits the plain-text extract on its `== Heading ==`/`=== Heading ===`
|
|
857
|
+
* markers (e.g. "Köken", "Söyleniş", "Ad") for convenience; `raw` has the
|
|
858
|
+
* unsplit text. This wiki has title capitalization turned off
|
|
859
|
+
* ($wgCapitalLinks=false — common for Wiktionaries, since case is
|
|
860
|
+
* meaningful for a dictionary: "Türkiye" the country vs. a lowercase
|
|
861
|
+
* common word), so an exact-case miss retries with the first letter
|
|
862
|
+
* uppercased (Turkish-locale-aware, so "istanbul" tries "İstanbul", not
|
|
863
|
+
* "Istanbul") before giving up. Returns `null` if neither is found or the
|
|
864
|
+
* request fails.
|
|
865
|
+
*/
|
|
866
|
+
public static async getWiktionary(word: string): Promise<WiktionaryEntry | null> {
|
|
867
|
+
if (!word || word.trim() === "") return null;
|
|
868
|
+
const trimmed = word.trim();
|
|
869
|
+
|
|
870
|
+
const direct = await this.fetchWiktionaryEntry(trimmed);
|
|
871
|
+
if (direct) return direct;
|
|
872
|
+
|
|
873
|
+
const capitalized = trimmed.charAt(0).toLocaleUpperCase("tr-TR") + trimmed.slice(1);
|
|
874
|
+
if (capitalized === trimmed) return null;
|
|
875
|
+
return this.fetchWiktionaryEntry(capitalized);
|
|
876
|
+
}
|
|
877
|
+
|
|
817
878
|
/**
|
|
818
879
|
* Convenience filter over `getWiktionary()`: returns just one section's
|
|
819
880
|
* text (e.g. `getWiktionarySection(word, "Köken")` for etymology), matched
|