@cmu-eberly-center/eberly-ontopic-visualization
Version:
Writing tasks require countless composing decisions that are typically beyond the conscious grasp of student writers. Much of the skill of being “text-aware” is to understand that texts are composed of highly structured and often highly predictive composi
379 lines (320 loc) • 14.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
// Rule storage - pluralize and singularize need to be run sequentially,
// while other rules can be optimized using an object for instant lookups.
var pluralRules = [];
var singularRules = [];
var uncountables = {};
var irregularPlurals = {};
var irregularSingles = {};
var plPointer = null;
/**
* Irregular rules.
*/
var irregular = [// Pronouns.
['I', 'we'], ['me', 'us'], ['he', 'they'], ['she', 'they'], ['them', 'them'], ['myself', 'ourselves'], ['yourself', 'yourselves'], ['itself', 'themselves'], ['herself', 'themselves'], ['himself', 'themselves'], ['themself', 'themselves'], ['is', 'are'], ['was', 'were'], ['has', 'have'], ['this', 'these'], ['that', 'those'], // Words ending in with a consonant and `o`.
['echo', 'echoes'], ['dingo', 'dingoes'], ['volcano', 'volcanoes'], ['tornado', 'tornadoes'], ['torpedo', 'torpedoes'], // Ends with `us`.
['genus', 'genera'], ['viscus', 'viscera'], // Ends with `ma`.
['stigma', 'stigmata'], ['stoma', 'stomata'], ['dogma', 'dogmata'], ['lemma', 'lemmata'], ['schema', 'schemata'], ['anathema', 'anathemata'], // Other irregular rules.
['ox', 'oxen'], ['axe', 'axes'], ['die', 'dice'], ['yes', 'yeses'], ['foot', 'feet'], ['eave', 'eaves'], ['goose', 'geese'], ['tooth', 'teeth'], ['quiz', 'quizzes'], ['human', 'humans'], ['proof', 'proofs'], ['carve', 'carves'], ['valve', 'valves'], ['looey', 'looies'], ['thief', 'thieves'], ['groove', 'grooves'], ['pickaxe', 'pickaxes'], ['passerby', 'passersby']];
/**
* Pluralization rules.
*/
var plural = [[/s?$/i, 's'], [/[^\u0000-\u007F]$/i, '$0'], [/([^aeiou]ese)$/i, '$1'], [/(ax|test)is$/i, '$1es'], [/(alias|[^aou]us|t[lm]as|gas|ris)$/i, '$1es'], [/(e[mn]u)s?$/i, '$1s'], [/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, '$1'], [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1i'], [/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'], [/(seraph|cherub)(?:im)?$/i, '$1im'], [/(her|at|gr)o$/i, '$1oes'], [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, '$1a'], [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, '$1a'], [/sis$/i, 'ses'], [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, '$1$2ves'], [/([^aeiouy]|qu)y$/i, '$1ies'], [/([^ch][ieo][ln])ey$/i, '$1ies'], [/(x|ch|ss|sh|zz)$/i, '$1es'], [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'], [/\b((?:tit)?m|l)(?:ice|ouse)$/i, '$1ice'], [/(pe)(?:rson|ople)$/i, '$1ople'], [/(child)(?:ren)?$/i, '$1ren'], [/eaux$/i, '$0'], [/m[ae]n$/i, 'men'], ['thou', 'you']];
/**
* Singularization rules.
*/
var singular = [[/s$/i, ''], [/(ss)$/i, '$1'], [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, '$1fe'], [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'], [/ies$/i, 'y'], [/(dg|ss|ois|lk|ok|wn|mb|th|ch|ec|oal|is|ck|ix|sser|ts|wb)ies$/i, '$1ie'], [/\b(l|(?:neck|cross|hog|aun)?t|coll|faer|food|gen|goon|group|hipp|junk|vegg|(?:pork)?p|charl|calor|cut)ies$/i, '$1ie'], [/\b(mon|smil)ies$/i, '$1ey'], [/\b((?:tit)?m|l)ice$/i, '$1ouse'], [/(seraph|cherub)im$/i, '$1'], [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i, '$1'], [/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i, '$1sis'], [/(movie|twelve|abuse|e[mn]u)s$/i, '$1'], [/(test)(?:is|es)$/i, '$1is'], [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1us'], [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, '$1um'], [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, '$1on'], [/(alumn|alg|vertebr)ae$/i, '$1a'], [/(cod|mur|sil|vert|ind)ices$/i, '$1ex'], [/(matr|append)ices$/i, '$1ix'], [/(pe)(rson|ople)$/i, '$1rson'], [/(child)ren$/i, '$1'], [/(eau)x?$/i, '$1'], [/men$/i, 'man']];
/**
* Uncountable rules.
*/
var uncountable = [// Singular words with no plurals.
'adulthood', 'advice', 'agenda', 'aid', 'aircraft', 'alcohol', 'ammo', 'analytics', 'anime', 'athletics', 'audio', 'bison', 'blood', 'bream', 'buffalo', 'butter', 'carp', 'cash', 'chassis', 'chess', 'clothing', 'cod', 'commerce', 'cooperation', 'corps', 'debris', 'diabetes', 'digestion', 'elk', 'energy', 'equipment', 'excretion', 'expertise', 'firmware', 'flounder', 'fun', 'gallows', 'garbage', 'graffiti', 'hardware', 'headquarters', 'health', 'herpes', 'highjinks', 'homework', 'housework', 'information', 'jeans', 'justice', 'kudos', 'labour', 'literature', 'machinery', 'mackerel', 'mail', 'media', 'mews', 'moose', 'music', 'mud', 'manga', 'news', 'only', 'personnel', 'pike', 'plankton', 'pliers', 'police', 'pollution', 'premises', 'rain', 'research', 'rice', 'salmon', 'scissors', 'series', 'sewage', 'shambles', 'shrimp', 'software', 'staff', 'swine', 'tennis', 'traffic', 'transportation', 'trout', 'tuna', 'wealth', 'welfare', 'whiting', 'wildebeest', 'wildlife', 'you', /pok[eé]mon$/i, // Regexes.
/[^aeiou]ese$/i, // "chinese", "japanese"
/deer$/i, // "deer", "reindeer"
/fish$/i, // "fish", "blowfish", "angelfish"
/measles$/i, /o[iu]s$/i, // "carnivorous"
/pox$/i, // "chickpox", "smallpox"
/sheep$/i];
/**
*
*/
var Pluralize = /*#__PURE__*/function () {
/**
*
*/
function Pluralize() {
_classCallCheck(this, Pluralize);
console.log("Pluralize ()");
plPointer = this;
var i = 0;
for (i = 0; i < irregular.length; i++) {
var rule = irregular[i];
this.addIrregularRule(rule[0], rule[1]);
}
for (i = 0; i < plural.length; i++) {
var _rule = plural[i];
this.addPluralRule(_rule[0], _rule[1]);
}
for (i = 0; i < singular.length; i++) {
var _rule2 = singular[i];
this.addSingularRule(_rule2[0], _rule2[1]);
}
for (i = 0; i < uncountable.length; i++) {
this.addUncountableRule(uncountable[i]);
}
console.log(this.pluralize("team", 2, false));
}
/**
* Sanitize a pluralization rule to a usable regular expression.
*
* @param {(RegExp|string)} rule
* @return {RegExp}
*/
_createClass(Pluralize, [{
key: "sanitizeRule",
value: function sanitizeRule(rule) {
if (typeof rule === 'string') {
return new RegExp('^' + rule + '$', 'i');
}
return rule;
}
/**
* Pass in a word token to produce a function that can replicate the case on
* another word.
*
* @param {string} word
* @param {string} token
* @return {Function}
*/
}, {
key: "restoreCase",
value: function restoreCase(word, token) {
// Tokens are an exact match.
if (word === token) return token; // Lower cased words. E.g. "hello".
if (word === word.toLowerCase()) return token.toLowerCase(); // Upper cased words. E.g. "WHISKY".
if (word === word.toUpperCase()) return token.toUpperCase(); // Title cased words. E.g. "Title".
if (word[0] === word[0].toUpperCase()) {
return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase();
} // Lower cased words. E.g. "test".
return token.toLowerCase();
}
/**
* Interpolate a regexp string.
*
* @param {string} str
* @param {Array} args
* @return {string}
*/
}, {
key: "interpolate",
value: function interpolate(str, args) {
return str.replace(/\$(\d{1,2})/g, function (match, index) {
return args[index] || '';
});
}
/**
* Replace a word using a rule.
*
* @param {string} word
* @param {Array} rule
* @return {string}
*/
}, {
key: "replace",
value: function replace(word, rule) {
return word.replace(rule[0], function (match, index) {
var result = plPointer.interpolate(rule[1], arguments);
if (match === '') {
return plPointer.restoreCase(word[index - 1], result);
}
return plPointer.restoreCase(match, result);
});
}
/**
* Sanitize a word by passing in the word and sanitization rules.
*
* @param {string} token
* @param {string} word
* @param {Array} rules
* @return {string}
*/
}, {
key: "sanitizeWord",
value: function sanitizeWord(token, word, rules) {
// Empty string or doesn't need fixing.
if (!token.length || uncountables.hasOwnProperty(token)) {
return word;
}
var len = rules.length; // Iterate over the sanitization rules and use the first one to match.
while (len--) {
var rule = rules[len];
if (rule[0].test(word)) return this.replace(word, rule);
}
return word;
}
/**
* Replace a word with the updated word.
*
* @param {Object} replaceMap
* @param {Object} keepMap
* @param {Array} rules
* @return {Function}
*/
}, {
key: "replaceWord",
value: function replaceWord(replaceMap, keepMap, rules) {
return function (word) {
// Get the correct token and case restoration functions.
var token = word.toLowerCase(); // Check against the keep object map.
if (keepMap.hasOwnProperty(token)) {
return plPointer.restoreCase(word, token);
} // Check against the replacement map for a direct word replacement.
if (replaceMap.hasOwnProperty(token)) {
return plPointer.restoreCase(word, replaceMap[token]);
} // Run all the rules against the word.
return this.sanitizeWord(token, word, rules);
};
}
/**
* Check if a word is part of the map.
*/
}, {
key: "checkWord",
value: function checkWord(replaceMap, keepMap, rules, bool) {
return function (word) {
var token = word.toLowerCase();
if (keepMap.hasOwnProperty(token)) return true;
if (replaceMap.hasOwnProperty(token)) return false;
return this.sanitizeWord(token, token, rules) === token;
};
}
/**
* Pluralize a word.
*
* @type {Function}
*/
}, {
key: "plural",
value: function plural(word) {
//console.log ("plural ()");
var replaceMap = irregularSingles;
var keepMap = irregularPlurals;
var rules = pluralRules; // Get the correct token and case restoration functions.
var token = word.toLowerCase(); // Check against the keep object map.
if (keepMap.hasOwnProperty(token)) {
//console.log ("keepMap.hasOwnProperty(token)");
return plPointer.restoreCase(word, token);
} // Check against the replacement map for a direct word replacement.
if (replaceMap.hasOwnProperty(token)) {
//console.log ("replaceMap.hasOwnProperty(token))");
return plPointer.restoreCase(word, replaceMap[token]);
} //console.log ("Wrapping up");
// Run all the rules against the word.
return this.sanitizeWord(token, word, rules);
}
/**
* Check if a word is plural.
*
* @type {Function}
*/
}, {
key: "isPlural",
value: function isPlural() {
return this.checkWord(irregularSingles, irregularPlurals, pluralRules);
}
/**
* Singularize a word.
*
* @type {Function}
*/
}, {
key: "singular",
value: function singular() {
return this.replaceWord(irregularPlurals, irregularSingles, singularRules);
}
/**
* Check if a word is singular.
*
* @type {Function}
*/
}, {
key: "isSingular",
value: function isSingular() {
return this.checkWord(irregularPlurals, irregularSingles, singularRules);
}
/**
* Add a pluralization rule to the collection.
*
* @param {(string|RegExp)} rule
* @param {string} replacement
*/
}, {
key: "addPluralRule",
value: function addPluralRule(rule, replacement) {
pluralRules.push([this.sanitizeRule(rule), replacement]);
}
/**
* Add a singularization rule to the collection.
*
* @param {(string|RegExp)} rule
* @param {string} replacement
*/
}, {
key: "addSingularRule",
value: function addSingularRule(rule, replacement) {
singularRules.push([this.sanitizeRule(rule), replacement]);
}
/**
* Add an uncountable word rule.
*
* @param {(string|RegExp)} word
*/
}, {
key: "addUncountableRule",
value: function addUncountableRule(word) {
if (typeof word === 'string') {
uncountables[word.toLowerCase()] = true;
return;
} // Set singular and plural references for the word.
this.addPluralRule(word, '$0');
this.addSingularRule(word, '$0');
}
/**
* Add an irregular word definition.
*
* @param {string} single
* @param {string} plural
*/
}, {
key: "addIrregularRule",
value: function addIrregularRule(single, plural) {
plural = plural.toLowerCase();
single = single.toLowerCase();
irregularSingles[single] = plural;
irregularPlurals[plural] = single;
}
/**
* Pluralize or singularize a word based on the passed in count.
*
* @param {string} word The word to pluralize
* @param {number} count How many of the word exist
* @param {boolean} inclusive Whether to prefix with the number (e.g. 3 ducks)
* @return {string}
*/
}, {
key: "pluralize",
value: function pluralize(word, count, inclusive) {
var pluralized = count === 1 ? this.singular(word) : this.plural(word);
return (inclusive ? count + ' ' : '') + pluralized;
}
}]);
return Pluralize;
}();
exports["default"] = Pluralize;