<commit_before>/*!
 * Translit (Rusyn transliteration) 2.0.7
 * https://tota.sk/translit
 *
 * Copyright 2014-20 <NAME>
 * Released under the MIT license
 *
 * Date: 2020-07-27
 */


/* Constants */

const latinVowelsLowerCase = "aeiouyŷ";
const cyrillicVowelsLowerCase = "аеіоуиыї"
const cyrillicJaje = "яєїёю";

const nonLatinLowercase = "áäčďéěíĺľňóôöőŕřšťúüűůýŷžабвгґдезіийклмнопрстуфъыьцчжшїщёєюях";
const nonLatinUppercase = nonLatinLowercase.toUpperCase();
const nonLatinChars = nonLatinLowercase + nonLatinUppercase;
const lowerCaseChars = "a-z" + nonLatinLowercase;
const upperCaseChars = "A-Z" + nonLatinUppercase;
const allChars = lowerCaseChars + upperCaseChars;



const mapping = {
	"exceptions" : {
		"text" : "текст",
		"taxi" : "таксі",
	},

	"priority-set-1" : {
		"ľľa" : "лля",
		"Ľľa" : "Лля",
	},

	"detenele" : {
		// da ta na la
		"ďa": "дя",
		"Ďa": "Дя",
		"ťa": "тя",
		"Ťa": "Тя",
		"ňa": "ня",
		"Ňa": "Ня",
		"ľa": "ля",
		"Ľa": "Ля",

		// de te ne le
		"ďe": "дє",
		"Ďe": "Дє",
		"ťe": "тє",
		"Ťe": "Тє",
		"ňe": "нє",
		"Ňe": "Hє",
		"ľe": "лє",
		"Ľe": "Лє",

		// di ti ni li
		"ďi": "дї",
		"Ďi": "Дї",
		"ťi": "тї",
		"Ťi": "Тї",
		"ňi": "нї",
		"Ňi": "Нї",
		"ľi": "лї",
		"Ľi": "Лї",

		// do to no lo
		"ďo": "дё",
		"Ďo": "Дё",
		"ťo": "тё",
		"Ťo": "Тё",
		"ňo": "нё",
		"Ňo": "Hё",
		"ľo": "лё",
		"Ľo": "Лё",


		// du tu nu lu
		"ďu": "дю",
		"Ďu": "Дю",
		"ťu": "тю",
		"Ťu": "Тю",
		"ňu": "ню",
		"Ňu": "Hю",
		"ľu": "лю",
		"Ľu": "Лю",
	},

	"priority-set-2" : {
		// cja, cji, cjo, cju, sja, sji, sjo, sju, rja, rji, rjo, rju, zja, zji, zjo, zju
		// keep these characters together, do not optimalize by removing first letters
		"c’a": "ця",
		"C’a": "Ця",
		"c’i": "цї",
		"C’i": "Цї",
		"c’o": "цё",
		"C’o": "Цё",
		"c’u": "цю",
		"C’u": "Цю",
		"s’a": "ся",
		"S’a": "Ся",
		"s’i": "сї",
		"S’i": "Сї",
		"s’o": "сё",
		"S’o": "Сё",
		"s’u": "сю",
		"S’u": "Сю",
		"r’a": "ря",
		"R’a": "Ря",
		"r’i": "рї",
		"R’i": "Рї",
		"r’o": "рё",
		"R’o": "Рё",
		"r’u": "рю",
		"R’u": "Рю",
		"z’a": "зя",
		"Z’a": "Зя",
		"z’i": "зї",
		"Z’i": "Зї",
		"z’o": "зё",
		"Z’o": "Зё",
		"z’u": "зю",
		"Z’u": "Зю",
		"ž’a" : "жя",
		"Ž’a" : "Жя",
		"ž’i" : "жї",
		"Ž’i" : "Жї",
		"ž’o" : "жё",
		"Ž’o" : "Жё",
		"ž’u" : "жю",
		"Ž’u" : "Жю",

	},

	"priority-set-3" : {
		"zja" : "зъя",
		"Zja" : "Зъя",
		"zje" : "зъє",
		"Zje" : "Зъє",
		"zji" : "зъї",
		"Zji" : "Зъї",
		"zjo" : "зъё",
		"Zjo" : "Зъё",
		"zju" : "зъю",
		"Zju" : "Зъю",
		"r’jo" : "рьё",
		"R’jo" : "Рьё",

		// d + ja, je, ji, jo, ju
		"dja" : "дъя",
		"dje" : "дъє",
		"dji" : "дъї",
		"djo" : "дъё",
		"dju" : "дъю",
		"Dja" : "Дъя",
		"Dje" : "Дъє",
		"Dji" : "Дъї",
		"Djo" : "Дъё",
		"Dju" : "Дъю",
	},


	"jajejijoju" : {
		"ja" : "я",
		"je" : "є",
		"ji" : "ї",
		"jo" : "ё",
		"ju" : "ю",
		"Ja" : "Я",
		"Je" : "Є",
		"Ji" : "Ї",
		"Jo" : "Ё",
		"Ju" : "Ю",		
	},


	"dtnl" : {
		"ď": "дь",
		"Ď": "Дь",
		"ť": "ть",
		"Ť": "Ть",
		"ň": "нь",
		"Ň": "Нь",
		"ľ": "ль",
		"Ľ": "Ль",
	},

	"basic" : {
		"ja": "я",
		"Ja": "Я",
		"ju": "ю",
		"Ju": "Ю",
		"je": "є",
		"Je": "Є",
		// "jo": "ё",
		// "Jo": "Ё",
		"’o": "ё",
		"’O": "Ë",
		"ji": "ї",
		"Ji": "Ї",
		"ch": "х",
		"Ch": "Х",
		"šč": "щ",
		"Šč": "Щ",
		"c’" : "ць",
		"C’" : "Ць",
		"s’" : "сь",
		"S’" : "Сь",
		"r’" : "рь",
		"R’" : "Рь",
		"z’" : "зь",
		"Z’" : "Зь",
		"ž’" : "жь",
		"Ž’" : "Жь",
	},
	"chars" : {
		"a" : "а",
		"b" : "б",
		"v" : "в",
		"h" : "г",
		"g" : "ґ",
		"d" : "д",
		"e" : "е",
		"z" : "з",
		"i" : "і",
		"y" : "и",
		"j" : "й",
		"k" : "к",
		"l" : "л",
		"m" : "м",
		"n" : "н",
		"o" : "о",
		"p" : "п",
		"r" : "р",
		"s" : "с",
		"t" : "т",
		"u" : "у",
		"f" : "ф",
		"ŷ" : "ы",
		"c" : "ц",
		"č" : "ч",
		"ž" : "ж",
		"š" : "ш",
		"A" : "А",
		"B" : "Б",
		"V" : "В",
		"H" : "Г",
		"G" : "Ґ",
		"D" : "Д",
		"E" : "Е",
		"Z" : "З",
		"I" : "I",
		"Y" : "И",
		"J" : "Й",
		"K" : "К",
		"L" : "Л",
		"M" : "М",
		"N" : "Н",
		"O" : "О",
		"P" : "П",
		"R" : "Р",
		"S" : "С",
		"T" : "Т",
		"U" : "У",
		"F" : "Ф",
		"Ŷ" : "Ы",
		"C" : "Ц",
		"Č" : "Ч",
		"Ž" : "Ж",
		"Š" : "Ш",
	}
}

