forked from enterprisey/unblock-review
-
Notifications
You must be signed in to change notification settings - Fork 0
/
unblock-review.js
176 lines (153 loc) · 7.4 KB
/
unblock-review.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// <nowiki>
( function () {
var UNBLOCK_REQ_COLOR = "rgb(235, 244, 255)";
var SIGNATURE = "~~" + "~~";
var DECLINE_REASON_HERE = "{" + "{subst:Decline reason here}}"; // broken up to prevent processing
var ADVERT = " ([[User:Enterprisey/unblock-review|unblock-review]])";
if( mw.config.get( "wgNamespaceNumber" ) === 3 ) {
/**
* Is there a signature (four tildes) present in the given text,
* outside of a nowiki element?
*/
function hasSig( text ) {
// no literal signature?
if( text.indexOf( SIGNATURE ) < 0 ) return false;
// if there's a literal signature and no nowiki elements,
// there must be a real signature
if( text.indexOf( "<nowiki>" ) < 0 ) return true;
// Save all nowiki spans
var nowikiSpanStarts = []; // list of ignored span beginnings
var nowikiSpanLengths = []; // list of ignored span lengths
var NOWIKI_RE = /<nowiki>.*?<\/nowiki>/g;
var spanMatch;
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 time
var nowikiSpanStartIdx = 0;
var SIG_RE = new RegExp( SIGNATURE, "g" );
var sigMatch;
matchLoop:
do {
sigMatch = SIG_RE.exec( text );
if( sigMatch ) {
// Check that we're not inside a nowiki
for( var nwIdx = nowikiSpanStartIdx; nwIdx <
nowikiSpanStarts.length; nwIdx++ ) {
if( sigMatch.index > nowikiSpanStarts[nwIdx] ) {
if ( sigMatch.index + sigMatch[0].length <=
nowikiSpanStarts[nwIdx] + nowikiSpanLengths[nwIdx] ) {
// Invalid sig
continue matchLoop;
} else {
// We'll never encounter this span again, since
// headers only get later and later in the wikitext
nowikiSpanStartIdx = nwIdx;
}
}
}
// We aren't inside a nowiki
return true;
}
} while( sigMatch );
return false;
}
/**
* Given the div of an unblock request, set up the UI and event
* listeners.
*/
function setUpUi( unblockDiv ) {
var container = document.createElement( "table" );
container.className = "unblock-review";
var hrEl = 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 );
var reasonArea = container.querySelector( "textarea" );
$( container ).find( "button" ).click( function () {
var action = $( this ).text().toLowerCase();
var someText = hrEl.nextElementSibling.nextElementSibling.childNodes[0].textContent;
console.log(someText);
$.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 response
var pageId = Object.keys(data.query.pages)[0];
wikitext = data.query.pages[pageId].revisions[0]["*"];
var textIdx = wikitext.indexOf( someText );
if( textIdx < 0 ) {
console.log( "Searching for target text failed!" );
return;
}
var startIdx = textIdx;
var i = 0;
while( wikitext[startIdx] != "{" && i < 50 ) {
startIdx--;
i++;
}
if( i == 50 ) {
console.log( "Searching backwards failed!" );
return;
}
startIdx--; // templates start with two opening curly braces
var initialText = wikitext.substring( startIdx, textIdx );
// Build reason
var reason = reasonArea.value;
if( !reason.trim() ) {
reason = DECLINE_REASON_HERE + " " + SIGNATURE;
} else if( !hasSig( reason ) ) {
reason = reason + " " + SIGNATURE;
}
wikitext = wikitext.replace( initialText + someText, "{" +
"{unblock reviewed|" + action + "=" + reason + "|1=" + someText );
var summary = ( action === "accept" ? "Accepting" : "Declining" ) +
" unblock request" + ADVERT;
( new mw.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" );
var userBlockBoxes = document.querySelectorAll( "div.user-block" );
for( var i = 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 UI
setUpUi( userBlockBoxes[i] );
}
} );
}
} )();
// </nowiki>