Multiplatform Hangul processor library for Kotlin & JS projects, based on reverse-engineered Branah keyboard algorithm. Supported platforms:
- JS (Node, Browser)
- Kotlin (JVM, JS, Native)
Install khangul npm package:
$ npm i khangulImport HangulContext:
import { HangulContext } from 'khangul'Create a new instance of HangulContext and use it to process Hangul:
const hangulContext = new HangulContext()
console.log(hangulContext.getValue()) // ''
hangulContext.appendLetter('γ
')
hangulContext.appendLetter('γ
')
hangulContext.appendLetter('γ΄')
console.log(hangulContext.getValue()) // μ
hangulContext.removeLastLetter()
console.log(hangulContext.getValue()) // μEach jamo is exposed as a Letter with character, name, romanization, and category.
The Letters registry provides them as named constants and grouped lists:
Letters.γ±.character // 'γ±'
Letters.γ±.name // 'giyeok'
Letters.γ±.romanization // ['g', 'k']
Letters.consonants // [γ±, γ΄, γ·, ...]
Letters.tenseConsonants // [γ², γΈ, γ
, ...]
Letters.vowels // [γ
, γ
, γ
, ...]
Letters.complexVowels // [γ
, γ
, γ
, ...]
Letters.findByCharacter('γ
')
Letters.getAll()
// output: [ ...consonants, ...tenseConsonants, ...vowels, ...complexVowels ]
Hangul.generateRandomSyllable()
// example output: λ²Ό, μΌ, λ·°, ν°, μ΄, ν¬, μ₯¬, μ, μ°HangulRecognizer identifies hand-drawn jamo from canvas paths and validates
guided stroke-by-stroke input. A live demo is available at
dzikoysk.github.io/khangul.
import { Letters, experimental } from 'khangul'
const recognizer = new experimental.recognition.HangulRecognizer()Free draw β pass an array of strokes (each stroke is a sequence of {x, y}
points captured from a canvas) and get back a ranked list of letter matches with
a 0β100 coverage score:
const paths = [[{x: 20, y: 25}, {x: 80, y: 25}, {x: 80, y: 80}]]
const results = recognizer.recognizeFromArrays(paths)
results[0].letter.character // 'γ±'
results[0].coverage // 0β100Guided mode β for tutorial-style UIs where the user is asked to draw a
specific letter one step at a time. Validates that the points the user just
drew match the expected shape and position of step stepIndex of the target
letter, scaled to your canvas size in pixels:
recognizer.validateGuidedStrokeFromArray(userPoints, Letters.γ±, 0, canvasSize)Reference geometry β query the built-in stroke templates for any letter. Each letter is broken down into a list of "steps" (one pen-down/up action), and each step contains one or more connected segments. Useful for rendering guides or animating stroke order:
recognizer.getStepCount(Letters.γΉ) // 3 β γΉ takes three pen strokes
recognizer.getStepSegments(Letters.γΉ, 0) // segments drawn during step 0
recognizer.sampleReferenceStroke(stroke, 40) // 40 evenly-spaced points along a segmentThe library handles natural Hangul input, so its main use-case is to be used in text editors, chat apps, etc. As an example, there's a preview of react-simple-keyboard component integrated with our Hangul context & compatibile keyboard layout:
import { HangulContext } from "khangul"
import Keyboard from 'react-simple-keyboard'
const hangulContext = useRef(new HangulContext())
const keyboard = useRef(null as unknown as SimpleKeyboard)
const [userInput, setUserInput] = useState('')
const [layoutName, setLayoutName] = useState('default')
const onKeyPress = (button: string) => {
if (button === "{shift}" || button === "{lock}") {
setLayoutName(layoutName === "default" ? "shift" : "default")
return
}
else if (button === "{bksp}") {
hangulContext.current.removeLastLetter()
setUserInput(hangulContext.current.getValue())
return
}
hangulContext.current.appendLetter(button)
setUserInput(hangulContext.current.getValue())
}
return (
<>
<Input
placeholder='Type here...'
value={userInput}
onChange={() => {}}
/>
<Keyboard
keyboardRef={ref => (keyboard.current = ref)}
enableLayoutCandidates={false}
layoutName={layoutName}
onChange={() => {}}
onKeyPress={onKeyPress}
layout={{
default: [
"` 1 2 3 4 5 6 7 8 9 0 - = {bksp}",
"{tab} γ
γ
γ· γ± γ
γ
γ
γ
γ
γ
[ ] \\",
"{lock} γ
γ΄ γ
γΉ γ
γ
γ
γ
γ
£ ; ' {enter}",
"{shift} γ
γ
γ
γ
γ
γ
γ
‘ , . / {shift}",
".com @ {space}",
],
shift: [
"~ ! @ # $ % ^ & * ( ) _ + {bksp}",
"{tab} γ
γ
γΈ γ² γ
γ
γ
{ } |",
'{lock} : " {enter}',
"{shift} | < > ? {shift}",
".com @ {space}",
],
}}
/>
</>
)