From e7e066ac6802ff430027ce05a42fd464d075dc88 Mon Sep 17 00:00:00 2001 From: greymoth <246701683+greymoth-jp@users.noreply.github.com> Date: Tue, 30 Jun 2026 09:05:37 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20convert=20=E3=83=B8/=E3=83=B9=20(U+30F8/?= =?UTF-8?q?U+30F9)=20in=20toHiraganaCase=20and=20toKatakanaCase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit toHiraganaCase already decomposes ヷ (U+30F7) to わ゛ and ヺ (U+30FA) to を゛, and toKatakanaCase composes them back, but the other two wa-row voiced katakana ヸ (U+30F8) and ヹ (U+30F9) were left out and passed through unconverted. The base letters ヰ/ヱ already map to ゐ/ゑ, so the voiced forms now follow the same pattern: ヸ <=> ゐ゛, ヹ <=> ゑ゛. --- src/index.js | 14 +++++++++++++- tests/test.js | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 191725f..02ea0df 100644 --- a/src/index.js +++ b/src/index.js @@ -358,6 +358,14 @@ var Encoding = { } else if (c === 0x30F7) { results[results.length] = 0x308F; c = 0x309B; + // 「ヰ゛」 => 「ゐ」 + 「゛」 + } else if (c === 0x30F8) { + results[results.length] = 0x3090; + c = 0x309B; + // 「ヱ゛」 => 「ゑ」 + 「゛」 + } else if (c === 0x30F9) { + results[results.length] = 0x3091; + c = 0x309B; // 「ヲ゛」 => 「を」 + 「゛」 } else if (c === 0x30FA) { results[results.length] = 0x3092; @@ -397,9 +405,13 @@ var Encoding = { c = data[i++]; if (c >= 0x3041 && c <= 0x3096) { if ((c === 0x308F || // 「わ」 + 「゛」 => 「ワ゛」 + c === 0x3090 || // 「ゐ」 + 「゛」 => 「ヰ゛」 + c === 0x3091 || // 「ゑ」 + 「゛」 => 「ヱ゛」 c === 0x3092) && // 「を」 + 「゛」 => 「ヲ゛」 i < len && data[i] === 0x309B) { - c = c === 0x308F ? 0x30F7 : 0x30FA; + c = c === 0x308F ? 0x30F7 : + c === 0x3090 ? 0x30F8 : + c === 0x3091 ? 0x30F9 : 0x30FA; i++; } else { c += 0x0060; diff --git a/tests/test.js b/tests/test.js index 2374cf3..39967a1 100644 --- a/tests/test.js +++ b/tests/test.js @@ -1517,6 +1517,24 @@ describe('encoding', function() { }); }); + it('toHiraganaCase/toKatakanaCase wa-row voiced kana', function() { + // 'ヷヸヹヺ' (U+30F7 - U+30FA) <=> base hiragana + voiced mark (U+309B) + var katakana = 'ヷヸヹヺ'; + var hiragana = 'わ゛ゐ゛ゑ゛を゛'; + + assert.equal(encoding.toHiraganaCase(katakana), hiragana); + assert.equal(encoding.toKatakanaCase(hiragana), katakana); + + assert.deepEqual( + encoding.toHiraganaCase(encoding.stringToCode(katakana)), + encoding.stringToCode(hiragana) + ); + assert.deepEqual( + encoding.toKatakanaCase(encoding.stringToCode(hiragana)), + encoding.stringToCode(katakana) + ); + }); + it('toHankanaCase', function() { zenkanas.forEach(function(zenkana, i) { var expect = hankanas[i];