Jump to content
Wikimedia Meta-Wiki

User:SunAfterRain/js/markrights.js

From Meta, a Wikimedia project coordination wiki

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
 /**
  * markrights.js
  * 在最近修改、監視列表、記錄歷史記錄等位置以特殊情況顯示有特殊權限的用戶
  *
  * 修改自 https://zh.wikipedia.org/w/index.php?title=MediaWiki:Gadget-MarkRights.js&oldid=59130792
  *
  * 請注意當你引用這個頁面時沒有效果是正常的
  * 你還需要參考[[User:SunAfterRain/js/markrights.css]]
  * 在[[Special:MyPage/common.css]](全域:[[Special:MyPage/global.js]])加入對應的css!
  * 
  * 註:
  * 此版本同時會嘗試抓取全域權限並標註
  * 但全域權限一個請求只能查一個用戶
  * 可能導致載入緩慢
  * 此功能可以在載入這個小工具前加上
  * <syntaxhighlight lang="js">window.wgMarkRightsDoNotProcessGlobal = true;</syntaxhighlight>
  * 來強制關閉
  */
 // <nowiki>
 $.when(
 $.ready,
 mw.loader.using(["mediawiki.api","mediawiki.storage","mediawiki.Title","mediawiki.util"])
 ).then(()=>{
 constrightsMap=newMap();
 constgRightsMap=newMap();

 let$users;
 letusers;
 letqueue1=[];
 letqueue2=[];
 letdeferreds=[];
 leti=0,
 n=0,
 gi=0;
 constprocessGlobalKey="markrights.processGlobal";
 letprocessGlobal=mw.storage.get(processGlobalKey);

 if(window.wgMarkrightsDoNotProcessGlobal){
 processGlobal=false;
 }

 constdefaultMaxConcurrentRequests=10;
 constdefaultRequestWaitMs=200;
 classConcurrentApiextendsmw.Api{
 constructor(maxConcurrentRequests,requestWaitMs){
 super();
 this.inFlightRequests=0;
 this.requestQueue=[];
 this.maxConcurrentRequests=maxConcurrentRequests??defaultMaxConcurrentRequests;
 this.requestWaitMs=requestWaitMs??defaultRequestWaitMs;
 }

 ajax(...reqParams){
 constdeferred=$.Deferred();
 this.requestQueue.push(()=>super.ajax(...reqParams).then(deferred.resolve,deferred.reject));
 this.processQueue();
 returndeferred;
 }

 processQueue(){
 if(this.requestQueue.length>0&&this.inFlightRequests<this.maxConcurrentRequests){
 constrequest=this.requestQueue.shift();
 this.inFlightRequests++;
 request().always(()=>{
 this.inFlightRequests--;
 setTimeout(()=>this.processQueue(),this.requestWaitMs);
 });
 }
 }
 }
 constapi=newConcurrentApi(window.wgMarkRightsMaxConcurrentRequests,window.wgMarkRightsRequestWaitMs);

 constpathReg=newRegExp("^"+mw.util.escapeRegExp(mw.config.get("wgArticlePath")).replace(/\\\1ドル/g/* \1ドル */,'([^\\/]+)')+"$","i");
 functiongetUsernameFromTitle(title){
 if(title.indexOf(':')>0&&!title.includes('/')){
 try{
 constmTitle=newmw.Title(title);
 if(mTitle.namespace===2){
 returnmTitle.getMainText();
 }
 }catch(e){
 // ignore
 }
 }
 returnnull;
 }
 functiongetUsernameInternal(href){
 if(!href){
 returnnull;
 }
 consturl=newURL(href,window.location.href);
 constqueryTitle=url.searchParams.has("title")?url.searchParams.get("title"):null;
 if(queryTitle!==null){
 returngetUsernameFromTitle(queryTitle);
 }
 constmPathname=pathReg.exec(decodeURIComponent(url.pathname));
 if(mPathname){
 returngetUsernameFromTitle(mPathname[1]);
 }
 returnnull;
 }
 constgetUsernameCache=newMap();
 functiongetUsername(href){
 if(getUsernameCache.has(href)){
 returngetUsernameCache.get(href);
 }
 constresult=getUsernameInternal(href);
 getUsernameCache.set(href,result);
 returnresult;
 }

 functionprocess(data){
 if(data.query&&data.query.users){
 constuser=data.query.users;

 for(letj=0;j<user.length;j++){
 constu=user[j];
 if(u.groups){
 rightsMap.set(u.name,u.groups);
 }
 }
 }
 }

 functiongProcess(data){
 if(data.query&&data.query.globaluserinfo){
 constuser=data.query.globaluserinfo;

 gRightsMap.set(user.name,user.groups||[]);
 }
 }

 functionbuildMarkrightElement(groupId,isGlobal=false){
 constfinalClass=[
 'markrights'
 ];

 if(isGlobal){
 finalClass.push('markrights-global');
 }

 finalClass.push('markrights-'+groupId);

 return$('<sup>').addClass(finalClass);
 }

 functionerrorCallback(error){
 console.error(error);
 }

 functionmarkUG(){
 $(".markrights").remove();

 // eslint-disable-next-line no-jquery/no-global-selector
 $users=$([
 "a.mw-userlink:not( .mw-anonuserlink )",
 "ul.mw-logevent-loglines > li > a.userlink",
 // ".mw-special-GlobalUsers a.userlink",
 ".mw-contributions-user-tools > a",// Waring: .mw-contributions-user-tools > a.userlink didn't exist in some wiki
 ].join(","));
 users={};
 $users.each(function(_i,link){
 if(link.textContent){
 users[link.textContent]=true;
 }
 });
 queue1=[];
 queue2=[];
 deferreds=[];
 i=0;
 n=0;
 for(constuserinusers){
 if(rightsMap.has(user)){
 deleteusers[user];
 continue;
 }
 queue1.push(user);
 gi++;
 i++;
 if(i===50){
 queue2.push(queue1);
 queue1=[];
 n++;
 i=0;
 }
 }
 if(queue1.length>0){
 queue2.push(queue1);
 n++;
 }
 if(queue2.length){
 for(letj=0;j<queue2.length;j++){
 deferreds.push(api.get({
 format:"json",
 action:"query",
 list:"users",
 usprop:"groups",
 ususers:queue2[j].join("|")
 }).then(process,errorCallback));
 }
 }
 if(processGlobal===null){
 deferreds.push(api.get({
 format:"json",
 action:"query",
 meta:"globaluserinfo"
 }).then(function(data){
 constsDeferreds=[];

 if(data.query&&data.query.globaluserinfo){
 mw.storage.set(processGlobalKey,"true");
 processGlobal=true;
 gi++;
 gProcess(data);
 if(gi){
 for(constguinusers){
 if(gu===mw.config.get("wgUserName")){
 gi--;
 continue;
 }else{
 sDeferreds.push(api.get({
 format:"json",
 action:"query",
 meta:"globaluserinfo",
 guiuser:gu,
 guiprop:"groups"
 }).then(gProcess,errorCallback));
 }
 }
 }
 }else{
 mw.storage.set(processGlobalKey,"false");
 processGlobal=false;
 }

 returnPromise.all(sDeferreds);
 },errorCallback));
 }elseif(processGlobal===true||processGlobal==="true"){
 for(constguinusers){
 if(gu===mw.config.get("wgUserName")){
 continue;
 }else{
 deferreds.push(api.get({
 format:"json",
 action:"query",
 meta:"globaluserinfo",
 guiuser:gu,
 guiprop:"groups"
 }).then(gProcess,errorCallback));
 }
 }
 }

 Promise.all(deferreds)
 .then(function(){
 $users.each(function(_i,el){
 constusername=getUsername($(el).attr("href"));
 if(username){
 constappends=[];

 (gRightsMap.get(username)||[]).forEach(function(group){
 appends.push(buildMarkrightElement(group,true));
 });

 // eslint-disable-next-line no-jquery/no-each-util
 (rightsMap.get(username)||[]).filter(function(group){
 if(processGlobal&&group==="steward"){// [[mw:Extension:CentralAuth#Setup]]: migrateStewards.php
 returnfalse;
 }
 return["*","user"].indexOf(group)===-1;
 }).forEach(function(group){
 appends.push(buildMarkrightElement(group));
 });
 $(el).append(...appends.reverse());
 }
 });
 });
 }

 if(mw.config.get("wgDiffNewId")||mw.config.get("wgDiffOldId")){
 // 啟用「互動式瀏覽歷史」,切換差異時重新標記
 mw.hook("wikipage.diff").add(function(){
 markUG();
 });
 }elseif(["Recentchanges","Recentchangeslinked","Watchlist"].indexOf(mw.config.get("wgCanonicalSpecialPageName"))!==-1){
 // 近期/相關變更更新時重新標記
 mw.hook("wikipage.content").add(function(element){
 if(element.hasClass("mw-changeslist")){
 markUG();
 }
 });
 markUG();
 }elseif(mw.config.get("wgCanonicalSpecialPageName")==="Listgrouprights"){
 $(".mw-listgrouprights-table tr").each(function(_i,e){
 const$e=$(e);
 if(!$e.attr("id")){
 return;
 }
 const$exec=$e.children("td:first").children(":first");
 letmethod="after";
 if(!$exec.length){
 return;
 }elseif($exec.get(0).tagName.toLowerCase()==="br"){
 method="before";
 }
 $exec[method](buildMarkrightElement($e.attr("id")));
 });
 }elseif(mw.config.get("wgCanonicalSpecialPageName")==="GlobalGroupPermissions"){
 constbase=mw.util.getUrl(mw.config.get("wgPageName"))+"/";

 functionfindGlobalGroupId($a){
 return$a.get().filter(function(a){
 if($(a).attr("href")&&$(a).attr("href").startsWith(base)){
 returntrue;
 }
 returnfalse;
 }).map(function(a){
 return$(a).attr("href").slice(base.length);
 })[0];
 }

 $(".mw-centralauth-groups-table tr").each(function(_i,e){
 const$e=$(e);
 constid=findGlobalGroupId($e.find("a"));
 if(!id){
 return;
 }
 const$exec=$e.children("td:first").children(":first");
 letmethod="after";
 if(!$exec.length){
 return;
 }elseif($exec.get(0).tagName.toLowerCase()==="br"){
 method="before";
 }
 $exec[method](buildMarkrightElement(id,true));
 });
 }else{
 markUG();
 }
 });
 // </nowiki>

AltStyle によって変換されたページ (->オリジナル) /