diff --git a/bindings/wasm/package-demo/index.html b/bindings/wasm/package-demo/index.html index 15e87867..3bfa88cf 100644 --- a/bindings/wasm/package-demo/index.html +++ b/bindings/wasm/package-demo/index.html @@ -3,17 +3,43 @@ - Vite + TS + + Kiwi Demo + + + + + + + + + -

KiwiBuilder/Kiwi Test Page

+
+ +
Loading...
+
-

Usage

-

Open the browser console to interact with KiwiBuilder

-

The default model files are available as modelFiles

-

To get started with a Kiwi instance use the following:

-

kiwi = await builder.build({ modelFiles })

+ - + + + + + + + + + + diff --git a/bindings/wasm/package-demo/public/logo.png b/bindings/wasm/package-demo/public/logo.png new file mode 100644 index 00000000..5ece1411 Binary files /dev/null and b/bindings/wasm/package-demo/public/logo.png differ diff --git a/bindings/wasm/package-demo/src/index.ts b/bindings/wasm/package-demo/src/index.ts new file mode 100644 index 00000000..35c0757e --- /dev/null +++ b/bindings/wasm/package-demo/src/index.ts @@ -0,0 +1,69 @@ +import { WorkerRequest, WorkerResponse } from './worker.js'; +import { TokenInfo } from 'kiwi-nlp'; + +const elVersion = document.getElementById('version')!; +const elInput = document.getElementById('input') as HTMLInputElement; +const elResultTable = document.getElementById('result') as HTMLTableElement; + +const worker = new Worker( + new URL('./worker.ts', import.meta.url), + { type: 'module' } +); + +worker.onmessage = (event) => { + const response: WorkerResponse = event.data; + + switch (response.type) { + case 'inited': + inited(response.version); + break; + case 'analyzed': + analyzed(response.result, response.text); + break; + default: + console.error('Unknown worker message'); + break; + } +}; + +function sendWorkerRequest(request: WorkerRequest) { + worker.postMessage(request); +} + +sendWorkerRequest({ type: 'init' }); + +function inited(version: string) { + elVersion.innerText = 'v' + version; + + elInput.hidden = false; + elInput.addEventListener('input', analyze); + analyze(); +} + +function analyze() { + const text = elInput.value; + worker.postMessage({ type: 'analyze', text }); +} + +function analyzed(tokenInfos: TokenInfo[], text: string) { + while (elResultTable.rows.length > 1) { + elResultTable.deleteRow(1); + } + + for (const tokenInfo of tokenInfos) { + const surface = text.substring( + tokenInfo.position, + tokenInfo.position + tokenInfo.length + ); + + const row = elResultTable.insertRow(); + row.insertCell().innerText = tokenInfo.position.toString(); + row.insertCell().innerText = tokenInfo.length.toString(); + row.insertCell().innerText = surface; + row.insertCell().innerText = tokenInfo.str; + row.insertCell().innerText = tokenInfo.tag; + row.insertCell().innerText = tokenInfo.score.toString(); + } + + elResultTable.hidden = tokenInfos.length === 0; +} diff --git a/bindings/wasm/package-demo/src/main.ts b/bindings/wasm/package-demo/src/main.ts deleted file mode 100644 index 3ffc6ae5..00000000 --- a/bindings/wasm/package-demo/src/main.ts +++ /dev/null @@ -1,27 +0,0 @@ -import './style.css'; - -import * as lib from 'kiwi-nlp'; -import { KiwiBuilder } from 'kiwi-nlp'; - -import kiwiWasmPath from 'kiwi-nlp/dist/kiwi-wasm.wasm?url'; - -import { modelFiles } from './modelFiles'; - -function setGlobal(key: string, value: any) { - // @ts-ignore - globalThis[key] = value; -} - -setGlobal('lib', lib); -for (const [key, value] of Object.entries(lib)) { - setGlobal(key, value); -} - -async function init() { - const builder = await KiwiBuilder.create(kiwiWasmPath); - setGlobal('builder', builder); - -} - -setGlobal('modelFiles', modelFiles); -init(); diff --git a/bindings/wasm/package-demo/src/style.css b/bindings/wasm/package-demo/src/style.css index 793bd15f..eae743e3 100644 --- a/bindings/wasm/package-demo/src/style.css +++ b/bindings/wasm/package-demo/src/style.css @@ -1,11 +1,77 @@ -:root { - background-color: #ffffff; - color: #000000; +* { + box-sizing: border-box; } -@media (prefers-color-scheme: dark) { - :root { - color: #efefef; - background-color: #101418; - } +html { + display: flex; + justify-content: center; +} + +body { + width: min(100%, 800px); + padding: 1rem; + + background-color: #ffffff; + color: #000000; + + font-family: "Noto Sans KR", sans-serif; + font-optical-sizing: auto; + font-weight: 400; + font-style: normal; + + display: flex; + flex-direction: column; + gap: 1rem; + +} + +.title-wrap { + display: flex; + flex-direction: row; + gap: 1rem; + align-items: center; + justify-content: space-between; +} + +.logo { + width: 15rem; +} + +#input { + width: 100%; + padding: 0.5rem; + font-size: 1rem; + + appearance: none; + border: 1px solid #ccc; + border-radius: 0.25rem; +} + +#input:focus { + outline: 2px solid #0078d4; +} + +#result { + width: 100%; + border-collapse: collapse; + border-style: hidden; + border-radius: 0.25rem; + box-shadow: 0 0 0 1px #ccc; + padding: 0; +} + +#result tr:not(:first-child) { + border-top: 1px solid #ccc; +} + +#result td, +#result th { + padding: 0.5rem; + border: none; +} + +#result th { + text-align: left; + font-weight: 400; + background-color: #f0f0f0; } diff --git a/bindings/wasm/package-demo/src/worker.ts b/bindings/wasm/package-demo/src/worker.ts new file mode 100644 index 00000000..5ce70ab5 --- /dev/null +++ b/bindings/wasm/package-demo/src/worker.ts @@ -0,0 +1,50 @@ +import { KiwiBuilder, Kiwi, TokenInfo } from 'kiwi-nlp'; +import kiwiWasmPath from 'kiwi-nlp/dist/kiwi-wasm.wasm?url'; +import { modelFiles } from './modelFiles'; + +let kiwiBuilder: KiwiBuilder | null = null; +let kiwi: Kiwi | null = null; +let version: string | null = null; + +export type WorkerRequest = + | { type: 'init' } + | { type: 'analyze'; text: string }; +export type WorkerResponse = + | { type: 'inited'; version: string } + | { type: 'analyzed'; result: TokenInfo[]; text: string }; + +function sendResponse(response: WorkerResponse) { + self.postMessage(response); +} + +async function init() { + kiwiBuilder = await KiwiBuilder.create(kiwiWasmPath); + version = kiwiBuilder.version(); + kiwi = await kiwiBuilder.build({ modelFiles }); + + sendResponse({ type: 'inited', version }); +} + +function analyze(text: string) { + if (!kiwi) { + throw new Error('Kiwi is not initialized'); + } + + const result = kiwi.tokenize(text); + sendResponse({ type: 'analyzed', result, text }); +} + +self.onmessage = (event) => { + const request: WorkerRequest = event.data; + + switch (request.type) { + case 'init': + init(); + break; + case 'analyze': + analyze(request.text); + break; + default: + throw new Error('Unknown request type'); + } +}; diff --git a/bindings/wasm/package/src/kiwi-builder.ts b/bindings/wasm/package/src/kiwi-builder.ts index 68f3364e..9d86af85 100644 --- a/bindings/wasm/package/src/kiwi-builder.ts +++ b/bindings/wasm/package/src/kiwi-builder.ts @@ -120,4 +120,12 @@ export class KiwiBuilder { }, }) as Kiwi; } + + /** + * Get the version of the Kiwi wasm module. + * @returns The version of the Kiwi wasm module. + */ + version(): string { + return this.api.cmd({ method: 'version', args: [] }) as string; + } }