braille-codec 0.0.1-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.github/workflows/ci.yml +80 -0
  2. package/LICENSE +201 -0
  3. package/README.md +10 -0
  4. package/bin/braille-decode +66 -0
  5. package/dist/decoder/constants/char_english.d.ts +1 -0
  6. package/dist/decoder/constants/char_shortcut.d.ts +1 -0
  7. package/dist/decoder/constants/choseong.d.ts +1 -0
  8. package/dist/decoder/constants/index.d.ts +10 -0
  9. package/dist/decoder/constants/indicators.d.ts +6 -0
  10. package/dist/decoder/constants/jongseong.d.ts +1 -0
  11. package/dist/decoder/constants/jungsong.d.ts +1 -0
  12. package/dist/decoder/constants/number.d.ts +1 -0
  13. package/dist/decoder/constants/symbol.d.ts +1 -0
  14. package/dist/decoder/constants/utils.d.ts +3 -0
  15. package/dist/decoder/index.d.ts +51 -0
  16. package/dist/decoder/index.test.d.ts +1 -0
  17. package/dist/index.cjs +770 -0
  18. package/dist/index.d.ts +53 -0
  19. package/dist/index.mjs +768 -0
  20. package/package.json +38 -0
  21. package/rollup.config.js +18 -0
  22. package/src/decoder/constants/char_english.ts +30 -0
  23. package/src/decoder/constants/char_shortcut.ts +33 -0
  24. package/src/decoder/constants/choseong.ts +18 -0
  25. package/src/decoder/constants/index.ts +110 -0
  26. package/src/decoder/constants/indicators.ts +8 -0
  27. package/src/decoder/constants/jongseong.ts +19 -0
  28. package/src/decoder/constants/jungsong.ts +25 -0
  29. package/src/decoder/constants/number.ts +14 -0
  30. package/src/decoder/constants/symbol.ts +34 -0
  31. package/src/decoder/constants/utils.ts +14 -0
  32. package/src/decoder/index.test.ts +77 -0
  33. package/src/decoder/index.ts +527 -0
  34. package/src/index.ts +3 -0
  35. package/tsconfig.json +16 -0
  36. package/vitest.config.ts +8 -0
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "braille-codec",
3
+ "version": "0.0.1-rc1",
4
+ "description": "Braille encoding and decoding library",
5
+ "main": "dist/index.cjs",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "build": "rollup -c",
10
+ "test": "vitest --run",
11
+ "lint": "eslint . --ext .ts",
12
+ "lint:fix": "eslint . --ext .ts --fix"
13
+ },
14
+ "bin": {
15
+ "braille-decode": "bin/braille-decode"
16
+ },
17
+ "keywords": [
18
+ "braille",
19
+ "BRL"
20
+ ],
21
+ "author": "Joseph Lee <joseph@jc-lab.net>",
22
+ "license": "Apache-2.0",
23
+ "devDependencies": {
24
+ "@rollup/plugin-typescript": "^11.1.6",
25
+ "@types/node": "^20.14.10",
26
+ "@typescript-eslint/eslint-plugin": "^7.16.0",
27
+ "@typescript-eslint/parser": "^7.16.0",
28
+ "eslint": "^8.57.0",
29
+ "eslint-config-prettier": "^9.1.0",
30
+ "eslint-plugin-prettier": "^5.1.3",
31
+ "prettier": "^3.3.2",
32
+ "rollup": "^4.18.0",
33
+ "rollup-plugin-dts": "^6.1.1",
34
+ "tslib": "^2.6.3",
35
+ "typescript": "^5.5.3",
36
+ "vitest": "^1.6.0"
37
+ }
38
+ }
@@ -0,0 +1,18 @@
1
+ import typescript from '@rollup/plugin-typescript';
2
+ import dts from 'rollup-plugin-dts';
3
+
4
+ export default [
5
+ {
6
+ input: 'src/index.ts',
7
+ output: [
8
+ { file: 'dist/index.cjs', format: 'cjs' },
9
+ { file: 'dist/index.mjs', format: 'es' },
10
+ ],
11
+ plugins: [typescript()],
12
+ },
13
+ {
14
+ input: 'src/index.ts',
15
+ output: [{ file: 'dist/index.d.ts', format: 'es' }],
16
+ plugins: [dts()],
17
+ },
18
+ ];
@@ -0,0 +1,30 @@
1
+ import { decodeUnicode } from './utils';
2
+
3
+ export const ENGLISH_ALPHABET: Record<number, string> = {
4
+ [decodeUnicode('⠁')]: 'a',
5
+ [decodeUnicode('⠃')]: 'b',
6
+ [decodeUnicode('⠉')]: 'c',
7
+ [decodeUnicode('⠙')]: 'd',
8
+ [decodeUnicode('⠑')]: 'e',
9
+ [decodeUnicode('⠋')]: 'f',
10
+ [decodeUnicode('⠛')]: 'g',
11
+ [decodeUnicode('⠓')]: 'h',
12
+ [decodeUnicode('⠊')]: 'i',
13
+ [decodeUnicode('⠚')]: 'j',
14
+ [decodeUnicode('⠅')]: 'k',
15
+ [decodeUnicode('⠇')]: 'l',
16
+ [decodeUnicode('⠍')]: 'm',
17
+ [decodeUnicode('⠝')]: 'n',
18
+ [decodeUnicode('⠕')]: 'o',
19
+ [decodeUnicode('⠏')]: 'p',
20
+ [decodeUnicode('⠟')]: 'q',
21
+ [decodeUnicode('⠗')]: 'r',
22
+ [decodeUnicode('⠎')]: 's',
23
+ [decodeUnicode('⠞')]: 't',
24
+ [decodeUnicode('⠥')]: 'u',
25
+ [decodeUnicode('⠧')]: 'v',
26
+ [decodeUnicode('⠺')]: 'w',
27
+ [decodeUnicode('⠭')]: 'x',
28
+ [decodeUnicode('⠽')]: 'y',
29
+ [decodeUnicode('⠵')]: 'z',
30
+ };
@@ -0,0 +1,33 @@
1
+ import { decodeUnicode } from './utils';
2
+
3
+ export const KOREAN_SHORTCUTS: Record<string, string> = {
4
+ [`${decodeUnicode('⠫')}`]: '가',
5
+ [`${decodeUnicode('⠉')}`]: '나',
6
+ [`${decodeUnicode('⠊')}`]: '다',
7
+ [`${decodeUnicode('⠑')}`]: '마',
8
+ [`${decodeUnicode('⠘')}`]: '바',
9
+ [`${decodeUnicode('⠇')}`]: '사',
10
+ [`${decodeUnicode('⠨')}`]: '자',
11
+ [`${decodeUnicode('⠋')}`]: '카',
12
+ [`${decodeUnicode('⠓')}`]: '타',
13
+ [`${decodeUnicode('⠙')}`]: '파',
14
+ [`${decodeUnicode('⠚')}`]: '하',
15
+ [`${decodeUnicode('⠸')},${decodeUnicode('⠎')}`]: '것',
16
+ [`${decodeUnicode('⠹')}`]: '억',
17
+ [`${decodeUnicode('⠾')}`]: '언',
18
+ [`${decodeUnicode('⠞')}`]: '얼',
19
+ [`${decodeUnicode('⠡')}`]: '연',
20
+ [`${decodeUnicode('⠳')}`]: '열',
21
+ [`${decodeUnicode('⠻')}`]: '영',
22
+ [`${decodeUnicode('⠭')}`]: '옥',
23
+ [`${decodeUnicode('⠷')}`]: '온',
24
+ [`${decodeUnicode('⠿')}`]: '옹',
25
+ [`${decodeUnicode('⠛')}`]: '운',
26
+ [`${decodeUnicode('⠯')}`]: '울',
27
+ [`${decodeUnicode('⠵')}`]: '은',
28
+ [`${decodeUnicode('⠮')}`]: '을',
29
+ [`${decodeUnicode('⠟')}`]: '인',
30
+ [`${decodeUnicode('⠠')},${decodeUnicode('⠻')}`]: '성',
31
+ [`${decodeUnicode('⠨')},${decodeUnicode('⠻')}`]: '정',
32
+ [`${decodeUnicode('⠰')},${decodeUnicode('⠻')}`]: '청',
33
+ };
@@ -0,0 +1,18 @@
1
+ import { decodeUnicode } from './utils';
2
+
3
+ export const KOREAN_CHOSEONG: Record<number, string> = {
4
+ [decodeUnicode('⠈')]: 'ㄱ',
5
+ [decodeUnicode('⠉')]: 'ㄴ',
6
+ [decodeUnicode('⠊')]: 'ㄷ',
7
+ [decodeUnicode('⠐')]: 'ㄹ',
8
+ [decodeUnicode('⠑')]: 'ㅁ',
9
+ [decodeUnicode('⠘')]: 'ㅂ',
10
+ [decodeUnicode('⠠')]: 'ㅅ',
11
+ // [decodeUnicode('')]: 'ㅇ', // skip ㅇ of choseong
12
+ [decodeUnicode('⠨')]: 'ㅈ',
13
+ [decodeUnicode('⠰')]: 'ㅊ',
14
+ [decodeUnicode('⠋')]: 'ㅋ',
15
+ [decodeUnicode('⠓')]: 'ㅌ',
16
+ [decodeUnicode('⠙')]: 'ㅍ',
17
+ [decodeUnicode('⠚')]: 'ㅎ',
18
+ };
@@ -0,0 +1,110 @@
1
+ export * from './utils';
2
+ export * from './choseong';
3
+ export * from './jungsong';
4
+ export * from './jongseong';
5
+ export * from './char_shortcut';
6
+ export * from './char_english';
7
+ export * from './number';
8
+ export * from './symbol';
9
+ export * from './indicators';
10
+
11
+ import { decodeUnicode } from './utils'
12
+
13
+ // ASCII Braille to Unicode mapping (Standard North American Braille ASCII)
14
+ // Reference: https://en.wikipedia.org/wiki/Braille_ASCII
15
+ export const ASCII_BRAILLE_MAP: Record<string, number> = {
16
+ ' ': decodeUnicode('⠀'),
17
+ '!': decodeUnicode('⠮'),
18
+ '"': decodeUnicode('⠐'),
19
+ '#': decodeUnicode('⠼'),
20
+ '$': decodeUnicode('⠫'),
21
+ '%': decodeUnicode('⠩'),
22
+ '&': decodeUnicode('⠯'),
23
+ '\'': decodeUnicode('⠄'),
24
+ '(': decodeUnicode('⠷'),
25
+ ')': decodeUnicode('⠾'),
26
+ '*': decodeUnicode('⠡'),
27
+ '+': decodeUnicode('⠬'),
28
+ ',': decodeUnicode('⠠'),
29
+ '-': decodeUnicode('⠤'),
30
+ '.': decodeUnicode('⠨'),
31
+ '/': decodeUnicode('⠌'),
32
+ '0': decodeUnicode('⠴'),
33
+ '1': decodeUnicode('⠂'),
34
+ '2': decodeUnicode('⠆'),
35
+ '3': decodeUnicode('⠒'),
36
+ '4': decodeUnicode('⠲'),
37
+ '5': decodeUnicode('⠢'),
38
+ '6': decodeUnicode('⠖'),
39
+ '7': decodeUnicode('⠶'),
40
+ '8': decodeUnicode('⠦'),
41
+ '9': decodeUnicode('⠔'),
42
+ ':': decodeUnicode('⠱'),
43
+ ';': decodeUnicode('⠰'),
44
+ '<': decodeUnicode('⠣'),
45
+ '=': decodeUnicode('⠿'),
46
+ '>': decodeUnicode('⠜'),
47
+ '?': decodeUnicode('⠹'),
48
+ '@': decodeUnicode('⠈'),
49
+ 'A': decodeUnicode('⠁'),
50
+ 'B': decodeUnicode('⠃'),
51
+ 'C': decodeUnicode('⠉'),
52
+ 'D': decodeUnicode('⠙'),
53
+ 'E': decodeUnicode('⠑'),
54
+ 'F': decodeUnicode('⠋'),
55
+ 'G': decodeUnicode('⠛'),
56
+ 'H': decodeUnicode('⠓'),
57
+ 'I': decodeUnicode('⠊'),
58
+ 'J': decodeUnicode('⠚'),
59
+ 'K': decodeUnicode('⠅'),
60
+ 'L': decodeUnicode('⠇'),
61
+ 'M': decodeUnicode('⠍'),
62
+ 'N': decodeUnicode('⠝'),
63
+ 'O': decodeUnicode('⠕'),
64
+ 'P': decodeUnicode('⠏'),
65
+ 'Q': decodeUnicode('⠟'),
66
+ 'R': decodeUnicode('⠗'),
67
+ 'S': decodeUnicode('⠎'),
68
+ 'T': decodeUnicode('⠞'),
69
+ 'U': decodeUnicode('⠥'),
70
+ 'V': decodeUnicode('⠧'),
71
+ 'W': decodeUnicode('⠺'),
72
+ 'X': decodeUnicode('⠭'),
73
+ 'Y': decodeUnicode('⠽'),
74
+ 'Z': decodeUnicode('⠵'),
75
+ '[': decodeUnicode('⠪'),
76
+ '\\': decodeUnicode('⠳'),
77
+ ']': decodeUnicode('⠻'),
78
+ '^': decodeUnicode('⠘'),
79
+ '_': decodeUnicode('⠸'),
80
+ a: decodeUnicode('⠁'),
81
+ b: decodeUnicode('⠃'),
82
+ c: decodeUnicode('⠉'),
83
+ d: decodeUnicode('⠙'),
84
+ e: decodeUnicode('⠑'),
85
+ f: decodeUnicode('⠋'),
86
+ g: decodeUnicode('⠛'),
87
+ h: decodeUnicode('⠓'),
88
+ i: decodeUnicode('⠊'),
89
+ j: decodeUnicode('⠚'),
90
+ k: decodeUnicode('⠅'),
91
+ l: decodeUnicode('⠇'),
92
+ m: decodeUnicode('⠍'),
93
+ n: decodeUnicode('⠝'),
94
+ o: decodeUnicode('⠕'),
95
+ p: decodeUnicode('⠏'),
96
+ q: decodeUnicode('⠟'),
97
+ r: decodeUnicode('⠗'),
98
+ s: decodeUnicode('⠎'),
99
+ t: decodeUnicode('⠞'),
100
+ u: decodeUnicode('⠥'),
101
+ v: decodeUnicode('⠧'),
102
+ w: decodeUnicode('⠺'),
103
+ x: decodeUnicode('⠭'),
104
+ y: decodeUnicode('⠽'),
105
+ z: decodeUnicode('⠵'),
106
+ '{': decodeUnicode('⠪'),
107
+ '|': decodeUnicode('⠳'),
108
+ '}': decodeUnicode('⠻'),
109
+ '~': decodeUnicode('⠘'),
110
+ };
@@ -0,0 +1,8 @@
1
+ import { decodeUnicode } from './utils';
2
+
3
+ export const NUMBER_INDICATOR = decodeUnicode('⠼');
4
+ export const ENGLISH_INDICATOR = decodeUnicode('⠴');
5
+ export const ENGLISH_TERMINATOR = decodeUnicode('⠲');
6
+ export const UPPERCASE_INDICATOR = decodeUnicode('⠠');
7
+ export const KOREAN_PART_INDICATOR = decodeUnicode('⠿');
8
+ export const KOREAN_CONSONANT_INDICATOR = decodeUnicode('⠸');
@@ -0,0 +1,19 @@
1
+ import { decodeUnicode } from './utils';
2
+
3
+ export const KOREAN_JONGSEONG: Record<number, string> = {
4
+ [decodeUnicode('⠁')]: 'ㄱ',
5
+ [decodeUnicode('⠒')]: 'ㄴ',
6
+ [decodeUnicode('⠔')]: 'ㄷ',
7
+ [decodeUnicode('⠂')]: 'ㄹ',
8
+ [decodeUnicode('⠢')]: 'ㅁ',
9
+ [decodeUnicode('⠃')]: 'ㅂ',
10
+ [decodeUnicode('⠄')]: 'ㅅ',
11
+ [decodeUnicode('⠌')]: 'ㅆ',
12
+ [decodeUnicode('⠶')]: 'ㅇ',
13
+ [decodeUnicode('⠅')]: 'ㅈ',
14
+ [decodeUnicode('⠆')]: 'ㅊ',
15
+ [decodeUnicode('⠖')]: 'ㅋ',
16
+ [decodeUnicode('⠦')]: 'ㅌ',
17
+ [decodeUnicode('⠲')]: 'ㅍ',
18
+ [decodeUnicode('⠴')]: 'ㅎ',
19
+ };
@@ -0,0 +1,25 @@
1
+ import { decodeUnicode } from './utils';
2
+
3
+ export const KOREAN_JUNGSEONG: Record<string, string> = {
4
+ [`${decodeUnicode('⠣')}`]: 'ㅏ',
5
+ [`${decodeUnicode('⠜')}`]: 'ㅑ',
6
+ [`${decodeUnicode('⠎')}`]: 'ㅓ',
7
+ [`${decodeUnicode('⠱')}`]: 'ㅕ',
8
+ [`${decodeUnicode('⠥')}`]: 'ㅗ',
9
+ [`${decodeUnicode('⠬')}`]: 'ㅛ',
10
+ [`${decodeUnicode('⠍')}`]: 'ㅜ',
11
+ [`${decodeUnicode('⠩')}`]: 'ㅠ',
12
+ [`${decodeUnicode('⠪')}`]: 'ㅡ',
13
+ [`${decodeUnicode('⠕')}`]: 'ㅣ',
14
+ [`${decodeUnicode('⠗')}`]: 'ㅐ',
15
+ [`${decodeUnicode('⠝')}`]: 'ㅔ',
16
+ [`${decodeUnicode('⠽')}`]: 'ㅚ',
17
+ [`${decodeUnicode('⠧')}`]: 'ㅘ',
18
+ [`${decodeUnicode('⠏')}`]: 'ㅝ',
19
+ [`${decodeUnicode('⠺')}`]: 'ㅢ',
20
+ [`${decodeUnicode('⠌')}`]: 'ㅖ',
21
+ [`${decodeUnicode('⠍')},${decodeUnicode('⠗')}`]: 'ㅟ',
22
+ [`${decodeUnicode('⠜')},${decodeUnicode('⠗')}`]: 'ㅒ',
23
+ [`${decodeUnicode('⠧')},${decodeUnicode('⠗')}`]: 'ㅙ',
24
+ [`${decodeUnicode('⠏')},${decodeUnicode('⠗')}`]: 'ㅞ',
25
+ };
@@ -0,0 +1,14 @@
1
+ import { decodeUnicode } from './utils';
2
+
3
+ export const NUMBERS: Record<number, string> = {
4
+ [decodeUnicode('⠁')]: '1',
5
+ [decodeUnicode('⠃')]: '2',
6
+ [decodeUnicode('⠉')]: '3',
7
+ [decodeUnicode('⠙')]: '4',
8
+ [decodeUnicode('⠑')]: '5',
9
+ [decodeUnicode('⠋')]: '6',
10
+ [decodeUnicode('⠛')]: '7',
11
+ [decodeUnicode('⠓')]: '8',
12
+ [decodeUnicode('⠊')]: '9',
13
+ [decodeUnicode('⠚')]: '0',
14
+ };
@@ -0,0 +1,34 @@
1
+ import { decodeUnicode } from './utils';
2
+
3
+ export const SYMBOLS: Record<string, string> = {
4
+ [`${decodeUnicode('⠖')}`]: '!',
5
+ [`${decodeUnicode('⠲')}`]: '.',
6
+ [`${decodeUnicode('⠐')}`]: ',',
7
+ [`${decodeUnicode('⠦')}`]: '?',
8
+ [`${decodeUnicode('⠐')},${decodeUnicode('⠂')}`]: ':',
9
+ [`${decodeUnicode('⠰')},${decodeUnicode('⠆')}`]: ';',
10
+ [`${decodeUnicode('⠤')}`]: '-',
11
+ [`${decodeUnicode('⠤')},${decodeUnicode('⠤')}`]: '―',
12
+ [`${decodeUnicode('⠦')}`]: '"', // opening
13
+ [`${decodeUnicode('⠴')}`]: '"', // closing
14
+ [`${decodeUnicode('⠠')},${decodeUnicode('⠦')}`]: "'",
15
+ [`${decodeUnicode('⠈')},${decodeUnicode('⠔')}`]: '~',
16
+ [`${decodeUnicode('⠲')},${decodeUnicode('⠲')},${decodeUnicode('⠲')}`]: '…',
17
+ [`${decodeUnicode('⠠')},${decodeUnicode('⠠')},${decodeUnicode('⠠')}`]: '⋯',
18
+ [`${decodeUnicode('⠦')},${decodeUnicode('⠄')}`]: '(',
19
+ [`${decodeUnicode('⠠')},${decodeUnicode('⠴')}`]: ')',
20
+ [`${decodeUnicode('⠦')},${decodeUnicode('⠂')}`]: '{',
21
+ [`${decodeUnicode('⠐')},${decodeUnicode('⠴')}`]: '}',
22
+ [`${decodeUnicode('⠦')},${decodeUnicode('⠆')}`]: '[',
23
+ [`${decodeUnicode('⠰')},${decodeUnicode('⠴')}`]: ']',
24
+ [`${decodeUnicode('⠐')},${decodeUnicode('⠆')}`]: '·',
25
+ [`${decodeUnicode('⠐')},${decodeUnicode('⠦')}`]: '「',
26
+ [`${decodeUnicode('⠴')},${decodeUnicode('⠂')}`]: '」',
27
+ [`${decodeUnicode('⠰')},${decodeUnicode('⠦')}`]: '『',
28
+ [`${decodeUnicode('⠴')},${decodeUnicode('⠆')}`]: '』',
29
+ [`${decodeUnicode('⠸')},${decodeUnicode('⠌')}`]: '/',
30
+ [`${decodeUnicode('⠐')},${decodeUnicode('⠶')}`]: '〈',
31
+ [`${decodeUnicode('⠶')},${decodeUnicode('⠂')}`]: '〉',
32
+ [`${decodeUnicode('⠰')},${decodeUnicode('⠶')}`]: '《',
33
+ [`${decodeUnicode('⠶')},${decodeUnicode('⠆')}`]: '》',
34
+ };
@@ -0,0 +1,14 @@
1
+ export const BRAILLE_UNICODE_START = 0x2800;
2
+
3
+ export function decodeUnicode(char: string): number {
4
+ const code = char.charCodeAt(0);
5
+ if (code >= BRAILLE_UNICODE_START && code <= BRAILLE_UNICODE_START + 0x3f) {
6
+ return code - BRAILLE_UNICODE_START;
7
+ }
8
+ return -1;
9
+ }
10
+
11
+ export function encodeUnicode(dot: number): string {
12
+ if (dot === 255) return '\n';
13
+ return String.fromCharCode(BRAILLE_UNICODE_START + dot);
14
+ }
@@ -0,0 +1,77 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { Decoder } from './index';
3
+
4
+ describe('Decoder', () => {
5
+ const decoder = new Decoder();
6
+
7
+ describe('asciiBrailleToUnicode', () => {
8
+ it('should convert basic letters', () => {
9
+ expect(decoder.asciiBrailleToUnicode('abcd')).toBe('⠁⠃⠉⠙');
10
+ });
11
+
12
+ it('should convert numbers (in ASCII Braille format)', () => {
13
+ // In Braille ASCII, '1' is ⠂, '2' is ⠆, etc.
14
+ expect(decoder.asciiBrailleToUnicode('1234')).toBe('⠂⠆⠒⠲');
15
+ });
16
+
17
+ it('should convert complex strings', () => {
18
+ expect(decoder.asciiBrailleToUnicode('<3c]j,n+')).toBe('⠣⠒⠉⠻⠚⠠⠝⠬');
19
+ });
20
+
21
+ it('ascii', () => {
22
+ // https://en.wikipedia.org/wiki/Braille_ASCII
23
+ expect(decoder.asciiBrailleToUnicode(' ')).toBe('⠀')
24
+ expect(decoder.asciiBrailleToUnicode('=')).toBe('⠿')
25
+ });
26
+
27
+
28
+ it('should convert complex korean strings 1', () => {
29
+ expect(decoder.asciiBrailleToUnicode(',ui{a@{5ra.{7e}8\'#bjbd c* @mr,x,0')).toBe('⠠⠥⠊⠪⠁⠈⠪⠢⠗⠁⠨⠪⠶⠑⠻⠦⠄⠼⠃⠚⠃⠙⠀⠉⠡⠀⠈⠍⠗⠠⠭⠠⠴');
30
+ });
31
+ });
32
+
33
+ describe('translateToText', () => {
34
+ it('should translate Korean "안녕하세요"', () => {
35
+ // 안: ⠣⠒ (ㅏ + ㄴ받침) -> Actually '안' is ⠣(ㅏ) + ⠒(ㄴ종성)
36
+ // 녕: ⠉⠻ (ㄴ초성 + 영약자)
37
+ // 하: ⠚ (하약자)
38
+ // 세: ⠠⠝ (ㅅ초성 + ㅔ)
39
+ // 요: ⠬ (ㅛ)
40
+ // Result: ⠣⠒⠉⠻⠚⠠⠝⠬
41
+ expect(decoder.translateToText('⠣⠒⠉⠻⠚⠠⠝⠬')).toBe('안녕하세요');
42
+ // Note: Full syllable composition is complex, for now we verify parts
43
+ });
44
+
45
+ it('should translate English with indicators', () => {
46
+ // ⠴ (English Indicator) + ⠁⠃⠉ (abc)
47
+ expect(decoder.translateToText('⠴⠁⠃⠉')).toBe('abc');
48
+ });
49
+
50
+ it('should translate Numbers with indicators', () => {
51
+ // ⠼ (Number Indicator) + ⠁⠃⠉ (123)
52
+ expect(decoder.translateToText('⠼⠁⠃⠉')).toBe('123');
53
+ });
54
+
55
+ it('should handle mixed content', () => {
56
+ // ⠼⠁⠀⠴⠁ (1 a)
57
+ expect(decoder.translateToText('⠼⠁⠀⠴⠁')).toBe('1 a');
58
+ });
59
+
60
+ it('should translate Korean sample 1', () => {
61
+ expect(decoder.translateToText('⠦⠄⠼⠃⠚⠃⠙⠀⠉⠡⠀⠈⠍⠗⠠⠭⠠⠴')).toBe('(2024년 귀속)');
62
+ expect(decoder.translateToText('⠘⠂⠈⠪⠃⠘⠾⠚⠥⠐⠂')).toBe('발급번호:');
63
+ });
64
+
65
+ it('should translate Korean sample 2', () => {
66
+ expect(decoder.translateToText('⠠⠥⠊⠪⠁⠈⠪⠢⠗⠁⠨⠪⠶⠑⠻⠦⠄⠼⠃⠚⠃⠙⠀⠉⠡⠀⠈⠍⠗⠠⠭⠠⠴')).toBe('소득금액증명(2024년 귀속)');
67
+ });
68
+
69
+ it('should translate Korean sample 3', () => {
70
+ expect(decoder.translateToText('⠰⠎⠐⠕⠈⠕⠫⠒⠐⠂⠀⠨⠪⠁⠠⠕')).toBe('처리기간: 즉시');
71
+ });
72
+
73
+ it('should translate Korean sample 4', () => {
74
+ expect(decoder.translateToText('⠨⠍⠑⠟⠊⠪⠶⠐⠭⠘⠾⠚⠥⠐⠂⠀⠼⠊⠊⠊⠊⠊⠊⠤⠸⠢⠢⠢⠢⠢⠢⠢⠇')).toBe('주민등록번호: 999999‐∗∗∗∗∗∗∗');
75
+ });
76
+ });
77
+ });