const HALF_KATA = [
'ァ','ア','ィ','イ','ゥ','ウ','ェ','エ','ォ','オ',
'カ','ガ','キ','ギ','ク','グ','ケ','ゲ','コ','ゴ',
'サ','ザ','シ','ジ','ス','ズ','セ','ゼ','ソ','ゾ',
'タ','ダ','チ','ヂ','ッ','ツ','ヅ','テ','デ','ト','ド',
'ナ','ニ','ヌ','ネ','ノ',
'ハ','バ','パ','ヒ','ビ','ピ','フ','ブ','プ','ヘ','ベ','ペ','ホ','ボ','ポ',
'マ','ミ','ム','メ','モ',
'ャ','ヤ','ュ','ユ','ョ','ヨ',
'ラ','リ','ル','レ','ロ',
'ヮ','ワ','ヰ','ヱ','ヲ','ン','ヴ','ヵ','ヶ','ヷ','イ゙','エ゙','ヺ'
]
const halfKataToWide = (text, hira=false) => {
const firstCharCode = hira === true ? 12353 : 12449
return text.replace(/[ワイエヲ]゙/g, m =>
'ヷヸヹヺ'.charAt('ヷイ゙エ゙ヺ'.indexOf(m) / 2)
).replace(/([ヲ-ッアイエオナ-ノマ-ン]|[ウカ-ト]゙?|[ハ-ホ][゙゚]?)/g, m =>
String.fromCharCode(HALF_KATA.indexOf(m) + firstCharCode)
).replace(/[゙゚ー。「」、・]/g, m =>
'゛゜ー。「」、・'.charAt('゙゚ー。「」、・'.indexOf(m))
)
}
const toHira = (text) =>
halfKataToWide(text, true).replace(/[ァ-ヶ]/g, m => String.fromCharCode(m.charCodeAt(0) - 0x60))
const toWideKata = (text) =>
halfKataToWide(text).replace(/[ぁ-ゖ]/g, m => String.fromCharCode(m.charCodeAt(0) + 0x60))
const toHalfKata = (text) =>
text.replace(/[ァ-ヺ]/g, m => HALF_KATA[m.charCodeAt(0) - 12449])
.replace(/[ぁ-ゖ]/g, m => HALF_KATA[m.charCodeAt(0) - 12353])
.replace(/[゛゜ー。「」、・]/g, m => '゙゚ー。「」、・'.charAt('゛゜ー。「」、・'.indexOf(m)))
const str = 'ひびぴヒビピヒビピゐゑをんゔゕゖン゙゚ヺ゚ー。「」、・゛゜ー。「」、・'
console.log(toHira(str))
//ひびぴひびぴひびぴゐゑをんゔゕゖん゛゜ヺ゜ー。「」、・゛゜ー。「」、・
console.log(toWideKata(str))
//ヒビピヒビピヒビピヰヱヲンヴヵヶン゛゜ヺ゜ー。「」、・゛゜ー。「」、・
console.log(toHalfKata(str))
//ヒビピヒビピヒビピヰヱヲンヴヵヶン゙゚ヺ゚ー。「」、・゙゚ー。「」、・
自分でまとめた変換用のclass構文からメソッドを抜き出して再構築したものです。