Sobre el proyecto

# plantuml.rs Una reimplementación 100% en Rust de [PlantUML](https://plantuml.com/) —la biblioteca Java de generación de diagramas— con la paridad de comportamiento como objetivo, además de enlaces de lenguaje para Java, TypeScript y Python mediante FFI. ## Estado **En progreso.** El análisis de diagramas de secuencia, la renderización SVG y la salida PREPROC (texto preprocesado) funcionan y están probados contra la referencia en Java. Otros tipos de diagramas (clases, actividad, casos de uso, etc.) y backends de renderización (PNG, PDF, LaTeX) se están portando de forma incremental. Consulta [`.agents/architecture.md`](.agents/architecture.md) para la hoja de ruta completa. ## Características **Funciona ahora:** - Análisis de diagramas de secuencia (`plantuml-sequence`) - Backend de renderización SVG (`plantuml-svg`) - Salida PREPROC (texto preprocesado mediante el motor TIM, `plantuml-preproc`) - API de renderización unificada: `render_svg`, `render_preproc`, `render(source, format)` (`plantuml-engine`) - Enlace Java mediante JNI — `PlantUml.renderSvg` / `PlantUml.renderPreproc` - Enlace TypeScript mediante WASM — `renderSvg` / `renderPreproc` (navegador + Node.js) - Solucionador de restricciones 1D para posicionamiento de diseño (`plantuml-real`) - Motor de expresiones regulares personalizado (`plantuml-regex`) - Preprocesador: `!include`, `!define`, variables, condicionales (`plantuml-preproc`) - Marco de análisis de comandos (`plantuml-command`) - Primitivas de gráficos 2D (`plantuml-klimt`) - Sistema de skin / estilo / tema (`plantuml-skin`) **Planificado:** - Diagramas de clases, actividad, casos de uso y otros tipos - Backends de renderización PNG, PDF, LaTeX/TikZ - Motores de diseño (Graphviz / ELK) - Binario CLI (`plantuml-cli`) - Enlace Python (PyO3 + maturin) - Biblioteca compartida C FFI para enlaces de lenguaje adicionales ## Arquitectura ### Pipeline ``` Texto fuente │ ▼ BlockUmlBuilder Divide la entrada en bloques @start/@end │ ▼ BlockUml Uno por cada bloque @start/@end. Perezoso: TimLoader preprocesa (!include, !define, variables) ▼ PSystemBuilder createPSystem() despacha a la fábrica de tipo de diagrama (Sequence, Class, Activity, UseCase, etc.) ▼ Objeto Diagram El modelo del diagrama en memoria │ ▼ Diagram.exportDiagram() Renderiza mediante un StringBinder específico de FileFormat a SVG / PNG / PDF / LaTeX / EPS / etc. ▼ Bytes de salida ``` ### Paquete Java → Crate de Rust | Paquete(s) Java | Crate de Rust | Responsabilidad | |------------------|------------|---------------| | `klimt` | `plantuml-klimt` | Gráficos 2D: formas, geometría, fuentes, `StringBounder`, `UGraphic`, `TextBlock` | | `com.plantuml.ubrex` | `plantuml-regex` | Motor de expresiones regulares personalizado | | `preproc` / `tim` | `plantuml-preproc` | Preprocesador: `!include`, `!define`, variables, condicionales | | `command` | `plantuml-command` | Marco de análisis `Command` / `CommandFactory` | | `abel` / `cucadiagram` | `plantuml-model` | Modelo entidad/relación: `Entity`, `Link`, `LeafType` | | `sequencediagram` | `plantuml-sequence` | Diagrama de secuencia | | `skin` / `style` / `theme` | `plantuml-skin` | Sistema de skin / estilo / tema | | `real` | `plantuml-real` | Solucionador de restricciones 1D para posicionamiento de diseño | | `svg` | `plantuml-svg` | Backend de renderización SVG | | raíz (parcial) | `plantuml-engine` | `BlockUml`, `BlockUmlBuilder`, `PSystemBuilder`, `SourceStringReader`, API de renderización unificada | | raíz (parcial) | `plantuml-core` | `Diagram`, `TextBlock`, `StringBounder`, `FileFormat`, `FileFormatOption` | | — | `plantuml-ffi` | Biblioteca compartida C FFI para enlaces de lenguaje | | — | `plantuml-wasm` | Módulo WASM (wasm-bindgen) para el enlace TypeScript | ### Patrones de diseño El port a Rust conserva los patrones de diseño clave del original en Java: 1. **Factory + Registry** — `PSystemBuilder` despacha a implementaciones `*DiagramFactory` por tipo mediante un registro basado en traits. 2. **Patrón Command** — Cada analizador de línea fuente es un `Command` registrado en un `CommandFactory`; se mapea a un trait `Command` con implementaciones. 3. **Strategy** — `FileFormat` selecciona el backend de renderización; la selección del backend de diseño (Graphviz vs ELK) también es una estrategia, usando objetos trait o enums. 4. **Inicialización perezosa** — `BlockUml.getDiagram()` construye el modelo bajo demanda mediante `OnceCell<T>` o llamadas explícitas a `build()`. 5. **Método plantilla** — `TitledDiagram` / `Diagram` definen el comportamiento base extendido por subclases; se mapea a traits con métodos por defecto y composición. ## Estructura del workspace ``` plantuml.rs/ ├── crates/ │ ├── plantuml-core/ # Diagram, TextBlock, StringBounder, FileFormat │ ├── plantuml-klimt/ # Gráficos 2D: formas, geometría, fuentes │ ├── plantuml-regex/ # Motor de expresiones regulares personalizado │ ├── plantuml-preproc/ # Preprocesador: !include, !define, variables │ ├── plantuml-command/ # Marco de análisis Command / CommandFactory │ ├── plantuml-model/ # Modelo entidad/relación │ ├── plantuml-engine/ # Pipeline de nivel superior y API de renderización unificada │ ├── plantuml-svg/ # Backend de renderización SVG │ ├── plantuml-skin/ # Sistema de skin / estilo / tema │ ├── plantuml-real/ # Solucionador de restricciones 1D para diseño │ ├── plantuml-sequence/ # Diagrama de secuencia │ ├── plantuml-ffi/ # Biblioteca compartida C FFI │ └── plantuml-wasm/ # Módulo WASM (wasm-bindgen) ├── bindings/ │ ├── plantuml-java/ # Enlace Java (JNI) — com.vgerbot.plantuml:plantuml-java │ └── plantuml-ts/ # Enlace TypeScript (WASM) — @vgerbot/plantuml ├── .agents/ # Directrices para agentes y documentos de arquitectura └── Cargo.toml # Manifiesto del workspace ``` ## Primeros pasos ### Requisitos previos - **Toolchain de Rust** (edición 2021, `resolver = "2"`) - **Java 17+** — solo necesario para el enlace Java - **Node.js** — solo necesario para el enlace TypeScript (`npm install` en `bindings/plantuml-ts`) ### Compilación ```sh cargo build ``` ### Pruebas ```sh cargo test ``` ### Lint ```sh cargo clippy --workspace -- -D warnings ``` ## Uso ### Rust ```rust use plantuml_engine::render_svg; let svg = render_svg("@startuml\nAlice -> Bob: hello\n@enduml")?; ``` La función `render` despacha según `FileFormat`: ```rust use plantuml_engine::render; use plantuml_core::FileFormat; let svg = render("@startuml\nAlice -> Bob: hello\n@enduml", FileFormat::Svg)?; ``` ### Java Coordenadas Maven: ```xml <dependency> <groupId>com.vgerbot.plantuml</groupId> <artifactId>plantuml-java</artifactId> <version>0.1.0</version> </dependency> ``` Uso: ```java import com.vgerbot.plantuml.PlantUml; String svg = PlantUml.renderSvg("@startuml\nAlice -> Bob: hello\n@enduml"); System.out.println(svg); ``` ### TypeScript Instalación: ```sh npm install @vgerbot/plantuml ``` Uso (navegador o Node.js): ```typescript import { renderSvg } from '@vgerbot/plantuml'; const svg = await renderSvg('@startuml\nAlice -> Bob: hello\n@enduml'); ``` ### Python Planificado (PyO3 + maturin). Aún no implementado. ## Compilaciones de enlaces | Enlace | Comando de compilación | |---------|-------------| | Java | `cd bindings/plantuml-java && ./gradlew build` | | TypeScript | `cd bindings/plantuml-ts && npm run build` | ## Pruebas ```sh cargo test --workspace ``` Las pruebas se portan directamente desde la referencia Java de PlantUML: - **Pruebas basadas en datos Vega** — archivos `.puml` con salida esperada `.svg` / `.preproc`, comparados con los datos de referencia de Java. Cubre 38 pruebas SVG de secuencia y pruebas PREPROC en las suites `asciiverse/`, `svg/` y `mvp/`. - **Pruebas nonreg** — pruebas de regresión portadas desde la suite nonreg de Java. - **Pruebas unitarias / misceláneas** — pruebas unitarias por crate en `#[cfg(test)] mod tests`. Los datos de prueba están comprometidos en `crates/plantuml-engine/tests/resources/vega/`. ## Directrices de portabilidad El port sigue un mapeo estricto 1:1 de archivos Java → Rust: - **Nomenclatura**: PascalCase → snake_case para archivos y métodos; paquete Java → ruta de crate de Rust. - **Mapeo de archivos**: un archivo Java → un archivo Rust; gobernanza del tamaño de archivo (≤500 / 501–800 / >800 líneas). - **POO → Rust**: interfaces → traits, clases → structs, sobrecargas → builders. - **Manejo de errores**: `Result` + `thiserror` para bibliotecas, `anyhow` para CLI. Sin panics en el código de biblioteca. - **Comentarios de documentación**: todos los elementos públicos citan la fuente Java, p. ej. `/// Ported from: net/sourceforge/plantuml/SourceStringReader.java`. Consulta [`.agents/rules/java-to-rust-porting.md`](.agents/rules/java-to-rust-porting.md) para más detalles. ## Contribuir Consulta [`.agents/AGENTS.md`](.agents/AGENTS.md) para las convenciones del proyecto y [`.agents/architecture.md`](.agents/architecture.md) para la visión general de la arquitectura, el mapeo de capas y los patrones de diseño. ## Licencia Licencia MIT (según el archivo [`LICENSE`](LICENSE) del workspace). > **Nota:** `Cargo.toml` declara `license = "GPL-3.0-only"` en los metadatos del paquete del workspace, pero el archivo `LICENSE` autoritativo es MIT. Este README refleja el archivo `LICENSE`. Si el proyecto pretende ser GPL-3.0, el archivo `LICENSE` y los metadatos de `Cargo.toml` deben reconciliarse.