{"version":3,"sources":["../../src/en/article.ts","../../src/en/plural.ts","../../src/en/index.ts"],"names":["splitPhrase","splitTrailingPunctuation","isCapitalized","capitalize","joinPhrase","registerLanguage"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * English indefinite-article selection (a/an) by *pronunciation*, not\n * spelling: \"an hour\", \"a university\", \"an MTA card\", \"an 8\".\n */\n\n/**\n * Vowel-letter words pronounced with an initial consonant sound (/j/ or /w/).\n * Prefix-matched, lowercase.\n */\nconst A_PREFIXES = [\n  \"eu\", // euro, europe, eulogy, euphemism, eureka…\n  \"ewe\",\n  \"one\",\n  \"once\",\n  \"ouija\",\n  \"ubiq\", // ubiquitous\n  \"unanim\", // unanimous\n  \"use\",\n  \"user\",\n  \"usu\", // usual, usurper\n  \"utensil\",\n  \"uterus\",\n  \"utili\", // utility, utilize\n  \"utopia\",\n  \"uran\", // uranium, uranus\n  \"uv\", // uvula\n] as const;\n\n/**\n * `uni…` is /juː/ (university, unicorn) EXCEPT when the prefix is the\n * negative `un-` + i… (unimportant, uninvited): those start with a vowel\n * sound.\n */\nconst UNI_NEGATIVE = /^un(im|in)/;\n\n/** Consonant-letter words with a silent initial `h`. Prefix-matched. */\nconst AN_PREFIXES = [\n  \"heir\", // heir, heiress, heirloom\n  \"honest\",\n  \"honor\",\n  \"honour\",\n  \"hour\", // hour, hourly, hourglass\n] as const;\n\n/**\n * Letters whose English names start with a vowel sound — an F (\"ef\"),\n * an M (\"em\"), an X (\"ex\") — for acronyms and single letters.\n */\nconst VOWEL_NAMED_LETTERS = new Set([...\"AEFHILMNORSX\"]);\n\nconst VOWELS = new Set([...\"aeiou\"]);\n\nfunction isAcronym(word: string): boolean {\n  return /^[A-Z][A-Z0-9]+$/.test(word) || /^[A-Z]$/.test(word);\n}\n\n/**\n * Spoken English for a leading number: 8… → \"eight…\" (an); 11 → \"eleven\",\n * 18 → \"eighteen\" (an); everything else starts with a consonant sound.\n */\nfunction digitTakesAn(word: string): boolean {\n  const digits = /^\\d+/.exec(word)?.[0] ?? \"\";\n  return digits.startsWith(\"8\") || digits === \"11\" || digits === \"18\";\n}\n\n/**\n * Pick `\"a\"` or `\"an\"` for the word that follows the article.\n *\n * Handles regular words, silent-h words, /juː/-initial vowel spellings,\n * acronyms/single letters (by letter name) and leading digits (by spoken\n * form).\n */\nexport function indefiniteArticle(nextWord: string): \"a\" | \"an\" {\n  if (nextWord.length === 0) return \"a\";\n  if (/^\\d/.test(nextWord)) return digitTakesAn(nextWord) ? \"an\" : \"a\";\n  if (isAcronym(nextWord)) {\n    return VOWEL_NAMED_LETTERS.has(nextWord[0] as string) ? \"an\" : \"a\";\n  }\n  const lower = nextWord.toLowerCase();\n  if (AN_PREFIXES.some((p) => lower.startsWith(p))) return \"an\";\n  if (lower.startsWith(\"uni\")) return UNI_NEGATIVE.test(lower) ? \"an\" : \"a\";\n  if (A_PREFIXES.some((p) => lower.startsWith(p))) return \"a\";\n  return VOWELS.has(lower[0] as string) ? \"an\" : \"a\";\n}\n","/** English noun pluralization: regular rules plus the core irregulars. */\n\nconst IRREGULAR: Record<string, string> = {\n  child: \"children\",\n  foot: \"feet\",\n  goose: \"geese\",\n  louse: \"lice\",\n  man: \"men\",\n  mouse: \"mice\",\n  ox: \"oxen\",\n  person: \"people\",\n  tooth: \"teeth\",\n  woman: \"women\",\n  die: \"dice\",\n};\n\n/** Nouns whose plural equals the singular. */\nconst INVARIANT = new Set([\n  \"aircraft\",\n  \"deer\",\n  \"fish\",\n  \"moose\",\n  \"series\",\n  \"sheep\",\n  \"species\",\n  \"swine\",\n]);\n\n/** `-f`/`-fe` nouns that take `-ves`. */\nconst F_TO_VES = new Set([\n  \"calf\",\n  \"elf\",\n  \"half\",\n  \"knife\",\n  \"leaf\",\n  \"life\",\n  \"loaf\",\n  \"self\",\n  \"shelf\",\n  \"thief\",\n  \"wife\",\n  \"wolf\",\n]);\n\n/** `-o` nouns that take `-oes` (the rest just take `-s`). */\nconst O_TO_OES = new Set([\"echo\", \"hero\", \"potato\", \"tomato\", \"torpedo\", \"veto\"]);\n\n/**\n * Pluralize an English noun. Preserves initial capitalization; ALL-CAPS\n * acronyms take a plain `s` (\"APIs\" is left to the caller's style — we emit\n * \"APIS\"-avoiding lowercase `s`).\n */\nexport function pluralize(word: string): string {\n  if (/^[A-Z][A-Z0-9]+$/.test(word)) return `${word}s`; // acronym: PDF → PDFs\n  const lower = word.toLowerCase();\n  const capitalized = word[0] !== undefined && word[0] !== lower[0];\n  const restore = (plural: string): string =>\n    capitalized ? (plural[0] as string).toUpperCase() + plural.slice(1) : plural;\n\n  if (INVARIANT.has(lower)) return word;\n  const irregular = IRREGULAR[lower];\n  if (irregular) return restore(irregular);\n  if (F_TO_VES.has(lower)) {\n    return restore(`${lower.replace(/fe?$/, \"\")}ves`);\n  }\n  if (/[^aeiou]y$/.test(lower)) return restore(`${lower.slice(0, -1)}ies`);\n  if (/(s|x|z|ch|sh)$/.test(lower)) return restore(`${lower}es`);\n  if (lower.endsWith(\"o\") && O_TO_OES.has(lower)) return restore(`${lower}es`);\n  return `${word}s`;\n}\n","import type { GrammaticalFeatures } from \"../core/features.js\";\nimport type { InflectionContext, InflectionResult, LanguagePack } from \"../core/pack.js\";\nimport {\n  capitalize,\n  isCapitalized,\n  joinPhrase,\n  splitPhrase,\n  splitTrailingPunctuation,\n} from \"../core/phrase.js\";\nimport { registerLanguage } from \"../core/registry.js\";\nimport { indefiniteArticle } from \"./article.js\";\nimport { pluralize } from \"./plural.js\";\n\n/**\n * English language pack: a/an agreement (sound-based, incl. acronyms and\n * digits) and noun pluralization.\n *\n * `import \"i18n-inflect/en\"` registers it as a side effect.\n */\n\nconst EXISTING_ARTICLES = new Set([\"a\", \"an\", \"the\"]);\n\nfunction inflectPhrase(\n  phrase: string,\n  features: GrammaticalFeatures,\n  _ctx: InflectionContext,\n): InflectionResult {\n  const split = splitPhrase(phrase);\n  if (split.words.length === 0) return { text: phrase, confidence: \"high\" };\n\n  // 1. Head inflection: pluralize the last word when requested.\n  if (features.number === \"plural\") {\n    const headIdx = split.wordIndexes[split.words.length - 1] as number;\n    const [core, punct] = splitTrailingPunctuation(split.parts[headIdx] as string);\n    split.parts[headIdx] = pluralize(core) + punct;\n  }\n\n  // 2. Article agreement. An explicit `article:` feature may prepend or\n  //    remove one; an a/an already present in the text is always re-agreed\n  //    against the word that follows it (post-interpolation).\n  const firstIdx = split.wordIndexes[0] as number;\n  const firstWord = split.parts[firstIdx] as string;\n  const firstLower = firstWord.toLowerCase();\n  const hasArticle = EXISTING_ARTICLES.has(firstLower);\n  const plural = features.number === \"plural\";\n\n  const wordAfter = (index: number): string => {\n    const idx = split.wordIndexes[index];\n    return idx === undefined ? \"\" : (split.parts[idx] as string);\n  };\n\n  if (features.article === \"none\" && hasArticle) {\n    // Remove the article and its following whitespace.\n    split.parts[firstIdx] = \"\";\n    if (split.wordIndexes.length > 1) split.parts[firstIdx + 1] = \"\";\n  } else if (hasArticle) {\n    if (firstLower !== \"the\") {\n      const next = wordAfter(1);\n      const article = plural ? \"\" : indefiniteArticle(next);\n      if (article === \"\") {\n        // \"a card\" + plural → \"cards\": indefinite article has no plural.\n        split.parts[firstIdx] = \"\";\n        if (split.wordIndexes.length > 1) split.parts[firstIdx + 1] = \"\";\n      } else {\n        split.parts[firstIdx] = isCapitalized(firstWord) ? capitalize(article) : article;\n      }\n    }\n  } else if (features.article === \"definite\") {\n    split.parts[firstIdx] = `the ${firstWord}`;\n  } else if (features.article === \"indefinite\" && !plural) {\n    split.parts[firstIdx] = `${indefiniteArticle(firstWord)} ${firstWord}`;\n  }\n\n  return { text: joinPhrase(split), confidence: \"high\" };\n}\n\n/** The English language pack. */\nexport const en: LanguagePack = {\n  locale: \"en\",\n  inflectPhrase,\n};\n\nregisterLanguage(en);\n"]}