Page MenuHomePhabricator

MobileFrontend removal of elements takes <templatestyles> tags with it
Open, Needs TriagePublic

Description

List of steps to reproduce (step by step, including full links if applicable):

What happens?:

  • Plainlist is not plain and hlist gets styling from core definition
  • This is because MobileFrontend removes the full style definition of those elements which happen to appear in MobileFrontend-stripped HTML, and de-duplication in TemplateStyles causes the remaining tags to be <link> rather than at least one <style> with a definition.

What should have happened instead?:
The styles should have definitions on the page from the local TemplateStyles sheets

Software version (if not a Wikimedia wiki), browser information, screenshots, other information, etc.:

Currently, this 'technique' is (ab)used by en.wp and ja.wp to remove navbox TemplateStyles from mobile, for which it more or less is reasonable (since navboxes are 'always' removed).

However, for most other styles defined in TemplateStyles, this is a problem where styles may not make it to the end user. Hopefully the templates are outputting nice HTML for a fallback, but no way to provide a systematic guarantee.

This would most likely be noticed with .hlist styles, soon to be TemplateStyles only on en.wp (and which already are so on mediawikiwiki) because there are two metatemplates (Template:Sidebar and Template:Military_navigation as campaignboxes) which are in the class of items which are removed by MobileFrontend and which occur near the top of the page, but I can imagine catching hapless uses of other styles like Template:Fraction/styles.css also existing inside of sidebars etc.

I plan to work around this as best I can with hlist, and I might be able to do some "parse everything looking for templatestyles tags and move them all outside the element" in the major problematic templates like Sidebar, but it should still get its own task and hopefully some chatter about how to resolve it best. (T124168: Show Navbox templates in mobile skins would resolve it, but only coincidentally, and I don't think that one will get done any sooner than say Parsoid read views and the post parse filtering that's been suggested... somewhere down the related-task-rabbithole of T200206: Omit `<link rel="mw-deduplicated-inline-style">` from page view HTML). In other words, we've gotten lucky so far and not too much styling has vanished. But we're getting to some of the more well-used styles now.

See also:

Event Timeline

To avoid this, MobileFrontend should "re-duplicate" the styles before doing its thing, and then de-duplicate them again after. As it happens, I implemented exactly this in JavaScript for T287675: reduplicateStyles(), deduplicateStyles(). Someone would just have to port it to PHP, and call it in MobileFormatter::filterContent(). For reference, here's Parsoid's own PHP implementation of de-duplicate: DedupeStyles.php (it doesn't need the re-duplicate operation). Parsoid is now included in MediaWiki, so one could use all of the Wikimedia\Parsoid\… stuff (and one should, it really makes using DOM in PHP bearable).

Of course strong support for fixing this.

I haven't looked into it, but rather than reduplicating then deduplicating again, couldn't the MobileFronted search for the TemplateStyles stuff in the elements it is about to remove, then replace the elements with the found TemplateStyles instead of removing everything?

It could, but it would be trickier to implement. The first problem is that the code that does the removals is actually implemented as a separate library called HtmlFormatter, so you'd have to make changes there, then make a release, then upgrade it in MobileFrontend. (And they might not even want to have that feature in it, as the libraries probably shouldn't have MediaWiki-specific features.) The second problem is that when you do that, it's easy to end up with invalid HTML, e.g. if you remove a table cell that contained styles while keeping the styles, you'll have a <style> tag inside a <tr> tag, which is invalid. (Resolving that is possible, but you need to know which elements can have which children, so it's easier to just rely on Parsoid, which already took care of that.)

Just so it's known, I hack around this slightly in navbox and sidebar currently with move_hiding_templatestyles which hoists the TemplateStyles strip markers outside of the relevant HTML (which was inspired by Module:Infobox doing something similar for the purpose of avoiding hidden rows). It obviously doesn't solve the general problem like occurs with Navbox top where the module can't reach into the content of {{navbox top}} .. content .. {{navbox bottom}}.

hey all, sorry this was the first I've ever heard of this bug.
I'll see what I can do to prioritize it.

On the one hand, MobileFrontend is doing exactly what it should do - using nomobile class should remove everything contained in the element from mobile.
On the other hand TemplateStyles de-duplication code needs to be aware of this or MobileFrontend should be aware of how TemplateStyles de-duplicates styles to make sure this is considered prior to removal.