### Successful Build Output
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/getting-started/installation.md
Example output indicating a successful build after adding HwpForge. This confirms the installation is complete.
```text
Compiling hwpforge v0.1.0
Finished `dev` profile [unoptimized + debuginfo] target(s) in ...
```
--------------------------------
### Create HwpxStyleStore with Default Fonts
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/style-templates.md
Initialize an `HwpxStyleStore` using the 'Modern' Hancom style set and a specified default font. This is a convenient way to get a pre-configured style store.
```rust
use hwpforge_smithy_hwpx::{HwpxStyleStore, HancomStyleSet};
// 기본값 (간단한 방법)
let modern = HwpxStyleStore::with_default_fonts("함초롬바탕");
// 특정 스타일셋 지정
// from_registry_with()로 커스텀 레지스트리 + 스타일셋 조합 가능
```
--------------------------------
### Install HwpForge CLI (Hammer)
Source: https://github.com/ai-screams/hwpforge/blob/main/README.md
Install the HwpForge command-line interface tool, named 'Hammer', to manage HWP/HWPX documents directly from the terminal.
```bash
cargo install hwpforge-bindings-cli
```
--------------------------------
### Full Pipeline: Markdown String to HWPX File
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/markdown-bridge.md
This example demonstrates the complete process of converting a Markdown string to an HWPX file. It includes decoding Markdown, validating the document, applying default styles, and encoding to HWPX bytes, which are then written to a file.
```rust
use hwpforge::md::{MdDecoder, MdDocument};
use hwpforge::hwpx::{HwpxEncoder, HwpxStyleStore};
fn markdown_to_hwpx(markdown: &str, output_path: &str) {
// 1. Markdown 파싱 → Core DOM
let MdDocument { document, .. } = MdDecoder::decode_with_default(markdown).unwrap();
// 2. 문서 검증
let validated = document.validate().unwrap();
// 3. 한컴 기본 스타일 적용 후 HWPX 인코딩
let style_store = HwpxStyleStore::with_default_fonts("함초롬바탕");
let image_store = Default::default();
let bytes = HwpxEncoder::encode(&validated, &style_store, &image_store).unwrap();
// 4. 파일 저장
std::fs::write(output_path, &bytes).unwrap();
println!("저장 완료: {output_path}");
}
fn main() {
let md = r#"---
title: AI 활용 정책 제안서
author: 정책팀
date: 2026-03-06
---
# 제안 배경
인공지능 기술의 급속한 발전에 대응하여 정책 수립이 필요합니다.
## 현황 분석
국내외 AI 활용 사례를 분석하였습니다.
## 정책 방향
단계적 도입과 윤리적 기준 마련을 제안합니다.
"#;
markdown_to_hwpx(md, "proposal.hwpx");
}
```
--------------------------------
### Register HWPForge with Claude Code (npm)
Source: https://github.com/ai-screams/hwpforge/blob/main/README.md
Install and register the HWPForge MCP server using npm. This is the recommended method as it automatically downloads the binary without requiring a Rust toolchain.
```bash
claude mcp add hwpforge -- npx -y @hwpforge/mcp
```
--------------------------------
### Process Legacy HWP5 Files
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/text-extraction.md
Handle legacy HWP5 (.hwp) files using the dedicated crate. This example iterates through sections, paragraphs, and runs to extract text content from a legacy HWP5 document.
```rust
use hwpforge_smithy_hwp5::Hwp5Decoder;
use hwpforge_core::run::RunContent;
let result = Hwp5Decoder::decode_file("legacy.hwp").unwrap();
let doc = &result.document;
for section in doc.sections() {
for paragraph in §ion.paragraphs {
for run in ¶graph.runs {
if let RunContent::Text(ref text) = run.content {
print!("{}", text);
}
}
println!();
}
}
```
--------------------------------
### GitHub README Banner Example
Source: https://github.com/ai-screams/hwpforge/blob/main/branding/BRANDING.md
Markdown snippet for displaying the main banner image in a GitHub README. Ensure the image path is correct.
```markdown
한글 문서를 코드로 벼려내다
Forge Korean Documents with Code
```
--------------------------------
### HWPX Formula Example (HancomEQN)
Source: https://github.com/ai-screams/hwpforge/blob/main/examples/interop/hwpx_md_convert/hwpx2md/full_report.md
Illustrates a mathematical formula using the HancomEQN format, which is specific to HWPX documents. Note that this format does not use standard MathML.
```text
x=\frac{-b+-root{2}of{b^{2}-4 ac}}{2 a}
```
--------------------------------
### Badge Combination Example for Crates.io and License
Source: https://github.com/ai-screams/hwpforge/blob/main/branding/BRANDING.md
Markdown snippet for creating badges to display on project pages, linking to the crates.io page and the license file. The colors are derived from the project's color palette.
```markdown
[](https://crates.io/crates/hwpforge)
[](LICENSE)
```
--------------------------------
### Complete HWPX Document Read-Modify-Save Example
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/hwpx-codec.md
Demonstrates a full workflow: decoding an HWPX file, modifying existing text (e.g., replacing '초안' with '최종본'), adding a new paragraph, validating the document, encoding it, and saving to a specified output file. This function handles potential errors during decoding, validation, and encoding.
```rust
use hwpforge_smithy_hwpx::{HwpxDecoder, HwpxEncoder};
use hwpforge_core::run::{Run, RunContent};
use hwpforge_core::paragraph::Paragraph;
use hwpforge_foundation::{CharShapeIndex, ParaShapeIndex};
fn modify_document(
input: &str,
output: &str,
) -> Result<(), Box> {
// 읽기
let mut result = HwpxDecoder::decode_file(input)
.map_err(|e| format!("디코딩 실패: {e}"))?;
let sections = result.document.sections_mut();
// 기존 텍스트 수정
for section in sections.iter_mut() {
for paragraph in &mut section.paragraphs {
for run in &mut paragraph.runs {
if let RunContent::Text(ref mut text) = run.content {
*text = text.replace("초안", "최종본");
}
}
}
}
// 새 문단 추가
if let Some(first_section) = result.document.sections_mut().first_mut() {
first_section.paragraphs.push(Paragraph::with_runs(
vec![Run::text("— 이 문서는 자동으로 수정되었습니다.", CharShapeIndex::new(0))],
ParaShapeIndex::new(0),
));
}
// 저장
let validated = result.document.validate()
.map_err(|e| format!("검증 실패: {e}"))?;
let bytes = HwpxEncoder::encode(&validated, &result.style_store, &result.image_store)
.map_err(|e| format!("인코딩 실패: {e}"))?;
std::fs::write(output, &bytes)?;
Ok(())
}
```
--------------------------------
### Create a New HWP Document
Source: https://github.com/ai-screams/hwpforge/blob/main/README.md
Demonstrates creating a new HWP document with a simple text run using the HWPForge Rust library. Ensure necessary imports are included.
```rust
use hwpforge::core::{Document, Draft, Paragraph, Run, Section, PageSettings};
use hwpforge::foundation::{CharShapeIndex, ParaShapeIndex};
let mut doc = Document::::new();
doc.add_section(Section::with_paragraphs(
vec![Paragraph::with_runs(
vec![Run::text("Hello, 한글!", CharShapeIndex::new(0))],
ParaShapeIndex::new(0),
)],
PageSettings::a4(),
));
```
--------------------------------
### Update Rust Toolchain
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/getting-started/installation.md
Update your Rust installation using rustup if your current version is below the minimum requirement.
```bash
rustup update stable
```
--------------------------------
### Build Project
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/getting-started/installation.md
Compile your project to ensure the HwpForge dependency is correctly integrated and the build is successful.
```bash
cargo build
```
--------------------------------
### Update/Delete HWPForge (Cargo)
Source: https://github.com/ai-screams/hwpforge/blob/main/README.md
Instructions for updating or uninstalling HWPForge when installed via Cargo. npm users do not need separate update commands.
```bash
cargo install hwpforge-bindings-mcp --force
```
```bash
cargo uninstall hwpforge-bindings-mcp
```
--------------------------------
### Register HWPForge with Claude Code (Cargo)
Source: https://github.com/ai-screams/hwpforge/blob/main/README.md
Install HWPForge using Cargo and register it with Claude Code. This method is suitable for Rust developers.
```bash
cargo install hwpforge-bindings-mcp && claude mcp add hwpforge hwpforge-mcp
```
--------------------------------
### Add HwpForge with All Features
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/getting-started/installation.md
Enable all available features of the HwpForge library by specifying the 'full' feature flag.
```toml
[dependencies]
hwpforge = { version = "0.1", features = ["full"] }
```
--------------------------------
### Create HwpxStyleStore with Default Fonts
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/hwpx-codec.md
Quickly create a `HwpxStyleStore` using a single font name. This is the simplest method for basic styling.
```rust
use hwpforge::hwpx::HwpxStyleStore;
let style_store = HwpxStyleStore::with_default_fonts("함초롬바탕");
```
--------------------------------
### CLI Format Conversion and Inspection
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/format-pipeline.md
Demonstrates CLI commands for converting Markdown to HWPX, inspecting HWPX documents with JSON output, and performing a roundtrip conversion from HWPX to JSON and back.
```bash
# Markdown → HWPX 변환
hwpforge convert report.md -o report.hwpx
# HWPX 문서 검사 (메타데이터 포함)
hwpforge inspect report.hwpx --json
# HWPX → JSON → 편집 → HWPX 라운드트립
hwpforge to-json report.hwpx -o report.json
# (AI 에이전트가 JSON 편집)
hwpforge from-json report.json -o updated.hwpx
# HWPX → Markdown (읽기용)
# Rust API: MdEncoder::encode_lossy(&validated)
```
--------------------------------
### Create and Save HWPX Document in Rust
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/README.md
Demonstrates the basic workflow of creating a new HWPX document, adding text, validating it, and saving it to a file using the HwpForge library. Ensure you have the necessary dependencies added to your Cargo.toml.
```rust
use hwpforge::core::{Document, Draft, Paragraph, Run, Section, PageSettings};
use hwpforge::foundation::{CharShapeIndex, ParaShapeIndex};
use hwpforge::hwpx::{HwpxEncoder, HwpxStyleStore};
use hwpforge::core::ImageStore;
// 1. 문서 생성
let mut doc = Document::::new();
doc.add_section(Section::with_paragraphs(
vec![Paragraph::with_runs(
vec![Run::text("안녕하세요, HwpForge!", CharShapeIndex::new(0))],
ParaShapeIndex::new(0),
)],
PageSettings::a4(),
));
// 2. 검증 + 인코딩
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();
// 3. 파일 저장
std::fs::write("output.hwpx", &bytes).unwrap();
```
--------------------------------
### HWPX and Markdown to Core DOM Conversion and Processing
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/format-pipeline.md
Demonstrates converting HWPX and Markdown files into a common Core DOM representation for independent processing. Shows how to access document metadata and content structure.
```rust
use hwpforge::hwpx::{HwpxDecoder, HwpxEncoder, HwpxRegistryBridge};
use hwpforge::md::{MdDecoder, MdDocument, MdEncoder};
use hwpforge::core::{Document, Draft, ImageStore};
// === 1. HWPX → Core DOM ===
let hwpx_result = HwpxDecoder::decode_file("input.hwpx").unwrap();
let doc_from_hwpx: Document = hwpx_result.document;
// === 2. Markdown → Core DOM ===
let markdown = "# 제목\n\n본문 내용입니다.";
let MdDocument { document: doc_from_md, style_registry } =
MdDecoder::decode_with_default(markdown).unwrap();
// === 3. 포맷 독립 처리 (어느 소스에서 왔든 동일) ===
fn process_document(doc: &Document) {
// 메타데이터 접근
let meta = doc.metadata();
println!("제목: {:?}", meta.title);
println!("작성자: {:?}", meta.author);
// 섹션/문단 순회
for section in doc.sections() {
println!("문단 수: {}", section.paragraphs.len());
let counts = section.content_counts();
println!("표: {}, 이미지: {}", counts.tables, counts.images);
}
}
process_document(&doc_from_hwpx);
process_document(&doc_from_md);
// === 4. Core DOM → 다른 포맷으로 출력 ===
// HWPX로 저장
let bridge = HwpxRegistryBridge::from_registry(&style_registry).unwrap();
let rebound = bridge.rebind_draft_document(doc_from_md).unwrap();
let validated = rebound.validate().unwrap();
let bytes = HwpxEncoder::encode(&validated, bridge.style_store(), &ImageStore::new()).unwrap();
std::fs::write("output.hwpx", &bytes).unwrap();
// Markdown으로 저장
let markdown_out = MdEncoder::encode_lossy(&validated).unwrap();
std::fs::write("output.md", &markdown_out).unwrap();
```
--------------------------------
### Handling Unicode Characters in HWPForge
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/hwpx-codec.md
Demonstrates that HWPForge internally uses UTF-8 and fully supports all Unicode characters, including Korean text, emojis, and special symbols. Examples show the creation of `Run` objects with various types of Unicode text.
```rust
use hwpforge::core::run::Run;
use hwpforge::foundation::CharShapeIndex;
// 모두 정상 동작
let run1 = Run::text("한글 텍스트 테스트", CharShapeIndex::new(0));
let run2 = Run::text("특수문자: ©®™ §¶ ±×÷", CharShapeIndex::new(0));
let run3 = Run::text("수학 기호: α β γ δ ∑ ∫", CharShapeIndex::new(0));
```
--------------------------------
### Ensuring Document Validity with Sections
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/hwpx-codec.md
Explains that a `Document` requires at least one section to pass validation. The example demonstrates creating a new document, showing that validation fails for an empty document, but succeeds after adding a section containing an empty paragraph.
```rust
use hwpforge::core::{Document, Draft, PageSettings, Paragraph, Section};
use hwpforge::foundation::ParaShapeIndex;
let mut doc = Document::::new();
// ❌ 빈 문서 — validate() 실패
// let validated = doc.validate(); // Err: 섹션 없음
// ✅ 빈 문단이라도 하나 추가
doc.add_section(Section::with_paragraphs(
vec![Paragraph::new(ParaShapeIndex::new(0))],
PageSettings::a4(),
));
let validated = doc.validate().unwrap(); // OK
```
--------------------------------
### Process Legacy HWP5 Files
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/migration-strategy.md
Handles legacy HWP5 files by either using the HwpForge CLI for direct conversion/auditing or by integrating with the `hwpforge-smithy-hwp5` crate to decode HWP5 files and reuse the existing Core/HWPX pipeline. Separating HWP5 files into a distinct queue is recommended for large-scale migrations.
```rust
// 현재 — HWP5 직접 decode 후 기존 pipeline에 연결
// use hwpforge_smithy_hwp5::Hwp5Decoder;
//
// let result = Hwp5Decoder::decode_file("legacy.hwp")?;
// let validated = result.document.validate()?;
// let markdown = MdEncoder::encode_lossy(&validated)?;
```
--------------------------------
### Run HwpForge Benchmarks
Source: https://github.com/ai-screams/hwpforge/blob/main/benches/README.md
Execute the benchmarks using Cargo. Results are generated in the target/criterion/ directory.
```bash
cargo bench
```
--------------------------------
### Error Handling with HwpxResult
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/hwpx-codec.md
Illustrates how to handle potential errors returned by HWPForge functions, which typically return `HwpxResult`. The example shows a `match` statement to differentiate between successful decoding (`Ok`) and failure (`Err`), printing appropriate messages to standard output or standard error.
```rust
use hwpforge::hwpx::HwpxDecoder;
match HwpxDecoder::decode_file("missing.hwpx") {
Ok(_result) => println!("디코딩 성공"),
Err(e) => eprintln!("디코딩 실패: {e}"),
}
```
--------------------------------
### HWP5 Conversion using CLI
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/format-pipeline.md
Command-line interface commands for converting HWP5 files to HWPX, auditing HWP5 files, and performing a census of HWP5 files.
```bash
hwpforge convert-hwp5 legacy.hwp -o converted.hwpx
hwpforge audit-hwp5 legacy.hwp converted.hwpx
hwpforge census-hwp5 legacy.hwp --json
```
--------------------------------
### Create HwpxStyleStore from Blueprint Template
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/hwpx-codec.md
Generate a `HwpxStyleStore` by converting a custom YAML style template using `StyleRegistry` and `HwpxRegistryBridge`. This is for advanced custom styling.
```rust
use hwpforge::blueprint::builtins::builtin_default;
use hwpforge::blueprint::registry::StyleRegistry;
use hwpforge::hwpx::HwpxRegistryBridge;
let template = builtin_default().unwrap();
let registry = StyleRegistry::from_template(&template).unwrap();
let bridge = HwpxRegistryBridge::from_registry(®istry).unwrap();
let style_store = bridge.style_store();
```
--------------------------------
### Programmatically Setting Metadata
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/metadata.md
Illustrates how to programmatically set metadata for a document in the `Document` state using `metadata_mut()` or `set_metadata()`. Also shows adding content and validating the document.
```rust
use hwpforge::core::{Document, Draft, Metadata, PageSettings, Paragraph, Run, Section};
use hwpforge::foundation::{CharShapeIndex, ParaShapeIndex};
let mut doc = Document::::new();
doc.metadata_mut().title = Some("제안서".to_string());
doc.metadata_mut().author = Some("홍길동".to_string());
doc.metadata_mut().created = Some("2026-03-06".to_string());
doc.metadata_mut().subject = Some("신규 사업 제안".to_string());
doc.metadata_mut().keywords = vec!["사업".to_string(), "제안".to_string()];
let meta = Metadata {
title: Some("제안서".to_string()),
author: Some("홍길동".to_string()),
created: Some("2026-03-06".to_string()),
..Metadata::default()
};
doc.set_metadata(meta);
doc.add_section(Section::with_paragraphs(
vec![Paragraph::with_runs(
vec![Run::text("본문 내용", CharShapeIndex::new(0))],
ParaShapeIndex::new(0),
)],
PageSettings::a4(),
));
let validated = doc.validate().unwrap();
```
--------------------------------
### Create Column Chart in HWP
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/charts.md
Generates a column chart with sales data and saves it as an HWPX file. Ensure to use default fonts for compatibility.
```rust
use hwpforge_core::control::Control;
use hwpforge_core::chart::{ChartType, ChartData, ChartGrouping, LegendPosition};
use hwpforge_core::run::Run;
use hwpforge_core::paragraph::Paragraph;
use hwpforge_core::{Document, Section, PageSettings};
use hwpforge_smithy_hwpx::{HwpxEncoder, HwpxStyleStore};
use hwpforge_foundation::{CharShapeIndex, ParaShapeIndex, HwpUnit};
let data = ChartData::category(
&["2022", "2023", "2024", "2025"],
&[
("국내 매출", &[3200.0, 4100.0, 5300.0, 6800.0]),
("해외 매출", &[1100.0, 1800.0, 2700.0, 3900.0]),
],
);
let chart = Control::Chart {
chart_type: ChartType::Column,
data,
title: Some("연도별 매출 현황 (단위: 백만원)".to_string()),
legend: LegendPosition::Bottom,
grouping: ChartGrouping::Clustered,
width: HwpUnit::from_mm(140.0).unwrap(),
height: HwpUnit::from_mm(90.0).unwrap(),
};
let mut doc = Document::new();
doc.add_section(Section::with_paragraphs(
vec![Paragraph::with_runs(
vec![Run::control(chart, CharShapeIndex::new(0))],
ParaShapeIndex::new(0),
)],
PageSettings::a4(),
));
let validated = doc.validate().unwrap();
let bytes = HwpxEncoder::encode(
&validated,
&HwpxStyleStore::with_default_fonts("함초롬바탕"),
&Default::default(),
).unwrap();
std::fs::write("bar_chart.hwpx", &bytes).unwrap();
```
--------------------------------
### HwpForge Architecture Overview
Source: https://github.com/ai-screams/hwpforge/blob/main/CONTRIBUTING.md
This diagram illustrates the layered architecture of HwpForge, from foundational primitives to user-facing bindings. Structure and Style are kept separate, similar to HTML and CSS.
```text
foundation (primitives: HwpUnit, Color, Index)
|
core (format-independent document model, style references only)
|
blueprint (YAML style templates, Figma Design Token pattern)
|
smithy-hwpx / smithy-md (format-specific compilers)
|
bindings-py / bindings-cli (user interfaces)
```
--------------------------------
### Register HWPForge with Claude Desktop
Source: https://github.com/ai-screams/hwpforge/blob/main/README.md
Configure HWPForge for Claude Desktop by editing the `claude_desktop_config.json` file.
```json
{
"mcpServers": {
"hwpforge": {
"command": "npx",
"args": ["-y", "@hwpforge/mcp"]
}
}
}
```
--------------------------------
### Essential Development Commands
Source: https://github.com/ai-screams/hwpforge/blob/main/CONTRIBUTING.md
Run these commands to maintain code quality and ensure compatibility. `make ci` runs the full CI pipeline.
```bash
make ci # Full CI pipeline: fmt + clippy + test + deny + lint
make test # cargo nextest run (parallel, all features)
make clippy # cargo clippy (all targets, all features, -D warnings)
make fmt-fix # Auto-format with rustfmt
make doc # Generate rustdoc (opens in browser)
make cov # Coverage report with 90% gate (llvm-cov)
mdbook build # Build the project book
```
--------------------------------
### Load Built-in Default Template
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/style-templates.md
Instantiate the default HWPX template without needing a separate YAML file. Verify the template metadata and default styles.
```rust
use hwpforge_blueprint::builtins::builtin_default;
use hwpforge_blueprint::registry::StyleRegistry;
let template = builtin_default().unwrap();
assert_eq!(template.meta.name, "default");
let registry = StyleRegistry::from_template(&template).unwrap();
let body = registry.get_style("body").unwrap();
let cs = registry.char_shape(body.char_shape_id).unwrap();
assert_eq!(cs.font, "한컴바탕");
```
--------------------------------
### Markdown to HWPX Pipeline Overview
Source: https://github.com/ai-screams/hwpforge/blob/main/docs/guide/markdown-bridge.md
This diagram illustrates the Markdown to HWPX conversion pipeline, showing the flow from Markdown string to HWPX file through intermediate Core DOM representations.
```text
Markdown 문자열
|
v (MdDecoder::decode)
Document + StyleRegistry
|
v (doc.validate())
Document
|
v (HwpxEncoder::encode)
HWPX 바이트 → .hwpx 파일
```