From 234bdaaad4970aa1c796211c48fb5854064ee802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B2=BD=EB=AF=BC?= Date: Thu, 19 Mar 2026 12:56:29 +0900 Subject: [PATCH] Update handlers/template/doc_template_analyzer.py --- .../handlers/template/doc_template_analyzer.py | 149 +++++++++++++++++- 1 file changed, 147 insertions(+), 2 deletions(-) diff --git a/03.Code/업로드용/handlers/template/doc_template_analyzer.py b/03.Code/업로드용/handlers/template/doc_template_analyzer.py index 8eb4281..a5f0656 100644 --- a/03.Code/업로드용/handlers/template/doc_template_analyzer.py +++ b/03.Code/업로드용/handlers/template/doc_template_analyzer.py @@ -1,3 +1,148 @@ -# 문서 템플릿 분석기 +# -*- coding: utf-8 -*- +""" +문서 템플릿 분석기 v5.1 (오픈 레이어) + +역할: tools/ 모듈들을 조합하여 HWPX → 템플릿 정보 추출 +- 특정 영역 파싱 로직은 없음 (모두 tools에 위임) +- 디폴트값 생성 없음 (tools가 None 반환하면 결과에서 제외) +- 사용자 추가 사항(config.json) → 템플릿에도 반영 + +구조: + tools/ + page_setup.py 짠7 용지/여백 + font.py 짠3 글꼴 + char_style.py 짠4 글자 모양 + para_style.py 짠5 문단 모양 + border_fill.py 짠2 테두리/배경 + table.py 짠6 표 + header_footer.py 짠8 머릿말/꼬릿말 스타일 및 매기기/글머리표 + image.py 이미지 +""" + +import json +from pathlib import Path +from typing import Optional + +from .tools import ( + page_setup, + font, + char_style, + para_style, + border_fill, + table, + header_footer, + section, + style_def, + numbering, + image, + content_order, +) + + class DocTemplateAnalyzer: - pass + """HWPX → 템플릿 추출 오픈 레이어""" + + # ================================================================ + # Phase 1: 추출 (모든 tools 호출) + # ================================================================ + + def analyze(self, parsed: dict) -> dict: + """HWPX parsed 결과에서 템플릿 구조 추출. + + Args: + parsed: processor.py가 HWPX를 분석한 결과 dict. + raw_xml, section_xml, header_xml, footer_xml, + tables, paragraphs 등 포함. + + Returns: + 추출된 항목만 포함하는 dict (None항목은 제외). + """ + raw_xml = parsed.get("raw_xml", {}) + + extractors = { + "page": lambda: page_setup.extract(raw_xml, parsed), + "fonts": lambda: font.extract(raw_xml, parsed), + "char_styles": lambda: char_style.extract(raw_xml, parsed), + "para_styles": lambda: para_style.extract(raw_xml, parsed), + "border_fills": lambda: border_fill.extract(raw_xml, parsed), + "tables": lambda: table.extract(raw_xml, parsed), + "header": lambda: header_footer.extract_header(raw_xml, parsed), + "footer": lambda: header_footer.extract_footer(raw_xml, parsed), + "section": lambda: section.extract(raw_xml, parsed), + "styles": lambda: style_def.extract(raw_xml, parsed), + "numbering": lambda: numbering.extract(raw_xml, parsed), + "images": lambda: image.extract(raw_xml, parsed), + "content_order":lambda: content_order.extract(raw_xml, parsed), + } + + result = {} + for key, extractor in extractors.items(): + try: + value = extractor() + if value is not None: + result[key] = value + except Exception as e: + # 개별 tool 실패 시 로그만, 전체 중단 안 함 + result.setdefault("_errors", []).append( + f"{key}: {type(e).__name__}: {e}" + ) + + return result + + + # ================================================================ + # Phase 2: 사용자 추가 사항 병합 + # ================================================================ + + def merge_user_config(self, template_info: dict, + config: dict) -> dict: + """config.json의 사용자 요청 사항을 template_info에 병합. + + 사용자 문서 유형 추가 시 지정된 커스텀 사항 반영: + - 강조 색상 오버라이드 + - 글꼴 오버라이드 + - 제목 크기 오버라이드 + - 기타 레이아웃 커스텀 + + 이 병합 결과는 style.json에 저장되고, + 이후 template.html 생성 시에도 반영됨. + + Args: + template_info: analyze()의 결과 + config: config.json 내용 + + Returns: + 병합된 template_info (원본 수정됨) + """ + user_overrides = config.get("user_overrides", {}) + if not user_overrides: + return template_info + + # 모든 사용자 설정을 template_info에 기록 + template_info["user_overrides"] = user_overrides + + return template_info + + + # ================================================================ + # Phase 3: template_info → style.json 저장 + # ================================================================ + + def save_style(self, template_info: dict, + save_path: Path) -> Path: + """template_info를 style.json으로 저장. + + Args: + template_info: analyze() + merge_user_config() 결과 + save_path: 저장 경로 (예: templates/user/{doc_type}/style.json) + + Returns: + 저장된 파일 경로 + """ + save_path = Path(save_path) + save_path.parent.mkdir(parents=True, exist_ok=True) + + with open(save_path, 'w', encoding='utf-8') as f: + json.dump(template_info, f, ensure_ascii=False, indent=2) + + return save_path