@laisuk/opencc-fmmseg-wasm 0.3.9 → 0.4.1

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.
package/README.md CHANGED
@@ -12,25 +12,33 @@ This package provides high-quality Simplified Chinese ↔ Traditional Chinese co
12
12
 
13
13
  Features:
14
14
 
15
- * OpenCC-compatible conversion configs
16
- * Pure WebAssembly (no native binaries)
17
- * Browser-friendly
18
- * TypeScript-friendly APIs
19
- * Fast Rust backend
20
- * FMM-based phrase segmentation
21
- * Traditional Chinese regional variants
22
- * Japanese Shinjitai conversion support
23
- * Chinese script detection (`zho_check`)
24
- * Optional CJK Compatibility Ideograph normalization
25
- * In-memory Office / EPUB document conversion
26
- * Zero-dependency Node.js CLI
15
+ - OpenCC-compatible conversion configs
16
+ - Pure WebAssembly (no native binaries)
17
+ - Browser-friendly
18
+ - TypeScript-friendly APIs
19
+ - Fast Rust backend
20
+ - FMM-based phrase segmentation
21
+ - Traditional Chinese regional variants
22
+ - Japanese Shinjitai conversion support
23
+ - Chinese script detection (`zho_check`)
24
+ - Optional CJK Compatibility Ideograph normalization
25
+ - In-memory Office / EPUB document conversion
26
+ - Zero-dependency Node.js CLI
27
27
 
28
28
  Package profile:
29
29
 
