Skip to content

text-editor: inline code inside bold makes the whole file unopenable #4061

Closed

Description

@paracetamol32

text-editor: inline code inside bold makes the whole file unopenable

Repo: opencloud-eu/web (web-app-text-editor / Yjs collaboration glue)
Version: OpenCloud server 9.0.0 rolling, Web UI 8.2.1 (Chromium)

Summary

A markdown file containing inline code inside a bold span — e.g. **`Sharing`** — cannot be
opened in the text editor. The whole editor fails, the page reloads in a loop, and the user only
sees:

Collaboration error — Preparing this file for collaborative editing failed. Please reload.

The Yjs service is healthy: the websocket connects, onAuthenticate succeeds and returns
readOnly=false, then the client disconnects immediately. Nothing is wrong server-side; the failure
happens during hydration, in the browser.

Console output

[yjs] hydration failed: Error: [tiptap error]: Invalid JSON content
    at Zu (tiptap-vendor-Cf18ApP7.mjs:10:71810)
    at Ad (tiptap-vendor-Cf18ApP7.mjs:10:78248)
    at Object.setContent (tiptap-vendor-Cf18ApP7.mjs:10:64419)
    at Object.hydrate (editor-C_TBqycw.mjs:146:6414)
    at Yjs-vA2k3HAq.mjs:11:3560
    at ye (Yjs-vA2k3HAq.mjs:11:3523)
    at Se (Yjs-vA2k3HAq.mjs:11:4329)
Caused by: RangeError: Invalid collection of marks for node text: bold,code

Reproduction

  1. Create a markdown file containing:

    | `allowDirectoryQueries = true` sur l'objet **`Sharing`**
  2. Open it with the text editor (/text-editor/... or the files app).

  3. The editor shows the collaboration error and the page reloads.

Removing the backticks, or the **, makes the file open again. Any file with a bold span that
contains at least one code span is affected (we hit 151 of 532 files in our documentation space).

Analysis

The markdown → ProseMirror JSON conversion produces a text node whose marks array is ordered
[bold, code]. ProseMirror validates marks against the schema's mark order and throws
Invalid collection of marks for node text: bold,code (Node.check). The order is imposed by the
markdown nesting itself: in **x** the code span is inside the bold span, so "bold then code" is
the natural emission order, while the schema ranks them the other way round.

Suggested fixes

  • Sort each text node's marks according to the schema mark ranking before handing the document to
    setContent (or build the nodes through schema.text(text, marks) with marks sorted, e.g.
    marks.sort((a, b) => schema.marks[a.type.name].rank - schema.marks[b.type.name].rank), or
    Mark.setFrom).
  • Add a regression test with **`code`** and with a sentence-level bold containing code
    (**some code here**).
  • Graceful degradation: when hydration throws, fall back to non-collaborative editing instead of
    reloading the page and losing the file entirely. A single markdown construct currently makes the
    document completely inaccessible from the web UI.

Environment detail

text-editor::<fileId>:8.2.1 document names confirm the client hardcodes the web version
(function FS(){return "8.2.1"} in Yjs-vA2k3HAq.mjs), so this is not a stale-bundle problem: the
served bundle and the console-reported version match.

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

Metadata

Metadata

Assignees

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions