Last active
January 24, 2017 07:14
-
-
Save foriequal0/78df728a4877c17cc047 to your computer and use it in GitHub Desktop.
야민정음.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var hangul = (function() { | |
var ChoSeong = [ | |
0x3131, 0x3132, 0x3134, 0x3137, 0x3138, | |
0x3139, 0x3141, 0x3142, 0x3143, 0x3145, | |
0x3146, 0x3147, 0x3148, 0x3149, 0x314a, | |
0x314b, 0x314c, 0x314d, 0x314e | |
]; | |
var JungSeong = [ | |
0x314f, 0x3150, 0x3151, 0x3152, 0x3153, | |
0x3154, 0x3155, 0x3156, 0x3157, 0x3158, | |
0x3159, 0x315a, 0x315b, 0x315c, 0x315d, | |
0x315e, 0x315f, 0x3160, 0x3161, 0x3162, | |
0x3163 | |
]; | |
var JongSeong = [ | |
0x0000, 0x3131, 0x3132, 0x3133, 0x3134, | |
0x3135, 0x3136, 0x3137, 0x3139, 0x313a, | |
0x313b, 0x313c, 0x313d, 0x313e, 0x313f, | |
0x3140, 0x3141, 0x3142, 0x3144, 0x3145, | |
0x3146, 0x3147, 0x3148, 0x314a, 0x314b, | |
0x314c, 0x314d, 0x314e | |
]; | |
var pushCharCode = function(array, charCode) { | |
array.push(String.fromCharCode(charCode)); | |
} | |
var split = function(text) { | |
var v = []; | |
for (var i = 0; i < text.length; i++) { | |
var ch = text.charCodeAt(i); | |
if (ch >= 0xAC00 && ch <= 0xD7A3) { | |
var i1, i2, i3; | |
i3 = ch - 0xAC00; | |
i1 = Math.floor(i3 / (21 * 28)); | |
i3 = i3 % (21 * 28); | |
i2 = Math.floor(i3 / 28); | |
i3 = i3 % 28; | |
pushCharCode(v, ChoSeong[i1]); | |
pushCharCode(v, JungSeong[i2]); | |
if (i3 != 0x0000) pushCharCode(v, JongSeong[i3]); | |
} else { | |
pushCharCode(v, ch); | |
} | |
} | |
return v; | |
} | |
var join = function(jaso, more) { | |
more = arguments[1] || false; | |
var johap = null; | |
var johap_stash = null; | |
var johap_new = null; | |
var res = []; | |
var state = 0; | |
var contains = function(array, item) { | |
return $.inArray(item, array) >= 0; | |
} | |
for (var i = 0; i < jaso.length; i++) { | |
var ch = jaso[i].charCodeAt(0); | |
if (!(contains(ChoSeong, ch) || contains(JungSeong, ch) || contains(JongSeong, ch))) { | |
if (johap != null) { | |
pushCharCode(res, johap); | |
} | |
pushCharCode(res, ch); | |
johap = null; | |
johap_stash = null; | |
johap_new = null; | |
state = 0; | |
continue; | |
} | |
var jaum = contains(ChoSeong, ch) || contains(JongSeong, ch); | |
switch (state) { | |
case 0: | |
// (초) | |
if (jaum) { | |
johap = ch; | |
state = 1; | |
} else { | |
if (johap) | |
pushCharCode(res, johap); | |
else | |
pushCharCode(res, ch); | |
johap = null; | |
state = 0; | |
} | |
break; | |
case 1: | |
// 초(중) | |
if (!jaum) { | |
johap = 0xAC00 + $.inArray(johap, ChoSeong) * (21 * 28); | |
johap = johap + $.inArray(ch, JungSeong) * 28; | |
state = 2; | |
} else { | |
pushCharCode(res, johap); | |
johap = ch; | |
state = 1; | |
} | |
break; | |
case 2: | |
// 초중(초) | |
johap_stash = johap; | |
johap_new = 0xAC00 + $.inArray(ch, ChoSeong) * (21 * 28); | |
johap = johap + $.inArray(ch, JongSeong); | |
state = 3; | |
break; | |
case 3: | |
// 초중초(?) | |
if (jaum) { // 초중초(초) | |
pushCharCode(res, johap); | |
johap = 0xAC00 + $.inArray(ch, ChoSeong) * (21 * 28); | |
johap_stash = null; | |
johap_new = null; | |
state = 1; | |
} else { // 초중초(중) | |
pushCharCode(res, johap_stash); | |
johap = johap_new + $.inArray(ch, JungSeong) * 28; | |
johap_stash = null; | |
johap_new = null; | |
state = 2; | |
} | |
break; | |
} | |
} | |
if (johap != null) { | |
pushCharCode(res, johap); | |
} | |
if (more) { | |
return res.join(""); | |
} else { | |
return res; | |
} | |
} | |
var split_strict = function(text) { | |
var v = []; | |
for (var i = 0; i < text.length; i++) { | |
var tmp = []; | |
var ch = text.charCodeAt(i); | |
if (ch >= 0xAC00 && ch <= 0xD7A3) { | |
var i1, i2, i3; | |
i3 = ch - 0xAC00; | |
i1 = Math.floor(i3 / (21 * 28)); | |
i3 = i3 % (21 * 28); | |
i2 = Math.floor(i3 / 28); | |
i3 = i3 % 28; | |
pushCharCode(tmp, ChoSeong[i1]); | |
pushCharCode(tmp, JungSeong[i2]); | |
if (i3 != 0x0000) pushCharCode(tmp, JongSeong[i3]); | |
} else { | |
pushCharCode(tmp, ch); | |
} | |
v.push(tmp); | |
} | |
return v; | |
} | |
var join_strict = function(strict_jaso, more) { | |
more = arguments[1] || false; | |
var res = []; | |
for (var i = 0; i < strict_jaso.length; i++) { | |
var chars = strict_jaso[i]; | |
var johap = join(chars, true); | |
res.push(johap); | |
} | |
if (more) { | |
return res.join(""); | |
} else { | |
return res; | |
} | |
} | |
return { | |
split: split, | |
join: join, | |
split_strict: split_strict, | |
join_strict: join_strict, | |
} | |
})(); | |
var config = { | |
kanji: true, | |
} | |
var yamin = (function() { | |
if (config === undefined) { | |
config = {}; | |
} | |
var rules = []; | |
(function() { | |
function getRandomInt(min, max) { | |
return Math.floor(Math.random() * (max - min)) + min; | |
} | |
var join = function() { | |
var x = ""; | |
for (var i = 0; i < arguments.length; i++) { | |
if (arguments[i]) { | |
x = x + arguments[i]; | |
} | |
} | |
return x; | |
} | |
var constant = function(v) { | |
return function() { | |
return v; | |
} | |
} | |
var xx_ = function(p) { | |
return function(x) { | |
return join(p, x[2]); | |
} | |
} | |
var _xx = function(p) { | |
return function(x) { | |
return join(x[0], p); | |
} | |
} | |
var x_x = function(p) { | |
return function(x) { | |
return join(x[0], p, x[1]); | |
} | |
} | |
var add = function(type) { | |
return function(pattern) { | |
var pattern_args = arguments; | |
if (type === "char") { | |
var regex = new RegExp(pattern); | |
var match = function(x) { | |
return x.match(regex) | |
}; | |
} else { | |
var match = function(x) { | |
if (x.startsWith(pattern)) return pattern; | |
else null; | |
}; | |
} | |
if (pattern_args.length == 2) { | |
rules.push({ | |
type: type, | |
match: match, | |
process: arguments[1] | |
}); | |
} else { | |
rules.push({ | |
type: type, | |
match: match, | |
process: function(x) { | |
var i = getRandomInt(1, pattern_args.length); | |
var select = pattern_args[i]; | |
return select(x); | |
} | |
}); | |
} | |
} | |
} | |
var word = add("word"); | |
var char = add("char"); | |
var rword = function() { | |
var candidates = arguments; | |
for (var i = 0; i < candidates.length; i++) { | |
var pivot = candidates[i]; | |
var args = [pivot]; | |
for (var j = 0; j < candidates.length; j++) { | |
if (i == j) continue; | |
args.push(constant(candidates[j])); | |
} | |
word.apply(this, args); | |
} | |
} | |
var rchar = function() { | |
var candidates = arguments; | |
for (var i = 0; i < candidates.length; i++) { | |
var pivot = candidates[i]; | |
var args = [pivot]; | |
for (var j = 0; j < candidates.length; j++) { | |
if (i == j) continue; | |
args.push(xx_(candidates[j])); | |
} | |
char.apply(this, args); | |
} | |
} | |
var rchar_xx = function() { | |
var candidates = arguments; | |
for (var i = 0; i < candidates.length; i++) { | |
var pivot = "." + candidates[i]; | |
var args = [pivot]; | |
for (var j = 0; j < candidates.length; j++) { | |
if (i == j) continue; | |
args.push(_xx(candidates[j])); | |
} | |
char.apply(this, args); | |
} | |
} | |
var rchar_x = function(a, b) { | |
char("." + a + "$", _xx(b)); | |
char("." + b, _xx(a)); | |
} | |
rword("김장훈", "숲튻훈"); | |
rword("이명박", "어맹뿌"); | |
rword("귀여", "커여"); | |
rword("명박", "맹뿌"); | |
rword("노래", "놃"); | |
char("ㅂ$", constant("ㅐ")); | |
rword("ㅅ", constant("ㅏ")); | |
rword("응", "%"); | |
rword("든", "ㅌ", "E"); | |
rword("나", "4"); | |
rword("또", "SE"); | |
rword("시", "N", "ㅐ"); | |
rword("서", "ㅒ"); | |
rword("m", "rn"); | |
rword("백", "뿌"); | |
rword("리", "21"); | |
rword("ㄺ", "27"); | |
rword("ㄻ", "20"); | |
rword("B", "13"); | |
rword("♡", "S2"); | |
rword("오우야", "ㅗㅜㅑ", "퍄"); | |
rword("오우", "ㅗㅜ", "ㅍ"); | |
rword("으아아아", "호옹이"); | |
rword("바비킴", "숲뜨뚜"); | |
rword("비버", "뜨또"); | |
if (config["generic_bieber"]) { | |
var c = { | |
"ㅣ": "ㅡ", | |
"ㅓ": "ㅗ", | |
"ㅏ": "ㅜ", | |
"ㅕ": "ㅛ", | |
"ㅑ": "ㅠ", | |
"ㅂ": "ㄸ", | |
"ㅁ": "ㅁ" | |
}; | |
var r = { | |
"ㅡ": "ㅣ", | |
"ㅗ": "ㅓ", | |
"ㅜ": "ㅓ", | |
"ㅛ": "ㅕ", | |
"ㅠ": "ㅑ", | |
"ㄸ": "ㅂ", | |
"ㅁ": "ㅁ" | |
} | |
char("(ㅁ|ㅂ)(ㅏ|ㅑ|ㅓ|ㅕ|ㅣ)(ㅁ|ㅂ|$)", | |
function(x) { | |
return join(c[x[2]], c[x[0]], c[x[1]]); | |
}); | |
char("(ㅁ|ㄸ)(ㅗ|ㅛ|ㅜ|ㅠ|ㅡ)$", | |
function(x) { | |
return join(r[x[0]], r[x[1]]); | |
}); | |
} | |
rword("복복", "뽂"); | |
rword("조조", "쬬"); | |
rword("돌돔", "뚊"); | |
rword("존좋", "쬲"); | |
rword("스스", "쓰"); | |
rword("스시", "씌"); | |
rword("부부", "쀼"); | |
rword("도도", "뚀", "뚀"); | |
rword("주주", "쮸"); | |
rword("굴국", "뀱"); | |
rword("|dH", "배"); | |
rword("♡", "오크"); | |
rword("육군", "곤뇽"); | |
rword("해군", "곤ㅐ우", "괜우"); | |
rword("공군", "곤운"); | |
rword("개새끼", "ILLHVHL"); | |
rword("너구리", "RtA"); | |
rword("플라이곤", "귄어근릎"); | |
rword("폭음룡", "율믕눞"); | |
rword("논문", "곰국"); | |
rword("디씨", "NVㅁ"); | |
rword("SKY", "ㅏ기ㄹ"); | |
if (config["generic_rot"]) { | |
var jaum_r = { | |
"ㄱ": "ㄴ", | |
"ㄴ": "ㄱ", | |
"ㄹ": "ㄹ", | |
"ㅁ": "ㅁ", | |
"ㅇ": "ㅇ", | |
"ㅍ": "ㅍ", | |
}; | |
var moum_r = { | |
"ㅗ": "ㅜ", | |
"ㅜ": "ㅗ", | |
"ㅛ": "ㅠ", | |
"ㅠ": "ㅛ", | |
"ㅡ": "ㅡ", | |
}; | |
char("(ㄱ|ㄴ|ㄹ|ㅁ|ㅇ|ㅍ)(ㅗ|ㅛ|ㅜ|ㅠ|ㅡ)(ㄱ|ㄴ|ㄹ|ㅁ|ㅇ|ㅍ)", | |
function(x) { | |
return join(jaum_r[x[0]], moum_r[x[1]], jaum_r[x[2]]); | |
}); | |
} | |
if (config["kanji"]) { | |
rword("日", "티"); | |
rword("目", "틴"); | |
rword("具", "틧"); | |
rword("音", "흡"); | |
rword("子", "구"); | |
rword("夬", "곳"); | |
rword("己", "근", "ㄹ"); | |
rword("呂", "몸"); | |
rword("長", "튽", "장"); | |
rword("張", "국튽"); | |
rword("金", "숲", "김"); | |
rword("辛", "푸", "곡"); | |
rword("卒", "쭈"); | |
rword("兵", "둇"); | |
rword("引", "뤼"); | |
rword("弓", "국"); | |
rword("丕", "조"); | |
rword("奀", "좆"); | |
rword("丛", "쓰"); | |
rword("笑", "씇"); | |
rword("刁", "ㅋ"); | |
rword("水", "갸"); | |
rword("公", "쇼"); | |
rword("豆", "묘"); | |
rword("音", "플"); | |
rword("站", "팜"); | |
rword("粘", "참"); | |
rword("左", "t2"); | |
rword("性", "아날"); | |
rword("情", "아홉"); | |
rword("大", "ㅊ"); | |
rword("号", "믁"); | |
rword("哭", "뽓"); | |
rword("爿", "뉘"); | |
rword("斗", "쿠"); | |
rword("完", "류"); | |
rword("今", "슥"); | |
rword("合", "슴"); | |
rword("召", "끔", "검"); | |
rword("㕦", "못"); | |
rword("丑", "표"); | |
rword("初", "체"); | |
rword("分", "슈"); | |
rword("化", "샤"); | |
rword("上", "노"); | |
rword("号", "묵"); | |
rword("彐", "크"); | |
} | |
rword("푸", "곡"); | |
rword("근", "ㄹ"); | |
rword("구", "ㅋ", "ヲ"); | |
rword("궆", "료"); | |
rword("넌", "보"); | |
rword("리", "긘"); | |
rword("러", "긘"); | |
rword("습", "슘"); | |
rword("봉", "넣"); | |
rword("픈", "곧"); | |
rword("페", "떼"); | |
rword("딘", "되", "티", "더"); | |
rchar("ㅌㅣ", "ㄷㅓ"); | |
rchar("ㄷㅐ", "ㅁㅓ"); | |
rchar("ㄷㅒ", "ㅁㅕ", "ㄸㅣ"); | |
char("ㄷㅣ$", constant("ㅁ")); | |
char("^ㅁ$", constant("ㄷㅣ")); | |
rchar("ㄱㅗ", "ㄲㅡ"); | |
rword("ㅍ", "고", "끄", "ㄸ"); | |
rchar("ㅍㅏ", "ㄱㅘ", "ㄸㅏ"); | |
rchar("ㅍㅣ", "ㄱㅢ", "ㄱㅚ", "ㄸㅣ"); | |
rchar("ㄱㅟ", "ㅋㅓ", "ㄱㅝ"); | |
rchar("ㅈㅓ", "ㄱㅕ"); | |
rchar_x("ㅠ", "ㅡㄲ"); | |
rchar_x("ㅜ", "ㅡㄱ"); | |
rword("ㅂ", "너"); | |
rchar("ㄴㅔ", "ㅂㅣ"); | |
rchar_xx("ㅘㅇ", "ㅏㅎ"); | |
rchar_xx("ㅗㅇ", "ㅡㅎ"); | |
rchar("ㄲㅛ", "ㄲㅗ"); | |
rchar_x("ㅢ", "ㅣㄱ"); | |
rchar_x("ㅟ", "ㅣㄲ"); | |
rchar_xx("ㅣㅁ", "ㅢㄴ"); | |
rchar_xx("ㅣㄹ", "ㅢㄷ"); | |
rchar_x("ㅚ", "ㅣㄴ"); | |
rchar_x("ㅘ", "ㅏㄴ"); | |
rchar_xx("ㅣㅂ", "ㅚㄴ"); | |
rchar_x("ㅕ", "ㅓㄱ"); | |
})(); | |
var findMatch = function(arr, func) { | |
for (var i = 0; i < arr.length; i++) { | |
if (func(arr[i])) { | |
return arr[i]; | |
} | |
} | |
return undefined; | |
} | |
return { | |
convert: function(text) { | |
var res = ""; | |
while (text.length > 0) { | |
var rule = findMatch(rules, function(r) { | |
if (r.type == 'word') { | |
return r.match(text); | |
} else { | |
var char = text[0]; | |
var jaso = hangul.split_strict(char)[0].join(""); | |
return r.match(jaso); | |
} | |
}); | |
if (rule) { | |
if (rule.type == 'word') { | |
var match = rule.match(text); | |
var processed = rule.process(match); | |
res = res + processed; | |
text = text.substring(match.length); | |
continue; | |
} else if (rule.type == 'char') { | |
var char = text[0]; | |
var jaso = hangul.split_strict(char)[0].join(""); | |
var converted = rule.process(jaso); | |
var joined = hangul.join_strict([converted], true); | |
res = res + joined; | |
text = text.substring(1); | |
} | |
} else { | |
var char = text[0]; | |
res = res + char; | |
text = text.substring(1); | |
} | |
} | |
return res; | |
} | |
} | |
})(); | |
var autoconvert = function() { | |
var text = $("#input_box").val(); | |
var converted = yamin.convert(text); | |
$("#result_box").text(converted); | |
} | |
autoconvert(); | |
$("#input_box").change(autoconvert).keyup(autoconvert); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment