Page MenuHomePhabricator

Allow CodeMirror preferences to differ between wikitext and non-wikitext
Closed, ResolvedPublic8 Estimated Story Points

Description

Background

See T418352 for discussion that prompted this.

In particular, many users will want different preferences for wikitext versus non-wikitext. Conceivably desire could go beyond that to specific content models/languages, but that would require a significant amount of code complexity, and worse, it could be more costly to storage. As for per-namespace granularity, I don't personally think doing this for preferences makes much sense, and unless we see a use case for it, I'll refrain from including it

If we only allow preferences to differ based on wikitext versus non-wikitext, we can use a four integer constants: (0) not enabled in any mode, (1) enabled in all modes, (2) wikitext mode only, and (3) non-wikitext modes only. This allows us to keep the storage footprint of the codemirror-preferences user option to a minimum (so it can continue to grow as we add more features). Furthermore, the 0 and 1 values are backwards-compatible with the current storage structure.

To keep things simple, for now we will carry on with only support for boolean preferences (i.e. the feature is on or off). Later that can be expanded, but will probably call for a new user option. See T408729 for example.

I'm assuming having a UI to manage all the content models of each preference is not necessary. We can instead just silently apply it as features are toggled.

Rough acceptance criteria

  • When toggling a preference in wikitext, it should only apply to wikitext and no other modes/languages.
  • Likewise when toggling a preference in non-wikitext, it effects all modes except wikitext.
  • "Reset to defaults" can be reworked if we want, i.e. when editing a JS page, you could have "Reset to defaults for JavaScript pages" and "Reset all preferences to defaults". The exact wording and design is to be determined.
  • Preferences for any given feature should only be saved to the codemirror-preferences user option if they differ from the default (as defined by $wgCodeMirrorDefaultPreferences).

Event Timeline

MusikAnimal triaged this task as High priority.

I've got this coded up and it's working. However I'm not convinced this is the best way to go. With my current implementation, we are assuming any settings changes should only apply to the current mode. So for example, if you disable a preference that is on by default in all modes, the storage will be an array of all the other modes. If you wanted to disable the feature in all modes, you'd need to do so piecemeal, one at a time. Then eventually you will get a storage value of just 0 (disabled for all modes).

I suspect this will end up causing the storage footprint of the preference to become bigger rather than smaller.

I see two potential solutions:

  1. Forget about the per-content model thing, and make preferences only apply to wikitext versus non-wikitext
  2. Introduce the concept of negation, so that negative mode IDs in the array mean the preference should be applied everywhere but that mode.

To elaborate on #2: The idea is we have IDs assigned to each mode. For example, if you have line wrapping enabled for everything but wikitext (and all other prefs matching defaults), the value in the storage would be {"lineWrapping":[2,3,4,5,6]}, where 1 is the mode ID for mediawiki/wikitext. Instead, we could store [-1] which tells to apply the preference to everywhere but wikitext. This could easily get very complicated, and the system would need to know that after so many positive or negative values, it's cheaper to store the inverse. It can be done, but at great cost to complexity. Something like this would probably be needed in the long run however, because otherwise when new modes are added, any preferences you've tweaked won't get applied to them.

#1 would be considerably easier, but we loose the flexibility of having control over other non-wikitext modes.

Does anyone have strong opinions on this? I'm sort of inclined to just go with #1 to keep things simple.

Lua is the only mode we have right now that doesn't use the Lezer parser. It probably will eventually (refs: 1, 2), meaning literally everything but wikitext will be treated the same way with respect to features. That's all the more motivation to keep preferences reduced to a dichotomy of either wikitext or non-wikitext.

To put it simply:

Do we need to have preferences sticky for each individual content model, or is it enough to only have preferences sticky between wikitext and non-wikitext?

Wikitext/non-wikitext is probably sufficient, especially since it wouldn't mean *losing* any functionality compared to what we have now (i.e. CodeEditor for non-wikitext, nothing more granular).

MusikAnimal renamed this task from Allow CodeMirror preferences to be applied to specific content models to Allow CodeMirror preferences to differ between wikitext and non-wikitext.Mar 11 2026, 4:39 AM
MusikAnimal updated the task description. (Show Details)

Change #1250239 had a related patch set uploaded (by MusikAnimal; author: MusikAnimal):

[mediawiki/extensions/CodeMirror@master] [POC] CodeMirrorPreferences: store prefs for the current mode only

https://gerrit.wikimedia.org/r/1250239

Change #1251541 had a related patch set uploaded (by MusikAnimal; author: MusikAnimal):

[mediawiki/extensions/CodeMirror@master] CodeMirrorPreferences: make prefs sticky for mediawiki vs not-mediawiki

https://gerrit.wikimedia.org/r/1251541

MusikAnimal changed the task status from Open to In Progress.Mar 13 2026, 9:12 PM

Change #1251541 merged by jenkins-bot:

[mediawiki/extensions/CodeMirror@master] CodeMirrorPreferences: make prefs sticky for mediawiki vs non-mediawiki

https://gerrit.wikimedia.org/r/1251541

Change #1250239 abandoned by MusikAnimal:

[mediawiki/extensions/CodeMirror@master] [POC] CodeMirrorPreferences: store prefs for the current mode only

Reason:

see Ieb6e8f7aca1f

https://gerrit.wikimedia.org/r/1250239

Change #1277249 had a related patch set uploaded (by MusikAnimal; author: MusikAnimal):

[mediawiki/extensions/CodeMirror@master] Split preferences into two pairs of user options for (non-)wikitext

https://gerrit.wikimedia.org/r/1277249

Change #1277249 merged by jenkins-bot:

[mediawiki/extensions/CodeMirror@master] Split preferences into two pairs of user options for (non-)wikitext

https://gerrit.wikimedia.org/r/1277249