Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
50 changes: 50 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Deploy site

on:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: true

jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v5

- uses: actions/setup-node@v5
with:
node-version: 22
cache: npm

- run: npm ci
- run: npm run build

- name: Assemble site
run: |
mkdir -p _site
cp -r site/. _site/
cp dist/kokey.global.js _site/
cp dist/kokey.global.js.map _site/

- uses: actions/configure-pages@v5
with:
enablement: true

- uses: actions/upload-pages-artifact@v3
with:
path: _site

- id: deployment
uses: actions/deploy-pages@v4
22 changes: 21 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
# Changelog

## 0.2.0 (2026-07-05)

### Added

- **DOM layer** — `bind(el, mode?)` and `observe(root?)` enforce an input
mode on `<input data-hangul="ko|en">` regardless of IME state.
Composition-safe (never touches the value mid-IME-composition), cursor
preserved via prefix conversion.
**DOM 레이어** — IME 상태와 무관하게 인풋 모드 강제. 조합 중 미개입,
커서 보존.
- **Browser global build** — `dist/kokey.global.js` (IIFE, minified) with
`unpkg`/`jsdelivr` fields, usable via
`<script src="https://cdn.jsdelivr.net/npm/@devslab/kokey/dist/kokey.global.js">`.
브라우저 전역 빌드 — CDN `<script>` 한 줄로 사용 가능.
- **Homepage** — live demo at https://devslab-kr.github.io/kokey/
(GitHub Pages, deployed on every main push).

## 0.1.0 (2026-07-05)

Initial release. / 최초 릴리스.
Initial release, published as **`@devslab/kokey`** — npm's name-similarity
rule blocks the unscoped name `kokey` (too similar to `hdkey`).
최초 릴리스, **`@devslab/kokey`** 로 발행 — unscoped `kokey`는 npm 유사 이름
규칙(`hdkey`와 유사)에 걸려 사용 불가.

### Added

Expand Down
40 changes: 34 additions & 6 deletions README.ko.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# kokey

