UNPKG

henkaku

Version:

Functions to convert UTF-8 characters between full-width 全角 and half-width 半角

255 lines (244 loc) 4.81 kB
enum Width { Full = 1, Half = 0, } const latinConvertRE = { half: /[!-~]/g, full: /[!-~]/g, delta: 0xfee0, }; const kanaMap: { half: Record<string, string>; full: Record<string, string>; } = { half: { ガ: "ガ", ギ: "ギ", グ: "グ", ゲ: "ゲ", ゴ: "ゴ", ザ: "ザ", ジ: "ジ", ズ: "ズ", ゼ: "ゼ", ゾ: "ゾ", ダ: "ダ", ヂ: "ヂ", ヅ: "ヅ", デ: "デ", ド: "ド", バ: "バ", ビ: "ビ", ブ: "ブ", ベ: "ベ", ボ: "ボ", パ: "パ", ピ: "ピ", プ: "プ", ペ: "ペ", ポ: "ポ", ヴ: "ヴ", ヷ: "ヷ", ヺ: "ヺ", ア: "ア", イ: "イ", ウ: "ウ", エ: "エ", オ: "オ", カ: "カ", キ: "キ", ク: "ク", ケ: "ケ", コ: "コ", サ: "サ", シ: "シ", ス: "ス", セ: "セ", ソ: "ソ", タ: "タ", チ: "チ", ツ: "ツ", テ: "テ", ト: "ト", ナ: "ナ", ニ: "ニ", ヌ: "ヌ", ネ: "ネ", ノ: "ノ", ハ: "ハ", ヒ: "ヒ", フ: "フ", ヘ: "ヘ", ホ: "ホ", マ: "マ", ミ: "ミ", ム: "ム", メ: "メ", モ: "モ", ヤ: "ヤ", ユ: "ユ", ヨ: "ヨ", ラ: "ラ", リ: "リ", ル: "ル", レ: "レ", ロ: "ロ", ワ: "ワ", ヲ: "ヲ", ン: "ン", ァ: "ァ", ィ: "ィ", ゥ: "ゥ", ェ: "ェ", ォ: "ォ", ッ: "ッ", ャ: "ャ", ュ: "ュ", ョ: "ョ", "。": "。", "、": "、", ー: "ー", "「": "「", "」": "」", "・": "・", ゚: "゜", ゙: "゛", }, full: { ガ: "ガ", ギ: "ギ", グ: "グ", ゲ: "ゲ", ゴ: "ゴ", ザ: "ザ", ジ: "ジ", ズ: "ズ", ゼ: "ゼ", ゾ: "ゾ", ダ: "ダ", ヂ: "ヂ", ヅ: "ヅ", デ: "デ", ド: "ド", バ: "バ", ビ: "ビ", ブ: "ブ", ベ: "ベ", ボ: "ボ", パ: "パ", ピ: "ピ", プ: "プ", ペ: "ペ", ポ: "ポ", ヴ: "ヴ", ヷ: "ヷ", ヺ: "ヺ", ア: "ア", イ: "イ", ウ: "ウ", エ: "エ", オ: "オ", カ: "カ", キ: "キ", ク: "ク", ケ: "ケ", コ: "コ", サ: "サ", シ: "シ", ス: "ス", セ: "セ", ソ: "ソ", タ: "タ", チ: "チ", ツ: "ツ", テ: "テ", ト: "ト", ナ: "ナ", ニ: "ニ", ヌ: "ヌ", ネ: "ネ", ノ: "ノ", ハ: "ハ", ヒ: "ヒ", フ: "フ", ヘ: "ヘ", ホ: "ホ", マ: "マ", ミ: "ミ", ム: "ム", メ: "メ", モ: "モ", ヤ: "ヤ", ユ: "ユ", ヨ: "ヨ", ラ: "ラ", リ: "リ", ル: "ル", レ: "レ", ロ: "ロ", ワ: "ワ", ヲ: "ヲ", ン: "ン", ァ: "ァ", ィ: "ィ", ゥ: "ゥ", ェ: "ェ", ォ: "ォ", ッ: "ッ", ャ: "ャ", ュ: "ュ", ョ: "ョ", "。": "。", "、": "、", ー: "ー", "「": "「", "」": "」", "・": "・", "゛": "゙", "゜": "゚", }, }; const flipWidthLatin = (str: string, toWidth: Width) => { const isFull = toWidth === Width.Full; const { half, full, delta } = latinConvertRE; const d = isFull ? delta : -delta; return str.replace(isFull ? half : full, (c) => String.fromCharCode(c.charCodeAt(0) + d) ); }; const flipWidthWhiteSpace = (str: string, toWidth: Width) => { return toWidth === Width.Full ? str.replace(/\u0020/g, "\u3000") : str.replace(/\u3000/g, "\u0020"); }; const flipWidthKatakana = (str: string, toWidth: Width) => { const isFull = toWidth === Width.Full; const mapTo = isFull ? kanaMap.half : kanaMap.full; const re = new RegExp( `(${Object.keys(isFull ? kanaMap.half : kanaMap.full).join("|")})`, "g" ); return str.replace(re, (c) => mapTo[c]); }; const toWidth = (str: string, toWidth: Width): string => { let converted = str; converted = flipWidthLatin(converted, toWidth); converted = flipWidthWhiteSpace(converted, toWidth); converted = flipWidthKatakana(converted, toWidth); return converted; }; /** * Convert a string to full-width. * * @param str - The string to convert. * @returns The converted string. */ const toFullWidth = (str: string): string => toWidth(str, Width.Full); /** * Convert a string to half-width. * * @param str - The string to convert. * @returns The converted string. */ const toHalfWidth = (str: string): string => toWidth(str, Width.Half); export { toFullWidth, toHalfWidth };