Skip to content

Annotation save fails when the quote prefix or suffix splits a surrogate pair (e.g., next to MathJax 4 math) #7586

Open

Description

@cxue-create

Saving an annotation fails with "Saving annotation failed" when the text-quote selector's prefix or suffix boundary falls in the middle of a non-BMP character, such as a character from the Mathematical Alphanumeric Symbols block.

This happens a lot on pages that use MathJax 4 with CHTML output. MathJax 4 writes each glyph as a DOM text node, and it maps italic variables to Unicode math-italic code points; for example, x becomes 𝑥 (U+1D465). In JavaScript these characters are stored as two code units (a surrogate pair). The prefix and suffix are cut at a fixed 32 code units, so if the cut falls between the two halves, the selector ends up with a lone surrogate. I believe the save fails at that point.

Steps to reproduce

  1. Serve this page and open it with the Hypothesis client active:

    <!doctype html>
    <html><head>
    <script async src="https://hypothes.is/embed.js"></script>
    </head><body>
    <p>Lorem ipsum consectetur. Lorem ipsum dolor sit ametus &#x1D465; elit.</p>
    </body></html>

    (You don't need MathJax to reproduce this; the &#x1D465; stands in for its output.)

  2. Highlight consectetur and click Annotate.

  3. Enter text and save.

Expected: The annotation saves.

Actual: "Saving annotation failed." The text after the highlight, . Lorem ipsum dolor sit ametus (31 code units), is followed by the two-unit 𝑥, so the 32-unit suffix ends with the lone high surrogate \uD835.

Highlighting the first Lorem ipsum instead saves normally, because its 32-unit suffix ends well before the 𝑥.

Suggested fix

When cutting prefix/suffix, don't split a surrogate pair. Move the boundary by one code unit when it would leave half of a non-BMP character, or cut by code point rather than by code unit.

Impact

On math-heavy pages that use MathJax 4 (e.g., textbooks), many highlights near inline math fail: any selection whose start or end is within 32 code units of an italic variable can be affected.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions