diff --git a/conversione/_pipeline/_apply.py b/conversione/_pipeline/_apply.py index 79d75e3..19cf3d7 100644 --- a/conversione/_pipeline/_apply.py +++ b/conversione/_pipeline/_apply.py @@ -15,7 +15,7 @@ from ._artifacts import ( from ._headers import ( _t_fix_header_concat, _t_extract_capitolo, _t_normalize_numbered_headings, _t_normalize_header_levels, - _t_remove_header_bold, _t_normalize_allcaps_headers, + _t_remove_header_bold, _t_normalize_allcaps_headers, _t_demote_h1, ) from ._structure import ( _t_remove_toc, _t_remove_orphan_toc, _t_allcaps_to_headers, @@ -68,6 +68,7 @@ def apply_transforms(text: str, on_step=None) -> tuple[str, dict]: (None, _t_extract_capitolo, "estrazione Capitolo inline"), ("n_header_numerati_normalizzati", _t_normalize_numbered_headings, "normalizzazione livelli numerati"), (None, _t_normalize_header_levels, "normalizzazione livelli ####→###"), + (None, _t_demote_h1, "demozione #→## (sezioni principali)"), (None, _t_remove_header_bold, "rimozione bold negli header"), (None, _t_normalize_allcaps_headers, "normalizzazione ALL-CAPS header"), # 4. Costruzione struttura diff --git a/conversione/_pipeline/_headers.py b/conversione/_pipeline/_headers.py index 5e34247..8cde3d7 100644 --- a/conversione/_pipeline/_headers.py +++ b/conversione/_pipeline/_headers.py @@ -98,6 +98,23 @@ def _t_remove_header_bold(text: str) -> tuple[str, int]: return text, 0 +def _t_demote_h1(text: str) -> tuple[str, int]: + """ + Demota # → ## quando il documento usa # per sezioni principali (≥5 h1 + con contenuto testuale). Crea gerarchia ## → ### invece di # → ###. + """ + h1_count = len(re.findall(r"^# [A-Za-z\xc0-\xff]", text, re.MULTILINE)) + if h1_count < 5: + return text, 0 + count = 0 + def _repl(m: re.Match) -> str: + nonlocal count + count += 1 + return f"## {m.group(1)}" + text = re.sub(r"^# (.+)$", _repl, text, flags=re.MULTILINE) + return text, count + + def _t_normalize_allcaps_headers(text: str) -> tuple[str, int]: def _norm(m: re.Match) -> str: hashes, content = m.group(1), m.group(2).strip()