// <nowiki>(function(){varUNBLOCK_REQ_COLOR="rgb(235, 244, 255)";varSIGNATURE="~~"+"~~";varDECLINE_REASON_HERE="{"+"{subst:Decline reason here}}";// broken up to prevent processingvarADVERT=" ([[User:Enterprisey/unblock-review|unblock-review]])";// Making this a function for unit test reasons.functiongetInitialText(wikitext,appealReason){// https://stackoverflow.com/a/6969486/3480193functionescapeRegExp(string){returnstring.replace(/[.*+?^${}()|[\]\\]/g,'\\$&');// $& means the whole matched string}letregEx=newRegExp(escapeRegExp(appealReason),'g');letmatches=wikitext.matchAll(regEx);matches=[...matches];if(matches.length===0){thrownewError("Searching for target text failed!");}for(letmatchofmatches){vartextIdx=match.index;varstartIdx=textIdx;// check for {{tlx|unblock. if found, this isn't what we want, skip.letstartOfSplice=startIdx-50<0?0:startIdx-50;varchunkFiftyCharactersWide=wikitext.substring(startOfSplice,startIdx);if(/\{\{\s*tlx\s*\|\s*unblock/i.test(chunkFiftyCharactersWide)){continue;}leti=0;while(wikitext[startIdx]!="{"&&i<50){startIdx--;i++;}if(i==50){continue;}startIdx--;// templates start with two opening curly bracesvarinitialText=wikitext.substring(startIdx,textIdx);returninitialText;}thrownewError("Searching backwards failed!");}if(mw.config.get("wgNamespaceNumber")===3){/** * Is there a signature (four tildes) present in the given text, * outside of a nowiki element? */functionhasSig(text){// no literal signature?if(text.indexOf(SIGNATURE)<0)returnfalse;// if there's a literal signature and no nowiki elements,// there must be a real signatureif(text.indexOf("<nowiki>")<0)returntrue;// Save all nowiki spansvarnowikiSpanStarts=[];// list of ignored span beginningsvarnowikiSpanLengths=[];// list of ignored span lengthsvarNOWIKI_RE=/<nowiki>.*?<\/nowiki>/g;varspanMatch;do{spanMatch=NOWIKI_RE.exec(text);if(spanMatch){nowikiSpanStarts.push(spanMatch.index);nowikiSpanLengths.push(spanMatch[0].length);}}while(spanMatch);// So that we don't check every ignore span every timevarnowikiSpanStartIdx=0;varSIG_RE=newRegExp(SIGNATURE,"g");varsigMatch;matchLoop:do{sigMatch=SIG_RE.exec(text);if(sigMatch){// Check that we're not inside a nowikifor(varnwIdx=nowikiSpanStartIdx;nwIdx<nowikiSpanStarts.length;nwIdx++){if(sigMatch.index>nowikiSpanStarts[nwIdx]){if(sigMatch.index+sigMatch[0].length<=nowikiSpanStarts[nwIdx]+nowikiSpanLengths[nwIdx]){// Invalid sigcontinuematchLoop;}else{// We'll never encounter this span again, since// headers only get later and later in the wikitextnowikiSpanStartIdx=nwIdx;}}}// We aren't inside a nowikireturntrue;}}while(sigMatch);returnfalse;}/** * Given the div of an unblock request, set up the UI and event * listeners. */functionsetUpUi(unblockDiv){varcontainer=document.createElement("table");container.className="unblock-review";varhrEl=unblockDiv.querySelector("hr");container.innerHTML="<tr><td class='reason-container' rowspan='2'>"+"<textarea class='unblock-review-reason mw-ui-input'"+" placeholder='Reason for accepting/declining here'>"+DECLINE_REASON_HERE+"</textarea></td>"+"<td><button class='unblock-review-accept mw-ui-button mw-ui-progressive'>Accept</button></td></tr>"+"<tr><td><button class='unblock-review-decline mw-ui-button mw-ui-destructive'>Decline</button></td></tr>";unblockDiv.insertBefore(container,hrEl.previousElementSibling);varreasonArea=container.querySelector("textarea");$(container).find("button").click(function(){varaction=$(this).text().toLowerCase();varappealReason=hrEl.nextElementSibling.nextElementSibling.childNodes[0].textContent;$.getJSON(mw.util.wikiScript("api"),{format:"json",action:"query",prop:"revisions",rvprop:"content",rvlimit:1,titles:mw.config.get("wgPageName")}).done(function(data){// Extract wikitext from API responsevarpageId=Object.keys(data.query.pages)[0];wikitext=data.query.pages[pageId].revisions[0]["*"];varinitialText=getInitialText(wikitext,appealReason);// Build accept/decline reasonvarreason=reasonArea.value;if(!reason.trim()){reason=DECLINE_REASON_HERE+" "+SIGNATURE;}elseif(!hasSig(reason)){reason=reason+" "+SIGNATURE;}wikitext=wikitext.replace(initialText+appealReason,"{"+"{unblock reviewed|"+action+"="+reason+"|1="+appealReason);varsummary=(action==="accept"?"Accepting":"Declining")+" unblock request"+ADVERT;(newmw.Api()).postWithToken("csrf",{action:"edit",title:mw.config.get("wgPageName"),summary:summary,text:wikitext}).done(function(data){if(data&&data.edit&&data.edit.result&&data.edit.result=="Success"){window.location.reload(true);}else{console.log(data);}});});});}$.when($.ready,mw.loader.using(["mediawiki.api","mediawiki.util"])).then(function(){mw.util.addCSS(".unblock-review td { padding: 0 }"+"td.reason-container { padding-right: 1em; width: 30em }"+".unblock-review-reason { height: 5em }");importStylesheet("User:Enterprisey/mw-ui-button.css");importStylesheet("User:Enterprisey/mw-ui-input.css");varuserBlockBoxes=document.querySelectorAll("div.user-block");for(vari=0,n=userBlockBoxes.length;i<n;i++){if(userBlockBoxes[i].style["background-color"]!==UNBLOCK_REQ_COLOR){continue;}// We now have a pending unblock request - add UIsetUpUi(userBlockBoxes[i]);}});}})();// </nowiki>