Files
Hankan/types/lib/hangul.d.ts
MechaCat02 966043ab3f feat(lib): type declarations and golden tests for the exported modules
lib/ ships unchanged, so its types live in types/lib/ and are wired up by a
tsconfig path mapping. Adding types costs nothing; reimplementing the logic
would cost the two things that make this port possible.

The tests exist so a later refactor cannot silently drift them:

  hangul       the nine Composer cases named in the export README —
               먹어 · 왔어 · 읽어 · 괜찮아 · 값 · 의사 · 뭐야 and backspace
  conjugation  all seven irregular classes, and every form in
               IRREGULAR_FORMS reachable through haeche()
  srs          the SM-2 transitions, ease and interval clamps
  blocks       parse → answerText round-trip for all four task types

101 tests.

One is a pinned defect rather than a guarantee. blocks.parse() never closes
a ::gloss block on its "=" line, so a multi-sentence gloss — which the tutor
prompt explicitly invites — collapses into one run-on line keeping only the
last translation. lib/ ships unchanged, so the test records the real
behaviour and the app works around it at the call site.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 19:12:19 +02:00

39 lines
1.1 KiB
TypeScript

/* Declarations for lib/hangul.js — the module itself ships unchanged. */
export const CHO: string;
export const JUNG: string;
export const JONG: string;
/** [initialIndex, medialIndex, finalIndex], or null if not a syllable block. */
export function decompose(ch: string): [number, number, number] | null;
export function compose(i: number, m: number, f?: number): string;
export const isJamo: {
initial(c: string): boolean;
medial(c: string): boolean;
final(c: string): boolean;
};
/**
* A 두벌식 IME. Hold one per input: feed jamo with key(), literal text with
* text(), Backspace with back(). Each call returns the full new value.
*/
export class Composer {
cho: string | null;
jung: string | null;
jong: string | null;
reset(): void;
readonly empty: boolean;
/** The syllable currently being assembled, as text. */
render(): string;
key(value: string, jamo: string): string;
back(value: string): string;
/** Commit the buffer and append literal text (space, punctuation). */
text(value: string, t: string): string;
}
export const KEYBOARD: {
rows: string[][];
shift: Record<string, string>;
};