Fix rendering issues around inline and fenced code in Markdown text fields.

Review Request #2473 — Created May 1, 2022 and updated

guest8365
Review Board
e385792...
guest8365
We try to keep a consistent presentation between Markdown text editing
and rendering in text fields, as opposed to the more standard approach
of having a "Preview" tab that's separate from the editor.

In Review Board 4, we tweaked the styling to try to more clearly
highlight any inline code literals by showing a light-grey background
and a rounded box around it. This is a pretty common appearance in many
apps, including Slack and Discord. To get this to render correctly, we
had to put some tricks in like negative margins to compensate for the
borders and keep everything aligned.

The prior approach had a few issues:

1. During editing, there was a faint border between the highlighting for
   the code literal backticks and the content (and, if you zoomed in,
   you'd see rounding on the border)

2. If putting in a fenced code block without a language mapped to a
   CodeMirror mode, the content would appear as one big inline literal
   while editing.

3. This inline literal, due to our styling and CodeMirror behavior,
   would display the cursor with a height of the full code block.

Part of the difficulty is that CodeMirror doesn't tell you when a code
literal starts or ends, and may break it up into multiple pieces
(opening backtick, one or more spans of content, closing backtick). It
also reuses the same styles for plain text in code blocks.

This change switches up the approach.

To eliminate the negative margins, but to keep the borders where we want
them, we no longer apply the border styling on the inline literal
selectors themselves. We instead set up `:before` styles,
absolutely-positioned relative to the owning span, offset out by `-1px`
on each side. This is the equivalent of what we had, but doesn't impact
layout.

We apply the top/bottom borders to the inline literals, and then apply
a left border (and radiuses) to the classes representing the
opening/closing backticks. Another rule then carefully matches the
right-most backtick class (using a combination of `:not` and `+` to
allow text to break up the adjacent selectors) and undoes the left
border and adds a right border.

The result of that is what appears to be one consistent span of text
styled as one unbroken code literal.

The second problem to solve involves the code blocks. CodeMirror does
not allow us to provide custom CSS classes for code blocks, but it does
allow us to create our own plain text lexer/highlighter mode, which
itself sets a suitable CSS class. We then map `text/plain` to that
lexer, so it's used as the fallback. This ensures that any fenced code
blocks either without a specific language or with one that's not
supported will edit and render correctly.

Testing Done:
Tested in Firefox and in Chrome, zooming far in (around 500%) and checking
the contents of code literals and code blocks in various circumstances.

This includes code blocks which are flush with the left/right edges (in the
review request fields, comment dialog, and draft banners) and ones that are
not (Review Dialog).

Reviewed at https://reviews.reviewboard.org/r/12225/

test

Description From Last Updated

why

guest8365guest8365

why

guest8365guest8365
Loading...