Page MenuHomePhabricator

Highlighting (CodeMirror) changes the editor font from the user preference (sans/serif) to monospace
Open, LowestPublicSpike

Description

NOTE: The 2 attached and merged patches resolved some consequential issues, but did not touch the core of this task.
Steps to Reproduce:
  1. Set "Edit area font style:" to sans or serif font. https://www.mediawiki.org/wiki/Special:Preferences#mw-prefsection-editing
  2. Edit source with WTE 2010 or WTE 2017 https://www.mediawiki.org/w/index.php?title=2017_wikitext_editor&action=edit
  3. Switch on / off "Syntax highlighting" on toolbar (WTE 2010) or hamburger menu (WTE 2017).
Actual Results:

When highlighting is enabled the text is rendered with monospace font.

Expected Results:

The text is always rendered in the editor with a font according to the "Edit area font style:" setting.

Questions

After a superficial skimming of the javascript code, this seems to be intentional: the used class is always .mw-editfont-monospace.

  1. Why is that so?
  2. Are there any concerns that would block using the proper setting?
  3. How to query that setting in client javascript?
  4. Why is editing done in a different - hidden - layer behind the visible text?

Answers

There are 2 editors layered above each other.

  • The top layer is visible to the users and does the syntax highlighting.
  • The bottom layer is invisible and doesn't do syntax highlighting, thus the style of the hidden text is different from the visible.

Non-monospace fonts would render the styles and non-styled characters with different sizes, thereby causing misalignment between the two layers.
As the editing happens in the hidden bottom layer, the cursor and text selection are also rendered there. Misalignment can be seen when text is selected: the highlight in the bottom layer is in a different location than the text in the above layer.

To avoid such misalignment, the editor is restricted to monospace fonts, which render characters with different styling in the same area.

  1. Why is editing done in a different - hidden - layer behind the visible text?

The bottom layer is created by Visual Editor, the top layer by CodeMirror.
Allegedly CodeMirror is not compatible with some unspecified tools in VE, therefore the bottom layer is for compatibility.

  1. What's the problem with CodeMirror?

This would require identifying and evaluating the incompatibilities in said tools.

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

Why is that so?

It's fundamental to working out how to draw the coloured boxes in the right places.

Are there any concerns that would block using the proper setting?

Yes.

How to query that setting in client javascript?

In the same way as any user preference; mw.user.options.get( 'editfont' ) in this case.

Why is that so?

It's fundamental to working out how to draw the coloured boxes in the right places.

No, it works perfectly with a serif font, see:

Are there any concerns that would block using the proper setting?

Yes.

?

How to query that setting in client javascript?

In the same way as any user preference; mw.user.options.get( 'editfont' ) in this case.

Thanks.

Change 573018 had a related patch set uploaded (by Aron Manning; owner: Aron Manning):
[mediawiki/extensions/CodeMirror@master] Remove the unnecessary 1.5em padding in MinervaNeue skin that misaligns highlights.

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

The patch 572876 fixes this bug for WTE 2010.
The solution for WTE 2017 is very different.

Why is that so?

The standard highlighting package applies bold and italics to bold and italic text. Without monospace this would affect the letter width which would break 2017WTE implementation. Given that using the edit font feature is pretty rare it was easier just to disable it for people who wanted to use syntax highlighting.

Change 573018 merged by jenkins-bot:
[mediawiki/extensions/CodeMirror@master] Remove the unnecessary 1.5em padding in MinervaNeue skin that misaligns highlights.

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

Change 572876 had a related patch set uploaded (by Aron Manning; owner: Aron Manning):
[mediawiki/extensions/CodeMirror@master] Fix the font-family: monospace; caused font-size mess-up: inherit the font setting from the parent in WTE 2017. Font set with style attribute in WTE 2010

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

The standard highlighting package applies bold and italics to bold and italic text. Without monospace this would affect the letter width which would break 2017WTE implementation. Given that using the edit font feature is pretty rare it was easier just to disable it for people who wanted to use syntax highlighting.

