• 
      

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

    Review Request #12225 — Created April 2, 2022 and submitted — Latest diff uploaded

    Information

    Review Board
    release-4.0.x

    Reviewers

    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.

    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).


    Commits

    Files