Skip to content

Layout de página/coluna programático e configurável por periódico (modelo intermediário: decisão + largura + justificativa) #1278

Description

@Rossi-Luciano

Objetivo

O gerador de PDF decide layout (colunas, largura de tabela/figura) hoje via heurísticas isoladas — DPI da imagem em figure.py, contagem de coluna em xml.py — sobre uma geometria de página fixa e hardcoded (enum.py::PAGE_ATTRIBUTES, A4/2-colunas). Meta: tornar essa decisão configurável por periódico via um JSON de layout passado por parâmetro, sem detecção automática.

Trabalho dividido em duas fases.

Fase 1 — PDF padrão, config em JSON (não mais hardcoded)

Migra os valores hoje fixos em enum.PAGE_ATTRIBUTES (margens, tamanho de página, espaçamento de coluna) para um único arquivo JSON, lido de um caminho fixo — sem flag de CLI, sem seleção de arquivo alternativo, sem camada de decisão de largura de tabela/figura ainda. Saída do PDF permanece idêntica à atual.

  • tests/fixtures/pdf/default_layout.json com os valores atuais de enum.PAGE_ATTRIBUTES + loader mínimo que os lê no lugar do dict Python.
  • Bugfix: _try_insert_picture insere imagem sem largura explícita — o python-docx infere sua própria leitura de DPI, divergindo (~33% medido) da largura já decidida pelo layout.
  • Validação: gerar PDF de tests/fixtures/pdf/a1.xml e revisão visual — saída deve ser igual à de hoje.

Fase 2 — PDF específico por periódico via JSON por parâmetro

Estende o mecanismo da Fase 1: passa a aceitar um arquivo diferente do padrão, e adiciona a camada de decisão de largura.

  • Flag -c/--layout-config no CLI e no pipeline (pipeline_docx) — permite trocar qual arquivo é lido; ausente, usa o default_layout.json da Fase 1.
  • PageProfile/LayoutDecision/LayoutConfig (packtools/sps/formats/pdf/layout_config.py) — decisão de largura de tabela/figura sempre como objeto estruturado (largura + justificativa + origem), consultado por figure.py/table.py/xml.py em vez de cada um ter sua própria heurística.
  • Bugfix: _compute_single_column_width/_compute_table_width assumem sempre 2 colunas (/2 fixo) — só verificável a partir daqui, quando um JSON específico pode setar default_column_count: 1.
  • figure_layout_policy (auto / always_full_width / always_within_column) em PageProfile — precedência: override por figura (já existente) > política do periódico > heurística geométrica atual.
  • Calibrar a1.xml/a1.pdf (Acta Amazonica) via JSON próprio — chaves necessárias definidas primeiro, valores por experimentação empírica contra o alvo; validado visualmente. Depois agregar a2/a3/a4.
  • Em aberto, sem mudança nesta tarefa: seleção manual de colunas via API/CLI; largura real de coluna medida (column_min_widths_pt) na decisão de tabela.

Histórico

Primeira tentativa (#1279, fechado): PR único, 14 arquivos, +1181/-86, com 54% do módulo layout_config.py em docstring. Refeito como PRs pequenos e sequenciais, nas duas fases acima.

Notas

  • Escala de figura dentro do teto disponível (não a decisão within-column/full-width) segue sem regra geral confirmada — uma hipótese de DPI de metadado bateu num periódico e foi contrariada noutro (~2.2x o tamanho nativo confiável). Não é resolvido por figure_layout_policy; fica registrado quando a calibração desse periódico for reintroduzida como JSON próprio.

  • Coordenar com Refatoração: separação entre modelos de dados e modelos de validação #1146 (refatoração de modelos em andamento) antes de expandir LayoutConfig.

  • Relacionado: pdf_generator  #773 (bug de CLI reproduzido durante testes, não corrigido aqui — fora de escopo).

  • PR original: Introduz LayoutConfig: layout de página/coluna configurável por periódico #1279 (fechado).

  • Escopo deliberadamente restrito a geometria de página/coluna e largura de tabela/figura. Um schema bem mais amplo (masthead, tipografia de título/autores, estrutura de abstract, referências, rodapé etc.) já foi levantado experimentalmente contra o mesmo gerador em outro projeto (26 periódicos, ver artifact "Layout Drift Audit") — fica de fora desta tarefa, reservado para uma issue futura separada.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions