diff --git a/docs/src/pages/docs/api/getChoseong.en.mdx b/docs/src/pages/docs/api/getChoseong.en.mdx new file mode 100644 index 00000000..7f9b9c99 --- /dev/null +++ b/docs/src/pages/docs/api/getChoseong.en.mdx @@ -0,0 +1,19 @@ +# getChoseong + + +Extracts the Choseong from a Korean word. (Example: 사과 -> 'ㅅㄱ') + +```typescript +function getChoseong( + // Korean string from which to extract the choseong + word: string +): string; +``` + +## Examples + +```tsx +getChoseong('사과') // 'ㅅㄱ' +getChoseong('리액트') // 'ㄹㅇㅌ' +getChoseong('띄어 쓰기') // 'ㄸㅇ ㅆㄱ' +``` diff --git a/docs/src/pages/docs/api/getChoseong.ko.mdx b/docs/src/pages/docs/api/getChoseong.ko.mdx new file mode 100644 index 00000000..72137500 --- /dev/null +++ b/docs/src/pages/docs/api/getChoseong.ko.mdx @@ -0,0 +1,20 @@ +# getChoseong + +단어에서 초성을 추출합니다. (예: `사과` -> `'ㅅㄱ'`) + +자세한 예시는 아래 Example을 참고하세요. + +```typescript +function getChoseong( + // 초성을 추출 할 한글 문자열 + word: string +): string; +``` + +## Examples + +```tsx +getChoseong('사과') // 'ㅅㄱ' +getChoseong('리액트') // 'ㄹㅇㅌ' +getChoseong('띄어 쓰기') // 'ㄸㅇ ㅆㄱ' +``` diff --git a/src/choseongIncludes.ts b/src/choseongIncludes.ts index de13a893..fbaf6407 100644 --- a/src/choseongIncludes.ts +++ b/src/choseongIncludes.ts @@ -1,5 +1,6 @@ import { disassembleToGroups } from './disassemble'; -import { canBeChoseong, getChoseong } from './utils'; +import { getChoseong } from './getChoseong'; +import { canBeChoseong } from './utils'; export function choseongIncludes(x: string, y: string) { const trimmedY = y.replace(/\s/g, ''); diff --git a/src/chosungIncludes.ts b/src/chosungIncludes.ts index 3c8f0ec1..7f775256 100644 --- a/src/chosungIncludes.ts +++ b/src/chosungIncludes.ts @@ -1,5 +1,5 @@ import { isOnlyChoseong } from './choseongIncludes'; -import { getChoseong } from './utils'; +import { getChoseong } from './getChoseong'; /** * @deprecated choseongIncludes를 사용해 주세요. diff --git a/src/getChoseong.spec.ts b/src/getChoseong.spec.ts new file mode 100644 index 00000000..ae1ddc4c --- /dev/null +++ b/src/getChoseong.spec.ts @@ -0,0 +1,20 @@ +import { getChoseong } from './getChoseong'; + +describe('getChoseong', () => { + it('"사과" 단어에서 초성 "ㅅㄱ"을 추출한다.', () => { + expect(getChoseong('사과')).toBe('ㅅㄱ'); + }); + it('"프론트엔드" 단어에서 초성 "ㅍㄹㅌㅇㄷ"을 추출한다.', () => { + expect(getChoseong('프론트엔드')).toBe('ㅍㄹㅌㅇㄷ'); + }); + it('"ㄴㅈ" 문자에서 초성 "ㄴㅈ"을 추출한다.', () => { + expect(getChoseong('ㄴㅈ')).toBe('ㄴㅈ'); + }); + it('"리액트" 단어에서 초성 "ㄹㅇㅌ"을 추출한다.', () => { + expect(getChoseong('리액트')).toBe('ㄹㅇㅌ'); + }); + + it('"띄어 쓰기" 문장에서 초성 "ㄸㅇ ㅆㄱ"을 추출한다.', () => { + expect(getChoseong('띄어 쓰기')).toBe('ㄸㅇ ㅆㄱ'); + }); +}); diff --git a/src/getChoseong.ts b/src/getChoseong.ts new file mode 100644 index 00000000..2889733f --- /dev/null +++ b/src/getChoseong.ts @@ -0,0 +1,32 @@ +import { HANGUL_CHARACTERS_BY_FIRST_INDEX, JASO_HANGUL_NFD } from './constants'; + +/** + * @name getChoseong + * @description + * 단어에서 초성을 추출합니다. (예: `사과` -> `'ㅅㄱ'`) + * ```typescript + * getChoseong( + * // 초성을 추출할 단어 + * word: string + * ): string + * ``` + * @example + * getChoseong('사과') // 'ㅅㄱ' + * getChoseong('리액트') // 'ㄹㅇㅌ' + * getChoseong('띄어 쓰기') // 'ㄸㅇ ㅆㄱ' + */ +export function getChoseong(word: string) { + return word + .normalize('NFD') + .replace(EXTRACT_CHOSEONG_REGEX, '') // NFD ㄱ-ㅎ, NFC ㄱ-ㅎ 외 문자 삭제 + .replace(CHOOSE_NFD_CHOSEONG_REGEX, $0 => HANGUL_CHARACTERS_BY_FIRST_INDEX[$0.charCodeAt(0) - 0x1100]); // NFD to NFC +} + +const EXTRACT_CHOSEONG_REGEX = new RegExp( + `[^\\u${JASO_HANGUL_NFD.START_CHOSEONG.toString(16)}-\\u${JASO_HANGUL_NFD.END_CHOSEONG.toString(16)}ㄱ-ㅎ\\s]+`, + 'ug' +); +const CHOOSE_NFD_CHOSEONG_REGEX = new RegExp( + `[\\u${JASO_HANGUL_NFD.START_CHOSEONG.toString(16)}-\\u${JASO_HANGUL_NFD.END_CHOSEONG.toString(16)}]`, + 'g' +); diff --git a/src/index.ts b/src/index.ts index 4d405f4d..8213053d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,11 +7,11 @@ export { disassemble, disassembleToGroups } from './disassemble'; export { disassembleCompleteCharacter } from './disassembleCompleteCharacter'; export { josa } from './josa'; export { removeLastHangulCharacter } from './removeLastHangulCharacter'; +export { getChoseong } from './getChoseong'; export { canBeChosung, canBeJongsung, canBeJungsung, - getChosung, hasBatchim, hasProperty, hasSingleBatchim, diff --git a/src/utils.spec.ts b/src/utils.spec.ts index d2660a9f..e5c618c7 100644 --- a/src/utils.spec.ts +++ b/src/utils.spec.ts @@ -2,8 +2,6 @@ import { canBeChoseong, canBeJongseong, canBeJungseong, - getChoseong, - getFirstConsonants, hasBatchim, hasProperty, hasSingleBatchim, @@ -84,44 +82,6 @@ describe('hasSingleBatchim', () => { }); }); -describe('getChoseong', () => { - it('"사과" 단어에서 초성 "ㅅㄱ"을 추출한다.', () => { - expect(getChoseong('사과')).toBe('ㅅㄱ'); - }); - it('"프론트엔드" 단어에서 초성 "ㅍㄹㅌㅇㄷ"을 추출한다.', () => { - expect(getChoseong('프론트엔드')).toBe('ㅍㄹㅌㅇㄷ'); - }); - it('"ㄴㅈ" 문자에서 초성 "ㄴㅈ"을 추출한다.', () => { - expect(getChoseong('ㄴㅈ')).toBe('ㄴㅈ'); - }); - it('"리액트" 단어에서 초성 "ㄹㅇㅌ"을 추출한다.', () => { - expect(getChoseong('리액트')).toBe('ㄹㅇㅌ'); - }); - - it('"띄어 쓰기" 문장에서 초성 "ㄸㅇ ㅆㄱ"을 추출한다.', () => { - expect(getChoseong('띄어 쓰기')).toBe('ㄸㅇ ㅆㄱ'); - }); -}); - -describe('getFirstConsonants', () => { - it('"사과" 단어에서 초성 "ㅅㄱ"을 추출한다.', () => { - expect(getFirstConsonants('사과')).toBe('ㅅㄱ'); - }); - it('"프론트엔드" 단어에서 초성 "ㅍㄹㅌㅇㄷ"을 추출한다.', () => { - expect(getFirstConsonants('프론트엔드')).toBe('ㅍㄹㅌㅇㄷ'); - }); - it('"ㄴㅈ" 문자에서 초성 "ㄴㅈ"을 추출한다.', () => { - expect(getFirstConsonants('ㄴㅈ')).toBe('ㄴㅈ'); - }); - it('"리액트" 단어에서 초성 "ㄹㅇㅌ"을 추출한다.', () => { - expect(getFirstConsonants('리액트')).toBe('ㄹㅇㅌ'); - }); - - it('"띄어 쓰기" 문장에서 초성 "ㄸㅇ ㅆㄱ"을 추출된다.', () => { - expect(getFirstConsonants('띄어 쓰기')).toBe('ㄸㅇ ㅆㄱ'); - }); -}); - describe('hasValueInReadOnlyStringList', () => { const testReadonlyList = ['ㄱ', 'ㄴ', 'ㄷ'] as const; diff --git a/src/utils.ts b/src/utils.ts index 941f736c..22725644 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -4,19 +4,8 @@ import { HANGUL_CHARACTERS_BY_FIRST_INDEX, HANGUL_CHARACTERS_BY_LAST_INDEX, HANGUL_CHARACTERS_BY_MIDDLE_INDEX, - JASO_HANGUL_NFD, NUMBER_OF_JONGSEONG, } from './constants'; -import { disassembleToGroups } from './disassemble'; - -const EXTRACT_CHOSEONG_REGEX = new RegExp( - `[^\\u${JASO_HANGUL_NFD.START_CHOSEONG.toString(16)}-\\u${JASO_HANGUL_NFD.END_CHOSEONG.toString(16)}ㄱ-ㅎ\\s]+`, - 'ug' -); -const CHOOSE_NFD_CHOSEONG_REGEX = new RegExp( - `[\\u${JASO_HANGUL_NFD.START_CHOSEONG.toString(16)}-\\u${JASO_HANGUL_NFD.END_CHOSEONG.toString(16)}]`, - 'g' -); /** * @name hasBatchim @@ -80,73 +69,6 @@ export function hasSingleBatchim(str: string) { return HANGUL_CHARACTERS_BY_LAST_INDEX[batchimCode].length === 1; } -/** - * @name getChosung - * @deprecated getChoseong을 사용해 주세요. - * @description - * 단어에서 초성을 추출합니다. (예: `사과` -> `'ㅅㄱ'`) - * ```typescript - * getChoseong( - * // 초성을 추출할 단어 - * word: string - * ): string - * ``` - * @example - * getChoseong('사과') // 'ㅅㄱ' - * getChoseong('리액트') // 'ㄹㅇㅌ' - * getChoseong('띄어 쓰기') // 'ㄸㅇ ㅆㄱ' - */ -export function getChosung(word: string) { - return word - .normalize('NFD') - .replace(EXTRACT_CHOSEONG_REGEX, '') // NFD ㄱ-ㅎ, NFC ㄱ-ㅎ 외 문자 삭제 - .replace(CHOOSE_NFD_CHOSEONG_REGEX, $0 => HANGUL_CHARACTERS_BY_FIRST_INDEX[$0.charCodeAt(0) - 0x1100]); // NFD to NFC -} - -/** - * @name getChoseong - * @description - * 단어에서 초성을 추출합니다. (예: `사과` -> `'ㅅㄱ'`) - * ```typescript - * getChoseong( - * // 초성을 추출할 단어 - * word: string - * ): string - * ``` - * @example - * getChoseong('사과') // 'ㅅㄱ' - * getChoseong('리액트') // 'ㄹㅇㅌ' - * getChoseong('띄어 쓰기') // 'ㄸㅇ ㅆㄱ' - */ -export function getChoseong(word: string) { - return word - .normalize('NFD') - .replace(EXTRACT_CHOSEONG_REGEX, '') // NFD ㄱ-ㅎ, NFC ㄱ-ㅎ 외 문자 삭제 - .replace(CHOOSE_NFD_CHOSEONG_REGEX, $0 => HANGUL_CHARACTERS_BY_FIRST_INDEX[$0.charCodeAt(0) - 0x1100]); // NFD to NFC -} - -/** - * @name getFirstConsonants - * @deprecated getChoseong을 사용해 주세요. - * @description - * 단어에서 초성을 추출합니다. (예: `사과` -> `'ㅅㄱ'`) - * ```typescript - * getFirstConsonants( - * // 초성을 추출할 단어 - * word: string - * ): string - * ``` - * @example - * getFirstConsonants('사과') // 'ㅅㄱ' - * getFirstConsonants('리액트') // 'ㄹㅇㅌ' - * getFirstConsonants('띄어 쓰기') // 'ㄸㅇ ㅆㄱ' - */ -export function getFirstConsonants(word: string) { - return disassembleToGroups(word).reduce((firstConsonants, [consonant]) => { - return `${firstConsonants}${consonant}`; - }, ''); -} - /** * @name canBeChosung * @deprecated canBeChoseong을 사용해 주세요.