Normalize the hybrid after patches; anchor ambiguous patch hunks in context

Extra paragraphs exist only inside a patch hunk's replace text (anchored
on the preceding original block). Deleting one produced a (X, "") hunk,
and apply_patch removed the text but not a surrounding separator, leaving
an accumulating blank line in the served/editor Markdown. hybrid_markdown
now re-chunks the patched text (join_chunks(chunk_markdown(...))), which
drops the stray blank lines on the read path — repairing gaps left by
already-stored patches too.

Adjacent fix in make_patch: a hunk whose search text occurred more than
once in the page hit the FIRST occurrence at apply time, blanking or
rewriting the wrong instance when identical paragraph text appeared
earlier. Ambiguous hunks now grow block context (preceding block first)
until unique; unique hunks stay context-free so they keep surviving
translation refreshes.
This commit is contained in:
2026-09-20 00:32:53 +00:00
parent c337651020
commit aae8d58c9f
2 changed files with 37 additions and 14 deletions
+6
View File
@@ -181,6 +181,9 @@ Hunks are produced from `difflib.SequenceMatcher` on the hybrid vs. the
edited text at block granularity: each `replace`/`delete`/`insert` opcode
becomes one `(search, replace)` pair, with the preceding block's tail as
left context for `insert` (pure inserts have empty search context otherwise).
A search text that occurs more than once in the page would hit the first
occurrence at apply time, so ambiguous hunks grow block context (preceding
block first) until unique or the page edge.
Application is dead simple:
```python
@@ -232,6 +235,9 @@ def get_translation(data, path, lang) -> Translation | None:
)
for patch in data.patches.get(f"{path}:{lang}", []):
hybrid = apply_patch(hybrid, patch)
# Deleting an extra (translation-only) paragraph leaves its surrounding
# blank lines behind; re-chunking normalizes them away.
hybrid = join_chunks(chunk_markdown(hybrid))
return Translation(markdown=hybrid, titles=title_map(data, lang))
```