[![npm](https://img.shields.io/npm/v/kokey)](https://www.npmjs.com/package/kokey)
[![npm](https://img.shields.io/npm/v/%40devslab%2Fkokey)](https://www.npmjs.com/package/@devslab/kokey)
[![CI](https://github.com/devslab-kr/kokey/actions/workflows/ci.yml/badge.svg)](https://github.com/devslab-kr/kokey/actions/workflows/ci.yml)
[![license](https://img.shields.io/npm/l/kokey)](./LICENSE)
[![license](https://img.shields.io/npm/l/%40devslab%2Fkokey)](./LICENSE)

한↔영 자판 변환 라이브러리 (두벌식 ↔ QWERTY).
TypeScript-first, **zero-dependency**, ESM/CJS 듀얼 패키지.
Expand All @@ -17,13 +17,23 @@ TypeScript-first, **zero-dependency**, ESM/CJS 듀얼 패키지.
## 설치

```sh
npm install kokey
npm install @devslab/kokey
```

CDN으로 빌드 없이 바로 — 전부 `kokey` 전역 아래에 노출됩니다:

```html
<script src="https://cdn.jsdelivr.net/npm/@devslab/kokey/dist/kokey.global.js"></script>
<script>
kokey.enToKo('dkssud') // '안녕'
kokey.observe() // <input data-hangul> 전부 자동 바인딩
</script>
```

## 사용법

```ts
import { koToEn, enToKo } from 'kokey'
import { koToEn, enToKo } from '@devslab/kokey'

// 한글 → 그 한글을 만든 QWERTY 키 시퀀스
koToEn('안녕') // 'dkssud'
Expand All @@ -44,20 +54,38 @@ enToKo('ekfrl') // '달기' (겹받침 분해 — 실제 IME와 동일
- **통과 처리**: 숫자·문장부호·미매핑 문자는 그대로 유지
- 한글 텍스트 왕복 보장: `enToKo(koToEn(s)) === s`

### DOM 레이어 — 입력 모드 강제

사용자 IME 상태와 무관하게 `<input>`/`<textarea>`를 특정 모드로 고정합니다 —
타이핑하는 대로 변환되고, IME 조합 중엔 건드리지 않으며, 커서가 보존됩니다:

```html
<input data-hangul="ko"> <!-- 영타가 한글로 조합됨 -->
<input data-hangul="en"> <!-- 한글 IME가 켜져 있어도 QWERTY로 복원 -->
```

```ts
import { bind, observe } from '@devslab/kokey'

observe() // 현재 + 이후 추가되는 [data-hangul] 전부 바인딩
const unbind = bind(el, 'en') // 개별 엘리먼트 명시 바인딩
```

## API

| 함수 | 시그니처 | 설명 |
| --- | --- | --- |
| `koToEn` | `(text: string) => string` | 한글 음절/자모를 두벌식 QWERTY 키 시퀀스로 분해 |
| `enToKo` | `(text: string) => string` | QWERTY 키 시퀀스를 표준 IME 오토마타로 한글 조합 |
| `bind` | `(el, mode?) => unbind` | 인풋 하나에 모드 강제 (mode 생략 시 `data-hangul` 속성값) |
| `observe` | `(root?) => stop` | `root` 아래 `[data-hangul]` 전부 바인딩 + MutationObserver로 감시 |

저수준 테이블(`CHOSUNG`, `JUNGSUNG`, `JONGSUNG`, `JAMO_TO_KEY`,
`KEY_TO_JAMO`)도 export 됩니다.

## 로드맵

- `v0.2` — DOM 레이어: `<input data-hangul="ko|en">` 입력 강제
(IME `compositionend` 처리 + 커서 보존), `observe(document)` 자동 바인딩
- ~~`v0.2` — DOM 레이어~~ ✅ 출시됨
- `v0.3` — Vue 디렉티브 / React 훅

## inko가 아닌 이유
Expand Down
42 changes: 35 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# kokey

[![npm](https://img.shields.io/npm/v/kokey)](https://www.npmjs.com/package/kokey)
[![npm](https://img.shields.io/npm/v/%40devslab%2Fkokey)](https://www.npmjs.com/package/@devslab/kokey)
[![CI](https://github.com/devslab-kr/kokey/actions/workflows/ci.yml/badge.svg)](https://github.com/devslab-kr/kokey/actions/workflows/ci.yml)
[![license](https://img.shields.io/npm/l/kokey)](./LICENSE)
[![license](https://img.shields.io/npm/l/%40devslab%2Fkokey)](./LICENSE)

Korean ↔ English keyboard layout converter (Dubeolsik ↔ QWERTY).
TypeScript-first, **zero dependencies**, ESM/CJS dual package.
Expand All @@ -17,13 +17,23 @@ directions, exactly the way a Dubeolsik IME composes Hangul.
## Install

```sh
npm install kokey
npm install @devslab/kokey
```

Or straight from a CDN — no build step, everything under the `kokey` global:

```html
<script src="https://cdn.jsdelivr.net/npm/@devslab/kokey/dist/kokey.global.js"></script>
<script>
kokey.enToKo('dkssud') // '안녕'
kokey.observe() // auto-bind every <input data-hangul>
</script>
```

## Usage

```ts
import { koToEn, enToKo } from 'kokey'
import { koToEn, enToKo } from '@devslab/kokey'

// Hangul → the QWERTY keystrokes that produced it
koToEn('안녕') // 'dkssud'
Expand All @@ -44,21 +54,39 @@ enToKo('ekfrl') // '달기' (compound-final split, like a real IME)
- **Pass-through**: digits, punctuation, and unmapped letters are left as-is
- Round-trip safe for Korean text: `enToKo(koToEn(s)) === s`

### DOM layer — enforce an input mode

Force an `<input>`/`<textarea>` to a specific mode regardless of the user's
IME state — the field converts as you type, composition-safe, cursor
preserved:

```html
<input data-hangul="ko"> <!-- QWERTY keystrokes compose into Hangul -->
<input data-hangul="en"> <!-- Hangul (IME left on) restored to QWERTY -->
```

```ts
import { bind, observe } from '@devslab/kokey'

observe() // bind all [data-hangul] now + watch for new ones
const unbind = bind(el, 'en') // or bind a single element explicitly
```

## API

| Function | Signature | Description |
| --- | --- | --- |
| `koToEn` | `(text: string) => string` | Decompose Hangul syllables/jamo into their Dubeolsik QWERTY key sequence |
| `enToKo` | `(text: string) => string` | Compose QWERTY key sequence into Hangul via the standard IME automaton |
| `bind` | `(el, mode?) => unbind` | Enforce a mode on one input/textarea (mode defaults to its `data-hangul` attribute) |
| `observe` | `(root?) => stop` | Bind every `[data-hangul]` under `root` and keep watching via MutationObserver |

Low-level tables (`CHOSUNG`, `JUNGSUNG`, `JONGSUNG`, `JAMO_TO_KEY`,
`KEY_TO_JAMO`) are exported for advanced use.

## Roadmap

- `v0.2` — DOM layer: `<input data-hangul="ko|en">` input enforcement
(IME `compositionend` handling + cursor preservation), `observe(document)`
auto-binding
- ~~`v0.2` — DOM layer~~ ✅ shipped
- `v0.3` — Vue directive / React hook

## Why not inko?
Expand Down
Loading