From 064b048c835c589af374829a8374e7fd79901ff0 Mon Sep 17 00:00:00 2001 From: upstream Date: Wed, 23 Sep 2026 12:36:14 +0200 Subject: [PATCH] Upstream spencermountain/compromise state of the touched files before c7e26e9613 --- src/3-three/nouns/api/toSingular.js | 18 ++ tests/three/nouns/toSingular.test.js | 259 +++++++++++++++++++++++++++ 2 files changed, 277 insertions(+) create mode 100644 src/3-three/nouns/api/toSingular.js create mode 100644 tests/three/nouns/toSingular.test.js diff --git a/src/3-three/nouns/api/toSingular.js b/src/3-three/nouns/api/toSingular.js new file mode 100644 index 0000000..8dcd9d2 --- /dev/null +++ b/src/3-three/nouns/api/toSingular.js @@ -0,0 +1,18 @@ +const keep = { tags: true } + +const nounToSingular = function (m, parsed) { + // already singular? + if (parsed.isPlural === false) { + return m + } + const { methods, model } = m.world + const { toSingular } = methods.two.transform.noun + // inflect the root noun + const str = parsed.root.text('normal') + const single = toSingular(str, model) + m.replace(parsed.root, single, keep).tag('Singular', 'toPlural') + // should we change the determiner/article? + // m.debug() + return m +} +export default nounToSingular diff --git a/tests/three/nouns/toSingular.test.js b/tests/three/nouns/toSingular.test.js new file mode 100644 index 0000000..c61259b --- /dev/null +++ b/tests/three/nouns/toSingular.test.js @@ -0,0 +1,259 @@ +import test from 'tape' +import nlp from '../_lib.js' +const here = '[three/noun-toSingular] ' + +test('toSingular:', function (t) { + const arr = [ + // ["Joneses", "Jones"], + + ['agents', 'agent'], + ['aircraft', 'aircraft'], + ['airports', 'airport'], + ['analyses', 'analysis'], + ['anchors', 'anchor'], + ['anchovies', 'anchovy'], + ['apples', 'apple'], + ['apricots', 'apricot'], + ['bags', 'bag'], + ['balls', 'ball'], + ['bananas', 'banana'], + ['barracks', 'barracks'], + ['bases', 'base'], + ['bass', 'bass'], + ['bats', 'bat'], + ['bears', 'bear'], + ['beds', 'bed'], + ['bells', 'bell'], + ['bicycles', 'bicycle'], + ['bison', 'bison'], + ['blankets', 'blanket'], + ['blocks', 'block'], + ['boats', 'boat'], + ['bonuses', 'bonus'], + ['books', 'book'], + ['bottles', 'bottle'], + ['bricks', 'brick'], + ['brooms', 'broom'], + ['bubbles', 'bubble'], + ['bunnies', 'bunny'], + ['buses', 'bus'], + ['butterflies', 'butterfly'], + ['buttons', 'button'], + ['cacti', 'cactus'], + ['cakes', 'cake'], + ['calves', 'calf'], + ['campuses', 'campus'], + ['candles', 'candle'], + ['capes', 'cape'], + ['carrots', 'carrot'], + ['cars', 'car'], + ['cases', 'case'], + ['cats', 'cat'], + ['causes', 'cause'], + ['chairs', 'chair'], + ['cheese', 'cheese'], + ['cheetahs', 'cheetah'], + ['chickens', 'chicken'], + ['children', 'child'], + ['clauses', 'clause'], + ['clocks', 'clock'], + ['clouds', 'cloud'], + ['cookies', 'cookie'], + ['cords', 'cord'], + ['cowboys', 'cowboy'], + ['cows', 'cow'], + ['crabs', 'crab'], + ['crayons', 'crayon'], + ['crises', 'crisis'], + ['cupcakes', 'cupcake'], + ['decreases', 'decrease'], + ['deer', 'deer'], + ['desks', 'desk'], + ['dinosaurs', 'dinosaur'], + ['diseases', 'disease'], + ['dogs', 'dog'], + ['donuts', 'donut'], + ['doorways', 'doorway'], + ['ducks', 'duck'], + ['eagles', 'eagle'], + ['embryos', 'embryo'], + ['eyebrows', 'eyebrow'], + ['fans', 'fan'], + ['fences', 'fence'], + ['fishes', 'fish'], + ['fountains', 'fountain'], + ['fowl', 'fowl'], + ['foxes', 'fox'], + ['frames', 'frame'], + ['frescos', 'fresco'], + ['fungi', 'fungus'], + ['geese', 'goose'], + ['ghettos', 'ghetto'], + ['glasses', 'glass'], + ['gloves', 'glove'], + ['grapes', 'grape'], + ['groceries', 'grocery'], + ['guns', 'gun'], + ['halos', 'halo'], + ['hammers', 'hammer'], + ['hens', 'hen'], + ['hippos', 'hippo'], + ['his excuses', 'his excuse'], + ['hooves', 'hoof'], + ['houses', 'house'], + ['increases', 'increase'], + ['jackets', 'jacket'], + ['kangaroos', 'kangaroo'], + ['keys', 'key'], + ['kilos', 'kilo'], + ['kimonos', 'kimono'], + ['kites', 'kite'], + ['kittens', 'kitten'], + ['knives', 'knife'], + ['laptops', 'laptop'], + ['lizards', 'lizard'], + ['loaves', 'loaf'], + ['locks', 'lock'], + ['logos', 'logo'], + ['lollipops', 'lollipop'], + ['mangos', 'mango'], + ['mannequins', 'mannequin'], + ['masks', 'mask'], + ['mementos', 'memento'], + ['memos', 'memo'], + ['men', 'man'], + ['mice', 'mouse'], + ['mirrors', 'mirror'], + ['monitors', 'monitor'], + ['monkeys', 'monkey'], + ['mottos', 'motto'], + ['mountains', 'mountain'], + ['mugs', 'mug'], + ['music', 'music'], + ['needles', 'needle'], + ['nerds', 'nerd'], + ['nuclei', 'nucleus'], + ['oafs', 'oaf'], + ['oceans', 'ocean'], + ['olives', 'olive'], + ['oranges', 'orange'], + ['owls', 'owl'], + ['paintings', 'painting'], + ['parentheses', 'parenthesis'], + ['pearls', 'pearl'], + ['penguins', 'penguin'], + ['pens', 'pen'], + ['people', 'person'], + ['phenomena', 'phenomenon'], + ['photos', 'photo'], + ['phrases', 'phrase'], + ['pianos', 'piano'], + ['pies', 'pie'], + ['pigs', 'pig'], + ['pillars', 'pillar'], + ['pillows', 'pillow'], + ['pimentos', 'pimento'], + ['plants', 'plant'], + ['plates', 'plate'], + ['pleases', 'please'], + ['ponchos', 'poncho'], + ['posters', 'poster'], + ['prognoses', 'prognosis'], + ['pros', 'pro'], + ['puzzles', 'puzzle'], + ['quintuplets', 'quintuplet'], + ['rabbits', 'rabbit'], + ['reeds', 'reed'], + ['releases', 'release'], + ['rivers', 'river'], + ['robots', 'robot'], + ['rocks', 'rock'], + ['roofs', 'roof'], + ['roses', 'rose'], + ['scarves', 'scarf'], + ['seeds', 'seed'], + ['sharks', 'shark'], + ['sheep', 'sheep'], + ['shoes', 'shoe'], + ['snails', 'snail'], + ['sofas', 'sofa'], + ['sombreros', 'sombrero'], + ['spiders', 'spider'], + ['spoons', 'spoon'], + ['spouses', 'spouse'], + ['stairs', 'stair'], + ['sticks', 'stick'], + ['surpluses', 'surplus'], + ['swords', 'sword'], + ['syllabi', 'syllabus'], + ['synopses', 'synopsis'], + ['tables', 'table'], + ['tacos', 'taco'], + ['teapots', 'teapot'], + ['teeth', 'tooth'], + ['tents', 'tent'], + ['the focuses', 'the focus'], + ['the geniouses', 'the genious'], + ['theses', 'thesis'], + ['tigers', 'tiger'], + ['tomatoes', 'tomato'], + ['tornados', 'tornado'], + ['torsos', 'torso'], + ['tosses', 'toss'], + ['toys', 'toy'], + ['trees', 'tree'], + ['tuxedos', 'tuxedo'], + ['uses', 'use'], + ['viruses', 'virus'], + ['walruses', 'walrus'], + ['whales', 'whale'], + ['wishes', 'wish'], + ['wives', 'wife'], + ['wolves', 'wolf'], + ['women', 'woman'], + ['worrywarts', 'worrywart'], + ['xylophones', 'xylophone'], + ['zebras', 'zebra'], + [`ireland potatoes`, 'ireland potato'], + [`irish potatoes`, 'irish potato'], + [`john's potatoes`, `john's potato`], + // ['Isley Brothers members', 'Isley Brothers member'], + // ['mayors of chicago', 'mayor of chicago'], + //test that sungular.singularize()==singular.. + ] + arr.forEach(function (a) { + let doc = nlp(a[0]) + doc.tag('Noun').compute('chunks') + let str = doc.nouns().toSingular().text() + t.equal(str, a[1], here + '[toSingular] ' + a[0]) + + doc = nlp(a[1]) + doc.tag('Noun').compute('chunks') + str = doc.nouns().toPlural().text() + t.equal(str, a[0], here + '[toPlural] ' + a[0]) + + // doc = nlp(a[0]) + // doc.tag('Noun').compute('chunks') + // str = doc.nouns().toPlural().text() + // t.equal(str, a[0], here + '[stay-plural] ' + a[0]) + + }) + t.end() +}) + +test('toSingular - longer:', function (t) { + const arr = [ + [`my fingers looked green afterwards`, `my finger looked green afterwards`], + [`other person`, 'other person'], + [`other people`, 'other person'], + // [`other people's kids`, 'other person\'s kid'], + // [`the women's room`, 'the women\'s room'], + ] + arr.forEach(function (a) { + const doc = nlp(a[0]) + doc.compute('chunks') + doc.nouns().toSingular() + t.equal(doc.text(), a[1], here + '[longer] ' + a[0]) + }) + t.end() +}) \ No newline at end of file