Jump to content

User:Evad37/Script modules

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Evad37 (talk | contribs) at 03:21, 25 January 2019 (start draft proposal). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

Draft proposal for reusable Javascript code to be stored in MediaWiki: namespace and be easily used in userscripts.

How it would work

Suppose you want some code to parse wikitext for templates, and return an array of nicely formatted objects like:

{
    name: 'nameOfTemplate',
    wikitext: '{{nameOfTemplate|foo|bar=qux}}',
    parameters: [
        {name: 1, value:'foo'},
        {name:'bar', value:'qux'}
    ]
}

The module code would stored at MediaWiki:Modules/templateParser.js and contain something like:

var templateParser = function(wikitext) {
    // ... lots of lines omitted ...
    return result;
};

var exports = templateParser;

The special variable exports defines what will be available to scripts that import the module. It would usually be either a function or an object containing functions.

A userscript would access the template parser using code like this:

importScriptModule('templateParser').then(function(tParser) {
    // `tParser` is the name we want to use for the module's `templateParser` function. We can choose any name we want.
    // We can now use the code defined in that module, e.g.
    var templateInfo = tParser('==See also==\n{{Commons category}}\n{{Portal-inline|JavaScript|size=tiny}}\n*[[JavaScript templating]]');
    /* `templateInfo` now evaluates to:
    [
        {
            name: 'Commons category',
            wikitext: '{{Commons category}}',
            parameters: []
        },
        {
            name: 'Portal-inline',
            wikitext: '{{Portal-inline|JavaScript|size=tiny}}',
            parameters: [
                {name: 1, value:'JavaScript'},
                {name:'size', value:'tiny'}
            ]
        }
     */
};
// The code imported from the module is not available out here. It does not infect the global scope / window object.

To load several modules, use $.when(). Access error message by using failFilter function in .then() e.g.

$.when(
    importScriptModule('templateParser'),
    importScriptModule('foobar')
).then(
    function(tParser, foo) {
        /* ... code using these modules goes here ... */
    },
    function(failMessage) {
        /* Show an error message to the user. Perhaps using bubble notifications from mw.notify */
    }
);

The code for function importScriptModule would be

window.importScriptModule = function(module) {
     return mw.loader.using('mediawiki.util').then(function() {
         return $.getScript( "https://en.wikipedia.org/w/index.php?title=MediaWiki:Module/' +mw.util.wikiUrlencode(module) + '.js&action=raw&ctype=text/javascript" );
     .then( function() {
         if ( exports === undefined ) {
             throw new Error("Script module "+module" does not export anything!");
         }
         return exports;
     }, function() {
         throw new Error("Failed to load script module "+module);
     });
};

This should probably be an on-by-default gadget, as it is only useful for registered users.