hwpforge-foundation 0.1.1

Foundation types for HwpForge (HwpUnit, Color, Interned IDs, Branded Index)
Documentation
# HwpForge ๐Ÿ”ฅ

> **Rust๋กœ ํ•œ๊ธ€(HWP/HWPX) ๋ฌธ์„œ๋ฅผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์ œ์–ด**
>
> [Hancom]https://www.hancom.com/ ํ•œ๊ธ€ ํŒŒ์ผ ์ฝ๊ธฐ, ์“ฐ๊ธฐ, ๋ณ€ํ™˜

[![CI](https://img.shields.io/github/actions/workflow/status/ai-screams/HwpForge/ci.yml?branch=main&label=CI&logo=github)](https://github.com/ai-screams/HwpForge/actions/workflows/ci.yml)
[![crates.io](https://img.shields.io/crates/v/hwpforge.svg?logo=rust)](https://crates.io/crates/hwpforge)
[![docs.rs](https://img.shields.io/docsrs/hwpforge?logo=docs.rs)](https://docs.rs/hwpforge)
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](LICENSE-MIT)
[![MSRV](https://img.shields.io/badge/MSRV-1.88+-orange.svg?logo=rust)](Cargo.toml)
[![codecov](https://img.shields.io/badge/coverage-92.65%25-brightgreen.svg?logo=codecov)](https://github.com/ai-screams/HwpForge)
[![Lines of Code](https://img.shields.io/badge/LOC-~49%2C200-informational.svg)](https://github.com/ai-screams/HwpForge)
[![Tests](https://img.shields.io/badge/tests-1%2C510_passed-success.svg?logo=checkmarx)](https://github.com/ai-screams/HwpForge)
[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg?logo=rust)](https://github.com/ai-screams/HwpForge)
[![Security Policy](https://img.shields.io/badge/security-policy-blueviolet.svg?logo=githubactions)](SECURITY.md)
[![Contributing](https://img.shields.io/badge/contributing-guide-blue.svg?logo=handshake)](CONTRIBUTING.md)
[![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-support-yellow.svg?logo=buy-me-a-coffee&logoColor=white)](https://buymeacoffee.com/pignuante)

<div align="center">
<img src="https://raw.githubusercontent.com/ai-screams/HwpForge/main/assets/banner-main.png" alt="HwpForge Banner" width="600">
</div>

---

## HwpForge๋ž€?

HwpForge๋Š” HWPX ๋ฌธ์„œ(ZIP + XML, KS X 6101)๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ **์˜คํ”ˆ์†Œ์Šค** ์ˆœ์ˆ˜ Rust ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. ํ•œ๊ตญ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ์›Œ๋“œํ”„๋กœ์„ธ์„œ์ธ [Hancom ํ•œ๊ธ€](https://www.hancom.com)์˜ ์ตœ์‹  ํฌ๋งท์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

### ์ง€์› ๋ฒ„์ „

| ํ•œ๊ธ€ ๋ฒ„์ „        | ํฌ๋งท         | ์ฝ๊ธฐ    | ์“ฐ๊ธฐ | ์Šคํƒ€์ผ ์„ธํŠธ                    |
| ---------------- | ------------ | ------- | ---- | ------------------------------ |
| ํ•œ๊ธ€ 2014 ~ 2020 | HWPX (.hwpx) | โœ…      | โœ…   | Classic (18 styles)            |
| ํ•œ๊ธ€ 2022 ~ 2024 | HWPX (.hwpx) | โœ…      | โœ…   | Modern (22 styles, **๊ธฐ๋ณธ๊ฐ’**) |
| ํ•œ๊ธ€ 2025+       | HWPX (.hwpx) | โœ…      | โœ…   | Latest (23 styles)             |
| ํ•œ๊ธ€ 97 ~ 2010   | HWP5 (.hwp)  | ๐Ÿ“‹ ์˜ˆ์ • | โ€”    | โ€”                              |

- **HWPX**: OWPML ๊ตญ๊ฐ€ํ‘œ์ค€ (KS X 6101) ๊ธฐ๋ฐ˜, ZIP + XML ์ปจํ…Œ์ด๋„ˆ
- **HWP5**: ๊ตฌํ˜• ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๋งท (v2.0์—์„œ ์ฝ๊ธฐ ์ง€์› ์˜ˆ์ •)
- ์Šคํƒ€์ผ ์„ธํŠธ๋Š” `HancomStyleSet` enum์œผ๋กœ ์„ ํƒ ๊ฐ€๋Šฅ (๊ธฐ๋ณธ: Modern)

**LLM-first ์„ค๊ณ„** ๐Ÿ”ฅ โ€” AI ์นœํ™”์ ์ธ Markdown๊ณผ ๊ณต์‹ ํ•œ๊ธ€ ๋ฌธ์„œ ํฌ๋งท(HWPX), ๋‘ ์„ธ๊ณ„๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ž‡์Šต๋‹ˆ๋‹ค. LLM์ด Markdown์œผ๋กœ ์ž‘์„ฑํ•œ ๋‚ด์šฉ์€ ๊ณต๋ฌธ์„œ ๊ทœ๊ฒฉ์˜ HWPX๋กœ ์ปดํŒŒ์ผ๋˜๊ณ  ๐Ÿ“œ, ๋ฐ˜๋Œ€๋กœ ๊ธฐ์กด HWPX ๋ฌธ์„œ๋Š” AI๊ฐ€ ์‰ฝ๊ฒŒ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋กœ ๊บผ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค โš’๏ธ.

- **HWPX Reader for AI** โ€” ๊ธฐ์กด ํ•œ๊ธ€ ๋ฌธ์„œ(.hwpx)๋ฅผ Markdown์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ LLM์ด ์ฆ‰์‹œ ์ดํ•ด ๊ฐ€๋Šฅ
- **Full HWPX codec** โ€” HWPX ํŒŒ์ผ์„ ์†์‹ค ์—†์ด ๋””์ฝ”๋”ฉ/์ธ์ฝ”๋”ฉ (lossless roundtrip)
- **Markdown bridge** โ€” GFM Markdown๊ณผ HWPX ๊ฐ„ ์–‘๋ฐฉํ–ฅ ๋ณ€ํ™˜ (์ฝ๊ธฐ + ์“ฐ๊ธฐ)
- **YAML style template** โ€” Figma Design Token์ฒ˜๋Ÿผ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์Šคํƒ€์ผ ์ •์˜ (ํฐํŠธ, ํฌ๊ธฐ, ์ƒ‰์ƒ)
- **Type-safe API** โ€” branded index, typestate validation, zero unsafe code

## ๋น ๋ฅธ ์‹œ์ž‘

### ์„ค์น˜

```bash
# Cargo.toml์— ์ถ”๊ฐ€
cargo add hwpforge

# Markdown ์ง€์› ํฌํ•จ
cargo add hwpforge --features full
```

๋˜๋Š” `Cargo.toml`์— ์ง์ ‘ ์ถ”๊ฐ€:

```toml
[dependencies]
hwpforge = "0.1"
```

### ๐Ÿ”จ ๋ฌธ์„œ ์ƒ์„ฑ

```rust
use hwpforge::core::{Document, Draft, Paragraph, Run, Section, PageSettings};
use hwpforge::foundation::{CharShapeIndex, ParaShapeIndex};

let mut doc = Document::<Draft>::new();
doc.add_section(Section::with_paragraphs(
    vec![Paragraph::with_runs(
        vec![Run::text("Hello, ํ•œ๊ธ€!", CharShapeIndex::new(0))],
        ParaShapeIndex::new(0),
    )],
    PageSettings::a4(),
));
```

### โš’๏ธ HWPX๋กœ ์ธ์ฝ”๋”ฉ

```rust
use hwpforge::hwpx::{HwpxEncoder, HwpxStyleStore};
use hwpforge::core::ImageStore;

let validated = doc.validate().unwrap();
let style_store = HwpxStyleStore::with_default_fonts("ํ•จ์ดˆ๋กฌ๋ฐ”ํƒ•");
let image_store = ImageStore::new();
let bytes = HwpxEncoder::encode(&validated, &style_store, &image_store).unwrap();
std::fs::write("output.hwpx", &bytes).unwrap();
```

### โš’๏ธ HWPX ๋””์ฝ”๋”ฉ

```rust
use hwpforge::hwpx::HwpxDecoder;

let result = HwpxDecoder::decode_file("input.hwpx").unwrap();
println!("์„น์…˜ ์ˆ˜: {}", result.document.sections().len());
```

### โš’๏ธ HWPX โ†’ Markdown ๋ณ€ํ™˜ (AI๊ฐ€ ํ•œ๊ธ€ ๋ฌธ์„œ ์ฝ๊ธฐ)

```rust
use hwpforge::hwpx::HwpxDecoder;
use hwpforge::md::MdEncoder;

let decoded = HwpxDecoder::decode_file("government_report.hwpx").unwrap();
let validated = decoded.document.validate().unwrap();
let markdown = MdEncoder::encode_lossy(&validated).unwrap();
println!("{}", markdown); // LLM์ด ๋ฐ”๋กœ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” Markdown
```

๊ธฐ์กด .hwpx ํŒŒ์ผ์„ Markdown์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด Claude, GPT ๋“ฑ ์–ด๋–ค LLM์ด๋“  ํ•œ๊ธ€ ๊ณต๋ฌธ์„œ๋ฅผ ์ฆ‰์‹œ ์ฝ๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

### โš’๏ธ Markdown โ†’ HWPX ๋ณ€ํ™˜

```rust
use hwpforge::md::MdDecoder;
use hwpforge::hwpx::{HwpxEncoder, HwpxStyleStore};

let md_doc = MdDecoder::decode_with_default("# ์ œ๋ชฉ\n\nMarkdown์—์„œ ๋ณ€ํ™˜!").unwrap();
let validated = md_doc.document.validate().unwrap();
let style_store = HwpxStyleStore::from_registry(&md_doc.style_registry);
let image_store = hwpforge::core::ImageStore::new();
let bytes = HwpxEncoder::encode(&validated, &style_store, &image_store).unwrap();
```

## Feature Flags

| Feature | ๊ธฐ๋ณธ๊ฐ’ | ์„ค๋ช…                 |
| ------- | ------ | -------------------- |
| `hwpx`  | Yes    | HWPX encoder/decoder |
| `md`    | โ€”      | Markdown โ†” Core ๋ณ€ํ™˜ |
| `full`  | โ€”      | ๋ชจ๋“  ๊ธฐ๋Šฅ ํฌํ•จ       |

```toml
# Markdown ์ง€์› ํฌํ•จ
hwpforge = { version = "0.1", features = ["full"] }
```

## ๐Ÿ“œ ์ง€์› ์ฝ˜ํ…์ธ 

| ์นดํ…Œ๊ณ ๋ฆฌ      | ์š”์†Œ                                                                 |
| ------------- | -------------------------------------------------------------------- |
| ํ…์ŠคํŠธ        | Run, character shape, paragraph shape, style (22๊ฐœ ํ•œ์ปด ๊ธฐ๋ณธ ์Šคํƒ€์ผ) |
| ๊ตฌ์กฐ          | Table (์ค‘์ฒฉ), Image (๋ฐ”์ด๋„ˆ๋ฆฌ + ๊ฒฝ๋กœ), TextBox, Caption              |
| ๋ ˆ์ด์•„์›ƒ      | ๋‹ค๋‹จ, ํŽ˜์ด์ง€ ์„ค์ •, ๊ฐ€๋กœ/์„ธ๋กœ ๋ฐฉํ–ฅ, ์ œ๋ณธ ์—ฌ๋ฐฑ, master page            |
| ๋จธ๋ฆฌ๊ธ€/๋ฐ”๋‹ฅ๊ธ€ | Header, Footer, ์ชฝ๋ฒˆํ˜ธ (autoNum)                                     |
| ๊ฐ์ฃผ/๋ฏธ์ฃผ     | ๊ฐ์ฃผ, ๋ฏธ์ฃผ                                                           |
| ๋„ํ˜•          | ์„ , ํƒ€์›, ๋‹ค๊ฐํ˜•, ํ˜ธ, ๊ณก์„ , ์—ฐ๊ฒฐ์„  (์ฑ„์›€, ํšŒ์ „, ํ™”์‚ดํ‘œ ์ง€์›)         |
| ์ˆ˜์‹          | HancomEQN script ํ˜•์‹                                                |
| ์ฐจํŠธ          | 18์ข… chart type (OOXML ํ˜ธํ™˜)                                         |
| ์ฐธ์กฐ          | ์ฑ…๊ฐˆํ”ผ, ์ƒํ˜ธ ์ฐธ์กฐ, ํ•„๋“œ (๋‚ ์งœ/์‹œ๊ฐ„/์š”์•ฝ), ๋ฉ”๋ชจ, ์ƒ‰์ธ                 |
| ๋ง๋ง/๊ฒน์นจ     | ๋ง๋ง (dutmal), ๊ธ€์ž ๊ฒน์นจ                                             |
| Markdown      | GFM decode, lossy + lossless encode, YAML frontmatter                |

## ์•„ํ‚คํ…์ฒ˜

```mermaid
%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '14px', 'lineColor': '#BDBDBD'}}}%%
flowchart TD
    subgraph formats["ํฌ๋งท"]
        HF(["๐Ÿ“„ .hwpx<br/>ํ•œ๊ธ€ ํŒŒ์ผ"]):::file
        MF(["๐Ÿ“ .md<br/>Markdown"]):::file
    end

    subgraph smithy["โš’๏ธ Smithy โ€” ํฌ๋งท ๋ณ€ํ™˜๊ธฐ"]
        SH["hwpforge-smithy-hwpx"]:::smithy
        SM["hwpforge-smithy-md"]:::smithy
    end

    C["๐Ÿ”จ hwpforge-core<br/>ํฌ๋งท ๋…๋ฆฝ ๋ฌธ์„œ ๋ชจ๋ธ (IR)"]:::core
    BP["๐Ÿ“ hwpforge-blueprint<br/>YAML ์Šคํƒ€์ผ ยท ํฐํŠธ ยท ์ƒ‰์ƒ"]:::blueprint
    F["๐Ÿ”ฉ hwpforge-foundation<br/>HwpUnit ยท Color ยท Index"]:::foundation

    HF <--> SH
    MF <--> SM
    SH & SM <--> C
    BP --> SH & SM
    F --> C & BP

    classDef file     fill:#FFFDE7,stroke:#F9A825,color:#5D4037
    classDef smithy   fill:#FFF3E0,stroke:#FB8C00,color:#E65100
    classDef core     fill:#E3F2FD,stroke:#42A5F5,color:#0D47A1
    classDef blueprint fill:#F3E5F5,stroke:#AB47BC,color:#4A148C
    classDef foundation fill:#FAFAFA,stroke:#BDBDBD,color:#424242
```

**ํ•ต์‹ฌ ์›์น™**: ๊ตฌ์กฐ(Structure)์™€ ์Šคํƒ€์ผ(Style)์˜ ๋ถ„๋ฆฌ โ€” HTML + CSS์™€ ๊ฐ™์€ ํŒจํ„ด์ž…๋‹ˆ๋‹ค.
Core๋Š” ์Šคํƒ€์ผ _์ฐธ์กฐ_(index)๋งŒ ๊ฐ€์ง€๊ณ , Blueprint๋Š” ์Šคํƒ€์ผ _์ •์˜_(ํฐํŠธ, ํฌ๊ธฐ, ์ƒ‰์ƒ)๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
Smithy compiler๊ฐ€ Core + Blueprint๋ฅผ ํ•ฉ์ณ ์ตœ์ข… ํฌ๋งท์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

## ํ”„๋กœ์ ํŠธ ํ˜„ํ™ฉ

| ์ง€ํ‘œ        | ๊ฐ’                      |
| ----------- | ----------------------- |
| ์ด LOC      | ~49,200                 |
| ํ…Œ์ŠคํŠธ      | 1,510๊ฐœ (cargo-nextest) |
| ์†Œ์Šค ํŒŒ์ผ   | 92 .rs                  |
| Crate ์ˆ˜    | 9๊ฐœ (6๊ฐœ ๋ฐฐํฌ)          |
| ์ปค๋ฒ„๋ฆฌ์ง€    | 92.65%                  |
| Clippy ๊ฒฝ๊ณ  | 0                       |
| Unsafe ์ฝ”๋“œ | 0                       |

## ๊ฐœ๋ฐœ

### ํ•„์ˆ˜ ์š”๊ตฌ์‚ฌํ•ญ

- Rust 1.88+ (MSRV)
- (๊ถŒ์žฅ) [cargo-nextest]https://nexte.st/ โ€” ๋ณ‘๋ ฌ ํ…Œ์ŠคํŠธ ์‹คํ–‰
- (์„ ํƒ) [pre-commit]https://pre-commit.com/ โ€” git hook ์ž๋™ํ™”

### MSRV ์ •์ฑ…

- ํ˜„์žฌ MSRV๋Š” **Rust 1.88**์ž…๋‹ˆ๋‹ค.
- HwpForge๋Š” **stable์—์„œ 4 ๋ฆด๋ฆฌ์Šค ๋’ค์ฒ˜์ง„ ๋ฒ„์ „**์„ ๊ธฐ๋ณธ MSRV ์ •์ฑ…์œผ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
- `Cargo.toml`์˜ `rust-version`์ด ๋‹จ์ผ ์ง„์‹ค์›์ด๋ฉฐ, CI์˜ `Verify โ€บ MSRV` job์ด ์ด ๊ณ„์•ฝ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.
- MSRV ์ƒํ–ฅ์ด ํ•„์š”ํ•˜๋ฉด PR์—์„œ ์ด์œ ๋ฅผ ๋ช…์‹œํ•˜๊ณ , `Cargo.toml`, CI, CHANGELOG๋ฅผ ํ•จ๊ป˜ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
- ๊ฐœ๋ฐœ์šฉ ๊ธฐ๋ณธ ํˆด์ฒด์ธ์€ ๋” ์ตœ์‹ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜ธํ™˜์„ฑ ํŒ๋‹จ ๊ธฐ์ค€์€ ์ตœ์‹  stable์ด ์•„๋‹ˆ๋ผ **MSRV + CI ํ†ต๊ณผ ์—ฌ๋ถ€**์ž…๋‹ˆ๋‹ค.

### โš’๏ธ ๋ช…๋ น์–ด

```bash
make ci          # fmt + clippy + test + deny + lint (CI์™€ ๋™์ผ)
make test        # cargo nextest run
make clippy      # cargo clippy (๋ชจ๋“  target, ๋ชจ๋“  feature, -D warnings)
make fmt-fix     # rustfmt ์ž๋™ ํฌ๋งท
make doc         # rustdoc ์ƒ์„ฑ (๋ธŒ๋ผ์šฐ์ €์—์„œ ์—ด๋ฆผ)
make cov         # coverage ๋ฆฌํฌํŠธ (90% gate)
```

### ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

```
HwpForge/
โ”œโ”€โ”€ crates/
โ”‚   โ”œโ”€โ”€ hwpforge/                 # Umbrella crate (re-exports)
โ”‚   โ”œโ”€โ”€ hwpforge-foundation/      # ๊ธฐ๋ณธ ํƒ€์ž… (HwpUnit, Color, Index<T>)
โ”‚   โ”œโ”€โ”€ hwpforge-core/            # ๋ฌธ์„œ ๋ชจ๋ธ (์Šคํƒ€์ผ ์ฐธ์กฐ๋งŒ)
โ”‚   โ”œโ”€โ”€ hwpforge-blueprint/       # YAML ํ…œํ”Œ๋ฆฟ (Figma ํŒจํ„ด)
โ”‚   โ”œโ”€โ”€ hwpforge-smithy-hwpx/     # HWPX codec (ZIP+XML โ†” Core)
โ”‚   โ”œโ”€โ”€ hwpforge-smithy-md/       # Markdown codec (MD โ†” Core)
โ”‚   โ”œโ”€โ”€ hwpforge-smithy-hwp5/     # HWP5 decoder (์˜ˆ์ •)
โ”‚   โ”œโ”€โ”€ hwpforge-bindings-py/     # Python bindings (์˜ˆ์ •)
โ”‚   โ””โ”€โ”€ hwpforge-bindings-cli/    # CLI ๋„๊ตฌ (์˜ˆ์ •)
โ”œโ”€โ”€ tests/                        # ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ + golden fixture
โ””โ”€โ”€ examples/                     # ๐Ÿ“œ ์‚ฌ์šฉ ์˜ˆ์ œ + ์ƒ์„ฑ๋œ HWPX ํŒŒ์ผ
```

## ๊ธฐ์—ฌ

๋ฒ„๊ทธ ์ˆ˜์ •, ํฌ๋งท ๋ฆฌ์„œ์น˜, ํ…Œ์ŠคํŠธ ๋ณด๊ฐ•, ๋ฌธ์„œ ๊ฐœ์„  ๋ชจ๋‘ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

- ์‹œ์ž‘ ์ „ ๊ฐ€์ด๋“œ: [CONTRIBUTING.md]CONTRIBUTING.md
- ํŠนํžˆ ํ™•์ธํ•  ๊ฒƒ: release-plz๊ฐ€ ์“ฐ๋Š” ์ปค๋ฐ‹ prefix (`feat`, `fix`, `perf`, `refactor`)
- ํŠนํžˆ ํ™•์ธํ•  ๊ฒƒ: MSRV ์ •์ฑ…๊ณผ dependency/MSRV ์ƒ์Šน ๊ธฐ์ค€
- ํŠนํžˆ ํ™•์ธํ•  ๊ฒƒ: ๋ฌธ์„œ ๋ณ€๊ฒฝ ์‹œ `mdbook build`์™€ markdown lint ๊ฒ€์ฆ
- ํŠนํžˆ ํ™•์ธํ•  ๊ฒƒ: CI required checks๋ฅผ ๊นจ์ง€ ์•Š๋Š” ๋ฒ”์œ„์—์„œ์˜ ๋ณ€๊ฒฝ ๋ถ„๋ฆฌ

## ๋กœ๋“œ๋งต

### ์ถœ์‹œ ์˜ˆ์ •

- [ ] HWP5 ์ฝ๊ธฐ โ€” ๊ตฌํ˜• ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๋งท(`.hwp`) ๋””์ฝ”๋”
- [ ] MCP ์„œ๋ฒ„ โ€” Claude, GPT ๋“ฑ LLM์ด tool๋กœ ์ง์ ‘ HWPX ์ƒ์„ฑ
- [ ] CLI ๋„๊ตฌ โ€” `hwpforge convert doc.md doc.hwpx` ํ•œ ์ค„ ๋ณ€ํ™˜

- [ ] HWPX ์™„์ „ ์ง€์› โ€” ์–‘์‹ ์ปจํŠธ๋กค, ๋ณ€๊ฒฝ ์ถ”์ , OLE ๊ฐ์ฒด
- [ ] Python ๋ฐ”์ธ๋”ฉ โ€” `pip install hwpforge`๋กœ ์„ค์น˜, PyPI ๋ฐฐํฌ

## ๋ผ์ด์„ ์Šค

๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE)
- MIT license ([LICENSE-MIT]LICENSE-MIT)

## Acknowledgements

HwpForge๋Š” ๊ฑฐ์ธ๋“ค์˜ ์–ด๊นจ ์œ„์— ์„œ ์žˆ์Šต๋‹ˆ๋‹ค.

- **[Hancom]https://www.hancom.com** โ€” HWPX ํฌ๋งท์˜ ๊ณต๊ฐœ ๋ฌธ์„œ์™€ [KS X 6101 (OWPML)]https://www.kssn.net/ ๊ตญ๊ฐ€ ํ‘œ์ค€์ด ์—†์—ˆ๋‹ค๋ฉด ์ด ํ”„๋กœ์ ํŠธ๋Š” ์‹œ์ž‘์กฐ์ฐจ ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ํฌ๋งท์„ ๊ณต๊ฐœํ•ด ์ฃผ์‹  Hancom์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

- **[openhwp]https://github.com/openhwp/openhwp** โ€” Rust๋กœ HWP/HWPX๋ฅผ ๋‹ค๋ฃจ๋Š” IR ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„์—์„œ ํฐ ์˜๊ฐ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. HwpForge์˜ Core ๋ ˆ์ด์–ด๊ฐ€ ์กด์žฌํ•  ์ˆ˜ ์žˆ์—ˆ๋˜ ๊ฒƒ์€ openhwp์ด ๋จผ์ € ๊ทธ ๊ธธ์„ ๊ฑธ์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

- **[hwpxlib]https://github.com/neolord0/hwpxlib** โ€” Java๋กœ ์ž‘์„ฑ๋œ ๊ฐ€์žฅ ์„ฑ์ˆ™ํ•œ HWPX ๊ตฌํ˜„์ฒด์ž…๋‹ˆ๋‹ค. ์ŠคํŽ™๊ณผ ์‹ค์ œ ๋™์ž‘์˜ ์ฐจ์ด๋ฅผ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ๊ฒฐ์ •์ ์ธ ์ฐธ๊ณ ๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

- **[hwp.js]https://github.com/hahnlee/hwp.js** โ€” HWP5 ํฌ๋งท์˜ quirks์™€ edge case๋ฅผ ๊ผผ๊ผผํžˆ ๋ฌธ์„œํ™”ํ•œ ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค. ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๋งท์˜ ์–ด๋‘์šด ๊ตฌ์„์„ ๋ฐํ˜€ ์ค€ ๋•๋ถ„์— ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ํฌ๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

- **[hwpx-owpml-model]https://github.com/hancom-io/hwpx-owpml-model** โ€” Hancom์ด ์ง์ ‘ ๊ณต๊ฐœํ•œ C++ OWPML ๋ชจ๋ธ ๊ตฌํ˜„์ฒด๋กœ, ์Šคํ‚ค๋งˆ ํ•ด์„์˜ ์ตœ์ข… ๊ธฐ์ค€์œผ๋กœ ์‚ผ์•˜์Šต๋‹ˆ๋‹ค.

- **Rust ์ƒํƒœ๊ณ„** โ€” [serde]https://serde.rs, [quick-xml]https://github.com/tafia/quick-xml, [pulldown-cmark]https://github.com/pulldown-cmark/pulldown-cmark, [zip]https://github.com/zip-rs/zip2 ๋“ฑ ๋›ฐ์–ด๋‚œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค ๋•๋ถ„์— HwpForge ์ „์ฒด๋ฅผ zero unsafe ์ˆœ์ˆ˜ Rust๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. Rust ์ปค๋ฎค๋‹ˆํ‹ฐ์™€ Ferris ๐Ÿฆ€์—๊ฒŒ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

- **[Claude]https://claude.ai by [Anthropic]https://www.anthropic.com** โ€” HwpForge์˜ ์„ค๊ณ„, ๊ตฌํ˜„, ํ…Œ์ŠคํŠธ, ๋ฌธ์„œํ™” ์ „ ๊ณผ์ •์—์„œ Claude Code๊ฐ€ ๊ฐœ๋ฐœ ํŒŒํŠธ๋„ˆ๋กœ ํ•จ๊ป˜ํ–ˆ์Šต๋‹ˆ๋‹ค. LLM-first๋ฅผ ํ‘œ๋ฐฉํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋‹ต๊ฒŒ, AI์™€ ์‚ฌ๋žŒ์ด ํ˜‘์—…ํ•˜์—ฌ ๋งŒ๋“ค์–ด๋‚ธ ๊ฒฐ๊ณผ๋ฌผ์ž…๋‹ˆ๋‹ค.

---

<div align="center">
<img src="https://raw.githubusercontent.com/ai-screams/HwpForge/main/assets/mascot-main.png" width="260" alt="์‡ ๋ถ€๋ฆฌ (SoeBuri)">

<br/><br/>

<strong>์‡ ๋ถ€๋ฆฌ (SoeBuri)</strong><br/>
<em>ํ•œ์ปด ๋ฌธ์„œ๋ฅผ ๋ถˆ์— ๋‹ฌ๊ตฌ์–ด ๋‹จ๋‹จํ•˜๊ฒŒ ๋ฒผ๋ ค๋‚ด๋Š” ๋Œ€์žฅ์žฅ์ด ์˜ค๋ฆฌ๋„ˆ๊ตฌ๋ฆฌ ๐Ÿ”ฅ</em>

<br/><br/>

<a href="https://buymeacoffee.com/pignuante">
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me a Coffee" height="50" width="217">
</a>

</div>