UNPKG

romaji-to-kana-ng

Version:

Angular module providing a pipe for converting romaji to kana

144 lines (138 loc) 6.91 kB
import { Pipe, NgModule } from '@angular/core'; const kanaMap = { // standard hiragana 'nn': 'ん', 'wa': 'わ', 'ra': 'ら', 'ya': 'や', 'ma': 'ま', 'ba': 'ば', 'ha': 'は', 'na': 'な', 'da': 'だ', 'ta': 'た', 'za': 'ざ', 'sa': 'さ', 'ga': 'が', 'ka': 'か', 'a': 'あ', 'ri': 'り', 'mi': 'み', 'bi': 'び', 'hi': 'ひ', 'ni': 'に', 'di': 'ぢ', 'chi': 'ち', 'ji': 'じ', 'shi': 'し', 'gi': 'ぎ', 'ki': 'き', 'i': 'い', 'ru': 'る', 'yu': 'ゆ', 'mu': 'む', 'bu': 'ぶ', 'fu': 'ふ', 'nu': 'ぬ', 'du': 'づ', 'tsu': 'つ', 'zu': 'ず', 'su': 'す', 'gu': 'ぐ', 'ku': 'く', 'u': 'う', 're': 'れ', 'me': 'め', 'be': 'べ', 'he': 'へ', 'ne': 'ね', 'de': 'で', 'te': 'て', 'ze': 'ぜ', 'se': 'せ', 'ge': 'げ', 'ke': 'け', 'e': 'え', 'wo': 'を', 'ro': 'ろ', 'yo': 'よ', 'mo': 'も', 'bo': 'ぼ', 'ho': 'ほ', 'no': 'の', 'do': 'ど', 'to': 'と', 'zo': 'ぞ', 'so': 'そ', 'go': 'ご', 'ko': 'こ', 'o': 'お', // little ya, yu, and yo 'kya': 'きゃ', 'kyu': 'きゅ', 'kyo': 'きょ', 'gya': 'ぎゃ', 'gyu': 'ぎゅ', 'gyo': 'ぎょ', 'sya': 'しゃ', 'syu': 'しゅ', 'syo': 'しょ', 'jya': 'じゃ', 'jyu': 'じゅ', 'jyo': 'じょ', 'cya': 'ちゃ', 'cyu': 'ちゅ', 'cyo': 'ちょ', 'nya': 'にゃ', 'nyu': 'にゅ', 'nyo': 'にょ', 'hya': 'ひゃ', 'hyu': 'ひゅ', 'hyo': 'ひょ', 'bya': 'びゃ', 'byu': 'びゅ', 'byo': 'びょ', 'mya': 'みゃ', 'myu': 'みゅ', 'myo': 'みょ', 'pya': 'ぴゃ', 'pyu': 'ぴゅ', 'pyo': 'ぴょ', 'rya': 'りゃ', 'ryu': 'りゅ', 'ryo': 'りょ', // standard katakana 'NN': 'ン', 'WA': 'ワ', 'RA': 'ラ', 'YA': 'ヤ', 'MA': 'マ', 'BA': 'バ', 'HA': 'ハ', 'NA': 'ナ', 'DA': 'ダ', 'TA': 'タ', 'ZA': 'ザ', 'SA': 'サ', 'GA': 'ガ', 'KA': 'カ', 'A': 'ア', 'RI': 'リ', 'MI': 'ミ', 'BI': 'ビ', 'HI': 'ヒ', 'NI': 'ニ', 'DI': 'ヂ', 'CHI': 'チ', 'JI': 'ジ', 'SHI': 'シ', 'GI': 'ギ', 'KI': 'キ', 'I': 'イ', 'RU': 'ル', 'YU': 'ユ', 'MU': 'ム', 'BU': 'ブ', 'FU': 'フ', 'NU': 'ヌ', 'DU': 'ヅ', 'TSU': 'ツ', 'ZU': 'ズ', 'SU': 'ス', 'GU': 'グ', 'KU': 'ク', 'U': 'ウ', 'RE': 'レ', 'ME': 'メ', 'BE': 'ベ', 'HE': 'ヘ', 'NE': 'ネ', 'DE': 'デ', 'TE': 'テ', 'ZE': 'ゼ', 'SE': 'セ', 'GE': 'ゲ', 'KE': 'ケ', 'E': 'エ', 'WO': 'ヲ', 'RO': 'ロ', 'YO': 'ヨ', 'MO': 'モ', 'BO': 'ボ', 'HO': 'ホ', 'NO': 'ノ', 'DO': 'ド', 'TO': 'ト', 'ZO': 'ゾ', 'SO': 'ソ', 'GO': 'ゴ', 'KO': 'コ', 'O': 'オ', // little ya yu and yo katakana 'KYA': 'キャ', 'KYU': 'キュ', 'KYO': 'キョ', 'GYA': 'ギャ', 'GYU': 'ギュ', 'GYO': 'ギョ', 'SYA': 'シャ', 'SYU': 'シュ', 'SYO': 'ショ', 'JYA': 'ジャ', 'JYU': 'ジュ', 'JYO': 'ジョ', 'CYA': 'チャ', 'CYU': 'チュ', 'CYO': 'チョ', 'NYA': 'ニャ', 'NYU': 'ニュ', 'NYO': 'ニョ', 'HYA': 'ヒャ', 'HYU': 'ヒュ', 'HYO': 'ヒョ', 'BYA': 'ビャ', 'BYU': 'ビュ', 'BYO': 'ビョ', 'MYA': 'ミャ', 'MYU': 'ミュ', 'MYO': 'ミョ', 'PYA': 'ピャ', 'PYU': 'ピュ', 'PYO': 'ピョ', 'RYA': 'リャ', 'RYU': 'リュ', 'RYO': 'リョ', // others '-': 'ー' // long vowel }; const katakanaRegExp = /[\u30a0-\u30ff]/g; // matches only katakana characters const specialCharAndKanaRegExp = /[!@#$%^&*(),.?":{}|<>\ _\u3040-\u30ff]/g; // matches kana and special characters class RomajiToKanaPipe { transform(value, ...args) { if (!value) return; let acc = ''; let valueArr = value.split(''); let result = ''; while (valueArr.length) { acc += valueArr.shift(); // if the acc contains a kana character or a special character reset acc and continue if (acc.match(specialCharAndKanaRegExp)) { result += acc; acc = ''; continue; } // check if there is mixed casing if (acc.match(/[a-z]/g) && acc.match(/[A-Z]/g)) { result += acc[0]; acc = acc.slice(1); } const mappedValue = kanaMap[acc]; if (!!mappedValue) { result += mappedValue; acc = ''; } else if (acc.length == 3) { // logic for a double consonant // check if the top is equal to the next char if (acc[0] == acc[1]) { const mappedTail = kanaMap[acc.slice(1)]; if (!!mappedTail) { result += this.makeDoubleConsonant(mappedTail); acc = ''; continue; } else { // peek at the next character const nextChar = valueArr.slice(0, 1); // using a slice since we don't know if there actually is another character const fourCharMatch = kanaMap[acc.slice(1).concat(...nextChar)]; // we found something like jjya or ggya if (!!fourCharMatch) { result += this.makeDoubleConsonant(fourCharMatch); acc = ''; valueArr.shift(); // remove the character we peeked at continue; } } } // attempt one last match before giving up on these 3 const match = kanaMap[acc.slice(1)]; // this will occur if we have something like kga result += acc[0]; if (!!match) { result += match; acc = ''; continue; } else { // remove the first character and allow this set to go through another pass // we might have a 3 character match like gya coming up acc = acc.slice(1); continue; } } } // add any leftovers to the result and return it return result + acc; } makeDoubleConsonant(kana) { // choose which little tsu to use based on if it is katakana return kana.match(katakanaRegExp) ? `ッ${kana}` : `っ${kana}`; } } RomajiToKanaPipe.decorators = [ { type: Pipe, args: [{ name: 'romajiToKana' },] } ]; class KanaPipeNgModule { } KanaPipeNgModule.decorators = [ { type: NgModule, args: [{ declarations: [RomajiToKanaPipe], imports: [], exports: [RomajiToKanaPipe] },] } ]; /* * Public API Surface of romaji-to-kana */ /** * Generated bundle index. Do not edit. */ export { KanaPipeNgModule, RomajiToKanaPipe }; //# sourceMappingURL=romaji-to-kana-ng.js.map