Requests for comment/Rewrite enhanced recent changes

Historical context
Once upon a time, in 2003, a man named Lee was admiring his work on the phase 3 "recent changes" page. He realised that while an unstructured chronological list of 50-250 changes might be good for robots, actual humans would benefit from some amount of grouping. Since it is common practice to edit a page multiple times in a single editing session, and since users reviewing recent changes are more likely to be interested in all the changes that happened to a page since their last visit, rather than reviewing every change to the wiki independently, Lee thought it would be a good idea to group the edits by page.

Lee was a forward thinker, and he knew that this feature would best be implemented using a language called JavaScript. By this time, many people had browsers that supported JavaScript. But for most denizens of Wikipedia at the time, JavaScript was weird and new and different, and there would have been an outcry if any default feature on the site required it.

So Lee introduced this "enhanced" grouped recent changes page, but he hid it behind a user preference, labelled "Enhanced recent changes (not for all browsers)", so that people could opt in to this feature, duly warned that they needed a more recent browser in order to use it. He called the non-JavaScript version the "old" recent changes.

Lee's original styling and design decision to hide the grouping behind a user preference have been lovingly preserved. The code structure and function names have also largely been preserved -- Skin::recentChangesBlockGroup became EnhancedChangesList::recentChangesBlockGroup, Skin::recentChangesLineOld became OldChangesList::recentChangesLine, Skin::recentChangesLineNew became EnhancedChangesList::recentChangesLine.

Problems

 * It is actually a useful feature, and deserves discoverability by exposing it on the page itself, rather than hidden away in preferences.
 * Monospace styling is weird. It was chosen to make a kind of pseudo-table using monospaced line prefixes, but probably something better can be done these days using CSS.
 * The code duplication between OldRecentChangesList and EnhancedRecentChangesList causes problems. Most notably, Wikidata hooks OldChangesListRecentChangesLine to customise display of events with the RC_EXTERNAL type, but enhanced RC has no equivalent hook.

Proposal

 * Restyle both old RC and enhanced RC according to modern conventions, making the DOM as similar as possible.
 * Merge the EnhancedChangesList and OldChangesList subclasses.
 * Have the list formatter produce an ungrouped array and optionally transform it to a grouped layout prior to output.
 * Write JavaScript code to transform the grouped output to ungrouped output and vice versa. The PHP list formatter should probably provide grouped and ungrouped integer sort indexes in an &lt;li&gt; attribute to make this easier.
 * Have a link or button, below the filter box, which switches grouping on and off. When clicked, post a user preference change to the MW API.
 * Make the user preference API only, i.e. hidden from Special:Preferences.

Alternative: JS only
An alternative, which the author does not favour, is to have MW output ungrouped HTML, and make grouping a purely client-side feature.

Implementation options:
 * 1) Send ungrouped HTML. In JavaScript before list display, style it with display:none. Then after the list is HTML is received, transform it to grouped if necessary and show it. If this is done with document.write at the relevant place in the document, flicker is avoided.
 * 2) Send JSON, and format it to HTML in JavaScript. This would make the PHP output smaller, and probably faster to generate. Client-side CPU and memory requirements would be increased. Supporting browsers with JavaScript disabled is difficult but not impossible.

Rationale for rejecting this option:
 * The client-side code is likely to be poorly optimised. For large lists, a delay in rendering is likely. Clients with poor single-thread CPU performance are becoming more common.
 * The hybrid client/server approach makes screen scraping, gadgets and user script hacks simpler.
 * Development time is not significantly reduced, in my estimation.