Skip to content

Take the newline with the paragraph it belongs to - #57

Merged
ptheofan merged 1 commit into
mainfrom
56-no-blank-lines
Aug 22, 2026
Merged

Take the newline with the paragraph it belongs to#57
ptheofan merged 1 commit into
mainfrom
56-no-blank-lines

Conversation

@ptheofan

Copy link
Copy Markdown
Owner

Every replaced or removed paragraph left its trailing newline behind as an
empty paragraph. diffOpsToRequests subtracted 1 from the end of every
paragraph-level delete — a blanket workaround for a restriction that
applies in exactly two places:

Deleting the newline character before a Table, TableOfContents or
SectionBreak without deleting the element.

Deleting the last newline character of a Body, Header, Footer, Footnote,
TableCell or TableOfContents.

DeleteContentRangeRequest

Deletes are now exact, shortened only at those boundaries. Where a run
does keep its newline, the inserted text drops its own trailing newline —
the surviving one terminates the last inserted paragraph, and the second
is what showed as a blank line.

GDocsStructuralElement gains tableOfContents. The app never writes
one, but a user's document may already have it and it carries a table's
restrictions.

Verification

Two tests, both watched failing first, both asserting the document that
results from applying the batch sequentially rather than the ranges
emitted:

  • expected 'Keep\n\nAlso keep\n' to be 'Keep\nAlso keep\n' — a paragraph
    removed between two others.
  • The wholesale rewrite across two tables now lands as
    ZZZZ\nYYYY\n<table>\n<table>\n, with no blank after the new content.

One existing test asserted the old behaviour outright (endIndex 15
rather than 16 for a deleted paragraph). It encoded the artefact, so it
was updated rather than worked around.

pnpm test 1035 passed / 62 files · typecheck clean · lint clean.

Known limit

A paragraph immediately before a table the sync is keeping cannot be
removed — its newline is the one Google refuses to delete, and taking the
table with it is exactly what a comment-preserving sync must not do. A
rewrite whose new content has nothing to put there leaves one empty
paragraph in front of each such table.

Closes #56

🤖 Generated with Claude Code

Every paragraph-level delete stopped one character short, so each
replaced or removed paragraph left an empty one behind. That blanket -1
was a workaround for a restriction that applies in exactly two places:
the newline before a table, table of contents or section break, and the
last newline of the body.

Deletes are now exact, shortened only at those boundaries. Where a run
does keep its newline, the text inserted in its place drops its own
trailing newline -- the surviving one terminates the last inserted
paragraph, and a second is what showed as a blank line.

A paragraph immediately before a kept table still cannot be removed:
Google refuses that newline unless the table goes too, and the table is
what a comment-preserving sync exists to protect.

Closes #56

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ptheofan
ptheofan merged commit 19ac466 into main Aug 22, 2026
5 checks passed
@ptheofan
ptheofan deleted the 56-no-blank-lines branch August 22, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replaced paragraphs leave blank lines behind

1 participant