Requests for comment/Redo skin framework

We would like to create a skin framework to:


 * Make modification, extension and creation of skins quicker and less prone to error
 * Achieve compatibility between skins through an object-based API on the server and client
 * Liberate developers from having to maintain HTML output compatibility between skins

Problem
Currently, most MediaWiki UI elements don't have APIs, or have poor ones, and instead the HTML output by the skins for these elements is treated as the API. The HTML output of skins is kept as similar as possible between each skin as to support the many assumptions that are made by core, extension and gadget software that modify them on the client. On the server side, the few features we do have are centered around this approach of nearly identical HTML output being treated as the API.

This dependency is extremely fragile and resistant to change. Changing a skin or even just adjusting a style can easily involve updating code in hundreds of locations – and there's no way to be sure which assumptions have been made – discouraging iteration and innovation. New skins that do not have a nearly identical HTML structure will fail to work with many features and take a very long time to come to maturity, discouraging creation. In the best case, features like  try to work around minor differences, but still make lots of assumptions about the HTML. In the worst case, a skin's HTML output is so different that nothing works unless it is written specifically for it.

Solution
Pages' UI elements can be made out of skinned widgets – server- and client-side objects which render/manage discrete elements on the page. A skin can then have a standard API on the server and client, on which other software can rely. The structure of widget objects on the server can be rendered only in the final stage, allowing them to be interacted with by extensions before responding to the client. Once on the client, a structure of widget objects can be built, bound to the skin, and be used to interact with the skin programmatically at and after startup. Both the server and client code can be extended, reducing duplication while supporting the development of new features.

Proposal

 * Skin class for defining which widgets to use
 * Standard widgets which can be styled and extended
 * Client-side API for defining dynamic rendering and behavior of widgets
 * Server-side API for defining static rendering and behavior of widgets
 * Convert existing skins to use the new system
 * Document the server and client APIs
 * Introduce a radically different skin (doesn't need to be the "next" skin) as a test to prove flexibility

Definitions

 * Template
 * A named item in the template registry with a reference to a file or string containing the actual template (written in a template language supporting property placeholders, implicit escaping, loops and conditionals). These can be used by the server-side in PHP, as well in javascript by associating them with a ResourceLoader module (similar to message keys) and used there.
 * Widget
 * An object that takes zero or more data parameters that it uses to create an HTML structure. It may defer html generation to one or more templates. For example a " " widget would use the " " template to create its HTML. It would loop through   and create headings and a list item for each in.
 * If the template library supports dynamic data binding and events (e.g. it doesn't compile HTML once, but maintains references to relevant nodes and allows adding items to lists and changing values without manually digging in the DOM), then we may not have to implement widgets separate from templates, we'd just have templates.
 * On the client side widgets have additional features such as dynamically changing the properties (thus affecting the rendering), and listening for relevant data and user events.

Details

 * Output manager

MediaWiki's output page, skin system and special pages should not write html directly to the output buffer.

Rationale:
 * Not re-usable.
 * Not guaranteed to be balanced.
 * No enforced and easily reviewable security/escaping.

Instead any HTML is handled through an abstraction layer. This output manager takes a widget instead.

So where previously one would have something like: $out->addHTML( ' .... '  . Html::element( 'div', array( .. ), .. ) . ' ' ); There'd now be: $out->add( new Widget( 'sidebar', array( 'sections' => array( .. ) ) ); $out->add( 'sidebar', array( 'sections' => array( .. ) );


 * Template / widget registry

Widgets would provide an interface agonistic of which template is used by the skin for that widget. In the event that we'd not have separate widget and template models, there would be no widgets and its features provided by templates. However one feature remains that templates wouldn't have built-in. Namely the ability to have the skin decide what html template to use.

Looking at different skins today, I'd say it's a worthwhile pursuit to try to keep this ability absent. While different skins do have slightly different HTML structures for the same concepts, they don't seem to be justifiably different.

If we do need this, we'd have a mutable registry where the skin can provide a different template string for a standardised component.


 * Unified page interface

To separate concerns and aim for easier maintainability and compatibility, any software outside the skin itself would use the provided interface. Not invoke templates directly. For example, on the client side one could invoke  to add a new section to the sidebar and   to add a list item. These methods would have a reference to the instance of the sidebar widget, thus making it trivial to extend it without needing to know about its HTML structure.