// Created on request by Enterprisey at [[WP:US/R]] ([[Special:Permalink/1080444570#2021 Q4]])
mw.loader.using(['mediawiki.diff', 'mediawiki.diff.styles', 'oojs-ui-core']).done(function() {
if (
!['view', 'edit'].includes(mw.config.get('wgAction')) ||
mw.config.get('wgNamespaceNumber') < 0 ||
mw.config.get('wgArticleId') < 1
) {
return;
}
var FER = {};
FER.pagename = mw.config.get('wgPageName');
FER.contentmodel = null;
FER.contentmodels = ['wikitext', 'text', 'sanitized-css', 'json', 'javascript', 'css', 'Scribunto'];
mw.util.addPortletLink('p-cactions', '', 'FER', 'pt-fer', 'Initialize Formatted Edit Request');
$('#pt-fer').click(function(e) {
e.preventDefault();
if (!$('#FER-main').length) {
mw.notify('Initializing, please wait...', {
autoHide: false,
tag: 'FER-notification'
});
main();
} else {
$('#mw-content-text, #FER-main').toggle();
}
function call(data, onsuccess, onerror) {
$.ajax({
url: mw.config.get('wgScriptPath') + '/api.php',
data: data,
type: 'POST',
dataType: 'json',
success: function(response) {
onsuccess(response);
},
error: function(response) {
onerror(response);
},
});
}
function main() {
(new mw.Api()).postWithEditToken({
action: 'query',
titles: FER.pagename,
prop: 'revisions',
rvprop: ['content', 'contentmodel'],
rvlimit: 1,
format: 'json',
formatversion: 2
}).done(function(response) {
FER.content = response.query.pages[0].revisions[0].content;
FER.contentmodel = response.query.pages[0].revisions[0].contentmodel;
if (!FER.contentmodels.includes(FER.contentmodel)) {
mw.notify('Page content model is not a simple text-based one.', {
title: 'Unallowed content model',
type: 'error',
autoHide: true,
autoHideSeconds: 5,
tag: 'FER-notification'
});
return;
}
$('#mw-content-text').hide();
FER.nochange =
'<table class="diff" id="FER-nochange">' +
'<tbody>' +
'<tr><td colspan="1" class="diff-notice">' +
'<div class="mw-diff-empty">(No difference)</div>' +
'</td></tr>' +
'</tbody>' +
'</table>';
FER.textarea = new OO.ui.MultilineTextInputWidget({
value: FER.content,
type: 'text',
id: 'FER-textarea-div',
inputId: 'FER-textarea'
});
FER.submit = new OO.ui.ButtonWidget({
label: 'Submit',
flags: [
'primary',
'progressive'
],
classes: 'FER-buttons',
id: 'FER-submit'
});
FER.copy = new OO.ui.ButtonWidget({
label: 'Copy',
classes: 'FER-buttons',
id: 'FER-copy'
});
FER.cancel = new OO.ui.ButtonWidget({
label: 'Cancel',
flags: [
'destructive'
],
classes: 'FER-buttons',
id: 'FER-cancel'
});
$('.mw-notification-tag-FER-notification').click();
$('#mw-content-text').after(
$('<div>').attr('id', 'FER-main').append(
FER.textarea.$element,
$('<div>').attr('id', 'FER-buttons').css({
'display': 'flex',
'padding': '5px',
'justify-content': 'space-between'
}),
$('<div>').attr('id', 'FER-diff').css({
'border': '1px solid #A2A9B1',
'padding': '0 5px'
}).html(FER.nochange)
)
);
$('#FER-buttons').prepend(
$('<div>').append(
FER.submit.$element, FER.copy.$element
),
$('<div>').append(
FER.cancel.$element
)
);
$('#FER-textarea-div').css({
'margin': 0,
'max-width': '100%'
});
$('#FER-textarea').css({
'min-height': '300px',
'min-width': '100%',
'resize': 'vertical',
'font-size': 'small',
'font-family': 'monospace, monospace'
});
$('#FER-buttons > .FER-buttons').css({
'padding-left': '5px'
});
$('#FER-copy').css({
'display': 'none'
});
$('#FER-submit').click(function() {
$('#FER-diff').empty();
$('#FER-copy').fadeOut('fast');
// Submit once, please.
$(this).removeClass('oo-ui-widget-enabled').addClass('oo-ui-widget-disabled');
$(this).children().removeClass('oo-ui-widget-enabled').addClass('oo-ui-widget-disabled');
// Notify user that FER is running
$('#FER-copy').after(
$('<img>').attr({
src: 'https://upload.wikimedia.org/wikipedia/commons/5/51/Ajax-loader4.gif',
width: 30,
height: 30,
alt: 'Loading...',
id: 'FER-submitting',
})
);
// Hidden counter.
$('#FER-diff').append(
$('<span>')
.text('10')
.attr('id', 'FER-counter')
.css('display', 'none')
);
// Timeout after 10 seconds or so.
FER.interval = window.setInterval(function() {
$('#FER-counter').text($('#FER-counter').text() - 1);
if ($('#FER-counter').text() == 0) {
window.clearInterval(FER.interval);
$('#FER-diff').css('border', '');
$('#FER-counter').show().html(
$('<div>').html(
$('<strong>')
.text('Cannot get diff for some reason. Please make your request manually.')
.attr('class', 'error')
.css('color', '#DD3333')
).css({
'display': 'block',
'text-align': 'center',
'font-size': 'larger'
})
);
$('.mw-notification-tag-FER-notification').click();
$('[id^=FER-]:not(#FER-diff, #FER-counter)').fadeOut('fast', 'swing', function() {
$(this).remove();
});
window.setTimeout(function() {
location.reload();
}, 2000);
}
}, 1000);
/* (new mw.Api()).get({ // Somehow mw.Api() doesn't work when countering long URLs.
action: 'compare',
// fromslots: 'main',
fromtitle: FER.pagename,
toslots: 'main',
'totext-main': $('#FER-textarea').val(),
format: 'json',
formatversion: 2
}).done(function(response) { */
call({
action: 'compare',
fromtitle: FER.pagename,
toslots: 'main',
'totext-main': $('#FER-textarea').val(),
format: 'json',
formatversion: 2
}, function(response) {
console.log(response);
window.clearInterval(FER.interval);
FER.diff =
(response.compare.body == '' ? FER.nochange :
'<table class="diff diff-editfont-monospace" id="FER-diff-inner" ' +
'style="margin: auto; font-size: small; overflow-wrap: break-word;">' +
'<colgroup>'+
'<col class="diff-marker">'+
'<col class="diff-content">'+
'<col class="diff-marker">'+
'<col class="diff-content">'+
'</colgroup>'+
'<tbody>' + response.compare.body + '</tbody>'+
'</table>'
);
// Revert things back to normal.
$('#FER-diff').empty(); // Clean up old diff or #FER-nochange.
$('#FER-diff').html(FER.diff); // Adding new one.
$('#FER-submit').removeClass('oo-ui-widget-disabled').addClass('oo-ui-widget-enabled');
$('#FER-submit').children().removeClass('oo-ui-widget-disabled').addClass('oo-ui-widget-enabled');
$('#FER-submitting').remove();
if (!($('#FER-nochange')[0] || !$('#FER-diff-inner')[0])) $('#FER-copy').fadeIn('fast'); // Show copy button.
// Remove diff markers
$('#FER-diff .diff-marker').remove();
$('td[colspan="2"]').removeAttr('colspan');
});
});
// Wikify and copy to clipboard.
$('#FER-copy').click(function() {
$('#FER-copy').fadeOut('fast');
// No change, no copying.
if ($('#FER-nochange')[0] || !$('#FER-diff-inner')[0]) {
mw.notify('No changes were made, no diff to copy.', {
title: 'No changes made',
type: 'error',
autoHide: true,
autoHideSeconds: 5,
tag: 'FER-notification'
});
return;
}
// Cloning diff.
$('#FER-diff-inner').clone().attr('id', 'FER-clone').appendTo('#FER-diff').hide();
// Replace all td > div s with nowiki s, excluding ins es and del es.
// For attribution: //stackoverflow.com/questions/3665820#3666167
$('#FER-clone').find('td > div:only-child').each(function() {
var re1 = new RegExp('<' + $(this).prop('tagName'), 'i');
var re2 = new RegExp('</' + $(this).prop('tagName'), 'i');
var newhtml = $(this).prop('outerHTML')
.replace(re1, '<' + 'nowiki')
.replace(re2, '</' + 'nowiki');
$(this).replaceWith(newhtml);
});
/* $('#FER-clone').find('ins, del').each(function() {
var re1 = new RegExp('<(' + $(this).prop('tagName') + ')((\s*[^\t\n\f \/>"\'=]+="[^"]+?")*?)>', 'i');
var re2 = new RegExp('</(' + $(this).prop('tagName') + ')>', 'i');
var newhtml = $(this).prop('outerHTML')
.replace(re1, '</nowiki><' + '$1' + '$2><nowiki>')
.replace(re2, '</nowiki></' + '$1' + '><nowiki>');
$(this).replaceWith(newhtml);
});
$('#FER-clone').find('nowiki').each(function() {
var re = new RegExp('<nowiki></nowiki>', 'gi');
var newhtml = $(this).prop('outerHTML')
.replace(re, '');
$(this).replaceWith(newhtml);
}); */
$('#FER-clone').find('colgroup').remove(); // Colgroup doesn't work in wikitext.
// Wikify and advert.
FER.clone = '<!-- Generated using w:en:User:NguoiDungKhongDinhDanh/FormattedEditRequest -->\n';
$('#FER-clone').find('a[name^="movedpara"]').remove();
$('#FER-clone').find('td').each(function() {
if ($(this).html().trim() === '<br>') {
$(this).empty();
}
});
FER.clone += $('#FER-clone').show().removeAttr('id').prop('outerHTML')
// Line break between tbody and first tr.
.replace(/(<tbody(?:(?:\s*[^\t\n\f \/>"\'=]+="[^"]+?")*?)>)(<tr(?:(?:\s*[^\t\n\f \/>"\'=]+="[^"]+?")*?)>)/, '$1\n$2')
// Table tag.
.replace(/<table((\s*[^\t\n\f \/>"\'=]+="[^"]+?")*?)>/, '{|$1')
.replace(/(?<=^\{\|.+)\s*display:\s*none;/m, '')
.replace(/<\/table>/, '|}')
// Tbody tag.
.replace(/<tbody((\s*[^\t\n\f \/>"\'=]+="[^"]+?")*?)>/, '')
.replace(/<\/tbody>/, '')
// Tr tags.
.replace(/<tr((\s*[^\t\n\f \/>"\'=]+="[^"]+?")*?)>/g, '|-$2')
.replace(/<\/tr>/g, '')
// Td tags.
.replace(/<td((\s*[^\t\n\f \/>"\'=]+="[^"]+?")*?)>/g, '|$2 | ')
.replace(/<\/td>/g, '')
// Ins[ert]es and del[et]es. Somehow the functions above doesn't work.
.replace(/<(ins|del)((\s*[^\t\n\f \/>"\'=]+="[^"]+?")*?)>/g, '</nowiki><$1$2><nowiki>')
.replace(/<\/(ins|del)>/g, '</nowiki></$1><nowiki>')
// Blank nowikis.
.replace(/<nowiki><\/nowiki>/g, '')
// Blank lines, leading spaces.
.replace(/\n{2,}/gm, '\n')
.replace(/^\s*/gm, '');
// Copy diff to clipboard.
// navigator.clipboard.writeText(FER.clone);
// For old browsers: [[Special:Diff/1080535780]].
// For attribution: [[User:Qwerfjkl/scripts/copy.js]]
var $ta = $('<textarea>').text(FER.clone).css('position', 'fixed').appendTo(document.body);
$ta[0].select();
// No trying and catching. If this doesn't work, I quit.
document.execCommand('copy');
$ta.remove();
// Cleanup.
$('#FER-diff > table:nth-child(2)').remove();
mw.notify('Diff copied to clipboard.', {
title: 'Copied!',
type: 'success',
autoHide: true,
autoHideSeconds: 5,
tag: 'FER-notification'
});
});
$('#FER-cancel').click(function() {
$('#mw-content-text, #FER-main').toggle();
$('#FER-main').remove();
});
});
}
});
});