Difference between revisions of "User:Chocohead/common.js"
Jump to navigation
Jump to search
m (Don't need this personally any more, any edits can be done to User:Chocohead/Lift.js) |
m (Let's see if I can find why the navigation has duplicate arguments) |
||
Line 272: | Line 272: | ||
} ); | } ); | ||
} | } | ||
jQuery(document).ready(function($) { | |||
var myContent = document.getElementsByName('wpTextbox1')[0]; | |||
// -------------------------------------------------------------------------------- // | |||
var mysummary = "Clean up [[:Category:Pages using duplicate arguments in template calls|duplicate template arguments]] using [[:en:User:Frietjes/findargdups|findargdups]]"; | |||
if(typeof findargdupseditsummary == 'string') {mysummary = findargdupseditsummary;} | |||
var morefound = "More duplicates found, fix some and run again!"; | |||
if(typeof findargdupsmorefound == 'string') {morefound = findargdupsmorefound;} | |||
var linktext = "Find dups"; | |||
if(typeof findargdupslinktext == 'string') {linktext = findargdupslinktext;} | |||
var showresultsbox = 0; | |||
if(typeof findargdupsresultsbox == 'string') { showresultsbox = 1;} | |||
// -------------------------------------------------------------------------------- // | |||
if(mw.config.get('wgNamespaceNumber') != -1 && myContent) { | |||
var portletlink = mw.util.addPortletLink('p-tb', '#', linktext, 't-fdup'); | |||
$(portletlink).click(function(e) { | |||
e.preventDefault(); | |||
wpFindDuplicateArgs(0); | |||
}); | |||
} | |||
// -------------------------------------------------------------------------------- // | |||
function wpAddResultsBox(text, num) | |||
{ | |||
var div = document.getElementById('wpSummaryLabel').parentNode; | |||
if( div ) { | |||
if( num < 2 ) { | |||
if( document.getElementById('FindArgDupsResultsBox') ) { | |||
document.getElementById('FindArgDupsResultsBox').innerHTML = ''; | |||
} else { | |||
div.innerHTML = '<div id="FindArgDupsResultsBox"></div>' + div.innerHTML; | |||
} | |||
} | |||
div1 = document.getElementById('FindArgDupsResultsBox'); | |||
if( div1 ) { | |||
text = text.replace(/</g, '<'); | |||
text = text.replace(/>/g, '>'); | |||
div1.innerHTML = div1.innerHTML + '<div class="FindArgDupsResultsBox" ' + | |||
'id="FindArgDupsResultsBox-' + num + '" ' + | |||
'style="max-height:5em; overflow:auto; padding:5px; border:#aaa 1px solid; ' + | |||
'background-color:cornsilk;">' + text + '</div>' + "\n"; | |||
} | |||
} | |||
} | |||
function wpClearResultsBox() | |||
{ | |||
var div = document.getElementById('wpSummaryLabel').parentNode; | |||
if( div ) { | |||
if( document.getElementById('FindArgDupsResultsBox') ) { | |||
document.getElementById('FindArgDupsResultsBox').innerHTML = ''; | |||
} | |||
} | |||
} | |||
// -------------------------------------------------------------------------------- // | |||
function wpFindDuplicateArgs(debugflag) | |||
{ | |||
// Flag used to determine if we have issued an alert popup | |||
var alertissued=0; | |||
// Internal for and while loop variables | |||
var i=0; var j=0; var loopcount=0; | |||
// Array used to hold the list of unnested templates | |||
var tlist = []; | |||
// Regular expression which matchs a template arg | |||
var argexp = new RegExp("\\|[\\s]*([^\\s=\\|\\[\\]\\{\\}][^=\\|\\[\\]\\{\\}]*[^\\s=\\|\\[\\]\\{\\}]|[^\\s=\\|\\[\\]\\{\\}]|)[\\s]*=", "gm"); | |||
// Copy the contents of the text window so we can modify it without problems | |||
var mytxt = myContent.value; | |||
// Remove some includeonly, noinclude, and onlyinclude tags | |||
mytxt = mytxt.replace(/<\/?[ ]*(?:includeonly|noinclude|onlyinclude)[ ]*>/gi, ''); | |||
// Remove PAGENAME, BASEPAGENAME, ... nested inside of triple braces | |||
mytxt = mytxt.replace(/\{\{\{[^\{\}]*\|[ ]*\{\{[A-Z]+\}\}\}\}\}/g, ''); | |||
// Remove some triple braces and parserfunctions inside of triple braces | |||
loopcount = 0; | |||
while((mytxt.search(/\{\{\{[^\{\}]*\}\}\}/g) >= 0) && (loopcount < 5) ) { | |||
mytxt = mytxt.replace(/\{\{\{[^\{\}]*\}\}\}/g, ''); | |||
mytxt = mytxt.replace(/\{\{#[a-z]+:[^{}=]*\}\}/gi, ''); | |||
loopcount++; | |||
} | |||
// Replace some bare braces with HTML equivalent | |||
mytxt = mytxt.replace(/([^\{])\{([^\{])/g, '$1{$2'); | |||
mytxt = mytxt.replace(/([^\}])\}([^\}])/g, '$1}$2'); | |||
// Remove newlines and tabs which confuse the regexp search | |||
mytxt = mytxt.replace(/[\s]/gm, ' '); | |||
// Compress whitespace | |||
mytxt = mytxt.replace(/[\s][\s]+/gm, ' '); | |||
// Remove some nowiki and pre text | |||
mytxt = mytxt.replace(/<nowiki[^<>]*>(?:<[^\/]|[^<])*<\/nowiki[^<>]*>/gi, ''); | |||
mytxt = mytxt.replace(/<pre[^<>]*>(?:<[^\/]|[^<])*<\/pre[^<>]*>/gi, ''); | |||
// Remove some HTML comments | |||
mytxt = mytxt.replace(/<!--(?:[^>]|[^\-]>|[^\-]->)*-->/gm, ''); | |||
// Modify some = inside of file/image/wikilinks which cause false positives | |||
loopcount = 0; | |||
while((mytxt.search(/\[\[[^\[\]\{\}]*=/gi) >= 0) && (loopcount < 5) ) { | |||
mytxt = mytxt.replace(/(\[\[[^\[\]\{\}]*)=/gi, '$1='); | |||
loopcount++; | |||
} | |||
// Now start unnesting the templates | |||
loopcount = 0; | |||
while( (mytxt.search(/(?:\{\{|\}\})/g) >= 0) && (loopcount < 20) ) { | |||
// Split into chunks, isolating the unnested templates | |||
var strlist = mytxt.split(/(\{\{[^\{\}]*\}\})/); | |||
// Loop through the chunks, removing the unnested templates | |||
for (i = 0; i < strlist.length; i++) { | |||
if( strlist[i].search(/^\{\{[^\{\}]*\}\}$/) >= 0 ) { | |||
tlist.push(strlist[i]); | |||
strlist[i] = ''; | |||
} | |||
} | |||
// Join the chunks back together for the next iteration | |||
mytxt = strlist.join(''); | |||
loopcount++; | |||
} | |||
// Preprocess some = signs inside of non-citation-templated citations | |||
for(i=0; i < tlist.length; ++i) { | |||
j=0; | |||
while( (tlist[i].search(/<ref[^<>\/]*>(?:<[^\/]|[^<])*=/gi) >= 0) | |||
&& (j < 50) ) { | |||
tlist[i] = tlist[i].replace(/(<ref[^<>\/]*>(?:<[^\/]|[^<])*)=/gi, '$1='); | |||
} | |||
} | |||
// Now find duplicates in the list of unnested templates | |||
for(i=0; i < tlist.length; ++i) { | |||
// Add numbers for unnamed parameters | |||
var unp=0; | |||
tlist[i] = tlist[i].replace(/(\{\{[\s_]*#invoke[\s ]*:[^{}\|]*)\|([^{}\|=]*\|)/gi, '$1|0=$2'); | |||
while((tlist[i].search(/(\{\{(?:[^{}\[\]]|\[\[[^\[\]]*\]\])*?\|)((?:[^{}\[\]=\|]|\[\[[^\[\]]*\]\])*(?:\||\}\}))/) >= 0) | |||
&& (unp < 25)) { | |||
unp++; | |||
tlist[i] = tlist[i].replace(/(\{\{(?:[^{}\[\]]|\[\[[^\[\]]*\]\])*?\|)((?:[^{}\[\]=\|]|\[\[[^\[\]]*\]\])*(?:\||\}\}))/, '$1' + unp + '=$2'); | |||
} | |||
// Array to hold any found duplicate args (reduce number of alerts) | |||
var f = []; | |||
// Split the template into an array of | arg = ... strings | |||
var p = tlist[i].match(argexp); | |||
if( p ) { | |||
for(j=0; j < p.length; ++j) { | |||
p[j] = p[j].replace(argexp, '$1'); | |||
} | |||
p = p.sort(); | |||
for(j=0; j < p.length - 1; ++j) { | |||
if( p[j] == p[j+1]) { | |||
f.push(p[j]); | |||
} | |||
} | |||
} | |||
if(f.length > 0) { | |||
alertissued = alertissued + 1; | |||
if(alertissued < 5) { | |||
if(showresultsbox > 0) { | |||
wpAddResultsBox('Duplicate \"' + f.join('\", \"') + '\" in\n' + tlist[i], alertissued); | |||
} | |||
alert('\"' + f.join('\", \"') + '\" in\n' + tlist[i]); | |||
} else if(alertissued == 6) { | |||
alert(morefound); | |||
} | |||
} | |||
} | |||
if (alertissued) { | |||
var editsummary = document.getElementsByName('wpSummary')[0]; | |||
if(typeof editsummary == 'object') { | |||
if (editsummary.value.indexOf(mysummary) == -1) { | |||
if (editsummary.value.match(/[^\*\/\s][^\/\s]?\s*$/)) { | |||
editsummary.value += '; ' + mysummary; | |||
} else { | |||
editsummary.value += mysummary; | |||
} | |||
} | |||
} | |||
} else { | |||
if(showresultsbox > 0) { wpClearResultsBox(); } | |||
} | |||
} | |||
// -------------------------------------------------------------------------------- // | |||
}); |
Revision as of 10:12, 5 June 2015
/****************************************** * Page Edit Bar Improver * *****************************************/ var customizeToolbar = function() { // Template subgroup $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { 'sections': { 'templates': { 'type': 'toolbar', // Can also be 'booklet' 'label': 'Templates' // or 'labelMsg': 'section-templates-label' for a localized label } } } ); // Infoboxes header $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { 'section': 'templates', 'groups': { 'infoboxes': { 'label': 'Infoboxes' // or use labelMsg for a localized label, see above } } } ); // [[Template:Block]] for blocks $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { 'section': 'templates', 'group': 'infoboxes', 'tools': { 'block': { label: 'Block Infobox', type: 'button', icon: '/images/a/a6/Grid_Stone.png', filters: [ 'body.ns-0' ], //Namespaceless things only - 100, 102, 104 could also fit in action: { type: 'encapsulate', options: { 'pre': "<onlyinclude>{{\ {{{1|Block}}}\n\ |title=\n\ |image=\n\ |image2=\n\ |image3=\n\ |invimage=\n\ |invimage2=\n\ |invimage3=\n\ |invimage4=\n\ |type=\n\ |dirt=\n\ |maxeu=\n\ |storage=\n\ |eu_use=\n\ |eu_use2=\n\ |tool=\n\ |stackable=\n\ |data=\n\ |fluidspeed=\n\ |movespeed=", 'post': "\n}}</onlyinclude>" } } } } } ); //[[Template:Userinfo]] $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { 'section': 'templates', 'group': 'infoboxes', 'tools': { 'user': { label: 'User Infobox', type: 'button', icon: '/images/a/a6/Grid_Stone.png', filters: [ 'body.ns-2' ], //User namespaces only action: { type: 'encapsulate', options: { 'pre': "{{\ UserInfo\n\ |width=\n\ |user-avatar=\n\ |user-ig=\n\ |section1=\n\ |stat1=|value1=\n\ |section2=\n\ |stat2=|value2=\n\ |section3=\n\ |stat3=|value3=\n\ |section4=\n\ |stat4=|value4=\n\ |section5=\n\ |stat5=|value5=\n\ |section6=\n\ |stat6=|value6=\n\ |section7=\n\ |stat7=|value7=\n\ |section8=\n\ |stat8=|value8=\n\ |section9=\n\ |stat9=|value9=", 'post': "\n}}" } } } } } ); // Solution for items $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { 'section': 'templates', 'group': 'infoboxes', 'tools': { 'item': { label: 'Item Infobox', type: 'button', icon: '/images/e/e9/Grid_Stick.png', filters: [ 'body.ns-0' ], //Namespaceless things only - 100, 102, 104 could also fit in action: { type: 'encapsulate', options: { 'peri': "<!-- We don't have one ;) -->" } } } } } ); $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { 'section': 'templates', 'groups': { 'craftingtemplates': { 'label': 'Crafting Grids' // or use labelMsg for a localized label, see above } } } ); // [[Template:Grid/Crafting Table]] for simple crafting recipes $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { 'section': 'templates', 'group': 'craftingtemplates', 'tools': { 'block': { label: 'Simple Crafting Table', type: 'button', icon: '/images/7/79/Grid_Crafting_Table.png', filters: [ 'body.ns-0' ], //Namespaceless things only - 100, 102, 104 could also fit in action: { type: 'encapsulate', options: { 'pre': "{{\ Grid/Crafting Table\n\ |A1=\n\ |B1=\n\ |C1=\n\ |A2=\n\ |B2=\n\ |C2=\n\ |A3=\n\ |B3=\n\ |C3=\n\ |Output= |OA=", 'post': "\n}}" } } } } } ); // [[Template:Grid/Crafting Table]] for complicated crafting recipes $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { 'section': 'templates', 'group': 'craftingtemplates', 'tools': { 'block': { label: 'Full Crafting Table', type: 'button', icon: '/images/7/79/Grid_Crafting_Table.png', filters: [ 'body.ns-0' ], //Namespaceless things only - 100, 102, 104 could also fit in action: { type: 'encapsulate', options: { 'pre': "{{\ Grid/Crafting Table\n\ |A1= |A1-link= |A1-image=\n\ |B1= |B1-link= |B1-image=\n\ |C1= |C1-link= |C1-image=\n\ |A2= |A2-link= |A2-image=\n\ |B2= |B2-link= |B2-image=\n\ |C2= |C2-link= |C2-image=\n\ |A3= |A3-link= |A3-image=\n\ |B3= |B3-link= |B3-image=\n\ |C3= |C3-link= |C3-image=\n\ |Output= |OA=", 'post': "\n}}" } } } } } ); // [[Template:Grid/Furnace]] for simple furnace recipes $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { 'section': 'templates', 'group': 'craftingtemplates', 'tools': { 'block': { label: 'Furnace', //Ex "Simple Furnace" type: 'button', icon: '/images/2/2e/Grid_Furnace.png', filters: [ 'body.ns-0' ], //Namespaceless things only - 100, 102, 104 could also fit in action: { type: 'encapsulate', options: { 'pre': "{{\ Grid/Furnace\n\ |Input=\n\ |Output=\n\ |Fuel=\n\ |Break=\n\ }}", 'post': "\n}}" } } } } } ); // [[Template:Grid/Furnace]] for complicated furnace recipes /* $( '#wpTextbox1' ).wikiEditor( 'addToToolbar', { 'section': 'templates', 'group': 'craftingtemplates', 'tools': { 'block': { label: 'Full Furnace', type: 'button', icon: '/images/2/2e/Grid_Furnace.png', filters: [ 'body.ns-0' ], //Namespaceless things only - 100, 102, 104 could also fit in action: { type: 'encapsulate', options: { 'pre': "{{\ Grid/Furnace\n\ |Input= |IA= \n\ |Output= |OA= \n\ |Fuel= |FA= \n\ }}", 'post': "\n}}" } } } } } );*/ }; /* Check if view is in edit mode and that the required modules are available. Then, customize the toolbar . . . */ if ( $.inArray( mw.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) !== -1 ) { mw.loader.using( 'user.options', function () { if ( mw.user.options.get('usebetatoolbar') && mw.user.options.get( 'showtoolbar' ) ) { mw.loader.using( 'ext.wikiEditor.toolbar', function () { $( customizeToolbar ); } ); } } ); } jQuery(document).ready(function($) { var myContent = document.getElementsByName('wpTextbox1')[0]; // -------------------------------------------------------------------------------- // var mysummary = "Clean up [[:Category:Pages using duplicate arguments in template calls|duplicate template arguments]] using [[:en:User:Frietjes/findargdups|findargdups]]"; if(typeof findargdupseditsummary == 'string') {mysummary = findargdupseditsummary;} var morefound = "More duplicates found, fix some and run again!"; if(typeof findargdupsmorefound == 'string') {morefound = findargdupsmorefound;} var linktext = "Find dups"; if(typeof findargdupslinktext == 'string') {linktext = findargdupslinktext;} var showresultsbox = 0; if(typeof findargdupsresultsbox == 'string') { showresultsbox = 1;} // -------------------------------------------------------------------------------- // if(mw.config.get('wgNamespaceNumber') != -1 && myContent) { var portletlink = mw.util.addPortletLink('p-tb', '#', linktext, 't-fdup'); $(portletlink).click(function(e) { e.preventDefault(); wpFindDuplicateArgs(0); }); } // -------------------------------------------------------------------------------- // function wpAddResultsBox(text, num) { var div = document.getElementById('wpSummaryLabel').parentNode; if( div ) { if( num < 2 ) { if( document.getElementById('FindArgDupsResultsBox') ) { document.getElementById('FindArgDupsResultsBox').innerHTML = ''; } else { div.innerHTML = '<div id="FindArgDupsResultsBox"></div>' + div.innerHTML; } } div1 = document.getElementById('FindArgDupsResultsBox'); if( div1 ) { text = text.replace(/</g, '<'); text = text.replace(/>/g, '>'); div1.innerHTML = div1.innerHTML + '<div class="FindArgDupsResultsBox" ' + 'id="FindArgDupsResultsBox-' + num + '" ' + 'style="max-height:5em; overflow:auto; padding:5px; border:#aaa 1px solid; ' + 'background-color:cornsilk;">' + text + '</div>' + "\n"; } } } function wpClearResultsBox() { var div = document.getElementById('wpSummaryLabel').parentNode; if( div ) { if( document.getElementById('FindArgDupsResultsBox') ) { document.getElementById('FindArgDupsResultsBox').innerHTML = ''; } } } // -------------------------------------------------------------------------------- // function wpFindDuplicateArgs(debugflag) { // Flag used to determine if we have issued an alert popup var alertissued=0; // Internal for and while loop variables var i=0; var j=0; var loopcount=0; // Array used to hold the list of unnested templates var tlist = []; // Regular expression which matchs a template arg var argexp = new RegExp("\\|[\\s]*([^\\s=\\|\\[\\]\\{\\}][^=\\|\\[\\]\\{\\}]*[^\\s=\\|\\[\\]\\{\\}]|[^\\s=\\|\\[\\]\\{\\}]|)[\\s]*=", "gm"); // Copy the contents of the text window so we can modify it without problems var mytxt = myContent.value; // Remove some includeonly, noinclude, and onlyinclude tags mytxt = mytxt.replace(/<\/?[ ]*(?:includeonly|noinclude|onlyinclude)[ ]*>/gi, ''); // Remove PAGENAME, BASEPAGENAME, ... nested inside of triple braces mytxt = mytxt.replace(/\{\{\{[^\{\}]*\|[ ]*\{\{[A-Z]+\}\}\}\}\}/g, ''); // Remove some triple braces and parserfunctions inside of triple braces loopcount = 0; while((mytxt.search(/\{\{\{[^\{\}]*\}\}\}/g) >= 0) && (loopcount < 5) ) { mytxt = mytxt.replace(/\{\{\{[^\{\}]*\}\}\}/g, ''); mytxt = mytxt.replace(/\{\{#[a-z]+:[^{}=]*\}\}/gi, ''); loopcount++; } // Replace some bare braces with HTML equivalent mytxt = mytxt.replace(/([^\{])\{([^\{])/g, '$1{$2'); mytxt = mytxt.replace(/([^\}])\}([^\}])/g, '$1}$2'); // Remove newlines and tabs which confuse the regexp search mytxt = mytxt.replace(/[\s]/gm, ' '); // Compress whitespace mytxt = mytxt.replace(/[\s][\s]+/gm, ' '); // Remove some nowiki and pre text mytxt = mytxt.replace(/<nowiki[^<>]*>(?:<[^\/]|[^<])*<\/nowiki[^<>]*>/gi, ''); mytxt = mytxt.replace(/<pre[^<>]*>(?:<[^\/]|[^<])*<\/pre[^<>]*>/gi, ''); // Remove some HTML comments mytxt = mytxt.replace(/<!--(?:[^>]|[^\-]>|[^\-]->)*-->/gm, ''); // Modify some = inside of file/image/wikilinks which cause false positives loopcount = 0; while((mytxt.search(/\[\[[^\[\]\{\}]*=/gi) >= 0) && (loopcount < 5) ) { mytxt = mytxt.replace(/(\[\[[^\[\]\{\}]*)=/gi, '$1='); loopcount++; } // Now start unnesting the templates loopcount = 0; while( (mytxt.search(/(?:\{\{|\}\})/g) >= 0) && (loopcount < 20) ) { // Split into chunks, isolating the unnested templates var strlist = mytxt.split(/(\{\{[^\{\}]*\}\})/); // Loop through the chunks, removing the unnested templates for (i = 0; i < strlist.length; i++) { if( strlist[i].search(/^\{\{[^\{\}]*\}\}$/) >= 0 ) { tlist.push(strlist[i]); strlist[i] = ''; } } // Join the chunks back together for the next iteration mytxt = strlist.join(''); loopcount++; } // Preprocess some = signs inside of non-citation-templated citations for(i=0; i < tlist.length; ++i) { j=0; while( (tlist[i].search(/<ref[^<>\/]*>(?:<[^\/]|[^<])*=/gi) >= 0) && (j < 50) ) { tlist[i] = tlist[i].replace(/(<ref[^<>\/]*>(?:<[^\/]|[^<])*)=/gi, '$1='); } } // Now find duplicates in the list of unnested templates for(i=0; i < tlist.length; ++i) { // Add numbers for unnamed parameters var unp=0; tlist[i] = tlist[i].replace(/(\{\{[\s_]*#invoke[\s ]*:[^{}\|]*)\|([^{}\|=]*\|)/gi, '$1|0=$2'); while((tlist[i].search(/(\{\{(?:[^{}\[\]]|\[\[[^\[\]]*\]\])*?\|)((?:[^{}\[\]=\|]|\[\[[^\[\]]*\]\])*(?:\||\}\}))/) >= 0) && (unp < 25)) { unp++; tlist[i] = tlist[i].replace(/(\{\{(?:[^{}\[\]]|\[\[[^\[\]]*\]\])*?\|)((?:[^{}\[\]=\|]|\[\[[^\[\]]*\]\])*(?:\||\}\}))/, '$1' + unp + '=$2'); } // Array to hold any found duplicate args (reduce number of alerts) var f = []; // Split the template into an array of | arg = ... strings var p = tlist[i].match(argexp); if( p ) { for(j=0; j < p.length; ++j) { p[j] = p[j].replace(argexp, '$1'); } p = p.sort(); for(j=0; j < p.length - 1; ++j) { if( p[j] == p[j+1]) { f.push(p[j]); } } } if(f.length > 0) { alertissued = alertissued + 1; if(alertissued < 5) { if(showresultsbox > 0) { wpAddResultsBox('Duplicate \"' + f.join('\", \"') + '\" in\n' + tlist[i], alertissued); } alert('\"' + f.join('\", \"') + '\" in\n' + tlist[i]); } else if(alertissued == 6) { alert(morefound); } } } if (alertissued) { var editsummary = document.getElementsByName('wpSummary')[0]; if(typeof editsummary == 'object') { if (editsummary.value.indexOf(mysummary) == -1) { if (editsummary.value.match(/[^\*\/\s][^\/\s]?\s*$/)) { editsummary.value += '; ' + mysummary; } else { editsummary.value += mysummary; } } } } else { if(showresultsbox > 0) { wpClearResultsBox(); } } } // -------------------------------------------------------------------------------- // });