UNPKG

@microsoft.azure/autorest.incubator

Version:
677 lines 35.8 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); /* * PORTED FROM System.Data.Entity.Infrastructure.Pluralization.EnglishPluralizationService (EntityFramework.dll) */ class StringBidirectionalDictionary { constructor(dict = {}) { this.dictForward = new Map(); this.dictBackward = new Map(); for (const key of Object.keys(dict)) { const value = dict[key]; this.AddValue(key, value); } } AddValue(first, second) { this.dictForward.set(first, second); this.dictBackward.set(second, first); } ExistsInFirst(s) { return this.dictForward.has(s); } ExistsInSecond(s) { return this.dictBackward.has(s); } GetFirstValue(s) { return this.dictBackward.get(s) || (() => { throw new Error('Cannot find key.'); })(); } GetSecondValue(s) { return this.dictForward.get(s) || (() => { throw new Error('Cannot find key.'); })(); } } function endsWithIgnoreCase(word, suffix) { return word.toLowerCase().endsWith(suffix.toLowerCase()); } class PluralizationServiceUtil { static DoesWordContainSuffix(word, suffixes) { return suffixes.some(s => endsWithIgnoreCase(word, s)); } static TryInflectOnSuffixInWord(word, suffixes, operationOnWord) { if (PluralizationServiceUtil.DoesWordContainSuffix(word, suffixes)) { return operationOnWord(word); } else { return null; } } } class EnglishPluralizationService { constructor() { this._uninflectiveSuffixList = ['fish', 'ois', 'sheep', 'deer', 'pos', 'itis', 'ism']; this._uninflectiveWordList = [ 'bison', 'flounder', 'pliers', 'bream', 'gallows', 'proceedings', 'breeches', 'graffiti', 'rabies', 'britches', 'headquarters', 'salmon', 'carp', '----', 'scissors', 'ch----is', 'high-jinks', 'sea-bass', 'clippers', 'homework', 'series', 'cod', 'innings', 'shears', 'contretemps', 'jackanapes', 'species', 'corps', 'mackerel', 'swine', 'debris', 'measles', 'trout', 'diabetes', 'mews', 'tuna', 'djinn', 'mumps', 'whiting', 'eland', 'news', 'wildebeest', 'elk', 'pincers', 'police', 'hair', 'ice', 'chaos', 'milk', 'cotton', 'pneumonoultramicroscopicsilicovolcanoconiosis', 'information', 'aircraft', 'scabies', 'traffic', 'corn', 'millet', 'rice', 'hay', '----', 'tobacco', 'cabbage', 'okra', 'broccoli', 'asparagus', 'lettuce', 'beef', 'pork', 'venison', 'mutton', 'cattle', 'offspring', 'molasses', 'shambles', 'shingles' ]; this._irregularVerbList = { 'am': 'are', 'are': 'are', 'is': 'are', 'was': 'were', 'were': 'were', 'has': 'have', 'have': 'have' }; this._pronounList = [ 'I', 'we', 'you', 'he', 'she', 'they', 'it', 'me', 'us', 'him', 'her', 'them', 'myself', 'ourselves', 'yourself', 'himself', 'herself', 'itself', 'oneself', 'oneselves', 'my', 'our', 'your', 'his', 'their', 'its', 'mine', 'yours', 'hers', 'theirs', 'this', 'that', 'these', 'those', 'all', 'another', 'any', 'anybody', 'anyone', 'anything', 'both', 'each', 'other', 'either', 'everyone', 'everybody', 'everything', 'most', 'much', 'nothing', 'nobody', 'none', 'one', 'others', 'some', 'somebody', 'someone', 'something', 'what', 'whatever', 'which', 'whichever', 'who', 'whoever', 'whom', 'whomever', 'whose' ]; this._irregularPluralsDictionary = { 'brother': 'brothers', 'child': 'children', 'cow': 'cows', 'ephemeris': 'ephemerides', 'genie': 'genies', 'money': 'moneys', 'mongoose': 'mongooses', 'mythos': 'mythoi', 'octopus': 'octopuses', 'ox': 'oxen', 'soliloquy': 'soliloquies', 'trilby': 'trilbys', 'crisis': 'crises', 'synopsis': 'synopses', 'rose': 'roses', 'gas': 'gases', 'bus': 'buses', 'axis': 'axes', 'memo': 'memos', 'casino': 'casinos', 'silo': 'silos', 'stereo': 'stereos', 'studio': 'studios', 'lens': 'lenses', 'alias': 'aliases', 'pie': 'pies', 'corpus': 'corpora', 'viscus': 'viscera', 'hippopotamus': 'hippopotami', 'trace': 'traces', 'person': 'people', 'chili': 'chilies', 'analysis': 'analyses', 'basis': 'bases', 'neurosis': 'neuroses', 'oasis': 'oases', 'synthesis': 'syntheses', 'thesis': 'theses', 'change': 'changes', 'lie': 'lies', 'calorie': 'calories', 'freebie': 'freebies', 'case': 'cases', 'house': 'houses', 'valve': 'valves', 'cloth': 'clothes', 'tie': 'ties', 'movie': 'movies', 'bonus': 'bonuses', 'specimen': 'specimens' }; this._assimilatedClassicalInflectionDictionary = { 'alumna': 'alumnae', 'alga': 'algae', 'vertebra': 'vertebrae', 'codex': 'codices', 'murex': 'murices', 'silex': 'silices', 'aphelion': 'aphelia', 'hyperbaton': 'hyperbata', 'perihelion': 'perihelia', 'asyndeton': 'asyndeta', 'noumenon': 'noumena', 'phenomenon': 'phenomena', 'criterion': 'criteria', 'organon': 'organa', 'prolegomenon': 'prolegomena', 'agendum': 'agenda', 'datum': 'data', 'extremum': 'extrema', 'bacterium': 'bacteria', 'desideratum': 'desiderata', 'stratum': 'strata', 'candelabrum': 'candelabra', 'erratum': 'errata', 'ovum': 'ova', 'forum': 'fora', 'addendum': 'addenda', 'stadium': 'stadia', 'automaton': 'automata', 'polyhedron': 'polyhedra', }; this._oSuffixDictionary = { 'albino': 'albinos', 'generalissimo': 'generalissimos', 'manifesto': 'manifestos', 'archipelago': 'archipelagos', 'ghetto': 'ghettos', 'medico': 'medicos', 'armadillo': 'armadillos', 'guano': 'guanos', 'octavo': 'octavos', 'commando': 'commandos', 'inferno': 'infernos', 'photo': 'photos', 'ditto': 'dittos', 'jumbo': 'jumbos', 'pro': 'pros', 'dynamo': 'dynamos', 'lingo': 'lingos', 'quarto': 'quartos', 'embryo': 'embryos', 'lumbago': 'lumbagos', 'rhino': 'rhinos', 'fiasco': 'fiascos', 'magneto': 'magnetos', 'stylo': 'stylos' }; this._classicalInflectionDictionary = { 'stamen': 'stamina', 'foramen': 'foramina', 'lumen': 'lumina', 'anathema': 'anathemata', '----': '----ta', 'oedema': 'oedemata', 'bema': 'bemata', 'enigma': 'enigmata', 'sarcoma': 'sarcomata', 'carcinoma': 'carcinomata', 'gumma': 'gummata', 'schema': 'schemata', 'charisma': 'charismata', 'lemma': 'lemmata', 'soma': 'somata', 'diploma': 'diplomata', 'lymphoma': 'lymphomata', 'stigma': 'stigmata', 'dogma': 'dogmata', 'magma': 'magmata', 'stoma': 'stomata', 'drama': 'dramata', 'melisma': 'melismata', 'trauma': 'traumata', 'edema': 'edemata', 'miasma': 'miasmata', 'abscissa': 'abscissae', 'formula': 'formulae', 'medusa': 'medusae', 'amoeba': 'amoebae', 'hydra': 'hydrae', 'nebula': 'nebulae', 'antenna': 'antennae', 'hyperbola': 'hyperbolae', 'nova': 'novae', 'aurora': 'aurorae', 'lacuna': 'lacunae', 'parabola': 'parabolae', 'apex': 'apices', 'latex': 'latices', 'vertex': 'vertices', 'cortex': 'cortices', 'pontifex': 'pontifices', 'vortex': 'vortices', 'index': 'indices', 'simplex': 'simplices', 'iris': 'irides', '----oris': '----orides', 'alto': 'alti', 'contralto': 'contralti', 'soprano': 'soprani', 'b----o': 'b----i', 'crescendo': 'crescendi', 'tempo': 'tempi', 'canto': 'canti', 'solo': 'soli', 'aquarium': 'aquaria', 'interregnum': 'interregna', 'quantum': 'quanta', 'compendium': 'compendia', 'lustrum': 'lustra', 'rostrum': 'rostra', 'consortium': 'consortia', 'maximum': 'maxima', 'spectrum': 'spectra', 'cranium': 'crania', 'medium': 'media', 'speculum': 'specula', 'curriculum': 'curricula', 'memorandum': 'memoranda', 'stadium': 'stadia', 'dictum': 'dicta', 'millenium': 'millenia', 't----zium': 't----zia', 'emporium': 'emporia', 'minimum': 'minima', 'ultimatum': 'ultimata', 'enconium': 'enconia', 'momentum': 'momenta', 'vacuum': 'vacua', 'gymnasium': 'gymnasia', 'optimum': 'optima', 'velum': 'vela', 'honorarium': 'honoraria', 'phylum': 'phyla', 'focus': 'foci', 'nimbus': 'nimbi', 'succubus': 'succubi', 'fungus': 'fungi', 'nucleolus': 'nucleoli', 'torus': 'tori', 'genius': 'genii', 'radius': 'radii', 'umbilicus': 'umbilici', 'incubus': 'incubi', 'stylus': 'styli', 'uterus': 'uteri', 'stimulus': 'stimuli', 'apparatus': 'apparatus', 'impetus': 'impetus', 'prospectus': 'prospectus', 'cantus': 'cantus', 'nexus': 'nexus', 'sinus': 'sinus', 'coitus': 'coitus', 'plexus': 'plexus', 'status': 'status', 'hiatus': 'hiatus', 'afreet': 'afreeti', 'afrit': 'afriti', 'efreet': 'efreeti', 'cherub': 'cherubim', 'goy': 'goyim', 'seraph': 'seraphim', 'alumnus': 'alumni' }; // this list contains all the plural words that being treated as singluar form, for example, "they" -> "they" this._knownConflictingPluralList = ['they', 'them', 'their', 'have', 'were', 'yourself', 'are']; // this list contains the words ending with "se" and we special case these words since // we need to add a rule for "ses" singularize to "s" this._wordsEndingWithSeDictionary = { 'house': 'houses', 'case': 'cases', 'enterprise': 'enterprises', 'purchase': 'purchases', 'surprise': 'surprises', 'release': 'releases', 'disease': 'diseases', 'promise': 'promises', 'refuse': 'refuses', 'whose': 'whoses', 'phase': 'phases', 'noise': 'noises', 'nurse': 'nurses', 'rose': 'roses', 'franchise': 'franchises', 'supervise': 'supervises', 'farmhouse': 'farmhouses', 'suitcase': 'suitcases', 'recourse': 'recourses', 'impulse': 'impulses', 'license': 'licenses', 'diocese': 'dioceses', 'excise': 'excises', 'demise': 'demises', 'blouse': 'blouses', 'bruise': 'bruises', 'misuse': 'misuses', 'curse': 'curses', 'prose': 'proses', 'purse': 'purses', 'goose': 'gooses', 'tease': 'teases', 'poise': 'poises', 'vase': 'vases', 'fuse': 'fuses', 'muse': 'muses', 'slaughterhouse': 'slaughterhouses', 'clearinghouse': 'clearinghouses', 'endonuclease': 'endonucleases', 'steeplechase': 'steeplechases', 'metamorphose': 'metamorphoses', '----': '----s', 'commonsense': 'commonsenses', 'intersperse': 'intersperses', 'merchandise': 'merchandises', 'phosphatase': 'phosphatases', 'summerhouse': 'summerhouses', 'watercourse': 'watercourses', 'catchphrase': 'catchphrases', 'compromise': 'compromises', 'greenhouse': 'greenhouses', 'lighthouse': 'lighthouses', 'paraphrase': 'paraphrases', 'mayonnaise': 'mayonnaises', '----course': '----courses', 'apocalypse': 'apocalypses', 'courthouse': 'courthouses', 'powerhouse': 'powerhouses', 'storehouse': 'storehouses', 'glasshouse': 'glasshouses', 'hypotenuse': 'hypotenuses', 'peroxidase': 'peroxidases', 'pillowcase': 'pillowcases', 'roundhouse': 'roundhouses', 'streetwise': 'streetwises', 'expertise': 'expertises', 'discourse': 'discourses', 'warehouse': 'warehouses', 'staircase': 'staircases', 'workhouse': 'workhouses', 'briefcase': 'briefcases', 'clubhouse': 'clubhouses', 'clockwise': 'clockwises', 'concourse': 'concourses', 'playhouse': 'playhouses', 'turquoise': 'turquoises', 'boathouse': 'boathouses', 'cellulose': 'celluloses', 'epitomise': 'epitomises', 'gatehouse': 'gatehouses', 'grandiose': 'grandioses', 'menopause': 'menopauses', 'penthouse': 'penthouses', '----horse': '----horses', 'transpose': 'transposes', 'almshouse': 'almshouses', 'customise': 'customises', 'footloose': 'footlooses', 'galvanise': 'galvanises', 'princesse': 'princesses', 'universe': 'universes', 'workhorse': 'workhorses' }; this._wordsEndingWithSisDictionary = { 'analysis': 'analyses', 'crisis': 'crises', 'basis': 'bases', 'atherosclerosis': 'atheroscleroses', 'electrophoresis': 'electrophoreses', 'psychoanalysis': 'psychoanalyses', 'photosynthesis': 'photosyntheses', 'amniocentesis': 'amniocenteses', 'metamorphosis': 'metamorphoses', 'toxoplasmosis': 'toxoplasmoses', 'endometriosis': 'endometrioses', 'tuberculosis': 'tuberculoses', 'pathogenesis': 'pathogeneses', 'osteoporosis': 'osteoporoses', 'parenthesis': 'parentheses', 'anastomosis': 'anastomoses', 'peristalsis': 'peristalses', 'hypothesis': 'hypotheses', 'antithesis': 'antitheses', 'apotheosis': 'apotheoses', 'thrombosis': 'thromboses', 'diagnosis': 'diagnoses', 'synthesis': 'syntheses', 'paralysis': 'paralyses', 'prognosis': 'prognoses', 'cirrhosis': 'cirrhoses', 'sclerosis': 'scleroses', 'psychosis': 'psychoses', 'apoptosis': 'apoptoses', 'symbiosis': 'symbioses', 'redis': 'redis' }; this._wordsEndingWithSusDictionary = { 'consensus': 'consensuses', 'census': 'censuses' }; this._wordsEndingWithInxAnxYnxDictionary = { 'sphinx': 'sphinxes', 'larynx': 'larynges', 'lynx': 'lynxes', 'pharynx': 'pharynxes', 'phalanx': 'phalanxes' }; const flatten = (l) => [].concat.apply([], l); this._userDictionary = new StringBidirectionalDictionary(); this._irregularPluralsPluralizationService = new StringBidirectionalDictionary(this._irregularPluralsDictionary); this._assimilatedClassicalInflectionPluralizationService = new StringBidirectionalDictionary(this._assimilatedClassicalInflectionDictionary); this._oSuffixPluralizationService = new StringBidirectionalDictionary(this._oSuffixDictionary); this._classicalInflectionPluralizationService = new StringBidirectionalDictionary(this._classicalInflectionDictionary); this._wordsEndingWithSePluralizationService = new StringBidirectionalDictionary(this._wordsEndingWithSeDictionary); this._wordsEndingWithSisPluralizationService = new StringBidirectionalDictionary(this._wordsEndingWithSisDictionary); this._wordsEndingWithSusPluralizationService = new StringBidirectionalDictionary(this._wordsEndingWithSusDictionary); this._wordsEndingWithInxAnxYnxPluralizationService = new StringBidirectionalDictionary(this._wordsEndingWithInxAnxYnxDictionary); // verb this._irregularVerbPluralizationService = new StringBidirectionalDictionary(this._irregularVerbList); this._knownSingluarWords = flatten([ Object.keys(this._irregularPluralsDictionary), Object.keys(this._assimilatedClassicalInflectionDictionary), Object.keys(this._oSuffixDictionary), Object.keys(this._classicalInflectionDictionary), Object.keys(this._irregularVerbList), Object.keys(this._irregularPluralsDictionary), Object.keys(this._wordsEndingWithSeDictionary), Object.keys(this._wordsEndingWithSisDictionary), Object.keys(this._wordsEndingWithSusDictionary), Object.keys(this._wordsEndingWithInxAnxYnxDictionary), Object.keys(this._uninflectiveWordList) ]).filter(x => !this._knownConflictingPluralList.includes(x)); // see the _knowConflictingPluralList comment above this._knownPluralWords = flatten([ Object.values(this._irregularPluralsDictionary), Object.values(this._assimilatedClassicalInflectionDictionary), Object.values(this._oSuffixDictionary), Object.values(this._classicalInflectionDictionary), Object.values(this._irregularVerbList), Object.values(this._irregularPluralsDictionary), Object.values(this._wordsEndingWithSeDictionary), Object.values(this._wordsEndingWithSisDictionary), Object.values(this._wordsEndingWithSusDictionary), Object.values(this._wordsEndingWithInxAnxYnxDictionary), Object.values(this._uninflectiveWordList) ]); } IsPlural(word) { if (this._userDictionary.ExistsInSecond(word)) { return true; } if (this._userDictionary.ExistsInFirst(word)) { return false; } if (this.IsUninflective(word) || this._knownPluralWords.includes(word.toLowerCase())) { return true; } else if (this.Singularize(word) === word) { return false; } else { return true; } } IsSingular(word) { if (this._userDictionary.ExistsInFirst(word)) { return true; } if (this._userDictionary.ExistsInSecond(word)) { return false; } if (this.IsUninflective(word) || this._knownSingluarWords.includes(word.toLowerCase())) { return true; } else if (!this.IsNoOpWord(word) && this.Singularize(word) === word) { return true; } else { return false; } } // Pluralize(word) { return this.Capitalize(word, w => this.InternalPluralize(w)); } InternalPluralize(word) { // words that we know of if (this._userDictionary.ExistsInFirst(word)) { return this._userDictionary.GetSecondValue(word); } if (this.IsNoOpWord(word)) { return word; } const { prefixWord, suffixWord } = this.GetSuffixWord(word); // by me -> by me if (this.IsNoOpWord(suffixWord)) { return prefixWord + suffixWord; } // handle the word that do not inflect in the plural form if (this.IsUninflective(suffixWord)) { return prefixWord + suffixWord; } // if word is one of the known plural forms, then just return if (this._knownPluralWords.includes(suffixWord.toLowerCase()) || this.IsPlural(suffixWord)) { return prefixWord + suffixWord; } // handle irregular plurals, e.g. "ox" -> "oxen" if (this._irregularPluralsPluralizationService.ExistsInFirst(suffixWord)) { return prefixWord + this._irregularPluralsPluralizationService.GetSecondValue(suffixWord); } let newSuffixWord; newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['man'], s => s.slice(0, -2) + 'en'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // handle irregular inflections for common suffixes, e.g. "mouse" -> "mice" newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['louse', 'mouse'], s => s.slice(0, -4) + 'ice'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['tooth'], s => s.slice(0, -4) + 'eeth'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['goose'], s => s.slice(0, -4) + 'eese'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['foot'], s => s.slice(0, -3) + 'eet'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['zoon'], s => s.slice(0, -3) + 'oa'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['cis', 'sis', 'xis'], s => s.slice(0, -2) + 'es'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // handle assimilated classical inflections, e.g. vertebra -> vertebrae if (this._assimilatedClassicalInflectionPluralizationService.ExistsInFirst(suffixWord)) { return prefixWord + this._assimilatedClassicalInflectionPluralizationService.GetSecondValue(suffixWord); } // Handle the classical variants of modern inflections // if (this._classicalInflectionPluralizationService.ExistsInFirst(suffixWord)) { return prefixWord + this._classicalInflectionPluralizationService.GetSecondValue(suffixWord); } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['trix'], s => s.slice(0, -1) + 'ces'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['eau', 'ieu'], s => s + 'x'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } if (this._wordsEndingWithInxAnxYnxPluralizationService.ExistsInFirst(suffixWord)) { return prefixWord + this._wordsEndingWithInxAnxYnxPluralizationService.GetSecondValue(suffixWord); } // [cs]h and ss that take es as plural form newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['ch', 'sh', 'ss'], s => s + 'es'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // f, fe that take ves as plural form newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['alf', 'elf', 'olf', 'eaf', 'arf'], s => endsWithIgnoreCase(s, 'deaf') ? s : s.slice(0, -1) + 'ves'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['nife', 'life', 'wife'], s => s.slice(0, -2) + 'ves'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // y takes ys as plural form if preceded by a vowel, but ies if preceded by a consonant, e.g. stays, skies newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['ay', 'ey', 'iy', 'oy', 'uy'], s => s + 's'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // if (endsWithIgnoreCase(suffixWord, 'y')) { return prefixWord + suffixWord.slice(0, -1) + 'ies'; } // handle some of the words o -> os, and [vowel]o -> os, and the rest are o->oes if (this._oSuffixPluralizationService.ExistsInFirst(suffixWord)) { return prefixWord + this._oSuffixPluralizationService.GetSecondValue(suffixWord); } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['ao', 'eo', 'io', 'oo', 'uo'], s => s + 's'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } if (endsWithIgnoreCase(suffixWord, 'o') || endsWithIgnoreCase(suffixWord, 's')) { return prefixWord + suffixWord + 'es'; } if (endsWithIgnoreCase(suffixWord, 'x')) { return prefixWord + suffixWord + 'es'; } // cats, bags, hats, speakers return prefixWord + suffixWord + 's'; } Singularize(word) { return this.Capitalize(word, w => this.InternalSingularize(w)); } InternalSingularize(word) { // words that we know of if (this._userDictionary.ExistsInSecond(word)) { return this._userDictionary.GetFirstValue(word); } if (this.IsNoOpWord(word)) { return word; } const { prefixWord, suffixWord } = this.GetSuffixWord(word); if (this.IsNoOpWord(suffixWord)) { return prefixWord + suffixWord; } // handle the word that is the same as the plural form if (this.IsUninflective(suffixWord)) { return prefixWord + suffixWord; } // if word is one of the known singular words, then just return if (this._knownSingluarWords.includes(suffixWord.toLowerCase())) { return prefixWord + suffixWord; } // handle simple irregular verbs, e.g. was -> were if (this._irregularVerbPluralizationService.ExistsInSecond(suffixWord)) { return prefixWord + this._irregularVerbPluralizationService.GetFirstValue(suffixWord); } // handle irregular plurals, e.g. "ox" -> "oxen" if (this._irregularPluralsPluralizationService.ExistsInSecond(suffixWord)) { return prefixWord + this._irregularPluralsPluralizationService.GetFirstValue(suffixWord); } // handle singluarization for words ending with sis and pluralized to ses, // e.g. "ses" -> "sis" if (this._wordsEndingWithSisPluralizationService.ExistsInSecond(suffixWord)) { return prefixWord + this._wordsEndingWithSisPluralizationService.GetFirstValue(suffixWord); } // handle words ending with se, e.g. "ses" -> "se" if (this._wordsEndingWithSePluralizationService.ExistsInSecond(suffixWord)) { return prefixWord + this._wordsEndingWithSePluralizationService.GetFirstValue(suffixWord); } // handle words ending with sus, e.g. "suses" -> "sus" if (this._wordsEndingWithSusPluralizationService.ExistsInSecond(suffixWord)) { return prefixWord + this._wordsEndingWithSusPluralizationService.GetFirstValue(suffixWord); } let newSuffixWord; newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['men'], s => s.slice(0, -2) + 'an'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // handle irregular inflections for common suffixes, e.g. "mouse" -> "mice" newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['lice', 'mice'], s => s.slice(0, -3) + 'ouse'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['teeth'], s => s.slice(0, -4) + 'ooth'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['geese'], s => s.slice(0, -4) + 'oose'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['feet'], s => s.slice(0, -3) + 'oot'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['zoa'], s => s.slice(0, -2) + 'oon'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // [cs]h and ss that take es as plural form, this is being moved up since the sses will be override by the ses newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['ches', 'shes', 'sses'], s => s.slice(0, -2)); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // handle assimilated classical inflections, e.g. vertebra -> vertebrae if (this._assimilatedClassicalInflectionPluralizationService.ExistsInSecond(suffixWord)) { return prefixWord + this._assimilatedClassicalInflectionPluralizationService.GetFirstValue(suffixWord); } // Handle the classical variants of modern inflections // if (this._classicalInflectionPluralizationService.ExistsInSecond(suffixWord)) { return prefixWord + this._classicalInflectionPluralizationService.GetFirstValue(suffixWord); } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['trices'], s => s.slice(0, -3) + 'x'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['eaux', 'ieux'], s => s.slice(0, -1)); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } if (this._wordsEndingWithInxAnxYnxPluralizationService.ExistsInSecond(suffixWord)) { return prefixWord + this._wordsEndingWithInxAnxYnxPluralizationService.GetFirstValue(suffixWord); } // f, fe that take ves as plural form newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['alves', 'elves', 'olves', 'eaves', 'arves'], s => s.slice(0, -3) + 'f'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['nives', 'lives', 'wives'], s => s.slice(0, -3) + 'fe'); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // y takes ys as plural form if preceded by a vowel, but ies if preceded by a consonant, e.g. stays, skies newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['ays', 'eys', 'iys', 'oys', 'uys'], s => s.slice(0, -1)); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // if (endsWithIgnoreCase(suffixWord, 'ies')) { return prefixWord + suffixWord.slice(0, -3) + 'y'; } // handle some of the words o -> os, and [vowel]o -> os, and the rest are o->oes if (this._oSuffixPluralizationService.ExistsInSecond(suffixWord)) { return prefixWord + this._oSuffixPluralizationService.GetFirstValue(suffixWord); } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['aos', 'eos', 'ios', 'oos', 'uos'], s => s.slice(0, -1)); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } // newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['ces'], s => s.slice(0, -1)); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } newSuffixWord = PluralizationServiceUtil.TryInflectOnSuffixInWord(suffixWord, ['ces', 'ses', 'xes'], s => s.slice(0, -2)); if (newSuffixWord !== null) { return prefixWord + newSuffixWord; } if (endsWithIgnoreCase(suffixWord, 'oes')) { return prefixWord + suffixWord.slice(0, -2); } if (endsWithIgnoreCase(suffixWord, 'ss')) { return prefixWord + suffixWord; } if (endsWithIgnoreCase(suffixWord, 's')) { return prefixWord + suffixWord.slice(0, -1); } // word is a singlar return prefixWord + suffixWord; } /// <summary> /// captalize the return word if the parameter is capitalized /// if word is "Table", then return "Tables" /// </summary> /// <param name="word"></param> /// <param name="action"></param> /// <returns></returns> Capitalize(word, action) { const result = action(word); if (this.IsCapitalized(word)) { if (result.length == 0) { return result; } return result.charAt(0).toUpperCase() + result.substr(1); } else { return result; } } /// <summary> /// separate one combine word in to two parts, prefix word and the last word(suffix word) /// </summary> /// <param name="word"></param> /// <param name="prefixWord"></param> /// <returns></returns> GetSuffixWord(word) { // use the last space to separate the words const lastSpaceIndex = word.lastIndexOf(' '); return { prefixWord: word.substr(0, lastSpaceIndex + 1), suffixWord: word.substr(lastSpaceIndex + 1) }; // } IsCapitalized(word) { if (word === '') { return false; } word = word.charAt(0); return word.toUpperCase() === word; } IsAlphabets(word) { // return false when the word is "[\s]*" or leading or tailing with spaces // or contains non alphabetical characters if (word === '' || word !== word.trim() || /[^a-zA-Z\\s]/.test(word)) { return false; } else { return true; } } IsUninflective(word) { if (PluralizationServiceUtil.DoesWordContainSuffix(word, this._uninflectiveSuffixList) || (word.toLowerCase() !== word && word.endsWith('ese')) || this._uninflectiveWordList.includes(word.toLowerCase())) { return true; } else { return false; } } /// <summary> /// return true when the word is "[\s]*" or leading or tailing with spaces /// or contains non alphabetical characters /// </summary> /// <param name="word"></param> /// <returns></returns> IsNoOpWord(word) { if (!this.IsAlphabets(word) || word.length <= 1 || this._pronounList.includes(word.toLowerCase())) { return true; } else { return false; } } /// <summary> /// This method allow you to add word to internal PluralizationService of English. /// If the singluar or the plural value was already added by this method, then an ArgumentException will be thrown. /// </summary> /// <param name="singular"></param> /// <param name="plural"></param> AddWord(singular, plural) { if (this._userDictionary.ExistsInSecond(plural)) { throw new Error(`The plural value '${plural}' already exists in the user-defined dictionary.`); } else if (this._userDictionary.ExistsInFirst(singular)) { throw new Error(`The singular value '${singular}' already exists in the user-defined dictionary.`); } else { this._userDictionary.AddValue(singular, plural); } } } exports.EnglishPluralizationService = EnglishPluralizationService; //# sourceMappingURL=pluralization.js.map