Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 일관된 한글 표기법 적용 #138

Merged
merged 16 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { chosungIncludes } from 'es-hangul';

export function ChosungIncludesDemo() {
export function ChoseongIncludesDemo() {
const [searchWord, setSearchWord] = useState<string>('홍길동');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 소문자로 바꾸신 이유가 있으신가요?
이 부분도 sung이 아닌, seong이 되면 좋겠어요!

Copy link
Contributor Author

@Collection50 Collection50 Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 알겠습니다 ! 👍

해당 PR에서 hangul을 제외하는 것도 진행해도 괜찮은지 여쭙고 싶습니다 !
만약 PR을 분리해야 한다면, 제가 맡고 싶습니다 :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR을 분리하면 좋을 것 같아요!
맡아주신다니 영광입니다, BC가 없도록 두가지 메서드씩 모두 살려두는 방향으로 작업해주시면 좋을 것 같아요!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sung => seong 이 작업 및 컨플리긑 해결 부탁드립니다 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

완료했습니다 !

const [userInput, setUserInput] = useState<string>('ㅎㄱㄷ');

Expand Down
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deprecated 되었다는 표기를 남기고 새로운 문서를 만드는 것이 좋지 않을까요? 🤔
패키지 상에서는 deprecated 인데, 문서는 없어지는 것이 우려됩니다.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰해주셔서 감사합니다 ! @minsoo-web

chosungIncludes는 라이브러리를 사용하는 사람들이 안전하게 사용하도록 chosungIncludes, choseongIncludes 을 동시에 export 해주고,

chosung~choseong~ 모두 작성하는 것으로 위 문장을 이해했는데 잘못 이해한 부분이 있다면 말씀해주시면 감사하겠습니다 !


새로운 문서를 만드는 것이 좋지 않을까요? 🤔

문서 또한 chosung~choseong~ 모두 작성하는 것으로 진행할까요??

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chosung과 choseong 모두 작성하는 것으로 위 문장을 이해했는데 잘못 이해한 부분이 있다면 말씀해주시면 감사하겠습니다 !

네네! 같은 방향으로 이해한 것 같습니다.
다만, chosung 이 잘못된 표기니까, deprecated 처리 하되 문서는 url이 chosung 이 포함된 url 이 있다면, choseong 으로 이동할 수 있도록 가이드 하면 어떨까요?

예시)
기존:
https://es-hangul.slash.page/docs/api/chosungIncludes

변경 후:
https://es-hangul.slash.page/docs/api/chosungIncludes (deprecated) > choseongIncludes 를 사용해주세요!
https://es-hangul.slash.page/docs/api/choseongInclues

이런 느낌이죠!!

아니면, deprecated features 라는 페이지를 만들어서 기재해두어도 괜찮을 것 같아요!
ref: https://v2.chakra-ui.com/getting-started/migration#5-deprecated-features

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 알겠습니다 !

  1. chosung은 deprecated 처리
  2. chousng의 문서는 삭제하지 않고 choseong과 함께 존재

정리하자면 위와 같이 진행하면 되는 것일까요??

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 바라는 방향성입니다!!
문의 주신 내용에 대해서는 @okinawaa 님이 답변 주시면 너무 좋을 것 같아요!!

제가 확답 드리지 못하는 이유는, 저는 메인테이너도 코드오너도 아니기 때문입니다 !!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 저도 @minsoo-web 님 의견 너무 좋습니다~ 문서도 살려두면 좋겠네요!

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChosungIncludesDemo } from '@/components/demo/chosung-includes-demo';
import { ChoseongIncludesDemo } from '@/components/demo/chosung-includes-demo';

# chosungIncludes

Expand All @@ -24,4 +24,4 @@ chosungIncludes('프론트엔드', '푸롴트'); // false

<br />

<ChosungIncludesDemo />
<ChoseongIncludesDemo />
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChosungIncludesDemo } from '@/components/demo/chosung-includes-demo';
import { ChoseongIncludesDemo } from '@/components/demo/chosung-includes-demo';

# chosungIncludes

Expand All @@ -24,4 +24,4 @@ chosungIncludes('프론트엔드', '푸롴트'); // false

<br />

