티스토리 치환자 주의사항

티스토리에는 많은 치환자가 사용된다. 각 치환자의 특징과 주의할 점을 정리해보려고 한다.

s_t3

s_t3은 티스토리 가이드에 다음과 같이 정의되어 있다.

자바스크립트를 지정해줄 영역을 선언하기 위해서 <body>안에 <s_t3></s_t3>를 넣어줘야 합니다.

여기서 말하는 자바스크립트는 티스토리 기능이 동작하도록 하는 스크립트이다. 실제로 s_t3을 넣은 영역 제일 상위에 다음의 스크립트가 추가된다. 티스토리 주인이냐 아니냐에 따라 조금 다른데 주인일 경우 스크립트가 더 길다. 아래는 손님에게 추가되는 내용이다. 이 스크립트가 없을경우 댓글 작성이나 단축키 등이 동작하지 않는다. 그 기능을 사용하지 않을 것이라면 없애도 된다.

<script type="text/javascript">
	function secondaryDomainLogin(authData) {
		if (!authData) {
			return;
		}

		var request = new HTTPRequest("POST", '/api/secondaryDomain/');
		request.async = false;
		request.onSuccess = function() {
			window.location.reload();
		};
		request.onVerify = function() {
			try {
				var result = eval("(" + this.getText() + ")");
				return (result.error == false)
			}
			catch (e) {
				return false;
			}
		};
		request.send('authData=' + encodeURIComponent(authData));
	}
</script>
<script type="text/javascript" src="http://www.tistory.com/api/secondaryDomain/?callback=secondaryDomainLogin&amp;dummy=1727273845"></script>

