UNPKG

affixi

Version:

Affixi is a helper library for Turkish suffixes for nouns and proper nouns written in typescript.

729 lines (728 loc) 26.3 kB
"use strict"; exports.__esModule = true; exports.AffixiWord = exports.makeCompound = exports.getCompoundSuffix = exports.makeCase = exports.getCaseSuffix = exports.makePossesive = exports.getPossesiveSuffix = exports.makeEqual = exports.getEqualitySuffix = exports.makePlural = exports.getPluralSuffix = exports.alterToVowelDrop = exports.alterToVoicedConsonant = exports.getVoicedConsonant = exports.exceptions = exports.sounds = exports.util = exports.Compound = exports.Case = exports.Pronoun = void 0; var tslib_1 = require("tslib"); var Pronoun; (function (Pronoun) { /** Birinci Tekil Şahıs */ Pronoun[Pronoun["SingularFirst"] = 0] = "SingularFirst"; /** İkinci Tekil Şahıs */ Pronoun[Pronoun["SingularSecond"] = 1] = "SingularSecond"; /** Üçüncü Tekil Şahıs */ Pronoun[Pronoun["SingularThird"] = 2] = "SingularThird"; /** Birinci Çoğul Şahıs */ Pronoun[Pronoun["PluralFirst"] = 3] = "PluralFirst"; /** İkinci Çoğul Şahıs */ Pronoun[Pronoun["PluralSecond"] = 4] = "PluralSecond"; /** Üçüncü Çoğul Şahıs */ Pronoun[Pronoun["PluralThird"] = 5] = "PluralThird"; })(Pronoun = exports.Pronoun || (exports.Pronoun = {})); var Case; (function (Case) { /** İsmin Yalın Hâli - */ Case[Case["Absolute"] = 0] = "Absolute"; /** İsmin Belirtme Hâli -i */ Case[Case["Accusative"] = 1] = "Accusative"; /** İsmin Ayrılma Hâli -den */ Case[Case["Ablative"] = 2] = "Ablative"; /** İsmin Bulunma Hâli -de */ Case[Case["Locative"] = 3] = "Locative"; /** İsmin Vasıta Hâli -ile */ Case[Case["Instrumental"] = 4] = "Instrumental"; /** İsmin Yönelme Hâli -e */ Case[Case["Dative"] = 5] = "Dative"; })(Case = exports.Case || (exports.Case = {})); var Compound; (function (Compound) { /** Tamlayan */ Compound[Compound["Compounder"] = 0] = "Compounder"; /** Tamlanan */ Compound[Compound["Compoundee"] = 1] = "Compoundee"; })(Compound = exports.Compound || (exports.Compound = {})); exports.util = { duplicateToUppercase: function (list) { var copy = (0, tslib_1.__spreadArray)([], list, true); return (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([], list, true), copy.map(function (item) { return item.toLocaleUpperCase('tr'); }), true); }, getComponents: function (base) { var input = base.split('').reverse().join(''); var index = 0; var letter = input[0].toLocaleLowerCase('tr'); var vowel = input[index].toLocaleLowerCase('tr'); while (!exports.sounds.vowels.includes(vowel)) { index++; vowel = input[index].toLocaleLowerCase('tr'); } return { letter: letter, vowel: vowel }; }, getSyllableCount: function (base) { var count = 0; var input = base.split(''); input.forEach(function (letter) { if (exports.sounds.vowels.includes(letter)) count++; }); return count; }, getNumberText: function (value) { var numberString = value.toString(); var map = ['sıfır', 'bir', 'iki', 'üç', 'dört', 'beş', 'altı', 'yedi', 'sekiz', 'dokuz']; var tensMap = [null, 'on', 'yirmi', 'otuz', 'kırk', 'elli', 'altmış', 'yetmiş', 'seksen', 'doksan']; var lastDigit = value % 10; if (value === 0) { return map[0]; } if (lastDigit !== 0) { return map[lastDigit]; } var coefficientIndex = 0; var currentValue = '0'; while (currentValue === '0') { coefficientIndex++; currentValue = numberString.split('').reverse()[coefficientIndex]; } if (coefficientIndex === 1) { var tensDigit = value.toString().split('').reverse()[1]; return tensMap[parseInt(tensDigit, 10)]; } if (coefficientIndex === 2) { return 'yüz'; } if (coefficientIndex >= 3 && coefficientIndex < 6) { return 'bin'; } if (coefficientIndex >= 6 && coefficientIndex < 9) { return 'milyon'; } if (coefficientIndex >= 9 && coefficientIndex < 12) { return 'milyar'; } if ((coefficientIndex >= 12 && coefficientIndex < 15) || (coefficientIndex >= 15 && coefficientIndex < 18)) { return 'trilyon'; } return 'a'; } }; exports.sounds = { unvoicedStoppingConsonants: exports.util.duplicateToUppercase(['p', 'ç', 't', 'k']), unvoicedContinuousConsonants: exports.util.duplicateToUppercase(['f', 's', 'ş', 'h']), voicedStoppingConsonants: exports.util.duplicateToUppercase(['b', 'c', 'd', 'ğ']), concatentorConsonants: exports.util.duplicateToUppercase(['y', 'ş', 's', 'n']), unvoicedConsonants: exports.util.duplicateToUppercase(['f', 's', 'ş', 'h', 'p', 'ç', 't', 'k']), roundedVowels: exports.util.duplicateToUppercase(['o', 'u', 'ö', 'ü']), unRoundedVowels: exports.util.duplicateToUppercase(['a', 'ı', 'e', 'i']), backVowels: exports.util.duplicateToUppercase(['e', 'i', 'ö', 'ü']), frontVowels: exports.util.duplicateToUppercase(['a', 'ı', 'o', 'u']), acuteVowels: exports.util.duplicateToUppercase(['ı', 'i', 'u', 'ü']), wideVowels: exports.util.duplicateToUppercase(['a', 'e', 'o', 'ö']), vowels: exports.util.duplicateToUppercase(['a', 'e', 'ı', 'i', 'o', 'ö', 'u', 'ü']) }; exports.exceptions = { /** Unvoiced exceptions that does not soften with a vowel suffix immediately after */ unvoiced: ['hukuk', 'bilet', 'tabiat', 'devlet', 'bisiklet', 'millet', 'ahret', 'ahiret', 'merak'], /** Unvoiced single syllable exceptions that does soften with a vowel suffix immediately after */ unvoicedSingleSyllable: ['uç'], /** Exceptions that need to be filled when made plural */ plural: ['o'], /** Limited list of words that drop their vowe upon a cretain condition */ vowelDrop: [ 'ağız', 'akıl', 'alın', 'bağır', 'beyin', 'boyun', 'burun', 'çevir', 'devir', 'emir', 'fikir', 'göğüs', 'gönül', 'hapis', 'isim', 'karın', 'kayıp', 'nehir', 'oğul', 'ömür', 'sabır', 'seyir', 'şehir', 'şekil', 'zulüm', ] }; function transformBase(_base) { if (typeof _base === 'number') { return exports.util.getNumberText(_base); } return _base; } /** Some words that end with an unvoiced consonants (p,ç,t,k) may be converted into their voiced counterparts (b,c,d,ğ). * If extist, this function returns the voiced consonant. If not returns undefined - * Eğer kelime sert ünsüz ile bitiyorsa, ünsüzün yumuşak halini, bitmiyorsa undefined döndürür */ var getVoicedConsonant = function (_base, isProperNoun) { if (isProperNoun === void 0) { isProperNoun = false; } var base = transformBase(_base); var letter = exports.util.getComponents(base).letter; if (exports.sounds.unvoicedStoppingConsonants.includes(letter) && !isProperNoun && !exports.exceptions.unvoiced.includes(base.toLocaleLowerCase('tr'))) { var i = exports.sounds.unvoicedStoppingConsonants.indexOf(base[base.length - 1]); var voicedCounterPart = void 0; var isNK = base .split('') .slice(base.length - 2, base.length) .join('') === 'nk'; if (isNK) { voicedCounterPart = 'g'; } else { if (exports.util.getSyllableCount(base) > 1 || exports.exceptions.unvoicedSingleSyllable.includes(base.toLocaleLowerCase('tr'))) { voicedCounterPart = exports.sounds.voicedStoppingConsonants[i]; } } return voicedCounterPart; } return; }; exports.getVoicedConsonant = getVoicedConsonant; /** This function returns the mutated version of a word with its voiced consonant. If base does not have a voiced counterpart, the base itself is returned - * Kelimenin sonunda sert ünsüz varsa, sert ünsüzü yumuşak haliyle değiştirir, yoksa kelimenin kendisini döndürür * 'Renk' -> 'Reng' * 'Akıl' -> 'Akıl' */ var alterToVoicedConsonant = function (_base, isProperNoun) { if (isProperNoun === void 0) { isProperNoun = false; } var base = transformBase(_base); var voicedCounterPart = (0, exports.getVoicedConsonant)(base, isProperNoun); if (voicedCounterPart) { var result = base .split('') .splice(0, base.length - 1) .join('') + voicedCounterPart; return result; } return base; }; exports.alterToVoicedConsonant = alterToVoicedConsonant; /** Alter given word to its vowel dropped version. If no vowel is supposed to drop, the word itself is returned - * Verilen kelimenin hecesi düşmüş versiyonunu döndürür. Eğer kelimede ünlü düşmesi yoksa, kelimenin kendisi döndürülür * e.g 'Akıl' -> 'Akl', * e.g 'Bebek' -> 'Bebek' */ var alterToVowelDrop = function (_base) { var base = transformBase(_base); var vowel = exports.util.getComponents(base).vowel; var word = base.trim(); if (exports.util.getSyllableCount(base) === 2 && exports.sounds.acuteVowels.includes(vowel) && exports.exceptions.vowelDrop.includes(word.toLocaleLowerCase('tr'))) { // Remove the last vowel e.g 'Akıl' -> 'Akl' var result = word.split('').reverse().join('').replace(vowel, '').split('').reverse().join(''); return result; } return word; }; exports.alterToVowelDrop = alterToVowelDrop; /** Returns the plural suffix for a given word - * Verilen kelimenin çoğul ekini dödürür */ var getPluralSuffix = function (_base) { var base = transformBase(_base); var vowel = exports.util.getComponents(base).vowel; var result; var infix = ''; if (exports.sounds.frontVowels.includes(vowel)) { result = 'lar'; } else if (exports.sounds.backVowels.includes(vowel)) { result = 'ler'; } else { throw Error('Unknown vowel'); } if (exports.exceptions.plural.includes(base.toLocaleLowerCase('tr'))) { infix = 'n'; } return infix + result; }; exports.getPluralSuffix = getPluralSuffix; /** Transforms a given word into plural form - * Verilen kelimeyi çoğul hale getirir */ var makePlural = function (_base) { var base = transformBase(_base); return "".concat(base).concat((0, exports.getPluralSuffix)(base)); }; exports.makePlural = makePlural; /** Returns the equality suffix for a given word - * Verilen kelimenin eşitlik ekini dödürür; e.g 'Çocuk' -> 'ça' */ var getEqualitySuffix = function (_base) { var base = transformBase(_base); var _a = exports.util.getComponents(base), vowel = _a.vowel, letter = _a.letter; var result = ''; if (exports.sounds.unvoicedConsonants.includes(letter)) { result += 'ç'; } else { result += 'c'; } if (exports.sounds.frontVowels.includes(vowel)) { result += 'a'; } else if (exports.sounds.backVowels.includes(vowel)) { result += 'e'; } else { throw Error('Unknown vowel'); } return result; }; exports.getEqualitySuffix = getEqualitySuffix; /** Transforms a given word into equal form - * Verilen kelimeye eşitlik ekini ekler; e.g 'Çocuk' -> 'Çocukça' */ var makeEqual = function (_base) { var base = transformBase(_base); return "".concat(base).concat((0, exports.getEqualitySuffix)(base)); }; exports.makeEqual = makeEqual; /** Returns the possesive suffix for a given word and pronoun - * Verilen kelimeye ve zamire uygun iyelik ekini döndürür */ var getPossesiveSuffix = function (_base, pronoun) { var base = transformBase(_base); var _a = exports.util.getComponents(base), vowel = _a.vowel, letter = _a.letter; var result = ''; var infix = ''; var vowelSuffix; if (exports.sounds.vowels.includes(letter)) { if (pronoun === Pronoun.SingularThird) { infix = 's'; if (exports.sounds.frontVowels.includes(vowel)) { if (exports.sounds.roundedVowels.includes(vowel)) { result += 'u'; vowelSuffix = 'u'; } else { result += 'ı'; vowelSuffix = 'ı'; } } else { if (exports.sounds.roundedVowels.includes(vowel)) { result += 'ü'; vowelSuffix = 'ü'; } else { result += 'i'; vowelSuffix = 'i'; } } } else { vowelSuffix = ''; } } else { if (pronoun !== Pronoun.PluralThird) { if (exports.sounds.frontVowels.includes(vowel)) { if (exports.sounds.roundedVowels.includes(vowel)) { result += 'u'; vowelSuffix = 'u'; } else { result += 'ı'; vowelSuffix = 'ı'; } } else { if (exports.sounds.roundedVowels.includes(vowel)) { result += 'ü'; vowelSuffix = 'ü'; } else { result += 'i'; vowelSuffix = 'i'; } } } else { vowelSuffix = ''; } } switch (pronoun) { case Pronoun.SingularFirst: result += 'm'; break; case Pronoun.SingularSecond: result += 'n'; break; case Pronoun.SingularThird: break; case Pronoun.PluralFirst: switch (vowelSuffix) { case 'u': result += 'muz'; break; case 'ı': result += 'mız'; break; case 'ü': result += 'müz'; break; case 'i': result += 'miz'; break; } break; case Pronoun.PluralSecond: switch (vowelSuffix) { case 'u': result += 'nuz'; break; case 'ı': result += 'nız'; break; case 'ü': result += 'nüz'; break; case 'i': result += 'niz'; break; } break; case Pronoun.PluralThird: var targetVowel = vowelSuffix !== '' ? vowelSuffix : vowel; if (exports.sounds.backVowels.includes(targetVowel)) { result += 'leri'; } else { result += 'ları'; } break; } return infix + result; }; exports.getPossesiveSuffix = getPossesiveSuffix; /** Concatenates the word with the possesive suffix for a given base and pronoun - * Verilen kelimeye ve zamire uygun iyelik ekini ekler */ var makePossesive = function (_base, pronoun, isProperNoun) { if (isProperNoun === void 0) { isProperNoun = false; } var base = transformBase(_base); var suffix = (0, exports.getPossesiveSuffix)(base, pronoun); var firstLetter = suffix[0]; var root; var word = (0, exports.alterToVowelDrop)(base); if (exports.sounds.vowels.includes(firstLetter)) { root = (0, exports.alterToVoicedConsonant)(word); } else { root = word; } var punctuation = isProperNoun ? "'" : ''; return root + punctuation + suffix; }; exports.makePossesive = makePossesive; /** Returns the appropriate case suffix for a given base word and a case - * Verilen kelimeye ve hâle uygun hâl ekini döndürür. */ var getCaseSuffix = function (_base, _case, isCompound) { if (isCompound === void 0) { isCompound = false; } var base = transformBase(_base); var _a = exports.util.getComponents(base), vowel = _a.vowel, letter = _a.letter; var result; var infix = ''; switch (_case) { case Case.Absolute: result = ''; break; case Case.Accusative: if (exports.sounds.vowels.includes(letter)) { infix = 'n'; } if (exports.sounds.frontVowels.includes(vowel)) { if (exports.sounds.roundedVowels.includes(vowel)) { result = 'u'; } else { result = 'ı'; } } else { if (exports.sounds.roundedVowels.includes(vowel)) { result = 'ü'; } else { result = 'i'; } } break; case Case.Ablative: if (exports.sounds.vowels.includes(letter) && isCompound) { infix = 'n'; } if (exports.sounds.unvoicedConsonants.includes(letter)) { result = 't'; } else { result = 'd'; } if (exports.sounds.frontVowels.includes(vowel)) { result += 'an'; } else { result += 'en'; } break; case Case.Locative: if (exports.sounds.vowels.includes(letter) && isCompound) { infix = 'n'; } if (exports.sounds.unvoicedConsonants.includes(letter)) { result = 't'; } else { result = 'd'; } if (exports.sounds.frontVowels.includes(vowel)) { result += 'a'; } else { result += 'e'; } break; case Case.Instrumental: if (exports.sounds.vowels.includes(letter)) { infix = 'y'; } if (exports.sounds.frontVowels.includes(vowel)) { result = 'la'; } else { result = 'le'; } break; case Case.Dative: if (exports.sounds.vowels.includes(letter)) { if (isCompound) { infix = 'n'; } else { infix = 'y'; } } if (exports.sounds.frontVowels.includes(vowel)) { result = 'a'; } else { result = 'e'; } break; } return infix + result; }; exports.getCaseSuffix = getCaseSuffix; /** Returns the word base concatenated with the appropriate case suffix for a given base word and a case * Verilen kelimeye ve hâle uygun hâl ekini ekler */ var makeCase = function (_base, _case, isProperNoun, isCompound) { if (isProperNoun === void 0) { isProperNoun = false; } if (isCompound === void 0) { isCompound = false; } var base = transformBase(_base); var suffix = (0, exports.getCaseSuffix)(base, _case, isCompound); var punctuation = isProperNoun ? "'" : ''; var word = _case === Case.Absolute ? base : (0, exports.alterToVoicedConsonant)(base); var firstLetter = suffix[0]; if (exports.sounds.vowels.includes(firstLetter)) { word = (0, exports.alterToVowelDrop)(word); } return word + punctuation + suffix; }; exports.makeCase = makeCase; /** Returns the appropriate compounder suffix for a given base word - * Verilen kelimeye uygun tamlayan ekini döndürür. */ var getCompounderSuffix = function (_base) { var base = transformBase(_base); var _a = exports.util.getComponents(base), vowel = _a.vowel, letter = _a.letter; var infix = ''; var result = ''; if (exports.sounds.vowels.includes(letter)) { infix += 'n'; } if (exports.sounds.unRoundedVowels.includes(vowel)) { if (exports.sounds.frontVowels.includes(vowel)) { result += 'ın'; } else { result += 'in'; } } else { if (exports.sounds.frontVowels.includes(vowel)) { result += 'un'; } else { result += 'ün'; } } return infix + result; }; /** Returns the appropriate compoundee suffix for a given base word - * Verilen kelimeye uygun tamlanan ekini döndürür. */ var getCompoundeeSuffix = function (_base) { var base = transformBase(_base); var _a = exports.util.getComponents(base), vowel = _a.vowel, letter = _a.letter; var infix = ''; var result = ''; if (exports.sounds.vowels.includes(letter)) { infix += 's'; } if (exports.sounds.unRoundedVowels.includes(vowel)) { if (exports.sounds.frontVowels.includes(vowel)) { result += 'ı'; } else { result += 'i'; } } else { if (exports.sounds.frontVowels.includes(vowel)) { result += 'u'; } else { result += 'ü'; } } return infix + result; }; /** Returns the appropriate case suffix for a given base word and a compound type - * Verilen kelimeye ve tamlama tipine uygun tamlama ekini döndürür. */ var getCompoundSuffix = function (_base, type) { var base = transformBase(_base); switch (type) { case Compound.Compoundee: return getCompoundeeSuffix(base); case Compound.Compounder: return getCompounderSuffix(base); } }; exports.getCompoundSuffix = getCompoundSuffix; /** Returns the word base concatenated with the appropriate compound suffix for a given base word and a compound type * Verilen kelimeye ve tamlama tipine uygun tamlama ekini ekler */ var makeCompound = function (_base, type, isProperNoun) { if (isProperNoun === void 0) { isProperNoun = false; } var base = transformBase(_base); var suffix; var firstLetter; var word = (0, exports.alterToVoicedConsonant)(base); var punctuation = isProperNoun ? "'" : ''; switch (type) { case Compound.Compoundee: suffix = getCompoundeeSuffix(base); firstLetter = suffix[0]; if (exports.sounds.vowels.includes(firstLetter)) { word = (0, exports.alterToVowelDrop)(word); } return word + punctuation + suffix; case Compound.Compounder: suffix = getCompounderSuffix(base); firstLetter = suffix[0]; if (exports.sounds.vowels.includes(firstLetter)) { word = (0, exports.alterToVowelDrop)(word); } return word + punctuation + suffix; } }; exports.makeCompound = makeCompound; /** AffixiWord is a construct that makes it easier to handle nouns in a complex manner. * It holds a state that can be undone and handles aspects like compoundness in itslef. * It has a toString method that returns the resulting word and can be used with String(word). * All its methods apart from toString return the instance itself so they are chainable. */ var AffixiWord = /** @class */ (function () { function AffixiWord(base, isProperNoun) { if (isProperNoun === void 0) { isProperNoun = false; } this.base = base; this.isProperNoun = isProperNoun; this.isCompound = false; this.history = []; this.word = transformBase(this.base); } /** Concatenates the word with the appropriate compound suffix for a given compound type - * Kelimeye verilen tamlama tipine uygun tamlama ekini ekler */ AffixiWord.prototype.makeCompound = function (type) { this.commit(); this.word = (0, exports.makeCompound)(this.word, type, this.isProperNoun); this.isCompound = true; return this; }; /** Concatenates the word with the appropriate case suffix for a given case - * Kelimeye verilen hâle uygun hâl ekini ekler */ AffixiWord.prototype.makeCase = function (_case) { this.commit(); this.word = (0, exports.makeCase)(this.word, _case, this.isProperNoun, this.isCompound); return this; }; /** Concatenates the word with the possesive suffix for a given pronoun - * Kelimeye verilen zamire uygun iyelik ekini ekler */ AffixiWord.prototype.makePossesive = function (pronoun) { this.commit(); this.word = (0, exports.makePossesive)(this.word, pronoun, this.isProperNoun); this.isCompound = true; return this; }; /** Transforms the word into equal form - * Kelimeye eşitlik ekini ekler; e.g 'Çocuk' -> 'Çocukça' */ AffixiWord.prototype.makeEqual = function () { this.commit(); this.word = (0, exports.makeEqual)(this.word); return this; }; /** Transforms the word into plural form - * Kelimeyi çoğul hale getirir */ AffixiWord.prototype.makePlural = function () { this.commit(); this.word = (0, exports.makePlural)(this.word); return this; }; AffixiWord.prototype.commit = function () { if (this.history.length >= 20) { this.history.shift(); } this.history.push({ word: this.word, isCompound: this.isCompound, isProperNoun: this.isProperNoun }); }; /** Undoes the last operation */ AffixiWord.prototype.undo = function () { var oldState = this.history.pop(); if (oldState) { this.word = oldState.word; this.isCompound = oldState.isCompound; this.isProperNoun = oldState.isProperNoun; } return this; }; AffixiWord.prototype.toString = function () { return this.word; }; return AffixiWord; }()); exports.AffixiWord = AffixiWord;