Skip to content

Instantly share code, notes, and snippets.

@foriequal0
Last active May 20, 2024 05:26
Show Gist options
  • Save foriequal0/154e73d3289d808e8ce94603f5eff6a4 to your computer and use it in GitHub Desktop.
Save foriequal0/154e73d3289d808e8ce94603f5eff6a4 to your computer and use it in GitHub Desktop.
브라우저의 모든 텍스트를 야민정음으로 바꿔줍니다
// 브라우저에 GreaseMonkey(Firefox) TamperMonkey(Chrome) 을 설치하고,
// https://gist.github.com/foriequal0/154e73d3289d808e8ce94603f5eff6a4/raw/yaminjeongeum.user.js
// 위 링크를 브라우저에 입력하면 자동으로 스크립트를 설치하겠느냐는 창이 뜹니다.
// ==UserScript==
// @name yaminjeongeum
// @namespace yaminjeongeum.kr
// @description 야민정음
// @include *
// @exclude file://*
// @version 1
// @grant none
// @run-at document-end
// ==/UserScript==
(function () {
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 inArray = function (item, array) {
for (var i = 0; i < array.length; i++) {
if (array[i] === item) {
return i;
}
}
return -1;
}
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 yamin = (function () {
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("노래", "놃");
rword("ㅂ", 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("비버", "뜨또");
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", "ㅏ기ㄹ");
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 converted = new Set();
function yaminate(root) {
for (var child of root.childNodes || []) {
yaminate(child);
}
if (root.nodeName == "#text" && !converted.has(root)) {
root.nodeValue = yamin.convert(root.nodeValue);
converted.add(root);
}
}
yaminate(document.body);
var observer = new MutationObserver(function (changes) {
for (var change of changes) {
yaminate(change.target);
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
})();
@BadSchool
Copy link

복복 - 뽁 을
복복 - 뾲 으로 바꿔야 할 것 같습니다!

@gerard2001
Copy link

ㄸㄸㄸ 머단하N비요

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment