WebKit's copy marker is not a line the author left
Paul's real clipboard bytes, captured off the Google Docs copy this branch is about, end like this: …<p>…Four…</p></b><br class="Apple-interchange-newline"><br class="Apple-interchange-newline"> Two of them, after the closing </b> of Google's wrapper. WebKit appends that marker to a copy ending at a block boundary — Safari and Chrome both do it — to record where the copy stopped. ProseMirror's clipboard parser ignores a <br> that is the last child of a non-inline parent, which disposes of exactly one; the first has a next sibling, survives, becomes a hard_break, and is the blank line that appeared under a paste with nothing after it. The previous commit turned that into an empty paragraph rather than a two-line one, which was an improvement and still one blank line more than Google shows. Ignoring the marker by its class removes it. Discriminating on the class rather than on position is what makes this safe, and it is the reason this is not simply "drop a trailing empty paragraph". A blank line the author really did leave at the end is a <br> Google puts INSIDE its wrapper, carrying no class; a positional rule would eat it. Both cases are checked against the real bytes: the copy with no trailing blank now yields exactly the five blocks Google shows, and the same copy with a real trailing blank keeps six. The rule goes ahead of schema-basic's own, which follow unchanged, so a <br> the author typed is still a break — losing that would silently delete every Shift+Enter on the way in, which the tests now pin along with the requirement that every other field of the node spec comes through untouched, since the node's name and shape are the wire format.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmyRH8GkGkt5ay8gDAUKNm
fixtures/editor-entry.js+8 −2fixtures/paste.mjs+25 −0fixtures/paste.test.mjs+30 −1internal/docs/static/{editor.a4e6489413ecd74e.js => editor.7b30ca1e00c791c0.js}+12 −12
Intent
<task-notification> <task-id>bhm8fjmvz</task-id> <tool-use-id>toolu_015TrH1JK3X54PhCG9pAXqJs</tool-use-id> <output-file>/home/paulca/.cache/tmp/claude-1001/-home-paulca-amadan-net-oficina-docs/b67dca22-59bf-4290-8b46-545183f24ea9/tasks/bhm8fjmvz.output</output-file> <status>failed</status> <summary>Background command "Re-run the full CI gate" failed with exit code 1</summary> </task-notification>
<task-notification> <task-id>botigsb37</task-id> <tool-use-id>toolu_017LSrM7qzzMDvUjdDRCp8qZ</tool-use-id> <output-file>/home/paulca/.cache/tmp/claude-1001/-home-paulca-amadan-net-oficina-docs/b67dca22-59bf-4290-8b46-545183f24ea9/tasks/botigsb37.output</output-file> <status>completed</status> <summary>Background command "Re-run the gate with a writable Go cache" completed (exit code 0)</summary> </task-notification>
<task-notification> <task-id>bjjhh9p11</task-id> <tool-use-id>toolu_01DEBLEM9aHQpkjDmC8kXs5L</tool-use-id> <output-file>/home/paulca/.cache/tmp/claude-1001/-home-paulca-amadan-net-oficina-docs/b67dca22-59bf-4290-8b46-545183f24ea9/tasks/bjjhh9p11.output</output-file> <status>completed</status> <summary>Background command "Poll hub CI until it finishes" completed (exit code 0)</summary> </task-notification>
=== text/html === <b id="docs-internal-guid-c8d9abf1-7fff-bd58-9d7a-e16744140628" style="font-size: medium; font-style: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-weight: normal;"><p dir="ltr" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span style="font-size: 11pt; font-family: Arial, sans-serif; color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-alternates: normal; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-position: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">One</span></p><p dir="ltr" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span style="font-size: 11pt; font-family: Arial, sans-serif; color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-alternates: normal; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-position: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Two</span></p><p dir="ltr" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span style="font-size: 11pt; font-family: Arial, sans-serif; color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-alternates: normal; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-position: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Three</span></p><br><p dir="ltr" style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;"><span style="font-size: 11pt; font-family: Arial, sans-serif; color: rgb(0, 0, 0); background-color: transparent; font-weight: 400; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-variant-alternates: normal; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-position: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Four</span></p></b><br class="Apple-interchange-newline" style="font-size: medium; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0);"><br class="Apple-interchange-newline" style="caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-size: medium; font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;"> === text/plain === "One\nTwo\nThree\n\nFour\n"
make a plan to handle images, links, and tables. Images can be rendered immediately and uploaded async to object storage
fixtures/editor-entry.jsLoading diff…
fixtures/paste.mjsLoading diff…
fixtures/paste.test.mjsLoading diff…
internal/docs/static/{editor.a4e6489413ecd74e.js => editor.7b30ca1e00c791c0.js}Loading diff…