sirena 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/build_deploy.yml +59 -0
- data/.github/workflows/links.yml +85 -0
- data/.github/workflows/rake.yml +15 -0
- data/.github/workflows/release.yml +27 -0
- data/.gitignore +68 -0
- data/.rspec +3 -0
- data/.rubocop.yml +14 -0
- data/.rubocop_todo.yml +70 -0
- data/ARCHITECTURE.md +744 -0
- data/Gemfile +12 -0
- data/LICENSE +25 -0
- data/README.adoc +357 -0
- data/Rakefile +11 -0
- data/docs/.gitignore +1 -0
- data/docs/Gemfile +13 -0
- data/docs/_config.yml +182 -0
- data/docs/_diagram_types/architecture-diagram.adoc +314 -0
- data/docs/_diagram_types/block-diagram.adoc +345 -0
- data/docs/_diagram_types/c4-diagram.adoc +559 -0
- data/docs/_diagram_types/class-diagram.adoc +816 -0
- data/docs/_diagram_types/er-diagram.adoc +719 -0
- data/docs/_diagram_types/error-diagram.adoc +114 -0
- data/docs/_diagram_types/examples/flowchart-examples.adoc +29 -0
- data/docs/_diagram_types/flowchart.adoc +488 -0
- data/docs/_diagram_types/gantt-chart.adoc +502 -0
- data/docs/_diagram_types/git-graph.adoc +600 -0
- data/docs/_diagram_types/index.adoc +192 -0
- data/docs/_diagram_types/info-diagram.adoc +103 -0
- data/docs/_diagram_types/kanban-diagram.adoc +262 -0
- data/docs/_diagram_types/mindmap.adoc +603 -0
- data/docs/_diagram_types/packet-diagram.adoc +378 -0
- data/docs/_diagram_types/pie-chart.adoc +335 -0
- data/docs/_diagram_types/quadrant-chart.adoc +406 -0
- data/docs/_diagram_types/radar-chart.adoc +528 -0
- data/docs/_diagram_types/requirement-diagram.adoc +416 -0
- data/docs/_diagram_types/sankey-diagram.adoc +357 -0
- data/docs/_diagram_types/sequence-diagram.adoc +664 -0
- data/docs/_diagram_types/state-diagram.adoc +658 -0
- data/docs/_diagram_types/timeline.adoc +352 -0
- data/docs/_diagram_types/treemap-diagram.adoc +462 -0
- data/docs/_diagram_types/user-journey.adoc +602 -0
- data/docs/_features/index.adoc +129 -0
- data/docs/_guides/cli-reference.adoc +203 -0
- data/docs/_guides/index.adoc +56 -0
- data/docs/_guides/installation.adoc +100 -0
- data/docs/_guides/quick-start.adoc +132 -0
- data/docs/_pages/comparison.adoc +441 -0
- data/docs/_pages/compatibility.adoc +300 -0
- data/docs/_pages/index.adoc +39 -0
- data/docs/_references/index.adoc +103 -0
- data/docs/_tutorials/index.adoc +57 -0
- data/docs/index.adoc +166 -0
- data/docs/lychee.toml +54 -0
- data/examples/.gitignore +10 -0
- data/examples/README.adoc +196 -0
- data/examples/README.md +64 -0
- data/examples/architecture/01-basic-services.mmd +9 -0
- data/examples/architecture/01-basic-services.svg +37 -0
- data/examples/architecture/02-service-groups.mmd +16 -0
- data/examples/architecture/02-service-groups.svg +55 -0
- data/examples/architecture/README.adoc +79 -0
- data/examples/block/01-basic-blocks.mmd +13 -0
- data/examples/block/01-basic-blocks.svg +44 -0
- data/examples/block/02-block-shapes.mmd +13 -0
- data/examples/block/02-block-shapes.svg +47 -0
- data/examples/block/README.adoc +85 -0
- data/examples/c4/01-context-diagram.mmd +10 -0
- data/examples/c4/01-context-diagram.svg +45 -0
- data/examples/c4/02-container-diagram.mmd +24 -0
- data/examples/c4/02-container-diagram.svg +105 -0
- data/examples/c4/README.adoc +92 -0
- data/examples/class_diagram/01-basic-classes.mmd +61 -0
- data/examples/class_diagram/01-basic-classes.svg +117 -0
- data/examples/class_diagram/02-relationships.mmd +61 -0
- data/examples/class_diagram/02-relationships.svg +129 -0
- data/examples/class_diagram/README.adoc +93 -0
- data/examples/er_diagram/01-basic-entities.mmd +64 -0
- data/examples/er_diagram/01-basic-entities.svg +5 -0
- data/examples/er_diagram/02-cardinality.mmd +57 -0
- data/examples/er_diagram/02-cardinality.svg +125 -0
- data/examples/er_diagram/README.adoc +88 -0
- data/examples/error/01-basic-error.mmd +1 -0
- data/examples/error/01-basic-error.svg +13 -0
- data/examples/error/02-error-display.mmd +1 -0
- data/examples/error/02-error-display.svg +13 -0
- data/examples/error/README.adoc +71 -0
- data/examples/error_message_example.svg +13 -0
- data/examples/flowchart/00-original.mmd +13 -0
- data/examples/flowchart/00-original.svg +5 -0
- data/examples/flowchart/01-basic-flow.mmd +7 -0
- data/examples/flowchart/01-basic-flow.svg +52 -0
- data/examples/flowchart/01-basic-flow.yml +13 -0
- data/examples/flowchart/02*.svg +87 -0
- data/examples/flowchart/02-node-shapes.mmd +9 -0
- data/examples/flowchart/02-node-shapes.svg +33 -0
- data/examples/flowchart/03-edge-types.mmd +7 -0
- data/examples/flowchart/03-edge-types.svg +53 -0
- data/examples/flowchart/04-subgraphs.mmd +9 -0
- data/examples/flowchart/04-subgraphs.svg +33 -0
- data/examples/flowchart/05-styling.mmd +9 -0
- data/examples/flowchart/05-styling.svg +33 -0
- data/examples/flowchart/06-complex-flow.mmd +8 -0
- data/examples/flowchart/06-complex-flow.svg +59 -0
- data/examples/flowchart/README.adoc +167 -0
- data/examples/gantt/01-simple-timeline.* +14 -0
- data/examples/gantt/01-simple-timeline.mmd +6 -0
- data/examples/gantt/01-simple-timeline.svg +26 -0
- data/examples/gantt/02-task-dependencies.mmd +6 -0
- data/examples/gantt/02-task-dependencies.svg +26 -0
- data/examples/gantt/README.adoc +86 -0
- data/examples/git_graph/01-linear-history.mmd +12 -0
- data/examples/git_graph/01-linear-history.svg +26 -0
- data/examples/git_graph/02-branching.mmd +12 -0
- data/examples/git_graph/02-branching.svg +26 -0
- data/examples/git_graph/README.adoc +73 -0
- data/examples/info/02-showinfo.mmd +1 -0
- data/examples/info/02-showinfo.svg +10 -0
- data/examples/info/README.adoc +58 -0
- data/examples/info_showinfo_example.svg +10 -0
- data/examples/kanban/01-simple-board.mmd +8 -0
- data/examples/kanban/01-simple-board.svg +43 -0
- data/examples/kanban/02-workflow.mmd +8 -0
- data/examples/kanban/02-workflow.svg +43 -0
- data/examples/kanban/README.adoc +79 -0
- data/examples/mindmap/01-simple-tree.mmd +19 -0
- data/examples/mindmap/01-simple-tree.svg +61 -0
- data/examples/mindmap/02-knowledge-map.mmd +19 -0
- data/examples/mindmap/02-knowledge-map.svg +61 -0
- data/examples/mindmap/README.adoc +77 -0
- data/examples/packet/01-basic-packet.* +17 -0
- data/examples/packet/01-basic-packet.mmd +4 -0
- data/examples/packet/01-basic-packet.svg +82 -0
- data/examples/packet/README.adoc +58 -0
- data/examples/pie/01-simple-chart.mmd +5 -0
- data/examples/pie/01-simple-chart.svg +17 -0
- data/examples/pie/02-labeled-slices.mmd +6 -0
- data/examples/pie/02-labeled-slices.svg +19 -0
- data/examples/pie/README.adoc +75 -0
- data/examples/quadrant/01-basic-quadrant.mmd +13 -0
- data/examples/quadrant/01-basic-quadrant.svg +33 -0
- data/examples/quadrant/02-positioned-items.mmd +14 -0
- data/examples/quadrant/02-positioned-items.svg +35 -0
- data/examples/quadrant/README.adoc +84 -0
- data/examples/radar/01-simple-radar.* +5 -0
- data/examples/radar/01-simple-radar.mmd +3 -0
- data/examples/radar/01-simple-radar.svg +25 -0
- data/examples/radar/02-multiple-curves.mmd +4 -0
- data/examples/radar/02-multiple-curves.svg +43 -0
- data/examples/radar/README.adoc +75 -0
- data/examples/requirement/01-basic-requirements.mmd +23 -0
- data/examples/requirement/01-basic-requirements.svg +49 -0
- data/examples/requirement/02-risk-levels.mmd +23 -0
- data/examples/requirement/02-risk-levels.svg +49 -0
- data/examples/requirement/README.adoc +85 -0
- data/examples/sankey/01-simple-flow.mmd +7 -0
- data/examples/sankey/01-simple-flow.svg +34 -0
- data/examples/sankey/02-multi-stage.mmd +11 -0
- data/examples/sankey/02-multi-stage.svg +44 -0
- data/examples/sankey/README.adoc +74 -0
- data/examples/sequence/01-basic-sequence.mmd +27 -0
- data/examples/sequence/01-basic-sequence.svg +5 -0
- data/examples/sequence/02-activations.mmd +17 -0
- data/examples/sequence/02-activations.svg +78 -0
- data/examples/sequence/README.adoc +86 -0
- data/examples/state_diagram/01-simple-states.mmd +29 -0
- data/examples/state_diagram/01-simple-states.svg +5 -0
- data/examples/state_diagram/02-composite.mmd +19 -0
- data/examples/state_diagram/02-composite.svg +81 -0
- data/examples/state_diagram/README.adoc +90 -0
- data/examples/timeline/01-simple-timeline.mmd +11 -0
- data/examples/timeline/01-simple-timeline.svg +36 -0
- data/examples/timeline/02-periods.mmd +15 -0
- data/examples/timeline/02-periods.svg +47 -0
- data/examples/timeline/README.adoc +78 -0
- data/examples/treemap/01-basic-treemap.mmd +12 -0
- data/examples/treemap/01-basic-treemap.svg +59 -0
- data/examples/treemap/README.adoc +59 -0
- data/examples/user_journey/01-simple-journey.mmd +23 -0
- data/examples/user_journey/01-simple-journey.svg +5 -0
- data/examples/user_journey/02-multi-actor.mmd +18 -0
- data/examples/user_journey/02-multi-actor.svg +129 -0
- data/examples/user_journey/README.adoc +81 -0
- data/examples/xychart/01-line-chart.mmd +5 -0
- data/examples/xychart/01-line-chart.svg +43 -0
- data/examples/xychart/02-bar-chart.mmd +7 -0
- data/examples/xychart/02-bar-chart.svg +48 -0
- data/examples/xychart/README.adoc +80 -0
- data/exe/sirena +7 -0
- data/lib/sirena/cli.rb +138 -0
- data/lib/sirena/commands/batch.rb +117 -0
- data/lib/sirena/commands/render.rb +80 -0
- data/lib/sirena/commands/types.rb +29 -0
- data/lib/sirena/commands/version.rb +24 -0
- data/lib/sirena/diagram/architecture.rb +46 -0
- data/lib/sirena/diagram/base.rb +61 -0
- data/lib/sirena/diagram/block.rb +81 -0
- data/lib/sirena/diagram/c4.rb +328 -0
- data/lib/sirena/diagram/class_diagram.rb +385 -0
- data/lib/sirena/diagram/er_diagram.rb +238 -0
- data/lib/sirena/diagram/error.rb +38 -0
- data/lib/sirena/diagram/flowchart.rb +160 -0
- data/lib/sirena/diagram/gantt.rb +71 -0
- data/lib/sirena/diagram/git_graph.rb +36 -0
- data/lib/sirena/diagram/info.rb +38 -0
- data/lib/sirena/diagram/kanban.rb +178 -0
- data/lib/sirena/diagram/mindmap.rb +54 -0
- data/lib/sirena/diagram/packet.rb +79 -0
- data/lib/sirena/diagram/pie.rb +115 -0
- data/lib/sirena/diagram/quadrant.rb +138 -0
- data/lib/sirena/diagram/radar.rb +52 -0
- data/lib/sirena/diagram/requirement.rb +133 -0
- data/lib/sirena/diagram/sankey.rb +217 -0
- data/lib/sirena/diagram/sequence.rb +242 -0
- data/lib/sirena/diagram/state_diagram.rb +237 -0
- data/lib/sirena/diagram/timeline.rb +171 -0
- data/lib/sirena/diagram/treemap.rb +84 -0
- data/lib/sirena/diagram/user_journey.rb +149 -0
- data/lib/sirena/diagram/xy_chart.rb +76 -0
- data/lib/sirena/diagram.rb +8 -0
- data/lib/sirena/diagram_registry.rb +101 -0
- data/lib/sirena/engine.rb +292 -0
- data/lib/sirena/parser/architecture.rb +41 -0
- data/lib/sirena/parser/base.rb +41 -0
- data/lib/sirena/parser/block.rb +72 -0
- data/lib/sirena/parser/c4.rb +53 -0
- data/lib/sirena/parser/class_diagram.rb +63 -0
- data/lib/sirena/parser/er_diagram.rb +40 -0
- data/lib/sirena/parser/error.rb +49 -0
- data/lib/sirena/parser/flowchart.rb +71 -0
- data/lib/sirena/parser/gantt.rb +60 -0
- data/lib/sirena/parser/git_graph.rb +95 -0
- data/lib/sirena/parser/grammars/architecture.rb +145 -0
- data/lib/sirena/parser/grammars/block.rb +190 -0
- data/lib/sirena/parser/grammars/c4.rb +226 -0
- data/lib/sirena/parser/grammars/class_diagram.rb +284 -0
- data/lib/sirena/parser/grammars/common.rb +84 -0
- data/lib/sirena/parser/grammars/er_diagram.rb +114 -0
- data/lib/sirena/parser/grammars/error.rb +40 -0
- data/lib/sirena/parser/grammars/flowchart.rb +298 -0
- data/lib/sirena/parser/grammars/gantt.rb +252 -0
- data/lib/sirena/parser/grammars/git_graph.rb +167 -0
- data/lib/sirena/parser/grammars/info.rb +58 -0
- data/lib/sirena/parser/grammars/kanban.rb +83 -0
- data/lib/sirena/parser/grammars/mindmap.rb +115 -0
- data/lib/sirena/parser/grammars/packet.rb +73 -0
- data/lib/sirena/parser/grammars/pie.rb +128 -0
- data/lib/sirena/parser/grammars/quadrant.rb +199 -0
- data/lib/sirena/parser/grammars/radar.rb +150 -0
- data/lib/sirena/parser/grammars/requirement.rb +188 -0
- data/lib/sirena/parser/grammars/sankey.rb +104 -0
- data/lib/sirena/parser/grammars/sequence.rb +247 -0
- data/lib/sirena/parser/grammars/state_diagram.rb +172 -0
- data/lib/sirena/parser/grammars/timeline.rb +142 -0
- data/lib/sirena/parser/grammars/treemap.rb +120 -0
- data/lib/sirena/parser/grammars/xy_chart.rb +120 -0
- data/lib/sirena/parser/info.rb +49 -0
- data/lib/sirena/parser/kanban.rb +97 -0
- data/lib/sirena/parser/mindmap.rb +106 -0
- data/lib/sirena/parser/packet.rb +76 -0
- data/lib/sirena/parser/pie.rb +49 -0
- data/lib/sirena/parser/quadrant.rb +57 -0
- data/lib/sirena/parser/radar.rb +104 -0
- data/lib/sirena/parser/requirement.rb +70 -0
- data/lib/sirena/parser/sankey.rb +64 -0
- data/lib/sirena/parser/sequence.rb +51 -0
- data/lib/sirena/parser/state_diagram.rb +69 -0
- data/lib/sirena/parser/timeline.rb +57 -0
- data/lib/sirena/parser/transforms/architecture.rb +97 -0
- data/lib/sirena/parser/transforms/block.rb +254 -0
- data/lib/sirena/parser/transforms/c4.rb +347 -0
- data/lib/sirena/parser/transforms/class_diagram.rb +352 -0
- data/lib/sirena/parser/transforms/er_diagram.rb +169 -0
- data/lib/sirena/parser/transforms/error.rb +58 -0
- data/lib/sirena/parser/transforms/flowchart.rb +293 -0
- data/lib/sirena/parser/transforms/gantt.rb +215 -0
- data/lib/sirena/parser/transforms/git_graph.rb +160 -0
- data/lib/sirena/parser/transforms/info.rb +58 -0
- data/lib/sirena/parser/transforms/kanban.rb +176 -0
- data/lib/sirena/parser/transforms/mindmap.rb +227 -0
- data/lib/sirena/parser/transforms/packet.rb +63 -0
- data/lib/sirena/parser/transforms/pie.rb +143 -0
- data/lib/sirena/parser/transforms/quadrant.rb +177 -0
- data/lib/sirena/parser/transforms/radar.rb +126 -0
- data/lib/sirena/parser/transforms/requirement.rb +272 -0
- data/lib/sirena/parser/transforms/sankey.rb +122 -0
- data/lib/sirena/parser/transforms/sequence.rb +342 -0
- data/lib/sirena/parser/transforms/state_diagram.rb +292 -0
- data/lib/sirena/parser/transforms/timeline.rb +177 -0
- data/lib/sirena/parser/transforms/treemap.rb +81 -0
- data/lib/sirena/parser/transforms/xy_chart.rb +132 -0
- data/lib/sirena/parser/treemap.rb +98 -0
- data/lib/sirena/parser/user_journey.rb +120 -0
- data/lib/sirena/parser/xy_chart.rb +114 -0
- data/lib/sirena/parser.rb +8 -0
- data/lib/sirena/renderer/architecture.rb +251 -0
- data/lib/sirena/renderer/base.rb +251 -0
- data/lib/sirena/renderer/block.rb +286 -0
- data/lib/sirena/renderer/c4.rb +490 -0
- data/lib/sirena/renderer/class_diagram.rb +499 -0
- data/lib/sirena/renderer/er_diagram.rb +417 -0
- data/lib/sirena/renderer/error.rb +131 -0
- data/lib/sirena/renderer/flowchart.rb +301 -0
- data/lib/sirena/renderer/gantt.rb +331 -0
- data/lib/sirena/renderer/git_graph.rb +368 -0
- data/lib/sirena/renderer/info.rb +93 -0
- data/lib/sirena/renderer/kanban.rb +295 -0
- data/lib/sirena/renderer/mindmap.rb +396 -0
- data/lib/sirena/renderer/packet.rb +239 -0
- data/lib/sirena/renderer/pie.rb +235 -0
- data/lib/sirena/renderer/quadrant.rb +292 -0
- data/lib/sirena/renderer/radar.rb +323 -0
- data/lib/sirena/renderer/requirement.rb +371 -0
- data/lib/sirena/renderer/sankey.rb +255 -0
- data/lib/sirena/renderer/sequence.rb +424 -0
- data/lib/sirena/renderer/state_diagram.rb +328 -0
- data/lib/sirena/renderer/timeline.rb +304 -0
- data/lib/sirena/renderer/treemap.rb +152 -0
- data/lib/sirena/renderer/user_journey.rb +331 -0
- data/lib/sirena/renderer/xy_chart.rb +452 -0
- data/lib/sirena/renderer.rb +8 -0
- data/lib/sirena/svg/circle.rb +41 -0
- data/lib/sirena/svg/document.rb +103 -0
- data/lib/sirena/svg/element.rb +65 -0
- data/lib/sirena/svg/ellipse.rb +33 -0
- data/lib/sirena/svg/group.rb +71 -0
- data/lib/sirena/svg/line.rb +49 -0
- data/lib/sirena/svg/path.rb +76 -0
- data/lib/sirena/svg/polygon.rb +43 -0
- data/lib/sirena/svg/polyline.rb +35 -0
- data/lib/sirena/svg/rect.rb +57 -0
- data/lib/sirena/svg/style.rb +44 -0
- data/lib/sirena/svg/text.rb +72 -0
- data/lib/sirena/svg.rb +19 -0
- data/lib/sirena/text_measurement.rb +71 -0
- data/lib/sirena/theme/builtin/dark.yml +70 -0
- data/lib/sirena/theme/builtin/default.yml +80 -0
- data/lib/sirena/theme/builtin/high_contrast.yml +70 -0
- data/lib/sirena/theme/builtin/light.yml +70 -0
- data/lib/sirena/theme/color_palette.rb +48 -0
- data/lib/sirena/theme/effect_styles.rb +28 -0
- data/lib/sirena/theme/registry.rb +41 -0
- data/lib/sirena/theme/shape_styles.rb +28 -0
- data/lib/sirena/theme/spacing_config.rb +24 -0
- data/lib/sirena/theme/typography.rb +30 -0
- data/lib/sirena/theme.rb +69 -0
- data/lib/sirena/transform/architecture.rb +273 -0
- data/lib/sirena/transform/base.rb +199 -0
- data/lib/sirena/transform/block.rb +215 -0
- data/lib/sirena/transform/c4.rb +288 -0
- data/lib/sirena/transform/class_diagram.rb +296 -0
- data/lib/sirena/transform/er_diagram.rb +204 -0
- data/lib/sirena/transform/error.rb +39 -0
- data/lib/sirena/transform/flowchart.rb +161 -0
- data/lib/sirena/transform/gantt.rb +253 -0
- data/lib/sirena/transform/git_graph.rb +283 -0
- data/lib/sirena/transform/info.rb +39 -0
- data/lib/sirena/transform/kanban.rb +180 -0
- data/lib/sirena/transform/mindmap.rb +251 -0
- data/lib/sirena/transform/packet.rb +185 -0
- data/lib/sirena/transform/pie.rb +62 -0
- data/lib/sirena/transform/quadrant.rb +167 -0
- data/lib/sirena/transform/radar.rb +227 -0
- data/lib/sirena/transform/requirement.rb +233 -0
- data/lib/sirena/transform/sankey.rb +212 -0
- data/lib/sirena/transform/sequence.rb +143 -0
- data/lib/sirena/transform/state_diagram.rb +228 -0
- data/lib/sirena/transform/timeline.rb +139 -0
- data/lib/sirena/transform/treemap.rb +120 -0
- data/lib/sirena/transform/user_journey.rb +207 -0
- data/lib/sirena/transform/xy_chart.rb +273 -0
- data/lib/sirena/transform.rb +8 -0
- data/lib/sirena/version.rb +5 -0
- data/lib/sirena.rb +328 -0
- data/lib/tasks/benchmark.rake +532 -0
- data/lib/tasks/examples.rake +468 -0
- data/lib/tasks/generate_mermaid_fixtures.rake +363 -0
- data/lib/tasks/mermaid_fixtures.rake +46 -0
- data/scripts/extract_mermaid_tests.rb +493 -0
- data/scripts/rename_to_sirena.rb +73 -0
- data/sirena.gemspec +47 -0
- metadata +529 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Sirena
|
|
6
|
+
module Diagram
|
|
7
|
+
# Architecture diagram model representing system architecture visualization
|
|
8
|
+
class ArchitectureDiagram < Lutaml::Model::Serializable
|
|
9
|
+
# Group (boundary) in architecture diagram
|
|
10
|
+
class Group < Lutaml::Model::Serializable
|
|
11
|
+
attribute :id, :string
|
|
12
|
+
attribute :label, :string
|
|
13
|
+
attribute :icon, :string
|
|
14
|
+
attribute :parent_id, :string
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Service/component in architecture diagram
|
|
18
|
+
class Service < Lutaml::Model::Serializable
|
|
19
|
+
attribute :id, :string
|
|
20
|
+
attribute :label, :string
|
|
21
|
+
attribute :icon, :string
|
|
22
|
+
attribute :group_id, :string
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Edge (relationship) between services
|
|
26
|
+
class Edge < Lutaml::Model::Serializable
|
|
27
|
+
attribute :from_id, :string
|
|
28
|
+
attribute :to_id, :string
|
|
29
|
+
attribute :from_position, :string
|
|
30
|
+
attribute :to_position, :string
|
|
31
|
+
attribute :label, :string
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
attribute :title, :string
|
|
35
|
+
attribute :acc_title, :string
|
|
36
|
+
attribute :acc_descr, :string
|
|
37
|
+
attribute :groups, Group, collection: true, default: -> { [] }
|
|
38
|
+
attribute :services, Service, collection: true, default: -> { [] }
|
|
39
|
+
attribute :edges, Edge, collection: true, default: -> { [] }
|
|
40
|
+
|
|
41
|
+
def type
|
|
42
|
+
"architecture"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lutaml/model'
|
|
4
|
+
|
|
5
|
+
module Sirena
|
|
6
|
+
module Diagram
|
|
7
|
+
# Abstract base class for all diagram models.
|
|
8
|
+
#
|
|
9
|
+
# This class provides common attributes and functionality shared across
|
|
10
|
+
# all diagram types. Specific diagram types (Flowchart, Sequence, etc.)
|
|
11
|
+
# inherit from this base and add their type-specific attributes.
|
|
12
|
+
#
|
|
13
|
+
# All diagram models use Lutaml::Model for serialization support.
|
|
14
|
+
#
|
|
15
|
+
# @example Define a custom diagram type
|
|
16
|
+
# class Flowchart < Diagram::Base
|
|
17
|
+
# attribute :nodes, :array
|
|
18
|
+
# attribute :edges, :array
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# @abstract Subclass and add diagram-specific attributes
|
|
22
|
+
class Base < Lutaml::Model::Serializable
|
|
23
|
+
# Unique identifier for the diagram
|
|
24
|
+
attribute :id, :string
|
|
25
|
+
|
|
26
|
+
# Optional title for the diagram
|
|
27
|
+
attribute :title, :string
|
|
28
|
+
|
|
29
|
+
# Direction or orientation of the diagram
|
|
30
|
+
# (e.g., 'TB' for top-to-bottom, 'LR' for left-to-right)
|
|
31
|
+
attribute :direction, :string
|
|
32
|
+
|
|
33
|
+
# Optional theme or style configuration
|
|
34
|
+
attribute :theme, :string
|
|
35
|
+
|
|
36
|
+
# Validates that required diagram structure is present.
|
|
37
|
+
#
|
|
38
|
+
# This method should be overridden by subclasses to implement
|
|
39
|
+
# diagram-specific validation logic.
|
|
40
|
+
#
|
|
41
|
+
# @return [Boolean] true if diagram is valid
|
|
42
|
+
# @raise [NotImplementedError] if not implemented by subclass
|
|
43
|
+
def valid?
|
|
44
|
+
raise NotImplementedError,
|
|
45
|
+
"#{self.class} must implement #valid?"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns the diagram type identifier.
|
|
49
|
+
#
|
|
50
|
+
# This method should be overridden by subclasses to return their
|
|
51
|
+
# specific diagram type.
|
|
52
|
+
#
|
|
53
|
+
# @return [Symbol] the diagram type identifier
|
|
54
|
+
# @raise [NotImplementedError] if not implemented by subclass
|
|
55
|
+
def diagram_type
|
|
56
|
+
raise NotImplementedError,
|
|
57
|
+
"#{self.class} must implement #diagram_type"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Sirena
|
|
6
|
+
module Diagram
|
|
7
|
+
# Represents a block in the diagram
|
|
8
|
+
class Block < Lutaml::Model::Serializable
|
|
9
|
+
attribute :id, :string
|
|
10
|
+
attribute :label, :string
|
|
11
|
+
attribute :width, :integer, default: -> { 1 }
|
|
12
|
+
attribute :shape, :string, default: -> { "rect" }
|
|
13
|
+
attribute :children, Block, collection: true, default: -> { [] }
|
|
14
|
+
attribute :block_type, :string # "block", "space", "arrow"
|
|
15
|
+
attribute :direction, :string # for arrow blocks: "up", "down", "left", "right"
|
|
16
|
+
attribute :is_compound, :boolean, default: -> { false }
|
|
17
|
+
|
|
18
|
+
def compound?
|
|
19
|
+
is_compound
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def space?
|
|
23
|
+
block_type == "space"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def arrow?
|
|
27
|
+
block_type == "arrow"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def add_child(child)
|
|
31
|
+
children << child
|
|
32
|
+
self.is_compound = true
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Represents a connection between blocks
|
|
37
|
+
class BlockConnection < Lutaml::Model::Serializable
|
|
38
|
+
attribute :from, :string
|
|
39
|
+
attribute :to, :string
|
|
40
|
+
attribute :connection_type, :string # "arrow" or "line"
|
|
41
|
+
attribute :label, :string
|
|
42
|
+
|
|
43
|
+
def arrow?
|
|
44
|
+
connection_type == "arrow"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def line?
|
|
48
|
+
connection_type == "line"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Represents styling for a block
|
|
53
|
+
class BlockStyle < Lutaml::Model::Serializable
|
|
54
|
+
attribute :block_id, :string
|
|
55
|
+
attribute :fill, :string
|
|
56
|
+
attribute :stroke, :string
|
|
57
|
+
attribute :stroke_width, :string
|
|
58
|
+
attribute :properties, :string, collection: true, default: -> { [] }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Represents a Mermaid block diagram
|
|
62
|
+
class BlockDiagram < Lutaml::Model::Serializable
|
|
63
|
+
attribute :columns, :integer, default: -> { 1 }
|
|
64
|
+
attribute :blocks, Block, collection: true, default: -> { [] }
|
|
65
|
+
attribute :connections, BlockConnection, collection: true, default: -> { [] }
|
|
66
|
+
attribute :styles, BlockStyle, collection: true, default: -> { [] }
|
|
67
|
+
|
|
68
|
+
def add_block(block)
|
|
69
|
+
blocks << block
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def add_connection(connection)
|
|
73
|
+
connections << connection
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def add_style(style)
|
|
77
|
+
styles << style
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lutaml/model'
|
|
4
|
+
require_relative 'base'
|
|
5
|
+
|
|
6
|
+
module Sirena
|
|
7
|
+
module Diagram
|
|
8
|
+
# Represents a C4 element (Person, System, Container, Component).
|
|
9
|
+
#
|
|
10
|
+
# Elements are the nodes in C4 diagrams representing various architectural
|
|
11
|
+
# entities like people, systems, containers, and components.
|
|
12
|
+
class C4Element < Lutaml::Model::Serializable
|
|
13
|
+
# Unique identifier for the element
|
|
14
|
+
attribute :id, :string
|
|
15
|
+
|
|
16
|
+
# Display label
|
|
17
|
+
attribute :label, :string
|
|
18
|
+
|
|
19
|
+
# Element type: Person, Person_Ext, System, System_Ext, SystemDb,
|
|
20
|
+
# SystemDb_Ext, SystemQueue, SystemQueue_Ext, Container, ContainerDb,
|
|
21
|
+
# ContainerQueue, Component
|
|
22
|
+
attribute :element_type, :string
|
|
23
|
+
|
|
24
|
+
# Description text
|
|
25
|
+
attribute :description, :string
|
|
26
|
+
|
|
27
|
+
# Technology stack (for Containers and Components)
|
|
28
|
+
attribute :technology, :string
|
|
29
|
+
|
|
30
|
+
# Sprite icon name
|
|
31
|
+
attribute :sprite, :string
|
|
32
|
+
|
|
33
|
+
# Link URL
|
|
34
|
+
attribute :link, :string
|
|
35
|
+
|
|
36
|
+
# Tags (comma-separated)
|
|
37
|
+
attribute :tags, :string
|
|
38
|
+
|
|
39
|
+
# Whether element is external (_Ext suffix)
|
|
40
|
+
attribute :external, :boolean, default: -> { false }
|
|
41
|
+
|
|
42
|
+
# Parent boundary ID (if nested)
|
|
43
|
+
attribute :boundary_id, :string
|
|
44
|
+
|
|
45
|
+
# Validates the element has required attributes.
|
|
46
|
+
#
|
|
47
|
+
# @return [Boolean] true if element is valid
|
|
48
|
+
def valid?
|
|
49
|
+
!id.nil? && !id.empty? &&
|
|
50
|
+
!label.nil? && !label.empty? &&
|
|
51
|
+
!element_type.nil?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Returns base type without _Ext suffix
|
|
55
|
+
#
|
|
56
|
+
# @return [String] base element type
|
|
57
|
+
def base_type
|
|
58
|
+
element_type&.gsub(/_Ext$/, '') || element_type
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Check if element is a person
|
|
62
|
+
#
|
|
63
|
+
# @return [Boolean] true if person
|
|
64
|
+
def person?
|
|
65
|
+
base_type == 'Person'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Check if element is a system
|
|
69
|
+
#
|
|
70
|
+
# @return [Boolean] true if system
|
|
71
|
+
def system?
|
|
72
|
+
%w[System SystemDb SystemQueue].include?(base_type)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Check if element is a container
|
|
76
|
+
#
|
|
77
|
+
# @return [Boolean] true if container
|
|
78
|
+
def container?
|
|
79
|
+
%w[Container ContainerDb ContainerQueue].include?(base_type)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Check if element is a component
|
|
83
|
+
#
|
|
84
|
+
# @return [Boolean] true if component
|
|
85
|
+
def component?
|
|
86
|
+
base_type == 'Component'
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Represents a C4 relationship between elements.
|
|
91
|
+
#
|
|
92
|
+
# Relationships show interactions or dependencies between architectural
|
|
93
|
+
# elements.
|
|
94
|
+
class C4Relationship < Lutaml::Model::Serializable
|
|
95
|
+
# Source element identifier
|
|
96
|
+
attribute :from_id, :string
|
|
97
|
+
|
|
98
|
+
# Target element identifier
|
|
99
|
+
attribute :to_id, :string
|
|
100
|
+
|
|
101
|
+
# Relationship label
|
|
102
|
+
attribute :label, :string
|
|
103
|
+
|
|
104
|
+
# Technology used in relationship
|
|
105
|
+
attribute :technology, :string
|
|
106
|
+
|
|
107
|
+
# Relationship type: Rel, BiRel
|
|
108
|
+
attribute :rel_type, :string
|
|
109
|
+
|
|
110
|
+
# Initialize with default type
|
|
111
|
+
def initialize(*args)
|
|
112
|
+
super
|
|
113
|
+
self.rel_type ||= 'Rel'
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Validates the relationship has required attributes.
|
|
117
|
+
#
|
|
118
|
+
# @return [Boolean] true if relationship is valid
|
|
119
|
+
def valid?
|
|
120
|
+
!from_id.nil? && !from_id.empty? &&
|
|
121
|
+
!to_id.nil? && !to_id.empty?
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Check if bidirectional relationship
|
|
125
|
+
#
|
|
126
|
+
# @return [Boolean] true if bidirectional
|
|
127
|
+
def bidirectional?
|
|
128
|
+
rel_type == 'BiRel'
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Represents a C4 boundary grouping.
|
|
133
|
+
#
|
|
134
|
+
# Boundaries group related elements together, representing enterprise
|
|
135
|
+
# boundaries, system boundaries, or custom boundaries.
|
|
136
|
+
class C4Boundary < Lutaml::Model::Serializable
|
|
137
|
+
# Unique identifier for the boundary
|
|
138
|
+
attribute :id, :string
|
|
139
|
+
|
|
140
|
+
# Display label
|
|
141
|
+
attribute :label, :string
|
|
142
|
+
|
|
143
|
+
# Boundary type: Enterprise_Boundary, System_Boundary, Boundary
|
|
144
|
+
attribute :boundary_type, :string
|
|
145
|
+
|
|
146
|
+
# Additional type parameter (for generic Boundary)
|
|
147
|
+
attribute :type_param, :string
|
|
148
|
+
|
|
149
|
+
# Link URL
|
|
150
|
+
attribute :link, :string
|
|
151
|
+
|
|
152
|
+
# Tags (comma-separated)
|
|
153
|
+
attribute :tags, :string
|
|
154
|
+
|
|
155
|
+
# Nested elements (element IDs)
|
|
156
|
+
attribute :element_ids, :string, collection: true, default: -> { [] }
|
|
157
|
+
|
|
158
|
+
# Nested boundaries (boundary IDs)
|
|
159
|
+
attribute :boundary_ids, :string, collection: true, default: -> { [] }
|
|
160
|
+
|
|
161
|
+
# Parent boundary ID (if nested)
|
|
162
|
+
attribute :parent_id, :string
|
|
163
|
+
|
|
164
|
+
# Initialize with default type
|
|
165
|
+
def initialize(*args)
|
|
166
|
+
super
|
|
167
|
+
self.boundary_type ||= 'Boundary'
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Validates the boundary has required attributes.
|
|
171
|
+
#
|
|
172
|
+
# @return [Boolean] true if boundary is valid
|
|
173
|
+
def valid?
|
|
174
|
+
!id.nil? && !id.empty? &&
|
|
175
|
+
!label.nil? && !label.empty?
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Check if enterprise boundary
|
|
179
|
+
#
|
|
180
|
+
# @return [Boolean] true if enterprise boundary
|
|
181
|
+
def enterprise?
|
|
182
|
+
boundary_type == 'Enterprise_Boundary'
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Check if system boundary
|
|
186
|
+
#
|
|
187
|
+
# @return [Boolean] true if system boundary
|
|
188
|
+
def system?
|
|
189
|
+
boundary_type == 'System_Boundary'
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# C4 diagram model.
|
|
194
|
+
#
|
|
195
|
+
# Represents a complete C4 diagram showing software architecture at
|
|
196
|
+
# different levels of abstraction: Context, Container, Component, or Code.
|
|
197
|
+
#
|
|
198
|
+
# @example Creating a C4 Context diagram
|
|
199
|
+
# c4 = C4.new(level: 'Context')
|
|
200
|
+
# c4.title = 'System Context diagram'
|
|
201
|
+
# c4.elements << C4Element.new(
|
|
202
|
+
# id: 'customer',
|
|
203
|
+
# label: 'Customer',
|
|
204
|
+
# element_type: 'Person',
|
|
205
|
+
# description: 'A user of the system'
|
|
206
|
+
# )
|
|
207
|
+
# c4.elements << C4Element.new(
|
|
208
|
+
# id: 'system',
|
|
209
|
+
# label: 'Banking System',
|
|
210
|
+
# element_type: 'System',
|
|
211
|
+
# description: 'Main banking application'
|
|
212
|
+
# )
|
|
213
|
+
# c4.relationships << C4Relationship.new(
|
|
214
|
+
# from_id: 'customer',
|
|
215
|
+
# to_id: 'system',
|
|
216
|
+
# label: 'Uses'
|
|
217
|
+
# )
|
|
218
|
+
class C4 < Base
|
|
219
|
+
# C4 level: Context, Container, Component, Dynamic, Deployment
|
|
220
|
+
attribute :level, :string
|
|
221
|
+
|
|
222
|
+
# Diagram title
|
|
223
|
+
attribute :title, :string
|
|
224
|
+
|
|
225
|
+
# Collection of elements
|
|
226
|
+
attribute :elements, C4Element, collection: true, default: -> { [] }
|
|
227
|
+
|
|
228
|
+
# Collection of relationships
|
|
229
|
+
attribute :relationships, C4Relationship, collection: true,
|
|
230
|
+
default: -> { [] }
|
|
231
|
+
|
|
232
|
+
# Collection of boundaries
|
|
233
|
+
attribute :boundaries, C4Boundary, collection: true, default: -> { [] }
|
|
234
|
+
|
|
235
|
+
# Layout configuration
|
|
236
|
+
attribute :layout_config, :string
|
|
237
|
+
|
|
238
|
+
# Initialize with default level
|
|
239
|
+
def initialize(*args)
|
|
240
|
+
super
|
|
241
|
+
self.level ||= 'Context'
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# Returns the diagram type identifier.
|
|
245
|
+
#
|
|
246
|
+
# @return [Symbol] :c4
|
|
247
|
+
def diagram_type
|
|
248
|
+
:c4
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Validates the C4 diagram structure.
|
|
252
|
+
#
|
|
253
|
+
# A C4 diagram is valid if:
|
|
254
|
+
# - It has a valid level
|
|
255
|
+
# - All elements are valid
|
|
256
|
+
# - All relationships are valid
|
|
257
|
+
# - All boundaries are valid
|
|
258
|
+
# - All relationship references point to existing elements
|
|
259
|
+
#
|
|
260
|
+
# @return [Boolean] true if C4 diagram is valid
|
|
261
|
+
def valid?
|
|
262
|
+
return false unless %w[Context Container Component Dynamic
|
|
263
|
+
Deployment].include?(level)
|
|
264
|
+
return false unless elements.nil? || elements.all?(&:valid?)
|
|
265
|
+
return false unless relationships.nil? ||
|
|
266
|
+
relationships.all?(&:valid?)
|
|
267
|
+
return false unless boundaries.nil? || boundaries.all?(&:valid?)
|
|
268
|
+
|
|
269
|
+
# Validate relationship references
|
|
270
|
+
element_ids = elements.map(&:id)
|
|
271
|
+
relationships&.each do |rel|
|
|
272
|
+
return false unless element_ids.include?(rel.from_id)
|
|
273
|
+
return false unless element_ids.include?(rel.to_id)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
true
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Finds an element by its identifier.
|
|
280
|
+
#
|
|
281
|
+
# @param id [String] the element identifier to find
|
|
282
|
+
# @return [C4Element, nil] the element or nil if not found
|
|
283
|
+
def find_element(id)
|
|
284
|
+
elements.find { |e| e.id == id }
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
# Finds a boundary by its identifier.
|
|
288
|
+
#
|
|
289
|
+
# @param id [String] the boundary identifier to find
|
|
290
|
+
# @return [C4Boundary, nil] the boundary or nil if not found
|
|
291
|
+
def find_boundary(id)
|
|
292
|
+
boundaries.find { |b| b.id == id }
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# Finds relationships from a specific element.
|
|
296
|
+
#
|
|
297
|
+
# @param element_id [String] the source element identifier
|
|
298
|
+
# @return [Array<C4Relationship>] relationships from the element
|
|
299
|
+
def relationships_from(element_id)
|
|
300
|
+
relationships.select { |r| r.from_id == element_id }
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# Finds relationships to a specific element.
|
|
304
|
+
#
|
|
305
|
+
# @param element_id [String] the target element identifier
|
|
306
|
+
# @return [Array<C4Relationship>] relationships to the element
|
|
307
|
+
def relationships_to(element_id)
|
|
308
|
+
relationships.select { |r| r.to_id == element_id }
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# Finds elements within a boundary.
|
|
312
|
+
#
|
|
313
|
+
# @param boundary_id [String] the boundary identifier
|
|
314
|
+
# @return [Array<C4Element>] elements in the boundary
|
|
315
|
+
def elements_in_boundary(boundary_id)
|
|
316
|
+
elements.select { |e| e.boundary_id == boundary_id }
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Finds child boundaries within a parent boundary.
|
|
320
|
+
#
|
|
321
|
+
# @param boundary_id [String] the parent boundary identifier
|
|
322
|
+
# @return [Array<C4Boundary>] child boundaries
|
|
323
|
+
def boundaries_in_boundary(boundary_id)
|
|
324
|
+
boundaries.select { |b| b.parent_id == boundary_id }
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
end
|