This is a proposal to merge the [[https://www.mediawiki.org/wiki/Extension:Theme|Theme extension]] into MediaWiki core in order to generally make it a lot more effective and useful. For a more thorough background on what MediaWiki themes are and the context for their use, please see the [writeup on mw.org](https://www.mediawiki.org/wiki/Requests_for_comment/Themes_in_core). This task describes the technical aspects, on the assumption we can all agree that we want to support things like Night mode and accessibility options in a way that doesn't constantly break and isn't purely js-based and/or done by adding a bunch of extra css on top of the existing styles. (//Does// anyone disagree with that?)
== Problem ==
[[https://www.mediawiki.org/wiki/Extension:Theme|Extension:Theme]] enables setting different variants (typically colour schemes, such as Night mode or the official colours of a project) for skins, and represents the most effective, efficient extant implementation we have for such functionality (the above writeup on mw.org includes many links to less effective implementations).
As an extension, however, it has certain limitations:
* All we can really do is define new modules, typically to add stylesheets on top of the existing stylesheets.
* We can't feasibly use SkinStyles (loading component-specific styles only on page(s) the components are on) extending ResourceLoader itself to handle themes, so we basically just have to load all theme styles on all pages.
* While it is technically possible to create variable-based themes, it's super hacky and basically just requires //including// all the actual styles from the variables files, instead of visa versa. And any theme variables again cannot be reused in SkinStyles.
* Developers tend to be resistant to making their products //depend// on other products, and we've already wound up with a bunch of half-forks, generally out of date and incomplete, of the extension living in various skins so that they don't require deploying an extra extension to make use of the full features.
== Solution ==
We should be moving toward using variable-based themes, as this is both more efficient to render and download, and also a lot easier to actually //make// as a developer. Because of the widespread desire for theme support and that some of this requires changing how ResourceLoader handles skin modules, it is simply not feasible to continue to support this in an extension.
I propose three things:
### 1. Merge the current logic of Extension:Theme into core ([[https://gerrit.wikimedia.org/r/c/mediawiki/core/+/465451|patch]])
This does the following:
* Add the basic support for defining the themes a skin supports (adding ThemeModules)
* Enable the settings for users/sysadmins to select themes, the ?usetheme url param for testing, etc
* Add the basic logic of adding theme modules, which will be loaded along with the other default modules (currently this is all the extension does and isn't a good solution in general, but we will still need this even with proper variable support regardless - sometimes, you gotta override/add some extra styles for a particular theme to fully work, no matter how good your variables are)
### 2. Add support to ResourceLoader to handle skin modules and theme modules together
Allow ResourceModule definitions to define what theme(s) their styles are for, and only use those styles if on that theme. Any styles where this is not set will be assumed to be for all themes. Same thing for adding to ResourceModuleSkinStyles - support adding to a module, but only for the given theme for the given skin.
So one might define a module like so:
```
"skins.skinwithnighttheme": {
"targets": [ "desktop", "mobile" ],
"styles": {
"resources/main.css": {
"media": "screen"
},
"resources/main-night.css": {
"media": "screen",
"theme": "night"
},
...
}
},
```
Where the main-night.css is loaded after the main.css as part of the same module iff the night theme is selected.
This would be //doing// effectively the same thing as Theme does currently, but more cleanly. However, changing to this approach will break backwards compatibility in terms of how we define themes and their stylesheets (currently we create separate modules entirely for each theme, which will no longer be necessary as such), so all current skins supporting themes will need to be updated, which we plan to do concurrently.
Again, this will still be required even after adding #3, as not all themes will be possible by (only) changing variables. For instance, one might make a theme to change all the fonts to be bigger, higher contrast, etc: while the main part would be done by changing the fonts and font-sizes in the variables file, it will likely also require adjusting/specifying some other changes as well to fully work, such as line heights, paddings and border positions for certain interface elements, and things like that that cannot necessarily be set/calculated from the variables themselves.
### 3. Add explicit support for theme variables, and push it as the primary method of implementing a theme
Basically, we add some way such that when we import the skin's default variables.less file, we can also import the automatically determined current theme-variables file.
So perhaps we do
```
"ThemeModules": {
"skinwithnighttheme": [
"night": {
"variables": "resources/themes/night.less"
},
...
]
},
```
in the skin.json, and this gets passed into a less variable we then use to load the file with the variables:
```
@import resources/variables.less // or whatever we called the main one
@import @theme-variables;
```
So then any variables in the second one override the first, but it doesn't require the second having all of them, either. And if no theme is selected or the theme doesn't actually have any variables (who knows, maybe one of the themes just rotates the entire page upside down or something; you don't need variables for that), just send it an empty file for the second.
== Notes ==
# If none of this makes sense, please look at how current skins define ResourceModules (example: any), ThemeModules (example: Bouquet), and ResourceModuleSkinStyles (example: MonoBook) in their skin.json; and tend to import a variables.less file in their specific stylesheets (example: Timeless).
# The suggestions for #2 and #3 are generally based on what we currently define in skin.json etc and what we could probably do with a ResourceLoaderVariableModule, but are largely theoretical. The Theme extension itself, however, already exists and is mostly solid in terms of what it's doing; it's just not doing //nearly enough//.
# The original RfC can be found [on mw.org](https://www.mediawiki.org/wiki/Requests_for_comment/Themes_in_core). Some discussion has also occurred on the related [talk page](https://www.mediawiki.org/wiki/Talk:Requests_for_comment/Themes_in_core) onwiki.