from typing import Any from ..elements.add_document_element import add_document_element from ..elements.update_document_element_attributes import update_document_element_attributes from ..labels.element_kind_labels import element_default_attributes from .add_document_page import add_document_page from .delete_document_page import delete_document_page from .list_document_pages import list_document_pages from .set_document_page_vertical_align import set_document_page_vertical_align def replace_document_content(slug: str, seed_pages: list[dict[str, Any]]) -> None: """Remplace TOUT le contenu du support par `seed_pages` — utilisé UNIQUEMENT quand le créateur choisit explicitement "utiliser le contenu du modèle" en appliquant un thème (voir routes/document/ document_theme_apply.py, jamais appelée sans confirmation explicite côté client : action destructive, irréversible côté serveur). `seed_pages` est une liste de pages, chaque page un dict `{"vertical_align": "top"|"center"|"bottom", "blocks": [...]}` (`vertical_align` optionnel, retombe sur "top" — voir set_document_page_vertical_align.VERTICAL_ALIGNS) ; chaque bloc de `blocks` est `{"kind": str, "attributes": dict, "children": [...]}` (`children` optionnel, uniquement pour un bloc `kind="row"` — chaque enfant a la même forme `{"kind", "attributes"}`, sans petit-enfant : le moteur de rangées ne descend jamais à plus d'un niveau, voir document_engine/rendering/render_document_element.py::_render_row). Les attributs fournis sont FUSIONNÉS sur element_default_attributes(kind) (jamais un remplacement brut) pour rester valides même si `seed_pages` n'en précise qu'une partie.""" # Les nouvelles pages sont créées AVANT de supprimer les anciennes # (jamais l'inverse) : passer par zéro page, même un court instant, # déclenche le filet de sécurité de ensure_document_pages_schema (un # support a TOUJOURS au moins une page), qui recréerait une "Page 1" # vide juste avant l'ajout de la première page du thème — bug réel # rencontré en écrivant les tests de cette fonction. old_page_ids = [page["id"] for page in list_document_pages(slug)] for seed_page in seed_pages: page_id = add_document_page(slug) vertical_align = seed_page.get("vertical_align") if vertical_align: set_document_page_vertical_align(slug, page_id, vertical_align) for block in seed_page.get("blocks", []): _add_seed_block(slug, page_id, block, parent_id=None) for old_page_id in old_page_ids: delete_document_page(slug, old_page_id) def _add_seed_block(slug: str, page_id: int, block: dict[str, Any], parent_id: int | None) -> None: kind = block["kind"] element_id = add_document_element(slug, kind, page_id=page_id, parent_id=parent_id) attributes = {**element_default_attributes(kind), **block.get("attributes", {})} update_document_element_attributes(slug, element_id, attributes) for child in block.get("children", []): _add_seed_block(slug, page_id, child, parent_id=element_id)