User:Dantman/Skinning system

Misc ToDo:
 * Currently the styles for the special preferences box and tabs, and also for the user login/creation form are hardcoded into skins. We should be defining the default style in a common stylesheet and letting skins like vector add their improvements to the style over top. Right now new custom skins have to copy monobook's or vector's css after they realize that those two special pages aren't styled right.

Defined areas

 * /SkinTemplate defined areas/

Improvement vs. rewrite
Right now a lot of the skin system improvements are improvements, not rewrites of the system. With the exception of the attempt at killing the previous-generation base "Skin" system so that we only have the SkinTemplate system. There are however some faults with the SkinTemplate system. The template has various areas where it is not consulted on what the markup should look like. Helpers are nice, but when the entire generation of the category box markup is hardcoded in the skin class and not defined by the template that is supposed to be defining markup... that doesn't look right. Improvement for now, but it does sound like creating a 3rd generation skin system that defines the separation between skin area logic and markup template logic much better is in order. A number of these pieces actually shouldn't be set as keys and then passed on to the template. The template should be much more involved in defining what areas there are in the skin, and asking for things. The fact that the template does not ask for things and is instead given a bunch of predefined keys is what causes limitations like skins not being able to easily say "I don't have a standard sidebar, however I have a classic website style of header tabs that need the ability for the user to customize them."

Extras
Tabbed areas: We appear to have some pages with a dedicated tab area. Internally we have one on Special:Preferences, though the MW bugzilla's custom theme styled after our skins has it too. And I can't say it's not a ui piece that special pages built by extensions won't have any reason to want to copy. We should make this ui piece more easy to utilize and style.

Icons and subtext

 * /Page icons and page subtext/

New syntax?
Potentially a syntax, perhaps slightly strange. MonoBook is a bad example, the idea here is not that  works the same as it does in a normal template, the idea is that these keys are not preloaded, they're only loaded when you request them, and we start adding things not listed here like the markup for a hover navigation menu or a set of header navigation links. Still, a little odd. Also note this would ideally be a new api, so in this case execute is expected to output the contents of the body block. In other words, headelement, printTrail,, gone from the boilerplate. Also note things like catlinks and dataAfterContent (blech) don't use if conditions anymore. Only if you need wrapping.

xml/html template syntax

 * See /Monobook template/ for a more final example of the template syntax.

This one might be slightly awkward, though it's most likely a complete pipe dream.

Things to note:
 * Instead of userlangattributes and specialpageattributes lang="mw:user" and lang="mw:special" which get replaced
 * Things like  to output individual pieces of the skin. (Incorporating the idea of deferring things and making them more expandable as above)
 *  for quick message system outputs
 * The mw:if="foo" attribute is a shorthand for wrapping the whole thing in something like ... and is used to indicate that an element is intended to not be included if that part of the skin is not actually used.
 * mw:loop="key" works on loopable keys, (like the $this->loop above) it's another short code. It's probably equivalent to things like the ... you see, or perhaps ....
 * Make note that in this case we have nothing but a inside to indicate that the loop should simply dump out a  with nothing special.
 * Then again there is that  idea where  (or perhaps ) just dumps out pieces when you don't have anything special to do on the contents.
 * In loops things like id="p-*" are context sensitive, they know to expand the * to something relevant to the item in the loop.
 * Likewise class="{generated}...{/generated}" is considered an if block to only output when in the context of a generated sidebar item (a little fancy hooking and keying to play with in the skin system).
 * And similarly {logopath} and {nav.mainpage}. Note that these are context sensitive to their attributes. {logopath} understands it's not only inside of a attribute to escape, but that it's inside of a style="" and inside of a url and it should escape everything acordingly. In fact url({logopath}) may result in a nice url('...') style output. Likewise {nav.mainpage} understands it's part of a href="" and grabs what would essentially more verbosely be {nav.mainpage.href}.
 * The is a little bit of magic here, usually we would use text('jsmimetype') ?>">, however since this is a template syntax, and that pattern is common enough, we play up a bit of magic and automatically add the proper type to untyped scripts.
 * The scripts should not be provided using, they should go via the resourceloader. ~ Platonides
 * Also take mw:optional="yes" into account, it's similar to the mw:if and perhaps could be used in many of the mw:if examples, the idea is that if the looped contents have no items, the list itself is omitted instead of output as an empty list. The args to footerlinks may desire a nicer syntax though.
 * Through the example I disagree with xml vs html a bit. html style parsing would be really nice, just some simple no frills parsing, at the very least boolean attributes and attributes without quotes. However xml of course is much easier to get a php library to actually parse.

