Page MenuHomePhabricator

SPIKE: Investigate real-time (live) preview [8H]
Closed, ResolvedPublic2 Estimated Story PointsSpike

Description

Background

From the Community Wishlist Survey 2021:

Wikitext editors often skip the step of previewing their edits, missing simple typos and formatting errors that could be easily avoided if previewed live. -- user Czar

Resources

Acceptance Criteria

  • Evaluate Actual Live Preview solution, share findings with team as well as estimated scope of work.

Event Timeline

As differentiation of terms is hard, this task is about always showing a preview, without any explicit user action needed?
Asking as https://www.mediawiki.org/wiki/Manual:Live_preview exists but still requires to press "Show Preview".

As differentiation of terms is hard, this task is about always showing a preview, without any explicit user action needed?
Asking as https://www.mediawiki.org/wiki/Manual:Live_preview exists but still requires to press "Show Preview".

Correct. mw:Manual:Live preview is a misnomer. After we're done with this project, we may want to rename that page and associated documentation / tasks.

MusikAnimal renamed this task from Introduce live preview for the wikitext editor to SPIKE: Investigate live preview [8H].Jul 12 2021, 10:40 PM
MusikAnimal edited projects, added Spike; removed WikiEditor (2010).
MusikAnimal updated the task description. (Show Details)
Restricted Application changed the subtype of this task from "Task" to "Spike". Β· View Herald TranscriptJul 12 2021, 10:40 PM

I just found T285500: SPIKE: Editing: Investigate live preview [8H] which is in Sprint 6. Surely that is supposed to come first, so I merged that here and reworded this task accordingly. I don't think we should have tickets for the actual work until we know what we're doing (new tickets will be the result of this investigation). I also removed WikiEditor (2010) as we're not even sure we'll be touching that extension yet.

NOTE: To avoid confusion with terminology, in this investigation I will refer to the new product as Real-time previews. This is because there is an existing (very poorly named!) named feature called Live Preview, which is in fact not actually live... rather it just uses AJAX to quickly get a preview without a page refresh, still requiring you to manually press "Show preview". So "Live Preview" means old, "Real-time preview" means new.

How TheDJ's script works

  • Uses CSS to force the editor area to be 50% width and re-positions the preview output area to be on the right side of the screen.
  • Clicks the "Show preview" button via JavaScript whenever you stop typing.
  • Depends on the Live Preview feature being enabled ("Show previews without reloading the page" preference), as well as the "Show preview before edit box" preference.
  • As the user scrolls in the editing window, the preview area is also scrolled so that it roughly matches where your cursor is. This part is a little buggy and doesn't work but so well.

How other real-time previews work

Discussion Tools provides a real-time preview, and it works the same way as Live Preview, which is through the action=parse API. You give the API endpoint some wikitext (and context such as the page you're editing), it gives you the HTML. Simple.

Possible performance problems

Unlike with Discussion Tools, we want to continually preview the entire page, which could be considerably large. Articles like Barack Obama can take over 8 seconds to preview using the action=parse API, in my testing, and that's with my fiber optic internet speeds. We obviously can't do this on every keystroke, nor should we attempt to. Just like with TheDJ's script, we can debounce keyboard input to ensure we don't fire off too many requests (basically wait till the user stops typing). Additionally we should probably also make sure requests are made synchronously (get a response back before making a new request). With that I don't think we'll have any server-side performance problems, and the perceived impact to the user is proportional to the size of the article, which in most cases is not going to be a problem.

Environmental compatibility

The assumption is people want a side-by-side view of the editor and preview output. We first perhaps should only support screens with say 1200px width (as is the case with TheDJ's script).

For now, I think it's safe to focus on just the 2010 and default editors, and not the 2017 wikitext editor. The latter would involve different UI challenges and likely would add a significant amount of work to the project. The 2017 wikitext editor ignores all existing preview preferences, anyway.

There is a conflict with MediaWiki-extensions-CodeMirror in TheDJ's script but following T284282 we can now easily get around that.

Preferences

Some people will want to keep their Live Preview like is now. Some have it positioned above the editor, some below. This unfortunately I think is one of the situations where we'll require a new preference. However it will be weird to have one called "Show previews without reloading the page" and then a separate one that overrides it called i.e. "Show previews in real time".

With that in mind, I have a few ideas:

  1. Turn the "Show preview before edit box" into radio buttons: "(x) Show preview after edit box ( ) Show preview before edit box ( ) Show preview to the side of the edit box on large screens". Then the "Show previews without reloading the page" becomes: "(x) Show previews without reloading the page ( ) Show previews in real-time". This means we need to make the new real-time preview feature work for all the other views, but this should be trivial as they all work in the same way, they're just positioned differently.
  2. Add a new preference "[ ] Show previews in real-time as you type". When this is checked, it disables the "Show previews without reloading the page" checkbox (but leaves it checked). Then we need some way to convey that the "real-time" preference means it gets positioned to the right, if there is room. If there is not enough room, it respects your "Show previews before the edit box" option. That could be tricky and/or weird.
  3. A hybrid of the aforementioned. Turn the preview positioning preference into three radio buttons, and then add a new "[ ] Show previews in real-time as you type" which disables/overrides "Show previews without reloading the page".
  4. Add a checkbox to the editing form directly "[ ] Show real-time previews". This might be nice because when I for instance go to edit [[Barack Obama]], I might want to disable real-time preview because previews are so slow on large pages, and this way I don't have to first go to preferences. As with #2 we still need to indicate to the user that the real-time previews are shown to the right of the editor (if there's room). The downside is this will cause clutter for those who don't want this feature, and I don't think we want a dedicated preference solely to show/hide the "Real-time previews" checkbox.

Overall I'm leaning to #1 as the least complex and most intuitive.

Conclusions

I had a play at this and managed to get TheDJ's script to work, and envision the new real-time preview working in much the same way. It could live within the existing mediawiki.action.edit.preview module, which it is part of MediaWiki Core. The actual JavaScript we add I don't think will be very complicated and would largely be the same as TheDJ's, except we call the parser directly rather than clicking the "Show preview" button. The auto-scrolling feature (whereby the preview is supposed to be scrolled to the area you're editing) might be the one tricky part.

