User:Jackmcbarn/editProtectedHelper.js/CILI sandbox.js

//The following was copied from User:Jackmcbarn/editProtectedHelper.js for sandbox purposes // var browserHasDataCorruptionBug = $(' ')[0].outerHTML != ' '; if(browserHasDataCorruptionBug && ('undefined' === typeof ephAllowDataCorruptionBug || !ephAllowDataCorruptionBug)) { $(document).ready(function {		$('.editrequest .mbox-text').append(' The editProtectedHelper script is currently disabled because your browser has a bug which will cause corruption of pages that it edits with Parsoid. See here 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. ');	}); // 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( ['mediawiki.api'], function { 'use strict'; var templateResponses = [ [ '', '(No template response)' ], [ 'd', 'Done' ], [ 'pd', 'Partly done:' ], [ 'nd', 'Not done:' ], [ 'nfn', 'Not done for now:' ], [ 'c', 'Not done: please establish a consensus for this alteration before using the template.'], // TODO make dynamic [ 'rs', 'Not done: please provide reliable sources that support the change you want to be made.' ], [ 'xy', 'Not done: it\'s not clear what changes you want made.' ],[ 'xy', 'Please mention the specific changes in a "change X to Y" format.' ], [ 'mis', 'Not done: this is the talk page for discussing improvements to the template '],[ 'mis', 'Please make your request at the talk page for the article concerned.'], // TODO make dynamic [ 'sb', 'Not done: please make your requested changes to the template\'s sandbox first; see WP:TESTCASES.' ], [ 'tp', 'Not done: this is the talk page for discussing improvements to the template .' ],[ 'tp', 'If possible, please make your request at the talk page for the article concerned.' ],[ 'tp', 'If you cannot edit the article\'s talk page, you can instead make your request at' ],[ 'tp', 'Wikipedia:Requests for page protection#Current requests for edits to a protected page.' ], [ 'a', 'Already done' ], [ 'hr', 'Not done: According to the page\'s protection level and your user rights, you should be able to edit the page yourself.' ], [ 'hr', 'If you seem to be unable to, please reopen the request with further details.'], [ 'nlp', 'Not done: The page\'s protection level has changed since this request was placed.' ],[ 'nlp', 'You should now be able to edit the page yourself. If you still seem to be unable to, please reopen the request with further details.'], [ 'doc', 'Not done: is usually not required for edits to the documentation, categories,' ],[ 'doc', 'or interlanguage links of templates using a documentation subpage.' ],[ 'doc', 'Use the \'edit\' link at the top of the green "Template documentation" box to edit the documentation subpage.' ], [ 'drv', 'Not done: requests for recreating deleted pages protected against creation should be made at Wikipedia:Deletion review.' ], [ 'r', 'Not done: requests for increases to the page protection level should be made at Wikipedia:Requests for page protection.' ], [ 'ru', 'Not done: requests for decreases to the page protection level should be directed to the protecting admin' ],[ 'ru', 'or to Wikipedia:Requests for page protection if the protecting admin is not active or has declined the request.' ], [ 'p', 'Not done: this is not the right page to request additional user rights.' ],[ 'p', 'You may reopen this request with the specific changes to be made and someone will add them for you.'], // TODO make dynamic [ 'm', 'Not done: page move requests should be made at Wikipedia:Requested moves.' ], [ 'q', 'Question:' ], [ 'note', 'Note:' ], [ 'udp', 'Undone: This request (or the completed portion of it) has been undone.' ], [ 'ud', 'Undone: This request has been undone.' ] ];			var selector = $('.editrequest .mbox-text');

// Global variable. In onParsoidDomReceived, this is set // to the ETag header so that we can pass it back later // in convertModifiedDom. var gEtag;

// Global variable. In onParsoidDomReceived, this is // set to the string we get back from the Parsoid API. // Used in convertModifiedDom. var parsoidDom;

