업데이트
2020.07.03 - innerHTML을 사용하지 않고 댓글 내용을 업데이트합니다.
단순히 텍스트밖에 적을 수 없는 티스토리 댓글에 링크, 이미지, 비디오, 유튜브 등을 추가해 화려하게 꾸미는 스크립트입니다.
HTML 수정
<s_rp_container>
바로 아래에 있는 요소에 id가 없다면 하나 추가해주세요.
방명록에도 사용하시려면 <s_guest_container>
아래에 있는 요소에 같은 id를 추가하시면 됩니다.
[##_rp_rep_desc_##]
을 감싼 요소에 class가 없다면 하나 추가해주세요. 댓글용과 답글용 2개가 있을 겁니다. 혹 class가 있더라도 해당 치환자를 감싼 요소가 아닌 다른 곳에도 사용되었다면 별도로 하나 추가해주세요.
마찬가지로 방명록에도 사용하시려면 [##_guest_rep_desc_##]
를 검색하셔서 같은 작업을 진행하시면 됩니다.
Javascript 작업
const autoWrap = ( containerId , selector ) => {
const wrapping = async () => {
const link = /( \b (https ? | ftp | file): \/\/ [-A-Z0-9|ㄱ-ㅎ|ㅏ-ㅣ|가-힣|+&@# \/ %?=~_|!:, . ;] * [-A-Z0-9|ㄱ-ㅎ|ㅏ-ㅣ|가-힣|+&@# \/ %=~_|] )/ gi ; // 링크 찾기
const mail = /(( \S + . )@ [a-z] + . [a-z] + )/ gi ;
const imageType = / \. (?:jpe ? g(:(large | orig)) ? | gif | png(:(large | orig)) ? | svg) $ / i ; // 이미지
const TistoryImage = /(?: \? original) $ / i ; // 티스토리 ?original 이미지
const videoType = / \. (?:mp4 | webm) $ / i ; // 비디오
const audioType = / \. (?:mp3 | ogg | wav) $ / i ; // 오디오
const youtubeLink = /(?:https ? : \/\/ ) ? (?:www \. ) ? (?:youtube \. com | youtu \. be) \/ (?:watch \? v=) ? / g ; // 유튜브 비디오
const createAnchor = ( string , type = "link" ) => {
const anchor = document . createElement ( "a" );
anchor . href = type === "link" ? string : `mailto: ${ string } ` ;
type === "link" &&
(( anchor . target = "_blank" ),
anchor . setAttribute ( "rel" , "noopener, noreferrer" ));
anchor . innerText = string ;
return anchor ;
};
document . querySelectorAll ( selector ). forEach (( comment ) => {
! comment . classList . contains ( "modded" ) &&
comment . hasChildNodes &&
[ ... comment . childNodes ]. forEach (( text ) => {
if ( text . nodeType === 3 ) {
let textArray = text . textContent . split ( link );
if ( textArray . length === 1 )
textArray = text . textContent . split ( mail );
if ( textArray . length === 1 ) return ;
const fragment = document . createDocumentFragment ();
for (
let i = 0 , length = textArray . length , j = 1 ;
i < length ;
i ++
) {
if ( j % 3 !== 0 ) {
const string = textArray [ i ];
if ( j % 2 === 0 ) {
if ( string . includes ( "http:" )) {
const anchor = createAnchor ( string );
fragment . append ( anchor );
} else {
if (
imageType . test ( string ) ||
TistoryImage . test ( string )
) {
const img = document . createElement (
"img"
);
img . src = string ;
img . alt = "userContent" ;
fragment . append ( img );
} else if ( videoType . test ( string )) {
const video = document . createElement (
"video"
);
video . src = string ;
video . autoplay = 1 ;
video . muted = 1 ;
video . loop = 1 ;
video . setAttribute (
"playsinline" ,
1
);
fragment . append ( video );
} else if ( audioType . test ( string )) {
const audio = document . createElement (
"audio"
);
audio . src = string ;
audio . controls = 1 ;
fragment . append ( audio );
} else if ( youtubeLink . test ( string )) {
const wrapper = document . createElement (
"div"
);
const div = document . createElement (
"div"
);
const iframe = document . createElement (
"iframe"
);
wrapper . className =
"youtubevid-wrapper" ;
div . className = "resvid" ;
iframe . src = `https://www.youtube.com/embed/ ${ string . replace (
youtubeLink ,
""
) } ?rel=0&playsinline=1` ;
iframe . allowFullscreen = 1 ;
iframe . frameBorder = 0 ;
div . append ( iframe );
wrapper . append ( div );
fragment . append ( wrapper );
} else if ( mail . test ( string )) {
const anchor = createAnchor (
string ,
"mail"
);
fragment . append ( anchor );
} else {
const anchor = createAnchor ( string );
fragment . append ( anchor );
}
}
} else {
const textNode = document . createTextNode (
string
);
fragment . append ( textNode );
}
j += 1 ;
} else {
j = 1 ;
}
}
text . parentNode . insertBefore ( fragment , text );
text . remove ();
}
comment . classList . add ( "modded" );
});
});
};
document . addEventListener (
"DOMContentLoaded" ,
wrapping (). then (() => {
// 수정, 삭제, 이전 댓글 불러오기 등 변화 감지
const container = document . getElementById ( containerId );
const observer = new MutationObserver ( wrapping );
container &&
observer . observe ( container , {
attributes : true ,
childList : true ,
subtree : true ,
});
})
);
};
예전 스크립트는 0.5초마다 한 번씩 함수를 실행하게 해뒀는데, 이젠 MutationObserver를 이용해 변화를 감지하게 해뒀습니다.
위 스크립트를 별도로 js 파일로 작성해 스킨 편집에서 업로드하셔서 사용하시거나, 아래 주소를 사용하시면 업로드 필요 없이 압축된 js 파일을 사용하실 수 있습니다.
jsdelivr : https://cdn.jsdelivr.net/gh/marshall-ku/update-tistory-comments@latest/dist/autoWrap.js
github : https://marshall-ku.github.io/update-tistory-comments/dist/autoWrap.js
autoWrap ( "comment-list" , ".comment-text" );
스크립트 추가를 완료하셨다면, 위 코드처럼 호출해주세요.
첫 번째 인자론 <s_rp_container>
바로 아래에 있는 요소에 추가한 id를, 두 번째 인자론 [##_rp_rep_desc_##]
를 감싼 요소에 추가한 class를 .과 함께 입력해주세요.
CSS 작업 (선택)
/* 이미지 비디오 최대 너비 설정 */
img ,
video {
max-width : 100 % ;
}
/* 유튜브 비디오 반응형으로 수정 */
.youtubevid-wrapper {
width : 400 px ;
max-width : 100 % ;
}
.resvid {
position : relative ;
width : 100 % ;
padding-bottom : 56.25 % ;
}
.resvid iframe {
position : absolute ;
top : 0 ;
left : 0 ;
width : 100 % ;
height : 100 % ;
}
이미지나 비디오가 댓글 창을 벗어나는 걸 방지하기 위해 최대 너비를 설정해주는 스타일과, 추가된 유튜브 비디오를 반응형으로 수정하는 스타일입니다. 필요하시면 추가해주세요.
확인
작업이 완료됐으면 댓글에 웹사이트의 주소, 혹은 이미지 / 비디오 등의 주소를 추가해보세요.
주소가 성공적으로 텍스트에서 링크 혹은 이미지 등으로 변경됐다면 댓글을 수정해보세요.
수정 후에도 해당 주소가 변경되면 끝입니다!
ⓒ 2020. Marshall K All rights reserved