Round 3 Word bisection: co-factor probes around the PAGEREF fields
The mini opens with 3 byte-identical fields while the full shell fails even with 3 (bisect_12) or 1 target (bisect_11), so the co-factor is outside the TOC. Six new candidates keep fields and strip the remaining families or probe the field mechanism: - 13 drop scene-break paragraphs - 14 drop all bookmarkStart/End (fields keep, targets vanish) - 15 full shell with the mini's own 3-entry TOC spliced in verbatim - 16 drop chapter title paragraphs (WAChapter) - 17 rewrite PAGEREF instructions to PAGE (structure unchanged) - 18 remove w:dirty (no auto field update on open)
This commit is contained in:
@@ -19,6 +19,7 @@ feature family:
|
||||
Open each in Word; whichever show the error dialog pinpoint the feature
|
||||
family at fault.
|
||||
"""
|
||||
from copy import deepcopy
|
||||
import os
|
||||
import sys
|
||||
|
||||
@@ -47,6 +48,12 @@ NAMES = [
|
||||
'bisect_10_no_toc_section.docx',
|
||||
'bisect_11_same_target_fields.docx',
|
||||
'bisect_12_first3_toc.docx',
|
||||
'bisect_13_no_scenes.docx',
|
||||
'bisect_14_no_bookmarks.docx',
|
||||
'bisect_15_mini_toc_in_full.docx',
|
||||
'bisect_16_no_titles.docx',
|
||||
'bisect_17_page_fields.docx',
|
||||
'bisect_18_no_dirty.docx',
|
||||
]
|
||||
|
||||
|
||||
@@ -201,6 +208,83 @@ def make_first3_toc(doc):
|
||||
p.remove(r)
|
||||
|
||||
|
||||
def make_no_scenes(doc):
|
||||
"""Drop the scene-break paragraphs (keep fields)."""
|
||||
for p in list(doc.element.body.iter(qn('w:p'))):
|
||||
txt = ''.join((t.text or '') for t in p.findall('.//' + qn('w:t')))
|
||||
if '>>>' in txt:
|
||||
p.getparent().remove(p)
|
||||
|
||||
|
||||
def make_no_bookmarks(doc):
|
||||
"""Remove every bookmarkStart/bookmarkEnd (fields stay, targets vanish)."""
|
||||
for tag in ('w:bookmarkStart', 'w:bookmarkEnd'):
|
||||
for b in list(doc.element.body.iter(qn(tag))):
|
||||
b.getparent().remove(b)
|
||||
|
||||
|
||||
def make_mini_toc_in_full(doc):
|
||||
"""Full shell WITHOUT the TOC section, but with the mini book's own
|
||||
3-entry TOC (heading + entries + fields) spliced in verbatim."""
|
||||
make_no_toc_section(doc)
|
||||
mini = Document(os.path.join(HERE, 'word_test_output.docx'))
|
||||
paras = [c for c in mini.element.body if c.tag == qn('w:p')]
|
||||
start = None
|
||||
for i, p in enumerate(paras):
|
||||
txt = ''.join((t.text or '') for t in p.findall('.//' + qn('w:t')))
|
||||
if txt.strip() == 'Table of Contents':
|
||||
start = i
|
||||
break
|
||||
end = len(paras)
|
||||
for i in range(start + 1, len(paras)):
|
||||
ppr = paras[i].find(qn('w:pPr'))
|
||||
if ppr is not None and ppr.find(qn('w:sectPr')) is not None:
|
||||
end = i
|
||||
break
|
||||
# anchor: first WAChapter paragraph (chapter 1 title) of the full shell
|
||||
body = doc.element.body
|
||||
anchor = None
|
||||
for p in body.iter(qn('w:p')):
|
||||
ppr = p.find(qn('w:pPr'))
|
||||
if ppr is None:
|
||||
continue
|
||||
st = ppr.find(qn('w:pStyle'))
|
||||
if st is not None and st.get(qn('w:val')) == 'WAChapter':
|
||||
anchor = p
|
||||
break
|
||||
for pi in range(start, end):
|
||||
body.insert(list(body).index(anchor), deepcopy(paras[pi]))
|
||||
|
||||
|
||||
def make_no_titles(doc):
|
||||
"""Drop the chapter title paragraphs (WAChapter) incl. their bookmarks."""
|
||||
for p in list(doc.element.body.iter(qn('w:p'))):
|
||||
ppr = p.find(qn('w:pPr'))
|
||||
if ppr is None:
|
||||
continue
|
||||
st = ppr.find(qn('w:pStyle'))
|
||||
if st is not None and st.get(qn('w:val')) == 'WAChapter':
|
||||
p.getparent().remove(p)
|
||||
|
||||
|
||||
def make_page_fields(doc):
|
||||
"""Replace every PAGEREF instruction with PAGE (structure kept)."""
|
||||
for it in doc.element.body.iter(qn('w:instrText')):
|
||||
if (it.text or '').strip().startswith('PAGEREF'):
|
||||
it.text = ' PAGE '
|
||||
|
||||
|
||||
def make_no_dirty(doc):
|
||||
"""Remove w:dirty from field runs (no auto field update on open)."""
|
||||
for fc in doc.element.body.iter(qn('w:fldChar')):
|
||||
r = fc.getparent()
|
||||
rpr = r.find(qn('w:rPr'))
|
||||
if rpr is not None:
|
||||
d = rpr.find(qn('w:dirty'))
|
||||
if d is not None:
|
||||
rpr.remove(d)
|
||||
|
||||
|
||||
MAKERS = [
|
||||
make_no_running,
|
||||
make_no_oddpage,
|
||||
@@ -214,6 +298,12 @@ MAKERS = [
|
||||
make_no_toc_section,
|
||||
make_same_target_fields,
|
||||
make_first3_toc,
|
||||
make_no_scenes,
|
||||
make_no_bookmarks,
|
||||
make_mini_toc_in_full,
|
||||
make_no_titles,
|
||||
make_page_fields,
|
||||
make_no_dirty,
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user