Script libraries are bits of Javascript code intended to be easily reused by userscripts.

The basics

edit

Script libraries add an object to the Window object. This object contains one or more pieces of code intended to be used by other scripts – typically functions or classes.

Window.libSomethingUseful = {
    doThis: function(param) { 
        // ...
        return something;
    },
    doThat: function(p1, p2) {
        // ...
        return somethingElse;
    }
}

The name used should be quite unique, and unlikely to be unintentionally overridden by other scripts.

To minimise the number of network requests, related functionality should all be contained within a single module, rather than several small modules. To minimise the size of network requests, unrelated functionality should be split between separate modules, rather than one huge module.

Dependencies

edit

Script libraries should, if possible, avoid having dependencies themselves. This allows scripts to easily use them:

mw.loader.getScript( /* script url */ ).then(function() {
    // the library is now available on the Window object
    // ...
} );

If necessary, then there are two options for handling dependencies:

  1. Specify dependencies in the documentation, and require scripts loading the library to be responsible for loading dependencies:
    mw.loader.using( /* dependencies */ ).then(function(
        mw.loader.getScript( /* script url */ ).then(function() {
            // the library is now available on the Window object
            // ...
        } );
    } );
    
  2. Load dependencies within the library itself, and attach a Promise/Deferred object to the window. Script using the library will need to access it using something like
    mw.loader.getScript( /* script url */ ).then(function() {
        // A Promise is now available on the window object. 
        $.when( /* library Promise */ ).then(function(libraryName) { // script gets to decide what to call the library
            // the library is now available, as a variable scoped to this function
            // ...
        } );
    } );
    

Test cases

edit

Should be required. Requires a little bit of effort to set up, but invaluable for making changes/updates much less likely to break things. Which could break a lot of things for a lot of users, if the library becomes widely used. Examples using QUnit: User:Evad37/rater/test.js, User:Evad37/Covery/sandbox.js

Pseudo-namespace?

edit

Should script modules be stored in a pseudo-namespace like MediaWiki:Script module/? This means that only code approved by Interface Admins can be exported to other scripts, who could require non-minor updates to pass a WP:Code review.

Module authors wanting to add or update a script module would use an edit request, or post a request at the Interface administrators' noticeboard.

  • Advantages: Less likely to break things; better security
  • Disadvantages: More bureaucracy; likely take longer for bugs to be fixed; harder for non-intAdmin authors to maintain their stuff

Library ideas

edit
  • API helper. Make working with returned values easier – extracting response page or pages from the response data structure; format an error message from the response parameters; etc. Stuff I'm doing in XFDcloser which could be used more generally.
  • OOUI helper. Multibutton confirm window like XFDcloser; open a process dialog with only a few lines of code, rather than the current method of having to create a whole new class per mw:OOUI/Windows/Process Dialogs; custom widgets I've made for various scripts
  • Wikitext parsing. Stuff that can actually be a bit tricky, like parsing dates, signatures, and especially templates.