User:Inductiveload/save load actions

Save/Load Actions user script

Save/Load Actions provides a simple way to run functions on page load and save. This can be used to automatically insert templates, tidy formatting and construct page headers or footers.


Installation edit

Add to your common.js:

mw.loader.load('//en.wikisource.org/w/index.php?title=User:Inductiveload/save_load_actions.js&action=raw&ctype=text/javascript');

Auto Refs edit

Auto Refs is a built-in function of Save/Load Actions that simplifies the placement of references on a page. This saves effort in copy-pasting ref content, which usually OCRs at the end of the page, into ref tags in the text. Simply leave a <rX> tag in the text body and give the refs a matching prefix at the bottom and Auto Refs does the rest: it formats the reference with <ref> tags and places them in the text at the right places.

You can turn this function off by setting auto_refs: false; in the configuration object. By default it is enabled.

The gadget conducts a replacement of references matching a set pattern:

Lorem ipsum dolor sit<r1> amet, consectetur adipisicing<r2> elit<r2>, sed do eiusmod tempor incididunt<r3> ut labore et dolore<r4> magna aliqua.

* r0=p34_r2 Follow ref from previous page
* r1 Ref 1 content
* r2 Ref 2 content
* r3= Ref 3 with auto name
* r4=name Ref 4 with name

After Auto Refs runs:

<ref follow="p34_r2">Follow ref from previous page</ref>
Lorem ipsum dolor sit<ref>Ref 1 content</ref> amet, consectetur adipisicing<ref name="pXXX_r2">Ref 2 content</ref> elit<ref name="pXXX_r2"/>, sed do eiusmod tempor incididunt<ref name="pXXX_r3>Ref 3 with auto name</ref> ut labore et dolore magna<ref name="name">Ref 4 with name</ref> aliqua.

Follow-refs edit

  • Refs called r0 will be treated as a follow-ref. Enter the name of the ref on the previous page to use in the follow attribute. They will be placed at the start of the page.

Named refs edit

  • If there are multiple instances of <rX>, the first one will contain the content and the second one will be a self-closed ref tag with the same name attribute. By default, the script will try to choose a sensible name that won't clash, by using the page number.
  • If the ref name after the asterisk contains an equals (=), the ref will be named, even it's the only instance. This allows a follow-ref on a subsequent page.
  • A name can be entered after the "=" and it will be used instead of the default ref name. E.g. *r1=myname Ref content will become <ref name="myname">Ref content</ref>.

Configuration edit

You can configure the Save/Load Actions gadget like this, using the save_load_actions.config hook:

{
  var quickRepls = [
      // Change <<cl something>> to {{center|{{larger|$1}}}}
      [/<<cl (.*?)>>/, "{{center|{{larger|$1}}}}"],
  ];

  mw.hook( 'save_load_actions.config' ).add( function ( cfg ) {
    cfg.enabled = true;
    cfg.saveHooks = [ yourFunction ];
    cfg.quickReplacements = quickRepls;
    cfg.autoRefs = true;
  } );
}

There are the following options that you can pass into the config hook:

  • enabled: set to false to disable the gadget entirely for this page
  • namespaces: a list of namespaces to enable the Gadget for (default is ["Page"])
  • saveHooks: a list of functions to run when "Save", "Show Preview" or "Show Changes" are clicked. This list is empty by default. The functions are of the form:
function callback(editbox) {
 ...
}
  • loadHooks: a list of functions to run when the page is first loaded. This list is empty by default.
  • quickReplacements: a list of replacements to make on page save. This list is empty by default. You can use these replacements to write your own "instant shortcuts" which are automatically replaced when you Save or Preview the page. This is a list of pairs of regular expressions and the replacements, which can be strings or functions.
  • autoRefs: enable the "auto refs" function.

Example replacements edit

