User:Evad37/Script modules
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.