Phase W + V' 완료: before→filled→after 파이프라인 + 조립 로직 수정
Phase W: - weight 비율 초기 배정 (space_allocator header 높이 반영) - block_assembler 공통 조립 함수 (filled/assembled 통합) - filled → Selenium 측정 → context 저장 - sidebar overflow 확장 + body 재배분 - sub_layouts 사전 계산 (이미지 누락 해결) Phase V': - 팝업 링크 우측상단 배치 (인라인 → position:absolute) - 표 내용 Kei 판단 (공란 크기 계산 → 행/열 산출 → Kei 요약) - 출처 라벨 삭제 + 이미지 아래 캡션 배치 - after 공란 제거 (결론 바로 위까지 body/sidebar 채움) 추가: - V-10 bold 키워드: 기계적 추출 → Kei 문맥 판단 - ** 마크다운 → <strong> 변환 - [이미지:] 마커 제거 (bold 변환 전 처리) - grid-template-rows AFTER 크기 반영 (Sonnet final) - assemble_stage2 CSS font-size override, white-space fix - 하드코딩 전수 검토 완료 - 본심 여러 topic 텍스트 합침 Phase X 계획 문서 작성 (동적 역할 구조) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -531,13 +531,79 @@ def render_slide_from_html(
|
||||
|
||||
title = analysis.get("title", "슬라이드")
|
||||
grid_areas = preset.get("grid_areas", "'header header' 'body sidebar' 'footer footer'")
|
||||
grid_columns = preset.get("grid_columns", "65fr 35fr")
|
||||
grid_rows = preset.get("grid_rows", "auto 1fr auto")
|
||||
|
||||
# Phase T: 동적 비율 반영 — container_ratio가 있으면 프리셋 고정값 대신 사용
|
||||
container_ratio = analysis.get("_container_ratio")
|
||||
if container_ratio and len(container_ratio) == 2:
|
||||
grid_columns = f"{container_ratio[0]}fr {container_ratio[1]}fr"
|
||||
else:
|
||||
grid_columns = preset.get("grid_columns", "65fr 35fr")
|
||||
|
||||
# Phase W: AFTER 컨테이너 크기를 grid-template-rows에 반영
|
||||
# header=auto, body/sidebar=AFTER 높이에 맞춤, footer=AFTER 높이
|
||||
containers = analysis.get("_containers", {})
|
||||
redist = analysis.get("_fit_redistribution", {})
|
||||
from src.fit_verifier import _load_design_tokens as _ldt
|
||||
_tokens = _ldt()
|
||||
_header_h = _tokens.get("header_height", 66)
|
||||
_gap_small = _tokens["spacing_small"]
|
||||
_bg_h = int(redist.get("배경", containers.get("배경", {}).get("height_px", 0)))
|
||||
_core_h = int(redist.get("본심", containers.get("본심", {}).get("height_px", 0)))
|
||||
_footer_h = int(redist.get("결론", containers.get("결론", {}).get("height_px", 0)))
|
||||
_body_row_h = _bg_h + _core_h + _gap_small if _bg_h and _core_h else 0
|
||||
if _body_row_h > 0 and _footer_h > 0:
|
||||
grid_rows = f"auto {_body_row_h}px {_footer_h}px"
|
||||
else:
|
||||
grid_rows = preset.get("grid_rows", "auto auto auto").replace("1fr", "auto")
|
||||
|
||||
body_html = generated.get("body_html", "")
|
||||
sidebar_html = generated.get("sidebar_html", "")
|
||||
footer_html = generated.get("footer_html", "")
|
||||
|
||||
# ── 후처리 ──
|
||||
import re as _re
|
||||
# 1) sidebar 최외곽 wrapper div만 width:100% (grid cell에 맞추기)
|
||||
# 첫 번째 태그의 style에서만 변경. 내부 요소(카드 번호 등)는 건드리지 않음.
|
||||
sidebar_html = _re.sub(
|
||||
r'^(\s*<div\s+style="[^"]*?)width:\s*\d+px',
|
||||
r'\1width:100%',
|
||||
sidebar_html,
|
||||
count=1,
|
||||
)
|
||||
# 2) overflow-y:auto/scroll → overflow:hidden (스크롤 절대 금지)
|
||||
body_html = _re.sub(r'overflow-y:\s*(auto|scroll)', 'overflow:hidden', body_html)
|
||||
body_html = _re.sub(r'overflow:\s*(?:auto|scroll)(?!bar)', 'overflow:hidden', body_html)
|
||||
sidebar_html = _re.sub(r'overflow-y:\s*(auto|scroll)', 'overflow:hidden', sidebar_html)
|
||||
sidebar_html = _re.sub(r'overflow:\s*(?:auto|scroll)(?!bar)', 'overflow:hidden', sidebar_html)
|
||||
# 3) markdown **bold** → <strong>
|
||||
body_html = _re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', body_html)
|
||||
sidebar_html = _re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', sidebar_html)
|
||||
# 4) 폰트 위계 강제: 배경 영역 font-size가 본심(core)보다 크면 안 됨
|
||||
font_h = analysis.get("_font_hierarchy", {})
|
||||
bg_max = font_h.get("bg", 11.0)
|
||||
core_max = font_h.get("core", 12.0)
|
||||
sidebar_max = font_h.get("sidebar", 10.0)
|
||||
|
||||
def _cap_font(html_str: str, max_size: float) -> str:
|
||||
"""font-size: NNpx 중 max_size 초과하는 것을 max_size로 캡."""
|
||||
def _repl(m):
|
||||
val = float(m.group(1))
|
||||
if val > max_size:
|
||||
return f"font-size:{max_size}px"
|
||||
return m.group(0)
|
||||
return _re.sub(r'font-size:\s*(\d+(?:\.\d+)?)px', _repl, html_str)
|
||||
|
||||
# body_html의 첫 번째 주요 div(배경)만 캡: height:117px or 배경 색상이 있는 div
|
||||
# 배경 div 끝(</div> + spacer) 이후가 본심
|
||||
bg_end = body_html.find('<div style="height:12px;') # spacer between bg and core
|
||||
if bg_end > 0:
|
||||
bg_part = body_html[:bg_end]
|
||||
core_part = body_html[bg_end:]
|
||||
bg_part = _cap_font(bg_part, bg_max)
|
||||
body_html = bg_part + core_part
|
||||
# sidebar 전체 캡
|
||||
sidebar_html = _cap_font(sidebar_html, sidebar_max)
|
||||
|
||||
html = f"""<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
|
||||
Reference in New Issue
Block a user