@daeinc/hangul
Version:
Hangul utilities
475 lines (462 loc) • 14.6 kB
JavaScript
import { assemble as assemble$1, canBeJongseong as canBeJongseong$1, disassembleCompleteCharacter, disassemble as disassemble$1 } from 'es-hangul';
/*! @daeinc/hangul@0.10.0 by Daeinc - MIT */
/*!
* @daeinc/hangul v0.10.0 | MIT
* Find third-party licenses in LICENSE.txt
*/
// src/consonants.ts
var CHOSEONGS = [
"\u3131",
"\u3132",
"\u3134",
"\u3137",
"\u3138",
"\u3139",
"\u3141",
"\u3142",
"\u3143",
"\u3145",
"\u3146",
"\u3147",
"\u3148",
"\u3149",
"\u314A",
"\u314B",
"\u314C",
"\u314D",
"\u314E"
];
var JUNGSEONGS = [
"\u314F",
"\u3150",
"\u3151",
"\u3152",
"\u3153",
"\u3154",
"\u3155",
"\u3156",
"\u3157",
"\u3157\u314F",
"\u3157\u3150",
"\u3157\u3163",
"\u315B",
"\u315C",
"\u315C\u3153",
"\u315C\u3154",
"\u315C\u3163",
"\u3160",
"\u3161",
"\u3161\u3163",
"\u3163"
];
var JONGSEONGS_DISASSEMBLED = [
"",
"\u3131",
"\u3132",
"\u3131\u3145",
"\u3134",
"\u3134\u3148",
"\u3134\u314E",
"\u3137",
"\u3139",
"\u3139\u3131",
"\u3139\u3141",
"\u3139\u3142",
"\u3139\u3145",
"\u3139\u314C",
"\u3139\u314D",
"\u3139\u314E",
"\u3141",
"\u3142",
"\u3142\u3145",
"\u3145",
"\u3146",
"\u3147",
"\u3148",
"\u314A",
"\u314B",
"\u314C",
"\u314D",
"\u314E"
];
var VOWELS_VERTICAL = [
"\u314F",
"\u3150",
"\u3151",
"\u3152",
"\u3153",
"\u3154",
"\u3155",
"\u3156",
"\u3163"
];
var VOWELS_HORIZONTAL = ["\u3157", "\u315B", "\u315C", "\u3160", "\u3161"];
var VOWELS_COMPOUND = [
"\u3158",
"\u3159",
"\u315A",
"\u315D",
"\u315E",
"\u315F",
"\u3162"
];
var HANGUL_SYLLABLES_START_CHARCODE = 44032;
var HANGUL_SYLLABLES_END_CHARCODE = 55215;
var HANGUL_COMPAT_JAMO_START_CHARCODE = 12592;
var HANGUL_COMPAT_JAMO_END_CHARCODE = 12687;
var HANGUL_COMPAT_CONSONANT_START_CHARCODE = 12593;
var HANGUL_COMPAT_CONSONANT_END_CHARCODE = 12622;
var HANGUL_COMPAT_VOWEL_START_CHARCODE = 12623;
var HANGUL_COMPAT_VOWEL_END_CHARCODE = 12643;
var HANGUL_COMPAT_OLD_CONSONANT_START_CHARCODE = 12645;
var HANGUL_COMPAT_OLD_CONSONANT_END_CHARCODE = 12678;
var HANGUL_COMPAT_OLD_VOWEL_START_CHARCODE = 12679;
var HANGUL_COMPAT_OLD_VOWEL_END_CHARCODE = 12686;
var HANGUL_JAMO_START_CHARCODE = 4352;
var HANGUL_JAMO_END_CHARCODE = 4607;
var HANGUL_JAMO_INITIAL_CONSONANT_START_CHARCODE = 4352;
var HANGUL_JAMO_INITIAL_CONSONANT_END_CHARCODE = 4370;
var HANGUL_JAMO_OLD_INITIAL_CONSONANT_START_CHARCODE = 4371;
var HANGUL_JAMO_OLD_INITIAL_CONSONANT_END_CHARCODE = 4446;
var HANGUL_JAMO_VOWEL_START_CHARCODE = 4449;
var HANGUL_JAMO_VOWEL_END_CHARCODE = 4469;
var HANGUL_JAMO_OLD_VOWEL_START_CHARCODE = 4470;
var HANGUL_JAMO_OLD_VOWEL_END_CHARCODE = 4519;
var HANGUL_JAMO_FINAL_CONSONANT_START_CHARCODE = 4520;
var HANGUL_JAMO_FINAL_CONSONANT_END_CHARCODE = 4546;
var HANGUL_JAMO_OLD_FINAL_CONSONANT_START_CHARCODE = 4547;
var HANGUL_JAMO_OLD_FINAL_CONSONANT_END_CHARCODE = 4607;
var HANGUL_JAMO_EXTENDED_A_START_CHARCODE = 43360;
var HANGUL_JAMO_EXTENDED_A_END_CHARCODE = 43391;
var HANGUL_JAMO_EXTENDED_B_START_CHARCODE = 55216;
var HANGUL_JAMO_EXTENDED_B_END_CHARCODE = 55295;
var HANGUL_JAMO_EXTENDED_B_VOWEL_START_CHARCODE = 55216;
var HANGUL_JAMO_EXTENDED_B_VOWEL_END_CHARCODE = 55238;
var HANGUL_JAMO_EXTENDED_B_CONSONANT_START_CHARCODE = 55243;
var HANGUL_JAMO_EXTENDED_B_CONSONANT_END_CHARCODE = 55291;
// src/isHangul/isHangul.ts
var isHangul = (ch, opts) => {
if (ch.length > 1) {
console.warn(`Only the first character ("${ch[0]}") will be processed.`);
ch = ch[0];
}
const options = {
jamo: false,
jamoExtendedA: false,
jamoExtendedB: false,
compatJamo: true,
syllable: true,
...opts
};
return options.syllable && isHangulSyllable(ch) || options.jamo && isHangulJamo(ch) || options.compatJamo && isHangulCompatJamo(ch) || options.jamoExtendedA && isHangulJamoExtendedA(ch) || options.jamoExtendedB && isHangulJamoExtendedB(ch);
};
var isHangulSyllable = (ch) => {
const code = ch.charCodeAt(0);
return code >= HANGUL_SYLLABLES_START_CHARCODE && code <= HANGUL_SYLLABLES_END_CHARCODE;
};
var isHangulJamo = (ch) => {
const code = ch.charCodeAt(0);
return code >= HANGUL_JAMO_START_CHARCODE && code <= HANGUL_JAMO_END_CHARCODE;
};
var isHangulCompatJamo = (ch) => {
const code = ch.charCodeAt(0);
return code >= HANGUL_COMPAT_JAMO_START_CHARCODE && code <= HANGUL_COMPAT_JAMO_END_CHARCODE;
};
var isHangulJamoExtendedA = (ch) => {
const code = ch.charCodeAt(0);
return code >= HANGUL_JAMO_EXTENDED_A_START_CHARCODE && code <= HANGUL_JAMO_EXTENDED_A_END_CHARCODE;
};
var isHangulJamoExtendedB = (ch) => {
const code = ch.charCodeAt(0);
return code >= HANGUL_JAMO_EXTENDED_B_START_CHARCODE && code <= HANGUL_JAMO_EXTENDED_B_END_CHARCODE;
};
var isConsonant = (ch) => {
return /^[ㄱ-ㅎ]$/.test(ch);
};
var isVowel = (ch, opts) => {
if (!/^[ㅏ-ㅣ]$/.test(ch)) return false;
const options = {
vertical: true,
horizontal: true,
compound: true,
...opts
};
if (VOWELS_VERTICAL.includes(ch) && !options.vertical) return false;
if (VOWELS_HORIZONTAL.includes(ch) && !options.horizontal)
return false;
if (VOWELS_COMPOUND.includes(ch) && !options.compound) return false;
return true;
};
// src/assemble/assemble.ts
var assemble = (strArr) => {
const str = strArr.join("");
const result = [];
let i = 0;
while (i < str.length) {
const ch = str[i];
if (isHangul(ch)) {
const hangulChars = [ch];
let j = i + 1;
while (j < str.length && isHangul(str[j])) {
hangulChars.push(str[j]);
j++;
}
let numAccChars = hangulChars.length;
while (numAccChars > 0) {
const charsToTry = hangulChars.slice(0, numAccChars);
try {
const assembledEsh = assemble$1(charsToTry);
result.push(assembledEsh);
if (numAccChars < hangulChars.length) {
const remaining = hangulChars.slice(numAccChars);
const assembledRemaining = assemble(remaining);
result.push(assembledRemaining);
}
break;
} catch (err) {
numAccChars--;
}
}
i = j;
} else {
result.push(ch);
i++;
}
}
return result.join("");
};
var _assemble = (strArr) => {
const str = strArr.join("");
const result = [];
let i = 0;
while (i < str.length) {
const ch = str[i];
if (isHangul(ch)) {
const hangulChars = [ch];
let j = i + 1;
while (j < str.length && isHangul(str[j])) {
hangulChars.push(str[j]);
j++;
}
result.push(assemble$1(hangulChars));
i = j;
} else {
result.push(ch);
i++;
}
}
return result.join("");
};
var canBeJongseong = (str) => {
return canBeJongseong$1(str);
};
// src/isJaOrMo/isJaOrMo.ts
var isJaOrMo = (ch) => {
if (ch.length > 1) {
console.warn(`Only the first character ("${ch[0]}") will be processed.`);
ch = ch[0];
}
const code = ch.charCodeAt(0);
if (isHangulJamo(ch)) {
if (code >= HANGUL_JAMO_INITIAL_CONSONANT_START_CHARCODE && code <= HANGUL_JAMO_OLD_INITIAL_CONSONANT_END_CHARCODE || code >= HANGUL_JAMO_FINAL_CONSONANT_START_CHARCODE && code <= HANGUL_JAMO_OLD_FINAL_CONSONANT_END_CHARCODE) {
return "ja";
}
if (code >= HANGUL_JAMO_VOWEL_START_CHARCODE && code <= HANGUL_JAMO_OLD_VOWEL_END_CHARCODE) {
return "mo";
}
}
if (isHangulCompatJamo(ch)) {
if (code >= HANGUL_COMPAT_CONSONANT_START_CHARCODE && code <= HANGUL_COMPAT_CONSONANT_END_CHARCODE) {
return "ja";
}
if (code >= HANGUL_COMPAT_VOWEL_START_CHARCODE && code <= HANGUL_COMPAT_VOWEL_END_CHARCODE) {
return "mo";
}
}
if (isHangulSyllable(ch)) {
return "syllable";
}
return "other";
};
// src/disassemble/disassemble.ts
var disassemble = (str) => {
return Array.from(str).map((ch) => {
if (!isHangul(ch)) {
return ch;
}
const disassembled = disassembleCompleteCharacter(ch);
if (disassembled) {
return disassembled;
} else {
const jamo = isJaOrMo(ch);
if (jamo === "ja") {
return {
// disassemble for consonants such as "ㄳ"
choseong: disassemble$1(ch),
jungseong: "",
jongseong: ""
};
} else if (jamo === "mo") {
return {
choseong: "",
jungseong: disassemble$1(ch),
jongseong: ""
};
}
}
return ch;
});
};
// src/disassembleToJamoString/disassembleToJamoString.ts
var disassembleToJamoString = (phrase) => {
return disassemble(phrase).map(
(v) => typeof v === "object" ? `${v.choseong}${v.jungseong}${v.jongseong}` : v
).join("");
};
// src/hangul-syllable/hangul-syllable.ts
var HangulSyllable = class _HangulSyllable {
char;
disassembled;
id;
constructor(char) {
if (!isHangul(char)) {
console.warn(
`It may be a mistake to store "${char}" in HangulSyllable object`
);
}
this.id = -1;
this.char = char;
if (char) {
this.disassembled = disassemble(char)[0];
} else {
this.disassembled = {
choseong: "",
jungseong: "",
jongseong: ""
};
}
}
setId(id) {
this.id = id;
}
clone() {
return new _HangulSyllable(this.char);
}
isEmpty() {
return !this.hasComponent();
}
hasComponent() {
return this.hasChoseong() || this.hasJungseong() || this.hasJongseong();
}
hasChoseong() {
return this.disassembled.choseong.length > 0;
}
hasJungseong() {
return this.disassembled.jungseong.length > 0;
}
hasJongseong() {
return this.disassembled.jongseong.length > 0;
}
/**
* Removes a single component starting from jongseong, jungseong to choseong.
* If it has a double jongseong or jungseong, it will remove a single one each time.
*
* @example
* const syl = new HangulSyllable("깖");
* syl.removeSingleComponent() // syl.char == "깔"
* syl.removeSingleComponent() // "까"
* syl.removeSingleComponent() // "ㄲ"
* syl.removeSingleComponent() // ""
*/
removeSingleComponent() {
if (this.disassembled.jongseong) {
this.disassembled.jongseong = this.disassembled.jongseong.slice(0, -1);
} else if (this.disassembled.jungseong) {
this.disassembled.jungseong = this.disassembled.jungseong.slice(0, -1);
} else {
this.disassembled.choseong = this.disassembled.choseong.slice(0, -1);
}
this.char = assemble(this.getDisassembledStringArray());
}
/**
* @example
* const syl = new HangulSyllable("깖");
* syl.removeSingleJongseong() // syl.char == "깔"
*
* @example
* const syl = new HangulSyllable("깔");
* syl.removeSingleJongseong() // syl.char == "까"
*/
removeSingleJongseong() {
this.disassembled.jongseong = this.disassembled.jongseong.slice(0, -1);
this.char = assemble(this.getDisassembledStringArray());
}
/**
* Updates `this.char` and `this.disassembled` according to the input `char`
*
* @param char -
*/
updateSyllable(char) {
this.char = char;
if (char) {
this.disassembled = disassemble(char)[0];
} else {
this.disassembled = {
choseong: "",
jungseong: "",
jongseong: ""
};
}
}
/**
* Returns an object with Hangul components
*
* @example
* const syl = new HangulSyllable("깖");
* syl.getDisassembled() // {choseong: "ㄲ", jungseong: "ㅏ", jongseong: "ㄹㅁ"}
*/
getDisassembled() {
return this.disassembled;
}
/**
* Returns an array of each Hangul component. Note that a double Jongseong is broken down.
*
* @example
* const syl = new HangulSyllable("깖");
* syl.getDisassembledStringArray() // ["ㄲ", "ㅏ", "ㄹㅁ"]
*/
getDisassembledStringArray() {
return Object.values(this.disassembled).map((v) => v);
}
/**
* Returns a flattened string each Hangul component. Note that a double Jongseong is broken down.
*
* @example
* const syl = new HangulSyllable("깖");
* syl.getDisassembledString() // "ㄲㅏㄹㅁ"
*/
getDisassembledString() {
return Object.values(this.disassembled).join("");
}
};
// src/isFirstSyllableReady/isFirstSyllableReady.ts
var isFirstSyllableReady = (first, second) => {
if (!second) return false;
if (first.length > 1 || second.length > 1) {
console.warn(
`the input string to "isFirstSyllableReady()" is greater than 1`
);
}
first = first[0];
second = second[0];
if (!isHangul(first) || !isHangul(second)) return true;
const firstDisass = disassemble(first)[0];
const secondDisass = disassemble(second)[0];
if (typeof firstDisass === "object" && typeof secondDisass === "object") {
if (secondDisass.choseong.length > 0 || secondDisass.jungseong.length > 0) {
return true;
}
}
return false;
};
export { CHOSEONGS, HANGUL_COMPAT_CONSONANT_END_CHARCODE, HANGUL_COMPAT_CONSONANT_START_CHARCODE, HANGUL_COMPAT_JAMO_END_CHARCODE, HANGUL_COMPAT_JAMO_START_CHARCODE, HANGUL_COMPAT_OLD_CONSONANT_END_CHARCODE, HANGUL_COMPAT_OLD_CONSONANT_START_CHARCODE, HANGUL_COMPAT_OLD_VOWEL_END_CHARCODE, HANGUL_COMPAT_OLD_VOWEL_START_CHARCODE, HANGUL_COMPAT_VOWEL_END_CHARCODE, HANGUL_COMPAT_VOWEL_START_CHARCODE, HANGUL_JAMO_END_CHARCODE, HANGUL_JAMO_EXTENDED_A_END_CHARCODE, HANGUL_JAMO_EXTENDED_A_START_CHARCODE, HANGUL_JAMO_EXTENDED_B_CONSONANT_END_CHARCODE, HANGUL_JAMO_EXTENDED_B_CONSONANT_START_CHARCODE, HANGUL_JAMO_EXTENDED_B_END_CHARCODE, HANGUL_JAMO_EXTENDED_B_START_CHARCODE, HANGUL_JAMO_EXTENDED_B_VOWEL_END_CHARCODE, HANGUL_JAMO_EXTENDED_B_VOWEL_START_CHARCODE, HANGUL_JAMO_FINAL_CONSONANT_END_CHARCODE, HANGUL_JAMO_FINAL_CONSONANT_START_CHARCODE, HANGUL_JAMO_INITIAL_CONSONANT_END_CHARCODE, HANGUL_JAMO_INITIAL_CONSONANT_START_CHARCODE, HANGUL_JAMO_OLD_FINAL_CONSONANT_END_CHARCODE, HANGUL_JAMO_OLD_FINAL_CONSONANT_START_CHARCODE, HANGUL_JAMO_OLD_INITIAL_CONSONANT_END_CHARCODE, HANGUL_JAMO_OLD_INITIAL_CONSONANT_START_CHARCODE, HANGUL_JAMO_OLD_VOWEL_END_CHARCODE, HANGUL_JAMO_OLD_VOWEL_START_CHARCODE, HANGUL_JAMO_START_CHARCODE, HANGUL_JAMO_VOWEL_END_CHARCODE, HANGUL_JAMO_VOWEL_START_CHARCODE, HANGUL_SYLLABLES_END_CHARCODE, HANGUL_SYLLABLES_START_CHARCODE, HangulSyllable, JONGSEONGS_DISASSEMBLED, JUNGSEONGS, VOWELS_COMPOUND, VOWELS_HORIZONTAL, VOWELS_VERTICAL, _assemble, assemble, canBeJongseong, disassemble, disassembleToJamoString, isConsonant, isFirstSyllableReady, isHangul, isHangulCompatJamo, isHangulJamo, isHangulJamoExtendedA, isHangulJamoExtendedB, isHangulSyllable, isJaOrMo, isVowel };