MediaWiki:Gadget-MarkupFormatting.js
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: hold down Ctrl and click the Refresh or Reload button. Firefox: hold down ⇧ Shift while clicking Reload (or press Ctrl+⇧ Shift+R). Google Chrome and Safari users can just click the Reload button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/**
* Prettifies template transclusions and gallery tags.
* Original author is Deltaneos.
* Adapted to gadget by Becasita.
* Further improvements by Dinoguy1000.
* @author Deltaneos, Becasita, Dinoguy1000
* @contact [[User:Becasita]] <https://yugipedia.com/wiki/User:Becasita>
* @contact [[User:Dinoguy1000]] <https://yugipedia.com/wiki/User:Dinoguy1000>
*/
( function _gadgetMarkupFormatting( window, $, mw, console ) {
"use strict";
var LAST_LOG = '13:11, 17 February 2024 (UTC)';
/**
* By Deltaneos
*/
function align( text ) {
// Get the selected text or all text
var selected_text = (window.getSelection().toString()) ? window.getSelection().toString() : text;
var cleaned_text, pos, max_pos = -1, j;
// Normalize whitespace and put each line in an array
var lines = selected_text
// paranoia
.replace(/\r\n/g, '\n')
// collapse multiple newlines
// "[^\S\n]" selects all whitespace but newlines <https://stackoverflow.com/a/3469155>
.replace(/(?:\n[^\S\n]*){3,}/g, '\n\n')
// replace all non-newline whitespace characters (except the ideographic space) with U+0020 spaces
.replace(/[^\S\n \u3000]/g, ' ')
// collapse multiple spaces
.replace(/ +/g, ' ')
// remove spaces from the ends of lines
.replace(/ +$/gm, '')
// normalize whitespace within template parameter lines
.replace(/^ ?\| ?([^=\n]+?) ?= ?([^\}])/gm, '| $1 = $2')
// split by line
.split('\n');
// Loop through each line to find the furthest out "=".
for (var i = 0; i < lines.length; i++)
{
pos = lines[i].startsWith('|') ? lines[i].indexOf(' = ') : -1;
if (pos > max_pos) { max_pos = pos; }
}
// Loop through each line again
for (i = 0; i < lines.length; i++)
{
// Only touch lines that start with a pipe and have an equals sign (but not {{=}})
if (lines[i].startsWith('|') && lines[i].indexOf(' = ') > 0)
{
// Get the number of spaces to add
pos = lines[i].indexOf(' = ');
lines[i] = lines[i].substring(0, pos) + ' '.repeat(max_pos - pos) + lines[i].substring(pos);
}
}
cleaned_text = lines.join('\n');
// Check for gallery tags
if (cleaned_text.indexOf('<gallery') > -1)
{
// Get the text inside each set of gallery tags
var galleries = cleaned_text.match(/<gallery[^>]*>(\n[^<][^\n]*)+\n<\/gallery>/g);
var gallery_lines;
for (i = 0; i < galleries.length; i++)
{
// Reset max_pos from previous iterations
max_pos = -1;
// Reduce the spacing around the "|" in each line to a single space.
// Put each line in an array.
gallery_lines = galleries[i].replace(/^([^\|]+?) ?\| ?/gm, '$1 \| ').split('\n');
// Loop through each line to find the furthest out "|"
for (j = 0; j < gallery_lines.length; j++)
{
pos = gallery_lines[j].indexOf('|');
if (pos > max_pos) { max_pos = pos; }
}
// Check if this gallery needs aligned (some galleries may not have anything but filenames)
if (max_pos > -1)
{
// Loop through each line again
for (j = 0; j < gallery_lines.length; j++)
{
if (gallery_lines[j].indexOf('|') > 0) {
// Get the amount of space to add
pos = gallery_lines[j].indexOf('|');
gallery_lines[j] = gallery_lines[j].substring(0, pos) + ' '.repeat(max_pos - pos) + gallery_lines[j].substring(pos);
}
}
}
cleaned_text = cleaned_text.replace(galleries[i], gallery_lines.join('\n'));
}
}
// Final changes
cleaned_text = cleaned_text
// add space between list markup and list item content
.replace(/^ ?([*#:;]+) ?/gm, '$1 ')
// fix [[wikipedia:MOS:LISTGAP]] issues
.replace(/^([*#:;][^\n]+)\n+(?=[*#:;])/gm, '$1\n')
// add space around header content
.replace(/^(=+) ?(.+?) ?\1$/gm, '$1 $2 $1')
// ensure each header is preceded by an empty line
.replace(/\n+((=+) .* \2)/gm, '\n\n$1')
// ensure each header is followed by content on the next line
.replace(/^((=+) .* \2)\n+/gm, '$1\n');
// Replace the old text with the new text
return text.replace(selected_text, cleaned_text);
}
function doAlign( $textBox ) {
$textBox.val( function( index, text ) {
return align( text );
} );
}
function init() {
var $editBox = $( '#wpTextbox1' );
if ( !$editBox.length ) {
window.MARKUP_FORMATTING_ONKEYDOWN_SET = function() {
// Nothing, just to prevent errors.
};
return;
}
var $button = $( '<span>', {
id: 'ca-alignText',
'class': 'tab',
html: $( '<a>', {
href: '#',
title: 'Align text.',
text: 'Align text',
} ),
click: function( e ) {
e.preventDefault();
doAlign( $editBox );
},
} );
if ( mw.user.options.get( 'usebetatoolbar' ) == 1 ) {
// Enhanced edit toolbar:
$( '#wikiEditor-ui-toolbar' )
.find( '.tabs' )
.append( $button )
;
} else {
// Classic toolbar:
$( '#toolbar' ).append(
$( '<div>' )
.addClass( 'mw-toolbar-editbutton' )
.addClass( 'mw-toolbar-editbutton--custom' )
.append( $button )
);
}
/**
* To add a keyboard shortcut, add the following to Special:MyPage/common.js
* ```
* mw.loader.using( 'ext.gadget.MarkupFormatting' ).then( function() {
* window.MARKUP_FORMATTING_ONKEYDOWN_SET( function( e ) {
* return // predicate.
* } );
* } );
* ```
* @param {function} keysPredicate Callback that receives
* an onKeydown event and returns a boolean indicating
* when the keydown listeners should be triggered.
*/
window.MARKUP_FORMATTING_ONKEYDOWN_SET = function( keysPredicate ) {
$editBox.keydown( function( e ) {
if ( keysPredicate( e ) ) {
doAlign( $editBox );
}
} );
};
}
mw.hook( 'wikipage.editform' ).add( function() {
if( mw.config.get('wgNamespaceNumber') !== 10) {
mw.loader.using( 'mediawiki.toolbar' ).then( init );
}
} );
console.log( '[Gadget] MarkupFormatting last updated at', LAST_LOG );
} )( window, window.jQuery, window.mediaWiki, window.console );