MediaWiki:Gadget-NewVillagePump.js/Core.js

Nota: Depois de publicar, poderá ter de contornar a cache do seu navegador para ver as alterações.

  • Firefox / Safari: Pressione Shift enquanto clica Recarregar, ou pressione Ctrl-F5 ou Ctrl-R (⌘-R no Mac)
  • Google Chrome: Pressione Ctrl-Shift-R (⌘-Shift-R no Mac)
  • Edge: Pressione Ctrl enquanto clica Recarregar, ou pressione Ctrl-F5.
// [[File:User:He7d3r/Tools/NewVillagePump.js]] (workaround for [[phab:T35355]])
/**
 * Script que aprimora a criação de tópicos
 * (na [[WP:Esplanada/propostas]] e na [[WP:Esplanada/geral]])
 * @dependencies mediawiki.util
 * @author: Helder (https://github.com/he7d3r)
 * @license: CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0/>
 */
/*global mediaWiki, jQuery */

( function ( mw, $ ) {
'use strict';

mw.messages.set( {
	// Error
	'nvp-error-errorEdit': 'Houve um erro ao tentar editar a página',
	'nvp-error-ajaxFail': 'Não foi possível usar AJAX para editar a página',
	'nvp-error-editFail': 'Houve um erro durante as edições.',
	'nvp-error-tryAgain': 'Por favor, tente novamente. Se o problema persistir, informe-o no ' +
		'<a href="' + mw.util.getUrl( 'WP:CP' ) + '">café dos programadores</a>, com uma cópia dessa mensagem.',

	// Edit
	'nvp-edit-captcha': 'Por favor, introduza na caixa abaixo as palavras apresentadas',
	'nvp-edit-sucess': 'A página $1 foi editada.',
	'nvp-edit-subject': 'É preciso informar o assunto deste tópico antes de criá-lo.',
	'nvp-edit-needContent': 'É preciso inserir algum conteúdo para poder criar um tópico novo.',
	'nvp-edit-waitCreation': 'Por favor, aguarde a criação do tópico e sua inclusão na esplanada e no arquivo desde mês.' +
		' O script se encarregará de atualizar a página quando terminar as edições.',
	'nvp-edit-topicDescription': 'Descreva brevemente o tópico (não coloque \'\'\'formatação\'\'\',' +
		' [[links]] nem {{predefinições}} aqui).',
	'nvp-edit-content': 'Coloque aqui o conteúdo do tópico que pretende criar e assine com ~~' + '~~. Depois, clique em $1 e aguarde.'
} );

var nvp = {
		$saveButton: $( '#wpSave' ),
		$textBox: $( '#wpTextbox1' ),
		$heading: $( '#firstHeading' ),
		pagesUsingNewFormat: [
			'Wikipédia:Esplanada/geral',
			'Wikipédia:Esplanada/propostas'
		]
	},
	api = new mw.Api();

nvp.addTextToEndOfSection = function ( newText, section, existingText, sections ) {
	var i, reSec, match, separator, id, next, updatedText,
		pos = {};
	existingText = existingText.trim();

	// Fill in pos with the position of each existing section
	for ( i = 0; i < sections.length; i++ ) {
		reSec = new RegExp( '^=\\s*' + sections[ i ] + '\\s*=', 'gmi' );
		match = existingText.match( reSec );
		match = match && match[ 0 ];

		if ( match ) {
			pos[ sections[ i ] ] = existingText.indexOf( match );
		}
	}

	sections.sort( function ( a, b ) {
		return pos[ a ] - pos[ b ];
	} );

	if ( typeof pos[ section ] === 'number' ) {
		// The text will be appended to an existing section. Just add some line breaks
		separator = '\n\n';
	} else {
		if ( existingText === '' ) {
			existingText = '{{esplanada}}\n[[Categoria:!Arquivo da Esplanada]]\n<!-- ARQUIVO -->';
		}

		// Build the header for a new section
		separator = '\n\n= ' + section.substr( 0, 1 ).toUpperCase() + section.substr( 1 ) + ' =\n';
	}

	id = $.inArray( section, sections );

	for ( next = id + 1; next < sections.length; next++ ) {
		if ( typeof pos[ sections[ next ] ] === 'number' ) {
			break;
		}
	}

	if ( id < sections.length - 1 && next < sections.length ) {
		// The new text needs to be inserted before an existing section
		updatedText = existingText.substr( 0, pos[ sections[ next ] ] ) +
			separator + newText + '\n\n' +
			existingText.substr( pos[ sections[ next ] ] );
	} else {
		// The new text can be inserted at the end of the page
		updatedText = existingText + separator + newText.trim();
	}

	return updatedText;
};

nvp.editPage = function ( info ) {
	var apiDeferred = $.Deferred(),
		callData = $.extend( {}, {
			format: 'json',
			action: 'edit',
			token: mw.user.tokens.get( 'csrfToken' )
		}, info ),
		getText = function () {
			if ( typeof callData.text === 'function' ) {
				return api.getCurrentPageText( callData.title ).done( function ( text ) {
					callData.text = callData.text( text || '' );
				} );
			}

			return true;
		},
		getCaptcha = function ( url, id ) {
			var $captchaForm,
				$captchaImg = $( '<img>', {
					src: url,
					width: 255,
					height: 76
				} ),
				captchaDfd = $.Deferred(),
				processCaptchas = function () {
					$( '.captcha-word' ).filter( function () {
						return $( this ).val();
					} ).each( function () {
						var $word = $( this ),
							$form = $word.closest( '.captcha-ne' );

						$form.data( 'captcha-dfd' ).resolve(
							// Captcha id
							$form.data( 'captcha-id' ),
							// Captcha word
							$word.val()
						);

						$form.remove();
					} );

					nvp.$saveButton.attr(
						'disabled',
						$( '.captcha-ne' ).length === 0
					);

					$( '.captcha-word' ).first().focus();
				};

			nvp.$saveButton.attr( 'disabled', false );

			if ( !getCaptcha.bound ) {
				nvp.$saveButton.click( function ( e ) {
					e.preventDefault();
					processCaptchas();
				} );

				getCaptcha.bound = true;
			}

			$captchaForm = $( '<div class="captcha-ne"></div>' )
				.text( mw.message( 'nvp-edit-captcha' ) + ':' )
				.append( '<br />' )
				.append( $captchaImg )
				.append( '<input class="captcha-word" autocorrect="off" autocapitalize="off" tabindex="1">' )
				.submit( function () {
					return false;
				} )
				.data( 'captcha-id', id )
				.data( 'captcha-dfd', captchaDfd )
				.keyup( function ( e ) {
					if ( e.which === /* ENTER */ 13 ) {
						processCaptchas();
					}
				} );

			$( '#mw-content-text' ).prepend( $captchaForm );

			// Return the promise
			return captchaDfd.promise();
		};

	$.when( getText() ).done( function () {
		$.ajax( {
			url: mw.util.wikiScript( 'api' ),
			type: 'POST',
			dataType: 'json',
			data: callData
		} ).done( function ( data ) {
			var result = data && data.edit && data.edit.result;

			if ( result === 'Success' ) {
				mw.notify(
					$.parseHTML(
						'<div>' +
							mw.message( 'nvp-edit-sucess', '<a href="' + mw.util.getUrl( callData.title ) + '">' + callData.title + '</a>' ) +
						'</div>'
					), {
						autoHide: false
				} );

				apiDeferred.resolve();
			} else if ( result === 'Failure' && data.edit.captcha !== undefined ) {
				$.when(
					getCaptcha( data.edit.captcha.url, data.edit.captcha.id )
				).done( function ( id, word ) {
					callData.captchaid = id;
					callData.captchaword = word;

					nvp.editPage( callData ).done( function () {
						apiDeferred.resolve();
					} );
				} );
			} else {
				alert(
					mw.message( 'nvp-error-errorEdit' ) + ' "' + callData.title + '"' + '.\n' +
					data.error.code + '. ' + data.error.callData + '. ' + mw.message( 'nvp-error-tryAgain' )
				);
				apiDeferred.reject();
			}
		} ).fail( function () {
			// FIXME: Remove spinner? Cancel other requests?
			alert( mw.message( 'nvp-error-ajaxFail' ) + ' "' + callData.title + '"' + '. ' + mw.message( 'nvp-error-tryAgain' ) );
			apiDeferred.reject();
		} );
	} );

	// Return the promise
	return apiDeferred.promise();
};

nvp.validateAndCreateTopic = function ( e ) {
	e.preventDefault();

	var categoryName, sumForMainPage, templates, archiveTitle, archiveSection, archiveSections, fullTopicText, sumForSubPage,
		// See [[phab:T6715]] and [[gerrit:15622]]
		byteLimit = 255,
		watchlist = $( '#wpWatchthis' ).is( ':checked' ) ? 'watch' : 'unwatch',
		content = nvp.$textBox.val(),
		$sum = $( '#wpSummary' ),
		sum = $sum.val(),
		today = new Date(),
		d = today.getDate(),
		m = mw.config.get( 'wgMonthNames' )[ today.getMonth() + 1 ],
		y = today.getFullYear(),
		shortDate = d + m.substr( 0, 3 ) + y,
		topic = sum.replace( /\[\[.+?\|(.+?)\]\]/g, '$1' )
			.replace( /\[\[(.+?)\]\]/g, '$1' )
			.replace( /\{\{(.+?)(?:\|.*?)?\}\}/g, '$1' )
			.replace( /[\{\}\[\]\|]/g, ' ' )
			.replace( /\s+/g, ' ' )
			.replace( /=/g, ' ' )
			.trim(),
		topicAndDate, fullTopicTitle;

	$sum.val( topic );

	if ( topic === '' ) {
		alert( mw.message( 'nvp-edit-subject' ) );
		$sum.focus();

		return false;
	}

	if ( content.trim() === '' ) {
		alert( mw.message( 'nvp-edit-needContent' ) );
		nvp.$textBox.focus();

		return false;
	}

	topicAndDate = topic + ' (' + shortDate + ')';
	fullTopicTitle = mw.config.get( 'wgPageName' ).replace( /^Wikipédia/, 'WP' ) +
		'/' + topicAndDate;
	archiveTitle = 'WP:Esplanada/Arquivo/' + y + '/' +
		m.substr( 0, 1 ).toUpperCase() + m.substr( 1 );
	archiveSection = mw.config.get( 'wgPageName' ).replace( /^.+?\//g, '' );
	archiveSections = [ 'anúncios', 'geral', 'propostas' ];
	fullTopicText = '<noinclude>{{Voltar}}[[Categoria:!Esplanada/' +
		mw.config.get( 'wgPageName' ).replace( /^.+\//g, '' ) +
		'/' + m + ' de ' + y + '|' + topicAndDate + ']]</noinclude>\n' +
		content;
	// 18 === 'novo tópico: [[|]]'.length
	sumForMainPage = 18 + fullTopicTitle.length + topic.length < byteLimit ?
		'novo tópico ([' + '[' + fullTopicTitle + '|' + topic + ']]): ' + content
		: 'novo tópico ([' + '[' + fullTopicTitle + ']]): ' + content;
	sumForSubPage = 'novo tópico: ' + content;
	templates = '{{discussão2|' + topic + '|' + shortDate + '|' +
		mw.config.get( 'wgPageName' ) + '}}\n{' + '{:' + fullTopicTitle + '}}';

	// Disable the save button to avoid duplicated topics
	nvp.$saveButton.attr( 'disabled', true );
	nvp.$heading.injectSpinner( 'editing-pages' );

	$( 'html, body' ).animate( {
		scrollTop: nvp.$heading.offset().top
	}, 'fast' );

	mw.notify( mw.message( 'nvp-edit-waitCreation' ), {
		autoHide: false
	} );

	$.when(
		nvp.editPage( {
			title: fullTopicTitle,
			summary: sumForSubPage,
			text: fullTopicText,
			watchlist: watchlist
		} ),
		nvp.editPage( {
			title: mw.config.get( 'wgPageName' ),
			summary: sumForMainPage,
			text: function ( currentText ) {
				return currentText + '\n\n' + templates;
			},
			watchlist: watchlist
		} ),
		nvp.editPage( {
			title: archiveTitle,
			summary: sumForMainPage,
			minor: true,
			text: function ( currentText ) {
				return nvp.addTextToEndOfSection(
					templates,
					archiveSection,
					currentText,
					archiveSections
				);
			},
			watchlist: 'nochange'
		} )
	).then( function () {
		categoryName = 'Categoria:!Esplanada/' + mw.config.get( 'wgPageName' ).replace( /^.+\//g, '' ) + '/' + m + ' de ' + y;

		api.getCurrentPageText( categoryName ).done( function ( text ) {
			if ( text === '' ) {
				nvp.editPage( {
					title: categoryName,
					summary: 'Criando categoria',
					minor: true,
					watchlist: watchlist,
					text: ':Essa categoria contém todos os tópicos da [[:Wikipedia:Esplanada/geral|página geral da Esplanada]] do mês de outubro de 2013.\n\n' +
						'{{mudanças}}\n\n[[Categoria:!Arquivo da Esplanada - 2013|g1013]]'
				} ).done( function () {
					mw.confirmCloseWindow().release();
					location.href = mw.util.getUrl( fullTopicTitle );
				} );
			} else {
				window.onbeforeunload = null;
				location.href = mw.util.getUrl( fullTopicTitle );
			}
		} );
	}, function () {
		alert( mw.message( 'nvp-error-editFail' ) );
	} );
};

nvp.improveTopicCreation = function () {
	$( '#wpSummary' ).attr(
		'placeholder',
		mw.message( 'nvp-edit-topicDescription' ).plain()
	);

	if ( $.inArray( mw.config.get( 'wgAction' ), ['edit', 'submit']) > -1 && mw.util.getParamValue( 'preload' ) ) {
		// Remover o texto pré-carregado
		nvp.$textBox.attr(
			'placeholder',
			mw.message( 'nvp-edit-content', '"' + nvp.$saveButton.val() + '"' )
		).val( '' );
	}

	nvp.$saveButton.click( nvp.validateAndCreateTopic );
	$( '#editform' ).show();
};

nvp.run = function () {
	if ( $.inArray( mw.config.get( 'wgPageName' ), nvp.pagesUsingNewFormat ) > -1 ) {
		if ( $.inArray( mw.config.get( 'wgAction' ), [ 'edit', 'submit' ] ) > -1 ) {
			// Se o editor tiver a intenção de editar a página (não de criar um tópico), não atrapalhe!
			if ( mw.util.getParamValue( 'section' ) === 'new' || nvp.$heading.text().indexOf( '(nova se' ) !== -1 ) {
				nvp.improveTopicCreation();
			} else {
				$( '#editform' ).show();
			}
		} else {
			if ( mw.config.get( 'skin' ) === 'vector' || mw.config.get( 'skin' ) === 'vector-2022' ) {
				// Move o botão "editar" para o menu de ações
				$( '#p-cactions' ).find( 'ul' ).prepend( $( '#ca-edit' ) );
			}
		}
	}
};

$( nvp.run );

}( mediaWiki, jQuery ) );