Revision as of 03:31, 23 September 2018 view sourceEnterprisey (talk | contribs)Edit filter managers, Autopatrolled, Administrators34,926 edits copy from User:Jackmcbarn/editProtectedHelper.js (at oldid 846176034) |
Latest revision as of 04:06, 13 April 2019 view source Enterprisey (talk | contribs)Edit filter managers, Autopatrolled, Administrators34,926 edits blank; mischief managedTag: Blanking |
(4 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
|
// <nowiki> |
|
|
var browserHasDataCorruptionBug = $('<div style="color:#ffd"></div>').outerHTML != '<div style="color:#ffd"></div>'; |
|
|
if(browserHasDataCorruptionBug && ('undefined' === typeof ephAllowDataCorruptionBug || !ephAllowDataCorruptionBug)) { |
|
|
$(document).ready(function() { |
|
|
$('.editrequest .mbox-text').append('<small>The editProtectedHelper script is currently disabled because your browser has a bug which will cause corruption of pages that it edits with Parsoid. See <a href="https://www.mediawiki.org/User:Catrope/IE_bugs#style_attributes_are_aggressively_normalized.2C_causing_data_loss">here</a> for details. To override this, add "ephAllowDataCorruptionBug = true;" immediately above the line where you load this script. You are responsible for any damage to pages that this causes.</small>'); |
|
|
}); |
|
|
// only enable this on the latest revision of the page |
|
|
} else if(mw.config.get('wgRevisionId') == mw.config.get('wgCurRevisionId')) { |
|
|
$(document).ready(function() { |
|
|
mw.loader.using( , function() { |
|
|
'use strict'; |
|
|
var templateResponses = [ |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
, // TODO make dynamic |
|
|
, |
|
|
, |
|
|
, // TODO make dynamic |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
, // TODO make dynamic |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
|
|
|
]; |
|
|
var selector = $('.editrequest .mbox-text'), parsoidDom; |
|
|
var selectedLevel = { semi: , extended: , template: , full: }; |
|
|
var templateLevel = { semi: 'semi-', extended: 'extended-', template: 'template-', full: 'fully-' }; |
|
|
var responseLevel = { semi: '{' + '{subst:ESp|', extended: '{' + '{subst:EEp|', template: '{' + '{subst:ETp|', full: '{' + '{subst:EP|' }; |
|
|
var warnOnRespond = false, warnOnQuickRespond = true, warnOnRemove = true, autoFixLevel = true; |
|
|
var quickResponses = [ |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
, |
|
|
|
|
|
]; |
|
|
if('undefined' !== typeof ephWarnOnRespond) { |
|
|
warnOnRespond = ephWarnOnRespond; |
|
|
} |
|
|
if('undefined' !== typeof ephWarnOnQuickRespond) { |
|
|
warnOnQuickRespond = ephWarnOnQuickRespond; |
|
|
} |
|
|
if('undefined' !== typeof ephWarnOnRemove) { |
|
|
warnOnRemove = ephWarnOnRemove; |
|
|
} |
|
|
if('undefined' !== typeof ephAutoFixLevel) { |
|
|
autoFixLevel = ephAutoFixLevel; |
|
|
} |
|
|
if('undefined' !== typeof ephQuickResponses) { |
|
|
quickResponses = ephQuickResponses; |
|
|
} |
|
|
function yesno(val, def) { |
|
|
if(typeof val === 'string') { |
|
|
val = val.toLowerCase(); |
|
|
} |
|
|
if(typeof val === 'undefined' || val === '') { |
|
|
return undefined; |
|
|
} else if(val === 'yes' || val === 'y' || val === 'true' || val === 1) { |
|
|
return true; |
|
|
} else if(val === 'no' || val === 'n' || val === 'false' || val === 0) { |
|
|
return false; |
|
|
} |
|
|
return def; |
|
|
} |
|
|
function getBanner(level, pagename, answered, force, demo) { |
|
|
return '{{edit ' + templateLevel + 'protected' + (pagename !== '' ? '|' + pagename : '') + '|answered=' + (answered ? 'yes' : 'no') + (force ? '|force=yes' : '') + (demo ? '|demo=yes}}' : '}}'); |
|
|
} |
|
|
function getResponse(level, template, free) { |
|
|
return ':' + (template === '' ? '' : responseLevel + template + '}} ') + (free === '' ? '' : free + ' ') + '~~' + "~~\n"; |
|
|
} |
|
|
function makeUniqueString(index) { |
|
|
// this looks like a strip marker on purpose |
|
|
return "\x7fUNIQ" + Math.random().toString(16).substr(2) + '-editProtectedHelper-' + index + "-QINU\x7f"; |
|
|
} |
|
|
function saveWikitextFromParsoid(parsoidObj, data) { |
|
|
var newWikitext, tmp, removerequest = false; |
|
|
if(parsoidObj.removerequest) { |
|
|
tmp = data.split(parsoidObj.templateMarker); |
|
|
removerequest = true; |
|
|
newWikitext = tmp; |
|
|
if(parsoidObj.respondedInPage) { |
|
|
tmp = tmp.split(parsoidObj.responseMarker); |
|
|
newWikitext = newWikitext.replace(/\n+$/, '') + "\n\n" + tmp.replace(/^\n+/, ''); |
|
|
} |
|
|
} else { |
|
|
var response = getResponse(parsoidObj.form.level.value, parsoidObj.form.responsetemplate.value, parsoidObj.form.responsefree.value); |
|
|
var banner = getBanner(parsoidObj.form.level.value, parsoidObj.form.pagetoedit.value, parsoidObj.form.answered.checked, parsoidObj.form.force.checked, parsoidObj.demo); |
|
|
// prevent empty response |
|
|
if(response == ':~~' + "~~\n") { |
|
|
response = ''; |
|
|
} |
|
|
tmp = data.split(parsoidObj.templateMarker); |
|
|
newWikitext = tmp.replace(/\n*$/, tmp.trim().length ? "\n\n" : '') + banner + tmp.replace(/^\n*/, "\n"); |
|
|
if(parsoidObj.respondedInPage) { |
|
|
tmp = newWikitext.split(parsoidObj.responseMarker); |
|
|
newWikitext = tmp.replace(/\n*$/, "\n") + response + tmp.replace(/^\n*/, "\n"); |
|
|
} else { |
|
|
newWikitext = newWikitext.replace(/\n*$/, "\n") + response; |
|
|
} |
|
|
} |
|
|
var resultObj = parsoidObj.resultObj, sectionName = parsoidObj.section && parsoidObj.section.text().trim(); |
|
|
if(sectionName && (sectionName.indexOf(parsoidObj.templateMarker) !== -1 || sectionName.indexOf(parsoidObj.responseMarker) !== -1)) { |
|
|
// someone put an edit request template inside the section header, or something like that. |
|
|
// don't even try to include a working section link in that case |
|
|
sectionName = null; |
|
|
} |
|
|
console.log(newWikitext); |
|
|
resultObj.text('Saving...'); |
|
|
debugger; // triggers only if debugger is active |
|
|
new mw.Api().get( { action: 'query', prop: 'revisions', rvprop: 'timestamp', revids: mw.config.get('wgRevisionId') }).done(function(data) { |
|
|
new mw.Api().postWithEditToken( { action: 'edit', pageid: mw.config.get('wgArticleId'), text: newWikitext, summary: (sectionName ? '/' + '* ' + sectionName + ' *' + '/ ' : '') + (removerequest ? 'Removed' : 'Responded to') + ' edit request (])', notminor: true, nocreate: true, basetimestamp: data.query.pages.revisions.timestamp } ).done(function(result) { |
|
|
if(typeof(result.edit.newrevid) === 'undefined' || typeof(result.edit.oldrevid) === 'undefined') { |
|
|
resultObj.css('color', 'red').text("Error: The API response omitted required information. Please check the page's history manually to see whether your edit was saved properly. The console may contain details."); |
|
|
} else { |
|
|
resultObj.css('color', 'green').text('Success: Loading diff...'); |
|
|
location.href = mw.config.get('wgScript') + '?diff=' + result.edit.newrevid + '&oldid=' + result.edit.oldrevid; |
|
|
} |
|
|
}).fail(function(err) { |
|
|
resultObj.css('color', 'red').text('Error: ' + err + '. The console may contain details.'); |
|
|
}).always(console.log); |
|
|
}); |
|
|
} |
|
|
function convertModifiedDom(e) { |
|
|
var parsoidObj, nextRequestBeforeHeader = false; |
|
|
if(warnOnRespond && !confirm('Are you sure you want to respond to this edit request?')) { |
|
|
return false; |
|
|
} |
|
|
$('.editrequest button').prop('disabled', true); |
|
|
parsoidObj = e.data; |
|
|
parsoidObj.resultObj.text('Preparing new wikitext...'); |
|
|
$(parsoidObj).before(parsoidObj.templateMarker); |
|
|
$('h1,h2,h3,h4,h5,h6,.editrequest', parsoidDom).each(function() { |
|
|
var obj = $(this); |
|
|
if(!obj.hasClass('editrequest')) { |
|
|
// a heading |
|
|
if(obj.closest('').length) { |
|
|
// it's from a template transclusion. ignore |
|
|
return true; |
|
|
} |
|
|
if(obj.add(parsoidObj) === this) { |
|
|
// before our banner. set as our section header (tentatively) and otherwise ignore |
|
|
parsoidObj.section = obj; |
|
|
return true; |
|
|
} |
|
|
} else if (obj.add(parsoidObj) === this) { |
|
|
// not after our banner. ignore |
|
|
return true; |
|
|
} else { |
|
|
nextRequestBeforeHeader = true; |
|
|
} |
|
|
obj.before(parsoidObj.responseMarker); |
|
|
parsoidObj.respondedInPage = true; |
|
|
return false; |
|
|
}); |
|
|
if(parsoidObj.removerequest && !nextRequestBeforeHeader && $(parsoidObj).prev().is(parsoidObj.section)) { |
|
|
// if the section header is immediately before a request being removed, remove it too |
|
|
parsoidObj.section.remove(); |
|
|
} |
|
|
$('', parsoidDom).remove(); |
|
|
$.ajax({ |
|
|
type: 'POST', |
|
|
url: '/api/rest_v1/transform/html/to/wikitext/' + encodeURIComponent(mw.config.get('wgPageName')) + '/' + mw.config.get('wgRevisionId'), |
|
|
headers: { |
|
|
Accept: 'text/plain; charset=utf-8; profile="mediawiki.org/specs/wikitext/1.0.0"', |
|
|
'Api-User-Agent': 'editProtectedHelper (https://en.wikipedia.org/User:Jackmcbarn/editProtectedHelper)' |
|
|
}, |
|
|
data: { html: parsoidDom.documentElement.outerHTML }, |
|
|
success: function(data) { return saveWikitextFromParsoid(parsoidObj, data); } |
|
|
}); |
|
|
} |
|
|
function appendForm(obj, level, pagename, answered, force, parsoidObj) { |
|
|
if(browserHasDataCorruptionBug) { |
|
|
$(obj).append('<div style="color:red;font-weight:bold">WARNING: Your browser has a bug which will cause corruption of pages that it edits with Parsoid. See <a href="https://www.mediawiki.org/User:Catrope/IE_bugs#style_attributes_are_aggressively_normalized.2C_causing_data_loss">here</a> for details. You are responsible for any damage to pages that this causes.</div>'); |
|
|
} |
|
|
var form = $('<form class="editProtectedHelper" style="display: none" />'); |
|
|
form.append('<style scoped>.mw-ui-input { background-color: white; }</style>'); |
|
|
form.append('<label>Level: <select name="level" class="mw-ui-input mw-ui-input-inline"><option value="semi"' + selectedLevel + '>Semi-protected</option><option value="extended"' + selectedLevel + '>Extended-confirmed-protected</option><option value="template"' + selectedLevel + '>Template-protected</option><option value="full"' + selectedLevel + '>Fully protected</option></select></label> '); |
|
|
if(force) { |
|
|
form.append('<label>Disable protection level autodetection (use only if necessary): <input type="checkbox" name="force" checked="checked" /></label> ' ); |
|
|
} else { |
|
|
form.append('<input type="checkbox" name="force" style="display: none" />' ); // if this is off and you want to turn it on, do it with firebug or something. otherwise people will use this when they shouldn't |
|
|
} |
|
|
var label = $('<label>Page to be edited: </label>'); |
|
|
label.append($('<input type="text" name="pagetoedit" class="mw-ui-input mw-ui-input-inline" />').attr('value', pagename !== '<!-- Page to be edited -->' ? pagename : '')); |
|
|
form.append(label); |
|
|
form.append(' <label>Answered: <input type="checkbox" name="answered"' + (answered ? ' checked="checked"' : '') + ' /></label><br />Response: '); |
|
|
var select = $('<select name="responsetemplate" class="mw-ui-input" />'); |
|
|
templateResponses.forEach(function(r) { |
|
|
select.append($('<option />').attr('value', r).text(r)); |
|
|
}); |
|
|
form.append(select); |
|
|
form.append('<textarea name="responsefree" class="mw-ui-input" placeholder="Enter any custom response text here. A signature will automatically be appended."></textarea> ~~' + '~~ '); |
|
|
var resultObj = $('<span></span>'); |
|
|
var button = $('<button type="button" class="mw-ui-button mw-ui-constructive">Submit</button>').click(parsoidObj, convertModifiedDom); |
|
|
form.append(button); |
|
|
form.append(' '); |
|
|
$(obj).append(form); |
|
|
var buttons = $('<div />'); |
|
|
buttons.append($('<button type="button" class="mw-ui-button mw-ui-progressive">Respond</button>').click(function(){ |
|
|
buttons.hide(); |
|
|
$(obj).closest('.editrequest').removeClass('mbox-small'); |
|
|
form.show(); |
|
|
})) |
|
|
.append(' ') |
|
|
.append($('<button type="button" class="mw-ui-button mw-ui-destructive">Remove request</button>').click(function(){ |
|
|
if(!warnOnRemove || confirm('Are you sure you want to completely remove this edit request from the page? In general, this should not be done to good-faith requests, even if they are blank, unless they are duplicates of other requests by the same user, etc.')) { |
|
|
warnOnRespond = false; |
|
|
parsoidObj.removerequest = true; |
|
|
button.click(); |
|
|
} |
|
|
})); |
|
|
if(!answered) { |
|
|
quickResponses.forEach(function(r){ |
|
|
buttons.append(' ').append($('<button type="button" class="mw-ui-button mw-ui-constructive" />').text(r).click(function(){ |
|
|
if(!warnOnQuickRespond || confirm('Are you sure you want to respond to this edit request?')) { |
|
|
warnOnRespond = false; |
|
|
parsoidObj.form.answered.checked = true; |
|
|
parsoidObj.form.responsetemplate.value = r; |
|
|
parsoidObj.form.responsefree.value = r; |
|
|
button.click(); |
|
|
} |
|
|
})); |
|
|
}); |
|
|
} |
|
|
$(obj).append(buttons); |
|
|
$(obj).append(resultObj); |
|
|
parsoidObj.form = form; |
|
|
parsoidObj.resultObj = resultObj; |
|
|
} |
|
|
function parsoidSetupFieldsForTemplate(index) { |
|
|
var obj = $(this); |
|
|
var data_mw = obj.attr('data-mw'); |
|
|
if(data_mw === undefined) { |
|
|
console.log("No data-mw attribute was found on edit request banner " + index + ". This is probably because some template above it on the page opened an HTML tag but didn't close it."); |
|
|
return; |
|
|
} |
|
|
data_mw = JSON.parse(data_mw); |
|
|
var templateName = data_mw.parts.template.target.wt; |
|
|
var level = obj.attr('data-origlevel'); |
|
|
if(autoFixLevel) { |
|
|
switch(this.id) { |
|
|
case 'editsemiprotected': |
|
|
level = 'semi'; |
|
|
break; |
|
|
case 'editextendedprotected': |
|
|
level = 'extended'; |
|
|
break; |
|
|
case 'edittemplateprotected': |
|
|
level = 'template'; |
|
|
break; |
|
|
case 'editprotected': |
|
|
level = 'full'; |
|
|
} |
|
|
} |
|
|
var params = ; |
|
|
for(var key in data_mw.parts.template.params) { |
|
|
params = data_mw.parts.template.params.wt; |
|
|
} |
|
|
|
|
|
// this only runs on numerical parameters |
|
|
params.forEach(function(value, key) { |
|
|
if(/=/.test(value)) { |
|
|
params = key + '=' + value; |
|
|
} |
|
|
}); |
|
|
|
|
|
var pagename = params.join('|').replace(/^\|+|\|+$/g, '').replace(/\|+/g, '|'); |
|
|
var answered = yesno(params.ans || params.answered, true); |
|
|
this.demo = yesno(params.demo); |
|
|
var force = yesno(params.force); |
|
|
this.params = params; |
|
|
this.templateMarker = makeUniqueString(2 * index); |
|
|
this.responseMarker = makeUniqueString(2 * index + 1); |
|
|
appendForm(selector, level, pagename, answered, force, this); |
|
|
} |
|
|
function onParsoidDomReceived(data) { |
|
|
parsoidDom = new DOMParser().parseFromString(data, 'text/html'); |
|
|
if(!parsoidDom) { |
|
|
// blech. Safari. |
|
|
parsoidDom = document.implementation.createHTMLDocument(''); |
|
|
parsoidDom.documentElement.innerHTML = data; |
|
|
} |
|
|
var parsoidSelector = $('.editrequest', parsoidDom); |
|
|
if(selector.length != parsoidSelector.length) { |
|
|
console.log('Sanity check failed: ' + selector.length + ' edit requests exist in the page but only ' + parsoidSelector.length + ' were found in Parsoid\'s output.'); |
|
|
return; |
|
|
} |
|
|
parsoidSelector.each(parsoidSetupFieldsForTemplate); |
|
|
} |
|
|
if(selector.length) { |
|
|
mw.loader.load('mediawiki.api.edit'); |
|
|
mw.loader.load('mediawiki.ui.button'); |
|
|
mw.loader.load('mediawiki.ui.input'); |
|
|
$.ajax({ |
|
|
url: '/api/rest_v1/page/html/' + encodeURIComponent(mw.config.get('wgPageName')) + '/' + mw.config.get('wgRevisionId'), |
|
|
headers: { |
|
|
Accept: 'text/html; charset=utf-8; profile="https://www.mediawiki.org/Specs/HTML/1.2.1"', |
|
|
'Api-User-Agent': 'editProtectedHelper (https://en.wikipedia.org/User:Jackmcbarn/editProtectedHelper)' |
|
|
}, |
|
|
success: onParsoidDomReceived |
|
|
}); |
|
|
} |
|
|
}); |
|
|
}); |
|
|
} |
|
|
// </nowiki> |
|