I've been experimenting with this and had a mix of success and trouble. I must note that using a html/xml mix that can be parsed into a dom leads to a beautiful situation where your markup is nicer to write (html style booleans and quote-less attributes) and a number of beautiful things become possible. Namely things like lang="mw:user". In the version I have in my experiment lang="mw:*" is very intelligent, it supports mw:user (user lang), mw:content (content lang), mw:page (lang the page uses, this is the same as mw:content in articles, but on special pages in the user's lang it is the same as mw:user), and it handles these very intelligently. Instead of outputting unnecessary lang tags or making guesses that lead to situations where necessary lang tags are omitted, since we have a dom when it goes through the dom, on the few elements in the template with a lang on it it checks to see if the first parent with a lang shares the same lang (making it redundant) and if so strips it out. In other words  becomes. I have however had issues doing the parsing the way I want. DOMDocument::loadHTML likes to throw warnings and strip the mw: from tags turning  into. I've heard of tidy's plugin supporting dom parsing but not everyone has tidy, and not everyone using tidy is using the php plugin (many are potentially using the executable). Additionally tidy never seamed to like  style tags anyways so it would probably screw that up as bad as DOMDocument::loadHTML. html5lib chokes on namespaced tags (well presumably it can handle a few predefined ones like svg). phpQuery and a variety of other libaries fail in various ways at parsing it, or querying it, and some are just wrappers around DOMDocument. The only one I've managed to get working so far is simplehtmldom, which unfortunately after so much of it working, I've found really screws up once you want to insert something before/after a node. It's probably not as efficient as it could be either (speaking just from looking at the api though).


 * Probably you might want to have a look at Zope Page Templates and its PHP implementation. This is a pretty mature solution and has influenced others a lot. « Saper // talk »  14:43, 13 March 2011 (UTC)

Wiki-like template syntax

 * (Platonides)

It would use a brace syntax as placeholder value between the literal tag syntax of html. It would not be supporting wikitext, or run through the parser, just the Preprocessor.

My notes: Dantman
 * The use of loses the advantages that lang="mw:page" has of removing redundant lang attributes while improving proper lang tagging of blocks on the page
 * I believe we'll lose the context sensitivity that the template syntax has, at least if we don't want to make significant changes to the preprocessor
 * The {} happy WikiText syntax is a mess to write templates with.
 * Without changes to the preprocessor I believe it will also be fairly tricky to extract information like that planned to be extracted from 

templates + php
Originally the idea was there would be a template api and a php api. However after experimenting with  and seeing the ugliness that a simple   expands to I've found really good quality skinning is in some cases close to impossible to the php api or just plain too ugly (lang="mw:user"'s intelligent stripping of lang attributes can't be done reliably in a way compatible with improvements to our multilang support the way it can with templates, and I really don't like continuing the ugly way we do script tags).

I do have one potential idea to get the flexibility of having a php api and a template api, while getting the advantages of both, not losing the advantages of the templating when using php. Instead of defining a template to use for the body, the body method is always used, and it's "that" output that gets passed through the template. So instead of doing  you use. If you don't need any special php processing the default body method will just output the contents of the template so it will be handled.

I may have to mull some of this over though. There were some ideas like the extraction of region information from a template. I need to examine if there is anything in the way of providing that ability by doing it this way.

custom / semi-standard link lists
Right now our only link list is the sidebar built from MediaWiki:Sidebar. The parsing code for this is hardcoded. Skins don't always work with this, skins can vary on what kind of navigation they offer, the most common being the sidebar, a single list of tabs in the header, or a multi-level navigation menu. Each of these has different restrictions and advantages, so they must be sourced from different lists. However to avoid skins endlessly adding more lists that can be shared we should define a standard message for each of the most common types of primary navigation. Skins can then come up with new custom ones only when they have an extra custom area that is not suited to the primary navigation and doesn't really make to much sense to share.

I have a partially finished ListMessageParser class lying around I should probably commit.

subskins
In consideration of sub-skins we may want to let skins define special blocks such as:

With a system like that, if a sub-skin defined a template it could use special mw:??? blocks to just override the contents of certain blocks.

regions

 * /Regions/