미디어위키:Gadget-PluginX.js: 두 판 사이의 차이
둘러보기로 이동
검색으로 이동
imported>Senouis (pluginX가 사이트 로딩 성능을 저하하는 구조라 api.getDocument를 비동기 통신 기반 함수로 대체할 때까지 임시로 조치) |
>BANIP (PluginX 버전업) |
||
3번째 줄: | 3번째 줄: | ||
* pluginX 시스템이 제대로 돌아가게 해 줍니다. | * pluginX 시스템이 제대로 돌아가게 해 줍니다. | ||
* 작성자: [[사용자:Bd3076|Bd3076]] | * 작성자: [[사용자:Bd3076|Bd3076]] | ||
* v2.0.0 전체수정 --[[사용자:BANIP|BANIP]] ([[사용자토론:BANIP|토론]]) 2023년 7월 9일 (일) 23:20 (KST) | |||
*/ | */ | ||
function pluginXCore() { | function pluginXCore() { | ||
// pluginX를 | //pluginX를 문서에서 사용하지 않으면 종료 | ||
if ( | if ($("#bodyContent .pluginx-script-wrapper").length == 0) return; | ||
var | // 플러그인 목록 반환 | ||
var getPluginList = function() { | |||
var pluginItems = []; | |||
/// 현재 문서 페이지에서 필요한 플러그인 수집 | |||
$("#bodyContent .pluginx-script-wrapper").each(function() { | |||
var $this = $(this); | |||
var url = $this.data('url'); | |||
// 이미 추가된 플러그인이면 추가하지 않음 | |||
if (pluginItems.find(function(item) { return item.url == url; })) return; | |||
// 플러그인 목록에 추가 | |||
pluginItems.push({ | |||
url: url, | |||
name: $this.data('name'), | |||
creator: $this.data('creator'), | |||
doc: $this.data('doc'), | |||
revid: $this.data('rev-id'), | |||
script: $this.text(), | |||
revTimestamp: $this.data('rev-timestamp'), | |||
revUser: $this.data('rev-user'), | |||
}); | |||
}); | |||
return pluginItems; | |||
} | |||
var setting = { | |||
storageKey: "gadget-pluginx", | |||
get: function(){ | |||
// trusted: {doc:string, revid, revUser:string, revTimestamp:string, }[] | |||
return JSON.parse(localStorage.getItem(setting.storageKey) || '{"trusted": []}'); | |||
}, | |||
getTrustedItems: function(){ | |||
return setting.get().trusted; | |||
}, | |||
getTrustedItemByDoc: function(doc){ | |||
return setting.getTrustedItems().find(function(item){ return item.doc == doc; }); | |||
}, | |||
set: function(data){ | |||
localStorage.setItem(setting.storageKey, JSON.stringify(data)); | |||
}, | |||
setTrustedItems: function(items){ | |||
var data = setting.get(); | |||
items.forEach(function(item){ | |||
var itemForPush = { | |||
revid : item.revid, | |||
revTimestamp : item.revTimestamp, | |||
revUser : item.revUser, | |||
doc : item.doc, | |||
}; | |||
var index = data.trusted.findIndex(function(trustedItem){ return trustedItem.doc == item.doc; }); | |||
if(index == -1){ | |||
data.trusted.push(itemForPush); | |||
}else{ | |||
data.trusted[index] = itemForPush; | |||
} | |||
}); | |||
setting.set(data); | |||
} | |||
}; | |||
var installPopup = { | |||
// 플러그인 인스톨 페이지 가져오기 | |||
_getPopupElement:function(option){ | |||
option = option || {}; | |||
resolveCallback = option.resolveCallback || function(){}; | |||
rejectCallback = option.rejectCallback || function(){}; | |||
if(installPopup._$popupWrapper === undefined){ | |||
// 설치 팝업 생성 | |||
var $popupWrapperOrigin = $('' | |||
+ '<div class="pluginx-popup-wrapper">' | |||
+ '<div class="pluginx-popup">' | |||
+ '<div class="pluginx-popup-header">' | |||
+ '<div class="pluginx-popup-title">플러그인 설치가 필요합니다.</div>' | |||
+ '</div>' | |||
+ '<div class="pluginx-popup-content-wrapper">' | |||
+ '<div class="pluginx-popup-content">' | |||
+ '<div class="pluginx-popup-code"></div>' | |||
+ '<div class="pluginx-popup-summary"></div>' | |||
+ '</div>' | |||
+ '</div>' | |||
+ '<div class="pluginx-popup-footer">' | |||
+ '<div class="pluginx-trust-check-wrapper">' | |||
+ '<input type="checkbox" id="pluginx-trust-check" />' | |||
+ '<label for="pluginx-trust-check">이 플러그인들을 신뢰</label>' | |||
+ '</div>' | |||
+ '<div class="pluginx-btn-accept pluginx-close pluginx-btn">사용</div>' | |||
+ '<div class="pluginx-btn-deny pluginx-close pluginx-btn">거부</div>' | |||
+ '</div>' | |||
+ '</div>' | |||
+ '</div>') | |||
// 만든팝업 캐싱 | |||
installPopup._$popupWrapper = $popupWrapperOrigin; | |||
} | |||
var $popupWrapper = installPopup._$popupWrapper.clone(); | |||
var closePopup = function(callback){ | |||
$popupWrapper.closest(".pluginx-popup-wrapper").fadeOut(0.3, function(){ | |||
$popupWrapper.remove(); | |||
callback($popupWrapper); | |||
}); | |||
}; | |||
// 팝업 외부 클릭시 팝업 종료 | |||
$popupWrapper.click(function(e){ | |||
if(e.target == $popupWrapper[0]){ | |||
closePopup(rejectCallback); | |||
} | |||
}) | |||
// 팝업 종료 이벤트 | |||
$popupWrapper.find(".pluginx-btn-accept").click(function(){ | |||
closePopup(resolveCallback); | |||
}); | |||
$popupWrapper.find(".pluginx-btn-deny").click(function(){ | |||
closePopup(rejectCallback); | |||
}) | |||
return $popupWrapper | |||
}, | |||
// 플러그인 인스톨 페이지에 설정값 바인딩 후 표시 | |||
show:function(pluginItems){ return new Promise(function(resolve, reject){ | |||
var $popupWrapper = installPopup._getPopupElement({ | |||
resolveCallback: function($popupWrapper){ resolve({ | |||
trust: $popupWrapper.find("#pluginx-trust-check").is(":checked"), | |||
}); }, | |||
rejectCallback: function(){ reject(); }, | |||
}); | |||
var formatTimestamp = function(timestamp){ | |||
timestamp = timestamp.toString(); | |||
return timestamp.substring(0,4) + "-" + timestamp.substring(4,6) + "-" + timestamp.substring(6,8) + " " + timestamp.substring(8,10) + ":" + timestamp.substring(10,12) + ":" + timestamp.substring(12,14); | |||
}; | |||
pluginItems.forEach(function(pluginItem){ | |||
var $plugin = $popupWrapper.find(".pluginx-popup-content").eq(0).clone().css({display: "block"}); | |||
$plugin.find(".pluginx-popup-code").text(pluginItem.script); // 자동 이스케이프 | |||
$plugin.find(".pluginx-popup-summary").append("<li> 원본문서 : " + pluginItem.doc + "</li>"); | |||
$plugin.find(".pluginx-popup-summary").append("<li> 최초작성자 : " + pluginItem.creator + "</li>"); | |||
$plugin.find(".pluginx-popup-summary").append("<li> 수정자 : " + pluginItem.revUser + "</li>"); | |||
$plugin.find(".pluginx-popup-summary").append("<li> 수정일 : " + formatTimestamp(pluginItem.revTimestamp) + "</li>"); | |||
var patternList = [ | |||
{ // 이전 신뢰된 편집자와 현재 편집자가 다른 경우 | |||
ciritica: function(pluginItem){ return pluginItem.prevTrusted.revid && pluginItem.prevTrusted.revUser !== pluginItem.revUser; }, | |||
severity: "danger", | |||
message: "이전 신뢰된 편집자와 현재 편집자가 다릅니다. 사용자를 확인해주세요.", | |||
}, | |||
{ // 신뢰된 버전과 현재 버전의 리비전이 동일한 경우 | |||
ciritica: function(pluginItem){ return pluginItem.prevTrusted.revid === pluginItem.revid; }, | |||
severity: "safe", | |||
message: "이전에 신뢰된 플러그인입니다.", | |||
}, | |||
{// 이전에 신뢰되었지만 현재 버전이 다른 경우 | |||
ciritica: function(pluginItem){ | |||
return pluginItem.prevTrusted.revid | |||
&& pluginItem.prevTrusted.revid !== pluginItem.revid | |||
&& pluginItem.prevTrusted.revUser === pluginItem.revUser; | |||
}, | |||
severity: "safe", | |||
message: "이전에 신뢰되었지만 버전업으로 재확인이 필요합니다.", | |||
}, | |||
]; | |||
for(var patternKey in patternList){ | |||
var pattern = patternList[patternKey]; | |||
if(pattern.ciritica(pluginItem)){ | |||
$plugin.find(".pluginx-popup-summary").append("<li class='severity " + pattern.severity + "'>" + pattern.message + "</li>"); | |||
} | |||
} | |||
$popupWrapper.find(".pluginx-popup-content-wrapper").append($plugin); | |||
}); | |||
$popupWrapper.appendTo("body").fadeIn(0.2); | |||
})}, | |||
}; | |||
// 문서에서 사용중인 플러그인 확인 | |||
var pluginItems = getPluginList(); | |||
// 모든 플러그인의 신뢰여부 체크 | |||
pluginItems = pluginItems.map(function(pluginItem){ | |||
return Object.assign(pluginItem, {prevTrusted: setting.getTrustedItemByDoc(pluginItem.doc) || {}}); | |||
}); | |||
// 플러그인의 신뢰여부 확인 | |||
var isPluginTrusted = pluginItems.every(function(pluginItem){ | |||
return pluginItem.prevTrusted.revTimestamp == pluginItem.revTimestamp; | |||
}); | |||
// 플러그인의 신뢰여부 확인, 미신뢰시 팝업 표시 | |||
var pluginTrustRequestPromise = isPluginTrusted ? Promise.resolve() : installPopup.show(pluginItems); //isPluginTrusted | |||
// todo localstoarge에서 대조 후 리비전이 다를때만 사용자 확인 필요 | |||
pluginTrustRequestPromise.then(function(result){ | |||
result = result || {}; | |||
// 사용자가 플러그인을 신뢰할 경우 localStoarge에 저장 | |||
if(result.trust){ | |||
setting.setTrustedItems(pluginItems); | |||
} | |||
// 스크립트 실행 | |||
pluginItems.forEach(function(pluginItem){ | |||
eval(pluginItem.script); | |||
}); | |||
}); | |||
} | } | ||
$(pluginXCore); | $(pluginXCore); | ||
2023년 7월 9일 (일) 23:20 판
/**
* pluginX Core
* pluginX 시스템이 제대로 돌아가게 해 줍니다.
* 작성자: [[사용자:Bd3076|Bd3076]]
* v2.0.0 전체수정 --[[사용자:BANIP|BANIP]] ([[사용자토론:BANIP|토론]]) 2023년 7월 9일 (일) 23:20 (KST)
*/
function pluginXCore() {
//pluginX를 문서에서 사용하지 않으면 종료
if ($("#bodyContent .pluginx-script-wrapper").length == 0) return;
// 플러그인 목록 반환
var getPluginList = function() {
var pluginItems = [];
/// 현재 문서 페이지에서 필요한 플러그인 수집
$("#bodyContent .pluginx-script-wrapper").each(function() {
var $this = $(this);
var url = $this.data('url');
// 이미 추가된 플러그인이면 추가하지 않음
if (pluginItems.find(function(item) { return item.url == url; })) return;
// 플러그인 목록에 추가
pluginItems.push({
url: url,
name: $this.data('name'),
creator: $this.data('creator'),
doc: $this.data('doc'),
revid: $this.data('rev-id'),
script: $this.text(),
revTimestamp: $this.data('rev-timestamp'),
revUser: $this.data('rev-user'),
});
});
return pluginItems;
}
var setting = {
storageKey: "gadget-pluginx",
get: function(){
// trusted: {doc:string, revid, revUser:string, revTimestamp:string, }[]
return JSON.parse(localStorage.getItem(setting.storageKey) || '{"trusted": []}');
},
getTrustedItems: function(){
return setting.get().trusted;
},
getTrustedItemByDoc: function(doc){
return setting.getTrustedItems().find(function(item){ return item.doc == doc; });
},
set: function(data){
localStorage.setItem(setting.storageKey, JSON.stringify(data));
},
setTrustedItems: function(items){
var data = setting.get();
items.forEach(function(item){
var itemForPush = {
revid : item.revid,
revTimestamp : item.revTimestamp,
revUser : item.revUser,
doc : item.doc,
};
var index = data.trusted.findIndex(function(trustedItem){ return trustedItem.doc == item.doc; });
if(index == -1){
data.trusted.push(itemForPush);
}else{
data.trusted[index] = itemForPush;
}
});
setting.set(data);
}
};
var installPopup = {
// 플러그인 인스톨 페이지 가져오기
_getPopupElement:function(option){
option = option || {};
resolveCallback = option.resolveCallback || function(){};
rejectCallback = option.rejectCallback || function(){};
if(installPopup._$popupWrapper === undefined){
// 설치 팝업 생성
var $popupWrapperOrigin = $(''
+ '<div class="pluginx-popup-wrapper">'
+ '<div class="pluginx-popup">'
+ '<div class="pluginx-popup-header">'
+ '<div class="pluginx-popup-title">플러그인 설치가 필요합니다.</div>'
+ '</div>'
+ '<div class="pluginx-popup-content-wrapper">'
+ '<div class="pluginx-popup-content">'
+ '<div class="pluginx-popup-code"></div>'
+ '<div class="pluginx-popup-summary"></div>'
+ '</div>'
+ '</div>'
+ '<div class="pluginx-popup-footer">'
+ '<div class="pluginx-trust-check-wrapper">'
+ '<input type="checkbox" id="pluginx-trust-check" />'
+ '<label for="pluginx-trust-check">이 플러그인들을 신뢰</label>'
+ '</div>'
+ '<div class="pluginx-btn-accept pluginx-close pluginx-btn">사용</div>'
+ '<div class="pluginx-btn-deny pluginx-close pluginx-btn">거부</div>'
+ '</div>'
+ '</div>'
+ '</div>')
// 만든팝업 캐싱
installPopup._$popupWrapper = $popupWrapperOrigin;
}
var $popupWrapper = installPopup._$popupWrapper.clone();
var closePopup = function(callback){
$popupWrapper.closest(".pluginx-popup-wrapper").fadeOut(0.3, function(){
$popupWrapper.remove();
callback($popupWrapper);
});
};
// 팝업 외부 클릭시 팝업 종료
$popupWrapper.click(function(e){
if(e.target == $popupWrapper[0]){
closePopup(rejectCallback);
}
})
// 팝업 종료 이벤트
$popupWrapper.find(".pluginx-btn-accept").click(function(){
closePopup(resolveCallback);
});
$popupWrapper.find(".pluginx-btn-deny").click(function(){
closePopup(rejectCallback);
})
return $popupWrapper
},
// 플러그인 인스톨 페이지에 설정값 바인딩 후 표시
show:function(pluginItems){ return new Promise(function(resolve, reject){
var $popupWrapper = installPopup._getPopupElement({
resolveCallback: function($popupWrapper){ resolve({
trust: $popupWrapper.find("#pluginx-trust-check").is(":checked"),
}); },
rejectCallback: function(){ reject(); },
});
var formatTimestamp = function(timestamp){
timestamp = timestamp.toString();
return timestamp.substring(0,4) + "-" + timestamp.substring(4,6) + "-" + timestamp.substring(6,8) + " " + timestamp.substring(8,10) + ":" + timestamp.substring(10,12) + ":" + timestamp.substring(12,14);
};
pluginItems.forEach(function(pluginItem){
var $plugin = $popupWrapper.find(".pluginx-popup-content").eq(0).clone().css({display: "block"});
$plugin.find(".pluginx-popup-code").text(pluginItem.script); // 자동 이스케이프
$plugin.find(".pluginx-popup-summary").append("<li> 원본문서 : " + pluginItem.doc + "</li>");
$plugin.find(".pluginx-popup-summary").append("<li> 최초작성자 : " + pluginItem.creator + "</li>");
$plugin.find(".pluginx-popup-summary").append("<li> 수정자 : " + pluginItem.revUser + "</li>");
$plugin.find(".pluginx-popup-summary").append("<li> 수정일 : " + formatTimestamp(pluginItem.revTimestamp) + "</li>");
var patternList = [
{ // 이전 신뢰된 편집자와 현재 편집자가 다른 경우
ciritica: function(pluginItem){ return pluginItem.prevTrusted.revid && pluginItem.prevTrusted.revUser !== pluginItem.revUser; },
severity: "danger",
message: "이전 신뢰된 편집자와 현재 편집자가 다릅니다. 사용자를 확인해주세요.",
},
{ // 신뢰된 버전과 현재 버전의 리비전이 동일한 경우
ciritica: function(pluginItem){ return pluginItem.prevTrusted.revid === pluginItem.revid; },
severity: "safe",
message: "이전에 신뢰된 플러그인입니다.",
},
{// 이전에 신뢰되었지만 현재 버전이 다른 경우
ciritica: function(pluginItem){
return pluginItem.prevTrusted.revid
&& pluginItem.prevTrusted.revid !== pluginItem.revid
&& pluginItem.prevTrusted.revUser === pluginItem.revUser;
},
severity: "safe",
message: "이전에 신뢰되었지만 버전업으로 재확인이 필요합니다.",
},
];
for(var patternKey in patternList){
var pattern = patternList[patternKey];
if(pattern.ciritica(pluginItem)){
$plugin.find(".pluginx-popup-summary").append("<li class='severity " + pattern.severity + "'>" + pattern.message + "</li>");
}
}
$popupWrapper.find(".pluginx-popup-content-wrapper").append($plugin);
});
$popupWrapper.appendTo("body").fadeIn(0.2);
})},
};
// 문서에서 사용중인 플러그인 확인
var pluginItems = getPluginList();
// 모든 플러그인의 신뢰여부 체크
pluginItems = pluginItems.map(function(pluginItem){
return Object.assign(pluginItem, {prevTrusted: setting.getTrustedItemByDoc(pluginItem.doc) || {}});
});
// 플러그인의 신뢰여부 확인
var isPluginTrusted = pluginItems.every(function(pluginItem){
return pluginItem.prevTrusted.revTimestamp == pluginItem.revTimestamp;
});
// 플러그인의 신뢰여부 확인, 미신뢰시 팝업 표시
var pluginTrustRequestPromise = isPluginTrusted ? Promise.resolve() : installPopup.show(pluginItems); //isPluginTrusted
// todo localstoarge에서 대조 후 리비전이 다를때만 사용자 확인 필요
pluginTrustRequestPromise.then(function(result){
result = result || {};
// 사용자가 플러그인을 신뢰할 경우 localStoarge에 저장
if(result.trust){
setting.setTrustedItems(pluginItems);
}
// 스크립트 실행
pluginItems.forEach(function(pluginItem){
eval(pluginItem.script);
});
});
}
$(pluginXCore);