pig-latinizer
Version:
Translates English text to Pig Latin, with proper handling of capitalization, punctuation, and hyphenated phrases
138 lines (112 loc) • 5.29 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Translates English to Pig Latin.
*/
var PigLatin = /** @class */ (function () {
function PigLatin() {
/** Words which should be excluded from translation. Case-sensitive. */
this.exclusions = [];
}
/**
* Translates an English string, containing an arbitrary amount of text, to Pig Latin.
* Punctuation and whitespace are preserved, including blank lines.
*
* @param english The English string to translate.
*/
PigLatin.prototype.translate = function (english) {
if (!english) {
return english;
}
return this._split(english).map(this._translateOne.bind(this)).join("");
};
/**
* Translates a single fragment (word or separator) to Pig Latin.
* @param fragment The word to translate or ignore, or separator to ignore.
*/
PigLatin.prototype._translateOne = function (fragment) {
// split into leading/trailing punctuation and the word itself;
// part 1 = punctuation, or empty string
// part 2 = the word up to any single apostrophe (if present)
// part 3 = apostrophe & word characters following it, or empty string
// part 4 = punctuation (including apostrophe if no word characters follow it), or empty string
var parts = /^([\W_]*)([^\W_]+)(['\u2019\u02bc][^\W_]+|)([\W_]*)$/.exec(fragment);
if (!parts) {
return fragment; // we can't translate this non-word (it may be a separator)
}
var word = parts[2] + parts[3].substring(1);
if (this.exclusions.indexOf(word) !== -1) {
return fragment;
}
if (/[0-9]/.test(word)) {
return fragment; // don't translate words which contain a digit
}
var isAllCaps = (word === word.toUpperCase() && word.length > 1);
var firstLetterUpped = word[0].toUpperCase();
if ("AEIOU".indexOf(firstLetterUpped) !== -1) {
// begins with vowel; append "yay", but without doubling up a trailing "y"
var lastChar = word[word.length - 1];
var append = (lastChar === "y" || lastChar === "Y") ? "ay" : "yay";
word += isAllCaps ? append.toUpperCase() : append;
}
else {
// begins with a consonant; find the first vowel (including "y", except at the start of the word)
var firstVowelPos = this._indexOfFirstVowel(word);
if (firstVowelPos !== -1) {
// (don't translate a word without vowels; maybe it's an acronym?)
// move leading consonants to the end, hyphenating if we're doubling them up, and append "ay"
var isCapitalized = (!isAllCaps && word[0] === firstLetterUpped);
var consonants = word.substring(0, firstVowelPos);
if (isCapitalized) {
consonants = consonants.toLowerCase();
}
var consonantsRepeated = (word.substr(-consonants.length).toUpperCase() === consonants.toUpperCase());
var firstConsonantRepeated = (word.substr(-1).toUpperCase() === consonants[0].toUpperCase());
var hyphen = (consonantsRepeated || firstConsonantRepeated) ? "-" : "";
word = word.substring(consonants.length) + hyphen + consonants + (isAllCaps ? "AY" : "ay");
if (isCapitalized) {
word = word[0].toUpperCase() + word.substring(1);
}
}
}
return parts[1] + word + parts[4]; // restore any leading and/or trailing punctuation
};
/**
* Splits a string into an array of fragments, i.e. alternating words and separators.
* @param str The string to split.
*/
PigLatin.prototype._split = function (str) {
// word separator = any whitespace, slash, underscore, Unicode dashes, regular dash
var re = /[\s/_\u2010-\u2015-]+/gm;
var fragments = [];
var lastLastIndex = 0;
while (true) {
var result = re.exec(str);
if (result === null) {
// no more separators, but there might be one more word
if (str && str.length > lastLastIndex) {
fragments.push(str.substring(lastLastIndex));
}
break;
}
var word = str.substring(lastLastIndex, result.index);
fragments.push(word);
var separator = str.substring(result.index, re.lastIndex);
fragments.push(separator);
lastLastIndex = re.lastIndex;
}
return fragments;
};
/**
* Gets the index of the first vowel in the given word, or -1 if it contains no vowels.
* @param word The word in which to find a vowel.
*/
PigLatin.prototype._indexOfFirstVowel = function (word) {
// split off any leading Ys (result[1]), then search whatever's left, if anything (result[2]), for the first vowel
var result = /(y*)(.*)/i.exec(word);
var index = result[2].search(/[aeiouy]/i);
return (index === -1) ? -1 : result[1].length + index;
};
return PigLatin;
}());
exports.default = PigLatin;
;