<script type="text/javascript">
//<![CDATA[
	var TOP_SSL_URL = 'https://www.tistory.com';

	function processShortcut(event) {
			if (isIE)
		{
			event = window.event;
			event.target = event.srcElement;
		}

		if (event.altKey || event.ctrlKey || event.metaKey)
			return;
		switch (event.target.nodeName) {
			case "INPUT":
			case "SELECT":
			case "TEXTAREA":
				return;
		}
		switch (event.keyCode) {
			case 81: //Q

				window.location = "/admin";
				break;
			case 83: //S
				window.location = "/378";
				break;
			case 90: //Z
				window.location = "#recentEntries";
				break;
			case 88: //X
				window.location = "#recentComments";
				break;
			case 67: //C
				window.location = "#recentTrackback";
				break;
		}
	}
	document.onkeydown = processShortcut;

	function addComment(caller, entryId) {
		var oForm = findFormObject(caller);
		if (!oForm)
			return false;
		var request = new HTTPRequest("POST", oForm.action);
		request.onSuccess = function () {
			if(entryId == 0)
				window.location = blogURL + "/guestbook";
			else {
				document.getElementById("entry" + entryId + "Comment").innerHTML = this.getText("/response/commentBlock");
				if(document.getElementById("recentComments"))
					document.getElementById("recentComments").innerHTML = this.getText("/response/recentCommentBlock");
				if(document.getElementById("commentCount" + entryId))
					document.getElementById("commentCount" + entryId).innerHTML = this.getText("/response/commentView");
				if(document.getElementById("commentCountOnRecentEntries" + entryId))
					document.getElementById("commentCountOnRecentEntries" + entryId).innerHTML = "(" + this.getText("/response/commentCount") + ")";
			}
			if(typeof window.needCommentCaptcha !== "undefined"){
				captchaPlugin.init('complete');
			}
		}
		request.onError = function() {
			var description = this.getText("/response/description");
			if (description) { alert(description); }
		}
		var queryString = "key=tistory";
		var captchaInput = document.getElementById('inputCaptcha');
		if (oForm["name"])
			queryString += "&name=" + encodeURIComponent(oForm["name"].value);
		if (oForm["password"])
			queryString += "&password=" + encodeURIComponent(oForm["password"].value);
		if (oForm["homepage"])
			queryString += "&homepage=" + encodeURIComponent(oForm["homepage"].value);
		if (oForm["secret"] && oForm["secret"].checked)
			queryString += "&secret=1";
		if (oForm["comment"])
			queryString += "&comment=" + encodeURIComponent(oForm["comment"].value);
		if (captchaInput) {
			if (!captchaInput.value) {
				alert('그림문자가 입력되지 않았습니다.');
				return false;
			}
			queryString += "&captcha=" + encodeURIComponent(captchaInput.value);
		}
		request.send(queryString);
	}
	function commentRequireLogin() {
		if(confirm("'JooStory Blog' 블로그에 댓글을 남기시려면 티스토리에 로그인하셔야 합니다. \n 지금 로그인하시겠습니까?")) {
			window.location = "https://www.tistory.com/login/?requestURI=http%3A%2F%2Fblog.joostory.net%2F379";
		} else {
			window.focus();
		}
	}
	function commentObserverForAuth(evetObj) {
		var reex = /name|password|homepage|secret|comment/;
		if (isIE)
			var	name = evetObj.srcElement.name
		else
			var	name = evetObj.target.name
		if(reex.test(name) && !(new RegExp("^entry\\d+password$").test(name))) {
			commentRequireLogin();
		}
	}

	STD.addEventListener(document);
	document.addEventListener("click", commentObserverForAuth, false);
	var openWindow='';
	function alignCenter(win,width,height) {
		if(navigator.userAgent.indexOf("Chrome") == -1)
			win.moveTo(screen.width/2-width/2,screen.height/2-height/2);
	}

	function deleteComment(id) {
		var width = 450;
		var height = 360;
				try { openWindow.close(); } catch(e) { }
				openWindow = window.open("/comment/delete/" + id, "tatter", "width="+width+",height="+height+",location=0,menubar=0,resizable=0,scrollbars=0,status=0,toolbar=0");
		openWindow.focus();
		alignCenter(openWindow,width,height);
	}

	function commentComment(parent, guestbookPage) {
		var width = 450;
		var height = 360;
				try { openWindow.close(); } catch(e) { }
				openWindow = window.open("/comment/comment/" + parent + (guestbookPage ? "?guestbookPage=" + guestbookPage: ""), "tatter", "width="+width+",height="+height+",location=0,menubar=0,resizable=0,scrollbars=0,status=0,toolbar=0");
		openWindow.focus();
		alignCenter(openWindow,width,height);
	}

	function editEntry(parent,child) {
		var width =  1169;
		var height = 600;
		if(openWindow != '') openWindow.close();
		openWindow = window.open("/admin/entry/edit/" + parent + "?popupEditor&returnURL=CLOSEME","tatter", "width="+1169+",height="+600+",location=0,menubar=0,resizable=1,scrollbars=1,status=0,toolbar=0");
		openWindow.focus();
		alignCenter(openWindow,width,height);
	}

	function guestbookComment(parent) {
		var width = 450;
		var height = 360;
				try { openWindow.close(); } catch(e) { }
				openWindow = window.open("/comment/comment/" + parent, "tatter", "width="+width+",height="+height+",location=0,menubar=0,resizable=0,scrollbars=0,status=0,toolbar=0");
		openWindow.focus();
		alignCenter(openWindow,width,height);
	}

	function sendTrackback(id) {
		var width = 700;
		var height = 500;
				try { openWindow.close(); } catch(e) { }
				openWindow = window.open("/trackback/send/" + id, "tatter", "width=580,height=400,location=0,menubar=0,resizable=1,scrollbars=1,status=0,toolbar=0");
				openWindow.focus();
		alignCenter(openWindow,width,height);
	}

	function deleteTrackback(id,entryId) {
		if (confirm("트랙백을 삭제하기 위해서는 로그인이 필요합니다.\n로그인 하시겠습니까?\t")) {
			window.location = "https://www.tistory.com/login/";
			return false;
		} else {
			return false;
		}
	}

	function reloadEntry(id) {
		var password = document.getElementById("entry" + id + "password");
		if (!password)
			return;
		document.cookie = "GUEST_PASSWORD=" + encodeURIComponent(password.value) + ";path=";

		window.location.href = window.location.href;
	}
	loadedComments = new Array();
	loadedTrackbacks = new Array();
	function viewTrigger(id, category, categoryId) {
		var request = new HTTPRequest("GET", "/"+category+"/view/" + id);
		var target = document.getElementById('entry'+id+(category == 'comment' ? 'Comment' : 'Trackback'));
		if(target == null)
			return false;
		request.onSuccess = function() {
			target.innerHTML = this.getText("/response/result");
			target.style.display = 'block';
			highlight();
			category == 'comment' ? loadedComments[id] = true : loadedTrackbacks[id] = true;
			if(categoryId > -1)
				location = location.toString();
			if(category == 'trackback') {
				var holder = document.getElementById('TrackbackCopyHolder' + id);
				if(holder) {
					holder.innerHTML = AC_FL_RunContentNotWriteGetString(
						'src','http://s1.daumcdn.net/cfs.tistory/resource/620/blog/script/copyTrackback',
						'Flashvars','url=http://blog.joostory.net/trackback/' + id + '&mode=whiteButton',
						'width','29',
						'height','18',
						'id', 'TrackbackCopyButton' + id,
						'wmode','transparent',
						'allowScriptAccess','always',
						'type','application/x-shockwave-flash',
						'pluginspage','http://www.macromedia.com/go/getflashplayer'
					);
				}
			}
			if(typeof window.needCommentCaptcha !== "undefined"){
				captchaPlugin.init();
			}
		}
		request.onError = function() {
			alert('실패 했습니다');
		}
		request.send();
	}
	function highlight() {
		var hash = new RegExp("^#(comment\\d+)").exec(window.location.hash);
		if(hash && (el = document.getElementById(hash[1])))
			highlightElement(hash[1], 0, el.style.backgroundColor);
	}
	function highlightElement(id, amount, origColor) {
		var el = document.getElementById(id);
		if (!el) {
			return;
		}
		el.style.backgroundColor = amount % 2 ? "#FFFF44" : origColor;
		if (++amount < 7) {
			setTimeout("highlightElement('" + id + "', " + amount + ", '" + origColor + "')", 200);
		}
	}
	function toggleLayerForEntry(id, category, categoryId, mode) {
		if((category == 'comment' ? loadedComments[id] : loadedTrackbacks[id])) {
			try {
				var obj = document.getElementById('entry'+id+(category == 'comment' ? 'Comment' : 'Trackback'));
				if(mode == undefined)
					obj.style.display = (obj.style.display == "none") ? "block" : "none";
				else
					obj.style.display = (mode == 'show') ? "block" : "none";
			} catch (e) {

			}
			return true;
		} else {
			if(categoryId) {
				viewTrigger(id,category, categoryId);
			} else {
				viewTrigger(id,category, -1);
			}
		}
	}
	function ObserverForAnchor(evetObj) {
		var lo = location.toString();
		var queryString = lo.substr(lo.lastIndexOf('/')+1);
		if(queryString.indexOf('#')>-1) {
			var qsElements = queryString.split('#');
			if(qsElements[1].indexOf('comment')>-1) {
				var category = 'comment';
			} else if(qsElements[1].indexOf('trackback')>-1) {
				var category = 'trackback';
			}
			if(category) {
				entryid = qsElements[0];
				categoryId = qsElements[1].substr(category.length);
				toggleLayerForEntry(entryid,category,categoryId, 'show');
			}
		}
	}

	STD.addEventListener(window);
	window.addEventListener("load", ObserverForAnchor, false);
