User:Monster Domosed/common.js: Difference between revisions

Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
/* Patch Formatter */
( function () {
'use strict';


var L = '{' + '{';
var R = '}' + '}';
// ---- CONFIG ---------------------------------------------------------
var GAME_MODE_SECTIONS = [ 'Street Brawl' ];
var WIKI_LINKS = [
[ /(?<!\w)Urn(?!\w)/g, '[[Urn]]' ],
[ /(?<!\w)parry(?!\w)/g, '[[Parry|parry]]' ]
];
var CHANGE_PREFIX = '';
// ---- API ------------------------------------------------------------
function getWikiData( templateName ) {
var api = new mw.Api();
var text = L + '#invoke:MonsterDomosed/patchformatter|' + templateName + R;
return api.get( {
action: 'expandtemplates',
text: text,
prop: 'wikitext',
format: 'json',
formatversion: 2
} ).then( function ( data ) {
var wikitext = ( data.expandtemplates && data.expandtemplates.wikitext ) || '';
return wikitext.split( ',' )
.map( function ( item ) {
return item.trim().replace( /^'+|'+$/g, '' );
} )
.filter( Boolean );
} );
}
// ---- PARSING --------------------------------------------------------
function parseEntries( rawText ) {
var entries = [];
var current = null;
rawText.split( '\n' ).forEach( function ( line ) {
var stripped = line.trim();
if ( stripped.indexOf( '-' ) === 0 ) {
if ( current !== null ) {
entries.push( current );
}
current = stripped.slice( 1 ).trim();
} else if ( current !== null ) {
current += ' ' + stripped;
}
} );
if ( current !== null ) {
entries.push( current );
}
return entries.map( function ( e ) {
return e.replace( /\s+/g, ' ' ).trim();
} ).filter( Boolean );
}
// ---- CLASSIFY -------------------------------------------------------
function classify( entry, heroes, items, gameModes ) {
var idx = entry.indexOf( ':' );
if ( idx !== -1 ) {
var prefix = entry.slice( 0, idx ).trim();
var rest = entry.slice( idx + 1 ).trim();
if ( gameModes.indexOf( prefix ) !== -1 ) {
return [ 'mode', prefix, rest ];
}
if ( heroes.indexOf( prefix ) !== -1 ) {
return [ 'hero', prefix, rest ];
}
if ( items.indexOf( prefix ) !== -1 ) {
return [ 'item', prefix, rest ];
}
}
return [ 'general', null, entry ];
}
// ---- FORMAT BODY ----------------------------------------------------
function escapeRegExp( s ) {
return s.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' );
}
function formatBody( text, heroes, abilities, items ) {
var protectedTokens = [];
function protect( value ) {
var token = '\u0000' + protectedTokens.length + '\u0000';
protectedTokens.push( value );
return token;
}
function wrap( terms, template ) {
terms.slice()
.sort( function ( a, b ) {
return b.length - a.length;
} )
.forEach( function ( term ) {
var pattern = new RegExp(
'(?<!\\w)' + escapeRegExp( term ) + '(?!\\w)',
'g'
);
text = text.replace( pattern, function () {
return protect(
template.replace( '%s', term )
);
} );
} );
}
wrap( abilities, L + 'AbilityIcon|%s' + R );
wrap( items, L + 'ItemIcon|%s' + R );
wrap( heroes, L + 'HeroIcon|%s' + R );
WIKI_LINKS.forEach( function ( pair ) {
text = text.replace( pair[ 0 ], function () {
return protect( pair[ 1 ] );
} );
} );
for ( var i = 0; i < protectedTokens.length; i++ ) {
text = text.split( '\u0000' + i + '\u0000' ).join( protectedTokens[ i ] );
}
return text;
}
// ---- OUTPUT ---------------------------------------------------------
function buildOutput( entries, heroes, abilities, items, gameModes ) {
var general = [];
var modes = {}, modeOrder = [];
var itemSections = {}, itemOrder = [];
var heroSections = {}, heroOrder = [];
entries.forEach( function ( entry ) {
var c = classify( entry, heroes, items, gameModes );
var kind = c[ 0 ];
var name = c[ 1 ];
var body = formatBody( c[ 2 ], heroes, abilities, items );
if ( kind === 'general' ) {
general.push( body );
} else if ( kind === 'mode' ) {
if ( !modes[ name ] ) {
modes[ name ] = [];
modeOrder.push( name );
}
modes[ name ].push( body );
} else if ( kind === 'item' ) {
if ( !itemSections[ name ] ) {
itemSections[ name ] = [];
itemOrder.push( name );
}
itemSections[ name ].push( body );
} else if ( kind === 'hero' ) {
if ( !heroSections[ name ] ) {
heroSections[ name ] = [];
heroOrder.push( name );
}
heroSections[ name ].push( body );
}
} );
var out = [];
// General
general.forEach( function ( entry ) {
out.push( '* ' + entry );
} );
// Modes
modeOrder.forEach( function ( mode ) {
out.push( '' );
out.push( '== [[' + mode + ']] ==' );
modes[ mode ].forEach( function ( body ) {
out.push( '* ' + body );
} );
} );
// Items
if ( itemOrder.length ) {
out.push( '' );
out.push( '== Items ==' );
itemOrder.forEach( function ( item ) {
out.push( '=== ' + L + 'ItemIcon|' + item + R + ' ===' );
itemSections[ item ].forEach( function ( body ) {
out.push( '* ' + body );
out.push( '' );
} );
} );
}
// Heroes
if ( heroOrder.length ) {
out.push( '' );
out.push( '== Heroes ==' );
heroOrder.forEach( function ( hero ) {
out.push( '=== ' + L + 'HeroIcon|' + hero + R + ' ===' );
heroSections[ hero ].forEach( function ( body ) {
out.push( '* ' + body );
out.push( '' );
} );
} );
}
return out.join( '\n' ).trim() + '\n';
}
// ---- INIT -----------------------------------------------------------
function init() {
var app = document.getElementById( 'patchformatter' );
if ( !app ) {
return;
}
var inputWidget = new OO.ui.MultilineTextInputWidget( {
rows: 14,
placeholder: 'Raw patch notes'
} );
var outputWidget = new OO.ui.MultilineTextInputWidget( {
rows: 20,
readOnly: true
} );
var formatButton = new OO.ui.ButtonWidget( {
label: 'Format',
flags: [ 'primary', 'progressive' ]
} );
var copyButton = new OO.ui.ButtonWidget( {
label: 'Copy output'
} );
var status = new OO.ui.LabelWidget();
var container = document.createElement( 'div' );
container.appendChild( inputWidget.$element[ 0 ] );
container.appendChild( formatButton.$element[ 0 ] );
container.appendChild( copyButton.$element[ 0 ] );
container.appendChild( status.$element[ 0 ] );
container.appendChild( outputWidget.$element[ 0 ] );
app.appendChild( container );
formatButton.on( 'click', function () {
status.setLabel( 'Loading...' );
Promise.all( [
getWikiData( 'get_released_heroes_list' ),
getWikiData( 'get_all_released_item_names' ),
getWikiData( 'get_all_released_abilities_list' )
] ).then( function ( lists ) {
var heroes = lists[ 0 ];
var items = lists[ 1 ];
var abilities = lists[ 2 ];
var entries = parseEntries( inputWidget.getValue() );
var result = buildOutput(
entries,
heroes,
abilities,
items,
GAME_MODE_SECTIONS
);
outputWidget.setValue( result );
status.setLabel('Done');
} ).catch( function ( e ) {
status.setLabel( 'Error' );
} );
} );
copyButton.on( 'click', function () {
navigator.clipboard.writeText(
outputWidget.getValue()
);
status.setLabel( 'Copied' );
} );
}
mw.loader.using( [
'oojs-ui-core',
'oojs-ui-widgets',
'mediawiki.api',
'mediawiki.util'
] ).then( function () {
init();
} );
}() );