Recommendations for gadget developers on Wikimedia wikis

From mediawiki.org

Gadgets and user scripts (which will be referred from now on as wiki-based code) are a key component of MediaWiki projects. However, historically, frontend APIs (e.g. how wiki-based code should interact with source control provided code) have been ill-defined. This has lead to misunderstandings between engineers and wiki-based code developers when wiki-based code breaks. In certain cases, developers do not feel empowered to make changes to their own software or clear technical debt. This is because sometimes, it's unclear if and how their changes will impact wiki-based code developers.

This document outlines a set of recommendations for how volunteer contributors can build gadgets and write user scripts with minimal breakage. This set of recommendations is designed to complement the stable interface policy for frontend development that Wikimedia developers agree to uphold.

Definitions[edit]

  • See RFC 2119 to understand the language used in this policy to Indicate Requirement Levels.
  • "Wiki-based code" is defined as code that executes on Wikimedia projects and whose source code lives inside a page that is editable on wiki.
  • A "MediaWiki developer" is defined as someone who contributes code to the MediaWiki code repository or one of its extensions or skins.

Recommendations[edit]

Communication with Wikimedia developers[edit]

Wiki-based code developers SHOULD follow m:Tech/News to learn about upcoming deprecations.

MediaWiki developers WILL notify m:Tech/News prior to making changes to HTML and stable APIs and in most cases should provide at least 1 month for action. The associated Phabricator ticket title will mention "BREAKING CHANGE" and provide steps to resolve the problem inside the description. Developers of wiki-based code are encouraged to subscribe to Tech News and CAN negotiate more time with MediaWiki developers where needed.

Unmaintained code and error tracking[edit]

  • MediaWiki developers CAN fix or disable error logging for any wiki-based code and/or user script errors with error volumes that trigger alerts via Wikimedia alerting systems. Having healthy metrics helps us have more confidence when we deploy code. Ideally the fix SHOULD be made by the maintainer of the code after discussion on the script's talk page, however in time sensitive situations MediaWiki developers MAY take action themselves if they feel comfortable doing so.
  • Wiki-based code MAY opt out of error tracking by the update guidelines given on wikitech:Client error.
  • Wiki-based code in the user namespace of a retired or blocked user SHOULD be blanked by MediaWiki developers or a site admin when no longer maintained to mitigate the likelihood of security, stability or privacy issues occurring in future. They MAY be forked to other places (e.g. MediaWiki namespace, another user namespace) where the maintainer is clear.
  • Volunteers MAY request anonymized data from WMF staff and other engineers with NDA about errors coming from their wiki-based code by creating a Phabricator ticket in #Instrument-ClientError.

HTML and CSS[edit]

  • HTML can change at any given time and should not be considered a stable API. Wiki-based code SHOULD NOT make assumptions about how existing interface code is structured. For example, the dropdown menus in Vector. Wherever possible it's recommended that you use methods documented in ResourceLoader/Core_modules and where functionality is missing that these are filed as requests in Phabricator (please use #MediaWiki-Core-Skin-Architecture if unclear on which Phabricator project to use).
  • When accessing HTML elements, it's important that your code is resilient to removal and it's important to check the HTML element prior to enhancement. Per the stable interface policy for frontend development, it is better to use elements prefixed with "mw-" as these are more likely to be stable.
  • Wiki-based code MUST NOT introduce or use CSS classes prefixed with mw- to avoid namespace clashes with MediaWiki developers. It SHOULD consider prefixing CSS classes with context about the code's origin e.g. mwgadget- / twinkle- where possible but not in a way that creates name clashes with other extensions or skins.

