fix: сохранять разрыв страницы (w:br type=page) при развороте циклов
Word хранит перенос страницы отдельным run в параграфе с <!-- loop_end -->. Нормализация раньше удаляла его при склейке текста — акты слипались. Теперь page break сохраняется и копируется в каждую итерацию цикла. Проверено: 2 ИС -> 2 разрыва страниц, XML валиден.
This commit is contained in:
@@ -93,6 +93,12 @@ def _normalize_loop_markers(doc_xml: str) -> str:
|
|||||||
if '{{' not in full and 'loop:' not in full and 'loop_end' not in full:
|
if '{{' not in full and 'loop:' not in full and 'loop_end' not in full:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Был ли в параграфе разрыв страницы (Word хранит его отдельным run)
|
||||||
|
has_page_break = any(
|
||||||
|
br.get(f'{{{W_NS}}}type') == 'page'
|
||||||
|
for br in p.iter(f'{{{W_NS}}}br')
|
||||||
|
)
|
||||||
|
|
||||||
# Сохраняем форматирование первого run
|
# Сохраняем форматирование первого run
|
||||||
first_r = p.find(f'{{{W_NS}}}r')
|
first_r = p.find(f'{{{W_NS}}}r')
|
||||||
rpr = None
|
rpr = None
|
||||||
@@ -106,6 +112,14 @@ def _normalize_loop_markers(doc_xml: str) -> str:
|
|||||||
if child.tag != f'{{{W_NS}}}pPr':
|
if child.tag != f'{{{W_NS}}}pPr':
|
||||||
p.remove(child)
|
p.remove(child)
|
||||||
|
|
||||||
|
# Разрыв страницы — отдельным run ПЕРЕД текстом (как было в оригинале)
|
||||||
|
if has_page_break:
|
||||||
|
br_r = etree.SubElement(p, f'{{{W_NS}}}r')
|
||||||
|
if rpr is not None:
|
||||||
|
br_r.append(etree.fromstring(etree.tostring(rpr)))
|
||||||
|
br_el = etree.SubElement(br_r, f'{{{W_NS}}}br')
|
||||||
|
br_el.set(f'{{{W_NS}}}type', 'page')
|
||||||
|
|
||||||
# Создаём один run с полным текстом параграфа
|
# Создаём один run с полным текстом параграфа
|
||||||
new_r = etree.SubElement(p, f'{{{W_NS}}}r')
|
new_r = etree.SubElement(p, f'{{{W_NS}}}r')
|
||||||
if rpr is not None:
|
if rpr is not None:
|
||||||
@@ -204,6 +218,12 @@ def expand_loops_in_zip(docx_path: str, loops: Dict[str, List[Dict]]) -> str:
|
|||||||
wrote = True
|
wrote = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Разрыв страницы рядом с маркером конца цикла (Word хранит его
|
||||||
|
# отдельным run в параграфе с <!-- loop_end -->). Если он есть —
|
||||||
|
# каждый акт/блок цикла должен начинаться с новой страницы.
|
||||||
|
probe = doc_xml[max(0, outer_end.start() - 800):outer_end.end()]
|
||||||
|
has_page_break = '<w:br w:type="page"/>' in probe
|
||||||
|
|
||||||
# Извлекаем шаблон (всё между start и end маркерами)
|
# Извлекаем шаблон (всё между start и end маркерами)
|
||||||
template = doc_xml[outer.end():outer_end.start()]
|
template = doc_xml[outer.end():outer_end.start()]
|
||||||
|
|
||||||
@@ -224,6 +244,7 @@ def expand_loops_in_zip(docx_path: str, loops: Dict[str, List[Dict]]) -> str:
|
|||||||
clone = clone.replace('{{number}}', str(idx))
|
clone = clone.replace('{{number}}', str(idx))
|
||||||
expanded_parts.append(clone)
|
expanded_parts.append(clone)
|
||||||
|
|
||||||
|
|
||||||
# Собираем новый XML
|
# Собираем новый XML
|
||||||
new_xml = doc_xml[:outer.start()] + ''.join(expanded_parts) + doc_xml[outer_end.end():]
|
new_xml = doc_xml[:outer.start()] + ''.join(expanded_parts) + doc_xml[outer_end.end():]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user