As for preferences, I recommend option #1. If that's the case, the implementation plan could be broken out like so:

  • Add a preference for "Show preview to the side of the edit box on large screens". This could be done separately from all other work.
  • Add basic real-time previews functionality (new preference, trigger preview from debounced keyboard input)
  • Implement the auto-scrolling part of real-time previews. This would only apply those who have the "Show preview to the side of the edit box" preference.

All of the above should be behind the same feature flag.

I expect this project to take around no more than a month to complete, and that's with a lot of padding.

Unlike with Discussion Tools, we want to continually preview the entire page, which could be considerably large. Articles like Barack Obama can take over 8 seconds to preview using the action=parse API, in my testing, and that's with my fiber optic internet speeds. We obviously can't do this on every keystroke, nor should we attempt to. Just like with TheDJ's script, we can debounce keyboard input to ensure we don't fire off too many requests (basically wait till the user stops typing). Additionally we should probably also make sure requests are made synchronously (get a response back before making a new request). With that I don't think we'll have any server-side performance problems, and the perceived impact to the user is proportional to the size of the article, which in most cases is not going to be a problem.

What about excluding this kind of pages from real-time preview? E.g. if a page is too large, or it has too many templates, or if the first preview attempt takes too long (or even a max time threshold to be reached after N previews, to avoid one-offs), or a combinations of these (I might help with that). At that point we might not even need synchronous requests. All in all, I think it should be perfectly fine to exclude massive articles from real-time preview.

Preferences

Some people will want to keep their Live Preview like is now. Some have it positioned above the editor, some below. This unfortunately I think is one of the situations where we'll require a new preference. However it will be weird to have one called "Show previews without reloading the page" and then a separate one that overrides it called i.e. "Show previews in real time".
With that in mind, I have a few ideas: [...]

Yeah, I think a new preference might be necessary, but as long as we're extending an existing one (e.g. having 3 options instead of 2), I think it's not going to have a huge impact. OTOH, on the wish page on meta there are some arguments for not having real-time preview an always-on-or-always-off preference.

What if we change the existing preview button instead? E.g. we could turn the preview button into a new widget consisting of the old button as it is now, and a smaller toggle button at the side, attached to it. If you click the toggle button, you enable live preview for that page. Technically, it would be a ButtonGroupWidget, with the existing preview button and a ToggleButtonWidget (actual design TBD, of course, this is just an idea). The main problem is that toggle buttons only exist on the JS side, but that shouldn't be hard to overcome. This may or may not be behind a preference, depending on how invasive the end result might be.

But if we are to regroup preview-related preferences, a new checkbox to enable the toggle might not be that bad. It also depends on whether enabling real-time preview is bound to enabling live preview first. If yes, then we might have a checkbox

  • Enable real-time preview button

(this wording sucks, I know) as a sub-choice of the live preview one (think of the global preferences checkboxes), and only clickable when live preview is enabled. This should have a smaller impact. If the two features are unrelated, then indeed we'd have to add a separate checkbox for enabling the real-time preview button, which might not be a good idea.

Another point to this is that the side-by-side preview probably won't work on Wikisource Index pages, as there's already a proofreading image next to the edit box. Probably a namespace-disabling config var would be useful.

Aklapper renamed this task from SPIKE: Investigate live preview [8H] to SPIKE: Investigate real-time (live) preview [8H].Jul 24 2021, 1:56 PM

Editing The Fighting Temeraire - Wikipedia.png (7Γ—1 px, 2 MB)

  • As the user scrolls in the editing window, the preview area is also scrolled so that it roughly matches where your cursor is. This part is a little buggy and doesn't work but so well.

You can do this very accurately if you use Parsoid and its "dsr" information (data source range, that is, indexes in the input wikitext corresponding to the generated DOM elements).

I wrote a proof-of-concept script once which uses those to display a real-time preview, except that the preview is an editable visual editor surface: https://en.wikipedia.org/wiki/User:Matma_Rex/whynotboth.js (screenshot on the right; it does not work very well in practice). I used the dsr information to add gaps to line up the two views, but you could also use it to scroll them.

As the user scrolls in the editing window, the preview area is also scrolled so that it roughly matches where your cursor is. This part is a little buggy and doesn't work but so well.

You can do this very accurately if you use Parsoid and its "dsr" information (data source range, that is, indexes in the input wikitext corresponding to the generated DOM elements).

This is very helpful to know. Thanks!

You can do this very accurately if you use Parsoid and its "dsr" information (data source range, that is, indexes in the input wikitext corresponding to the generated DOM elements).

I suppose this also means that when we generate previews, we could perhaps intelligently parse only the areas of the wikitext that were changed, rather the whole document. This would avoid the performance problems mentioned in T284796#7213296. The first preview of course will have to parse the whole page, then subsequent previews can benefit from the data source range. This performance improvement would add a bit of complexity to the project, but it could be added later after we're done with an MVP.

ldelench_wmf set the point value for this task to 2.Aug 27 2021, 5:25 PM