I admit I haven't investigated bold/italics in detail. Now I've done a more thorough research, here's the result:

  • CodeMirror highlights text in place, using in place html markup: it's the browser's job to render bold/italic/background in the right place, which it does, regardless of the font used, there can't be misalignment.
  • WTE 2010 highlighting and text selection works as expected with any font.
  • WTE 2017, on the other hand, does a weird thing with overlaying CodeMirror over VisualEditor, keeping the content of the two editors in sync and does something unexpected: the contenteditable=true attribute is on the quasi-hidden VisualEditor element, not CodeMirror's and CM is also not accepting input (pointer-events: none;), although
  • the text in VE is hidden with: .ve-ce-documentNode-codeEditor-webkit-hide { -webkit-text-fill-color: transparent; }

The result is that text is selected in VisualEditor and the selection is visible behind CodeMirror. VE can become misaligned from CM as seen in T245532 and also bold and italic highlights from CM aren't transferred to VE, causing the cursor and text selection to appear in the middle of characters, misaligned if the font is not monospace. This is not an implication of CodeMirror, but how WTE2017 uses CM and duplicates the edited text in an invisible VE layer.
Note that while experimenting I noticed that a change in the font/size also causes such misalignment of the selection in WTE2010. This only happens if the font is changed after the editor was loaded, not in normal usage.

I've suspected the reason for doing this is so that CTRL+C copies rich text without highlighting. This is not the case, both WTE 2010 without this trick and WTE 2017 seem to be copying unformatted text. I'm still looking for the reason to do this.

The reason we did this is because NWE uses ve.ce.Surface as the edit surface. This is where all our input support is coded, including things like RTL and IME support, which are more buggy in CodeMirror, and also things like inline inspectors (like the link inspector). The two surface approach is a workaround to allow us to keep using the ve.ce.Surface.

The reason we did this is because NWE uses ve.ce.Surface as the edit surface. This is where all our input support is coded, including things like RTL and IME support, which are more buggy in CodeMirror, and also things like inline inspectors (like the link inspector). The two surface approach is a workaround to allow us to keep using the ve.ce.Surface.

That's a good reason.
How is this handled in WTE 2010? Using CodeMirror, it's just a bit buggy?

It's just buggy.

If anything, in particular, comes to mind, that would help me understand the implications.

Change 572876 merged by jenkins-bot:
[mediawiki/extensions/CodeMirror@master] Don't let CodeMirror set the font to monospace if it's set on an ancestor.

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

NB for anyone else watching this task, the above patch does not change the behaviour outlined in the description.

JTannerWMF added a subscriber: JTannerWMF.

Unfortunately, we can not prioritize this at this time.

Demian changed the task status from Open to Stalled.Jun 24 2020, 7:55 PM
Demian removed Demian as the assignee of this task.
Demian lowered the priority of this task from Low to Lowest.

The 2 attached and merged patches resolved some consequential issues, but did not touch the core of this task.
The main question is: what's needed from VE (the bottom layer) that can't be done with CodeMirror (top layer).

Currently I'm not working on answering that question, therefore this task is stalled for the foreseeable future, until someone revisits the question.
There is no bug to solve other than an unusual UX limitation and a massive resource-usage. This however only affects a few users and changing it a big undertaking, therefore this ticket is very low priority.

Demian changed the subtype of this task from "Bug Report" to "Spike".Jun 24 2020, 8:00 PM
Demian updated the task description. (Show Details)

Off the top of my head:

  1. RTL issues: https://github.com/codemirror/CodeMirror/issues?q=is%3Aissue+is%3Aopen+rtl
  2. Inspector placement. We need to know the bounding box(es) of the selected text to place things like the link inspector.

I understand these are issues, but not the technical reasons.

As I understand the current solution depends on CM rendering correctly (visually the same as VE). If there are issues in RTL, does that mean the two layers are misaligned when these bugs in CM take effect for RTL users?

  1. Inspector placement. We need to know the bounding box(es) of the selected text to place things like the link inspector.

Without diving deep into the code I'd assume acquiring the bounding box for the selection would be done similarly in both layers. What is the difference? Is there some logic in VE that makes this easier, that's not available in CM?

Aklapper changed the task status from Stalled to Open.Jun 25 2020, 7:25 AM

Resetting task status as anyone is free to revisit the question.

Resetting task status as anyone is free to revisit the question.

Thank you. Hopefully someone would, I just doubt it with a 99% certainty.

@Esanders should I expect details to your answer in T245568#6254833?