Task #164: HWPX Serializer 구현 — Document IR → HWPX 저장#170
Merged
edwardkim merged 13 commits intoedwardkim:develfrom Apr 17, 2026
Merged
Task #164: HWPX Serializer 구현 — Document IR → HWPX 저장#170edwardkim merged 13 commits intoedwardkim:develfrom
edwardkim merged 13 commits intoedwardkim:develfrom
Conversation
HWPX Serializer 구현을 위한 5단계 계획: 1. 모듈 스켈레톤 + 빈 HWPX 2. 본문 문단·텍스트·lineSegArray 3. 표(Table) 직렬화 4. 그림(Picture) + BinData 5. 라운드트립 테스트 + CLI + 보고서 참조 문서: hwp_save_guide.md, hwp_hwpx_ir_differences.md
- src/serializer/hwpx/ 신설 (mod/writer/content/header/section/utils) - HwpxSerializer + DocumentSerializer 구현체 등록 - SerializeError를 serializer 루트로 이동 (HWP+HWPX 공용) - examples/hwpx_dump_empty: output/stage1_empty.hwpx 생성용 - 단위 테스트 4개 통과: parse_hwpx 라운드트립, mimetype STORED/최초엔트리
- ref_empty.hwpx — 빈 문서 (111.hwpx) - ref_text.hwpx — '안녕 Hello 123' 1줄 (222.hwpx) - ref_table.hwpx — 2x3 표 포함 (333.hwpx) Stage 1 호환성 검증 + Stage 2~3 구조 역공학 레퍼런스
한컴 레퍼런스(ref_empty.hwpx) 분석 결과 반영:
- static_assets 신설: version.xml, META-INF/container.{xml,rdf}, META-INF/manifest.xml,
settings.xml, Preview/PrvText.txt(CRLF), Preview/PrvImage.png(1x1 투명)
- content.hpf 확장: 14개 네임스페이스 선언 + metadata(opf:language, creator 등)
- section.rs 확장: 1 문단 + full <hp:secPr>(pagePr/margin/footNotePr/endNotePr/
pageBorderFill×3) + <hp:ctrl><hp:colPr> + <hp:linesegarray>
- header.rs 확장: fontfaces(7언어) + 1 charPr/paraPr/borderFill/style/tabPr +
compatibleDocument + docOption
테스트 5개 통과:
- hancom_required_files_present (11개 필수 파일 검증)
- parse_hwpx 라운드트립 2종
- mimetype STORED + 최초 엔트리 검증 2종
빈 문서(1섹션) 출력 시 한컴2020 ref_empty.hwpx의 header.xml(32KB), section0.xml(3340B), version.xml, settings.xml을 include_str!로 직접 사용하여 한컴 호환성 보장. 11개 파일 중 9개 바이트 일치, PrvImage.png(1x1 PNG 대체)과 content.hpf(metadata 일반화)만 차이. Stage 2+에서 IR 기반 동적 생성으로 점진 교체 예정.
한컴2020에서 빈 HWPX 정상 오픈 검증 완료. - 자동 테스트 5/5 통과 - 핵심 XML 9/11 바이트 동일, 2파일 기능적 대체 - Stage 2(본문 문단·텍스트·lineSegArray) 준비 완료
- utils.rs에 xml_escape() 추가 (&, <, >, ", ') - section.rs에서 첫 문단 텍스트를 <hp:t/> 자리에 주입 - 제어문자 있는 문단은 Stage 2.2 전까지 빈 템플릿 유지 - examples/hwpx_dump_text.rs로 시각 검증용 산출 - 한글2020에서 "안녕 Hello 123" 정상 표시 확인 - 단위 테스트 2종 추가 (로운드트립 + escape), 7/7 통과 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- section.rs render_text_run(): \t -> <hp:tab/>, \n -> <hp:lineBreak/> - 한컴 레퍼런스 패턴(<hp:t> 내 혼합 콘텐츠) 채택 - 단위 테스트 tab_and_linebreak_emitted_inline 추가 - stage2_ctrl.hwpx 예제로 시각 검증 - 한계: lineseg 1개뿐이라 시각 줄 나눔 미반영 (Stage 2.3 연기) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
사용자 제공 레퍼런스(ref_mixed.hwpx) 역공학 기반: - Enter -> <hp:p> 여러 개 (하드 문단 경계) - Shift+Enter -> <hp:t> 내 <hp:lineBreak/> 혼합 콘텐츠 - Tab -> <hp:tab width="4000" leader="0" type="1"/> 속성 포함 - vertpos 증분 1600 HWPUNIT (vertsize 1000 + spacing 600) IR 매핑: - section.paragraphs 개수 = 하드 문단 수 - paragraph.text 내 \n = 소프트 브레이크 - paragraph.text 내 \t = 탭 한글2020에서 4문단 + 소프트 브레이크 + 탭 정상 렌더링 확인. 단위 테스트 10/10 통과. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- tools/verify_hwpx.py: 한컴 OLE(pyhwpx) 기반 오픈/텍스트/문단 수 검증 - 보안 팝업은 pyhwpx 내장 FilePathCheckerModule.dll로 자동 회피 - stage2_mixed.hwpx 검증 통과 (4문단 + 소프트 브레이크 + 탭) - 사용: PYTHONIOENCODING=utf-8 python tools/verify_hwpx.py <파일> [--expect-text ...] [--expect-paragraphs N] Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tools/verify_all.py: 모든 stage 산출물을 한 번에 한컴 자동 검증 - stage1_empty (빈 문서) - stage2_text (단일 문단) - stage2_mixed (다문단 + 소프트 브레이크 + 탭) 3/3 통과 확인. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- examples/hwpx_roundtrip.rs: 입력 HWPX -> 파싱 -> 재직렬화 - tools/verify_all.py: rt_ref_mixed.hwpx 검증 케이스 포함 검증된 라운드트립: - ref_mixed.hwpx (4문단): 본문/탭/소프트브레이크 완벽 보존 - 2025년 2분기 해외직접투자 (134KB, 130문단): 한컴 오픈 + 본문 보존, 3페이지 페이지네이션 동작 (표/이미지/스타일은 범위 밖이라 탈락) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- task_m100_164_report.md: 4 stage + 검증 인프라 + 라운드트립 결과 종합 - orders/20260417.md: 오늘할일 등록, Task edwardkim#165/166/167 후속 이슈 제안 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Apr 16, 2026
Owner
|
고생하셨습니다. 덕분에 오늘 패지버전으로 배포할 수 있겠습니다. |
edwardkim
approved these changes
Apr 17, 2026
Owner
edwardkim
left a comment
There was a problem hiding this comment.
로컬 검증 완료 ✅
코드 구조 리뷰:
- 파서(parser::hwpx)의 거울 구조로 깔끔하게 구성
- 테스트 10개로 라운드트립, XML escape, mimetype 순서 등 철저 검증
- OPC 규격 준수 (mimetype STORED, 최초 엔트리)
보안 점검:
- XML Injection: xml_escape() + quick_xml 자동 이스케이프 ✅
- ZIP path traversal: 하드코딩 경로만 사용 ✅
- 메모리 안전: unsafe 없음 ✅
- BinDataEntry.href: 현재 미사용, 후속 구현 시 경로 검증 필요 (주의)
빌드/테스트:
- cargo test: 798개 전체 통과
- cargo clippy: 통과
후속 이슈:
- #176: WASM API 노출 및 사용자 오류 전달
하이퍼-워터폴을 자발적으로 적용한 훌륭한 기여입니다! 🎉
This was referenced Apr 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
\n) + 탭(\t) + XML escape 지원closes #164
주요 변경사항
신규 모듈
src/serializer/hwpx/mod.rs—serialize_hwpx()진입점, ZIP 패키징writer.rs— mimetype STORED + 나머지 DEFLATEDheader.rs— 한컴2020 레퍼런스 템플릿 임베딩 (Stage 2.5에서 IR 기반 동적화 예정)section.rs—<hp:p>다문단,<hp:t>+<hp:tab>+<hp:lineBreak/>동적 생성content.rs—Contents/content.hpfOPF manifeststatic_assets.rs— META-INF/version/Preview 정적 자산templates/*.xml— 한컴 호환 5개 정적 템플릿IR 매핑
section.paragraphs여러 개 → 하드 문단 경계 (<hp:p>여러 개)paragraph.text내\n→<hp:lineBreak/>(소프트 브레이크, 같은 문단 내)paragraph.text내\t→<hp:tab width="4000" leader="0" type="1"/>검증 인프라
tools/verify_hwpx.py— pyhwpx 기반 한컴 자동 오픈/텍스트 검증tools/verify_all.py— 모든 stage 산출물 일괄 검증examples/hwpx_dump_empty|text|roundtrip.rs— 산출 예제단계별 진행 (4 stage)
각 stage별 완료 보고서는
mydocs/working/task_m100_164_stage*.md참조.검증 결과
단위 테스트 — 10/10 통과
한글2020 자동 검증 — 4/4 통과
실문서 라운드트립 (참고)
한계 및 후속 이슈 제안
Test plan
🤖 Generated with Claude Code