var selectedLevel = { semi: [' selected="selected"', , , , ], extended: [, ' selected="selected"', , , ], template: [, , ' selected="selected"', , ], full: [, , , ' selected="selected"', ], interface: [, , , , ' selected="selected"'] }; var templateLevel = { semi: 'semi-', extended: 'extended-', template: 'template-', full: 'fully-', interface: 'interface-' }; var responseLevel = { semi: '{' + '{subst:ESp|', extended: '{' + '{subst:EEp|', template: '{' + '{subst:ETp|', full: '{' + '{subst:EP|', interface: '{' + '{subst:EIp|' }; var warnOnRespond = false, warnOnQuickRespond = true, warnOnRemove = true, autoFixLevel = true; var quickResponses = [ [ 'd', '', 'Done'], [ 'rs', '', 'Needs reliable sources'], [ 'xy', '', 'Unclear/X to Y'], [ 'hr', '', 'Could always edit'], [ 'nlp', '', 'Can edit now'], [ 'mis', '', 'Misplaced'] ];			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  : '}}');			}			function getResponse(level, template, free) {				return ':' + (template ===  ?  : responseLevel[level] + 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[0];					if(parsoidObj.respondedInPage) {						tmp = tmp[1].split(parsoidObj.responseMarker);						newWikitext = newWikitext.replace(/\n+$/, ) + "\n\n" + tmp[1].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[0].replace(/\n*$/, tmp[0].trim.length ? "\n\n" : '') + banner + tmp[1].replace(/^\n*/, "\n"); if(parsoidObj.respondedInPage) { tmp = newWikitext.split(parsoidObj.responseMarker); newWikitext = tmp[0].replace(/\n*$/, "\n") + response + tmp[1].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 (EPH)', notminor: true, nocreate: true, basetimestamp: data.query.pages[mw.config.get('wgArticleId')].revisions[0].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...'); if( window.editProtectedHelperReloadAfter ) { window.location.reload( /* forcedReload */ true ); } else { 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('[typeof="mw:Transclusion"]').length) {							// it's from a template transclusion. ignore							return true;						}						if(obj.add(parsoidObj)[0] === this) {							// before our banner. set as our section header (tentatively) and otherwise ignore							parsoidObj.section = obj;							return true;						}					} else if (obj.add(parsoidObj)[0] === 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; }				$('[about="' + $(parsoidObj).attr('about').replace('\\', '\\\\').replace('"', '\\"') + '"]', 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/wiki/User:Jackmcbarn/editProtectedHelper)',						'If-Match': gEtag					},					data: { html: parsoidDom.documentElement.outerHTML },					success: function(data) { return saveWikitextFromParsoid(parsoidObj, data); }				}); }			function appendForm(obj, level, pagename, answered, force, parsoidObj) { if(browserHasDataCorruptionBug) { $(obj).append(' WARNING: Your browser has a bug which will cause corruption of pages that it edits with Parsoid. See here for details. You are responsible for any damage to pages that this causes. '); }				var form = $(''); form.append(' .mw-ui-input { background-color: white; } '); form.append(' Level: Semi-protected Extended-confirmed-protected Template-protected Fully protected Interface-protected  '); if(force) { form.append(' Disable protection level autodetection (use only if necessary):  ' ); } else { form.append('' ); // 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 = $(' Page to be edited: '); label.append($('').attr('value', pagename !== '' ? pagename : '')); form.append(label); form.append(' Answered:  Response: '); var select = $(''); templateResponses.forEach(function(r) {					select.append($(' ').attr('value', r[0]).text(r[1]));				}); 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."> ' + ' '); var resultObj = $(' '); var button = $('<button type="button" class="mw-ui-button mw-ui-constructive">Submit ').click(parsoidObj, convertModifiedDom); form.append(button); form.append(' '); $(obj).append(form); var buttons = $(' '); buttons.append($('<button type="button" class="mw-ui-button mw-ui-progressive">Respond ').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 ').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[2]).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[0];								parsoidObj.form.responsefree.value = r[1];								button.click;							}						}));					}); }				$(obj).append(buttons); $(obj).append(resultObj); parsoidObj.form = form[0]; 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[0].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'; break; case 'editinterfaceprotected': level = 'interface'; }				}				var params = []; for(var key in data_mw.parts[0].template.params) { params[key] = data_mw.parts[0].template.params[key].wt; }				// this only runs on numerical parameters params.forEach(function(value, key) {					if(/=/.test(value)) {						params[key] = 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[index], level, pagename, answered, force, this); }			function onParsoidDomReceived(data, textStatus, jqXHR) {

// Grab the ETag header and store it in the global // gEtag for later use var headers = jqXHR.getAllResponseHeaders.split( "\r\n" ); for( var i = 0, n = headers.length; i < n; i++ ) { if( headers[i].substring( 0, headers[i].indexOf( ":" ) ) === "etag" ) { gEtag = headers[i].substring( headers[i].indexOf( ":" ) + 2 ); break; }				}

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/wiki/Specs/HTML/2.0.0"',						'Api-User-Agent': 'editProtectedHelper (https://en.wikipedia.org/wiki/User:Jackmcbarn/editProtectedHelper)'					},					success: onParsoidDomReceived				}); }		});	}); } // ]