feat(eda): portada cap01 + zebra global y emphasis de render
Itera el capítulo PORTADA del AutomaticEDA y dos mejoras globales de los renderers PDF/PPTX: 1. Zebra global (PDF): _place_kv_table ahora sombrea las filas pares igual que las DataTable, así toda tabla del documento queda rayada (no solo las DataTable). Mismo patrón coherente al partir/repetir cabecera. 2. Portada usa la descripción LLM rica (profile['llm']['summary']) cuando el perfil la tiene; se elimina del fallback derivado el texto ruido "active la interpretación LLM (run_llm)…". No fuerza llamadas LLM en el capítulo, solo consume profile['llm'] si está. 3. Se quita el bloque "Criterios de calidad" de la portada (PDF y PPTX); el score "Calidad" se mantiene. 4. "Resumen del análisis" (PDF): los valores se alinean al margen derecho via el nuevo KVTable.value_align="right". 5. Nombre del dataset en la portada PPTX más grande (44pt) y subrayado via los nuevos hints Heading.underline / Heading.size_pt (el PDF los ignora). Bump CHAPTER_VERSION de portada 1.2.0 -> 1.3.0. Verificado: suite 213 passed / 1 skipped (incl. aceptación de los 16 capítulos); golden zebra = 185 filas zebra en 13 capítulos del PDF completo; portada con run_llm sin "Criterios de calidad", con descripción LLM rica y valores a la derecha; PPTX con nombre 44pt subrayado; edge sin LLM cae al fallback derivado sin ruido; fn index sin error. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,10 +38,18 @@ ENGINE_NAME = "AutomaticEDA"
|
||||
# --------------------------------------------------------------------------- #
|
||||
@dataclass
|
||||
class Heading:
|
||||
"""A section heading. ``level`` 1 (largest) .. 3 (smallest)."""
|
||||
"""A section heading. ``level`` 1 (largest) .. 3 (smallest).
|
||||
|
||||
``underline`` and ``size_pt`` are optional emphasis hints honoured by the
|
||||
PPTX renderer (the cover uses them to show the dataset name big and
|
||||
underlined). ``size_pt`` overrides the per-level font size when set; the PDF
|
||||
renderer ignores both so its layout is unchanged.
|
||||
"""
|
||||
|
||||
text: str = ""
|
||||
level: int = 1
|
||||
underline: bool = False
|
||||
size_pt: Optional[float] = None
|
||||
kind: str = field(default="heading", init=False)
|
||||
|
||||
|
||||
@@ -62,10 +70,17 @@ class Markdown:
|
||||
|
||||
@dataclass
|
||||
class KVTable:
|
||||
"""A two-column key/value table. ``rows`` is a list of ``(label, value)``."""
|
||||
"""A two-column key/value table. ``rows`` is a list of ``(label, value)``.
|
||||
|
||||
``value_align`` controls the horizontal alignment of the value column in the
|
||||
PDF renderer: ``"left"`` (default) keeps values next to the label column;
|
||||
``"right"`` pins them to the right margin (used by the cover's analysis
|
||||
summary so the numbers line up flush right).
|
||||
"""
|
||||
|
||||
rows: list = field(default_factory=list)
|
||||
title: Optional[str] = None
|
||||
value_align: str = "left"
|
||||
kind: str = field(default="kv_table", init=False)
|
||||
|
||||
|
||||
@@ -210,13 +225,20 @@ def as_block(obj: Any):
|
||||
# Build only with fields the dataclass accepts (ignore extras).
|
||||
try:
|
||||
if cls is Heading:
|
||||
size_pt = obj.get("size_pt")
|
||||
return Heading(text=_safe_str(obj.get("text")),
|
||||
level=int(obj.get("level", 1) or 1))
|
||||
level=int(obj.get("level", 1) or 1),
|
||||
underline=bool(obj.get("underline", False)),
|
||||
size_pt=(float(size_pt)
|
||||
if isinstance(size_pt, (int, float))
|
||||
else None))
|
||||
if cls is Markdown:
|
||||
return Markdown(text=_safe_str(obj.get("text")))
|
||||
if cls is KVTable:
|
||||
return KVTable(rows=list(obj.get("rows") or []),
|
||||
title=obj.get("title"))
|
||||
title=obj.get("title"),
|
||||
value_align=_safe_str(
|
||||
obj.get("value_align")) or "left")
|
||||
if cls is DataTable:
|
||||
return DataTable(header=list(obj.get("header") or []),
|
||||
rows=list(obj.get("rows") or []),
|
||||
|
||||
Reference in New Issue
Block a user