Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ packages/npm-core-rs/site-dist/
packages/npm-core-rs/*.tgz
packages/npm-core-rs/tmp/
target/
packages/core-rs/src/generators/hwpx/reference/*-sample.hwpx
118 changes: 100 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,66 @@
# docxly core-rs
<div align="center">
<h1>docxly core-rs</h1>
<p><strong>Embeddable Rust/WASM document generation for DOCX and HWPX.</strong></p>
<p>Where Pandoc is a general-purpose converter, docxly is designed to live inside Node services, browser workflows, and product surfaces as a library.</p>
<p>
<a href="https://github.com/docxly/core-rs/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/docxly/core-rs/ci.yml?branch=main&label=ci"></a>
<a href="https://www.npmjs.com/package/@docxly/core-rs"><img alt="npm" src="https://img.shields.io/npm/v/%40docxly%2Fcore-rs?label=npm"></a>
<a href="https://docxly.github.io/core-rs/"><img alt="demo" src="https://img.shields.io/badge/demo-live-1f7a4c"></a>
<a href="https://github.com/docxly/core-rs/blob/main/LICENSE"><img alt="license" src="https://img.shields.io/github/license/docxly/core-rs"></a>
</p>
</div>

`docxly/core-rs` is a Rust-first mono repo for a Markdown-based DOCX/HWPX generation library, plus an npm-facing WASM wrapper package.
Language: [English](/Users/limchaesung/Github/docxly/core-rs/README.md) · [한국어](/Users/limchaesung/Github/docxly/core-rs/docs/ko/README.md) · [Docs](/Users/limchaesung/Github/docxly/core-rs/docs/README.md)

The project is being developed with a TDD-first workflow. The current milestone implements the DOCX rich slice and is bringing up HWPX compatibility from a minimal package baseline.
`docxly/core-rs` currently measures at an 80 ms cold start and a 2 ms steady median, versus 284 ms cold and 210 ms steady for Pandoc on the summary DOCX benchmark corpus, a 105x steady-state advantage while also exposing browser-local generation and HWPX support from the same Rust core.

## Live Demo
The project is developed with a TDD-first workflow. The current milestone implements the DOCX rich slice and an approved HWPX baseline backed by manually validated golden fixtures.

Try the browser demo on GitHub Pages:
## Install

- https://docxly.github.io/core-rs/
The fastest way to start using docxly today is the npm package:

The live page uses the published WASM wrapper and downloads a real `.docx` file directly in the browser.
```bash
npm install @docxly/core-rs
```

The Rust crate is the source of truth in this repository and can be consumed from the workspace or as a path dependency:

```toml
[dependencies]
core-rs = { path = "packages/core-rs" }
```

## Quick Start

### Node

```js
import { writeFile } from "node:fs/promises";
import { generateDocx } from "@docxly/core-rs";

const bytes = await generateDocx("# Hello\n\nThis is **docxly**.");
await writeFile("output.docx", bytes);
```

### Rust

```rust
use std::fs;

use core_rs::{DocxOptions, generate_docx};

let docx = generate_docx("# Hello\n\nThis is **docxly**.", DocxOptions::default())?;
fs::write("output.docx", docx)?;
```

## Why docxly

- Build document generation directly into a product instead of shelling out to a converter.
- On the current summary corpus, generate complex DOCX output in `2 ms` steady median versus Pandoc's `210 ms`, with `80 ms` versus `284 ms` cold start.
- Use the same Rust core across Node, browser, and HWPX workflows.
- Start with DOCX today and expand into HWPX from the same repository.
- Ship deterministic outputs backed by fixture-driven tests and normalized archive checks.

## Live Demo

Expand All @@ -20,6 +70,39 @@ Try the browser demo on GitHub Pages:

The live page uses the published WASM wrapper and downloads a real `.docx` file directly in the browser.

<!-- comparison:start -->

## Why docxly instead of Pandoc?

Pandoc is a general-purpose converter; docxly is an embeddable generation engine.

Use docxly when document generation must live inside a Node service, browser workflow, or product surface. Use Pandoc when you need broad format conversion and a CLI-first publishing workflow.

| Corpus | docxly cold | Pandoc cold | docxly steady | Pandoc steady | Speed ratio |
| --- | --- | --- | --- | --- | --- |
| Small | 66 ms | 539 ms | 1 ms | 249 ms | 369.84x |
| Medium | 80 ms | 284 ms | 2 ms | 126 ms | 64.85x |
| Large | 88 ms | 219 ms | 4 ms | 210 ms | 57.60x |
| Summary | 80 ms | 284 ms | 2 ms | 210 ms | 105.00x |

| Capability | docxly | Pandoc |
| --- | --- | --- |
| Embeddable in app | Yes, library-first for Node and browser bundlers | CLI-first with process invocation |
| Browser-local generation | First-party browser package and WASM path | Possible through pandoc.wasm, not the primary npm workflow |
| npm distribution | Published package | Not a first-party npm package |
| HWPX generation | Supported in the Rust core | Not supported |
| Broad format conversion | Focused on DOCX and HWPX generation | Wide multi-format conversion |
| DOCX reference-template workflow | Not a reference.docx workflow | Supported via reference.docx |

Measured on darwin 25.2.0 / arm64 at 2026-03-10T14:29:12.752Z with Node v23.7.0 and Pandoc 3.9.

- This benchmark measures DOCX generation only and does not compare HWPX.
- The numbers above come from an offline Node environment and are not browser runtime timings.
- Cold timings include WASM initialization for docxly and process startup for Pandoc.
- Steady timings are medians from 15 runs after one warm-up per corpus.

<!-- comparison:end -->

## Workspace Layout

```text
Expand All @@ -43,9 +126,9 @@ The live page uses the published WASM wrapper and downloads a real `.docx` file
- Implemented: Markdown parser, internal shared intermediate model, deterministic DOCX packaging
- Implemented: fixture-driven integration tests with normalized hash comparison
- Implemented: strict/fallback handling for unsupported HTML, non-data images, and deep nested lists
- In progress: HWPX compatibility bring-up from a minimal Hancom-compatible package baseline
- Current HWPX CI gates only manually approved fixtures; `core-paragraph`, `core-heading`, `core-inline-style`, `core-link-text`, `core-mixed`, `style-typography`, `style-centered-layout`, and `style-brand-color` are the current approved baselines
- Stale compatibility snapshots are quarantined and used only for reverse-engineering
- Implemented: approved HWPX baseline backed by manually validated fixtures
- Current HWPX CI gates use these approved fixtures: `core-paragraph`, `blockquote-basic`, `code-block-basic`, `core-heading`, `core-inline-style`, `core-link-text`, `core-mixed`, `list-basic`, `list-nested-depth-2`, `style-typography`, `style-centered-layout`, and `style-brand-color`
- Provisional and quarantined HWPX artifacts are excluded from the release gate
- HWPX style options currently apply to body paragraphs and heading paragraphs; future block types such as lists and tables may add more paragraph categories

## Supported Markdown Today
Expand Down Expand Up @@ -104,7 +187,7 @@ Current options:
Notes:

- `generate_docx` returns a deterministic `.docx` archive as `Vec<u8>`
- `generate_hwpx` currently targets a minimal compatibility baseline and is still being validated against Hancom
- `generate_hwpx` targets the approved HWPX baseline reproduced by the committed golden fixtures
- `HwpxStyleOptions` currently supports document-level body/heading font, body/heading size, text/link/heading color, and paragraph alignment overrides
- Custom HWPX fonts are best-effort only; the current HWPX path records font family names but does not embed font binaries
- internal modules such as parser/model/generator helpers are not part of the public contract
Expand All @@ -113,19 +196,17 @@ Notes:

The current HWPX path is narrower than the DOCX rich slice.

- approved baseline: `core-paragraph`, `core-heading`, `core-inline-style`, `core-link-text`, `core-mixed`
- approved baseline: `core-paragraph`, `blockquote-basic`, `code-block-basic`, `core-heading`, `core-inline-style`, `core-link-text`, `core-mixed`
- approved list baseline: `list-basic`, `list-nested-depth-2`
- approved style baseline: `style-typography`, `style-centered-layout`, `style-brand-color`
- supported content today:
- paragraphs
- headings
- visible-text emphasis/strong/code/link rendering inside the approved compatibility contract
- document-level HWPX style overrides
- not yet part of the approved HWPX baseline:
- lists
- tables
- images
- blockquotes
- fenced code blocks

Example HWPX generation:

Expand Down Expand Up @@ -273,10 +354,11 @@ hash.txt

## HWPX Reference Material

- `/Users/limchaesung/Github/docxly/core-rs/packages/core-rs/src/generators/hwpx/docs/README.md`
- `/Users/limchaesung/Github/docxly/core-rs/packages/core-rs/src/generators/hwpx/docs/schema-md/index.md`
- `packages/core-rs/src/generators/hwpx/docs/README.md`
- `packages/core-rs/src/generators/hwpx/docs/schema-md/index.md`
- `packages/core-rs/src/generators/hwpx/reference/paragraph-only`

These files are the repository-level reference corpus for HWPX work. They combine curated implementation notes with Markdown conversions of official Hancom PDF references, KS X 6101 source metadata, and a synthetic compatibility corpus.
These files are the repository-level reference corpus for HWPX work. They combine curated implementation notes, Markdown conversions of Hancom reference material, and the local approved/reference fixtures used to keep the package contract stable.

## Development Notes

Expand Down
15 changes: 15 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Docs

`docxly` documentation is organized by entrypoint, similar to a product docs hub.

## Languages

- [English (repository README)](/Users/limchaesung/Github/docxly/core-rs/README.md)
- [한국어](/Users/limchaesung/Github/docxly/core-rs/docs/ko/README.md)

## Sections

- [Getting Started](/Users/limchaesung/Github/docxly/core-rs/docs/ko/getting-started.md)
- [Runtime Guide](/Users/limchaesung/Github/docxly/core-rs/docs/ko/runtime.md)
- [Benchmark and Positioning](/Users/limchaesung/Github/docxly/core-rs/docs/ko/benchmark.md)
- [Design System](/Users/limchaesung/Github/docxly/core-rs/docs/ko/design-system.md)
31 changes: 31 additions & 0 deletions docs/ko/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# docxly 문서

`docxly`는 DOCX와 HWPX 생성을 애플리케이션 내부에 직접 내장하기 위한 Rust/WASM 문서 생성 엔진입니다.

Pandoc이 범용 문서 변환기라면, `docxly`는 Node 서비스, 브라우저 워크플로, 제품 UI 안에 직접 들어가는 라이브러리 경로에 초점을 맞춥니다.

## 시작하기

- [빠른 시작](/Users/limchaesung/Github/docxly/core-rs/docs/ko/getting-started.md)
- [런타임 가이드](/Users/limchaesung/Github/docxly/core-rs/docs/ko/runtime.md)
- [성능 비교와 포지셔닝](/Users/limchaesung/Github/docxly/core-rs/docs/ko/benchmark.md)
- [디자인 시스템](/Users/limchaesung/Github/docxly/core-rs/docs/ko/design-system.md)

## 핵심 수치

- 현재 summary benchmark 기준 `docxly`는 `80 ms cold / 2 ms steady`
- 같은 코퍼스에서 Pandoc은 `284 ms cold / 210 ms steady`
- steady 기준으로 `105x` 빠른 수치가 측정됨

## 언제 docxly를 선택해야 하나

- 문서 생성을 별도 CLI 프로세스가 아니라 애플리케이션 내부 라이브러리로 붙이고 싶을 때
- Node와 브라우저에서 같은 Rust 코어를 재사용하고 싶을 때
- DOCX뿐 아니라 HWPX까지 같은 저장소와 API 흐름으로 확장하고 싶을 때
- 테스트 가능한 결정적 출력과 fixture 기반 검증이 필요할 때

## 바로 가기

- [루트 README](/Users/limchaesung/Github/docxly/core-rs/README.md)
- [npm package README](/Users/limchaesung/Github/docxly/core-rs/packages/npm-core-rs/README.md)
- [라이브 데모](https://docxly.github.io/core-rs/)
42 changes: 42 additions & 0 deletions docs/ko/benchmark.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# 성능 비교와 포지셔닝

## 요약

`docxly`는 Pandoc의 대체 CLI가 아니라, 앱 내부에 문서 생성을 임베드하기 위한 라이브러리 경로를 제공합니다.

- `docxly`: embeddable generation engine
- `Pandoc`: general-purpose converter

## 현재 summary benchmark

- `docxly`: `80 ms cold / 2 ms steady`
- `Pandoc`: `284 ms cold / 210 ms steady`
- steady median 기준 `105x`

측정 조건:

- 환경: `darwin 25.2.0 / arm64`
- Node: `v23.7.0`
- Pandoc: `3.9`
- 기준: complex DOCX benchmark corpus

## 해석

- cold start는 초기화 비용을 포함합니다.
- `docxly`: WASM initialization 포함
- `Pandoc`: process startup 포함
- steady median은 warm-up 이후 반복 생성 비용을 의미합니다.
- 이 수치는 브라우저 실측이 아니라 offline Node benchmark입니다.

## 언제 Pandoc이 더 적합한가

- 폭넓은 문서 포맷 변환이 필요할 때
- CLI 중심 출판 파이프라인이 있을 때
- `reference.docx` 기반 커스터마이징 흐름이 필요할 때

## 언제 docxly가 더 적합한가

- 앱 내부에 직접 문서 생성 기능을 붙여야 할 때
- Node와 브라우저에서 같은 코어를 재사용해야 할 때
- HWPX까지 같은 제품 흐름 안에서 다뤄야 할 때
- 별도 프로세스 의존성 없이 라이브러리 형태로 배포하고 싶을 때
Loading