{"version":3,"sources":["../src/core/cache.ts","../src/core/features.ts","../src/core/warnings.ts","../src/core/engine.ts","../src/template/parser.ts","../src/template/render.ts","../src/index.ts"],"names":["resolveLocale","getLanguage","getFallback"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * A minimal least-recently-used cache built on `Map`'s insertion order.\n *\n * Used for two hot paths: memoized template parsing and the shared\n * inflection \"oracle\" cache that lets asynchronous neural answers upgrade\n * later synchronous calls.\n */\nexport class LruCache<K, V> {\n  private readonly map = new Map<K, V>();\n\n  constructor(private readonly capacity: number) {\n    if (capacity < 1) throw new RangeError(\"LruCache capacity must be >= 1\");\n  }\n\n  /** Number of entries currently stored. */\n  get size(): number {\n    return this.map.size;\n  }\n\n  /** Read a value and refresh its recency. */\n  get(key: K): V | undefined {\n    const value = this.map.get(key);\n    if (value === undefined && !this.map.has(key)) return undefined;\n    // Re-insert to move the key to the \"most recently used\" end.\n    this.map.delete(key);\n    this.map.set(key, value as V);\n    return value;\n  }\n\n  /** Store a value, evicting the least recently used entry when full. */\n  set(key: K, value: V): void {\n    if (this.map.has(key)) this.map.delete(key);\n    else if (this.map.size >= this.capacity) {\n      const oldest = this.map.keys().next();\n      if (!oldest.done) this.map.delete(oldest.value);\n    }\n    this.map.set(key, value);\n  }\n\n  has(key: K): boolean {\n    return this.map.has(key);\n  }\n\n  clear(): void {\n    this.map.clear();\n  }\n}\n","/**\n * The grammatical feature model.\n *\n * A small, closed vocabulary shared by every language pack, modeled after\n * Apple Foundation's `Morphology`. Languages consume the features they\n * understand and ignore the rest (with a warning, so typos surface in dev).\n */\n\n/** Part-of-speech hint for the phrase head. */\nexport type PartOfSpeech =\n  | \"noun\"\n  | \"properNoun\"\n  | \"adjective\"\n  | \"determiner\"\n  | \"numeral\"\n  | \"pronoun\"\n  | \"particle\";\n\n/** Grammatical number of the phrase head. */\nexport type GrammaticalNumber = \"singular\" | \"plural\";\n\n/** Grammatical gender (Indo-European three-way system plus \"common\"). */\nexport type GrammaticalGender = \"masculine\" | \"feminine\" | \"neuter\" | \"common\";\n\n/**\n * Grammatical case.\n *\n * The union covers the pan-European core, the full Hungarian oblique set and\n * the Korean particle semantics (topic/comitative are modeled as cases so a\n * single `case:` template key works across languages).\n */\nexport type GrammaticalCase =\n  // pan-European core\n  | \"nominative\"\n  | \"accusative\"\n  | \"dative\"\n  | \"genitive\"\n  | \"instrumental\"\n  | \"vocative\"\n  // Hungarian interior locatives: -ban/-ben, -ból/-ből, -ba/-be\n  | \"inessive\"\n  | \"elative\"\n  | \"illative\"\n  // Hungarian surface locatives: -on/-en/-ön, -ról/-ről, -ra/-re\n  | \"superessive\"\n  | \"delative\"\n  | \"sublative\"\n  // Hungarian proximal locatives: -nál/-nél, -tól/-től, -hoz/-hez/-höz\n  | \"adessive\"\n  | \"ablative\"\n  | \"allative\"\n  // Hungarian: -vá/-vé, -ért, -ig\n  | \"translative\"\n  | \"causalFinal\"\n  | \"terminative\"\n  // Hungarian: -ként, \"in the capacity of\"\n  | \"essiveFormal\"\n  // Korean particle semantics\n  | \"topic\"\n  | \"comitative\";\n\n/** Definiteness of the noun phrase (drives article agreement). */\nexport type Definiteness = \"definite\" | \"indefinite\" | \"none\";\n\n/** Grammatical person. */\nexport type GrammaticalPerson = \"first\" | \"second\" | \"third\";\n\n/** Explicit request to prepend (or normalize) an article on the phrase. */\nexport type ArticleRequest = \"definite\" | \"indefinite\" | \"none\";\n\n/**\n * Word formation rather than inflection: make a different word out of this\n * one. `\"relational\"` is the adjective meaning \"belonging to / coming from\"\n * — Hungarian Budapest → budapesti, German Wien → Wiener.\n */\nexport type Derivation = \"relational\";\n\n/**\n * A bundle of grammatical features to apply to a phrase.\n *\n * Every field is optional; a pack applies what it understands. This is the\n * programmatic mirror of the `^[...](key: value)` template annotations.\n */\nexport interface GrammaticalFeatures {\n  /** Part of speech of the phrase head (default: noun). */\n  partOfSpeech?: PartOfSpeech;\n  /** Target grammatical number. */\n  number?: GrammaticalNumber;\n  /** Target grammatical case (or particle role for Korean). */\n  case?: GrammaticalCase;\n  /** Grammatical gender of the head — required for correct German articles. */\n  gender?: GrammaticalGender;\n  /** Definiteness used when agreeing an article already present in the text. */\n  definiteness?: Definiteness;\n  /** Grammatical person (reserved for future verb agreement). */\n  person?: GrammaticalPerson;\n  /** Request to prepend/normalize an article on the phrase. */\n  article?: ArticleRequest;\n  /** Derive a different word before applying any of the above. */\n  derivation?: Derivation;\n  /**\n   * Mark the noun as possessed by someone: Hungarian `ház` → `házam` (my\n   * house), `házunk` (our house). `number` keeps its usual meaning — how\n   * many things are possessed — so `{ possessor: \"first\", number: \"plural\" }`\n   * is \"my houses\".\n   */\n  possessor?: GrammaticalPerson;\n  /** Whether the possessor is plural: our house rather than my house. */\n  possessorNumber?: GrammaticalNumber;\n}\n\nconst PART_OF_SPEECH: readonly PartOfSpeech[] = [\n  \"noun\",\n  \"properNoun\",\n  \"adjective\",\n  \"determiner\",\n  \"numeral\",\n  \"pronoun\",\n  \"particle\",\n];\nconst NUMBERS: readonly GrammaticalNumber[] = [\"singular\", \"plural\"];\nconst GENDERS: readonly GrammaticalGender[] = [\"masculine\", \"feminine\", \"neuter\", \"common\"];\nconst CASES: readonly GrammaticalCase[] = [\n  \"nominative\",\n  \"accusative\",\n  \"dative\",\n  \"genitive\",\n  \"instrumental\",\n  \"vocative\",\n  \"inessive\",\n  \"elative\",\n  \"illative\",\n  \"superessive\",\n  \"delative\",\n  \"sublative\",\n  \"adessive\",\n  \"ablative\",\n  \"allative\",\n  \"translative\",\n  \"causalFinal\",\n  \"terminative\",\n  \"essiveFormal\",\n  \"topic\",\n  \"comitative\",\n];\nconst DEFINITENESS: readonly Definiteness[] = [\"definite\", \"indefinite\", \"none\"];\nconst PERSONS: readonly GrammaticalPerson[] = [\"first\", \"second\", \"third\"];\nconst ARTICLES: readonly ArticleRequest[] = [\"definite\", \"indefinite\", \"none\"];\nconst DERIVATIONS: readonly Derivation[] = [\"relational\"];\n\nfunction pick<T extends string>(allowed: readonly T[], value: string): T | undefined {\n  return (allowed as readonly string[]).includes(value) ? (value as T) : undefined;\n}\n\n/** Callback used to surface ignored template feature keys/values. */\nexport type FeatureWarning = (\n  kind: \"unknown-feature-key\" | \"unknown-feature-value\",\n  detail: string,\n) => void;\n\n/**\n * Default mapping from raw template annotations (`case: instrumental`) to\n * {@link GrammaticalFeatures}. Language packs may refine it via\n * `LanguagePack.normalizeFeatures` (e.g. to accept locale-specific aliases).\n *\n * Unknown keys and values are ignored and reported through `warn` — a\n * malformed annotation must never break formatting.\n */\nexport function normalizeFeatures(\n  raw: Record<string, string>,\n  warn: FeatureWarning = () => {},\n): GrammaticalFeatures {\n  const out: GrammaticalFeatures = {};\n  for (const [rawKey, rawValue] of Object.entries(raw)) {\n    const key = rawKey.trim();\n    const value = rawValue.trim();\n    switch (key) {\n      case \"case\": {\n        const v = pick(CASES, value);\n        if (v) out.case = v;\n        else warn(\"unknown-feature-value\", `case: ${value}`);\n        break;\n      }\n      case \"number\": {\n        const v = pick(NUMBERS, value);\n        if (v) out.number = v;\n        else warn(\"unknown-feature-value\", `number: ${value}`);\n        break;\n      }\n      case \"gender\": {\n        const v = pick(GENDERS, value);\n        if (v) out.gender = v;\n        else warn(\"unknown-feature-value\", `gender: ${value}`);\n        break;\n      }\n      case \"definiteness\": {\n        const v = pick(DEFINITENESS, value);\n        if (v) out.definiteness = v;\n        else warn(\"unknown-feature-value\", `definiteness: ${value}`);\n        break;\n      }\n      case \"article\": {\n        const v = pick(ARTICLES, value);\n        if (v) out.article = v;\n        else warn(\"unknown-feature-value\", `article: ${value}`);\n        break;\n      }\n      case \"derivation\": {\n        const v = pick(DERIVATIONS, value);\n        if (v) out.derivation = v;\n        else warn(\"unknown-feature-value\", `derivation: ${value}`);\n        break;\n      }\n      case \"possessor\": {\n        const v = pick(PERSONS, value);\n        if (v) out.possessor = v;\n        else warn(\"unknown-feature-value\", `possessor: ${value}`);\n        break;\n      }\n      case \"possessorNumber\": {\n        const v = pick(NUMBERS, value);\n        if (v) out.possessorNumber = v;\n        else warn(\"unknown-feature-value\", `possessorNumber: ${value}`);\n        break;\n      }\n      case \"person\": {\n        const v = pick(PERSONS, value);\n        if (v) out.person = v;\n        else warn(\"unknown-feature-value\", `person: ${value}`);\n        break;\n      }\n      case \"pos\":\n      case \"partOfSpeech\": {\n        const v = pick(PART_OF_SPEECH, value);\n        if (v) out.partOfSpeech = v;\n        else warn(\"unknown-feature-value\", `${key}: ${value}`);\n        break;\n      }\n      case \"inflect\":\n        // Apple-compat: `^[...](inflect: true)` is accepted and reserved for\n        // the future automatic-agreement layer. It adds no explicit feature.\n        break;\n      default:\n        warn(\"unknown-feature-key\", key);\n    }\n  }\n  return out;\n}\n","/**\n * Warning channel.\n *\n * `inflect()`/`format()` never throw on bad input — they degrade gracefully\n * and report what they ignored through this hook, so problems surface in\n * development without breaking production rendering.\n */\n\n/** Machine-readable warning categories. */\nexport type WarningCode =\n  | \"unknown-locale\"\n  | \"unknown-feature-key\"\n  | \"unknown-feature-value\"\n  | \"missing-argument\"\n  | \"malformed-template\"\n  | \"missing-gender\"\n  | \"fallback-error\"\n  | \"fallback-rejected\"\n  | \"low-confidence\";\n\n/** A single reported warning. */\nexport interface InflectWarning {\n  code: WarningCode;\n  /** Resolved language subtag, when the warning is locale-specific. */\n  locale?: string;\n  /** Human-readable detail (offending key, span, argument name, …). */\n  detail: string;\n}\n\n/** Handler installed via {@link onWarning}. */\nexport type WarningHandler = (warning: InflectWarning) => void;\n\nlet handler: WarningHandler | undefined;\n\n/**\n * Install a global warning handler (pass `undefined` to remove).\n *\n * Typical development setup: `onWarning(w => console.warn(\"[i18n-inflect]\", w))`.\n * No handler is installed by default — production stays silent.\n */\nexport function onWarning(next: WarningHandler | undefined): void {\n  handler = next;\n}\n\n/** Report a warning to the installed handler (no-op without one). */\nexport function emitWarning(warning: InflectWarning): void {\n  handler?.(warning);\n}\n","import { LruCache } from \"./cache.js\";\nimport { type GrammaticalFeatures, normalizeFeatures } from \"./features.js\";\nimport type { FallbackRequest, InflectionContext, LanguagePack } from \"./pack.js\";\nimport { getFallback, getLanguage, resolveLocale } from \"./registry.js\";\nimport { emitWarning } from \"./warnings.js\";\n\n/**\n * The inflection engine: sync rule-based inflection plus the two-pass async\n * upgrade path.\n *\n * Design: packs are pure and synchronous. All answers a pack cannot derive\n * from rules go through `ctx.lookup`, which reads the shared oracle cache\n * below. `inflectAsync` runs the pack once, feeds the recorded misses to the\n * registered fallback, fills the cache, and re-runs the pack synchronously —\n * so after the first async resolution, plain sync `inflect`/`format` calls\n * return the corrected forms too.\n */\n\n/** Shared answers produced by fallbacks, keyed by locale/lemma/tag. */\nconst oracleCache = new LruCache<string, string>(2000);\n\nfunction oracleKey(locale: string, request: FallbackRequest): string {\n  return `${locale}\\0${request.lemma}\\0${request.tag}`;\n}\n\n/**\n * Seed the oracle cache directly (used by tests and by applications that\n * want to pre-store known answers, e.g. from a server response).\n */\nexport function seedOracle(locale: string, request: FallbackRequest, form: string): void {\n  oracleCache.set(oracleKey(resolveLocale(locale), request), form);\n}\n\n/** Clear the oracle cache (test isolation). */\nexport function clearOracle(): void {\n  oracleCache.clear();\n}\n\ninterface PackRun {\n  text: string;\n  confidence: \"high\" | \"low\";\n  misses: FallbackRequest[];\n}\n\nfunction runPack(pack: LanguagePack, phrase: string, features: GrammaticalFeatures): PackRun {\n  const misses: FallbackRequest[] = [];\n  const seen = new Set<string>();\n  const ctx: InflectionContext = {\n    locale: pack.locale,\n    lookup: (request) => oracleCache.get(oracleKey(pack.locale, request)),\n    requestFallback: (request) => {\n      const key = oracleKey(pack.locale, request);\n      if (!seen.has(key)) {\n        seen.add(key);\n        misses.push(request);\n      }\n    },\n    warn: (code, detail) => emitWarning({ code, locale: pack.locale, detail }),\n  };\n  const result = pack.inflectPhrase(phrase, features, ctx);\n  return { text: result.text, confidence: result.confidence, misses };\n}\n\n/**\n * How much longer than its lemma an inflected form may plausibly be. Real\n * suffix chains are short; a much longer answer means the model ran away.\n */\nconst MAX_SUFFIX_GROWTH = 12;\n\n/**\n * Why a fallback answer must not be cached, or `undefined` when it is\n * acceptable. Generic sanity checks live here; language-specific\n * plausibility is delegated to the pack's `acceptFallback`.\n */\nfunction rejectionReason(\n  pack: LanguagePack,\n  request: FallbackRequest,\n  answer: string,\n): string | undefined {\n  if (answer.length === 0) return \"empty\";\n  if (answer.length > request.lemma.length + MAX_SUFFIX_GROWTH) return \"implausibly long\";\n  if (pack.acceptFallback && !pack.acceptFallback(request, answer)) return \"rejected by pack\";\n  return undefined;\n}\n\nfunction packOrWarn(locale: string): LanguagePack | undefined {\n  const pack = getLanguage(locale);\n  if (!pack) emitWarning({ code: \"unknown-locale\", locale: resolveLocale(locale), detail: locale });\n  return pack;\n}\n\n/**\n * Inflect a phrase synchronously using rules, lexicon and any cached\n * fallback answers. Unknown locales return the phrase unchanged (with a\n * warning) — this function never throws on user input.\n *\n * @example\n * ```ts\n * import \"i18n-inflect/hu\";\n * inflect(\"hu\", \"kőr ász\", { case: \"instrumental\" }); // \"kőr ásszal\"\n * ```\n */\nexport function inflect(\n  locale: string,\n  phrase: string,\n  features: GrammaticalFeatures = {},\n): string {\n  const pack = packOrWarn(locale);\n  if (!pack) return phrase;\n  return runPack(pack, phrase, features).text;\n}\n\n/**\n * Like {@link inflect}, but may await the registered fallback (e.g. the\n * neural module) for words the rules were unsure about. Falls back to the\n * best synchronous answer when no fallback is registered or it fails.\n */\nexport async function inflectAsync(\n  locale: string,\n  phrase: string,\n  features: GrammaticalFeatures = {},\n): Promise<string> {\n  const pack = packOrWarn(locale);\n  if (!pack) return phrase;\n  const first = runPack(pack, phrase, features);\n  if (first.misses.length === 0) return first.text;\n  const fallback = getFallback(pack.locale);\n  if (!fallback) return first.text;\n  try {\n    const answers = await fallback.predict(first.misses);\n    first.misses.forEach((request, i) => {\n      const answer = answers[i];\n      if (typeof answer !== \"string\") return;\n      const rejection = rejectionReason(pack, request, answer);\n      if (rejection !== undefined) {\n        emitWarning({\n          code: \"fallback-rejected\",\n          locale: pack.locale,\n          detail: `${request.lemma} ${request.tag} → \"${answer}\" (${rejection})`,\n        });\n        return;\n      }\n      oracleCache.set(oracleKey(pack.locale, request), answer);\n    });\n  } catch (error) {\n    emitWarning({\n      code: \"fallback-error\",\n      locale: pack.locale,\n      detail: error instanceof Error ? error.message : String(error),\n    });\n    return first.text;\n  }\n  // Second pass: same pure pack, now with the cache warm.\n  return runPack(pack, phrase, features).text;\n}\n\n/**\n * Warm up the fallback for a locale (loads the neural session, if one is\n * registered). Safe to call unconditionally — resolves immediately when\n * there is nothing to preload.\n */\nexport async function preload(locale: string): Promise<void> {\n  await getFallback(locale)?.preload?.();\n}\n\n/**\n * Internal: inflect with raw (string) template annotations. Used by the\n * template renderer so per-pack `normalizeFeatures` overrides apply.\n * @internal\n */\nexport function inflectRaw(locale: string, phrase: string, raw: Record<string, string>): string {\n  const pack = packOrWarn(locale);\n  if (!pack) return phrase;\n  return runPack(pack, phrase, normalizeRawFor(pack, raw)).text;\n}\n\n/**\n * Internal async twin of {@link inflectRaw}.\n * @internal\n */\nexport async function inflectRawAsync(\n  locale: string,\n  phrase: string,\n  raw: Record<string, string>,\n): Promise<string> {\n  const pack = packOrWarn(locale);\n  if (!pack) return phrase;\n  return inflectAsync(locale, phrase, normalizeRawFor(pack, raw));\n}\n\nfunction normalizeRawFor(pack: LanguagePack, raw: Record<string, string>): GrammaticalFeatures {\n  const warn = (kind: \"unknown-feature-key\" | \"unknown-feature-value\", detail: string): void =>\n    emitWarning({ code: kind, locale: pack.locale, detail });\n  return pack.normalizeFeatures ? pack.normalizeFeatures(raw, warn) : normalizeFeatures(raw, warn);\n}\n","import { LruCache } from \"../core/cache.js\";\nimport { emitWarning } from \"../core/warnings.js\";\nimport type { Template, TemplateNode, TextNode, VariableNode } from \"./ast.js\";\n\n/**\n * Hand-written single-pass parser for the template grammar:\n *\n * ```\n * template  := element*\n * element   := TEXT | escape | variable | span\n * escape    := \"\\\" ANY                      // the literal char, everywhere\n * variable  := \"{\" ident \"}\"                // ident: [A-Za-z_][A-Za-z0-9_]*\n * span      := \"^[\" body \"](\" features \")\"\n * body      := (TEXT | escape | variable)*  // no nested spans\n * features  := pair (\";\" pair)* \";\"?        // pair: key \":\" value\n * ```\n *\n * Malformed input is never an error: an unmatched `^[`, `{`, or feature list\n * falls back to literal text (with a `malformed-template` warning), so a\n * translator's typo can only ever cost an inflection, not a render.\n */\n\nconst IDENT_START = /[A-Za-z_]/;\nconst IDENT_CHAR = /[A-Za-z0-9_]/;\n\nconst parseCache = new LruCache<string, Template>(500);\n\n/** Parse a template string (memoized on the source string). */\nexport function parseTemplate(source: string): Template {\n  const cached = parseCache.get(source);\n  if (cached) return cached;\n  const template = parse(source);\n  parseCache.set(source, template);\n  return template;\n}\n\nfunction parse(source: string): Template {\n  const nodes: TemplateNode[] = [];\n  let text = \"\";\n\n  const flushText = (): void => {\n    if (text.length > 0) {\n      nodes.push({ kind: \"text\", value: text });\n      text = \"\";\n    }\n  };\n\n  let i = 0;\n  while (i < source.length) {\n    const ch = source[i] as string;\n    if (ch === \"\\\\\" && i + 1 < source.length) {\n      text += source[i + 1];\n      i += 2;\n      continue;\n    }\n    if (ch === \"{\") {\n      const variable = tryParseVariable(source, i);\n      if (variable) {\n        flushText();\n        nodes.push(variable.node);\n        i = variable.end;\n        continue;\n      }\n      warnMalformed(source, i);\n    }\n    if (ch === \"^\" && source[i + 1] === \"[\") {\n      const span = tryParseSpan(source, i);\n      if (span) {\n        flushText();\n        nodes.push(span.node);\n        i = span.end;\n        continue;\n      }\n      warnMalformed(source, i);\n    }\n    text += ch;\n    i += 1;\n  }\n  flushText();\n  return { nodes };\n}\n\nfunction warnMalformed(source: string, at: number): void {\n  emitWarning({\n    code: \"malformed-template\",\n    detail: `treating as literal text at index ${at}: …${source.slice(at, at + 24)}`,\n  });\n}\n\nfunction tryParseVariable(\n  source: string,\n  start: number,\n): { node: VariableNode; end: number } | undefined {\n  let i = start + 1;\n  const first = source[i];\n  if (first === undefined || !IDENT_START.test(first)) return undefined;\n  let name = first;\n  i += 1;\n  while (i < source.length && IDENT_CHAR.test(source[i] as string)) {\n    name += source[i];\n    i += 1;\n  }\n  if (source[i] !== \"}\") return undefined;\n  return { node: { kind: \"var\", name }, end: i + 1 };\n}\n\nfunction tryParseSpan(\n  source: string,\n  start: number,\n): { node: TemplateNode; end: number } | undefined {\n  // Body runs from after \"^[\" to the first unescaped \"](\" sequence.\n  const body: (TextNode | VariableNode)[] = [];\n  let text = \"\";\n  const flushText = (): void => {\n    if (text.length > 0) {\n      body.push({ kind: \"text\", value: text });\n      text = \"\";\n    }\n  };\n\n  let i = start + 2;\n  while (i < source.length) {\n    const ch = source[i] as string;\n    if (ch === \"\\\\\" && i + 1 < source.length) {\n      text += source[i + 1];\n      i += 2;\n      continue;\n    }\n    if (ch === \"]\" && source[i + 1] === \"(\") {\n      const features = tryParseFeatures(source, i + 2);\n      if (!features) return undefined;\n      flushText();\n      return {\n        node: { kind: \"inflect\", body, features: features.features },\n        end: features.end,\n      };\n    }\n    if (ch === \"{\") {\n      const variable = tryParseVariable(source, i);\n      if (variable) {\n        flushText();\n        body.push(variable.node);\n        i = variable.end;\n        continue;\n      }\n    }\n    text += ch;\n    i += 1;\n  }\n  return undefined; // no \"](\" found — caller falls back to literal text\n}\n\nfunction tryParseFeatures(\n  source: string,\n  start: number,\n): { features: Record<string, string>; end: number } | undefined {\n  const close = source.indexOf(\")\", start);\n  if (close === -1) return undefined;\n  const features: Record<string, string> = {};\n  const list = source.slice(start, close);\n  for (const pair of list.split(\";\")) {\n    const trimmed = pair.trim();\n    if (trimmed.length === 0) continue; // tolerate a trailing \";\"\n    const colon = trimmed.indexOf(\":\");\n    if (colon === -1) return undefined; // not a feature list — not a span\n    const key = trimmed.slice(0, colon).trim();\n    const value = trimmed.slice(colon + 1).trim();\n    if (key.length === 0 || !/^[A-Za-z][A-Za-z0-9]*$/.test(key)) return undefined;\n    features[key] = value;\n  }\n  return { features, end: close + 1 };\n}\n","import { emitWarning } from \"../core/warnings.js\";\nimport type { Template, TextNode, VariableNode } from \"./ast.js\";\n\n/** Values usable as template arguments. Numbers are stringified. */\nexport type TemplateArgs = Record<string, string | number>;\n\n/** Inflects an interpolated span body; sync and async variants. */\nexport type SpanInflector = (phrase: string, features: Record<string, string>) => string;\nexport type AsyncSpanInflector = (\n  phrase: string,\n  features: Record<string, string>,\n) => Promise<string>;\n\nfunction substitute(nodes: (TextNode | VariableNode)[], args: TemplateArgs): string {\n  let out = \"\";\n  for (const node of nodes) {\n    if (node.kind === \"text\") {\n      out += node.value;\n    } else if (Object.hasOwn(args, node.name)) {\n      out += String(args[node.name]);\n    } else {\n      emitWarning({ code: \"missing-argument\", detail: node.name });\n      out += `{${node.name}}`;\n    }\n  }\n  return out;\n}\n\n/** Render a parsed template with a synchronous span inflector. */\nexport function renderTemplate(\n  template: Template,\n  args: TemplateArgs,\n  inflectSpan: SpanInflector,\n): string {\n  let out = \"\";\n  for (const node of template.nodes) {\n    if (node.kind === \"inflect\") {\n      out += inflectSpan(substitute(node.body, args), node.features);\n    } else {\n      out += substitute([node], args);\n    }\n  }\n  return out;\n}\n\n/** Render a parsed template, awaiting each span's inflection. */\nexport async function renderTemplateAsync(\n  template: Template,\n  args: TemplateArgs,\n  inflectSpan: AsyncSpanInflector,\n): Promise<string> {\n  const parts: (string | Promise<string>)[] = [];\n  for (const node of template.nodes) {\n    if (node.kind === \"inflect\") {\n      parts.push(inflectSpan(substitute(node.body, args), node.features));\n    } else {\n      parts.push(substitute([node], args));\n    }\n  }\n  return (await Promise.all(parts)).join(\"\");\n}\n","/**\n * i18n-inflect — grammatical inflection and agreement for i18n.\n *\n * ```ts\n * import { format } from \"i18n-inflect\";\n * import \"i18n-inflect/hu\"; // registers the Hungarian pack\n *\n * format(\"hu\", \"Nyertél ^[a {card}](case: instrumental)!\", { card: \"kőr ász\" });\n * // → \"Nyertél a kőr ásszal!\"\n * ```\n *\n * @packageDocumentation\n */\n\nimport { inflectRaw, inflectRawAsync } from \"./core/engine.js\";\nimport { parseTemplate } from \"./template/parser.js\";\nimport { renderTemplate, renderTemplateAsync, type TemplateArgs } from \"./template/render.js\";\n\n// ---- engine ----\nexport {\n  clearOracle,\n  inflect,\n  inflectAsync,\n  preload,\n  seedOracle,\n} from \"./core/engine.js\";\n// ---- core feature model ----\nexport type {\n  ArticleRequest,\n  Definiteness,\n  Derivation,\n  GrammaticalCase,\n  GrammaticalFeatures,\n  GrammaticalGender,\n  GrammaticalNumber,\n  GrammaticalPerson,\n  PartOfSpeech,\n} from \"./core/features.js\";\nexport { normalizeFeatures } from \"./core/features.js\";\n// ---- pack + fallback contracts ----\nexport type {\n  FallbackRequest,\n  InflectionContext,\n  InflectionFallback,\n  InflectionResult,\n  LanguagePack,\n} from \"./core/pack.js\";\n// ---- phrase helpers (public: for language pack authors) ----\nexport {\n  capitalize,\n  isCapitalized,\n  joinPhrase,\n  type SplitPhrase,\n  splitPhrase,\n  splitTrailingPunctuation,\n} from \"./core/phrase.js\";\n// ---- registry ----\nexport {\n  getFallback,\n  getLanguage,\n  registeredLocales,\n  registerFallback,\n  registerLanguage,\n  resetRegistry,\n  resolveLocale,\n} from \"./core/registry.js\";\n// ---- warnings ----\nexport type { InflectWarning, WarningCode, WarningHandler } from \"./core/warnings.js\";\nexport { onWarning } from \"./core/warnings.js\";\n// ---- template AST (public: reusable by alternative renderers) ----\nexport type {\n  InflectNode,\n  Template,\n  TemplateNode,\n  TextNode,\n  VariableNode,\n} from \"./template/ast.js\";\nexport { parseTemplate } from \"./template/parser.js\";\nexport type { TemplateArgs } from \"./template/render.js\";\n\n/**\n * Format a template with Apple-style inflection spans.\n *\n * `^[body](key: value; …)` spans are interpolated (`{var}` placeholders\n * first) and then inflected by the locale's language pack. Synchronous:\n * uses rules, lexicon and previously cached fallback answers only.\n *\n * Never throws on malformed templates or unknown locales — it degrades to\n * plain interpolated text and reports via {@link onWarning}.\n *\n * @example\n * ```ts\n * format(\"en\", \"You drew ^[a {c}](article: indefinite)\", { c: \"ace\" });\n * // → \"You drew an ace\"\n * ```\n */\nexport function format(locale: string, template: string, args: TemplateArgs = {}): string {\n  return renderTemplate(parseTemplate(template), args, (phrase, features) =>\n    inflectRaw(locale, phrase, features),\n  );\n}\n\n/**\n * Like {@link format}, but spans may await the registered fallback (e.g.\n * the neural module) for words the rules were unsure about. Results are\n * cached, so subsequent synchronous {@link format} calls with the same\n * words return the corrected forms too.\n */\nexport async function formatAsync(\n  locale: string,\n  template: string,\n  args: TemplateArgs = {},\n): Promise<string> {\n  return renderTemplateAsync(parseTemplate(template), args, (phrase, features) =>\n    inflectRawAsync(locale, phrase, features),\n  );\n}\n"]}