30
- * 0 runtime dependencies
31
- * 1 WASM file
32
- * 18 conversion configs
33
- * 100% offline
30
+ - 0 runtime dependencies
31
+ - 1 WASM file
32
+ - 20 conversion configs
33
+ - 100% offline
34
+
35
+ ### 🌐 Live Demo
36
+
37
+ Try `opencc-fmmseg-wasm` directly in your browser:
38
+
39
+ **[Open the live WASM demo: CJK Conversion Tool](https://laisuk.github.io/opencc-fmmseg-wasm/)**
40
+
41
+ No installation or server backend required.
34
42
 
35
43
  ---
36
44
 
@@ -40,79 +48,31 @@ Package profile:
40
48
  npm install @laisuk/opencc-fmmseg-wasm
41
49
  ```
42
50
 
43
- ---
44
-
45
- ## Quick Start
46
-
47
- ```javascript
48
- import init, {
49
- OpenccWasm,
50
- DetofuLevelWasm
51
- } from "@laisuk/opencc-fmmseg-wasm";
52
-
53
- await init();
54
-
55
- const cc = new OpenccWasm("s2t");
51
+ Or installation from the mirror package:
56
52
 
57
- console.log(cc.convert("汉字", false));
58
- // 漢字
59
-
60
- console.log(cc.convertDetofu("儼驂騑於上路", false, DetofuLevelWasm.ExtB));
61
- // 俨骖騑于上路
53
+ ```bash
54
+ npm install opencc-fmmseg-wasm
62
55
  ```
63
56
 
64
57
  ---
65
58
 
66
- ## Using Config Enums
59
+ ## Quick Start
67
60
 
68
61
  ```javascript
69
62
  import init, {
70
- OpenccWasm,
71
- OpenccConfigWasm
63
+ OpenccWasm
72
64
  } from "@laisuk/opencc-fmmseg-wasm";
73
65
 
74
66
  await init();
75
67
 
76
- const cc = OpenccWasm.newWithEnum(
77
- OpenccConfigWasm.S2hkp
78
- );
68
+ const cc = new OpenccWasm("s2t");
79
69
 
80
- console.log(cc.convert("别随便录影侵犯个人隐私权", false));
81
- // 別隨便錄影侵犯個人私隱權
70
+ console.log(cc.convert("汉字转换测试", false));
71
+ // 漢字轉換測試
82
72
  ```
83
73
 
84
74
  ---
85
75
 
86
- ## Supported Configs
87
-
88
- | Config | Enum | Description |
89
- |---------|--------------------------|-------------------------------------------------------|
90
- | `s2t` | `OpenccConfigWasm.S2t` | Simplified Chinese → Traditional Chinese |
91
- | `s2tw` | `OpenccConfigWasm.S2tw` | Simplified Chinese → Taiwan Traditional |
92
- | `s2twp` | `OpenccConfigWasm.S2twp` | Simplified Chinese → Taiwan Traditional (phrases) |
93
- | `s2hk` | `OpenccConfigWasm.S2hk` | Simplified Chinese → Hong Kong Traditional |
94
- | `s2hkp` | `OpenccConfigWasm.S2hkp` | Simplified Chinese → Hong Kong Traditional (phrases) |
95
- | `t2s` | `OpenccConfigWasm.T2s` | Traditional Chinese → Simplified Chinese |
96
- | `t2tw` | `OpenccConfigWasm.T2tw` | Traditional Chinese → Taiwan Traditional |
97
- | `t2twp` | `OpenccConfigWasm.T2twp` | Traditional Chinese → Taiwan Traditional (phrases) |
98
- | `t2hk` | `OpenccConfigWasm.T2hk` | Traditional Chinese → Hong Kong Traditional |
99
- | `t2hkp` | `OpenccConfigWasm.T2hkp` | Traditional Chinese → Hong Kong Traditional (phrases) |
100
- | `tw2s` | `OpenccConfigWasm.Tw2s` | Taiwan Traditional → Simplified Chinese |
101
- | `tw2sp` | `OpenccConfigWasm.Tw2sp` | Taiwan Traditional → Simplified Chinese (phrases) |
102
- | `tw2t` | `OpenccConfigWasm.Tw2t` | Taiwan Traditional → Traditional Chinese |
103
- | `tw2tp` | `OpenccConfigWasm.Tw2tp` | Taiwan Traditional → Traditional Chinese (phrases) |
104
- | `hk2s` | `OpenccConfigWasm.Hk2s` | Hong Kong Traditional → Simplified Chinese |
105
- | `hk2sp` | `OpenccConfigWasm.Hk2sp` | Hong Kong Traditional → Simplified Chinese (phrases) |
106
- | `hk2t` | `OpenccConfigWasm.Hk2t` | Hong Kong Traditional → Traditional Chinese |
107
- | `hk2tp` | `OpenccConfigWasm.Hk2tp` | Hong Kong Traditional → Traditional Chinese (phrases) |
108
- | `jp2t` | `OpenccConfigWasm.Jp2t` | Japanese Shinjitai → Traditional Chinese |
109
- | `t2jp` | `OpenccConfigWasm.T2jp` | Traditional Chinese → Japanese Shinjitai |
110
-
111
- The numeric enum values match the vendored Rust backend. Existing values are unchanged; `S2hkp = 17`, `Hk2sp = 18`,
112
- `T2hkp = 19`, and `Hk2tp = 20`.
113
-
114
- ---
115
-
116
76
  ## API
117
77
 
118
78
  ### Constructor
@@ -123,8 +83,8 @@ const cc = new OpenccWasm("s2t");
123
83
 
124
84
  Parameters:
125
85
 
126
- * `config` (optional): OpenCC config string
127
- * default: `"s2t"`
86
+ - `config` (optional): OpenCC config string
87
+ - default: `"s2t"`
128
88
 
129
89
  Example:
130
90
 
@@ -132,13 +92,22 @@ Example:
132
92
  const cc = new OpenccWasm("t2s");
133
93
  ```
134
94
 
95
+ Taiwan phrase config example:
96
+
97
+ ```javascript
98
+ const cc = new OpenccWasm("s2twp");
99
+
100
+ cc.convert("预订‘奔驰’品牌出租车", true);
101
+ // 預訂『賓士』品牌計程車
102
+ ```
103
+
135
104
  Hong Kong phrase config example:
136
105
 
137
106
  ```javascript
138
- const cc = new OpenccWasm("s2hkp");
107
+ const cc = new OpenccWasm("hk2sp");
139
108
 
140
- cc.convert("别随便录影侵犯个人隐私权", false);
141
- // 別隨便錄影侵犯個人私隱權
109
+ cc.convert("作業系統加密保護個人私隱權", false);
110
+ // 操作系统加密保护个人隐私权
142
111
  ```
143
112
 
144
113
  ---
@@ -151,12 +120,12 @@ cc.convert(text, punctuation)
151
120
 
152
121
  Parameters:
153
122
 
154
- * `text`: input string
155
- * `punctuation`: whether to convert punctuation variants
123
+ - `text`: input string
124
+ - `punctuation`: whether to convert punctuation variants
156
125
 
157
126
  Returns:
158
127
 
159
- * converted string
128
+ - converted string
160
129
 
161
130
  Example:
162
131
 
@@ -166,6 +135,85 @@ cc.convert("汉字", false);
166
135
 
167
136
  ---
168
137
 
138
+ ### setConfig
139
+
140
+ ```javascript
141
+ cc.setConfig("t2s");
142
+ ```
143
+
144
+ Returns:
145
+
146
+ - `true` if valid
147
+ - `false` if invalid
148
+
149
+ ---
150
+
151
+ ### getConfig
152
+
153
+ ```javascript
154
+ cc.getConfig();
155
+ ```
156
+
157
+ Returns current config string.
158
+
159
+ ---
160
+
161
+ ### isValidConfig
162
+
163
+ ```javascript
164
+ OpenccWasm.isValidConfig("s2t");
165
+ ```
166
+
167
+ ---
168
+
169
+ ### getSupportedConfigs
170
+
171
+ ```javascript
172
+ OpenccWasm.getSupportedConfigs();
173
+ ```
174
+
175
+ Returns all supported config strings.
176
+
177
+ Includes `s2hkp`, `hk2sp`, `t2hkp`, and `hk2tp`.
178
+
179
+ ---
180
+
181
+ ### getAvailableSlots
182
+
183
+ ```javascript
184
+ const slots = OpenccWasm.getAvailableSlots();
185
+ ```
186
+
187
+ Returns all canonical dictionary slot names accepted by `newWithCustomDicts` as a string array. The list is sourced from
188
+ the core `DictSlot` definitions, so callers can use it to populate selectors or validate custom dictionary input without
189
+ maintaining their own slot list.
190
+
191
+ ```javascript
192
+ if (!OpenccWasm.getAvailableSlots().includes(slot)) {
193
+ throw new Error(`Unsupported dictionary slot: ${slot}`);
194
+ }
195
+ ```
196
+
197
+ ---
198
+
199
+ ### zhoCheck
200
+
201
+ Detect Chinese script type.
202
+
203
+ ```javascript
204
+ cc.zhoCheck(text);
205
+ ```
206
+
207
+ Returns:
208
+
209
+ | Value | Meaning |
210
+ |-------|---------------------|
211
+ | `0` | Unknown / mixed |
212
+ | `1` | Traditional Chinese |
213
+ | `2` | Simplified Chinese |
214
+
215
+ ---
216
+
169
217
  ### normalizeCompat
170
218
 
171
219
  Normalize Unicode CJK Compatibility Ideographs before conversion.
@@ -176,11 +224,11 @@ cc.normalizeCompat(text)
176
224
 
177
225
  Parameters:
178
226
 
179
- * `text`: input string
227
+ - `text`: input string
180
228
 
181
229
  Returns:
182
230
 
183
- * normalized string
231
+ - normalized string
184
232
 
185
233
  Example:
186
234
 
@@ -197,9 +245,89 @@ console.log(cc.convert(normalized, false));
197
245
  // 天龙八部书里的乔峰是契丹人
198
246
  ```
199
247
 
200
- This is an optional pre-conversion pass for text that contains compatibility ideographs from Unicode compatibility
201
- ranges. Unmapped characters are preserved unchanged. Normal OpenCC conversion does not automatically run this pass, so
202
- call it explicitly when compatibility normalization is desired.
248
+ This is an optional pre-conversion pass for text that contains CJK Compatibility Ideographs. Unmapped characters are
249
+ preserved unchanged. Normal OpenCC conversion does not automatically run this pass, so call it explicitly when
250
+ compatibility normalization is desired.
251
+
252
+ ### normalizeUnicodeCompat
253
+
254
+ Normalize additional Unicode compatibility forms, CJK radicals, allographs, legacy glyphs, and selected
255
+ compatibility-like punctuation before conversion.
256
+
257
+ ```javascript
258
+ cc.normalizeUnicodeCompat(text)
259
+ ```
260
+
261
+ Parameters:
262
+
263
+ - `text`: input string
264
+
265
+ Returns:
266
+
267
+ - normalized string
268
+
269
+ Example:
270
+
271
+ ```javascript
272
+ const cc = new OpenccWasm("t2s");
273
+
274
+ const input = "聼聼竒羙⽟䂖甁噐⾳";
275
+ const normalized = cc.normalizeUnicodeCompat(input);
276
+
277
+ console.log(normalized);
278
+ // 聽聽奇美玉石瓶器音
279
+
280
+ console.log(cc.convert(normalized, false));
281
+ // 听听奇美玉石瓶器音
282
+ ```
283
+
284
+ This pass uses the extended Unicode compatibility table and is separate from `normalizeCompat()`. It is useful for text
285
+ containing radical forms, historical or allographic Han forms, and other compatibility-like characters that are not
286
+ covered by the CJK Compatibility Ideograph ranges.
287
+
288
+ Unmapped characters are preserved unchanged.
289
+
290
+ ### normalizeCompatExtended
291
+
292
+ Apply complete compatibility normalization before conversion.
293
+
294
+ ```javascript
295
+ cc.normalizeCompatExtended(text)
296
+ ```
297
+
298
+ Parameters:
299
+
300
+ - `text`: input string
301
+
302
+ Returns:
303
+
304
+ - normalized string
305
+
306
+ Example:
307
+
308
+ ```javascript
309
+ const cc = new OpenccWasm("t2s");
310
+
311
+ const input = "天龍八部書裡的聼眾";
312
+ const normalized = cc.normalizeCompatExtended(input);
313
+
314
+ console.log(normalized);
315
+ // 天龍八部書裡的聽眾
316
+
317
+ console.log(cc.convert(normalized, false));
318
+ // 天龙八部书里的听众
319
+ ```
320
+
321
+ `normalizeCompatExtended()` combines the extended Unicode compatibility table with CJK Compatibility Ideograph
322
+ normalization. Use this when input may contain characters handled by either normalization set.
323
+
324
+ The normalization order is:
325
+
326
+ 1. extended Unicode compatibility normalization;
327
+ 2. CJK Compatibility Ideograph normalization.
328
+
329
+ Normal OpenCC conversion does not automatically perform compatibility normalization. Call this method explicitly before
330
+ `convert()` when complete compatibility normalization is desired.
203
331
 
204
332
  ---
205
333
 
@@ -213,12 +341,12 @@ cc.detofu(text, level)
213
341
 
214
342
  Parameters:
215
343
 
216
- * `text`: input string
217
- * `level`: `DetofuLevelWasm` threshold for the CJK extension ranges to replace
344
+ - `text`: input string
345
+ - `level`: `DetofuLevelWasm` threshold for the CJK extension ranges to replace
218
346
 
219
347
  Returns:
220
348
 
221
- * detofu-safe string
349
+ - detofu-safe string
222
350
 
223
351
  Supported levels:
224
352
 
@@ -265,13 +393,13 @@ cc.convertDetofu(text, punctuation, level)
265
393
 
266
394
  Parameters:
267
395
 
268
- * `text`: input string
269
- * `punctuation`: whether to convert punctuation variants
270
- * `level`: `DetofuLevelWasm` threshold for the CJK extension ranges to replace
396
+ - `text`: input string
397
+ - `punctuation`: whether to convert punctuation variants
398
+ - `level`: `DetofuLevelWasm` threshold for the CJK extension ranges to replace
271
399
 
272
400
  Returns:
273
401
 
274
- * converted detofu-safe string
402
+ - converted detofu-safe string
275
403
 
276
404
  Example:
277
405
 
@@ -282,85 +410,6 @@ cc.convertDetofu("儼驂騑於上路", false, DetofuLevelWasm.ExtB);
282
410
 
283
411
  ---
284
412
 
285
- ### setConfig
286
-
287
- ```javascript
288
- cc.setConfig("t2s");
289
- ```
290
-
291
- Returns:
292
-
293
- * `true` if valid
294
- * `false` if invalid
295
-
296
- ---
297
-
298
- ### getConfig
299
-
300
- ```javascript
301
- cc.getConfig();
302
- ```
303
-
304
- Returns current config string.
305
-
306
- ---
307
-
308
- ### isValidConfig
309
-
310
- ```javascript
311
- OpenccWasm.isValidConfig("s2t");
312
- ```
313
-
314
- ---
315
-
316
- ### getSupportedConfigs
317
-
318
- ```javascript
319
- OpenccWasm.getSupportedConfigs();
320
- ```
321
-
322
- Returns all supported config strings.
323
-
324
- Includes `s2hkp`, `hk2sp`, `t2hkp`, and `hk2tp`.
325
-
326
- ---
327
-
328
- ### getAvailableSlots
329
-
330
- ```javascript
331
- const slots = OpenccWasm.getAvailableSlots();
332
- ```
333
-
334
- Returns all canonical dictionary slot names accepted by `newWithCustomDicts` as a string array. The list is sourced from
335
- the core `DictSlot` definitions, so callers can use it to populate selectors or validate custom dictionary input without
336
- maintaining their own slot list.
337
-
338
- ```javascript
339
- if (!OpenccWasm.getAvailableSlots().includes(slot)) {
340
- throw new Error(`Unsupported dictionary slot: ${slot}`);
341
- }
342
- ```
343
-
344
- ---
345
-
346
- ### zhoCheck
347
-
348
- Detect Chinese script type.
349
-
350
- ```javascript
351
- cc.zhoCheck(text);
352
- ```
353
-
354
- Returns:
355
-
356
- | Value | Meaning |
357
- |-------|---------------------|
358
- | `0` | Unknown / mixed |
359
- | `1` | Traditional Chinese |
360
- | `2` | Simplified Chinese |
361
-
362
- ---
363
-
364
413
  ### newWithCustomDicts
365
414
 
366
415
  Construct a converter with in-memory custom dictionary pairs.
@@ -371,8 +420,8 @@ const cc = OpenccWasm.newWithCustomDicts(config, specs);
371
420
 
372
421
  Parameters:
373
422
 
374
- * `config`: OpenCC config string, such as `"s2t"`
375
- * `specs`: array of custom dictionary specs
423
+ - `config`: OpenCC config string, such as `"s2t"`
424
+ - `specs`: array of custom dictionary specs
376
425
 
377
426
  TypeScript-style spec shape:
378
427
 
@@ -455,14 +504,14 @@ Suffixes such as `.txt` are not accepted, even though case and surrounding white
455
504
 
456
505
  Merge contract:
457
506
 
458
- * Custom dictionaries are loaded from in-memory pairs only; no file I/O is involved.
459
- * The embedded compressed CBOR dictionary is loaded first.
460
- * Custom specs are applied to `DictionaryMaxlength` before `OpenCC::from_dictionary(...)`.
461
- * Conversion hot paths remain immutable after construction.
462
- * `Append` mode merges into the selected slot.
463
- * Duplicate or conflicting keys use last-wins semantics.
464
- * `Override` mode clears the selected slot first, then inserts the provided custom pairs.
465
- * Multiple specs are applied in array order.
507
+ - Custom dictionaries are loaded from in-memory pairs only; no file I/O is involved.
508
+ - The embedded compressed CBOR dictionary is loaded first.
509
+ - Custom specs are applied to `DictionaryMaxlength` before `OpenCC::from_dictionary(...)`.
510
+ - Conversion hot paths remain immutable after construction.
511
+ - `Append` mode merges into the selected slot.
512
+ - Duplicate or conflicting keys use last-wins semantics.
513
+ - `Override` mode clears the selected slot first, then inserts the provided custom pairs.
514
+ - Multiple specs are applied in array order.
466
515
 
467
516
  This API is useful for browser apps, user-defined terminology, database-loaded terms, generated dictionaries,
468
517
  `localStorage` or `IndexedDB` terms, testing, and embedded WASM environments. Customization happens at construction
@@ -470,6 +519,56 @@ time, not during conversion.
470
519
 
471
520
  ---
472
521
 
522
+ ## Supported Configs
523
+
524
+ | Config | Enum | Description |
525
+ |---------|--------------------------|-------------------------------------------------------|
526
+ | `s2t` | `OpenccConfigWasm.S2t` | Simplified Chinese → Traditional Chinese |
527
+ | `s2tw` | `OpenccConfigWasm.S2tw` | Simplified Chinese → Taiwan Traditional |
528
+ | `s2twp` | `OpenccConfigWasm.S2twp` | Simplified Chinese → Taiwan Traditional (phrases) |
529
+ | `s2hk` | `OpenccConfigWasm.S2hk` | Simplified Chinese → Hong Kong Traditional |
530
+ | `s2hkp` | `OpenccConfigWasm.S2hkp` | Simplified Chinese → Hong Kong Traditional (phrases) |
531
+ | `t2s` | `OpenccConfigWasm.T2s` | Traditional Chinese → Simplified Chinese |
532
+ | `t2tw` | `OpenccConfigWasm.T2tw` | Traditional Chinese → Taiwan Traditional |
533
+ | `t2twp` | `OpenccConfigWasm.T2twp` | Traditional Chinese → Taiwan Traditional (phrases) |
534
+ | `t2hk` | `OpenccConfigWasm.T2hk` | Traditional Chinese → Hong Kong Traditional |
535
+ | `t2hkp` | `OpenccConfigWasm.T2hkp` | Traditional Chinese → Hong Kong Traditional (phrases) |
536
+ | `tw2s` | `OpenccConfigWasm.Tw2s` | Taiwan Traditional → Simplified Chinese |
537
+ | `tw2sp` | `OpenccConfigWasm.Tw2sp` | Taiwan Traditional → Simplified Chinese (phrases) |
538
+ | `tw2t` | `OpenccConfigWasm.Tw2t` | Taiwan Traditional → Traditional Chinese |
539
+ | `tw2tp` | `OpenccConfigWasm.Tw2tp` | Taiwan Traditional → Traditional Chinese (phrases) |
540
+ | `hk2s` | `OpenccConfigWasm.Hk2s` | Hong Kong Traditional → Simplified Chinese |
541
+ | `hk2sp` | `OpenccConfigWasm.Hk2sp` | Hong Kong Traditional → Simplified Chinese (phrases) |
542
+ | `hk2t` | `OpenccConfigWasm.Hk2t` | Hong Kong Traditional → Traditional Chinese |
543
+ | `hk2tp` | `OpenccConfigWasm.Hk2tp` | Hong Kong Traditional → Traditional Chinese (phrases) |
544
+ | `jp2t` | `OpenccConfigWasm.Jp2t` | Japanese Shinjitai → Traditional Chinese |
545
+ | `t2jp` | `OpenccConfigWasm.T2jp` | Traditional Chinese → Japanese Shinjitai |
546
+
547
+ The numeric enum values match the vendored Rust backend. Existing values are unchanged; `S2hkp = 17`, `Hk2sp = 18`,
548
+ `T2hkp = 19`, and `Hk2tp = 20`.
549
+
550
+ ---
551
+
552
+ ## Using Config Enums
553
+
554
+ ```javascript
555
+ import init, {
556
+ OpenccWasm,
557
+ OpenccConfigWasm
558
+ } from "@laisuk/opencc-fmmseg-wasm";
559
+
560
+ await init();
561
+
562
+ const cc = OpenccWasm.newWithEnum(
563
+ OpenccConfigWasm.S2hkp
564
+ );
565
+
566
+ console.log(cc.convert("操作系统加密保护个人隐私权", false));
567
+ // 作業系統加密保護個人私隱權
568
+ ```
569
+
570
+ ---
571
+
473
572
  ## Office / EPUB Conversion
474
573
 
475
574
  Office and EPUB conversion runs fully locally in the browser or Node.js. Files are passed in and returned as bytes;
@@ -484,8 +583,12 @@ docx, xlsx, pptx, odt, ods, odp, epub
484
583
  File size is limited by available browser or Node.js memory, but there is no upload or server-side limit. Font
485
584
  preservation is supported with the `keepFont` option.
486
585
 
487
- Use the instance method when possible. It reuses the converter configuration and any custom dictionaries already held by
488
- the `OpenccWasm` instance.
586
+ Use the instance methods when possible. They reuse the converter configuration, custom dictionaries, and other converter
587
+ state already held by the `OpenccWasm` instance.
588
+
589
+ ### Basic Office Conversion
590
+
591
+ For normal OpenCC conversion, use:
489
592
 
490
593
  ```javascript
491
594
  cc.convertOfficeBytes(inputBytes, format, punctuation, keepFont)
@@ -493,21 +596,93 @@ cc.convertOfficeBytes(inputBytes, format, punctuation, keepFont)
493
596
 
494
597
  Parameters:
495
598
 
496
- * `inputBytes`: `Uint8Array` document bytes
497
- * `format`: `docx`, `xlsx`, `pptx`, `odt`, `ods`, `odp`, or `epub`
498
- * `punctuation`: whether to convert punctuation variants
499
- * `keepFont`: whether to preserve font declarations where supported
599
+ - `inputBytes`: `Uint8Array` document bytes
600
+ - `format`: `docx`, `xlsx`, `pptx`, `odt`, `ods`, `odp`, or `epub`
601
+ - `punctuation`: whether to convert punctuation variants
602
+ - `keepFont`: whether to preserve font declarations where supported
500
603
 
501
604
  Returns:
502
605
 
503
- * converted output bytes
606
+ - converted output bytes
504
607
 
505
- The older free function remains available for compatibility:
608
+ The existing free function remains available for compatibility:
506
609
 
507
610
  ```javascript
508
611
  convert_office_bytes(inputBytes, format, config, punctuation, keepFont)
509
612
  ```
510
613
 
614
+ ### Office Conversion Pipeline
615
+
616
+ For compatibility normalization and optional DeTofu processing, use:
617
+
618
+ ```javascript
619
+ cc.convertOfficeBytesPipeline(
620
+ inputBytes,
621
+ format,
622
+ punctuation,
623
+ keepFont,
624
+ normalizeMode,
625
+ detofuLevel
626
+ )
627
+ ```
628
+
629
+ The text-processing order is:
630
+
631
+ ```text
632
+ Normalize -> OpenCC -> DeTofu
633
+ ```
634
+
635
+ `normalizeMode` is a `NormalizeModeWasm` value:
636
+
637
+ ```javascript
638
+ NormalizeModeWasm.None
639
+ NormalizeModeWasm.Compat
640
+ NormalizeModeWasm.UnicodeCompat
641
+ NormalizeModeWasm.CompatExtended
642
+ ```
643
+
644
+ The final `detofuLevel` argument is optional. When omitted or `undefined`, DeTofu is not applied.
645
+
646
+ To enable DeTofu, pass a `DetofuLevelWasm` value:
647
+
648
+ ```javascript
649
+ DetofuLevelWasm.ExtB
650
+ DetofuLevelWasm.ExtC
651
+ DetofuLevelWasm.ExtD
652
+ DetofuLevelWasm.ExtE
653
+ DetofuLevelWasm.ExtF
654
+ DetofuLevelWasm.ExtG
655
+ DetofuLevelWasm.ExtH
656
+ DetofuLevelWasm.ExtI
657
+ ```
658
+
659
+ `ExtB` applies all supported DeTofu mappings from Extension B onward.
660
+
661
+ For example, extended compatibility normalization followed by OpenCC conversion, without DeTofu:
662
+
663
+ ```javascript
664
+ const outputBytes = cc.convertOfficeBytesPipeline(
665
+ inputBytes,
666
+ "docx",
667
+ true,
668
+ true,
669
+ NormalizeModeWasm.CompatExtended
670
+ );
671
+ ```
672
+
673
+ To additionally apply DeTofu:
674
+
675
+ ```javascript
676
+ const outputBytes = cc.convertOfficeBytesPipeline(
677
+ inputBytes,
678
+ "docx",
679
+ true,
680
+ true,
681
+ NormalizeModeWasm.CompatExtended,
682
+ DetofuLevelWasm.ExtB
683
+ );
684
+ ```
685
+
511
686
  ### Browser Office Example
512
687
 
513
688
  ```javascript
@@ -537,6 +712,41 @@ a.click();
537
712
  URL.revokeObjectURL(a.href);
538
713
  ```
539
714
 
715
+ ### Browser Office Pipeline Example
716
+
717
+ ```javascript
718
+ import init, {
719
+ OpenccWasm,
720
+ NormalizeModeWasm,
721
+ DetofuLevelWasm
722
+ } from "@laisuk/opencc-fmmseg-wasm";
723
+
724
+ await init();
725
+
726
+ const cc = new OpenccWasm("t2s");
727
+ const file = document.querySelector("input[type=file]").files[0];
728
+ const inputBytes = new Uint8Array(await file.arrayBuffer());
729
+
730
+ const outputBytes = cc.convertOfficeBytesPipeline(
731
+ inputBytes,
732
+ "docx",
733
+ true,
734
+ true,
735
+ NormalizeModeWasm.CompatExtended,
736
+ DetofuLevelWasm.ExtB
737
+ );
738
+
739
+ const blob = new Blob([outputBytes], {
740
+ type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
741
+ });
742
+
743
+ const a = document.createElement("a");
744
+ a.href = URL.createObjectURL(blob);
745
+ a.download = "converted.docx";
746
+ a.click();
747
+ URL.revokeObjectURL(a.href);
748
+ ```
749
+
540
750
  ### Node.js Office Example
541
751
 
542
752
  ```javascript
@@ -558,6 +768,33 @@ const outputBytes = cc.convertOfficeBytes(
558
768
  fs.writeFileSync("output.docx", outputBytes);
559
769
  ```
560
770
 
771
+ ### Node.js Office Pipeline Example
772
+
773
+ ```javascript
774
+ import fs from "fs";
775
+ import init, {
776
+ OpenccWasm,
777
+ NormalizeModeWasm,
778
+ DetofuLevelWasm
779
+ } from "@laisuk/opencc-fmmseg-wasm";
780
+
781
+ await init();
782
+
783
+ const cc = new OpenccWasm("t2s");
784
+ const inputBytes = fs.readFileSync("input.epub");
785
+
786
+ const outputBytes = cc.convertOfficeBytesPipeline(
787
+ inputBytes,
788
+ "epub",
789
+ true,
790
+ true,
791
+ NormalizeModeWasm.CompatExtended,
792
+ DetofuLevelWasm.ExtB
793
+ );
794
+
795
+ fs.writeFileSync("output.epub", outputBytes);
796
+ ```
797
+
561
798
  ---
562
799
 
563
800
  ## Browser Example
@@ -618,7 +855,7 @@ The package includes a zero-dependency Node.js CLI:
618
855
  ```bash
619
856
  opencc-fmmseg convert -i input.txt -o output.txt -c s2t -p
620
857
  opencc-fmmseg convert -i input.txt -o output.txt -c t2s -p --detofu all
621
- echo "别随便录影侵犯个人隐私权" | opencc-fmmseg convert -c s2hkp
858
+ echo "操作系统加密保护个人隐私权" | opencc-fmmseg convert -c s2hkp
622
859
  echo "天龍八部書裡的喬峰是契丹人" | opencc-fmmseg convert -c t2s --norm-compat
623
860
  // 天龙八部书里的乔峰是契丹人
624
861
  echo "這個細路哥很靈活" | opencc-fmmseg convert -c hk2sp --custom-dict hkphrasesrev:append:my_hk_dict.txt
@@ -649,6 +886,7 @@ opencc-fmmseg office -i input.docx -o output.docx -c s2t -p --keep-font
649
886
  default when omitted value: all
650
887
  --keep-ids Preserve complete IDS expressions during conversion (default: false)
651
888
  -n, --norm-compat Normalize CJK Compatibility Ideographs before conversion (default: false)
889
+ -E, --norm-compat-extended Normalize extended Unicode compatibility forms before conversion (default: false)
652
890
  -D, --custom-dict <slot:mode:file>
653
891
  Load a custom dictionary.
654
892
  May be specified multiple times.
@@ -677,12 +915,18 @@ tw2s, tw2sp, tw2t, tw2tp, hk2s, hk2sp, hk2t, hk2tp, jp2t, t2jp
677
915
  -F, --convert-filename Convert generated output filename stem (default: false)
678
916
  --keep-font Preserve font-family information (default)
679
917
  --no-keep-font Do not preserve font-family information
680
- --custom-dict <slot:mode:file>
681
- Load a custom dictionary.
682
- May be specified multiple times.
683
- Examples:
684
- --custom-dict hkphrasesrev:append:my_hk_dict.txt
685
- --custom-dict stphrases:override:terms.txt
918
+ --keep-ids Preserve complete IDS expressions during conversion (default: false)
919
+ -n, --norm-compat Normalize CJK Compatibility Ideographs before conversion (default: false)
920
+ -E, --norm-compat-extended Normalize extended Unicode compatibility forms before conversion (default: false)
921
+ --detofu [level] Replace tofu-risk rare CJK extension chars after conversion
922
+ level: all | ext-b | ext-c | ext-d | ext-e | ext-f | ext-g | ext-h | ext-i
923
+ default when omitted value: all
924
+ -D, --custom-dict <slot:mode:file>
925
+ Load a custom dictionary.
926
+ May be specified multiple times.
927
+ Examples:
928
+ --custom-dict hkphrasesrev:append:my_hk_dict.txt
929
+ --custom-dict stphrases:override:terms.txt
686
930
  ```
687
931
 
688
932
  For `office`, the format is inferred from the input file extension when `--format` is omitted.
@@ -708,18 +952,19 @@ The WASM-facing enum is exported as `OpenccConfigWasm`, alongside `OpenccWasm`.
708
952
 
709
953
  ## Performance Notes
710
954
 
711
- * WebAssembly build disables Rayon parallelism by default.
712
- * Dictionaries are embedded into the WASM binary.
713
- * Browser caching significantly improves subsequent loads.
955
+ - WebAssembly build disables Rayon parallelism by default.
956
+ - Dictionaries are embedded into the WASM binary.
957
+ - Browser caching significantly improves subsequent loads.
714
958
 
715
959
  ---
716
960
 
717
961
  ## Related Projects
718
962
 
719
- * Rust backend: https://github.com/laisuk/opencc-fmmseg
720
- * C API: https://github.com/laisuk/opencc-fmmseg/tree/master/capi/opencc-fmmseg-capi
721
- * .NET: https://github.com/laisuk/OpenccNet
722
- * Python: https://github.com/laisuk/opencc_purepy
963
+ - Rust backend: https://github.com/laisuk/opencc-fmmseg
964
+ - C API: https://github.com/laisuk/opencc-fmmseg/tree/master/capi/opencc-fmmseg-capi
965
+ - .NET: https://github.com/laisuk/OpenccNet
966
+ - Python: https://github.com/laisuk/opencc_purepy
967
+ - Java: https://github.com/laisuk/OpenccJava
723
968
 
724
969
  ---
725
970