JavaScript[edit]

  • Wiki-based code MUST be loaded to a page by the mw.loader.load method or convenience wrappers calling that method (such as importScript , importStylesheet ,importScriptURI or importStylesheetURI). Other methods are not officially supported by the MediaWiki software and may break in future. See ResourceLoader/Migration guide (users) for more information.
  • Wiki based code SHOULD be loaded from a Wikimedia owned domain e.g. hosted on a project OR a cloud VPS instance.
    • Depending on T296847 this could change to MUST in future.
  • Code inside the mw object CAN be used by wiki-based code and is subject to the rules of the Stable interface policy for frontend development. Wiki-based code developers are encouraged to use any available libraries, but wiki-based code MUST act on any deprecation warnings in JavaScript console to avoid breaking, being disabled or edited by other developers at a future point in time.
  • Wiki-based code developers SHOULD NOT assume that certain HTML structures and classes that are used now will be used in future and are encouraged to request explicit APIs for absent use cases.
    • For example, menu items SHOULD be added via the mw.util.addPortletLink method. Any menu items added via other mechanisms e.g. $('<a>').appendTo("#p-personal ul li") is not supported and is prone to future breakage.
    • Wiki-based code MAY enhance elements but when doing so must know this is done at their own risk as these elements are not subject to the deprecation policy.
    • Wiki-based code MUST cater for the situation where these elements do not exist. When accessing HTML elements, it's important that your code is resilient to removal and it's important to check the HTML element prior to enhancement. Per the stable interface policy for frontend development, it is better to use elements prefixed with "mw-" as these are more likely to be stable. [Example]
    • Wiki-based code SHOULD use named functions where-ever possible, to make it easier for other JavaScript developers to debug where errors originate.
  • At the top of wiki-based code, the maintainers SHOULD be listed, so that when there is a problem it is clear who needs to be talked to. Alternatively this can be documented on the talk page. In the absence of such information, when wiki-based code is in the user namespace, the user SHOULD be considered as the maintainer. If the user is retired, the script should be forked to another location e.g. MediaWiki namespace. When necessary, MediaWiki developers CAN consult the revision history to see who to contact, or go through Village Pumps, make protected edit requests, for non-urgent matters.

CSS[edit]

  • Wiki-based code SHOULD provide their own CSS for styling their features and SHOULD NOT rely on MediaWiki HTML classes provided by the software to style their features, even if this results in duplicated CSS. In certain cases it might make sense for wiki-based code and MediaWiki developers to share code, but this MUST be documented in the source-controlled code using a @public keyword per the Stable interface policy. If the code is not documented wiki-based code developers MUST file a Phabricator ticket to make sure this is documented.
  • Wiki-based code MAY override existing default CSS rules for content generated by wikitext e.g. thumbnails, message boxes.
  • Wiki-based code SHOULD NOT repurpose existing CSS classes for users other than intended. e.g. mw-message-box class should not be used for anything other than interface messages.
  • MediaWiki developers and wiki-based code MUST NOT share CSS classes. Wiki-based code should therefore never create HTML which prefixes classes or IDs with "mw-".

Examples[edit]

The following examples provide guidelines.

Handling error states[edit]

Always program defensively and handle unexpected states. There are several ways you can handle errors:

// these errors get picked up by Wikimedia developers and give them context to report/fix issues in your script. If using this approach you MUST be active on Phabricator to respond to any errors that arise, particularly if your script becomes popular! Descriptive error messages, in particular naming the script are very helpful for swift resolution.
throw new Error('MediaWiki-Gadget-script.js: context about error');
// These errors are for you. They do not get reported to Wikimedia and as a result will attract less attention to your script in the event of bugs.
mw.log.error('Error for script author benefit. Opt out of edits from other MediaWiki developers');

Cater for the situation where these elements do not exist[edit]

// good.js
var cactions = document.getElementById( 'p-cactions');
if ( cactions ) {
    enhanceCActions( cactions );
} else {
    // see [[#Handling error states]]
    handleError();
}

// bad.js
enhanceCActions( document.getElementById( 'p-cactions') );

Use named functions[edit]

This makes it easier for Wikimedia developers to report issues with your code.

// MediaWiki:Gadget-bad-example.js
$( 'a' ).on( 'click', function () {
    // do something
} );

// MediaWiki:Gadget-good-example.js
function goodExampleGadgetClickHandler() {
    // do something
}
$( 'a' ).on( 'click', goodExampleGadgetClickHandler );

See also[edit]

Template editors may find Recommendations for mobile friendly articles on Wikimedia wikis useful.