From 16645753056faa9702be5c50f1042618c032b186 Mon Sep 17 00:00:00 2001 From: Evan Moon Date: Tue, 16 Apr 2024 20:47:17 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=9D=B8=EC=9E=90=EB=A1=9C=20=EB=B0=9B?= =?UTF-8?q?=EC=9D=80=20=EB=AC=B8=EC=9E=90=EC=9D=98=20=EC=B4=88=EC=84=B1,?= =?UTF-8?q?=20=EC=A4=91=EC=84=B1,=20=EC=A2=85=EC=84=B1=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EA=B0=80=EB=8A=A5=20=EC=97=AC=EB=B6=80=EB=A5=BC=20?= =?UTF-8?q?=ED=8C=8C=EC=95=85=ED=95=98=EB=8A=94=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#36)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 인자로 받은 문자의 초성, 중성, 종성 위치 가능 여부를 파악하는 함수 추가 * Create sweet-fireants-cough.md --- .changeset/sweet-fireants-cough.md | 5 +++ src/chosungIncludes.ts | 4 +- src/utils.spec.ts | 65 ++++++++++++++++++++++++++- src/utils.ts | 70 ++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 .changeset/sweet-fireants-cough.md diff --git a/.changeset/sweet-fireants-cough.md b/.changeset/sweet-fireants-cough.md new file mode 100644 index 00000000..7ec8af43 --- /dev/null +++ b/.changeset/sweet-fireants-cough.md @@ -0,0 +1,5 @@ +--- +"es-hangul": patch +--- + +feat: 인자로 받은 문자의 초성, 중성, 종성 위치 가능 여부를 파악하는 함수 추가 #24 diff --git a/src/chosungIncludes.ts b/src/chosungIncludes.ts index a2275783..cd9dccea 100644 --- a/src/chosungIncludes.ts +++ b/src/chosungIncludes.ts @@ -1,6 +1,6 @@ import { HANGUL_CHARACTERS_BY_FIRST_INDEX } from './constants'; import { disassembleHangulToGroups } from './disassemble'; -import { getFirstConsonants, hasValueInReadOnlyStringList } from './utils'; +import { canBeChosung, getFirstConsonants, hasValueInReadOnlyStringList } from './utils'; export function chosungIncludes(x: string, y: string) { if (!isOnlyInitialConsonant(y)) { @@ -18,6 +18,6 @@ export function chosungIncludes(x: string, y: string) { */ function isOnlyInitialConsonant(str: string) { return disassembleHangulToGroups(str).every(disassembled => { - return disassembled.length === 1 && hasValueInReadOnlyStringList(HANGUL_CHARACTERS_BY_FIRST_INDEX, disassembled[0]); + return disassembled.length === 1 && canBeChosung(disassembled[0]); }); } diff --git a/src/utils.spec.ts b/src/utils.spec.ts index c5aafe3f..e724051c 100644 --- a/src/utils.spec.ts +++ b/src/utils.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, expectTypeOf, it } from 'vitest'; -import { getFirstConsonants, hasBatchim, hasProperty, hasValueInReadOnlyStringList } from './utils'; +import { canBeChosung, canBeJongsung, canBeJungsung, getFirstConsonants, hasBatchim, hasProperty, hasValueInReadOnlyStringList } from './utils'; describe('hasBatchim', () => { it('should return true for the character "값"', () => { @@ -89,3 +89,66 @@ describe('hasProperty', () => { } }); }); + +describe('canBeChosung', () => { + it('ㄱ', () => { + expect(canBeChosung('ㄱ')).toBe(true); + }); + it('ㅃ', () => { + expect(canBeChosung('ㅃ')).toBe(true); + }); + it('ㅏ', () => { + expect(canBeChosung('ㅏ')).toBe(false); + }); + it('ㅘ', () => { + expect(canBeChosung('ㅏ')).toBe(false); + }); + it('ㄱㅅ', () => { + expect(canBeChosung('ㅏ')).toBe(false); + }); + it('가', () => { + expect(canBeChosung('ㅏ')).toBe(false); + }); +}); + +describe('canBeJungsung', () => { + it('ㅗㅏ', () => { + expect(canBeJungsung('ㅗㅏ')).toBe(true); + }); + it('ㅏ', () => { + expect(canBeJungsung('ㅏ')).toBe(true); + }); + it('ㄱ', () => { + expect(canBeJungsung('ㄱ')).toBe(false); + }); + it('ㄱㅅ', () => { + expect(canBeJungsung('ㄱㅅ')).toBe(false); + }); + it('가', () => { + expect(canBeJungsung('가')).toBe(false); + }); +}); + +describe('canBeJongsung', () => { + it('ㄱ', () => { + expect(canBeJongsung('ㄱ')).toBe(true); + }); + it('ㄱㅅ', () => { + expect(canBeJongsung('ㄱㅅ')).toBe(true); + }); + it('ㅂㅅ', () => { + expect(canBeJongsung('ㅂㅅ')).toBe(true); + }); + it('ㅎㄹ', () => { + expect(canBeJongsung('ㅎㄹ')).toBe(false); + }); + it('ㅗㅏ', () => { + expect(canBeJongsung('ㅗㅏ')).toBe(false); + }); + it('ㅏ', () => { + expect(canBeJongsung('ㅏ')).toBe(false); + }); + it('가', () => { + expect(canBeJongsung('ㅏ')).toBe(false); + }); +}); diff --git a/src/utils.ts b/src/utils.ts index 38ed2457..e40a0359 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,3 +1,8 @@ +import { + HANGUL_CHARACTERS_BY_FIRST_INDEX, + HANGUL_CHARACTERS_BY_LAST_INDEX, + HANGUL_CHARACTERS_BY_MIDDLE_INDEX, +} from './constants'; import { disassembleHangulToGroups } from './disassemble'; import { disassembleCompleteHangulCharacter } from './disassembleCompleteHangulCharacter'; @@ -42,6 +47,71 @@ export function getFirstConsonants(word: string) { }, ''); } +/** + * @name canBeChosung + * @description + * 인자로 받은 문자가 초성으로 위치할 수 있는 문자인지 검사합니다. + * ```typescript + * canBeChosung( + * // 대상 문자 + * character: string + * ): boolean + * ``` + * @example + * canBeChosung('ㄱ') // true + * canBeChosung('ㅃ') // true + * canBeChosung('ㄱㅅ') // false + * canBeChosung('ㅏ') // false + * canBeChosung('가') // false + */ +export function canBeChosung(character: string) { + return hasValueInReadOnlyStringList(HANGUL_CHARACTERS_BY_FIRST_INDEX,character); +} + +/** + * @name canBeJungsung + * @description + * 인자로 받은 문자가 중성으로 위치할 수 있는 문자인지 검사합니다. + * ```typescript + * canBeJungsung( + * // 대상 문자 + * character: string + * ): boolean + * ``` + * @example + * canBeChosung('ㅏ') // true + * canBeChosung('ㅗㅏ') // true + * canBeChosung('ㅏㅗ') // false + * canBeChosung('ㄱ') // false + * canBeChosung('ㄱㅅ') // false + * canBeChosung('가') // false + */ +export function canBeJungsung(character: string) { + return hasValueInReadOnlyStringList(HANGUL_CHARACTERS_BY_MIDDLE_INDEX, character); +} + +/** + * @name canBeJongsung + * @description + * 인자로 받은 문자가 종성으로 위치할 수 있는 문자인지 검사합니다. + * ```typescript + * canBeJongsung( + * // 대상 문자 + * character: string + * ): boolean + * ``` + * @example + * canBeChosung('ㄱ') // true + * canBeChosung('ㄱㅅ') // true + * canBeChosung('ㅎㄹ') // false + * canBeChosung('가') // false + * canBeChosung('ㅏ') // false + * canBeChosung('ㅗㅏ') // false + */ +export function canBeJongsung(character: string) { + return hasValueInReadOnlyStringList(HANGUL_CHARACTERS_BY_LAST_INDEX, character); +} + export function hasValueInReadOnlyStringList(list: readonly T[], value: string): value is T { return list.some(item => item === value); }