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

Jump to navigation Jump to search
No edit summary
No edit summary
Line 20: Line 20:
// ---- API ------------------------------------------------------------
// ---- API ------------------------------------------------------------
function getWikiData( templateName ) {
function getWikiData( templateName ) {
var api = new mw.Api();
var api = new mw.Api();
var text = L + '#invoke:MonsterDomosed/patchformatter|' + templateName + R;
var text = L + '#invoke:MonsterDomosed/patchformatter|' + templateName + R;
Line 43: Line 44:
// ---- PARSING --------------------------------------------------------
// ---- PARSING --------------------------------------------------------
function parseEntries( rawText ) {
function parseEntries( rawText ) {
var entries = [];
var entries = [];
var current = null;
var current = null;


rawText.split( '\n' ).forEach( function ( line ) {
rawText.split( '\n' ).forEach( function ( line ) {
var stripped = line.trim();
var stripped = line.trim();


if ( stripped.indexOf( '-' ) === 0 ) {
if ( stripped.indexOf( '-' ) === 0 ) {
if ( current !== null ) entries.push( current );
 
if ( current !== null ) {
entries.push( current );
}
 
current = stripped.slice( 1 ).trim();
current = stripped.slice( 1 ).trim();
} else if ( current !== null ) {
} else if ( current !== null ) {
current += ' ' + stripped;
current += ' ' + stripped;
}
}
} );
} );


if ( current !== null ) entries.push( current );
if ( current !== null ) {
entries.push( current );
}


return entries.map( function ( e ) {
return entries.map( function ( e ) {
return e.replace( /\s+/g, ' ' ).trim();
return e.replace( /\s+/g, ' ' ).trim();
} ).filter( Boolean );
} ).filter( Boolean );
}
}


// ---- FORMAT ---------------------------------------------------------
// ---- 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 ) {
function escapeRegExp( s ) {
return s.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' );
return s.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' );
Line 80: Line 119:


function wrap( terms, template ) {
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' );
terms.slice()
.sort( function ( a, b ) {
return b.length - a.length;
} )
.forEach( function ( term ) {


text = text.replace( pattern, function () {
var pattern = new RegExp(
return protect(
'(?<!\\w)' + escapeRegExp( term ) + '(?!\\w)',
template.replace( '%s', term )
'g'
);
);
text = text.replace( pattern, function () {
return protect(
template.replace( '%s', term )
);
} );
} );
} );
} );
}
}


Line 112: Line 157:


// ---- OUTPUT ---------------------------------------------------------
// ---- OUTPUT ---------------------------------------------------------
function buildOutput( entries, heroes, abilities, items ) {
function buildOutput( entries, heroes, abilities, items, gameModes ) {
 
console.log('[PatchFormatter] buildOutput');
 
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 = [];
var out = [];


entries.forEach( function ( entry ) {
// General
out.push( '* ' + formatBody( entry, heroes, abilities, items ) );
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 );
} );
} );
} );


return out.join( '\n' ) + '\n';
// 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';
}
}


Line 131: Line 269:


if ( !app ) {
if ( !app ) {
console.error('[PatchFormatter] container missing');
console.error('[PatchFormatter] container not found');
return;
return;
}
}


// --- INPUT (OOUI)
var inputWidget = new OO.ui.MultilineTextInputWidget( {
var inputWidget = new OO.ui.MultilineTextInputWidget( {
rows: 14,
rows: 14,
Line 141: Line 278:
} );
} );


// --- OUTPUT (OOUI)
var outputWidget = new OO.ui.MultilineTextInputWidget( {
var outputWidget = new OO.ui.MultilineTextInputWidget( {
rows: 20,
rows: 20,
Line 147: Line 283:
} );
} );


// --- BUTTONS
var formatButton = new OO.ui.ButtonWidget( {
var formatButton = new OO.ui.ButtonWidget( {
label: 'Format',
label: 'Format',
Line 159: Line 294:
var status = new OO.ui.LabelWidget();
var status = new OO.ui.LabelWidget();


// --- UI CONTAINER (simple safe DOM, no broken layouts)
var container = document.createElement('div');
var container = document.createElement('div');


Line 169: Line 303:


app.appendChild( container );
app.appendChild( container );
// ---- EVENTS -----------------------------------------------------


formatButton.on( 'click', function () {
formatButton.on( 'click', function () {
console.log('[PatchFormatter] click format');


status.setLabel( 'Loading...' );
status.setLabel( 'Loading...' );
Line 188: Line 318:
var abilities = lists[ 2 ];
var abilities = lists[ 2 ];


// IMPORTANT FIX: OOUI INPUT VALUE
var entries = parseEntries( inputWidget.getValue() );
var raw = inputWidget.getValue();
 
console.log('[PatchFormatter] input length:', raw.length);
 
var entries = parseEntries( raw );
 
console.log('[PatchFormatter] entries:', entries.length);


var result = buildOutput( entries, heroes, abilities, items );
var result = buildOutput(
entries,
heroes,
abilities,
items,
GAME_MODE_SECTIONS
);


outputWidget.setValue( result );
outputWidget.setValue( result );
Line 203: Line 332:
status.setLabel( 'Done: ' + entries.length );
status.setLabel( 'Done: ' + entries.length );


} ).catch( function ( err ) {
} ).catch( function ( e ) {


console.error('[PatchFormatter] ERROR', err);
console.error('[PatchFormatter] ERROR', e);
status.setLabel( 'Error' );
status.setLabel( 'Error' );