{"version":3,"sources":["../../src/ko/hangul.ts","../../src/ko/particles.ts","../../src/ko/index.ts"],"names":["splitTrailingPunctuation","registerLanguage"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Hangul syllable analysis for particle selection.\n *\n * A precomposed syllable (U+AC00–U+D7A3) encodes its final consonant\n * (batchim) as `(codepoint - 0xAC00) % 28`: 0 = open syllable, 8 = ㄹ\n * (which selects 로 instead of 으로 for the instrumental).\n */\n\n/** What particle alternation the phrase-final character calls for. */\nexport interface FinalSound {\n  /** True when the syllable ends in a consonant (batchim). */\n  hasBatchim: boolean;\n  /** True when that consonant is ㄹ (jongseong index 8). */\n  isRieul: boolean;\n}\n\nconst HANGUL_BASE = 0xac00;\nconst HANGUL_END = 0xd7a3;\n\n/**\n * Korean readings of digits (native Sino-Korean): 0 영, 1 일, 2 이, 3 삼,\n * 4 사, 5 오, 6 육, 7 칠, 8 팔, 9 구 — encoded as their final-sound classes.\n */\nconst DIGIT_FINALS: Record<string, FinalSound> = {\n  \"0\": { hasBatchim: true, isRieul: false }, // 영\n  \"1\": { hasBatchim: true, isRieul: true }, // 일\n  \"2\": { hasBatchim: false, isRieul: false }, // 이\n  \"3\": { hasBatchim: true, isRieul: false }, // 삼\n  \"4\": { hasBatchim: false, isRieul: false }, // 사\n  \"5\": { hasBatchim: false, isRieul: false }, // 오\n  \"6\": { hasBatchim: true, isRieul: false }, // 육\n  \"7\": { hasBatchim: true, isRieul: true }, // 칠\n  \"8\": { hasBatchim: true, isRieul: true }, // 팔\n  \"9\": { hasBatchim: false, isRieul: false }, // 구\n};\n\n/**\n * Analyze the last pronounceable character of a phrase.\n *\n * Returns `undefined` when the final sound cannot be determined (Latin\n * script, symbols) — callers then use the paired particle form (\"을(를)\").\n */\nexport function finalSoundOf(phrase: string): FinalSound | undefined {\n  for (let i = phrase.length - 1; i >= 0; i--) {\n    const ch = phrase[i] as string;\n    if (/[\\s.,;:!?…\"'()[\\]{}]/.test(ch)) continue;\n    const cp = ch.codePointAt(0) as number;\n    if (cp >= HANGUL_BASE && cp <= HANGUL_END) {\n      const jong = (cp - HANGUL_BASE) % 28;\n      return { hasBatchim: jong > 0, isRieul: jong === 8 };\n    }\n    const digit = DIGIT_FINALS[ch];\n    if (digit) return digit;\n    return undefined; // undecidable script\n  }\n  return undefined;\n}\n","import type { FinalSound } from \"./hangul.js\";\n\n/**\n * Korean case particles with their phonological alternations.\n *\n * The particle attaches to the *whole* noun phrase, chosen by the final\n * sound of its last syllable. When the final sound is undecidable (Latin\n * text), the conventional paired notation is used: \"Chrome을(를)\".\n */\n\n/** Grammatical roles the Korean pack maps from `case:`. */\nexport type KoRole =\n  | \"nominative\"\n  | \"accusative\"\n  | \"topic\"\n  | \"instrumental\"\n  | \"comitative\"\n  | \"genitive\";\n\ninterface ParticleForms {\n  /** After a batchim (closed syllable). */\n  closed: string;\n  /** After an open syllable. */\n  open: string;\n  /** After ㄹ — only differs for the instrumental (서울로). */\n  rieul?: string;\n  /** Paired notation for undecidable finals. */\n  paired: string;\n}\n\nconst PARTICLES: Record<KoRole, ParticleForms> = {\n  nominative: { closed: \"이\", open: \"가\", paired: \"이(가)\" },\n  accusative: { closed: \"을\", open: \"를\", paired: \"을(를)\" },\n  topic: { closed: \"은\", open: \"는\", paired: \"은(는)\" },\n  instrumental: { closed: \"으로\", open: \"로\", rieul: \"로\", paired: \"(으)로\" },\n  comitative: { closed: \"과\", open: \"와\", paired: \"과(와)\" },\n  genitive: { closed: \"의\", open: \"의\", paired: \"의\" },\n};\n\n/** Select the particle for a role given the phrase-final sound. */\nexport function particleFor(role: KoRole, final: FinalSound | undefined): string {\n  const forms = PARTICLES[role];\n  if (final === undefined) return forms.paired;\n  if (final.isRieul && forms.rieul !== undefined) return forms.rieul;\n  return final.hasBatchim ? forms.closed : forms.open;\n}\n\n/** True when the core feature case maps to a Korean particle role. */\nexport function isKoRole(value: string): value is KoRole {\n  return value in PARTICLES;\n}\n","import type { GrammaticalFeatures } from \"../core/features.js\";\nimport type { InflectionContext, InflectionResult, LanguagePack } from \"../core/pack.js\";\nimport { splitTrailingPunctuation } from \"../core/phrase.js\";\nimport { registerLanguage } from \"../core/registry.js\";\nimport { finalSoundOf } from \"./hangul.js\";\nimport { isKoRole, particleFor } from \"./particles.js\";\n\n/**\n * Korean language pack: phonological case-particle attachment\n * (은/는, 이/가, 을/를, (으)로, 과/와, 의) driven by the batchim of the last\n * syllable, with digit readings and a paired-form fallback for\n * undecidable (e.g. Latin) finals.\n *\n * `import \"i18n-inflect/ko\"` registers it as a side effect.\n */\n\nfunction inflectPhrase(\n  phrase: string,\n  features: GrammaticalFeatures,\n  ctx: InflectionContext,\n): InflectionResult {\n  const [core, punct] = splitTrailingPunctuation(phrase.trimEnd());\n  const trailingWs = phrase.slice(phrase.trimEnd().length);\n  if (core.length === 0) return { text: phrase, confidence: \"high\" };\n\n  let body = core;\n\n  // Optional plural marker 들 (commonly omitted in Korean; applied on request).\n  if (features.number === \"plural\") body += \"들\";\n\n  let confidence: \"high\" | \"low\" = \"high\";\n  if (features.case && features.case !== \"nominative\" && !isKoRole(features.case)) {\n    ctx.warn(\"unknown-feature-value\", `case not supported for ko: ${features.case}`);\n  } else if (features.case && isKoRole(features.case)) {\n    const final = finalSoundOf(body);\n    if (final === undefined) confidence = \"low\"; // paired form used\n    body += particleFor(features.case, final);\n  }\n\n  return { text: body + punct + trailingWs, confidence };\n}\n\n/** The Korean language pack. */\nexport const ko: LanguagePack = {\n  locale: \"ko\",\n  inflectPhrase,\n};\n\nregisterLanguage(ko);\n"]}