From f1ed06f12ecd6932c4775130ff6632748a6cd5b7 Mon Sep 17 00:00:00 2001 From: Rex Lorenzo Date: Tue, 12 May 2026 18:57:49 -0700 Subject: [PATCH] fix: pluralize nucleus/nuclei correctly Adds anchored regex rules so: - pluralize('nucleus') === 'nuclei' - pluralize('nuclei') === 'nuclei' - pluralize('nucleuses') === 'nucleuses' - singularize('nuclei') === 'nucleus' - singularize('nucleuses') === 'nucleus' - singularize('nucleus') === 'nucleus' Patterns are anchored to the `nucle` stem so they cannot match other -us/-i words. Fixes #71 --- src/inflection.ts | 9 +++++++++ test/inflection.test.ts | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/src/inflection.ts b/src/inflection.ts index 43bb6ca..7ae0d0f 100644 --- a/src/inflection.ts +++ b/src/inflection.ts @@ -376,6 +376,8 @@ const regex = { whereases: new RegExp('^(whereas)es$', 'gi'), criteria: new RegExp('^(criteri)a$', 'gi'), genera: new RegExp('^genera$', 'gi'), + nuclei: new RegExp('^(nucle)i$', 'gi'), + nucleuses: new RegExp('^(nucle)uses$', 'gi'), ss: new RegExp('ss$', 'gi'), s: new RegExp('s$', 'gi'), }, @@ -409,6 +411,7 @@ const regex = { whereas: new RegExp('^(whereas)$', 'gi'), criterion: new RegExp('^(criteri)on$', 'gi'), genus: new RegExp('^genus$', 'gi'), + nucleus: new RegExp('^(nucle)us$', 'gi'), s: new RegExp('s$', 'gi'), common: new RegExp('$', 'gi'), }, @@ -448,6 +451,8 @@ const pluralRules: [RegExp, string?][] = [ [regex.plural.whereases], [regex.plural.criteria], [regex.plural.genera], + [regex.plural.nuclei], + [regex.plural.nucleuses], // original rule [regex.singular.man, '$1en'], @@ -478,6 +483,7 @@ const pluralRules: [RegExp, string?][] = [ [regex.singular.whereas, '$1es'], [regex.singular.criterion, '$1a'], [regex.singular.genus, 'genera'], + [regex.singular.nucleus, '$1i'], [regex.singular.s, 's'], [regex.singular.common, 's'], @@ -515,6 +521,7 @@ const singularRules: [RegExp, string?][] = [ [regex.singular.whereas], [regex.singular.criterion], [regex.singular.genus], + [regex.singular.nucleus], // original rule [regex.plural.men, '$1an'], @@ -524,6 +531,8 @@ const singularRules: [RegExp, string?][] = [ [regex.plural.drives, '$1'], [regex.plural.genera, 'genus'], [regex.plural.criteria, '$1on'], + [regex.plural.nuclei, '$1us'], + [regex.plural.nucleuses, '$1us'], [regex.plural.tia, '$1um'], [regex.plural.analyses, '$1$2sis'], [regex.plural.hives, '$1ve'], diff --git a/test/inflection.test.ts b/test/inflection.test.ts index a6b30d3..b8f2b10 100644 --- a/test/inflection.test.ts +++ b/test/inflection.test.ts @@ -51,6 +51,9 @@ describe('test .pluralize', function () { expect(inflection.pluralize('aws')).toEqual('aws'); expect(inflection.pluralize('media')).toEqual('media'); expect(inflection.pluralize('police')).toEqual('police'); + expect(inflection.pluralize('nucleus')).toEqual('nuclei'); + expect(inflection.pluralize('nuclei')).toEqual('nuclei'); + expect(inflection.pluralize('nucleuses')).toEqual('nucleuses'); }); }); @@ -105,6 +108,9 @@ describe('test .singularize', function () { expect(inflection.singularize('aws')).toEqual('aws'); expect(inflection.singularize('media')).toEqual('media'); expect(inflection.singularize('police')).toEqual('police'); + expect(inflection.singularize('nuclei')).toEqual('nucleus'); + expect(inflection.singularize('nucleuses')).toEqual('nucleus'); + expect(inflection.singularize('nucleus')).toEqual('nucleus'); }); });