diff --git a/src/helpers/smartSpacing.js b/src/helpers/smartSpacing.js index 3e1dfbeb9..7fe8b1b91 100644 --- a/src/helpers/smartSpacing.js +++ b/src/helpers/smartSpacing.js @@ -21,8 +21,17 @@ function applyPrepend(text, precedingChar) { return " " + text; } +// Unspaced scripts (Han, kana) and CJK punctuation (Symbols and Punctuation, +// Fullwidth/Halfwidth Forms, Vertical Forms, Compatibility Forms): a trailing +// ASCII space after "你好" or "です。" violates East Asian typography and +// accumulates as "你好 世界" gaps across consecutive dictations. Hangul is +// excluded on purpose — Korean separates words with spaces. +const ENDS_WITH_CJK = + /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\u3000-\u303f\uff00-\uff65\ufe10-\ufe1f\ufe30-\ufe4f]$/u; + function applyAppend(text) { if (/\s$/.test(text)) return text; + if (ENDS_WITH_CJK.test(text)) return text; return text + " "; } diff --git a/test/helpers/smartSpacing.test.js b/test/helpers/smartSpacing.test.js index 2bb7330ed..844a7d585 100644 --- a/test/helpers/smartSpacing.test.js +++ b/test/helpers/smartSpacing.test.js @@ -98,6 +98,39 @@ test("append: handles empty transcript", () => { assert.equal(append(""), ""); }); +test("append: no trailing space after CJK ideographs", () => { + assert.equal(append("你好"), "你好"); + assert.equal(append("日本語"), "日本語"); +}); + +test("append: no trailing space after kana", () => { + assert.equal(append("こんにちは"), "こんにちは"); + assert.equal(append("カタカナ"), "カタカナ"); +}); + +test("append: no trailing space after full-width punctuation", () => { + assert.equal(append("你好。"), "你好。"); + assert.equal(append("すごい!"), "すごい!"); + assert.equal(append("何?"), "何?"); + assert.equal(append("はい、"), "はい、"); + assert.equal(append("「引用」"), "「引用」"); + assert.equal(append("(括弧)"), "(括弧)"); +}); + +test("append: no trailing space after halfwidth CJK punctuation and vertical forms", () => { + assert.equal(append("テスト。"), "テスト。"); + assert.equal(append("你好︒"), "你好︒"); +}); + +test("append: last character decides for mixed-script text", () => { + assert.equal(append("hello 你好"), "hello 你好"); + assert.equal(append("你好 hello"), "你好 hello "); +}); + +test("append: keeps trailing space after Hangul (Korean uses word spacing)", () => { + assert.equal(append("안녕하세요"), "안녕하세요 "); +}); + test("returns text unchanged for unknown mode", () => { assert.equal(applySmartSpacing({ text: "hello", mode: "noop" }), "hello"); });