Note: After saving, changes may not occur immediately. Click here to learn how to bypass your browser's cache.
  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Cmd-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (Cmd-Shift-R on a Mac)
  • Internet Explorer: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Clear the cache in Tools → Preferences

For details and instructions about other browsers, see Wikipedia:Bypass your cache.

/**
 * Simple replace-on-load-or-save framework
 *
 * Configurations:
 *     enable:     disable the entire gadget on a page
 *     namespaces:  enable the gadget only on the given namespaces
 *     saveHooks: list of callback functions to run, in order in Save or Preview.
 *                 One param is given: the main edit box.
 *     loadHooks: list of callbacks to run when loaded.
 *     quickReplacements: list of regex/replacement pairs to apply, in order
 *                 on save.
 *     quickReplacements_global: true if all quick replacements should be
 *                 made global regexes. Default: true.
 *     autoRefs:  enable automatic refs insertion. Default: true
 *
 * Configure it like this, from your main JS:
 *
 * mw.hook( 'save_load_actions.config' ).add( function ( cfg ) {
 *
 *   var repls = [
 *     [ /^c,, ?(.*)$/m, '{{center|$1}}' ],
 *   ];
 *
 *   cfg.enabled = true;
 *   cfg.namespaces = [ 'Page', '', 'Author', 'User' ];
 *   cfg.saveHooks = [ yourFunction ];
 *   cfg.quickReplacements = repls;
 * } );
 *
 */

// uncomment when running locally - gadgets get an auto-wrapped closure
( function ( $, mw ) {

	'use strict';

	var gadgetName = 'save_load_actions';

	var SLAState = {
		config: {
			enabled: true,
			namespaces: [ 'Page' ],
			saveHooks: [],
			loadHooks: [],
			quickReplacements: [],
			autoRefs: true
		}
	};

	function updateTextarea( editbox, content ) {
		// deal with CodeMirror?
		editbox.value = content;
	}

	/*
	 * Iterate the user's regexes and apply them in order, globally to the editbox
	 */
	function doQuickReplacements( editbox ) {
		var content = editbox.value;
		var qReps = SLAState.config.quickReplacements;

		for ( var i = 0; i < qReps.length; i++ ) {

			var flags = qReps[ i ][ 0 ].flags;
			// all quick replacements are global
			flags = 'g' + flags.replace( 'g', '' );
			var re = new RegExp( qReps[ i ][ 0 ].source, flags );
			content = content.replace( re, qReps[ i ][ 1 ] );
		}
		updateTextarea( editbox, content );
	}

	function getPageNum() {
		return parseInt( mw.config.get( 'wgTitle' ).split( '/' ).slice( -1 )[ 0 ] );
	}

	/*
	 * Move things that look like autorefs to the right place
	 */
	function doAutoRefs( editbox ) {

		// first split up the text a pick out ref bodies
		var text = editbox.value;

		var refBodyRe = /(?:^|\n)\* *(r[0-9]+)(=?(\w*)) *((?:.|\n)*?)(?=\n\n|\n\*|\n*$)/g;

		var refBodies = [];

		var result;
		while ( ( result = refBodyRe.exec( text ) ) !== null ) {
			var refname = null;
			if ( result[ 2 ] ) {
			// we have an equals - buy could be empty
				refname = result[ 3 ];
			}
			refBodies.push( [ result[ 1 ], result[ 4 ], refname ] );
		}

		// delete them
		text = text.replace( refBodyRe, '' );

		// for each body, find the insertion point
		for ( var i = 0; i < refBodies.length; ++i ) {
			var rb = refBodies[ i ];
			// this is a follow-ref, place it at the top
			var rname, refMarkup;

			if ( rb[ 0 ] === 'r0' ) {

				if ( rb[ 2 ] && rb[ 2 ].length > 0 ) {
					rname = rb[ 2 ];
				} else {
					rname = 'p' + ( getPageNum() - 1 ) + '_';
				}

				refMarkup = '<ref follow="' + rname + '">' + rb[ 1 ] + '</ref>';

				// prepend to whole text field
				text = refMarkup + '\n' + text;
			} else {
			// a normal reference

				var reStr = '<\\s*' + rb[ 0 ] + '\\s*\\/?\\s*>';
				var matches = text.match( new RegExp( reStr, 'g' ), rb[ 1 ] );

				if ( matches ) {

					if ( rb[ 2 ] && rb[ 2 ].length > 0 ) {
						rname = rb[ 2 ];
					} else {
						rname = 'p' + getPageNum() + '_' + rb[ 0 ];
					}

					if ( matches.length === 1 ) {
						refMarkup = '';
						if ( rb[ 2 ] !== null ) {
						// named
							refMarkup += '<ref name="' + rname + '">';
						} else {
							refMarkup += '<ref>';
						}
						refMarkup += rb[ 1 ] + '</ref>';
						text = text.replace( new RegExp( reStr, '' ), refMarkup );
					} else if ( matches.length > 1 ) {
						var ref1Markup = '<ref name="' + rname + '">' + rb[ 1 ] + '</ref>';
						var ref2Markup = '<ref name="' + rname + '"/>';

						// first instance with the content
						text = text.replace( new RegExp( reStr, '' ), ref1Markup );
						// And the rest with the named ref only
						text = text.replace( new RegExp( reStr, 'g' ), ref2Markup );
					}
				}
			}
		}

		updateTextarea( editbox, text );
	}

	/*
	 * Run user functions and replacements
	 */
	function slaActionOnSave() {

		console.log( 'On save' );

		var editbox = document.getElementById( 'wpTextbox1' );

		doQuickReplacements( editbox );

		if ( SLAState.config.autoRefs ) {
			doAutoRefs( editbox );
		}

		for ( var i = 0; i < SLAState.config.saveHooks.length; i++ ) {
			SLAState.config.saveHooks[ i ]( editbox );
		}
	}

	/*
	 * Run setup, apply any load functions
	 */
	function slaActionOnLoad() {

		var editbox = document.getElementById( 'wpTextbox1' );

		if ( editbox ) {

			for ( var i = 0; i < SLAState.config.loadHooks.length; i++ ) {
				SLAState.config.loadHooks[ i ]( editbox );
			}
		}

		// Install the on-save hook
		// eslint-disable-next-line no-jquery/no-global-selector
		$( '.editButtons' ).on( 'click', slaActionOnSave );
	}

	function slaActionSetup() {

		mw.hook( gadgetName + '.config' ).fire( SLAState.config );

		if ( !SLAState.config.enabled || SLAState.config.namespaces.indexOf(
			mw.config.get( 'wgCanonicalNamespace' ) ) === -1 ) {
			return;
		}

		if ( [ 'edit', 'submit' ].indexOf( mw.config.get( 'wgAction' ) ) !== -1 ) {
			mw.loader.using( 'ext.proofreadpage.page', function () {
			// mimic code in the extension, there is a conditionnal deps on ext.wikiEditor.
				if ( mw.user.options.get( 'usebetatoolbar' ) &&
					mw.loader.getModuleNames().indexOf( 'ext.wikiEditor' ) !== -1 ) {
					var loadDeps = [ 'ext.wikiEditor' ];
					if ( mw.user.options.get( 'codemirror-syntax-highlight' ) === 1 ) {
						loadDeps.push( 'ext.CodeMirror.lib' );
					}
					mw.loader.using( loadDeps, function () {
						slaActionOnLoad();
					} );
				} else {
					slaActionOnLoad();
				}
			} );
		}
	}
	$( slaActionSetup );

// eslint-disable-next-line no-undef
}( jQuery, mediaWiki ) );