프로젝트 소개

# plantuml.rs Java 다이어그램 생성 라이브러리인 [PlantUML](https://plantuml.com/)을 100% Rust로 재구현한 프로젝트로, 동작 동등성을 목표로 하며 FFI를 통한 Java, TypeScript, Python 언어 바인딩을 제공합니다. ## 상태 **진행 중.** 시퀀스 다이어그램 파싱, SVG 렌더링, PREPROC(전처리된 텍스트) 출력이 작동하며 Java 참조 구현에 대해 테스트되었습니다. 다른 다이어그램 유형(클래스, 액티비티, 유스 케이스 등)과 렌더링 백엔드(PNG, PDF, LaTeX)는 점진적으로 포팅 중입니다. 전체 로드맵은 [`.agents/architecture.md`](.agents/architecture.md)를 참조하세요. ## 기능 **현재 작동:** - 시퀀스 다이어그램 파싱 (`plantuml-sequence`) - SVG 렌더링 백엔드 (`plantuml-svg`) - PREPROC 출력 (TIM 엔진을 통한 전처리된 텍스트, `plantuml-preproc`) - 통합 렌더 API: `render_svg`, `render_preproc`, `render(source, format)` (`plantuml-engine`) - JNI를 통한 Java 바인딩 — `PlantUml.renderSvg` / `PlantUml.renderPreproc` - WASM을 통한 TypeScript 바인딩 — `renderSvg` / `renderPreproc` (브라우저 + Node.js) - 레이아웃 위치 지정을 위한 1D 제약 솔버 (`plantuml-real`) - 사용자 정의 정규식 엔진 (`plantuml-regex`) - 전처리기: `!include`, `!define`, 변수, 조건문 (`plantuml-preproc`) - 명령 파싱 프레임워크 (`plantuml-command`) - 2D 그래픽 기본 요소 (`plantuml-klimt`) - 스킨 / 스타일 / 테마 시스템 (`plantuml-skin`) **계획됨:** - 클래스, 액티비티, 유스 케이스 및 기타 다이어그램 유형 - PNG, PDF, LaTeX/TikZ 렌더링 백엔드 - 레이아웃 엔진 (Graphviz / ELK) - CLI 바이너리 (`plantuml-cli`) - Python 바인딩 (PyO3 + maturin) - 추가 언어 바인딩을 위한 C FFI 공유 라이브러리 ## 아키텍처 ### 파이프라인 ``` 소스 텍스트 │ ▼ BlockUmlBuilder 입력을 @start/@end 블록으로 분할 │ ▼ BlockUml @start/@end 블록당 하나. 지연: TimLoader가 전처리 (!include, !define, 변수) ▼ PSystemBuilder createPSystem()이 다이어그램 유형 팩토리(Sequence, Class, Activity, UseCase 등)로 디스패치 ▼ Diagram 객체 메모리 내 다이어그램 모델 │ ▼ Diagram.exportDiagram() FileFormat별 StringBinder를 통해 SVG / PNG / PDF / LaTeX / EPS 등으로 렌더링 ▼ 출력 바이트 ``` ### Java 패키지 → Rust 크레이트 | Java 패키지 | Rust 크레이트 | 책임 | |------------------|------------|---------------| | `klimt` | `plantuml-klimt` | 2D 그래픽: 도형, 기하학, 폰트, `StringBounder`, `UGraphic`, `TextBlock` | | `com.plantuml.ubrex` | `plantuml-regex` | 사용자 정의 정규식 엔진 | | `preproc` / `tim` | `plantuml-preproc` | 전처리기: `!include`, `!define`, 변수, 조건문 | | `command` | `plantuml-command` | `Command` / `CommandFactory` 파싱 프레임워크 | | `abel` / `cucadiagram` | `plantuml-model` | 엔티티/관계 모델: `Entity`, `Link`, `LeafType` | | `sequencediagram` | `plantuml-sequence` | 시퀀스 다이어그램 | | `skin` / `style` / `theme` | `plantuml-skin` | 스킨 / 스타일 / 테마 시스템 | | `real` | `plantuml-real` | 레이아웃 위치 지정을 위한 1D 제약 솔버 | | `svg` | `plantuml-svg` | SVG 렌더링 백엔드 | | 루트 (부분) | `plantuml-engine` | `BlockUml`, `BlockUmlBuilder`, `PSystemBuilder`, `SourceStringReader`, 통합 렌더 API | | 루트 (부분) | `plantuml-core` | `Diagram`, `TextBlock`, `StringBounder`, `FileFormat`, `FileFormatOption` | | — | `plantuml-ffi` | 언어 바인딩을 위한 C FFI 공유 라이브러리 | | — | `plantuml-wasm` | TypeScript 바인딩을 위한 WASM 모듈 (wasm-bindgen) | ### 디자인 패턴 Rust 포트는 Java 원본의 핵심 디자인 패턴을 유지합니다: 1. **팩토리 + 레지스트리** — `PSystemBuilder`가 트레이트 기반 레지스트리를 통해 유형별 `*DiagramFactory` 구현으로 디스패치합니다. 2. **명령 패턴** — 각 소스 라인 파서는 `CommandFactory`에 등록된 `Command`이며, 구현이 있는 `Command` 트레이트에 매핑됩니다. 3. **전략** — `FileFormat`이 렌더링 백엔드를 선택하며, 레이아웃 백엔드 선택(Graphviz vs ELK)도 트레이트 객체 또는 열거형을 사용하는 전략입니다. 4. **지연 초기화** — `BlockUml.getDiagram()`이 `OnceCell<T>` 또는 명시적 `build()` 호출을 통해 필요 시 모델을 빌드합니다. 5. **템플릿 메서드** — `TitledDiagram` / `Diagram`이 서브클래스로 확장되는 기본 동작을 정의하며, 기본 메서드와 컴포지션이 있는 트레이트에 매핑됩니다. ## 워크스페이스 구조 ``` plantuml.rs/ ├── crates/ │ ├── plantuml-core/ # Diagram, TextBlock, StringBounder, FileFormat │ ├── plantuml-klimt/ # 2D 그래픽: 도형, 기하학, 폰트 │ ├── plantuml-regex/ # 사용자 정의 정규식 엔진 │ ├── plantuml-preproc/ # 전처리기: !include, !define, 변수 │ ├── plantuml-command/ # Command / CommandFactory 파싱 프레임워크 │ ├── plantuml-model/ # 엔티티/관계 모델 │ ├── plantuml-engine/ # 최상위 파이프라인 및 통합 렌더 API │ ├── plantuml-svg/ # SVG 렌더링 백엔드 │ ├── plantuml-skin/ # 스킨 / 스타일 / 테마 시스템 │ ├── plantuml-real/ # 레이아웃을 위한 1D 제약 솔버 │ ├── plantuml-sequence/ # 시퀀스 다이어그램 │ ├── plantuml-ffi/ # C FFI 공유 라이브러리 │ └── plantuml-wasm/ # WASM 모듈 (wasm-bindgen) ├── bindings/ │ ├── plantuml-java/ # Java 바인딩 (JNI) — com.vgerbot.plantuml:plantuml-java │ └── plantuml-ts/ # TypeScript 바인딩 (WASM) — @vgerbot/plantuml ├── .agents/ # 에이전트 가이드라인 및 아키텍처 문서 └── Cargo.toml # 워크스페이스 매니페스트 ``` ## 시작하기 ### 사전 요구 사항 - **Rust 툴체인** (edition 2021, `resolver = "2"`) - **Java 17+** — Java 바인딩에만 필요 - **Node.js** — TypeScript 바인딩에만 필요 (`bindings/plantuml-ts`에서 `npm install`) ### 빌드 ```sh cargo build ``` ### 테스트 ```sh cargo test ``` ### 린트 ```sh cargo clippy --workspace -- -D warnings ``` ## 사용법 ### Rust ```rust use plantuml_engine::render_svg; let svg = render_svg("@startuml\nAlice -> Bob: hello\n@enduml")?; ``` `render` 함수는 `FileFormat`에 따라 디스패치합니다: ```rust use plantuml_engine::render; use plantuml_core::FileFormat; let svg = render("@startuml\nAlice -> Bob: hello\n@enduml", FileFormat::Svg)?; ``` ### Java Maven 좌표: ```xml <dependency> <groupId>com.vgerbot.plantuml</groupId> <artifactId>plantuml-java</artifactId> <version>0.1.0</version> </dependency> ``` 사용법: ```java import com.vgerbot.plantuml.PlantUml; String svg = PlantUml.renderSvg("@startuml\nAlice -> Bob: hello\n@enduml"); System.out.println(svg); ``` ### TypeScript 설치: ```sh npm install @vgerbot/plantuml ``` 사용법 (브라우저 또는 Node.js): ```typescript import { renderSvg } from '@vgerbot/plantuml'; const svg = await renderSvg('@startuml\nAlice -> Bob: hello\n@enduml'); ``` ### Python 계획됨 (PyO3 + maturin). 아직 구현되지 않음. ## 바인딩 빌드 | 바인딩 | 빌드 명령 | |---------|-------------| | Java | `cd bindings/plantuml-java && ./gradlew build` | | TypeScript | `cd bindings/plantuml-ts && npm run build` | ## 테스트 ```sh cargo test --workspace ``` 테스트는 PlantUML Java 참조 구현에서 직접 포팅됩니다: - **Vega 데이터 기반 테스트** — 예상 `.svg` / `.preproc` 출력이 있는 `.puml` 파일을 Java 참조 데이터와 비교합니다. `asciiverse/`, `svg/`, `mvp/` 스위트 전반에 걸쳐 38개의 시퀀스 SVG 테스트와 PREPROC 테스트를 포함합니다. - **Nonreg 테스트** — Java nonreg 스위트에서 포팅된 회귀 테스트. - **단위 / 기타 테스트** — `#[cfg(test)] mod tests`의 크레이트별 단위 테스트. 테스트 데이터는 `crates/plantuml-engine/tests/resources/vega/` 아래에 커밋됩니다. ## 포팅 가이드라인 포트는 엄격한 1:1 Java → Rust 파일 매핑을 따릅니다: - **명명**: 파일과 메서드에 대해 PascalCase → snake_case; Java 패키지 → Rust 크레이트 경로. - **파일 매핑**: 하나의 Java 파일 → 하나의 Rust 파일; 파일 크기 관리 (≤500 / 501–800 / >800 줄). - **OOP → Rust**: 인터페이스 → 트레이트, 클래스 → 구조체, 오버로드 → 빌더. - **오류 처리**: 라이브러리에는 `Result` + `thiserror`, CLI에는 `anyhow`. 라이브러리 코드에서 패닉 없음. - **문서 주석**: 모든 공개 항목은 Java 소스를 인용합니다, 예: `/// Ported from: net/sourceforge/plantuml/SourceStringReader.java`. 전체 세부 사항은 [`.agents/rules/java-to-rust-porting.md`](.agents/rules/java-to-rust-porting.md)를 참조하세요. ## 기여 프로젝트 규칙은 [`.agents/AGENTS.md`](.agents/AGENTS.md)를, 아키텍처 개요, 레이어 매핑, 디자인 패턴은 [`.agents/architecture.md`](.agents/architecture.md)를 참조하세요. ## 라이선스 MIT 라이선스 (워크스페이스 [`LICENSE`](LICENSE) 파일에 따름). > **참고:** `Cargo.toml`은 워크스페이스 패키지 메타데이터에서 `license = "GPL-3.0-only"`를 선언하지만, 권위 있는 `LICENSE` 파일은 MIT입니다. 이 README는 `LICENSE` 파일을 반영합니다. 프로젝트가 GPL-3.0을 의도한다면 `LICENSE` 파일과 `Cargo.toml` 메타데이터를 조정해야 합니다.