Files
hermes-skills/skills/legal/contract-editor/references/paragraph-deletion.md
T

2.4 KiB

Paragraph Deletion via Tracked Changes (WB)

When a reviewer instructs you to delete an entire clause/paragraph, use paragraph-level deletion — not just deleting the text but marking the entire paragraph as removed in tracked changes.

Two-Part Deletion

Part 1: Paragraph Mark Deletion

Add a w:del element inside the paragraph's w:pPr/w:rPr:

<w:pPr>
  <w:rPr>
    <w:del w:id="7777" w:author="WB" w:date="2026-06-26T00:00:00Z"/>
  </w:rPr>
</w:pPr>

This marks the paragraph marker (¶) as deleted, so the paragraph doesn't leave an empty line.

Part 2: Content Deletion

Wrap every text run in the paragraph inside w:del elements, converting w:t to w:delText:

for child in list(paragraph):
    tag = child.tag.split('}')[-1]
    if tag in ('r', 'ins'):
        paragraph.remove(child)
        del_elem = etree.SubElement(paragraph, f'{{{W}}}del')
        del_elem.set(f'{{{W}}}id', '7777')
        del_elem.set(f'{{{W}}}author', 'WB')
        del_elem.set(f'{{{W}}}date', '2026-06-26T00:00:00Z')
        
        target_runs = child.findall(f'{{{W}}}r') if tag == 'ins' else [child]
        for r in target_runs:
            t = r.find(f'{{{W}}}t')
            if t is not None:
                r.remove(t)
                dt = etree.SubElement(r, f'{{{W}}}delText')
                dt.set('{http://www.w3.org/XML/1998/namespace}space', 'preserve')
                dt.text = t.text
            r.set(f'{{{W}}}rsidDel', new_rsid())
            del_elem.append(r)

Key Points

  • Same del id for both the paragraph mark and content dels (e.g., 7777) — they're part of the same deletion operation
  • Handle existing INS runs: If the paragraph has runs inside w:ins (from previous revisions), extract them and wrap in w:del too
  • Leave existing DEL runs untouched — they're already deleted
  • Copy rPr: If the original run had rPr, copy it into the del run so the strikethrough text renders with correct font/size
  • Use unique ids: Pick an id that doesn't collide with existing del/ins ids in the document. Check max(del_ids) + 1000 if unsure

Verification

After deletion, render with OnlyOffice and check:

  1. The deleted paragraph appears with strikethrough in markup view
  2. Accepting all revisions removes the paragraph entirely (no empty line)
  3. The paragraph mark (¶) is also deleted — no gap between surrounding paragraphs