Replace <<cl XXXX>> with {{center|{{larger|XXX}} edit

      [/<<cl (.*?)>>/, "{{center|{{larger|$1}}}}"]

Alert you if the page contains the word "ILLEGAL" edit

      [/ILLEGAL/, function(x) { alert(x); return x; }]

Replace [[Foo/Bar||]] with [[Foo/Bar|Bar]] edit

This is useful when constructing ToCs.

      [/\[\[(.*)\/(.*)\|\|\s*\]\]/, "[[$1/$2|$2]]"],

Replace {{al}} with a plain author-namespace link edit

      [ /{{(?:[Aa]l|[Aa]uthor link)\|(.*?)(?:\|(.*?))?}}/, '[[Author:$1|$2]]' ]

Transparently display long-s as Unicode but save {{ls}} edit

// you might set up the hook arrays differently, this is just an example
var saveHooks = [];
var loadHooks = [];

if ( mw.config.get( 'wgCanonicalNamespace' ) === 'Page' ) {
    loadHooks.push( function ( editbox ) {
        editbox.value = editbox.value.replace( /\{\{ls\}\}/gi, 'ſ' );
    } );

    saveHooks.push( function ( editbox ) {
        editbox.value = editbox.value.replace( /ſ/g, '{{ls}}' );
    } );
}

mw.hook( 'save_load_actions.config' ).add( function ( cfg ) {
  cfg.saveHooks = loadHooks;
  cfg.loadHooks = saveHooks;
} );

Alert you for some suspicious section tags edit

var checkSectionTags = function ( editbox ) {
    var t = editbox.value;

    var parser = new DOMParser();

    var lastSecName;
    var lastSecType;

    var messages = [];

    var matches = t.match( /<section.*?\/\s*>/g ) || [];
    matches.forEach( function ( s ) {

        var sectionNode = parser.parseFromString( s, 'text/xml' ).childNodes[ 0 ];

        var type;
        var name;

        if ( sectionNode.attributes.begin ) {
            type = 'begin';
        } else if ( sectionNode.attributes.end ) {
            type = 'end';
        }
        name = sectionNode.attributes[ type ].nodeValue;

        if ( lastSecType === undefined && !( type === 'begin' ) ) {
            messages.push( 'First section tag (for "' + name + '") is not a "begin"' );
        }

        if ( type === 'end' && !( lastSecType === 'begin' && lastSecName === name ) ) {
            messages.push( 'Section "' + name + '"" ended, but the previous section tag was not a matching begin' );
        }

        if ( type === 'begin' && !( lastSecType === 'end' || lastSecType === undefined ) ) {
            messages.push( 'Section "' + name + '"" begun, but the previous section tag was not an end' );
        }

        lastSecName = name;
        lastSecType = type;
    } );

    if ( lastSecType && lastSecType !== 'end' ) {
        messages.push( 'Last section tag (for "' + lastSecName + '") is not an "end"' );
    }

    if ( messages.length ) {
        alert( messages.join( '\n' ) );
    }
};

Write a running header on page creation, changing sides as needed edit

The following load function will put it into a running header on the correct side. You can add more logic to control what title is used, or even pull text out of the main text box and use that.

  let make_rh = function() {
    if (mw.config.get("wgArticleId") !== 0 || mw.config.get("wgCanonicalNamespace") !== "Page") {
      return; // page exists, or not a page
    }

    let parts = mw.config.get("wgTitle").split("/");

    if (parts.length !== 2) {
      return; // can't get page number
    }

    let page_num = parseInt(parts[1]);

    if (!page_num) {
      return;
    }

    let rh = "";
    let num = mw.config.get('prpFormattedPageNumber');
    if (page_num % 2 == 0) {
      rh = `{{rh|${num}|TITLE VERSO|}}`;
    } else {
      rh = `{{rh||TITLE RECTO|${num}}}`;
    }

    $('#wpHeaderTextbox').val(rh);
  }

  var easyLstConfig = {
    load_hooks: [make_rh],
  }