このプロジェクトについて

# plantuml.rs Java製の図生成ライブラリ [PlantUML](https://plantuml.com/) を100%Rustで再実装したもので、動作の一致を目標とし、さらにJava、TypeScript、Python向けの言語バインディングをFFI経由で提供します。 ## ステータス **進行中。** シーケンス図の解析、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) - レイアウト配置用の1次元制約ソルバー(`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ブロックごとに1つ。遅延評価: 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` | レイアウト配置用の1次元制約ソルバー | | `svg` | `plantuml-svg` | SVGレンダリングバックエンド | | root (一部) | `plantuml-engine` | `BlockUml`、`BlockUmlBuilder`、`PSystemBuilder`、`SourceStringReader`、統一レンダリングAPI | | root (一部) | `plantuml-core` | `Diagram`、`TextBlock`、`StringBounder`、`FileFormat`、`FileFormatOption` | | — | `plantuml-ffi` | 言語バインディング向けC FFI共有ライブラリ | | — | `plantuml-wasm` | TypeScriptバインディング向けWASMモジュール(wasm-bindgen) | ### デザインパターン Rustへの移植では、Javaオリジナルの主要なデザインパターンを維持しています: 1. **Factory + Registry** — `PSystemBuilder` がトレイトベースのレジストリを介して図種ごとの `*DiagramFactory` 実装へディスパッチします。 2. **Commandパターン** — 各行パーサーは `CommandFactory` に登録された `Command` であり、実装を持つ `Command` トレイトにマッピングされます。 3. **Strategy** — `FileFormat` がレンダリングバックエンドを選択します。レイアウトバックエンドの選択(Graphviz対ELK)も同様にストラテジであり、トレイトオブジェクトまたはenumを使用します。 4. **遅延初期化** — `BlockUml.getDiagram()` は `OnceCell<T>` または明示的な `build()` 呼び出しを通じてオンデマンドでモデルを構築します。 5. **Template method** — `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/ # レイアウト用1次元制約ソルバー │ ├── 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 ``` ### Lint ```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クレートパス。 - **ファイルマッピング**: 1つのJavaファイル → 1つのRustファイル。ファイルサイズのガバナンス(≤500 / 501–800 / >800行)。 - **OOP → Rust**: インターフェース → トレイト、クラス → 構造体、オーバーロード → ビルダー。 - **エラー処理**: ライブラリには `Result` + `thiserror`、CLIには `anyhow`。ライブラリコードでpanicを起こさない。 - **ドキュメントコメント**: すべての公開項目は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`](LICENSE) ファイルに準拠)。 > **注記:** `Cargo.toml` はワークスペースパッケージメタデータで `license = "GPL-3.0-only"` を宣言していますが、権威ある `LICENSE` ファイルはMITです。このREADMEは `LICENSE` ファイルを反映しています。プロジェクトがGPL-3.0を意図する場合、`LICENSE` ファイルと `Cargo.toml` のメタデータを整合させる必要があります。