<ChosungIncludesDemo />
<ChoseongIncludesDemo />
3 changes: 2 additions & 1 deletion docs/src/pages/index.en.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import { Callout, useTheme, Steps } from 'nextra-theme-docs';
<h3 className="">A modern JavaScript Hangul library</h3>
</div>
<Callout className="w-full">
es-hangul is a small JavaScript library that helps you conveniently handle Hangul. It provides a convenient and clean API for actions such as searching for initial consonants and attaching particles.
es-hangul is a small JavaScript library that helps you conveniently handle Hangul. It provides a convenient and
clean API for actions such as searching for initial consonants and attaching particles.
</Callout>
</div>
</div>
Expand Down
30 changes: 15 additions & 15 deletions src/_internal/hangul.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import assert, { excludeLastElement, isBlank, joinString } from '.';
import { combineHangulCharacter, combineVowels, curriedCombineHangulCharacter } from '../combineHangulCharacter';
import { disassembleHangulToGroups } from '../disassemble';
import { removeLastHangulCharacter } from '../removeLastHangulCharacter';
import { canBeChosung, canBeJongsung, canBeJungsung, hasSingleBatchim } from '../utils';
import { canBeChoseong, canBeJongseong, canBeJungseong, hasSingleBatchim } from '../utils';

export function isHangulCharacter(character: string) {
return /^[가-힣]$/.test(character);
Expand Down Expand Up @@ -57,12 +57,12 @@ export function safeParseHangul(actual: unknown): SafeParseSuccess | SafeParseEr
* ```
*/
export function binaryAssembleHangulAlphabets(source: string, nextCharacter: string) {
if (canBeJungsung(`${source}${nextCharacter}`)) {
if (canBeJungseong(`${source}${nextCharacter}`)) {
return combineVowels(source, nextCharacter);
}

const isConsonantSource = canBeJungsung(source) === false;
if (isConsonantSource && canBeJungsung(nextCharacter)) {
const isConsonantSource = canBeJungseong(source) === false;
if (isConsonantSource && canBeJungseong(nextCharacter)) {
return combineHangulCharacter(source, nextCharacter);
}

Expand Down Expand Up @@ -106,7 +106,7 @@ export function binaryAssembleHangulCharacters(source: string, nextCharacter: st
);
assert(
isHangulAlphabet(nextCharacter),
`Invalid next character: ${nextCharacter}. Next character must be one of the chosung, jungsung, or jongsung.`
`Invalid next character: ${nextCharacter}. Next character must be one of the choseong, jungseong, or jongseong.`
);

const sourceJamos = disassembleHangulToGroups(source)[0];
Expand All @@ -119,29 +119,29 @@ export function binaryAssembleHangulCharacters(source: string, nextCharacter: st

const [restJamos, lastJamo] = excludeLastElement(sourceJamos);

const needLinking = canBeChosung(lastJamo) && canBeJungsung(nextCharacter);
const needLinking = canBeChoseong(lastJamo) && canBeJungseong(nextCharacter);
if (needLinking) {
return linkHangulCharacters(source, nextCharacter);
}

const fixConsonant = curriedCombineHangulCharacter;
const combineJungsung = fixConsonant(restJamos[0]);
const combineJungseong = fixConsonant(restJamos[0]);

if (canBeJungsung(`${lastJamo}${nextCharacter}`)) {
return combineJungsung(`${lastJamo}${nextCharacter}`)();
if (canBeJungseong(`${lastJamo}${nextCharacter}`)) {
return combineJungseong(`${lastJamo}${nextCharacter}`)();
}

if (canBeJungsung(lastJamo) && canBeJongsung(nextCharacter)) {
return combineJungsung(lastJamo)(nextCharacter);
if (canBeJungseong(lastJamo) && canBeJongseong(nextCharacter)) {
return combineJungseong(lastJamo)(nextCharacter);
}

const fixVowel = combineJungsung;
const combineJongsung = fixVowel(restJamos[1]);
const fixVowel = combineJungseong;
const combineJongseong = fixVowel(restJamos[1]);

const lastConsonant = lastJamo;

if (hasSingleBatchim(source) && canBeJongsung(`${lastConsonant}${nextCharacter}`)) {
return combineJongsung(`${lastConsonant}${nextCharacter}`);
if (hasSingleBatchim(source) && canBeJongseong(`${lastConsonant}${nextCharacter}`)) {
return combineJongseong(`${lastConsonant}${nextCharacter}`);
}

return joinString(source, nextCharacter);
Expand Down
18 changes: 9 additions & 9 deletions src/chosungIncludes.spec.ts → src/choseongIncludes.spec.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
import { chosungIncludes } from './chosungIncludes';
import { choseongIncludes } from './choseongIncludes';

describe('chosungIncludes', () => {
describe('choseongIncludes', () => {
describe('초성이 포함되어있다고 판단되는 경우', () => {
it('"ㅍㄹㅌ" 문자열로 "프론트엔드"를 검색하면 true를 반환한다.', () => {
expect(chosungIncludes('프론트엔드', 'ㅍㄹㅌ')).toBe(true);
expect(choseongIncludes('프론트엔드', 'ㅍㄹㅌ')).toBe(true);
});

it('"ㅍㄹㅌ" 문자열로 "00프론트엔드"를 검색하면 true를 반환한다.', () => {
expect(chosungIncludes('00프론트엔드', 'ㅍㄹㅌ')).toBe(true);
expect(choseongIncludes('00프론트엔드', 'ㅍㄹㅌ')).toBe(true);
});

it('"ㅍㄹㅌㅇㄷㄱㅂㅈ" 문자열로 "프론트엔드 개발자"를 검색하면 true를 반환한다.', () => {
expect(chosungIncludes('프론트엔드 개발자', 'ㅍㄹㅌㅇㄷㄱㅂㅈ')).toBe(true);
expect(choseongIncludes('프론트엔드 개발자', 'ㅍㄹㅌㅇㄷㄱㅂㅈ')).toBe(true);
});

it('"ㅍㄹㅌㅇㄷ ㄱㅂㅈ" 문자열로 "프론트엔드 개발자"를 검색하면 true를 반환한다.', () => {
expect(chosungIncludes('프론트엔드 개발자', 'ㅍㄹㅌㅇㄷ ㄱㅂㅈ')).toBe(true);
expect(choseongIncludes('프론트엔드 개발자', 'ㅍㄹㅌㅇㄷ ㄱㅂㅈ')).toBe(true);
});
});

describe('초성이 포함되어있다고 판단되지 않는 경우', () => {
it('"ㅍㅌ" 문자열로 "프론트엔드"를 검색하면 false를 반환한다.', () => {
expect(chosungIncludes('프론트엔드', 'ㅍㅌ')).toBe(false);
expect(choseongIncludes('프론트엔드', 'ㅍㅌ')).toBe(false);
});

it('빈 문자열로 "프론트엔드 개발자"를 검색하면 false를 반환한다.', () => {
expect(chosungIncludes('프론트엔드 개발자', ' ')).toBe(false);
expect(choseongIncludes('프론트엔드 개발자', ' ')).toBe(false);
});

it('"푸롴트" 문자열로 "프론트엔드"를 검색하면 초성으로만 구성되어 있지 않아 false를 반환한다.', () => {
expect(chosungIncludes('프론트엔드', '푸롴트')).toBe(false);
expect(choseongIncludes('프론트엔드', '푸롴트')).toBe(false);
});
});
});
29 changes: 29 additions & 0 deletions src/choseongIncludes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { disassembleHangulToGroups } from './disassemble';
import { canBeChoseong, getChoseong } from './utils';

export function choseongIncludes(x: string, y: string) {
const trimmedY = y.replace(/\s/g, '');

if (!isOnlyChoseong(trimmedY)) {
return false;
}

const choseongX = getChoseong(x).replace(/\s/g, '');
const choseongY = trimmedY;

return choseongX.includes(choseongY);
}

/*
* @description 문자열이 한글초성으로만 주어진 경우
*/
export function isOnlyChoseong(str: string) {
const groups = disassembleHangulToGroups(str);
if (groups.length === 0) {
return false;
}

return groups.every(disassembled => {
return disassembled.length === 1 && canBeChoseong(disassembled[0]);
});
}
29 changes: 9 additions & 20 deletions src/chosungIncludes.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,18 @@
import { disassembleHangulToGroups } from './disassemble';
import { canBeChosung, getChosung } from './utils';
import { isOnlyChoseong } from './choseongIncludes';
import { getChoseong } from './utils';

/**
* @deprecated choseongIncludes를 사용해 주세요.
*/
export function chosungIncludes(x: string, y: string) {
const trimmedY = y.replace(/\s+/g, '');

if (!isOnlyChosung(trimmedY)) {
if (!isOnlyChoseong(trimmedY)) {
return false;
}

const chosungX = getChosung(x).replace(/\s+/g, '');
const chosungY = trimmedY;

return chosungX.includes(chosungY);
}

/*
* @description 문자열이 한글초성으로만 주어진 경우
*/
function isOnlyChosung(str: string) {
const groups = disassembleHangulToGroups(str);
if (groups.length === 0) {
return false;
}
const choseongX = getChoseong(x).replace(/\s/g, '');
const choseongY = trimmedY;

return groups.every(disassembled => {
return disassembled.length === 1 && canBeChosung(disassembled[0]);
});
return choseongX.includes(choseongY);
}
8 changes: 4 additions & 4 deletions src/combineHangulCharacter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
HANGUL_CHARACTERS_BY_LAST_INDEX,
HANGUL_CHARACTERS_BY_MIDDLE_INDEX,
} from './constants';
import { canBeChosung, canBeJongsung, canBeJungsung } from './utils';
import { canBeChoseong, canBeJongseong, canBeJungseong } from './utils';

/**
* @name combineHangulCharacter
Expand All @@ -27,9 +27,9 @@ import { canBeChosung, canBeJongsung, canBeJungsung } from './utils';
*/
export function combineHangulCharacter(firstCharacter: string, middleCharacter: string, lastCharacter = '') {
if (
canBeChosung(firstCharacter) === false ||
canBeJungsung(middleCharacter) === false ||
canBeJongsung(lastCharacter) === false
canBeChoseong(firstCharacter) === false ||
canBeJungseong(middleCharacter) === false ||
canBeJongseong(lastCharacter) === false
) {
throw new Error(`Invalid hangul Characters: ${firstCharacter}, ${middleCharacter}, ${lastCharacter}`);
}
Expand Down
6 changes: 3 additions & 3 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const COMPLETE_HANGUL_START_CHARCODE = '가'.charCodeAt(0);
export const COMPLETE_HANGUL_END_CHARCODE = '힣'.charCodeAt(0);
export const NUMBER_OF_JONGSUNG = 28;
export const NUMBER_OF_JUNGSUNG = 21;
export const NUMBER_OF_JONGSEONG = 28;
export const NUMBER_OF_JUNGSEONG = 21;

const _JASO_HANGUL_NFD = [...'각힣'.normalize('NFD')].map(char => char.charCodeAt(0)); // NFC 에 정의되지 않은 문자는 포함하지 않음
export const JASO_HANGUL_NFD = {
Expand All @@ -11,7 +11,7 @@ export const JASO_HANGUL_NFD = {
END_CHOSEONG: _JASO_HANGUL_NFD[3], // ㅎ
END_JUNGSEONG: _JASO_HANGUL_NFD[4], // ㅣ
END_JONGSEONG: _JASO_HANGUL_NFD[5], // ㅎ
}
};

/**
* ㄱ -> 'ㄱ'
Expand Down
10 changes: 5 additions & 5 deletions src/disassembleCompleteHangulCharacter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {
HANGUL_CHARACTERS_BY_FIRST_INDEX,
HANGUL_CHARACTERS_BY_LAST_INDEX,
HANGUL_CHARACTERS_BY_MIDDLE_INDEX,
NUMBER_OF_JONGSUNG,
NUMBER_OF_JUNGSUNG,
NUMBER_OF_JONGSEONG,
NUMBER_OF_JUNGSEONG,
} from './constants';

interface ReturnTypeDisassembleCompleteHangulCharacter {
Expand Down Expand Up @@ -41,9 +41,9 @@ export function disassembleCompleteHangulCharacter(

const hangulCode = charCode - COMPLETE_HANGUL_START_CHARCODE;

const lastIndex = hangulCode % NUMBER_OF_JONGSUNG;
const middleIndex = ((hangulCode - lastIndex) / NUMBER_OF_JONGSUNG) % NUMBER_OF_JUNGSUNG;
const firstIndex = Math.floor((hangulCode - lastIndex) / NUMBER_OF_JONGSUNG / NUMBER_OF_JUNGSUNG);
const lastIndex = hangulCode % NUMBER_OF_JONGSEONG;
const middleIndex = ((hangulCode - lastIndex) / NUMBER_OF_JONGSEONG) % NUMBER_OF_JUNGSEONG;
const firstIndex = Math.floor((hangulCode - lastIndex) / NUMBER_OF_JONGSEONG / NUMBER_OF_JUNGSEONG);

return {
first: HANGUL_CHARACTERS_BY_FIRST_INDEX[firstIndex],
Expand Down
Loading
Loading