한글과컴퓨터의 한/글 문서 파일(.hwp, .hwpx)을 파싱하는 Rust 라이브러리입니다.
본 프로젝트는 한글과컴퓨터의 한/글 문서 파일 형식 공개 문서를 참고하여 개발하였습니다. 공개 문서 다운로드
- HWP 5.0: 바이너리 형식 (Compound File Binary Format)
- HWPX: XML 기반 형식 (OWPML 표준, KS X 6101)
| Format | Status | Notes |
|---|---|---|
| HWP 5.0 | Maintained / frozen | Existing parser support is kept, but new feature work focuses on HWPX. |
| HWPX | Active | Primary target for parser reliability and diagnostics improvements. |
hwp-rs/
├── crates/
│ └── hwp-core/ # 핵심 Rust 라이브러리
│ ├── src/
│ │ ├── lib.rs # 라이브러리 진입점, HwpParser 정의
│ │ ├── cfb.rs # Compound File Binary 파서 (HWP 5.0)
│ │ ├── decompress.rs # zlib 압축 해제
│ │ ├── error.rs # 에러 타입 및 ParseWarnings
│ │ ├── types.rs # 공통 타입 (HWPUNIT, Color 등)
│ │ │
│ │ ├── parser/ # 파일 형식별 파서
│ │ │ ├── mod.rs # 파서 통합 (HWP/HWPX 자동 감지)
│ │ │ ├── detect.rs # 파일 형식 감지
│ │ │ └── hwpx/ # HWPX (XML) 파서
│ │ │ ├── section.rs # 섹션 파싱 (문단, 테이블, 이미지, 하이퍼링크)
│ │ │ ├── header.rs # 문서 정보 파싱 (폰트, 스타일, 문단 모양)
│ │ │ └── bindata.rs # 바이너리 데이터 파싱
│ │ │
│ │ ├── document/ # 문서 구조체 정의
│ │ │ ├── fileheader/ # 파일 헤더 (버전, 플래그)
│ │ │ ├── docinfo/ # 문서 정보 (폰트, 스타일, 번호매기기)
│ │ │ ├── bodytext/ # 본문 (섹션, 문단, 표, 그림)
│ │ │ │ ├── ctrl_header/ # 컨트롤 헤더 (표, 각주, 머리글 등)
│ │ │ │ └── shape_component/ # 도형 (사각형, 선, 이미지 등)
│ │ │ ├── bindata/ # 바이너리 데이터 (이미지, OLE)
│ │ │ └── scripts/ # 문서 스크립트
│ │ │
│ │ └── viewer/ # 출력 변환기
│ │ ├── shared.rs # 공통 유틸리티 (MIME 감지, 이미지 저장)
│ │ ├── markdown/ # Markdown 변환
│ │ └── html/ # HTML 변환 (페이지 레이아웃, SVG 테이블)
│ │
│ └── tests/
│ ├── fixtures/ # 테스트용 HWP/HWPX 파일
│ └── snapshots/ # 스냅샷 테스트 결과
│
└── packages/
└── hwpx-python/ # Python 바인딩
├── src/lib.rs # PyO3 바인딩 코드
├── pyproject.toml # Python 패키지 설정
└── Cargo.toml # Rust 의존성
- HWP/HWPX 문서 파싱
- Markdown 변환
- 테이블 지원 (HTML 테이블 렌더링)
- 중첩 테이블(Nested Table) 지원
- 테이블 셀 내 이미지 렌더링
- 이미지 추출 (base64 또는 파일 저장)
- 하이퍼링크 렌더링
- 밑줄(underline) 렌더링
- 이미지 alt text 커스터마이징
- HTML 변환
- XSS 방지 (텍스트 이스케이프)
- 올바른 charset 선언
- JSON 변환
- 텍스트 추출
- 이미지 추출 (PNG, JPEG, BMP, GIF, WebP, TIFF 지원)
- 파싱 경고 시스템 (
ParseWarnings)
The parser exposes both legacy string warnings and structured diagnostics. Diagnostics identify unsupported elements, recovered invalid values, skipped binary assets, and likely data loss so conversion problems are visible instead of silently ignored.
HWP/HWPX files are treated as untrusted input. The HWPX parser enforces ZIP, XML, and section-level resource limits; rejects unsafe ZIP paths; normalizes binary references; and sanitizes image output extensions. CI runs Rust tests, clippy, formatting, dependency audit, dependency policy checks, CodeQL, Python wheel validation, and packaging smoke tests.
See SECURITY.md and docs/security-model.md for the threat model, resource limits, and vulnerability reporting process.
Parser fuzzing is configured with cargo-fuzz targets for autodetected parsing and
HWPX-specific parsing. See docs/fuzzing.md for target details and
local fuzzing workflow.
Python releases are built as ABI3 wheels and published through PyPI Trusted Publishing. See docs/release.md for release and publishing checks.
CI generates LCOV coverage artifacts with cargo-llvm-cov; see
docs/coverage.md for local reports and review policy.
The repository includes Criterion benchmarks for HWPX parsing and Markdown conversion. CI compiles the benchmark target in test mode to catch performance harness breakage without depending on noisy shared-runner timings. See docs/performance.md for local benchmark workflow and reporting.
pip install hwpxkitimport hwpxkit
# 파일에서 문서 열기
doc = hwpxkit.parse_file("document.hwpx")
# 또는 바이트에서 파싱
with open("document.hwp", "rb") as f:
doc = hwpxkit.parse(f.read())
# 문서 정보
print(doc.version) # 예: "5.1.0.1"
print(doc.section_count) # 섹션 수
print(doc.warnings) # 파싱 경고 목록
# Markdown 변환
markdown = doc.to_markdown()
markdown = doc.to_markdown(
use_html=True, # HTML 태그 사용 (테이블 등)
include_version=True, # 버전 정보 포함
image_output_dir="./images" # 이미지를 파일로 저장 (없으면 base64)
)
# HTML 변환
html = doc.to_html()
html = doc.to_html(image_output_dir="./images")
# JSON 변환
json_str = doc.to_json()
# 텍스트 추출
text = doc.get_text()use hwp_core::{HwpParser, HwpDocument};
use hwp_core::viewer::markdown::{to_markdown, MarkdownOptions};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let data = std::fs::read("document.hwp")?;
let parser = HwpParser::new();
let doc = parser.parse(&data)?;
let options = MarkdownOptions::default();
let markdown = to_markdown(&doc, &options);
println!("{}", markdown);
// 파싱 경고 확인
for warning in doc.warnings.warnings() {
eprintln!("Warning: {}", warning);
}
Ok(())
}# Rust 라이브러리 빌드
cargo build --release
# Python 휠 빌드
cd packages/hwpx-python
pip install maturin
maturin build --release# CI와 동일한 로컬 검사
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace
cargo llvm-cov --workspace --all-features --lcov --output-path lcov.info
cargo bench -p hwp-core --bench parse_benchmark -- --test
cargo check --manifest-path fuzz/Cargo.toml --locked
cargo deny --locked check
cargo audit
cargo audit --file fuzz/Cargo.lock
# 스냅샷 테스트 업데이트
cargo insta accept --workspaceMIT