사용자:하늘/EditTools.js: 두 판 사이의 차이

편집 요약 없음
잔글 (Chirho님이 사용자:Cerulean/EditTools.js 문서를 넘겨주기를 만들지 않고 사용자:하늘/EditTools.js 문서로 이동했습니다: "Cerulean" 사용자의 이름을 "하늘"(으)로 바꿀 때 문서를 자동으로 이동했습니다)
(차이 없음)

2022년 5월 11일 (수) 10:30 판

/**
 * 원본 [[mw:User:Alex Smotrov/edittools.js]], 수정본 리브레 위키 이용자 Cerulean, Utolee90
 * 
 * Configuration (to be set from [[Special:MyPage/common.js]]):
 *   window.charinsertCustom – Object. Merged into the default charinsert list. For example, setting
 *       this to { Symbols: '‽' } will add the interrobang to the end of the Symbols section.
 *   window.editToolsRecall – Boolean. Set true to create a recall switch.
 *   window.charinsertDontMove – Boolean. Set true to leave the box in its default position, rather
 *       than moving it above the edit summary.
 *   window.updateEditTools() – Function. Call after updating window.charinsertCustom to regenerate the
 *       EditTools window.
 * 
 *	global jQuery, mw, charinsertCustom
 *	window.updateEditTools = function () {};
*/

$(".mw-editTools > #mw-edittools-charinsert").remove(); //기존 edittools 제거
mw.loader.load('//librewiki.net/index.php?title=User:cerulean/EditTools.css&action=raw&ctype=text/css', 'text/css');

var editTools;
//editTools.charinsert.로마자  editTools.charinsert.그리스어처럼 다른 js 코드에서 편집 도구들을 추가할 수 있습니다.