//]]>
</script>
<div style="margin:0px; padding:0px; border:none; background:none; float:none; clear:none; z-index:0"></div>

header

blogmenu_

[#_blog_menu_#]는 다음으로 치환된다.

<ul>	<li class="t_menu_home first">
		<a href="/">홈</a>
	</li>
	<li class="t_menu_tag">
		<a href="/tag">태그</a>
	</li>
	<li class="t_menu_medialog">
		<a href="/media">미디어로그</a>
	</li>
	<li class="t_menu_location">
		<a href="/location">위치로그</a>
	</li>
	<li class="t_menu_guestbook last">
		<a href="/guestbook">방명록</a>
	</li>
</ul>

content

검색

티스토리의 검색은 parameter가 아닌 /search/[text] 같은 url로 하기 때문에 일반적인 폼으로는 검색을 구현할 수 없다. 따라서 반드시 가이드에 나온 치환자를 사용해야 한다. 가이드에는 onclick에 넣으라고 했지만 false를 return하기때문에 submit 이벤트에 넣어줘도 잘 동작한다.

태그

[#_tag_label_rep_#]는 다음과 같이 치환된다. 콤마까지 넣어준다. 따라서 다양한 스타일링을 하기에는 무리가 있다.

<a href="/tag/angularJs"  rel="tag">angularJs</a>,<a href="/tag/handlebars"  rel="tag">handlebars</a>

댓글

[#_rp_rep_id_#] 는 댓글의 고유id인데 hash로 접근하기 위해서 사용한다. 따라서 댓글에 직접 접근을 할 수 있도록 하려면 넣어줘야한다.

[#_rp_rep_class_#] 는 글의 성격에 따라 관리자의 댓글은 rpadmin, 일반 사용자가 작성한 글은 rpgeneral, 비밀글은 rp_secret 으로 치환된다.

댓글쓰기

<s_rp_input_form> 는 form 태그를 만든다. class를 따로 지정할 수는 없다.

댓글이 없는 경우 [#_article_rep_rp_link_#]는 댓글을 작성할 수 없다는 메시지를 출력하는 alert으로 치환된다.

<s_rp_count> 는 댓글이 2개 이상일 경우에만 원하는 내용을 넣을 수 있다. 2개 미만(0개, 1개)인 경우 "Comment 0" 과 같은 형태로 치환된다.

paging

_prev_page_, _next_page_

<s_paging></s_paging> 내부에 <s_paging_rep></s_paging_rep>로 페이지 리스트를 뿌릴 수 있다. 이전 페이지, 다음 페이지로의 이동은 [#_prev_page_#] 등으로 따로 명시해주면 되는데 통째로 href="[prevPageUrl]" 로 변환되니 href="[#_prev_page_#]" 처럼 사용하면 안된다.

s_paging_rep

<s_paging_rep></s_paging_rep> 는 루프를 돌면서 [#_paging_rep_link_#][#_paging_rep_link_num_#]를 사용할 수 있도록 해주는데 1~ 100까지의 숫자가 있다고 한다면 "1, 2, 3, 4, ..., 100" 로 출력한다. 근데 문제는 "..." 에 있다. 무조건 <span class="interword">...</span> 가 중간에 추가되며 이를 컨트롤 할 수가 없다. li 로 페이징을 구성했다면 다음과 같은 결과를 얻게 된다.

<li><a class="num"><span class="selected">1</span></a></li>
<li><a href="/378" class="num"><span>2</span></a></li>
<li><a href="/377" class="num"><span>3</span></a></li>
<li><a href="/376" class="num"><span>4</span></a></li>
<li><a href="/375" class="num"><span>5</span></a></li>
<span class="interword">...</span>
<li><a href="/1" class="num"><span>378</span></a></li>

paging에 li를 사용해선 안된다. 이전/다음만 사용하려면 li를 사용해도 된다.

_no_more_prev_, _no_more_next_

이전 글이 없을때 [#_no_more_prev_#]no-more-prev[#_no_more_next_#]no-more-prev로 변환된다. 이 class에 대한 css를 지정해두어야 한다.

반응형