User:Ykhwong/koLinks.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/* <nowiki> */
$(function() {
	var mainTitle = mw.config.get('wgTitle');
	var pageName = mw.config.get("wgPageName");
	var isDirty = false;
	var enSource = "";
	var showKoLinksCompleted = false;
	var captchaId = "";

	function onlyUnique(value, index, self) {
		return self.indexOf(value) === index;
	}

	window.setInputSelection = function(input, startPos, endPos) {
		input.focus();
		if (typeof input.selectionStart != "undefined") {
			input.selectionStart = startPos;
			input.selectionEnd = endPos;
		} else if (document.selection && document.selection.createRange) {
			// IE branch
			input.select();
			var range = document.selection.createRange();
			range.collapse(true);
			range.moveEnd("character", endPos);
			range.moveStart("character", startPos);
			range.select();
		}
	};

	window.setInputSelectionTa2 = function(startPos, endPos) {
		setInputSelection(document.getElementById('ta2'), startPos, endPos);
	};

	function getMatchIndexes(str, toMatch) {
		var re = new RegExp(toMatch, "ig"),
			indexMatches = [], match;

		while (match = re.exec(str)) {
			indexMatches.push(match.index);
		}

		return indexMatches;
	}

	function addWarn() {
	    window.addEventListener("beforeunload", function (e) {
	        if (!isDirty) {
	            return undefined;
	        }
	        
	        var confirmationMessage = 'It looks like you have been editing something. '
	                                + 'If you leave before saving, your changes will be lost.';
	
	        (e || window.event).returnValue = confirmationMessage;
	        return confirmationMessage;
	    });
	}

	function insertAtCursor(myField, myValue) {
		if (document.selection) {
			myField.focus();
			sel = document.selection.createRange();
			sel.text = myValue;
		} else if (myField.selectionStart || myField.selectionStart == '0') {
			var startPos = myField.selectionStart;
			var endPos = myField.selectionEnd;
			myField.value = myField.value.substring(0, startPos) +
				myValue +
				myField.value.substring(endPos, myField.value.length);
		} else {
			myField.value += myValue;
		}
		myField.focus();
	}

	function getEnSource() {
		$.get(
			'https://en.wikipedia.org/w/index.php?title=' + encodeURIComponent(pageName) + '&action=raw', function(cont) {
			enSource = cont;
		});
	}

	function dragElement(elmnt) {
		var pos1 = 0,
			pos2 = 0,
			pos3 = 0,
			pos4 = 0;
		if (document.getElementById(elmnt.id + "Header")) {
			document.getElementById(elmnt.id + "Header").onmousedown = dragMouseDown;
		} else {
			elmnt.onmousedown = dragMouseDown;
		}

		function dragMouseDown(e) {
			e = e || window.event;
			e.preventDefault();
			pos3 = e.clientX;
			pos4 = e.clientY;
			document.onmouseup = closeDragElement;
			document.onmousemove = elementDrag;
		}

		function elementDrag(e) {
			e = e || window.event;
			e.preventDefault();
			pos1 = pos3 - e.clientX;
			pos2 = pos4 - e.clientY;
			pos3 = e.clientX;
			pos4 = e.clientY;
			elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
			elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
		}

		function closeDragElement() {
			document.onmouseup = null;
			document.onmousemove = null;
		}
	}

	function getVal(text, key) {
		var retData = "";
		for (var i = 0; i < text.split(/\n/).length; i++) {
			var ln = text.split(/\n/)[i];
			var regex = "^\\s*\\|\\s*" + key + "\\s*=\\s*";
			var re = new RegExp(regex,"i");
			if (ln.match(re)) {
				 retData = ln.replace(re, "");
				 break;
			}
		}
		return retData.trim();
	}

	function getTmpl(text, key, isBeginning) {
		var retData = "";
		var detected = false;
		text = text.replace(/(infobox) +/i, "$1 ");
		for (var i = 0; i < text.split(/\n/).length; i++) {
			var ln = text.split(/\n/)[i];
			if (detected) {
				if ( /^(\}\}|==)/.test(ln) ) {
					retData += ln + "\n";
					break;
				}
				retData += ln + "\n";
				continue;
			}
			var regex = "";
			if (!isBeginning) {
				regex = ".*(\\{\\{\\s*" + key + "\\s*\\|.*)";
				var re1 = new RegExp(regex,"i");
				if (ln.match(re1)) {
					ln = ln.replace(re1, "$1").replace(/\}\}.*/, "}}");
					return ln.trim();
				}
			} else {
				regex = "^\\{\\{\\s*" + key + "\\s*(\\||$)";
				var re = new RegExp(regex,"i");
				if (ln.match(re)) {
					 detected = true;
					 retData += ln + "\n";
					 continue;
				}
			}
		}
		return retData.trim();
	}

	function getTmplLoose(text, key) {
		var retData = "";
		var detected = false;
		text = text.replace(/(infobox) +/i, "$1 ");
		for (var i = 0; i < text.split(/\n/).length; i++) {
			var ln = text.split(/\n/)[i];
			if (/^\s*'''/.test(ln)) {
				break;
			}
			if (detected) {
				retData += ln + "\n";
				continue;
			}
			var regex = "";
			regex = "^\\{\\{\\s*" + key + "\\s*(\\||$)";
			var re = new RegExp(regex,"i");
			if (ln.match(re)) {
				 detected = true;
				 retData += ln + "\n";
				 continue;
			}
		}
		return retData.trim();
	}
	function addBox() {
		if (!/^(0|2|10|14)$/.test(mw.config.get("wgNamespaceNumber"))) {
			return;
		}

		if ($("#koBox").length > 0) {
			return;
		}

		addWarn();

		var koBoxCss = {
			position: "fixed",
			top: $(window).height() - 500 - 175,
			left: $(window).width() - 400 - 30,
			minWidth: "400px",
			minHeight: "500px",
			zIndex: 9,
			backgroundColor: "#f1f1f1",
			border: "1px solid #d3d3d3",
			textAlign: "center"
		};
		var koBoxCssHeader = {
			padding: "10px",
			cursor: "move",
			zIndex: 10,
			backgroundColor: "#2196F3",
			color: "#fff"
		};

		$("body").append('<div id="koBox"><div id="koBoxHeader">koBox&nbsp;<span id="closeKoBox" style="text-align: right; cursor: pointer;">[Close]</span></div><textarea id="ta1" style="height: 370px;"></textarea><div id="captchaBox"><span id="captchaImg">CAPTCHA IMG</span>&nbsp;<input id="captchaWord" style="width: 100px; float: right; height: 75px;"/></div></div>');
		$("body").append('<div id="koBox2"><div id="koBox2Header">Source&nbsp;<span id="closeKoBox2" style="text-align: right; cursor: pointer;">[Close]</span></div><textarea id="ta2" style="height: 460px;"></textarea><div id="ta2_refs" style="max-width: 400px; height: 20px; overflow-y: scroll; overflow-x: hidden;"></div></div>');
		$("#koBox2").hide();
		$("#koBox, #koBox2").css(koBoxCss);
		$("#koBoxHeader, #koBox2Header").css(koBoxCssHeader);

		$("#koBoxHeader")
			.append('<br /><div id="showKoLinks" style="cursor: pointer; background-color: black; color: white;">START</div>')
			.append('&nbsp;<span class="koBoxButton" onClick="copyTitle();">Get Title</span>')
			.append('&nbsp;<span class="koBoxButton" onClick="copyLinks();">Get Links</span>')
			.append('&nbsp;<span class="koBoxButton" onClick="copyCategories();">Get Cats</span>')
			.append('&nbsp;<span class="koBoxButton" onClick="copyExtLinks();">Get ExtLinks</span>')
			.append('<br /><span class="koBoxButton" id="viewSource">View Source</span>')
			.append('<span class="koBoxButton" id="replaceLnk">[[ to *[[</span>')
			.append('<span class="koBoxButton" id="fillFilmVals">FillFilmVals</span>')
			.append('<span class="koBoxButton" id="sc">SC</span>')
			.append('<span class="koBoxButton" id="iw">IW</span>')
			.append('<br /><span class="koBoxButton" id="getCleanText">Get clean text</span>')
			.append('<span class="koBoxButton" id="cleanup">Cleanup</span>')
			.append('<span class="koBoxButton" id="translate">Translate</span>')
			.append('<span class="koBoxButton" id="setSiteLink">Set SiteLink</span>')
			.append('<br /><span class="koBoxButton" id="extSite">ExtSite</span>')
			.append('<span class="koBoxButton" id="openKoWiki">Open koWiki</span>')
			.append('<span class="koBoxButton" id="setKoWiki">Set koWiki</span>')
			.append('<label style="font-size: smaller;">Add on click<input type="checkbox" id="addOnClick" checked></label>');
		$(".koBoxButton").css({
			cursor: "pointer",
			fontSize: "smaller",
			backgroundColor: "#4CAF50",
			border: "none",
			color: "white",
			padding: "5px 10px",
			margin: "3px",
			textAlign: "center",
			textDecoration: "none",
			display: "inline-block"
		});

		dragElement(document.getElementById("koBox"));
		dragElement(document.getElementById("koBox2"));

		$("#showKoLinks").click(function() {
			showKoLinks();
		});
		$("#replaceLnk").click(function() {
			$("#ta1").val($("#ta1").val().replace(/^\[\[/mg, "* [["));
		});

		$("#extSite").click(function() {
			var tUrl;
			if (/Infobox +film/i.test(enSource)) {
				tUrl= 'https://movie.naver.com/movie/search/result.naver?query=' +
				encodeURIComponent(mainTitle.replace(/ +\(.*/, "")) +
				'&section=all&ie=utf8';
			} else {
				tUrl = 'https://search.naver.com/search.naver?sm=tab_hty.top&where=nexearch&query=' +
				encodeURIComponent(mainTitle.replace(/ +\(.*/, ""));
			}
			window.open(tUrl);
		});
		
		$("#openKoWiki").click(function() {
			var koTaText = $("#ta1").val();
			var koTitle = "";
			for ( var i = 0; i < koTaText.split(/\n/).length; i++ ) {
				var ln = koTaText.split(/\n/)[i];
				if (/^'''/.test(ln)) {
					koTitle = ln.replace(/^'''/, "").replace(/'''.*/, "");
					break;
				}
			}
			if (/\S/.test(koTitle)) {
				var tUrl = "https://ko.wikipedia.org/w/index.php?search=" + encodeURIComponent(koTitle);
				window.open(tUrl);
			}
		});

		$("#setKoWiki").click(function() {
			var koTaText = $("#ta1").val();
			var koTitle = "";
			for ( var i = 0; i < koTaText.split(/\n/).length; i++ ) {
				var ln = koTaText.split(/\n/)[i];
				if (/^'''/.test(ln)) {
					koTitle = ln.replace(/^'''/, "").replace(/'''.*/, "");
					break;
				}
			}

			if (!/\S/.test(koTitle)) {
				alert("koTitle not found");
				return;
			}

			var myJson = {
				action:'edit',
				summary: '',
				text: koTaText,
				title: koTitle
			};

			if (/\S/.test(captchaId) && /\S/.test($("#captchaWord").val())) {
				myJson.captchaid = captchaId;
				myJson.captchaword = $("#captchaWord").val();
			}

			mw.loader.using(['mediawiki.ForeignApi']).then(function() {
				var api = new mw.ForeignApi('https://ko.wikipedia.org/w/api.php');

				api.postWithEditToken(myJson).then( function ( e ) {
					if (e.edit.result === 'Failure') {
						if (e.edit.captcha && e.edit.captcha.id) {
							var captchaUrl = 'https://ko.wikipedia.org/w/index.php?title=특수:캡차/image&wpCaptchaId=' + e.edit.captcha.id;
							captchaId = e.edit.captcha.id;
							//window.open(captchaUrl);
							$("#captchaImg").html('<img src=' + captchaUrl + '>');
						} else {
							mw.notify( 'Failed to save the page.', { title: 'Failed' } );
						}
					} else {
						mw.notify( 'Page saved.', { title: 'Edited' } );
					}
				});
			});

		});

		$("#fillFilmVals").click(function() {
			var koTaText = $("#ta1").val();
			var resultDat = "";
			var enDat = "";
			for ( var i = 0; i < koTaText.split(/\n/).length; i++ ) {
				var ln = koTaText.split(/\n/)[i];
				if (/\|\s*촬영\s*=\s*/.test(ln) && ! /\|\s*촬영\s*=\s*\S/.test(ln)) {
					enDat = getVal(enSource, "cinematography");
					ln = ln.replace(/(\|\s*촬영\s*=\s*)/, "$1" + enDat);
				} else if (/\|\s*편집\s*=\s*/.test(ln) && ! /\|\s*편집\s*=\s*\S/.test(ln)) {
					enDat = getVal(enSource, "editing");
					ln = ln.replace(/(\|\s*편집\s*=\s*)/, "$1" + enDat);
				} else if (/\|\s*개봉\s*=\s*/.test(ln) && ! /\|\s*개봉\s*=\s*\S/.test(ln)) {
					enDat = getVal(enSource, "released");
					ln = ln.replace(/(\|\s*개봉\s*=\s*)/, "$1" + enDat).replace(/\{\{\s*film date\s*\|/ig, "{{영화 날짜|");
				} else if (/\|\s*시간\s*=\s*/.test(ln) && ! /\|\s*시간\s*=\s*\S/.test(ln)) {
					enDat = getVal(enSource, "runtime");
					ln = ln.replace(/(\|\s*시간\s*=\s*)/, "$1" + enDat).replace(/ (minutes|min\.)/ig, "분");
				} else if (/\|\s*언어\s*=\s*/.test(ln) && ! /\|\s*언어\s*=\s*\S/.test(ln)) {
					enDat = getVal(enSource, "language")
					.replace("English (language)", "영어")
					.replace("English", "영어")
					.replace("Russian", "러시아어")
					.replace("Spanish", "스페인어")
					.replace("Japanese", "일본어")
					;
					ln = ln.replace(/(\|\s*언어\s*=\s*)/, "$1" + enDat);
				} else if (/\|\s*음악\s*=\s*/.test(ln) && ! /\|\s*음악\s*=\s*\S/.test(ln)) {
					enDat = getVal(enSource, "music");
					ln = ln.replace(/(\|\s*음악\s*=\s*)/, "$1" + enDat);
				}

				resultDat += ln + "\n";
			}
			$("#ta1").val(resultDat);
		});

		function procVideoGame() {
			var resultDat = "";
			resultDat = "{{비디오 게임 정보\n|제목=\n|그림=\n}}" + "\n";
			resultDat += "'''제목'''(" + mainTitle.replace(/[_\s]\(.*\)$/, "") + ")\n\n";
			if ( /\{\{\s*(Video game reviews)/i.test(enSource) ) {
				resultDat += "== 평가 ==\n";
				resultDat += 
				getTmpl(enSource, "Video game reviews", true)
				.replace(/^\}\}/mg, "|align=none\n}}") +
				"\n\n== 각주 ==\n{{각주}}\n\n";
			}
			$("#ta1").val(resultDat);
			$("#showKoLinks").trigger("click");
			copyExtLinks();
		}
		
		function procCompany() {
			var resultDat = "";
			var logo = getVal(enSource, "logo").replace(/^\s*\[\[/, "").replace(/\|.*/, "").replace(/^(file:|image:)/i, "");
			var image = getVal(enSource, "image").replace(/^\s*\[\[/, "").replace(/\|.*/, "").replace(/^(file:|image:)/i, "");
			
			resultDat = "{{회사 정보\n";
			if (/\S/.test(logo)) { resultDat += "|로고=" + logo + "\n"; }
			if (/\S/.test(image)) { resultDat += "|그림=" + image + "\n"; }
			resultDat += "}}\n";
			resultDat += "'''제목'''(" + mainTitle.replace(/[_\s]\(.*\)$/, "").replace(/,\s*.*/, "") + ")은 \n\n";
			$("#ta1").val(resultDat);
			$("#showKoLinks").trigger("click");
			copyExtLinks();
		}

		function procSettlement() {
			var resultDat = "";
			var imgSkyline = getVal(enSource, "image_skyline").replace(/^\s*\[\[/, "").replace(/\|.*/, "").replace(/^(file:|image:)/i, "");
			var imgMap = getVal(enSource, "image_map").replace(/^\s*\[\[/, "").replace(/\|.*/, "").replace(/^(file:|image:)/i, "");

			if (/\S/.test(imgSkyline)) { resultDat += "[[파일:" + imgSkyline + "|thumb]]\n"; }
			if (/\S/.test(imgMap)) { resultDat += "[[파일:" + imgMap + "|thumb]]\n"; }
			resultDat += "'''제목'''(" + mainTitle.replace(/[_\s]\(.*\)$/, "").replace(/,\s*.*/, "") + ")은 \n\n";

			if (enSource.match(/(\{\{) *(Historical *population|Historical *populations|USCensusPop|US *Census *population|Philippine *Census) *(\|)*/i)) {
				var popData = "";
				resultDat += "== 인구 ==\n";
				if ( /\{\{\s*(Historical *populations)/i.test(enSource) ) {
					popData += getTmpl(enSource, "historical populations", true) + "\n";
				} else if ( /\{\{\s*(Historical *population)/i.test(enSource) ) {
					popData += getTmpl(enSource, "historical population", true) + "\n";
				} else if ( /\{\{\s*(USCensusPop)/i.test(enSource) ) {
					popData += getTmpl(enSource, "USCensusPop", true) + "\n";
				} else if ( /\{\{\s*(US *Census *population)/i.test(enSource) ) {
					popData += getTmpl(enSource, "US Census population", true) + "\n";
				} else if ( /\{\{\s*(Philippine Census)/i.test(enSource) ) {
					popData += getTmpl(enSource, "Philippine Census", true) + "\n";
				}
				if (/\|\s*align\s*=\s*(right|left|none)/i.test(popData)) {
					popData = popData.replace(/(\|\s*align\s*=\s*)(right|left)/i, "$1none");
				} else {
					popData = popData.replace(/\|/, "|align=none\n|");
				}
				resultDat += popData;
			}

			if (enSource.match(/(\{\{) *(weather *box|climate *box|infobox *weather|Klimatabelle) *(\|)*/i)) {
				resultDat += "\n== 기후 ==\n";
				if ( /\{\{\s*(weather box)/i.test(enSource) ) {
					resultDat += getTmpl(enSource, "weather box", true) + "\n";
				} else if ( /\{\{\s*(climate box)/i.test(enSource) ) {
					resultDat += getTmpl(enSource, "climate box", true) + "\n";
				} else if ( /\{\{\s*(infobox weather)/i.test(enSource) ) {
					resultDat += getTmpl(enSource, "infobox weather", true) + "\n";
				} else if ( /\{\{\s*(Klimatabelle)/i.test(enSource) ) {
					resultDat += getTmpl(enSource, "Klimatabelle", true) + "\n";
				}				
			}

			if (/<ref( |>)/i.test(resultDat)) {
				resultDat += "\n== 각주 ==\n{{각주}}\n\n";
			}
			$("#ta1").val(resultDat);
			$("#showKoLinks").trigger("click");
			copyExtLinks();
		}

		function procChem() {
			var resultDat = "";
			var formula = getVal(enSource, "formula");
			resultDat += getTmplLoose(enSource, "Chembox") + "\n";
			resultDat += "'''제목'''(" + mainTitle.replace(/[_\s]\(.*\)$/, "") + ")은 ";

			if (/\S/.test(formula)) {
				resultDat += "[[화학식]] " + formula + "을 갖는 ";
			}

			resultDat += "\n";
			if (/<ref( |>)/i.test(resultDat)) {
				resultDat += "\n== 각주 ==\n{{각주}}\n\n";
			}
			$("#ta1").val(resultDat);
			$("#showKoLinks").trigger("click");
			copyExtLinks();
		}

		function procAirport() {
			var resultDat = "";
			resultDat = "'''제목'''(" + mainTitle.replace(/[_\s]\(.*\)$/, "");
			
			if ( /\{\{\s*(airport codes)/i.test(enSource) ) {
				resultDat += ", " + getTmpl(enSource, "airport codes", false);
			}
			resultDat += ")\n\n";
			if ( /\{\{\s*(Airport-Statistics)/i.test(enSource) ) {
				resultDat += "== 통계 ==\n";
				resultDat += getTmpl(enSource, "Airport-Statistics", false) + "\n";
			}

			$("#ta1").val(resultDat);
			$("#showKoLinks").trigger("click");
			copyExtLinks();
		}

		function procSoftware() {
			var resultDat = "";
			if ( /\{\{\s*(infobox +software)/i.test(enSource)) {
				resultDat = getTmpl(enSource, "Infobox software", true);
			} else if ( /\{\{\s*(infobox +OS)/i.test(enSource)) {
				resultDat = getTmpl(enSource, "Infobox OS", true);
			} else {
				resultDat = getTmpl(enSource, "Infobox video game engine", true);
			}
			resultDat = resultDat
				.replace(/\[\[Unix-like(\]\]|\||#)/img, "[[유닉스 계열$1")
				.replace(/\[\[Cross-platform(\]\]|\||#)/img, "[[크로스 플랫폼$1")
				.replace(/\[\[C \(Programming language\)(\]\]|\||#)/img, "[[C (프로그래밍 언어)$1")
				.replace(/\[\[GNU General Public License(\]\]|\||#)/img, "[[GNU 일반 공중 사용 허가서$1")
				.replace(/\[\[GNU Lesser General Public License(\]\]|\||#)/img, "[[GNU 약소 일반 공중 사용 허가서$1")
				.replace(/\[\[Python \(programming language\)(\]\]|\||#)/img, "[[파이썬$1")
				.replace(/\[\[Command \(computing\)(\]\]|\||#)/img, "[[명령어 (컴퓨팅)$1")
				.replace(/\[\[Proprietary software(\]\]|\||#)/img, "[[사유 소프트웨어$1")
				.replace(/\[\[Library \(computing\)(\]\]|\||#)/img, "[[라이브러리 (컴퓨팅)$1")
				+ "\n";
			resultDat += "'''제목'''(" + mainTitle.replace(/[_\s]\(.*\)$/, "") + ")\n";
			$("#ta1").val(resultDat);
			$("#showKoLinks").trigger("click");
			copyExtLinks();
		}

		$("#sc").click(function() {
			if ( /\{\{\s*(infobox +film|infobox +movie|film +infobox|infobox +short +film)/i.test(enSource) ) {
				$("#showKoLinks").trigger("click");
				$('#addOnClick').prop('checked', true);
				copyExtLinks();
				$("#fillFilmVals").trigger("click");
			} else if ( /\{\{\s*(infobox +software|Infobox +video +game +engine|Infobox +OS)/i.test(enSource)) {
				$('#addOnClick').prop('checked', true);
				procSoftware();
			} else if ( /\{\{\s*(Infobox +)(video +game|VG)/i.test(enSource) ) {
				$('#addOnClick').prop('checked', true);
				procVideoGame();
			} else if ( /\{\{\s*(infobox +airport)/i.test(enSource)) {
				$('#addOnClick').prop('checked', true);
				procAirport();
			} else if ( /\{\{\s*(chembox)/i.test(enSource)) {
				$('#addOnClick').prop('checked', true);
				procChem();
			} else if ( /\{\{\s*Infobox settlement/i.test(enSource)) {
				$('#addOnClick').prop('checked', true);
				procSettlement();
			} else if ( /\{\{\s*Infobox company/.test(enSource)) {
				$('#addOnClick').prop('checked', true);
				procCompany();
			}
		});
		
		$("#iw").click(function() {
			var koTaText = $("#ta1").val();
			$("#ta1").val(koTaText + "\n[[en:" + mainTitle + "]]\n");
		});

		$("#translate").click(function() {
			var koTaText = $("#ta1").val();
			translate(koTaText).then(text => $("#ta1").val(replaceStr(text)));
		});
		
		$("#setSiteLink").click(function() {
			var koTaText = $("#ta1").val();
			var koTitle = "";
			for ( var i = 0; i < koTaText.split(/\n/).length; i++ ) {
				var ln = koTaText.split(/\n/)[i];
				if (/^'''/.test(ln)) {
					koTitle = ln.replace(/^'''/, "").replace(/'''.*/, "");
					break;
				}
			}
			if (!/\S/.test(koTitle)) {
				alert("koTitle not found");
				return;
			}
			var wikidataAPI = new mw.ForeignApi('https://www.wikidata.org/w/api.php');
			var json = {
				action: 'wbsetsitelink',
				site: "enwiki",
				title: pageName,
				linksite: "kowiki",
				linktitle: koTitle
			};
			mw.loader.using('mediawiki.ForeignApi').then(function() {
				return wikidataAPI.postWithToken('csrf', json);
			});
		});
		
		$("#cleanup").click(function() {
			var koTaText = $("#ta1").val();
			$("#ta1").val(cleanupText(koTaText));
		});

		$("#getCleanText").click(function() {
			setCleanText();
		});

		$("#viewSource").click(function() {
			$("#koBox2").css({
				top: $(window).height() - 500 - 30,
				left: $(window).width() - 400 - 400 - 30
			});
			$("#koBox2").show();
			$("#ta2").val(enSource);

			var refStartIndex = getMatchIndexes($("#ta2").val(), '<ref( |\>)');
			var refEndIndex = getMatchIndexes($("#ta2").val(), '<\/ref>|\/>');
			for (var ii = 0; ii < refStartIndex.length; ii++) {
				$("#ta2_refs").append("<span style='display: inline-block;' onclick='setInputSelectionTa2("+ refStartIndex[ii] + ', ' + (refEndIndex[ii] + 6) + ");'>[" + ii + "]</span>&nbsp;");
			}
			setInputSelectionTa2(0,0);
			$("#ta2").scrollTop(0);
		});
		$("#closeKoBox").click(function() {
			$("#koBox").hide();
		});
		$("#closeKoBox2").click(function() {
			$("#koBox2").hide();
		});

		$("#ta1").keyup(function() {
			isDirty = true;
		});

	}

	window.copyToClipboard = function(text, plain) {
		if (!/\S/.test(text)) {
			return;
		}
		const elem = document.createElement('textarea');
		text = plain ? text : text.replace(/^\(/, "").replace(/\)$/, "");
		if (plain) {
			// do nothing
		} else if (/^틀:/.test(text)) {
			text = "{{" + text.replace(/^틀:/, "") + "}}";
		} else {
			text = "[[" + text + "]]";
		}
		elem.value = text;
		document.body.appendChild(elem);
		elem.select();
		document.execCommand('copy');
		document.body.removeChild(elem);
		if ($("#addOnClick").is(":checked")) {
			insertAtCursor(document.getElementById("ta1"), text);
		}
	};

	window.copyTitle = function() {
		copyToClipboard(mainTitle, true);
	};

	window.copyCategories = function() {
		var cats = "";
		$("#mw-normal-catlinks sup").each(function(idx) {
			cats += "[[" + $(this).text().replace(/^\(/, "").replace(/\)$/, "") + "]]\n";
		});
		copyToClipboard(cats, true);
	};

	window.copyLinks = function() {
		var cats = "";
		$(".koTitleGrp").each(function(idx) {
			var cat = $(this).text().replace(/^\(/, "").replace(/\)$/, "");
			if (!/^분류:/.test(cat)) {
				cats += "* [[" + cat + "]]\n";
			}
		});
		copyToClipboard(cats, true);
	};

	window.copyExtLinks = function() {
		var hold = false;
		var resultDat = "";
		for (var i = 0; i < enSource.split(/\n/).length; i++) {
			var ln = enSource.split(/\n/)[i];
			if ( hold ) {
				if ( /^\s*\[\[\s*category/i.test(ln) ) {
					break;
				}
				if (
					( ! /^\s*\{\{/.test(ln) || /^\s*\{\{\s*authority(\s|_)*control\s*\}\}\s*$/i.test(ln)
					|| /^\s*\{\{\s*taxonbar\s*(\||\}\})/i.test(ln)
					)
					&& /\S/.test(ln) ) {
					resultDat += ln + "\n";
					continue;
				}
			}
			if ( /^\s*==\s*external\s+links\s*==/i.test(ln)) {
				hold = true;
				continue;
			}
		}
		if ( /\S/.test(resultDat) ) {
			if (! /== *외부 링크 *==/.test($("#ta1").val())) {
				resultDat = "== 외부 링크 ==" + "\n" + resultDat;
			}
		}
		copyToClipboard(resultDat, true);
	};

	function cleanupText(text) {
		var result = text;
		result = result
			.replace(/\[\d+\]/mg, '')
			.replace(/\[citation needed\]/mg, '')
			.replace(/\[better source needed\]/mg, '');
		return result;
	}
	
	function setCleanText() {
		$.get(
			'https://en.wikipedia.org/w/api.php?action=query&prop=extracts&titles=' + encodeURIComponent(mainTitle) + '&explaintext=1&exintro=1&formatversion=2&format=json', function(cont) {
				var mData = cont.query.pages[0].extract.replace(/\n/g, "\n\n");
				$("#ta1").val(mData);
		});
	}

	function translate(text) {
		var source = 'en';
		var target = 'ko';

		var url = 'https://translate.googleapis.com/translate_a/single?client=gtx&sl='
		+ source + "&tl=" + target + "&dt=t&q=" + encodeURIComponent(text);
	
		var parseJSON = function(txt) {
			return JSON.parse(txt.split(',').map( x => x || 'null').join(','));
		};

		var joinSnippets = function(json) {
			return json[0].map( x => x[0] ).join('');
		};

		return fetch(url)
		.then( res => res.text())
		.then( text => joinSnippets(parseJSON(text)) )
		.catch( reason => console.log('Google Translate: ' + reason)  );
	}

	const matchHangul = [
		/* ㅏ,ㅓ,ㅕ,ㅗ,ㅛ,ㅜ,ㅡ,ㅣ,ㅐ,ㅚ,ㅟ */
		// ㅏ 
		{ key: '[각-갛]', val: '간' },
		{ key: '[낙-낳]', val: '난' },
		{ key: '[닥-닿]', val: '단' },
		{ key: '[락-랗]', val: '란' },
		{ key: '[막-맣]', val: '만' },
		{ key: '[박-밯]', val: '반' },
		{ key: '[삭-샇]', val: '산' },
		{ key: '[악-앟]', val: '안' },
		{ key: '[작-잫]', val: '잔' },
		{ key: '[착-챃]', val: '찬' },
		{ key: '[칵-캏]', val: '칸' },
		{ key: '[탁-탛]', val: '탄' },
		{ key: '[팍-팧]', val: '판' },
		{ key: '[학-핳]', val: '한' },
		{ key: '[깍-깧]', val: '깐' },
		{ key: '[딱-땋]', val: '딴' },
		{ key: '[빡-빻]', val: '빤' },
		{ key: '[싹-쌓]', val: '싼' },
		{ key: '[짝-짷]', val: '짠' },
	
		// ㅓ 
		{ key: '[건-겋]', val: '건' },
		{ key: '[넉-넣]', val: '넌' },
		{ key: '[덕-덯]', val: '던' },
		{ key: '[럭-렇]', val: '런' },
		{ key: '[먹-멓]', val: '먼' },
		{ key: '[벅-벟]', val: '번' },
		{ key: '[석-섷]', val: '선' },
		{ key: '[억-엏]', val: '언' },
		{ key: '[적-젛]', val: '전' },
		{ key: '[척-첳]', val: '천' },
		{ key: '[컥-컿]', val: '컨' },
		{ key: '[턱-텋]', val: '턴' },
		{ key: '[퍽-펗]', val: '펀' },
		{ key: '[헉-헣]', val: '헌' },
		{ key: '[꺽-껗]', val: '껀' },
		{ key: '[떡-떻]', val: '떤' },
		{ key: '[뻑-뻫]', val: '뻔' },
		{ key: '[썩-쎃]', val: '썬' },
		{ key: '[쩍-쩧]', val: '쩐' },
	
		// ㅕ
		{ key: '[견-곃]', val: '견' },
		{ key: '[녁-녛]', val: '년' },
		{ key: '[뎍-뎧]', val: '뎐' },
		{ key: '[력-렿]', val: '련' },
		{ key: '[멱-몋]', val: '면' },
		{ key: '[벽-볗]', val: '변' },
		{ key: '[셕-셯]', val: '션' },
		{ key: '[역-옇]', val: '연' },
		{ key: '[젹-졓]', val: '젼' },
		{ key: '[쳑-쳫]', val: '쳔' },
		{ key: '[켝-켷]', val: '켠' },
		{ key: '[텩-톃]', val: '텬' },
		{ key: '[펵-폏]', val: '편' },
		{ key: '[혁-혛]', val: '현' },
		{ key: '[껵-꼏]', val: '껸' },
		{ key: '[뗙-뗳]', val: '뗜' },
		{ key: '[뼉-뼣]', val: '뼌' },
		{ key: '[쎡-쎻]', val: '쎤' },
		{ key: '[쪅-쪟]', val: '쪈' },
	
		// ㅗ
		{ key: '[곡-곻]', val: '곤' },
		{ key: '[녹-놓]', val: '논' },
		{ key: '[독-돟]', val: '돈' },
		{ key: '[록-롷]', val: '론' },
		{ key: '[목-뫃]', val: '몬' },
		{ key: '[복-봏]', val: '본' },
		{ key: '[속-솧]', val: '손' },
		{ key: '[옥-옿]', val: '온' },
		{ key: '[족-좋]', val: '존' },
		{ key: '[촉-촣]', val: '촌' },
		{ key: '[콕-콯]', val: '콘' },
		{ key: '[톡-톻]', val: '톤' },
		{ key: '[폭-퐇]', val: '폰' },
		{ key: '[혹-홓]', val: '혼' },
		{ key: '[꼭-꽇]', val: '꼰' },
		{ key: '[똑-똫]', val: '똔' },
		{ key: '[뽁-뽛]', val: '뽄' },
		{ key: '[쏙-쏳]', val: '쏜' },
		{ key: '[쪽-쫗]', val: '쫀' },
	
		// ㅛ
		{ key: '[굑-굫]', val: '굔' },
		{ key: '[뇩-눃]', val: '뇬' },
		{ key: '[됵-둏]', val: '됸' },
		{ key: '[룍-룧]', val: '룐' },
		{ key: '[묙-묳]', val: '묜' },
		{ key: '[뵥-뵿]', val: '뵨' },
		{ key: '[쇽-숗]', val: '숀' },
		{ key: '[욕-욯]', val: '욘' },
		{ key: '[죡-죻]', val: '죤' },
		{ key: '[쵹-춓]', val: '쵼' },
		{ key: '[쿅-쿟]', val: '쿈' },
		{ key: '[툑-툫]', val: '툔' },
		{ key: '[푝-푷]', val: '푠' },
		{ key: '[횩-훃]', val: '횬' },
		{ key: '[꾝-꾷]', val: '꾠' },
		{ key: '[뚁-뚛]', val: '뚄' },
		{ key: '[뾱-뿋]', val: '뾴' },
		{ key: '[쑉-쑣]', val: '쑌' },
		{ key: '[쬭-쭇]', val: '쬰' },
	
		// ㅜ
		{ key: '[국-궇]', val: '군' },
		{ key: '[눅-눟]', val: '눈' },
		{ key: '[둑-둫]', val: '둔' },
		{ key: '[룩-뤃]', val: '룬' },
		{ key: '[묵-뭏]', val: '문' },
		{ key: '[북-붛]', val: '분' },
		{ key: '[숙-숳]', val: '순' },
		{ key: '[욱-웋]', val: '운' },
		{ key: '[죽-줗]', val: '준' },
		{ key: '[축-춯]', val: '춘' },
		{ key: '[쿡-쿻]', val: '쿤' },
		{ key: '[툭-퉇]', val: '툰' },
		{ key: '[푹-풓]', val: '푼' },
		{ key: '[훅-훟]', val: '훈' },
		{ key: '[꾹-꿓]', val: '꾼' },
		{ key: '[뚝-뚷]', val: '뚠' },
		{ key: '[뿍-뿧]', val: '뿐' },
		{ key: '[쑥-쑿]', val: '쑨' },
		{ key: '[쭉-쭣]', val: '쭌' },
		
		// ㅡ
		{ key: '[극-긓]', val: '근' },
		{ key: '[늑-늫]', val: '는' },
		{ key: '[득-듷]', val: '든' },
		{ key: '[륵-릏]', val: '른' },
		{ key: '[믁-믛]', val: '믄' },
		{ key: '[븍-븧]', val: '븐' },
		{ key: '[슥-슿]', val: '슨' },
		{ key: '[윽-읗]', val: '은' },
		{ key: '[즉-즣]', val: '즌' },
		{ key: '[측-츻]', val: '츤' },
		{ key: '[큭-킇]', val: '큰' },
		{ key: '[특-틓]', val: '튼' },
		{ key: '[픅-픟]', val: '픈' },
		{ key: '[흑-흫]', val: '흔' },
		{ key: '[끅-끟]', val: '끈' },
		{ key: '[뜩-띃]', val: '뜬' },
		{ key: '[쁙-쁳]', val: '쁜' },
		{ key: '[쓱-씋]', val: '쓴' },
		{ key: '[쯕-쯯]', val: '쯘' },
		
		// ㅣ
		{ key: '[긱-깋]', val: '긴' },
		{ key: '[닉-닣]', val: '닌' },
		{ key: '[딕-딯]', val: '딘' },
		{ key: '[릭-맇]', val: '린' },
		{ key: '[믹-밓]', val: '민' },
		{ key: '[빅-빟]', val: '빈' },
		{ key: '[식-싷]', val: '신' },
		{ key: '[익-잏]', val: '인' },
		{ key: '[직-짛]', val: '진' },
		{ key: '[칙-칳]', val: '친' },
		{ key: '[킥-킿]', val: '킨' },
		{ key: '[틱-팋]', val: '틴' },
		{ key: '[픽-핗]', val: '핀' },
		{ key: '[힉-힣]', val: '힌' },
		{ key: '[끽-낗]', val: '낀' },
		{ key: '[띡-띻]', val: '띤' },
		{ key: '[삑-삫]', val: '삔' },
		{ key: '[씩-앃]', val: '씬' },
		{ key: '[찍-찧]', val: '찐' },
	
		// ㅐ
		{ key: '[객-갷]', val: '갠' },
		{ key: '[낵-냏]', val: '낸' },
		{ key: '[댁-댛]', val: '댄' },
		{ key: '[랙-랳]', val: '랜' },
		{ key: '[맥-맿]', val: '맨' },
		{ key: '[백-뱋]', val: '밴' },
		{ key: '[색-샣]', val: '샌' },
		{ key: '[액-앻]', val: '앤' },
		{ key: '[잭-쟇]', val: '잰' },
		{ key: '[책-챟]', val: '챈' },
		{ key: '[캑-캫]', val: '캔' },
		{ key: '[택-탷]', val: '탠' },
		{ key: '[팩-퍃]', val: '팬' },
		{ key: '[핵-햏]', val: '핸' },
		{ key: '[깩-꺃]', val: '깬' },
		{ key: '[땍-땧]', val: '땐' },
		{ key: '[빽-뺗]', val: '뺀' },
		{ key: '[쌕-쌯]', val: '쌘' },
		{ key: '[짹-쨓]', val: '짼' },
	
		// ㅚ
		{ key: '[괵-굏]', val: '괸' },
		{ key: '[뇍-뇧]', val: '뇐' },
		{ key: '[됙-됳]', val: '된' },
		{ key: '[뢱-룋]', val: '뢴' },
		{ key: '[뫽-묗]', val: '묀' },
		{ key: '[뵉-뵣]', val: '뵌' },
		{ key: '[쇡-쇻]', val: '쇤' },
		{ key: '[왹-욓]', val: '왼' },
		{ key: '[죅-죟]', val: '죈' },
		{ key: '[쵝-쵷]', val: '쵠' },
		{ key: '[쾩-쿃]', val: '쾬' },
		{ key: '[퇵-툏]', val: '퇸' },
		{ key: '[푁-푛]', val: '푄' },
		{ key: '[획-횧]', val: '횐' },
		{ key: '[꾁-꾛]', val: '꾄' },
		{ key: '[뙥-뙿]', val: '뙨' },
		{ key: '[뾕-뾯]', val: '뾘' },
		{ key: '[쐭-쑇]', val: '쐰' },
		{ key: '[쬑-쬫]', val: '쬔' },
	
		// ㅟ
		{ key: '[귁-귛]', val: '귄' },
		{ key: '[뉙-뉳]', val: '뉜' },
		{ key: '[뒥-뒿]', val: '뒨' },
		{ key: '[뤽-륗]', val: '륀' },
		{ key: '[뮉-뮣]', val: '뮌' },
		{ key: '[뷕-뷯]', val: '뷘' },
		{ key: '[쉭-슇]', val: '쉰' },
		{ key: '[윅-윟]', val: '윈' },
		{ key: '[쥑-쥫]', val: '쥔' },
		{ key: '[췩-츃]', val: '췬' },
		{ key: '[퀵-큏]', val: '퀸' },
		{ key: '[튁-튛]', val: '튄' },
		{ key: '[퓍-퓧]', val: '퓐' },
		{ key: '[휙-휳]', val: '휜' },
		{ key: '[뀍-뀧]', val: '뀐' },
		{ key: '[뛱-뜋]', val: '뛴' },
		{ key: '[쀡-쀻]', val: '쀤' },
		{ key: '[쒹-쓓]', val: '쒼' },
		{ key: '[쮝-쮷]', val: '쮠' },
	];
	
	function replaceStr(txt) {
		var result = "";
		txt = txt
		.replace(/좁습니다(\.|<|\()/g,  '좁다$1')
		.replace(/넓습니다(\.|<|\()/g,  '넓다$1')
		.replace(/졌습니다(\.|<|\()/g,  '졌다$1')
		.replace(/([있없갔었였했았렸렀짧꼈겠켰됐났쳤겼같높낮녔많깝왔썼잤랐렵냈뒀혔롭럽좋싫췄섰웠맵])습니다(\.|<|\()/g,  '$1다$2')
		.replace(/ (우세|유능|무능|무능력|촉촉|익숙|순|편안|편리|간편|중요|확실|불확실|필요|불편|편|동일|암울|우울|귀중|소중|모호|애매|애매모호|유명|저명|다양|잔인|강인|상이|편협|협소|광대|광활|불과|간결|가능|불가|불가능|흔|가득|독특|특별|적합|부적합|적절|부적절|유사|유연|뻣뻣|행복|비슷|분명|곤란|불안)합니다(\.|<|\()/g,  ' $1하다$2')
		//.replace(/이기도 합니다(\.|<|\()/g,'이기도 하다$1') // TO-DO: Fix 학생이기도 합니다(학생이기도 하다) and 쓰이기도 합니다(쓰이기도 한다)
		.replace(/ 아닙니다(\.|<|\()/g,' 아니다$1')
		.replace(/ 보입니다(\.|<|\()/g,' 보인다$1')
		.replace(/ 줄입니다(\.|<|\()/g,' 줄인다$1')
		.replace(/ 높입니다(\.|<|\()/g,' 높인다$1')
		.replace(/ 작습니다(\.|<|\()/g,' 작다$1')
		.replace(/ 바람직합니다(\.|<|\()/g,' 바람직하다$1')
		.replace(/ 저렴합니다(\.|<|\()/g,' 저렴하다$1')
		//.replace(/ 절입니다(\.|<|\()/g,' 절인다$1') // TO-DO: Fix noun(절) and verb(절)
		.replace(/들입니다(\.|<|\()/g,'들인다$1') // e.g, 들인다, 곁들인다
		.replace(/입니다(\.|<|\()/g,'이다$1')
		.replace(/쁩니다(\.|<|\()/g,'쁘다$1') // e.g, 기쁩니다, 예쁩니다
		.replace(/쉽니다(\.|<|\()/g,'쉰다$1') // e.g, 내쉽니다
		.replace(/쉽습니다(\.|<|\()/g,'쉽다$1') // e.g, 쉽습니다, 아쉽습니다
		.replace(/ 부릅니다(\.|<|\()/g,' 부른다$1')
		.replace(/ 바릅니다(\.|<|\()/g,' 바른다$1')
		.replace(/릅니다(\.|<|\()/g,'르다$1') // e.g, 푸르릅니다, 다릅니다
		.replace(/ 깁니다(\.|<|\()/g, ' 길다$1'); // but note: 굶깁니다 → 굶긴다
	
		for ( var i=0; i < txt.split(/\n/).length; i++ ) {
			var line = txt.split(/\n/)[i];
			if ( ! /니다(\.|<|\()/.test(line) ) {
				result += line + "\n";
				continue;
			}
			// e.g, 엮습니다 → 엮는다
			if (/습니다(\.|<|\()/.test(line)) {
				line = line.replace(/습니다(\.|<|\()/g, '는다$1');
			}
			if (/[가-힣]니다(\.|<|\()/.test(line)) {
				for ( var i2=0; i2 < matchHangul.length; i2++ ) {
					var key = matchHangul[i2].key;
					var val = matchHangul[i2].val;
					line = line.replace(new RegExp(key + "니다(\\.|<|\\()", "g"), val + "다$1");
				}
			}
			result += line + "\n";
		}
		return result.trim() + "\n";
	}

	function showKoLinks() {
		var titles = [];

		$("#mw-content-text a, #catlinks a").each(function(index) {
			if ($(this).hasClass('mw-redirect')) {
				$(this).append('<sup style="user-select: none;">[Redirect]</sup>');
			}

			if (
				$(this).attr('title') &&
				!$(this).attr('aria-label') &&
				!/Edit section: /.test($(this).attr('title'))
			) {
				titles.push($(this).attr('title'));
			}
		});
		titles = titles.filter(onlyUnique);

		for (var i = 0; i < titles.length; i++) {
			$.get("/w/api.php?action=query&titles=" + encodeURIComponent(titles[i]) +
			"&redirects&prop=langlinks&format=json&lllimit=500", function(data) {
				if (data.query.pages && Object.values(data.query.pages)[0].langlinks) {
					var title = Object.values(data.query.pages)[0].title;
					var langLinks = Object.values(data.query.pages)[0].langlinks;
					var koTitle = "";
					var zhFound = false;
					var jaFound = false;
					var koFound = false;
					for (var i2 = 0; i2 < langLinks.length; i2++) {
						if (langLinks[i2].lang === "ko") {
							koFound = true;
							koTitle = langLinks[i2]["*"];
							langFound = true;
							if (zhFound && jaFound && koTitle !== "") { break; }
							continue;
						}
						if (langLinks[i2].lang === "zh") {
							zhFound = true;
							if (zhFound && jaFound && koTitle !== "") { break; }
							continue;
						}
						if (langLinks[i2].lang === "ja") {
							jaFound = true;
							if (zhFound && jaFound && koTitle !== "") { break; }
							continue;
						}
					}
					//var koTitle = Object.values(data.query.pages)[0].langlinks[0]["*"];
					if (data.query.redirects && (data.query.redirects)[0].from) {
						title = Object.values(data.query.redirects)[0].from;
					}
					$("#mw-content-text a, #catlinks a").each(function(idx) {
						if ($(this).prop("title") === title && !$(this).data("koUsed")) {
							$(this).data("koUsed", "true");
							if (koTitle !== "") {
								$(this).append('<a href="javascript:void(null);" onClick="copyToClipboard(this.innerText, false);" class="koTitleGrp" style="color: green;"><sup style="user-select: none;">(' + koTitle + ')</sup></a>');
							}
							if (zhFound) {
								$(this).append('<a href="javascript:void(null);"><sub style="user-select: none; color: green;">[Z]</sub></a>');
							}
							if (jaFound) {
								$(this).append('<a href="javascript:void(null);"><sub style="user-select: none; color: green;">[J]</sub></a>');
							}
							if (koFound) {
								$(this).append('<a href="javascript:void(null);"><sub style="user-select: none; color: green;">[K]</sub></a>');
							}
							if (zhFound && jaFound && !koFound) {
								$(this).append('<a href="javascript:void(null);"><sub style="user-select: none; color: green;">[-]</sub></a>');
							}
							if (koTitle === "" && !zhFound && !jaFound) {
								$(this).append('<a href="javascript:void(null);"><sub style="user-select: none; color: green;">[*' + langLinks.length + ']</sub></a>');
							}
						}
					});
				}
			});
		}
		$("#mw-normal-catlinks").prepend('<span style="cursor: pointer;" onClick="copyCategories();">(Get)</span>&nbsp;');
		$(".image").each(function(idx) {
			$(this).prepend(
'<a href="javascript:void(null);" onClick="copyToClipboard(\'File:\' + this.innerText + \'|thumb\', false);" style="user-select: none;">' +
				$(this).attr("href").replace(/.*File:/, "") +
				'</a>'
			);
		});
		showKoLinksCompleted = true;
	}
	getEnSource();
	addBox();
}());
/* </nowiki> */