/*
	 (39) dumb single quote,
	 (8217) right single quotation mark
	 (700) modifier letter apostrophe; https://en.wikipedia.org/wiki/Modifier_letter_apostrophe
	 (8216) left single quotation mark
*/
function streamlineApostrophes(string) {
	return string.replace(/\'|’|ʼ|‘/g , '’');
}



function mapCyrLat(string, mappingOption) {
	for (var rule in mapping[mappingOption]){
		var re = new RegExp(mapping[mappingOption][rule],"g");
		string =  string.replace(re, rule);
	}
	return string;
}


function mapLatCyr(string, mappingOption) {
	for (var rule in mapping[mappingOption]){
		var re = new RegExp(rule,"g");
		string =  string.replace(re, mapping[mappingOption][rule]);
	}
	return string;
}


/*
  Transliterate words that begin with "naj|Naj|NAJ" followed by a vowel to "най|Най|НАЙ"

	Standard transliteration for "ja", "je", "ji", "jo", "ju" is:
	ja → я
	je → є
	ji → ї
	jo → ё
	ju → ю
	
	However, when "j" + "vowel" is in place where you could hyphenate a word, 
	then you translitate "j" + "vowel" to "й" + "vowel" and vice versa.
	
	Examples
	"najatraktivňišŷj" → "найатрактівнїшый"

	Counterexamples
	"najidž" → "наїдж"

	Algorithm
	match all words beginning with naj, following with a vowel and not ending with any of superlative suffixes

	@param {string} string: input text for mapping
	@returns {string} where all words that begin with "naj|Naj|NAJ" followed by a vowel will be transliterated to "най|Най|НАЙ"
*/
export function mapSuperlativeLatCyr(string){
	let pattern =
		'(\\b)'
	+ '(naj)'
	+ '([' + latinVowelsLowerCase + '])'
	+ '([' + lowerCaseChars + ']+?)'
	+ '(šŷj|šoho|šomu|šom|šŷm|šŷ|šŷch|šŷmi|šŷmy|ša|šoj|šu|šov|šŷch|še)';
	let re = new RegExp(pattern, 'gi');

	return string.replace(re, function($0, $1, $2, $3, $4, $5){
		return $1 + mapLatCyr($2, 'chars') + $3 + $4 + $5;
	});

}



/*
	Transliterate ja, je, ji, jo, ju at the beginning of the word

	Transliteration rules:
	ja ↔ я
	je ↔ є
	ji ↔ ї
	jo ↔ ё
	ju ↔ ю

	Examples
	jabčanka ↔ ябчaнка
	jedenastka ↔ єденастка
	jidnaňa ↔ їднaня
	joho ↔ ёгo
	o-jo-joj ↔ о-ё-ёй
	jubilant ↔ юбілaнт
		
	Counterexamples
	jedenadc’atŷj ↔ єденадцятый (ja in the middle)
	každopadňi ↔ каждопаднї
	zrivňovaty ↔ зрiвнёвати
	čeľustnŷj ↔ чeлюстный

	@param {string} string: latin text for mapping
	@returns {string} cyrillic text with mapped ja, je, ji, jo, ju
*/
export function mapJajeBeginningLatCyr(string) {
	let pattern =
			'(\\b)'
		+ '(j)'
		+ '([' + latinVowelsLowerCase + '])';
	let re = new RegExp(pattern, 'gi');

	return string.replace(re, function($0, $1, $2, $3){
		return $1 + mapLatCyr($2 + $3, 'jajejijoju');
	});
}



/*
	Transliterate я, є, ї, ё, ю at the beginning of the word

	Transliteration rules:
	ja ↔ я
	je ↔ є
	ji ↔ ї
	jo ↔ ё
	ju ↔ ю

	Examples
	jabčanka ↔ ябчaнка
	jedenastka ↔ єденастка
	jidnaňa ↔ їднaня
	joho ↔ ёгo
	o-jo-joj ↔ о-ё-ёй
	jubilant ↔ юбілaнт
		
	Counterexamples
	jedenadc’atŷj ↔ єденадцятый (ja in the middle)
	každopadňi ↔ каждопаднї
	zrivňovaty ↔ зрiвнёвати
	čeľustnŷj ↔ чeлюстный

	@param {string} string: cyrillic text for mapping
	@returns {string} latin text with mapped я, є, ї, ё, ю

*/
export function mapJajeBeginningCyrLat(string) {
	let pattern =
			'([^' + allChars + ']|^)'
		+ '([' + cyrillicJaje + '])';
	let re = new RegExp(pattern, 'gi');

	return string.replace(re, function($0, $1, $2){
		return $1 + mapCyrLat($2, 'jajejijoju');
	});
}



/*
	Transliterate ja, je, ji, jo, ju before a vowel (a, e, i, o, u, y, ŷ)

	Examples
	bajusatŷj	↔ баюсaтый
	akciji ↔ aкції
	čornyjova ↔ чорниёвa
	oklejuju ↔ оклеюю
	svojoj ↔ своёй
	šŷje ↔ šŷje
	ujidaty ↔ уїдaти

	@param {string} string: latin text for mapping
	@returns {string} cyrillic text with mapped ja, je, ji, jo, ju
*/
export function mapJajeBeforeVowelLatCyr(string) {

	let pattern =
			'([' + latinVowelsLowerCase + '])'
		+ '(ja|je|ji|jo|ju)';
	let re = new RegExp(pattern, 'gi');

	return string.replace(re, function($0, $1, $2){
		return $1 + mapLatCyr($2, 'jajejijoju');
	});
}





/*
	Transliterate я, є, ї, ё, ю before a vowel (а, е, і, о, у, и, ы)

	Examples
	bajusatŷj	↔ баюсaтый
	akciji ↔ aкції
	čornyjova ↔ чорниёвa
	oklejuju ↔ оклеюю
	svojoj ↔ своёй
	šŷje ↔ šŷje
	ujidaty ↔ уїдaти

	@param {string} string: latin text for mapping
	@returns {string} cyrillic text with mapped я, є, ї, ё, ю
*/
export function mapJajeBeforeVowelCyrLat(string) {

	let pattern =
			'([' + cyrillicVowelsLowerCase + '])'
		+ '([' + cyrillicJaje + '])';
	let re = new RegExp(pattern, 'gi');

	return string.replace(re, function($0, $1, $2){
		return $1 + mapCyrLat($2, 'jajejijoju');
	});
}



/*
	 Public API
*/
export function translitCyrLat(string) {
	string = mapJajeBeginningCyrLat(string);
	string = mapJajeBeforeVowelCyrLat(string);
	string = mapCyrLat(string, 'exceptions');
	string = mapCyrLat(string, 'priority-set-1');
	string = mapCyrLat(string, 'detenele');
	string = mapCyrLat(string, 'priority-set-2');
	string = mapCyrLat(string, 'priority-set-3');
	string = mapCyrLat(string, 'dtnl');
	string = mapCyrLat(string, 'basic');
	string = mapCyrLat(string, 'chars');
	return string;
}



export function translitLatCyr(string) {
	string = streamlineApostrophes(string);
	string = mapSuperlativeLatCyr(string);
	string = mapJajeBeginningLatCyr(string);
	string = mapJajeBeforeVowelLatCyr(string);
	string = mapLatCyr(string, 'exceptions');
	string = mapLatCyr(string, 'priority-set-1');
	string = mapLatCyr(string, 'detenele');
	string = mapLatCyr(string, 'priority-set-2');
	string = mapLatCyr(string, 'priority-set-3');
	string = mapLatCyr(string, 'dtnl');
	string = mapLatCyr(string, 'basic');
	string = mapLatCyr(string, 'chars');
	return string;<commit_msg>🎨 Consolidate variables<commit_after>/*!
 * Translit (Rusyn transliteration) 2.0.7
 * https://tota.sk/translit
 *
 * Copyright 2014-20 <NAME>
 * Released under the MIT license
 *
 * Date: 2020-07-27
 */


/* Constants */

const latinVowelsLowerCase = "aeiouyŷ";
const cyrillicVowelsLowerCase = "аеіоуиыї"
const cyrillicJaje = "яєїёю";

const nonLatinLowercase = "áäčďéěíĺľňóôöőŕřšťúüűůýŷžабвгґдезіийклмнопрстуфъыьцчжшїщёєюях";
const nonLatinUppercase = nonLatinLowercase.toUpperCase();
const nonLatinChars = nonLatinLowercase + nonLatinUppercase;
const lowerCaseChars = "a-z" + nonLatinLowercase;
const upperCaseChars = "A-Z" + nonLatinUppercase;
const allChars = lowerCaseChars + upperCaseChars;



const mapping = {
	"exceptions" : {
		"text" : "текст",
		"taxi" : "таксі",
	},

	"priority-set-1" : {
		"ľľa" : "лля",
		"Ľľa" : "Лля",
	},

	"detenele" : {
		// da ta na la
		"ďa": "дя",
		"Ďa": "Дя",
		"ťa": "тя",
		"Ťa": "Тя",
		"ňa": "ня",
		"Ňa": "Ня",
		"ľa": "ля",
		"Ľa": "Ля",

		// de te ne le
		"ďe": "дє",
		"Ďe": "Дє",
		"ťe": "тє",
		"Ťe": "Тє",
		"ňe": "нє",
		"Ňe": "Hє",
		"ľe": "лє",
		"Ľe": "Лє",

		// di ti ni li
		"ďi": "дї",
		"Ďi": "Дї",
		"ťi": "тї",
		"Ťi": "Тї",
		"ňi": "нї",
		"Ňi": "Нї",
		"ľi": "лї",
		"Ľi": "Лї",

		// do to no lo
		"ďo": "дё",
		"Ďo": "Дё",
		"ťo": "тё",
		"Ťo": "Тё",
		"ňo": "нё",
		"Ňo": "Hё",
		"ľo": "лё",
		"Ľo": "Лё",


		// du tu nu lu
		"ďu": "дю",
		"Ďu": "Дю",
		"ťu": "тю",
		"Ťu": "Тю",
		"ňu": "ню",
		"Ňu": "Hю",
		"ľu": "лю",
		"Ľu": "Лю",
	},

	"priority-set-2" : {
		// cja, cji, cjo, cju, sja, sji, sjo, sju, rja, rji, rjo, rju, zja, zji, zjo, zju
		// keep these characters together, do not optimalize by removing first letters
		"c’a": "ця",
		"C’a": "Ця",
		"c’i": "цї",
		"C’i": "Цї",
		"c’o": "цё",
		"C’o": "Цё",
		"c’u": "цю",
		"C’u": "Цю",
		"s’a": "ся",
		"S’a": "Ся",
		"s’i": "сї",
		"S’i": "Сї",
		"s’o": "сё",
		"S’o": "Сё",
		"s’u": "сю",
		"S’u": "Сю",
		"r’a": "ря",
		"R’a": "Ря",
		"r’i": "рї",
		"R’i": "Рї",
		"r’o": "рё",
		"R’o": "Рё",
		"r’u": "рю",
		"R’u": "Рю",
		"z’a": "зя",
		"Z’a": "Зя",
		"z’i": "зї",
		"Z’i": "Зї",
		"z’o": "зё",
		"Z’o": "Зё",
		"z’u": "зю",
		"Z’u": "Зю",
		"ž’a" : "жя",
		"Ž’a" : "Жя",
		"ž’i" : "жї",
		"Ž’i" : "Жї",
		"ž’o" : "жё",
		"Ž’o" : "Жё",
		"ž’u" : "жю",
		"Ž’u" : "Жю",

		"zja" : "зъя",
		"Zja" : "Зъя",
		"zje" : "зъє",
		"Zje" : "Зъє",
		"zji" : "зъї",
		"Zji" : "Зъї",
		"zjo" : "зъё",
		"Zjo" : "Зъё",
		"zju" : "зъю",
		"Zju" : "Зъю",
		"r’jo" : "рьё",
		"R’jo" : "Рьё",

		// d + ja, je, ji, jo, ju
		"dja" : "дъя",
		"dje" : "дъє",
		"dji" : "дъї",
		"djo" : "дъё",
		"dju" : "дъю",
		"Dja" : "Дъя",
		"Dje" : "Дъє",
		"Dji" : "Дъї",
		"Djo" : "Дъё",
		"Dju" : "Дъю",

	},


	"jajejijoju" : {
		"ja" : "я",
		"je" : "є",
		"ji" : "ї",
		"jo" : "ё",
		"ju" : "ю",
		"Ja" : "Я",
		"Je" : "Є",
		"Ji" : "Ї",
		"Jo" : "Ё",
		"Ju" : "Ю",		
	},


	"dtnl" : {
		"ď": "дь",
		"Ď": "Дь",
		"ť": "ть",
		"Ť": "Ть",
		"ň": "нь",
		"Ň": "Нь",
		"ľ": "ль",
		"Ľ": "Ль",
	},

	"doubleChars" : {
		"ja": "я",
		"Ja": "Я",
		"ju": "ю",
		"Ju": "Ю",
		"je": "є",
		"Je": "Є",
		// "jo": "ё",
		// "Jo": "Ё",
		"’o": "ё",
		"’O": "Ë",
		"ji": "ї",
		"Ji": "Ї",
		"ch": "х",
		"Ch": "Х",
		"šč": "щ",
		"Šč": "Щ",
		"c’" : "ць",
		"C’" : "Ць",
		"s’" : "сь",
		"S’" : "Сь",
		"r’" : "рь",
		"R’" : "Рь",
		"z’" : "зь",
		"Z’" : "Зь",
		"ž’" : "жь",
		"Ž’" : "Жь",
	},
	"singleChars" : {
		"a" : "а",
		"b" : "б",
		"v" : "в",
		"h" : "г",
		"g" : "ґ",
		"d" : "д",
		"e" : "е",
		"z" : "з",
		"i" : "і",
		"y" : "и",
		"j" : "й",
		"k" : "к",
		"l" : "л",
		"m" : "м",
		"n" : "н",
		"o" : "о",
		"p" : "п",
		"r" : "р",
		"s" : "с",
		"t" : "т",
		"u" : "у",
		"f" : "ф",
		"ŷ" : "ы",
		"c" : "ц",
		"č" : "ч",
		"ž" : "ж",
		"š" : "ш",
		"A" : "А",
		"B" : "Б",
		"V" : "В",
		"H" : "Г",
		"G" : "Ґ",
		"D" : "Д",
		"E" : "Е",
		"Z" : "З",
		"I" : "I",
		"Y" : "И",
		"J" : "Й",
		"K" : "К",
		"L" : "Л",
		"M" : "М",
		"N" : "Н",
		"O" : "О",
		"P" : "П",
		"R" : "Р",
		"S" : "С",
		"T" : "Т",
		"U" : "У",
		"F" : "Ф",
		"Ŷ" : "Ы",
		"C" : "Ц",
		"Č" : "Ч",
		"Ž" : "Ж",
		"Š" : "Ш",
	}
}

/*
	 (39) dumb single quote,
	 (8217) right single quotation mark
	 (700) modifier letter apostrophe; https://en.wikipedia.org/wiki/Modifier_letter_apostrophe
	 (8216) left single quotation mark
*/
function streamlineApostrophes(string) {
	return string.replace(/\'|’|ʼ|‘/g , '’');
}



function mapCyrLat(string, mappingOption) {
	for (var rule in mapping[mappingOption]){
		var re = new RegExp(mapping[mappingOption][rule],"g");
		string =  string.replace(re, rule);
	}
	return string;
}


function mapLatCyr(string, mappingOption) {
	for (var rule in mapping[mappingOption]){
		var re = new RegExp(rule,"g");
		string =  string.replace(re, mapping[mappingOption][rule]);
	}
	return string;
}


/*
  Transliterate words that begin with "naj|Naj|NAJ" followed by a vowel to "най|Най|НАЙ"

	Standard transliteration for "ja", "je", "ji", "jo", "ju" is:
	ja → я
	je → є
	ji → ї
	jo → ё
	ju → ю
	
	However, when "j" + "vowel" is in place where you could hyphenate a word, 
	then you translitate "j" + "vowel" to "й" + "vowel" and vice versa.
	
	Examples
	"najatraktivňišŷj" → "найатрактівнїшый"

	Counterexamples
	"najidž" → "наїдж"

	Algorithm
	match all words beginning with naj, following with a vowel and not ending with any of superlative suffixes

	@param {string} string: input text for mapping
	@returns {string} where all words that begin with "naj|Naj|NAJ" followed by a vowel will be transliterated to "най|Най|НАЙ"
*/
export function mapSuperlativeLatCyr(string){
	let pattern =
		'(\\b)'
	+ '(naj)'
	+ '([' + latinVowelsLowerCase + '])'
	+ '([' + lowerCaseChars + ']+?)'
	+ '(šŷj|šoho|šomu|šom|šŷm|šŷ|šŷch|šŷmi|šŷmy|ša|šoj|šu|šov|šŷch|še)';
	let re = new RegExp(pattern, 'gi');

	return string.replace(re, function($0, $1, $2, $3, $4, $5){
		return $1 + mapLatCyr($2, 'singleChars') + $3 + $4 + $5;
	});

}



/*
	Transliterate ja, je, ji, jo, ju at the beginning of the word

	Transliteration rules:
	ja ↔ я
	je ↔ є
	ji ↔ ї
	jo ↔ ё
	ju ↔ ю

	Examples
	jabčanka ↔ ябчaнка
	jedenastka ↔ єденастка
	jidnaňa ↔ їднaня
	joho ↔ ёгo
	o-jo-joj ↔ о-ё-ёй
	jubilant ↔ юбілaнт
		
	Counterexamples
	jedenadc’atŷj ↔ єденадцятый (ja in the middle)
	každopadňi ↔ каждопаднї
	zrivňovaty ↔ зрiвнёвати
	čeľustnŷj ↔ чeлюстный

	@param {string} string: latin text for mapping
	@returns {string} cyrillic text with mapped ja, je, ji, jo, ju
*/
export function mapJajeBeginningLatCyr(string) {
	let pattern =
			'(\\b)'
		+ '(j)'
		+ '([' + latinVowelsLowerCase + '])';
	let re = new RegExp(pattern, 'gi');

	return string.replace(re, function($0, $1, $2, $3){
		return $1 + mapLatCyr($2 + $3, 'jajejijoju');
	});
}



/*
	Transliterate я, є, ї, ё, ю at the beginning of the word

	Transliteration rules:
	ja ↔ я
	je ↔ є
	ji ↔ ї
	jo ↔ ё
	ju ↔ ю

	Examples
	jabčanka ↔ ябчaнка
	jedenastka ↔ єденастка
	jidnaňa ↔ їднaня
	joho ↔ ёгo
	o-jo-joj ↔ о-ё-ёй
	jubilant ↔ юбілaнт
		
	Counterexamples
	jedenadc’atŷj ↔ єденадцятый (ja in the middle)
	každopadňi ↔ каждопаднї
	zrivňovaty ↔ зрiвнёвати
	čeľustnŷj ↔ чeлюстный

	@param {string} string: cyrillic text for mapping
	@returns {string} latin text with mapped я, є, ї, ё, ю

*/
export function mapJajeBeginningCyrLat(string) {
	let pattern =
			'([^' + allChars + ']|^)'
		+ '([' + cyrillicJaje + '])';
	let re = new RegExp(pattern, 'gi');

	return string.replace(re, function($0, $1, $2){
		return $1 + mapCyrLat($2, 'jajejijoju');
	});
}



/*
	Transliterate ja, je, ji, jo, ju before a vowel (a, e, i, o, u, y, ŷ)

	Examples
	bajusatŷj	↔ баюсaтый
	akciji ↔ aкції
	čornyjova ↔ чорниёвa
	oklejuju ↔ оклеюю
	svojoj ↔ своёй
	šŷje ↔ šŷje
	ujidaty ↔ уїдaти

	@param {string} string: latin text for mapping
	@returns {string} cyrillic text with mapped ja, je, ji, jo, ju
*/
export function mapJajeBeforeVowelLatCyr(string) {

	let pattern =
			'([' + latinVowelsLowerCase + '])'
		+ '(ja|je|ji|jo|ju)';
	let re = new RegExp(pattern, 'gi');

	return string.replace(re, function($0, $1, $2){
		return $1 + mapLatCyr($2, 'jajejijoju');
	});
}





/*
	Transliterate я, є, ї, ё, ю before a vowel (а, е, і, о, у, и, ы)

	Examples
	bajusatŷj	↔ баюсaтый
	akciji ↔ aкції
	čornyjova ↔ чорниёвa
	oklejuju ↔ оклеюю
	svojoj ↔ своёй
	šŷje ↔ šŷje
	ujidaty ↔ уїдaти

	@param {string} string: latin text for mapping
	@returns {string} cyrillic text with mapped я, є, ї, ё, ю
*/
export function mapJajeBeforeVowelCyrLat(string) {

	let pattern =
			'([' + cyrillicVowelsLowerCase + '])'
		+ '([' + cyrillicJaje + '])';
	let re = new RegExp(pattern, 'gi');

	return string.replace(re, function($0, $1, $2){
		return $1 + mapCyrLat($2, 'jajejijoju');
	});
}



/*
	 Public API
*/
export function translitCyrLat(string) {
	string = mapJajeBeginningCyrLat(string);
	string = mapJajeBeforeVowelCyrLat(string);
	string = mapCyrLat(string, 'exceptions');
	string = mapCyrLat(string, 'priority-set-1');
	string = mapCyrLat(string, 'detenele');
	string = mapCyrLat(string, 'priority-set-2');
	string = mapCyrLat(string, 'dtnl');
	string = mapCyrLat(string, 'doubleChars');
	string = mapCyrLat(string, 'singleChars');
	return string;
}



export function translitLatCyr(string) {
	string = streamlineApostrophes(string);
	string = mapSuperlativeLatCyr(string);
	string = mapJajeBeginningLatCyr(string);
	string = mapJajeBeforeVowelLatCyr(string);
	string = mapLatCyr(string, 'exceptions');
	string = mapLatCyr(string, 'priority-set-1');
	string = mapLatCyr(string, 'detenele');
	string = mapLatCyr(string, 'priority-set-2');
	string = mapLatCyr(string, 'dtnl');
	string = mapLatCyr(string, 'doubleChars');
	string = mapLatCyr(string, 'singleChars');
	return string;
{'fraction_non_alphanumeric': 0.23302818350133717, 'fraction_numerical': 0.007251594322155935, 'mean_word_length': 3.2764460083571585, 'pattern_counts': {'":': 192, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7081437', 'n_tokens_mistral': 10664, 'n_tokens_neox': 10218, 'n_words': 2306}