Round 2 Word bisection: isolate the field-run co-factor
bisect_03 (fields removed) was the only round-1 file Word opened, and document.xml becomes byte-identical between the full book and bisect_03 once field runs are removed — but the mini book opens with identical PAGEREF fields, so the fields interact with a second factor. Add six candidates that keep the 28 PAGEREF fields while peeling other layers: - 07 drop deep-copied chapter prose (keep titles/bookmarks/fields) - 08 drop numbering properties - 09 inline hyperlink wrappers - 10 remove the whole TOC section (cleaner no-fields control) - 11 rewrite all PAGEREF targets to a single bookmark - 12 keep fields only for the first 3 TOC entries
This commit is contained in:
@@ -41,6 +41,12 @@ NAMES = [
|
||||
'bisect_04_no_styles.docx',
|
||||
'bisect_05_first8.docx',
|
||||
'bisect_06_no_images.docx',
|
||||
'bisect_07_no_prose.docx',
|
||||
'bisect_08_no_numbering.docx',
|
||||
'bisect_09_no_hyperlinks.docx',
|
||||
'bisect_10_no_toc_section.docx',
|
||||
'bisect_11_same_target_fields.docx',
|
||||
'bisect_12_first3_toc.docx',
|
||||
]
|
||||
|
||||
|
||||
@@ -116,6 +122,85 @@ def make_no_images(doc):
|
||||
p.getparent().remove(p)
|
||||
|
||||
|
||||
def _sections(doc):
|
||||
"""Return list of [start, end) kid-slices, one per body section,
|
||||
using the in-paragraph sectPr holder paragraphs as boundaries."""
|
||||
body = doc.element.body
|
||||
holders = []
|
||||
for s in body.iter(qn('w:sectPr')):
|
||||
par = s.getparent().getparent()
|
||||
if par is not None and par.getparent() is body:
|
||||
holders.append(par)
|
||||
kids = [c for c in body if c.tag == qn('w:p')]
|
||||
secs, start = [], 0
|
||||
for h in holders:
|
||||
hi = kids.index(h)
|
||||
secs.append((start, hi + 1))
|
||||
start = hi + 1
|
||||
if start < len(kids):
|
||||
secs.append((start, len(kids)))
|
||||
return kids, secs
|
||||
|
||||
|
||||
def make_no_prose(doc):
|
||||
"""Drop the deep-copied chapter prose (sections 5..32) while keeping each
|
||||
chapter's title paragraph (with its bookmark) and section holder."""
|
||||
kids, secs = _sections(doc)
|
||||
body = doc.element.body
|
||||
drop = []
|
||||
for ci, (a, b) in enumerate(secs):
|
||||
if 5 <= ci <= 32: # chapters 1..28
|
||||
drop.extend(kids[a + 1:b - 1]) # keep title [a], holder [b-1]
|
||||
for k in drop:
|
||||
body.remove(k)
|
||||
|
||||
|
||||
def make_no_numbering(doc):
|
||||
"""Remove all list-numbering properties (keeps fields)."""
|
||||
for np_ in list(doc.element.body.iter(qn('w:numPr'))):
|
||||
np_.getparent().remove(np_)
|
||||
|
||||
|
||||
def make_no_hyperlinks(doc):
|
||||
"""Remove w:hyperlink wrappers, inlining their runs (keeps fields)."""
|
||||
for hl in list(doc.element.body.iter(qn('w:hyperlink'))):
|
||||
par = hl.getparent()
|
||||
anchor = hl
|
||||
for r in list(hl):
|
||||
par.addnext(r)
|
||||
par.remove(hl)
|
||||
|
||||
|
||||
def make_no_toc_section(doc):
|
||||
"""Remove the whole TOC section (heading + entries + its section holder)."""
|
||||
kids, secs = _sections(doc)
|
||||
body = doc.element.body
|
||||
a, b = secs[4] # TOC section
|
||||
for k in kids[a:b]:
|
||||
body.remove(k)
|
||||
|
||||
|
||||
def make_same_target_fields(doc):
|
||||
"""Rewrite every PAGEREF target to _UF_ch_0 (uniform targets, fields kept)."""
|
||||
for it in doc.element.body.iter(qn('w:instrText')):
|
||||
if (it.text or '').strip().startswith('PAGEREF'):
|
||||
it.text = ' PAGEREF _UF_ch_0 '
|
||||
|
||||
|
||||
def make_first3_toc(doc):
|
||||
"""Keep only the first 3 TOC entries' fields; plain-text the rest."""
|
||||
seen = 0
|
||||
for p in doc.element.body.iter(qn('w:p')):
|
||||
if p.find(".//" + qn('w:instrText')) is None:
|
||||
continue
|
||||
if seen < 3:
|
||||
seen += 1
|
||||
continue
|
||||
for r in list(p.findall(qn('w:r'))):
|
||||
if r.find(qn('w:fldChar')) is not None or r.find(qn('w:instrText')) is not None:
|
||||
p.remove(r)
|
||||
|
||||
|
||||
MAKERS = [
|
||||
make_no_running,
|
||||
make_no_oddpage,
|
||||
@@ -123,6 +208,12 @@ MAKERS = [
|
||||
make_no_styles,
|
||||
make_first8,
|
||||
make_no_images,
|
||||
make_no_prose,
|
||||
make_no_numbering,
|
||||
make_no_hyperlinks,
|
||||
make_no_toc_section,
|
||||
make_same_target_fields,
|
||||
make_first3_toc,
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user