UNPKG

@azure-tools/codegen

Version:
1,044 lines 40 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EnglishPluralizationService = void 0; const text_manipulation_1 = require("./text-manipulation"); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ /* * 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", "https", "sas", "statuses", "as", "statistics", "alias", "dns", "ms", "os", "vmss", "acls", "rights", "credentials", "ddos", "media", "gbps", "kbps", "mbps", "bps", "fips", ]; 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", 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", response: "responses", phrase: "phrases", }; 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", status: "statuses", }; this.wordsEndingWithInxAnxYnxDictionary = { sphinx: "sphinxes", larynx: "larynges", lynx: "lynxes", pharynx: "pharynxes", phalanx: "phalanxes", }; // eslint-disable-next-line prefer-spread 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) { if (!word) { return word; } // split it up. const de = (0, text_manipulation_1.deconstruct)(word); // singularize the last word only de[de.length - 1] = this.capitalize(de[de.length - 1], (w) => this.internalSingularize(w)); // return the pascal cased whole thing. return (0, text_manipulation_1.pascalCase)(de); } 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.slice(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.slice(0, lastSpaceIndex + 1), suffixWord: word.slice(lastSpaceIndex + 1), }; // } isCapitalized(word) { if (word === "") { return false; } return word.charAt(0) == word.charAt(0).toUpperCase(); } 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