tdk-api-wrapper 1.7.0 → 1.7.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/LICENSE +674 -21
- package/README.md +2 -2
- package/dist/{chunk-ZFWZXNGY.mjs → chunk-YY4WA2AO.mjs} +126 -142
- package/dist/{chunk-MELLECWT.mjs → chunk-ZG7YRT7V.mjs} +1 -1
- package/dist/cli.js +332 -300
- package/dist/cli.mjs +2 -2
- package/dist/index.d.mts +8 -37
- package/dist/index.d.ts +8 -37
- package/dist/index.js +125 -141
- package/dist/index.mjs +2 -2
- package/dist/{mcp-NAXIX4TQ.mjs → mcp-GBTXQJLW.mjs} +2 -2
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -71,168 +71,12 @@ var init_errors = __esm({
|
|
|
71
71
|
}
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
// src/
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
function restoreConsonantSoftening(stem) {
|
|
79
|
-
if (stem.length < 2)
|
|
80
|
-
return [];
|
|
81
|
-
const last = stem.slice(-1);
|
|
82
|
-
const base = stem.slice(0, -1);
|
|
83
|
-
switch (last) {
|
|
84
|
-
case "b":
|
|
85
|
-
return [base + "p"];
|
|
86
|
-
case "c":
|
|
87
|
-
return [base + "\xE7"];
|
|
88
|
-
case "d":
|
|
89
|
-
return [base + "t"];
|
|
90
|
-
case "\u011F":
|
|
91
|
-
return [base + "k"];
|
|
92
|
-
case "g":
|
|
93
|
-
return [base + "k"];
|
|
94
|
-
default:
|
|
95
|
-
return [];
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
function restoreVowelDrop(stem) {
|
|
99
|
-
if (stem.length < 3)
|
|
100
|
-
return [];
|
|
101
|
-
const c1 = stem[stem.length - 2];
|
|
102
|
-
const c2 = stem[stem.length - 1];
|
|
103
|
-
if (!isVowel(c1) && !isVowel(c2)) {
|
|
104
|
-
const vowelsInBase = stem.slice(0, -2).split("").filter(isVowel);
|
|
105
|
-
if (vowelsInBase.length > 0) {
|
|
106
|
-
const lastVowel = vowelsInBase[vowelsInBase.length - 1];
|
|
107
|
-
let inserted = "i";
|
|
108
|
-
if ("a\u0131".includes(lastVowel))
|
|
109
|
-
inserted = "\u0131";
|
|
110
|
-
else if ("ei".includes(lastVowel))
|
|
111
|
-
inserted = "i";
|
|
112
|
-
else if ("ou".includes(lastVowel))
|
|
113
|
-
inserted = "u";
|
|
114
|
-
else if ("\xF6\xFC".includes(lastVowel))
|
|
115
|
-
inserted = "\xFC";
|
|
116
|
-
return [stem.slice(0, -1) + inserted + c2];
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
return [];
|
|
120
|
-
}
|
|
121
|
-
function restoreGemination(stem) {
|
|
122
|
-
if (stem.length < 3)
|
|
123
|
-
return [];
|
|
124
|
-
const c1 = stem[stem.length - 2];
|
|
125
|
-
const c2 = stem[stem.length - 1];
|
|
126
|
-
if (c1 === c2 && !isVowel(c1)) {
|
|
127
|
-
const single = stem.slice(0, -1);
|
|
128
|
-
const hardened = restoreConsonantSoftening(single);
|
|
129
|
-
return [single, ...hardened];
|
|
130
|
-
}
|
|
131
|
-
return [];
|
|
132
|
-
}
|
|
133
|
-
function restoreVowelNarrowing(stem) {
|
|
134
|
-
if (stem.length < 2)
|
|
135
|
-
return [];
|
|
136
|
-
if (stem === "di")
|
|
137
|
-
return ["de"];
|
|
138
|
-
if (stem === "yi")
|
|
139
|
-
return ["ye"];
|
|
140
|
-
const lastChar = stem[stem.length - 1];
|
|
141
|
-
const isLastNarrow = "\u0131iu\xFC".includes(lastChar);
|
|
142
|
-
if (isLastNarrow) {
|
|
143
|
-
const vowelsInBase = stem.slice(0, -1).split("").filter(isVowel);
|
|
144
|
-
const lastVowel = vowelsInBase.length > 0 ? vowelsInBase[vowelsInBase.length - 1] : lastChar;
|
|
145
|
-
const widened = "a\u0131ou".includes(lastVowel) ? "a" : "e";
|
|
146
|
-
return [stem.slice(0, -1) + widened];
|
|
147
|
-
}
|
|
148
|
-
if (!isVowel(lastChar)) {
|
|
149
|
-
const vowelsInBase = stem.split("").filter(isVowel);
|
|
150
|
-
if (vowelsInBase.length > 0) {
|
|
151
|
-
const lastVowel = vowelsInBase[vowelsInBase.length - 1];
|
|
152
|
-
const widened = "a\u0131ou".includes(lastVowel) ? "a" : "e";
|
|
153
|
-
return [stem + widened];
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return [];
|
|
157
|
-
}
|
|
158
|
-
function restoreInfinitive(stem) {
|
|
159
|
-
if (stem.length < 2)
|
|
160
|
-
return [];
|
|
161
|
-
const vowelsInBase = stem.split("").filter(isVowel);
|
|
162
|
-
if (vowelsInBase.length === 0)
|
|
163
|
-
return [];
|
|
164
|
-
const lastVowel = vowelsInBase[vowelsInBase.length - 1];
|
|
165
|
-
return "a\u0131ou".includes(lastVowel) ? [stem + "mak"] : [stem + "mek"];
|
|
166
|
-
}
|
|
167
|
-
function getStemCandidates(word2, minStemLength = 2, maxDepth = 4) {
|
|
168
|
-
if (!word2 || word2.trim().length === 0)
|
|
169
|
-
return [];
|
|
170
|
-
const raw = word2.trim();
|
|
171
|
-
const normalized = raw.toLocaleLowerCase("tr-TR");
|
|
172
|
-
const candidatesWithWeight = [];
|
|
173
|
-
const seen = /* @__PURE__ */ new Set();
|
|
174
|
-
if (raw.includes("'") || raw.includes("\u2019")) {
|
|
175
|
-
const apostropheStem = normalized.split(/['’]/)[0];
|
|
176
|
-
if (apostropheStem.length >= minStemLength) {
|
|
177
|
-
candidatesWithWeight.push({ candidate: apostropheStem, baseLength: apostropheStem.length + 10 });
|
|
178
|
-
seen.add(apostropheStem);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
const bareInfinitives = restoreInfinitive(normalized);
|
|
182
|
-
for (const inf of bareInfinitives) {
|
|
183
|
-
if (!seen.has(inf) && inf !== normalized) {
|
|
184
|
-
seen.add(inf);
|
|
185
|
-
candidatesWithWeight.push({ candidate: inf, baseLength: normalized.length });
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
let frontier = [normalized];
|
|
189
|
-
for (let depth = 0; depth < maxDepth; depth++) {
|
|
190
|
-
const nextFrontier = [];
|
|
191
|
-
for (const current of frontier) {
|
|
192
|
-
for (const suffix of TURKISH_SUFFIXES) {
|
|
193
|
-
if (current.length - suffix.length >= minStemLength && current.endsWith(suffix)) {
|
|
194
|
-
const stem = current.slice(0, -suffix.length);
|
|
195
|
-
const hardened = restoreConsonantSoftening(stem);
|
|
196
|
-
const vowelDropped = restoreVowelDrop(stem);
|
|
197
|
-
const geminated = restoreGemination(stem);
|
|
198
|
-
const isNarrowingSuffix = suffix.startsWith("yor") || suffix.includes("iyor") || suffix.includes("\u0131yor") || suffix.includes("uyor") || suffix.includes("\xFCyor");
|
|
199
|
-
const isDeYeBuffer = (stem === "di" || stem === "yi") && suffix.startsWith("y");
|
|
200
|
-
const narrowed = isNarrowingSuffix || isDeYeBuffer ? restoreVowelNarrowing(stem) : [];
|
|
201
|
-
const isVerbSuffix = isNarrowingSuffix || suffix.includes("ecek") || suffix.includes("acak") || suffix.includes("mi\u015F") || suffix.includes("m\u0131\u015F") || suffix.includes("m\xFC\u015F") || suffix.includes("mu\u015F") || suffix.includes("mek") || suffix.includes("mak") || suffix.includes("erek") || suffix.includes("arak") || suffix.includes("dik") || suffix.includes("d\u0131k") || suffix.includes("duk") || suffix.includes("d\xFCk") || suffix.includes("tik") || suffix.includes("t\u0131k") || suffix.includes("tuk") || suffix.includes("t\xFCk") || suffix.includes("sen") || suffix.includes("san") || suffix.includes("sem") || suffix.includes("sam") || suffix.includes("sek") || suffix.includes("sak");
|
|
202
|
-
const verbalBases = [stem, ...hardened, ...narrowed];
|
|
203
|
-
const infinitives = verbalBases.flatMap((v) => restoreInfinitive(v));
|
|
204
|
-
const variants = [stem, ...hardened, ...vowelDropped, ...geminated, ...narrowed];
|
|
205
|
-
for (const variant of variants) {
|
|
206
|
-
if (!seen.has(variant) && variant !== normalized) {
|
|
207
|
-
seen.add(variant);
|
|
208
|
-
nextFrontier.push(variant);
|
|
209
|
-
candidatesWithWeight.push({ candidate: variant, baseLength: stem.length });
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
for (const inf of infinitives) {
|
|
213
|
-
if (!seen.has(inf) && inf !== normalized) {
|
|
214
|
-
seen.add(inf);
|
|
215
|
-
nextFrontier.push(inf);
|
|
216
|
-
const weight = isVerbSuffix ? stem.length + 5 : stem.length;
|
|
217
|
-
candidatesWithWeight.push({ candidate: inf, baseLength: weight });
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
if (nextFrontier.length === 0)
|
|
224
|
-
break;
|
|
225
|
-
frontier = nextFrontier;
|
|
226
|
-
}
|
|
227
|
-
candidatesWithWeight.sort((a, b) => b.baseLength - a.baseLength);
|
|
228
|
-
return [...new Set(candidatesWithWeight.map((c2) => c2.candidate))];
|
|
229
|
-
}
|
|
230
|
-
var TURKISH_VOWELS, TURKISH_SUFFIXES;
|
|
231
|
-
var init_morphology = __esm({
|
|
232
|
-
"src/morphology.ts"() {
|
|
74
|
+
// src/data/suffixes.ts
|
|
75
|
+
var TURKISH_SUFFIXES;
|
|
76
|
+
var init_suffixes = __esm({
|
|
77
|
+
"src/data/suffixes.ts"() {
|
|
233
78
|
"use strict";
|
|
234
79
|
init_cjs_shims();
|
|
235
|
-
TURKISH_VOWELS = "ae\u0131io\xF6u\xFC";
|
|
236
80
|
TURKISH_SUFFIXES = [
|
|
237
81
|
// 9-letter composite suffixes
|
|
238
82
|
"lerimizden",
|
|
@@ -638,36 +482,179 @@ var init_morphology = __esm({
|
|
|
638
482
|
}
|
|
639
483
|
});
|
|
640
484
|
|
|
641
|
-
// src/
|
|
642
|
-
function
|
|
643
|
-
|
|
644
|
-
return 0;
|
|
645
|
-
if (DIACRITIC_SIBLINGS[a] === b)
|
|
646
|
-
return DIACRITIC_SUB_COST;
|
|
647
|
-
const pa = KEYBOARD_COORDS[a];
|
|
648
|
-
const pb = KEYBOARD_COORDS[b];
|
|
649
|
-
if (!pa || !pb)
|
|
650
|
-
return 1;
|
|
651
|
-
const dx = Math.abs(pa[0] - pb[0]);
|
|
652
|
-
const dy = Math.abs(pa[1] - pb[1]);
|
|
653
|
-
if (dy === 0 && dx <= 1 + 1e-9)
|
|
654
|
-
return KEYBOARD_ROW_SUB_COST;
|
|
655
|
-
if (dy === 1 && dx <= 1 + 1e-9)
|
|
656
|
-
return KEYBOARD_DIAGONAL_SUB_COST;
|
|
657
|
-
return 1;
|
|
485
|
+
// src/morphology.ts
|
|
486
|
+
function isVowel(ch) {
|
|
487
|
+
return TURKISH_VOWELS.includes(ch);
|
|
658
488
|
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
489
|
+
function restoreConsonantSoftening(stem) {
|
|
490
|
+
if (stem.length < 2)
|
|
491
|
+
return [];
|
|
492
|
+
const last = stem.slice(-1);
|
|
493
|
+
const base = stem.slice(0, -1);
|
|
494
|
+
switch (last) {
|
|
495
|
+
case "b":
|
|
496
|
+
return [base + "p"];
|
|
497
|
+
case "c":
|
|
498
|
+
return [base + "\xE7"];
|
|
499
|
+
case "d":
|
|
500
|
+
return [base + "t"];
|
|
501
|
+
case "\u011F":
|
|
502
|
+
return [base + "k"];
|
|
503
|
+
case "g":
|
|
504
|
+
return [base + "k"];
|
|
505
|
+
default:
|
|
506
|
+
return [];
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
function restoreVowelDrop(stem) {
|
|
510
|
+
if (stem.length < 3)
|
|
511
|
+
return [];
|
|
512
|
+
const c1 = stem[stem.length - 2];
|
|
513
|
+
const c2 = stem[stem.length - 1];
|
|
514
|
+
if (!isVowel(c1) && !isVowel(c2)) {
|
|
515
|
+
const vowelsInBase = stem.slice(0, -2).split("").filter(isVowel);
|
|
516
|
+
if (vowelsInBase.length > 0) {
|
|
517
|
+
const lastVowel = vowelsInBase[vowelsInBase.length - 1];
|
|
518
|
+
let inserted = "i";
|
|
519
|
+
if ("a\u0131".includes(lastVowel))
|
|
520
|
+
inserted = "\u0131";
|
|
521
|
+
else if ("ei".includes(lastVowel))
|
|
522
|
+
inserted = "i";
|
|
523
|
+
else if ("ou".includes(lastVowel))
|
|
524
|
+
inserted = "u";
|
|
525
|
+
else if ("\xF6\xFC".includes(lastVowel))
|
|
526
|
+
inserted = "\xFC";
|
|
527
|
+
return [stem.slice(0, -1) + inserted + c2];
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return [];
|
|
531
|
+
}
|
|
532
|
+
function restoreGemination(stem) {
|
|
533
|
+
if (stem.length < 3)
|
|
534
|
+
return [];
|
|
535
|
+
const c1 = stem[stem.length - 2];
|
|
536
|
+
const c2 = stem[stem.length - 1];
|
|
537
|
+
if (c1 === c2 && !isVowel(c1)) {
|
|
538
|
+
const single = stem.slice(0, -1);
|
|
539
|
+
const hardened = restoreConsonantSoftening(single);
|
|
540
|
+
return [single, ...hardened];
|
|
541
|
+
}
|
|
542
|
+
return [];
|
|
543
|
+
}
|
|
544
|
+
function restoreVowelNarrowing(stem) {
|
|
545
|
+
if (stem.length < 2)
|
|
546
|
+
return [];
|
|
547
|
+
if (stem === "di")
|
|
548
|
+
return ["de"];
|
|
549
|
+
if (stem === "yi")
|
|
550
|
+
return ["ye"];
|
|
551
|
+
const lastChar = stem[stem.length - 1];
|
|
552
|
+
const isLastNarrow = "\u0131iu\xFC".includes(lastChar);
|
|
553
|
+
if (isLastNarrow) {
|
|
554
|
+
const vowelsInBase = stem.slice(0, -1).split("").filter(isVowel);
|
|
555
|
+
const lastVowel = vowelsInBase.length > 0 ? vowelsInBase[vowelsInBase.length - 1] : lastChar;
|
|
556
|
+
const widened = "a\u0131ou".includes(lastVowel) ? "a" : "e";
|
|
557
|
+
return [stem.slice(0, -1) + widened];
|
|
558
|
+
}
|
|
559
|
+
if (!isVowel(lastChar)) {
|
|
560
|
+
const vowelsInBase = stem.split("").filter(isVowel);
|
|
561
|
+
if (vowelsInBase.length > 0) {
|
|
562
|
+
const lastVowel = vowelsInBase[vowelsInBase.length - 1];
|
|
563
|
+
const widened = "a\u0131ou".includes(lastVowel) ? "a" : "e";
|
|
564
|
+
return [stem + widened];
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
return [];
|
|
568
|
+
}
|
|
569
|
+
function restoreInfinitive(stem) {
|
|
570
|
+
if (stem.length < 2)
|
|
571
|
+
return [];
|
|
572
|
+
const vowelsInBase = stem.split("").filter(isVowel);
|
|
573
|
+
if (vowelsInBase.length === 0)
|
|
574
|
+
return [];
|
|
575
|
+
const lastVowel = vowelsInBase[vowelsInBase.length - 1];
|
|
576
|
+
return "a\u0131ou".includes(lastVowel) ? [stem + "mak"] : [stem + "mek"];
|
|
577
|
+
}
|
|
578
|
+
function getStemCandidates(word2, minStemLength = 2, maxDepth = 4) {
|
|
579
|
+
if (!word2 || word2.trim().length === 0)
|
|
580
|
+
return [];
|
|
581
|
+
const raw = word2.trim();
|
|
582
|
+
const normalized = raw.toLocaleLowerCase("tr-TR");
|
|
583
|
+
const candidatesWithWeight = [];
|
|
584
|
+
const seen = /* @__PURE__ */ new Set();
|
|
585
|
+
if (raw.includes("'") || raw.includes("\u2019")) {
|
|
586
|
+
const apostropheStem = normalized.split(/['’]/)[0];
|
|
587
|
+
if (apostropheStem.length >= minStemLength) {
|
|
588
|
+
candidatesWithWeight.push({ candidate: apostropheStem, baseLength: apostropheStem.length + 10 });
|
|
589
|
+
seen.add(apostropheStem);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
const bareInfinitives = restoreInfinitive(normalized);
|
|
593
|
+
for (const inf of bareInfinitives) {
|
|
594
|
+
if (!seen.has(inf) && inf !== normalized) {
|
|
595
|
+
seen.add(inf);
|
|
596
|
+
candidatesWithWeight.push({ candidate: inf, baseLength: normalized.length });
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
let frontier = [normalized];
|
|
600
|
+
for (let depth = 0; depth < maxDepth; depth++) {
|
|
601
|
+
const nextFrontier = [];
|
|
602
|
+
for (const current of frontier) {
|
|
603
|
+
for (const suffix of TURKISH_SUFFIXES) {
|
|
604
|
+
if (current.length - suffix.length >= minStemLength && current.endsWith(suffix)) {
|
|
605
|
+
const stem = current.slice(0, -suffix.length);
|
|
606
|
+
const hardened = restoreConsonantSoftening(stem);
|
|
607
|
+
const vowelDropped = restoreVowelDrop(stem);
|
|
608
|
+
const geminated = restoreGemination(stem);
|
|
609
|
+
const isNarrowingSuffix = suffix.startsWith("yor") || suffix.includes("iyor") || suffix.includes("\u0131yor") || suffix.includes("uyor") || suffix.includes("\xFCyor");
|
|
610
|
+
const isDeYeBuffer = (stem === "di" || stem === "yi") && suffix.startsWith("y");
|
|
611
|
+
const narrowed = isNarrowingSuffix || isDeYeBuffer ? restoreVowelNarrowing(stem) : [];
|
|
612
|
+
const isVerbSuffix = isNarrowingSuffix || suffix.includes("ecek") || suffix.includes("acak") || suffix.includes("mi\u015F") || suffix.includes("m\u0131\u015F") || suffix.includes("m\xFC\u015F") || suffix.includes("mu\u015F") || suffix.includes("mek") || suffix.includes("mak") || suffix.includes("erek") || suffix.includes("arak") || suffix.includes("dik") || suffix.includes("d\u0131k") || suffix.includes("duk") || suffix.includes("d\xFCk") || suffix.includes("tik") || suffix.includes("t\u0131k") || suffix.includes("tuk") || suffix.includes("t\xFCk") || suffix.includes("sen") || suffix.includes("san") || suffix.includes("sem") || suffix.includes("sam") || suffix.includes("sek") || suffix.includes("sak");
|
|
613
|
+
const verbalBases = [stem, ...hardened, ...narrowed];
|
|
614
|
+
const infinitives = verbalBases.flatMap((v) => restoreInfinitive(v));
|
|
615
|
+
const variants = [stem, ...hardened, ...vowelDropped, ...geminated, ...narrowed];
|
|
616
|
+
for (const variant of variants) {
|
|
617
|
+
if (!seen.has(variant) && variant !== normalized) {
|
|
618
|
+
seen.add(variant);
|
|
619
|
+
nextFrontier.push(variant);
|
|
620
|
+
candidatesWithWeight.push({ candidate: variant, baseLength: stem.length });
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
for (const inf of infinitives) {
|
|
624
|
+
if (!seen.has(inf) && inf !== normalized) {
|
|
625
|
+
seen.add(inf);
|
|
626
|
+
nextFrontier.push(inf);
|
|
627
|
+
const weight = isVerbSuffix ? stem.length + 5 : stem.length;
|
|
628
|
+
candidatesWithWeight.push({ candidate: inf, baseLength: weight });
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (nextFrontier.length === 0)
|
|
635
|
+
break;
|
|
636
|
+
frontier = nextFrontier;
|
|
637
|
+
}
|
|
638
|
+
candidatesWithWeight.sort((a, b) => b.baseLength - a.baseLength);
|
|
639
|
+
return [...new Set(candidatesWithWeight.map((c2) => c2.candidate))];
|
|
640
|
+
}
|
|
641
|
+
var TURKISH_VOWELS;
|
|
642
|
+
var init_morphology = __esm({
|
|
643
|
+
"src/morphology.ts"() {
|
|
644
|
+
"use strict";
|
|
645
|
+
init_cjs_shims();
|
|
646
|
+
init_suffixes();
|
|
647
|
+
init_suffixes();
|
|
648
|
+
TURKISH_VOWELS = "ae\u0131io\xF6u\xFC";
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
// src/data/misspellings.ts
|
|
653
|
+
var COMMON_MISSPELLINGS, SEY_EXCEPTIONS;
|
|
654
|
+
var init_misspellings = __esm({
|
|
655
|
+
"src/data/misspellings.ts"() {
|
|
662
656
|
"use strict";
|
|
663
657
|
init_cjs_shims();
|
|
664
|
-
init_errors();
|
|
665
|
-
init_morphology();
|
|
666
|
-
fs = __toESM(require("fs"));
|
|
667
|
-
path = __toESM(require("path"));
|
|
668
|
-
os = __toESM(require("os"));
|
|
669
|
-
https = __toESM(require("https"));
|
|
670
|
-
tls = __toESM(require("tls"));
|
|
671
658
|
COMMON_MISSPELLINGS = {
|
|
672
659
|
// -şey ile biten ve ayrı yazılması zorunlu söz öbekleri
|
|
673
660
|
her\u015Fey: "her \u015Fey",
|
|
@@ -821,58 +808,17 @@ var init_tdk = __esm({
|
|
|
821
808
|
babaanne: "babaanne"
|
|
822
809
|
};
|
|
823
810
|
SEY_EXCEPTIONS = /* @__PURE__ */ new Set(["d\xFC\u015Fey", "e\u015Fey", "konsey", "jersey", "\u015Fey"]);
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
});
|
|
836
|
-
return coords;
|
|
837
|
-
})();
|
|
838
|
-
DIACRITIC_SIBLINGS = {
|
|
839
|
-
\u0131: "i",
|
|
840
|
-
i: "\u0131",
|
|
841
|
-
\u00F6: "o",
|
|
842
|
-
o: "\xF6",
|
|
843
|
-
\u00FC: "u",
|
|
844
|
-
u: "\xFC",
|
|
845
|
-
\u015F: "s",
|
|
846
|
-
s: "\u015F",
|
|
847
|
-
\u00E7: "c",
|
|
848
|
-
c: "\xE7",
|
|
849
|
-
\u011F: "g",
|
|
850
|
-
g: "\u011F",
|
|
851
|
-
\u00E2: "a",
|
|
852
|
-
a: "\xE2"
|
|
853
|
-
};
|
|
854
|
-
KEYBOARD_ROW_SUB_COST = 0.4;
|
|
855
|
-
KEYBOARD_DIAGONAL_SUB_COST = 0.55;
|
|
856
|
-
DIACRITIC_SUB_COST = 0.3;
|
|
857
|
-
TRANSPOSITION_COST = 0.8;
|
|
858
|
-
TDK = class {
|
|
859
|
-
static BASE_URL = "https://sozluk.gov.tr";
|
|
860
|
-
static AUDIO_API_HOST = "api.sozluk.gov.tr";
|
|
861
|
-
static KUBBEALTI_HOST = "eski.lugatim.com";
|
|
862
|
-
/**
|
|
863
|
-
* `eski.lugatim.com` (Kubbealtı Lugatı's data API) sends only its leaf
|
|
864
|
-
* certificate during the TLS handshake, omitting the intermediates a
|
|
865
|
-
* correctly configured server would include — a server-side misconfiguration,
|
|
866
|
-
* not something we should paper over by disabling verification. These are
|
|
867
|
-
* the two certificates the server *should* be sending (fetched from the
|
|
868
|
-
* leaf's own Authority Information Access URLs), supplied here so Node can
|
|
869
|
-
* still build a full, properly verified chain up to a root it already
|
|
870
|
-
* trusts (ISRG Root X1). If Let's Encrypt rotates this intermediate, this
|
|
871
|
-
* stops working and every Kubbealtı call fails closed to `null` — same
|
|
872
|
-
* fail-closed contract as the rest of this file's fragile integrations.
|
|
873
|
-
*/
|
|
874
|
-
static KUBBEALTI_EXTRA_CA = [
|
|
875
|
-
`-----BEGIN CERTIFICATE-----
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
// src/data/kubbealti-ca.ts
|
|
815
|
+
var KUBBEALTI_EXTRA_CA;
|
|
816
|
+
var init_kubbealti_ca = __esm({
|
|
817
|
+
"src/data/kubbealti-ca.ts"() {
|
|
818
|
+
"use strict";
|
|
819
|
+
init_cjs_shims();
|
|
820
|
+
KUBBEALTI_EXTRA_CA = [
|
|
821
|
+
`-----BEGIN CERTIFICATE-----
|
|
876
822
|
MIIE2jCCAsKgAwIBAgIQTr0klH4k05SALYSlL9WzGTANBgkqhkiG9w0BAQsFADAu
|
|
877
823
|
MQswCQYDVQQGEwJVUzENMAsGA1UEChMESVNSRzEQMA4GA1UEAxMHUm9vdCBZUjAe
|
|
878
824
|
Fw0yNTA5MDMwMDAwMDBaFw0yODA5MDIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYw
|
|
@@ -900,7 +846,7 @@ NA3wJdl4DDUuQSV8hBgx6zoI1ZSGORprDFux7c6rhc77QZMSRrEgomBeklervEve
|
|
|
900
846
|
86ylWmZ3WWHV6RLMi8xNvjd71r4EPIGgY7BZU/VPBkq+uA7Gb6mbJnFgV43uh3xy
|
|
901
847
|
LRFgxIAphIukwTGSMZZR+AI+Qnp0BYTWovHXozOf3H8r6hozEoT02JHn0AeTfA==
|
|
902
848
|
-----END CERTIFICATE-----`,
|
|
903
|
-
|
|
849
|
+
`-----BEGIN CERTIFICATE-----
|
|
904
850
|
MIIF9DCCA9ygAwIBAgIRAPJLbRf52a18scn+p4eCaZ8wDQYJKoZIhvcNAQELBQAw
|
|
905
851
|
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
|
906
852
|
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjYwNTEzMDAwMDAw
|
|
@@ -934,7 +880,146 @@ RGMuHGnzS3hFIrRTfKxrzUZ9RzQWzEG3K6fJ3r2nqSltkeytis9DIBoFY9VmVyjL
|
|
|
934
880
|
M71DMi+y1+TRSJVClEMwvA4yL++7q9XZx5r5wBRWB4kQTKH5qyoZnDw7iiuh1lID
|
|
935
881
|
yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
936
882
|
-----END CERTIFICATE-----`
|
|
937
|
-
|
|
883
|
+
];
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
// src/data/keyboard-layout.ts
|
|
888
|
+
function keyboardSubCost(a, b) {
|
|
889
|
+
if (a === b)
|
|
890
|
+
return 0;
|
|
891
|
+
if (DIACRITIC_SIBLINGS[a] === b)
|
|
892
|
+
return DIACRITIC_SUB_COST;
|
|
893
|
+
const pa = KEYBOARD_COORDS[a];
|
|
894
|
+
const pb = KEYBOARD_COORDS[b];
|
|
895
|
+
if (!pa || !pb)
|
|
896
|
+
return 1;
|
|
897
|
+
const dx = Math.abs(pa[0] - pb[0]);
|
|
898
|
+
const dy = Math.abs(pa[1] - pb[1]);
|
|
899
|
+
if (dy === 0 && dx <= 1 + 1e-9)
|
|
900
|
+
return KEYBOARD_ROW_SUB_COST;
|
|
901
|
+
if (dy === 1 && dx <= 1 + 1e-9)
|
|
902
|
+
return KEYBOARD_DIAGONAL_SUB_COST;
|
|
903
|
+
return 1;
|
|
904
|
+
}
|
|
905
|
+
var KEYBOARD_ROWS, KEYBOARD_COORDS, DIACRITIC_SIBLINGS, KEYBOARD_ROW_SUB_COST, KEYBOARD_DIAGONAL_SUB_COST, DIACRITIC_SUB_COST, TRANSPOSITION_COST;
|
|
906
|
+
var init_keyboard_layout = __esm({
|
|
907
|
+
"src/data/keyboard-layout.ts"() {
|
|
908
|
+
"use strict";
|
|
909
|
+
init_cjs_shims();
|
|
910
|
+
KEYBOARD_ROWS = [
|
|
911
|
+
["qwertyu\u0131op\u011F\xFC", 0],
|
|
912
|
+
["asdfghjkl\u015Fi", 0.5],
|
|
913
|
+
["zxcvbnm\xF6\xE7", 1]
|
|
914
|
+
];
|
|
915
|
+
KEYBOARD_COORDS = (() => {
|
|
916
|
+
const coords = {};
|
|
917
|
+
KEYBOARD_ROWS.forEach(([keys, offset], row) => {
|
|
918
|
+
[...keys].forEach((key, col) => {
|
|
919
|
+
coords[key] = [col + offset, row];
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
return coords;
|
|
923
|
+
})();
|
|
924
|
+
DIACRITIC_SIBLINGS = {
|
|
925
|
+
\u0131: "i",
|
|
926
|
+
i: "\u0131",
|
|
927
|
+
\u00F6: "o",
|
|
928
|
+
o: "\xF6",
|
|
929
|
+
\u00FC: "u",
|
|
930
|
+
u: "\xFC",
|
|
931
|
+
\u015F: "s",
|
|
932
|
+
s: "\u015F",
|
|
933
|
+
\u00E7: "c",
|
|
934
|
+
c: "\xE7",
|
|
935
|
+
\u011F: "g",
|
|
936
|
+
g: "\u011F",
|
|
937
|
+
\u00E2: "a",
|
|
938
|
+
a: "\xE2"
|
|
939
|
+
};
|
|
940
|
+
KEYBOARD_ROW_SUB_COST = 0.4;
|
|
941
|
+
KEYBOARD_DIAGONAL_SUB_COST = 0.55;
|
|
942
|
+
DIACRITIC_SUB_COST = 0.3;
|
|
943
|
+
TRANSPOSITION_COST = 0.8;
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
// src/lib/edit-distance.ts
|
|
948
|
+
function damerauLevenshtein(a, b) {
|
|
949
|
+
const dp = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
950
|
+
for (let i = 0; i <= a.length; i++)
|
|
951
|
+
dp[i][0] = i;
|
|
952
|
+
for (let j = 0; j <= b.length; j++)
|
|
953
|
+
dp[0][j] = j;
|
|
954
|
+
for (let i = 1; i <= a.length; i++) {
|
|
955
|
+
for (let j = 1; j <= b.length; j++) {
|
|
956
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
957
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
958
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
959
|
+
dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + cost);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
return dp[a.length][b.length];
|
|
964
|
+
}
|
|
965
|
+
function keyboardAwareDistance(a, b) {
|
|
966
|
+
const dp = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
967
|
+
for (let i = 0; i <= a.length; i++)
|
|
968
|
+
dp[i][0] = i;
|
|
969
|
+
for (let j = 0; j <= b.length; j++)
|
|
970
|
+
dp[0][j] = j;
|
|
971
|
+
for (let i = 1; i <= a.length; i++) {
|
|
972
|
+
for (let j = 1; j <= b.length; j++) {
|
|
973
|
+
const cost = keyboardSubCost(a[i - 1], b[j - 1]);
|
|
974
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
975
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
976
|
+
dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + TRANSPOSITION_COST);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
return dp[a.length][b.length];
|
|
981
|
+
}
|
|
982
|
+
var init_edit_distance = __esm({
|
|
983
|
+
"src/lib/edit-distance.ts"() {
|
|
984
|
+
"use strict";
|
|
985
|
+
init_cjs_shims();
|
|
986
|
+
init_keyboard_layout();
|
|
987
|
+
}
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
// src/lib/html.ts
|
|
991
|
+
function htmlToPlainText(html) {
|
|
992
|
+
return html.replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div)>/gi, "\n\n").replace(/<[^>]+>/g, "").replace(/ /gi, " ").replace(/</gi, "<").replace(/>/gi, ">").replace(/"/gi, '"').replace(/'|’/gi, "'").replace(/&/gi, "&").replace(/[ \t]+/g, " ").replace(/[ \t]*\n[ \t]*/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
993
|
+
}
|
|
994
|
+
var init_html = __esm({
|
|
995
|
+
"src/lib/html.ts"() {
|
|
996
|
+
"use strict";
|
|
997
|
+
init_cjs_shims();
|
|
998
|
+
}
|
|
999
|
+
});
|
|
1000
|
+
|
|
1001
|
+
// src/tdk.ts
|
|
1002
|
+
var fs, path, os, https, tls, TDK;
|
|
1003
|
+
var init_tdk = __esm({
|
|
1004
|
+
"src/tdk.ts"() {
|
|
1005
|
+
"use strict";
|
|
1006
|
+
init_cjs_shims();
|
|
1007
|
+
init_errors();
|
|
1008
|
+
init_morphology();
|
|
1009
|
+
init_misspellings();
|
|
1010
|
+
init_kubbealti_ca();
|
|
1011
|
+
init_edit_distance();
|
|
1012
|
+
init_html();
|
|
1013
|
+
fs = __toESM(require("fs"));
|
|
1014
|
+
path = __toESM(require("path"));
|
|
1015
|
+
os = __toESM(require("os"));
|
|
1016
|
+
https = __toESM(require("https"));
|
|
1017
|
+
tls = __toESM(require("tls"));
|
|
1018
|
+
init_misspellings();
|
|
1019
|
+
TDK = class {
|
|
1020
|
+
static BASE_URL = "https://sozluk.gov.tr";
|
|
1021
|
+
static AUDIO_API_HOST = "api.sozluk.gov.tr";
|
|
1022
|
+
static KUBBEALTI_HOST = "eski.lugatim.com";
|
|
938
1023
|
// Configuration
|
|
939
1024
|
static defaultTimeoutMs = 8e3;
|
|
940
1025
|
static defaultRetries = 1;
|
|
@@ -1481,12 +1566,12 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1481
1566
|
continue;
|
|
1482
1567
|
if (Math.abs(candidate.length - cleanWord.length) > 2)
|
|
1483
1568
|
continue;
|
|
1484
|
-
const rawDist =
|
|
1569
|
+
const rawDist = damerauLevenshtein(cleanWord, candidate);
|
|
1485
1570
|
if (rawDist === 0 || rawDist > 2)
|
|
1486
1571
|
continue;
|
|
1487
1572
|
const firstMismatch = candidate[0] === cleanWord[0] ? 0 : 1;
|
|
1488
1573
|
const lengthMismatch = candidate.length === cleanWord.length ? 0 : 1;
|
|
1489
|
-
const score =
|
|
1574
|
+
const score = keyboardAwareDistance(cleanWord, candidate) + (firstMismatch > 0 ? 1.2 : 0);
|
|
1490
1575
|
const better = !best || score < best.score - 1e-9 || Math.abs(score - best.score) < 1e-9 && firstMismatch < best.firstMismatch || Math.abs(score - best.score) < 1e-9 && firstMismatch === best.firstMismatch && lengthMismatch < best.lengthMismatch;
|
|
1491
1576
|
if (better) {
|
|
1492
1577
|
best = { candidate, score, rawDist, firstMismatch, lengthMismatch };
|
|
@@ -1617,14 +1702,11 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1617
1702
|
const contentEnd = html.indexOf("<footer", contentStart);
|
|
1618
1703
|
if (contentEnd === -1)
|
|
1619
1704
|
return null;
|
|
1620
|
-
return
|
|
1705
|
+
return htmlToPlainText(html.slice(contentStart, contentEnd));
|
|
1621
1706
|
} catch {
|
|
1622
1707
|
return null;
|
|
1623
1708
|
}
|
|
1624
1709
|
}
|
|
1625
|
-
static htmlToPlainText(html) {
|
|
1626
|
-
return html.replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div)>/gi, "\n\n").replace(/<[^>]+>/g, "").replace(/ /gi, " ").replace(/</gi, "<").replace(/>/gi, ">").replace(/"/gi, '"').replace(/'|’/gi, "'").replace(/&/gi, "&").replace(/[ \t]+/g, " ").replace(/[ \t]*\n[ \t]*/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
1627
|
-
}
|
|
1628
1710
|
/**
|
|
1629
1711
|
* GETs a JSON path from Kubbealtı Lugatı's data API (`eski.lugatim.com`),
|
|
1630
1712
|
* supplying `KUBBEALTI_EXTRA_CA` to work around that host's incomplete
|
|
@@ -1638,7 +1720,7 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1638
1720
|
hostname: this.KUBBEALTI_HOST,
|
|
1639
1721
|
path: path2,
|
|
1640
1722
|
method: "GET",
|
|
1641
|
-
ca: [...tls.rootCertificates, ...
|
|
1723
|
+
ca: [...tls.rootCertificates, ...KUBBEALTI_EXTRA_CA],
|
|
1642
1724
|
headers: {
|
|
1643
1725
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
|
|
1644
1726
|
}
|
|
@@ -1730,7 +1812,7 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1730
1812
|
const entries = await this.getKubbealti(word2);
|
|
1731
1813
|
if (!entries)
|
|
1732
1814
|
return null;
|
|
1733
|
-
return entries.map((e) =>
|
|
1815
|
+
return entries.map((e) => htmlToPlainText(e.anlam));
|
|
1734
1816
|
}
|
|
1735
1817
|
/**
|
|
1736
1818
|
* Autocomplete suggestions from Kubbealtı Lugatı's own typeahead endpoint
|
|
@@ -1766,7 +1848,7 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1766
1848
|
const match = html.match(/<meta name="description" content="([^"]*)"/);
|
|
1767
1849
|
if (!match)
|
|
1768
1850
|
return null;
|
|
1769
|
-
const description =
|
|
1851
|
+
const description = htmlToPlainText(match[1]);
|
|
1770
1852
|
if (description === "\xC7a\u011Fda\u015F T\xFCrk\xE7enin Etimolojisi")
|
|
1771
1853
|
return null;
|
|
1772
1854
|
return description;
|
|
@@ -1997,56 +2079,6 @@ yDFx8r7i9vIJU5HS3moZLkYWAOilMaV9N56A9Bgb6dNcHkvg3NoaYA==
|
|
|
1997
2079
|
}
|
|
1998
2080
|
return analyses;
|
|
1999
2081
|
}
|
|
2000
|
-
/**
|
|
2001
|
-
* Damerau-Levenshtein edit-distance (optimal string alignment variant):
|
|
2002
|
-
* like classic Levenshtein but also counts an adjacent-character
|
|
2003
|
-
* transposition (e.g. "yanlız" -> "yalnız") as a single edit instead of
|
|
2004
|
-
* two substitutions — a very common class of typo that plain Levenshtein
|
|
2005
|
-
* otherwise misses.
|
|
2006
|
-
*/
|
|
2007
|
-
static damerauLevenshtein(a, b) {
|
|
2008
|
-
const dp = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
2009
|
-
for (let i = 0; i <= a.length; i++)
|
|
2010
|
-
dp[i][0] = i;
|
|
2011
|
-
for (let j = 0; j <= b.length; j++)
|
|
2012
|
-
dp[0][j] = j;
|
|
2013
|
-
for (let i = 1; i <= a.length; i++) {
|
|
2014
|
-
for (let j = 1; j <= b.length; j++) {
|
|
2015
|
-
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
2016
|
-
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
2017
|
-
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
2018
|
-
dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + cost);
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
|
-
return dp[a.length][b.length];
|
|
2023
|
-
}
|
|
2024
|
-
/**
|
|
2025
|
-
* Keyboard- and diacritic-aware edit distance: same optimal-string-alignment
|
|
2026
|
-
* recurrence as {@link damerauLevenshtein}, but a substitution is charged by
|
|
2027
|
-
* {@link keyboardSubCost} (a fraction of an edit when the two letters are
|
|
2028
|
-
* adjacent on a Turkish Q keyboard or are ASCII/diacritic siblings) and a
|
|
2029
|
-
* transposition costs {@link TRANSPOSITION_COST}. Insertions and deletions
|
|
2030
|
-
* still cost a full 1. Used only to *rank* spelling candidates; the plain
|
|
2031
|
-
* integer distance still gates whether a suggestion is offered at all.
|
|
2032
|
-
*/
|
|
2033
|
-
static keyboardAwareDistance(a, b) {
|
|
2034
|
-
const dp = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
2035
|
-
for (let i = 0; i <= a.length; i++)
|
|
2036
|
-
dp[i][0] = i;
|
|
2037
|
-
for (let j = 0; j <= b.length; j++)
|
|
2038
|
-
dp[0][j] = j;
|
|
2039
|
-
for (let i = 1; i <= a.length; i++) {
|
|
2040
|
-
for (let j = 1; j <= b.length; j++) {
|
|
2041
|
-
const cost = keyboardSubCost(a[i - 1], b[j - 1]);
|
|
2042
|
-
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
2043
|
-
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
2044
|
-
dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + TRANSPOSITION_COST);
|
|
2045
|
-
}
|
|
2046
|
-
}
|
|
2047
|
-
}
|
|
2048
|
-
return dp[a.length][b.length];
|
|
2049
|
-
}
|
|
2050
2082
|
/**
|
|
2051
2083
|
* Fetches multiple words concurrently with a small delay to avoid rate limiting.
|
|
2052
2084
|
*/
|