$(document).ready(function ($) {
	var $currentFocused;

	function getSelectedSection() {
		var selectedSection = mw.storage.get(editTools.storageKey) || mw.storage.session.get(editTools.storageKey);
		return selectedSection;
	}

	function saveSelectedSection(newIndex) {
		mw.storage.set(editTools.storageKey, newIndex) || mw.storage.session.set(editTools.storageKey, newIndex);
	}

	editTools = {
		// 각 심볼은 '카테고리 이름' : '문자셋 이름', 형태로 작성합니다. 자바스크립트 오브젝트 형식으로 처리하므로 반드시 카테고리 이름, 문자셋 이름 앞뒤로 따옴표를 추가하고, 맨 뒤에는 반점(,)으로 구분하셔야 합니다.
		// 카테고리를 구별할 때에는 문자셋 이름 부분에 (카테고리명): 기호를 추가합니다.
		// 심볼을 구분할 때에는 띄어쓰기를 이용하며, 같은 심볼 안에서 공백을 입력할 때에는 온점 .을 이용합니다. 단 =기호 이후에는 .을 입력하면 온점이 입력되는 현상이 있어 공백을 삽입할 때 _기호를 사용합니다.
		// 버튼 형태로 심볼을 분리할 때에는 _기호를 사용하면 됩니다. 
		// + 기호를 입력하면 심볼을 입력할 때 커서가 위치하는 지점을 지정할 수 있습니다.
		// 줄넘김을 표현할 때에는 \n을 삽입합니다. 반드시 뒤에 공백을 띄워줘야 제대로 작동합니다. 
		// 정규표현식으로 처리하므로 중괄호 여는 기호 {나 대괄호 여는 기호 [를 입력하기 위해서는 앞에 \ 기호를 써서 \{, \[라고 사용해야 합니다. 닫을 때에는 알아서 처리하므로 \ 기호를 삽입할 필요는 없습니다. 
		// 예시 : 다른 뜻 틀 삽입 => \{\{다른.뜻|+}}
		// 기호 앞에 ␥ (U+2425 SYMBOL FOR DELETE FORM TWO)이 붙어있으면 메인 이름공간(0번)에서는 표시되지 않습니다.

		// 이 오브젝트 안에 '카테고리 이름' : '문자셋 이름' 형태로 작성하면 됩니다.
		charinsert: {
			'기본': '괄호: (+) [+] {+} 〔+〕 〈+〉 【+】 ' +
				'위키텍스트: {\{크기||+}} [\[+]] [\[#+]] {\{+}} <!--+--> /*+*/ [\[분류:+]] [\[분류:+|_]] [\[파일:+]] &nbsp; <del>+</del> <br/> <hr/> ---- {\{-}} {\{각주}} <ref>+</ref> <ref.name="+"_/> {\{URL|+}} __TOC__ <span.id="+"/> ' +
				'틀: {\{색||+}} {\{lang||+}} {\{llang||+}} {\{=|+}} {\{|+}} {\{PAGENAME}} {\{FULLPAGENAME}} {\{삭제|+}} {\{특정판.삭제|+}} {\{유튜브|+}} {\{퍼온문서|문서=+|판=_|일부=_}} {\{번역된.문서|en|+||}} {\{string|+}} {\{배지|+}} {\{인용문|+}}  {\{PD-author}}',
			'틀 작성': '{\{\{+}}} {\{\{+|}}} <onlyinclude>+</onlyinclude> <includeonly>+</includeonly> <noinclude>+</noinclude> {\{풀기:+}} <templatestyles.src="+/styles.css"/>  파서함수: {\{#expr:+}} {\{#if:+}} {\{#ifeq:+}} {\{#iferror:+}} {\{#ifexist:+}} {\{#switch:+}} {\{#time:+}} {\{#titlepart:+}} {\{#invoke:+|}}',
			'코드': '<div>+</div> <div.class="".style="">+</div> <span>+</span> <span.class="".style="">+</span> <code>+</code> <code><nowiki>+</nowiki></code> <pre>+</pre> <syntaxhighlight.lang="console">\n+\n</syntaxhighlight>',
			'파일 저작권': '{\{PD-self}} {\{PD-old}} {\{PD-author}} {\{CC-BY-3.0}} {\{CC-BY-SA-3.0}}',
			'기호': '~ | ¡¿†‡↔↑↓•¶#∞  〈+〉 《+》  ‘+’ “+” ‹+› «+»  ¤₳฿₵¢₡₢$₫₯€₠₣ƒ₴₭₤ℳ₥₦№₧₰£៛₨₪৳₮₩¥  ♠♣♥♦  ♭♯♮  ©®™ ◌',
			'로마자': 'A a Á á À à Â â Ä ä Ǎ ǎ Ă ă Ā ā Ã ã Å å Ą ą Æ æ Ǣ ǣ ' +
				'B b  C c Ć ć Ċ ċ Ĉ ĉ Č č Ç ç  D d Ď ď Đ đ Ḍ ḍ Ð ð  E e É é È è Ė ė Ê ê Ë ë Ě ě Ĕ ĕ Ē ē Ẽ ẽ Ę ę Ẹ ẹ Ɛ ɛ Ǝ ǝ Ə ə  F f  G g Ġ ġ Ĝ ĝ Ğ ğ Ģ ģ  H h Ĥ ĥ Ħ ħ Ḥ ḥ' +
				'I i İ ı Í í Ì ì Î î Ï ï Ǐ ǐ Ĭ ĭ Ī ī Ĩ ĩ Į į Ị ị  J j Ĵ ĵ   K k Ķ ķ  L l Ĺ ĺ Ŀ ŀ Ľ ľ Ļ ļ Ł ł Ḷ ḷ Ḹ ḹ  M m Ṃ ṃ  N n Ń ń Ň ň Ñ ñ Ņ ņ Ṇ ṇ Ŋ ŋ' +
				'O o Ó ó Ò ò Ô ô Ö ö Ǒ ǒ Ŏ ŏ Ō ō Õ õ Ǫ ǫ Ọ ọ Ő ő Ø ø Œ œ  Ɔ ɔ  P p  Q q  R r Ŕ ŕ Ř ř Ŗ ŗ Ṛ ṛ Ṝ ṝ  S s Ś ś Ŝ ŝ Š š Ş ş Ș ș Ṣ ṣ ß  T t Ť ť Ţ ţ Ț ț Ṭ ṭ Þ þ' +
				'U u Ú ú Ù ù Û û Ü ü Ǔ ǔ Ŭ ŭ Ū ū Ũ ũ Ů ů Ų ų Ụ ụ Ű ű Ǘ ǘ Ǜ ǜ Ǚ ǚ Ǖ ǖ  V v  W w Ŵ ŵ  X x  Y y Ý ý Ŷ ŷ Ÿ ÿ Ỹ ỹ Ȳ ȳ  Z z Ź ź Ż ż Ž ž  ß Ð ð Þ þ Ŋ ŋ Ə ə',
			'그리스 문자': 'ΆάΈέΉήΊίΌόΎύΏώ  ΑαΒβΓγΔδ  ΕεΖζΗηΘθ  ΙιΚκΛλΜμ  ΝνΞξΟοΠπ  ΡρΣσςΤτΥυ  ΦφΧχΨψΩω Ϝϝυ̯ι̯' +
				'ᾼᾳᾴᾺὰᾲᾶᾷἈἀᾈᾀἉἁᾉᾁἌἄᾌᾄἊἂᾊᾂἎἆᾎᾆἍἅᾍᾅἋἃᾋᾃἏἇᾏᾇ  ῈὲἘἐἙἑἜἔἚἒἝἕἛἓ  ῌῃῄῊὴῂῆῇἨἠᾘᾐἩἡᾙᾑἬἤᾜᾔἪἢᾚᾒἮἦᾞᾖἭἥᾝᾕἫἣᾛᾓἯἧᾟᾗ  ῚὶῖἸἰἹἱἼἴἺἲἾἶἽἵἻἳἿἷΪϊΐῒῗ' +
				'ῸὸὈὀὉὁὌὄὊὂὍὅὋὃ  ῤῬῥ  ῪὺῦὐὙὑὔὒὖὝὕὛὓὟὗΫϋΰῢῧ  ῼῳῴῺὼῲῶῷὨὠᾨᾠὩὡᾩᾡὬὤᾬᾤὪὢᾪᾢὮὦᾮᾦὭὥᾭᾥὫὣᾫᾣὯὧᾯᾧ ᾹᾱᾸᾰῙῑῘῐῩῡῨῠ {{lang|el|+}} {{lang|grc|+}}',
			'키릴 문자': 'АаБбВвГг  ҐґЃѓДдЂђ  ЕеЁёЄєЖж  ЗзЅѕИиІі  ЇїЙйЈјКк  ЌќЛлЉљМм  НнЊњОоПп  РрСсТтЋћ  УуЎўФфХх  ЦцЧчЏџШш  ЩщЪъЫыЬь  ЭэЮюЯя ӘәӨөҒғҖҗ' +
				'ҚқҜҝҢңҮү ҰұҲҳҸҹҺһ  ҔҕӢӣӮӯҘҙ  ҠҡҤҥҪҫӐӑ  ӒӓӔӕӖӗӰӱ  ӲӳӸӹӀ  ҞҟҦҧҨҩҬҭ  ҴҵҶҷҼҽҾҿ  ӁӂӃӄӇӈӋӌ  ӚӛӜӝӞӟӠӡ  ӤӥӦӧӪӫӴӵ  ́',
			'IPA (영어)': 'ˈ ˌ  ŋ ɡ tʃ dʒ ʃ ʒ θ ð ʔ  ɑː ɒ æ aɪ aʊ ɛ eɪ ɪ iː ɔː ɔɪ oʊ ʊ uː ʌ ɜr  ə ər ᵻ ᵿ ɒ̃ æ̃  {\{angle.bracket|+}} {\{IPA|+}} {\{IPA.링크|+}}',
			'IPA': '닿소리: ɱɳɲŋɴ : t̪ d̪ ʈɖɟɡɢʡʔ : ɸβθð  ʃʒʂʐɕʑ  çʝɣχʁ  ħʕʜʢɦɧ : ʋɹɻɥɰʍ : ʙⱱɾɽʀ  ɺ  ɫɬɮɭʎʟ : ɓɗᶑʄɠʛ  ʘǀǃǂǁ  홀소리: ɪʏɨʉɯʊ : øɘɵɤ  ə ɚ  ɛœɜɝɞʌɔ : æɶɐɑɒ  Spacing_diacritics: ˈˌːˑʼˀˤᵝᵊᶢˠʰʱʲˡⁿᵑʷᶣ˞‿˕˔  Combining_diacritics: ̚ ̪ ̺ ̻ ̼ ̬  ̊ ̥ ̞ ̝ ̘ ̙ ̽ ̟ ̠  ̈ ̤ ̹ ̜ ̍ ̩  ̆ ̯  ̃ ̰ ͡ ͜  성조:  ̋  ́  ̄  ̀  ̏  ̌  ̂ ᷄ ᷅ ᷇ ᷆ ᷈ ᷉  ˥˦˧˨˩ꜛꜜ : ↗↘‖  extIPA: ͈ ͉ ͎ ̣ ̫ ͊ ᷽ ͇ : ˭ᵻᵿ  {\{angle.bracket|+}} {\{IPA|+}} {\{IPA.링크|+}}',
			'수학·논리학': '− × ÷ ⋅ ° ∗ ∘ ± ∓ ≤ ≥ ≠ ≡ ≅ ≜ ≝ ≐ ≃ ≈ ⊕ ⊗ ⇐ ⇔ ⇒ ∞ ← ↔ → ≪ ≫ ∝ √ ∤ ≀ ◅ ▻ ⋉ ⋊ ⋈ ∴ ∵ ↦ ¬ ∧ ∨ ⊻ ∀ ∃ ∈ ∉ ∋ ⊆ ⊈ ⊊ ⊂ ⊄ ⊇ ⊉ ⊋ ⊃ ⊅ ∪ ∩ ∑ ∏ ∐ ′ ∫ ∬ ∭ ∮ ∇ ∂ ∆ ∅ ℂ ℍ ℕ ℙ ℚ ℝ ℤ ℵ ⌊ ⌋ ⌈ ⌉ ⊤ ⊥ ⊢ ⊣ ⊧ □ ∠ ⟨ ⟩ <math>+</math> {\{수학|+}} {\{수학.변수|+}} {\{분수|+|}} {\{수직분수|+|}}'
		},
		// 문자열 나누는 기호
		charinsertDivider: "\240",

		storageKey: 'edittoolscharsubset',

		createEditTools: function (placeholder) {
			var sel, id;
			var box = document.createElement('div');
			var prevSubset = 0, curSubset = 0;
			box.id = 'editpage-specialchars';
			box.className = "nopopups";
			// 문자 선택시 나타나는 제목 이름
			box.title = '편집 창에 입력할 글자 혹은 태그를 클릭하세요';

			// append user-defined sets
			if (window.charinsertCustom) {
				for (id in charinsertCustom) {
					if (!editTools.charinsert[id]) {
						editTools.charinsert[id] = '';
					}
				}
			}

			// 문자셋 드랍다운 메뉴를 만듭니다.
			sel = document.createElement('select');
			for (id in editTools.charinsert) {
				sel.options[sel.options.length] = new Option(id, id);
			}
			sel.selectedIndex = 0;
			sel.style.marginRight = '.3em';
			// 입력상자 타이틀
			sel.title = 'Choose character subset';
			sel.onchange = sel.onkeyup = selectSubset;
			box.appendChild(sel);

			// create "recall" switch
			if (window.editToolsRecall) {
				var recall = document.createElement('span');
				recall.appendChild(document.createTextNode('↕')); // ↔
				recall.onclick = function () {
					sel.selectedIndex = prevSubset;
					selectSubset();
				};
				recall.style.cssFloat = 'left';
				recall.style.marginRight = '5px';
				recall.style.cursor = 'pointer';
				box.appendChild(recall);
			}

			if (getSelectedSection()) {
				sel.selectedIndex = getSelectedSection();
			}

			placeholder.parentNode.replaceChild(box, placeholder);
			selectSubset();
			return;

			function selectSubset() {
				// remember previous (for "recall" button)
				prevSubset = curSubset;
				curSubset = sel.selectedIndex;
				//save into web storage for persistence
				saveSelectedSection(curSubset);

				//hide other subsets
				var pp = box.getElementsByTagName('p');
				for (var i = 0; i < pp.length; i++) {
					pp[i].style.display = 'none';
				}
				//show/create current subset
				var id = sel.options[curSubset].value;
				var p = document.getElementById(id);
				if (!p) {
					p = document.createElement('p');
					p.className = 'nowraplinks';
					p.id = id;
					if (id == 'Arabic' || id == 'Hebrew') {
						p.style.fontSize = '120%';
						p.dir = 'rtl';
					}
					var tokens = editTools.charinsert[id];
					if (window.charinsertCustom && charinsertCustom[id]) {
						if (tokens.length > 0) {
							tokens += ' ';
						}
						tokens += charinsertCustom[id];
					}
					editTools.createTokens(p, tokens);
					box.appendChild(p);
				}
				p.style.display = 'inline';
			}
		},

		createTokens: function (paragraph, str) {
			var tokens = str.split(' '), token, i, n;
			for (i = 0; i < tokens.length; i++) {
				token = tokens[i];
				n = token.indexOf('+');
				if (token.charAt(0) === '␥') {
					if (token.length > 1 && mw.config.get('wgNamespaceNumber') === 0) {
						continue;
					} else {
						token = token.substring(1);
					}
				}
				if (token === '' || token === '_') {
					addText(editTools.charinsertDivider + ' ');
				} else if (token === '\n') {
					paragraph.appendChild(document.createElement('br'));
				} else if (token === '___') {
					paragraph.appendChild(document.createElement('hr'));
				} else if (token.charAt(token.length - 1) === ':') { // : at the end means just text
					addBold(token);
				} else if (n === 0) { // +<tag>  ->   <tag>+</tag>
					addLink(token.substring(1), '</' + token.substring(2), token.substring(1));
				} else if (n > 0) { // <tag>+</tag>
					addLink(token.substring(0, n), token.substring(n + 1));
				} else if (token.length > 2 && token.charCodeAt(0) > 127) { // a string of insertable characters
					for (var j = 0; j < token.length; j++) {
						addLink(token.charAt(j), '');
					}
				} else {
					addLink(token, '');
				}
			}
			return;

			function addLink(tagOpen, tagClose, name) {
				var handler;
				var dle = tagOpen.indexOf('\x10');
				var a = document.createElement('a');

				if (dle > 0) {
					var path = tagOpen.substring(dle + 1).split('.');
					tagOpen = tagOpen.substring(0, dle);
					handler = window;
					for (var i = 0; i < path.length; i++) {
						handler = handler[path[i]];
					}
					$(a).on('click', handler);
				} else {
					tagOpen = tagOpen.replace(/\./g, ' ');
					tagClose = tagClose ? tagClose.replace(/_/g, ' ') : '';
					$(a).on('click', {
						tagOpen: tagOpen,
						sampleText: '',
						tagClose: tagClose
					}, insertTags);
				}

				name = name || tagOpen + tagClose;
				name = name.replace(/\\n/g, '');
				a.appendChild(document.createTextNode(name));
				a.href = '';
				paragraph.appendChild(a);
				addText(' ');
			}

			function addBold(text) {
				var b = document.createElement('b');
				b.appendChild(document.createTextNode(text.replace(/_/g, ' ')));
				paragraph.appendChild(b);
				addText(' ');
			}
			function addText(txt) {
				paragraph.appendChild(document.createTextNode(txt));
			}
			function insertTags(e) {
				e.preventDefault();
				if ($currentFocused && $currentFocused.length && !$currentFocused.prop('readonly')) {
					$currentFocused.textSelection(
						'encapsulateSelection', {
						pre: e.data.tagOpen,
						peri: e.data.sampleText,
						post: e.data.tagClose
					}
					);
				}
			}
		},

		setup: function () {
			var placeholder;
			if ($('#editpage-specialchars').length) {
				placeholder = $('#editpage-specialchars')[0];
			} else {
				placeholder = $('<div id="editpage-specialchars"> </div>').prependTo('.mw-editTools')[0];
			}
			if (!placeholder) {
				return;
			}
			if (!window.charinsertDontMove) {
				$('.editOptions').before(placeholder);
			}
			// Find the element that is focused
			$currentFocused = $('#wpTextbox1');
			// Apply to dynamically created textboxes as well as normal ones
			$(document).on('focus', 'textarea, input:text', function () {
				$currentFocused = $(this);
			});

			// Used to determine where to insert tags
			editTools.createEditTools(placeholder);
			window.updateEditTools = function () {
				editTools.createEditTools($('#editpage-specialchars')[0]);
			};
		}
	}; // end editTools

	editTools.setup();
});