😺

【JS/TS】全角ひらがな→全角カタカナ→半角カタカナ

に公開

コード

TypeScript Playgroundにコピペしてすぐ動作確認できます👍

// 全角ひらがな → 全角カタカナ
const hiraToKana = (str: string) => str.replace(/[\u3041-\u3096]/g, (match) => String.fromCharCode(match.charCodeAt(0) + 0x60));
// 全角の濁点&半濁点 → 半角の濁点&半濁点
const narrowDakuten = (str: string) => str.replace(/\u309B|\u3099/g, '\uFF9E').replace(/\u309C|\u309A/g, '\uFF9F');
// 全角カタカナ → 半角カタカナ
const  narrowKatakana = (str: string) => {
  const convertMap = {
    ァ: 'ァ',
    ィ: 'ィ',
    ゥ: 'ゥ',
    ェ: 'ェ',
    ォ: 'ォ',
    ャ: 'ャ',
    ュ: 'ュ',
    ョ: 'ョ',
    ッ: 'ッ',
    ヵ: 'カ',
    ヶ: 'ケ',
    ヮ: 'ワ',
    ー: 'ー',
    ア: 'ア',
    イ: 'イ',
    ウ: 'ウ',
    エ: 'エ',
    オ: 'オ',
    カ: 'カ',
    キ: 'キ',
    ク: 'ク',
    ケ: 'ケ',
    コ: 'コ',
    サ: 'サ',
    シ: 'シ',
    ス: 'ス',
    セ: 'セ',
    ソ: 'ソ',
    タ: 'タ',
    チ: 'チ',
    ツ: 'ツ',
    テ: 'テ',
    ト: 'ト',
    ナ: 'ナ',
    ニ: 'ニ',
    ヌ: 'ヌ',
    ネ: 'ネ',
    ノ: 'ノ',
    ハ: 'ハ',
    ヒ: 'ヒ',
    フ: 'フ',
    ヘ: 'ヘ',
    ホ: 'ホ',
    マ: 'マ',
    ミ: 'ミ',
    ム: 'ム',
    メ: 'メ',
    モ: 'モ',
    ヤ: 'ヤ',
    ユ: 'ユ',
    ヨ: 'ヨ',
    ラ: 'ラ',
    リ: 'リ',
    ル: 'ル',
    レ: 'レ',
    ロ: 'ロ',
    ワ: 'ワ',
    ン: 'ン',
    ヰ: 'イ',
    ヱ: 'エ',
    ヲ: 'ヲ',
    ガ: 'ガ',
    ギ: 'ギ',
    グ: 'グ',
    ゲ: 'ゲ',
    ゴ: 'ゴ',
    ザ: 'ザ',
    ジ: 'ジ',
    ズ: 'ズ',
    ゼ: 'ゼ',
    ゾ: 'ゾ',
    ダ: 'ダ',
    ヂ: 'ヂ',
    ヅ: 'ヅ',
    デ: 'デ',
    ド: 'ド',
    バ: 'バ',
    ビ: 'ビ',
    ブ: 'ブ',
    ベ: 'ベ',
    ボ: 'ボ',
    パ: 'パ',
    ピ: 'ピ',
    プ: 'プ',
    ペ: 'ペ',
    ポ: 'ポ',
    ヷ: 'ヷ',
    ヸ: 'イ゙',
    ヴ: 'ヴ',
    ヹ: 'エ゙',
    ヺ: 'ヺ'
  };

  for (const [wideKana, narrowKana] of Object.entries(convertMap)) {
    str = str.replace(new RegExp(wideKana, 'g'), narrowKana);
  }
  return str;
}

const hiragana = 'あいうえおがぎぐげご ゛゜';
const result1 = hiraToKana(hiragana);
const result2 = narrowDakuten(result1);
const result3 = narrowKatakana(result2);

console.log(hiragana); // "あいうえおがぎぐげご ゛゜";
console.log(result1);  // "アイウエオガギグゲゴ ゛゜" 
console.log(result2);  // "アイウエオガギグゲゴ ゙゚" 
console.log(result3);  // "アイウエオガギグゲゴ ゙゚" 

全角ひらがな → 全角カタカナ

const hiragana = 'あいうえお';
const katakana = hiraToKana(hiragana);// アイウエオ

function hiraToKana(str: string) {
    return str.replace(/[\u3041-\u3096]/g, function(match) {
        var chr = match.charCodeAt(0) + 0x60;
        return String.fromCharCode(chr);
    });
}

【\u3041-\u3096】って何?

「ぁ(U+3041)」から「け(U+3096)」までのUnicode from [Hiragana(Unicode block)]

+ 0x60 って何?

全角ひらがな と 全角カタカナ のUnicodeはちょうど【0x60】の等しい間隔になっている。
「あ(U+3042)」-「ア(U+30A2)」= 4 - A(10) = 6
「け(U+3051)」-「ケ(U+30B1)」= 5 - B(11) = 6

なので、この間隔をなくせば全角ひらがな ⇔ 全角カタカナの変換が可能。

全角カタカナ → 半角カタカナ

先ほどの全角ひらがな⇔全角カタカナのように、Unicodeが等しい間隔になっているわけではないので、地道にマッピングを作成してあげる必要がある。

Discussion