Skip to content

Instantly share code, notes, and snippets.

@adamay000
Last active January 30, 2018 07:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamay000/6757d9dc0b47f86315ab8f27c233b0e6 to your computer and use it in GitHub Desktop.
Save adamay000/6757d9dc0b47f86315ab8f27c233b0e6 to your computer and use it in GitHub Desktop.
オレオレkana
// 入力から学習した漢字->ひらがなのマッピングを入れる
const mapping = {};
// 漢字の部分を取得するための正規表現キー
// 漢字としているが、実際にはひらがな以外の文字で、カタカナなども含む
const KANJI = '(.+)';
/**
* 学習した漢字->ひらがなのマッピングを適用して学習済みの漢字をひらがなに置き換える
* @param {string} _word
* @returns {*}
*/
const toMapped = (_word) => {
let word = _word;
Object.keys(mapping).forEach((mapped) => {
word = word.replace(new RegExp(mapped, 'g'), mapping[mapped]);
});
return word;
};
/**
* 入力のかなを取得する
* @param {string} src - 入力中の文字列
* @param {string} dest - 変換するかな文字列
* @param {Object} [options = {}]
* @param {boolean} [options.toKatakana] - カタカナにするかどうか
* @returns {string}
*/
export const kana = (src, dest, options = {}) => {
// 入力が空になったらかなも空にする
if (src.length === 0) {
return '';
}
// reduceで一文字ずつ見たいので配列にする
// 同じ漢字を何度も学習しないようにこの時点で学習済みの漢字はひらがなに変換する
const srcArray = toMapped(src).split('');
// 学習用に漢字だけ抜き出す
const kanjis = [];
// 漢字部分を抜き出すための正規表現を生成する
// 入力文字列が「あいう漢字えお」だと、「あいう(.*)えお」に変換する
// また、kanjis = ['漢字']になる
const pattern = srcArray.reduce((reduction, char) => {
// ひらがなはそのまま入れる
if (!char.match(/[^ぁ-ゖァ-ヶー]/)) {
reduction.push(char);
} else if (reduction[reduction.length - 1] === KANJI) {
// 1文字前が漢字の場合は結合する
kanjis[kanjis.length - 1] += char;
} else {
// 新しく漢字が出てきた場合はkanjisに追加して、正規表現上は(.*)に置き換える
kanjis.push(char);
reduction.push(KANJI);
}
return reduction;
}, []).join('');
// 漢字部分を抜き出すための正規表現
const regex = new RegExp(pattern);
const matched = dest.match(regex);
// かな入力のinputが正規表現を満たしている場合は漢字->ひらがなのマッピングを学習する
if (matched) {
kanjis.forEach((kanji, i) => {
// 既に登録済の場合は更新しない
if (mapping[kanji]) {
return;
}
// アルファベットを含むものは、入力途中の文字の可能性が高いので登録しない
if (/^[a-zA-Z0-9]+$/.test(kanji)) {
return;
}
// 上記以外を登録する
mapping[kanji] = matched[i + 1];
});
}
// かなだけを返却する
const result = toMapped(src).replace(/[^ぁ-ゖァ-ヶー]/g, '');
// カタカナで返却
if (options.toKatakana === true) {
return result.replace(/[ぁ-ゖ]/g, (match) => {
return String.fromCharCode(match.charCodeAt(0) + 0x60);
});
}
// ひらがなで返却
return result.replace(/[ァ-ヶ]/g, (match) => {
return String.fromCharCode(match.charCodeAt(0) - 0x60);
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment