UNPKG

nhb-toolbox

Version:

A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.

157 lines (156 loc) 5.57 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.pluralizer = exports.Pluralizer = void 0; const primitives_1 = require("../guards/primitives"); const utilities_1 = require("../number/utilities"); const rules_1 = require("./rules"); class Pluralizer { #pluralRules = []; #singularRules = []; #uncountables = new Set(); #irregularSingles = {}; #irregularPlurals = {}; constructor() { this.#loadRules(); } #loadRules() { rules_1.irregularRules.forEach(([single, plural]) => { this.addIrregular(single, plural); }); rules_1.pluralRules.forEach(([rule, replacement]) => { this.addPluralRule(rule, replacement); }); rules_1.singularRules.forEach(([rule, replacement]) => { this.addSingularRule(rule, replacement); }); rules_1.uncountables.forEach((word) => { this.addUncountable(word); }); } #restoreCase(original, transformed) { original = original?.trim(); if (original === transformed) return transformed; if (original === original.toLowerCase()) { return transformed.toLowerCase(); } if (original === original.toUpperCase()) { return transformed.toUpperCase(); } if (original[0] === original[0].toUpperCase() && original.slice(1) === original.slice(1).toLowerCase()) { return transformed.charAt(0).toUpperCase() + transformed.slice(1).toLowerCase(); } let result = ''; for (let i = 0; i < transformed.length; i++) { const origChar = original[i]; if (origChar && origChar === origChar.toUpperCase() && origChar !== origChar.toLowerCase()) { result += transformed[i].toUpperCase(); } else { result += transformed[i].toLowerCase(); } } return result; } #applyRules(word, rules) { if (!(0, primitives_1.isNonEmptyString)(word)) return ''; if (this.#isUncountable(word)) { return word; } for (let i = rules.length - 1; i >= 0; i--) { const [rule, replacement] = rules[i]; if (rule.test(word)) { return word.replace(rule, replacement); } } return word; } #isUncountable(word) { for (const entry of this.#uncountables) { if ((0, primitives_1.isString)(entry)) { if (entry.toLowerCase() === word) return true; } else { if (entry?.test(word)) return true; } } return false; } addPluralRule(rule, replacement) { this.#pluralRules.push([rule, replacement]); } addSingularRule(rule, replacement) { this.#singularRules.push([rule, replacement]); } addUncountable(word) { this.#uncountables.add((0, primitives_1.isString)(word) ? word?.toLowerCase() : word); } addIrregular(single, plural) { const singleLower = single?.toLowerCase(); const pluralLower = plural?.toLowerCase(); this.#irregularSingles[singleLower] = pluralLower; this.#irregularPlurals[pluralLower] = singleLower; } pluralize(word, options = {}) { const count = (0, utilities_1.normalizeNumber)(options?.count); if (!(0, primitives_1.isUndefined)(count)) { const pluralized = count === 1 ? this.toSingular(word) : this.toPlural(word); return options?.inclusive ? `${count} ${pluralized}` : pluralized; } return this.toPlural(word); } toPlural(word) { if (!(0, primitives_1.isNonEmptyString)(word)) return ''; const lower = word?.trim()?.toLowerCase(); if (this.#isUncountable(lower)) return word; if (this.#irregularSingles[lower]) { return this.#restoreCase(word, this.#irregularSingles[lower]); } return this.#restoreCase(word, this.#applyRules(lower, this.#pluralRules)); } toSingular(word) { if (!(0, primitives_1.isNonEmptyString)(word)) return ''; const lower = word?.trim()?.toLowerCase(); if (this.#isUncountable(lower)) return word; if (this.#irregularPlurals[lower]) { return this.#restoreCase(word, this.#irregularPlurals[lower]); } return this.#restoreCase(word, this.#applyRules(lower, this.#singularRules)); } isPlural(word) { if (!(0, primitives_1.isNonEmptyString)(word)) return false; const lower = word?.trim()?.toLowerCase(); if (this.#isUncountable(lower)) return true; if (this.#irregularPlurals[lower]) return true; if (this.#irregularSingles[lower]) return false; return this.toSingular(lower) !== lower; } isSingular(word) { if (!(0, primitives_1.isNonEmptyString)(word)) return false; const lower = word?.trim()?.toLowerCase(); if (this.#isUncountable(lower)) return true; if (this.#irregularSingles[lower]) return true; if (this.#irregularPlurals[lower]) return false; return this.toSingular(lower) === lower; } } exports.Pluralizer = Pluralizer; exports.pluralizer = new Pluralizer();