User:Inductiveload/save load actions.js
Jump to navigation
Jump to search
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.
Code that you insert on this page could contain malicious content capable of compromising your account. If you are unsure whether code you are adding to this page is safe, you can ask at the central discussion page, Scriptorium. The code will be executed when previewing this page under some skins, including Monobook. You can in the interim if you wish to refresh the content sooner under another skin. |
This script seems to have a documentation page at User:Inductiveload/save load actions. |
/**
* Simple replace-on-load-or-save framework
*
* Configurations:
* enable: disable the entire gadget on a page
* debug: enable some ill-defined debug logging
* 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';
const gadgetName = 'save_load_actions';
const SLAState = {
config: {
enabled: true,
debug: false,
namespaces: [ 'Page' ],
saveHooks: [],
loadHooks: [],
quickReplacements: [],
autoRefs: true
}
};
function slaLog( text ) {
if ( SLAState.debug ) {
// eslint-disable-next-line no-console
console.log( text );
}
}
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 ) {
let content = editbox.value;
const qReps = SLAState.config.quickReplacements;
for ( let i = 0; i < qReps.length; i++ ) {
let flags = qReps[ i ][ 0 ].flags;
// all quick replacements are global
flags = 'g' + flags.replace( 'g', '' );
const 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
let text = editbox.value;
const refBodyRe = /(?:^|\n)\* *(r[0-9]+)(?:=?(\w*)) *((?:.|\n)*?)(?=\n\n|\n\*|\n*$)/g;
// Iterate matchs for footnote bodies, replacing as we go
// Collect refs we found - we'll delete the bodies at the end
// because we're going to badly mess with the indexes
// We don't wish to just delete all of them, in case there's a body
// and no usage - then deleting it would just delete the text, not move it
const foundNums = [];
// Git gud
// eslint-disable-next-line no-restricted-properties
const matches = text.matchAll( refBodyRe );
for ( const match of matches ) {
const num = match[ 1 ];
const name = match[ 2 ];
const body = match[ 3 ];
// may need an autoname
const autoName = name || ( 'p' + getPageNum() + '_' + num );
// this is a follow-ref, place it at the top
if ( num === 'r0' ) {
const refMarkup = '<ref follow="' + autoName + '">' + body + '</ref>';
// prepend to whole text field
text = refMarkup + '\n' + text;
foundNums.push( num );
} else {
// a normal reference
const reStr = '<\\s*' + num + '\\s*\\/?\\s*>';
const usageMatches = text.match( new RegExp( reStr, 'g' ) );
if ( usageMatches ) {
if ( usageMatches.length === 1 ) {
let refMarkup = '';
if ( name ) {
// named
refMarkup += '<ref name="' + name + '">';
} else {
refMarkup += '<ref>';
}
refMarkup += body + '</ref>';
text = text.replace( new RegExp( reStr, '' ), refMarkup );
foundNums.push( num );
} else if ( usageMatches.length > 1 ) {
const ref1Markup = '<ref name="' + autoName + '">' + body + '</ref>';
const ref2Markup = '<ref name="' + autoName + '"/>';
// 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 );
foundNums.push( num );
}
}
}
}
// Finally, strip out the old bodies of the ones we found
text = text.replace( refBodyRe, ( wholeMatch, num ) => {
if ( foundNums.indexOf( num ) !== -1 ) {
return '';
}
return wholeMatch;
} );
updateTextarea( editbox, text );
}
/*
* Run user functions and replacements
*/
function slaActionOnSave() {
slaLog( 'On save' );
const editbox = document.getElementById( 'wpTextbox1' );
doQuickReplacements( editbox );
if ( SLAState.config.autoRefs ) {
doAutoRefs( editbox );
}
for ( let i = 0; i < SLAState.config.saveHooks.length; i++ ) {
SLAState.config.saveHooks[ i ]( editbox );
}
}
/*
* Run setup, apply any load functions
*/
function slaActionOnLoad() {
const editbox = document.getElementById( 'wpTextbox1' );
if ( editbox ) {
for ( let 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 ) {
const 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 ) );