mermaid 0.0.1 → 0.0.2
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 +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +116 -12
- data/Rakefile +2 -2
- data/lib/mermaid/class_diagram_renderer.rb +45 -0
- data/lib/mermaid/element_renderers/edge_renderer.rb +19 -0
- data/lib/mermaid/element_renderers/node_renderer.rb +16 -0
- data/lib/mermaid/element_renderers/relationship_renderer.rb +24 -0
- data/lib/mermaid/element_renderers/slice_renderer.rb +16 -0
- data/lib/mermaid/element_renderers/state_renderer.rb +15 -0
- data/lib/mermaid/element_renderers/task_renderer.rb +15 -0
- data/lib/mermaid/element_renderers/transition_renderer.rb +17 -0
- data/lib/mermaid/flowchart_diagram_renderer.rb +23 -0
- data/lib/mermaid/gantt_diagram_renderer.rb +16 -0
- data/lib/mermaid/gitgraph_diagram_renderer.rb +113 -0
- data/lib/mermaid/pie_diagram_renderer.rb +16 -0
- data/lib/mermaid/state_diagram_renderer.rb +42 -0
- data/lib/mermaid/timeline_diagram_renderer.rb +29 -0
- data/lib/mermaid/version.rb +1 -1
- data/lib/mermaid.rb +20 -10
- data/sig/diagrams/base.rbs +8 -0
- data/sig/diagrams/class_diagram.rbs +18 -0
- data/sig/diagrams/elements/edge.rbs +16 -0
- data/sig/diagrams/elements/node.rbs +15 -0
- data/sig/diagrams/elements/relationship.rbs +17 -0
- data/sig/diagrams/elements/slice.rbs +16 -0
- data/sig/diagrams/elements/state.rbs +15 -0
- data/sig/diagrams/elements/task.rbs +17 -0
- data/sig/diagrams/elements/transition.rbs +16 -0
- data/sig/diagrams/flowchart_diagram.rbs +14 -0
- data/sig/diagrams/gantt_diagram.rbs +14 -0
- data/sig/diagrams/pie_diagram.rbs +14 -0
- data/sig/diagrams/state_diagram.rbs +18 -0
- data/sig/mermaid/base_diagram.rbs +31 -0
- data/sig/mermaid/state_diagram.rbs +26 -0
- metadata +168 -35
- data/lib/mermaid/base_diagram.rb +0 -13
- data/lib/mermaid/c4_diagram.rb +0 -9
- data/lib/mermaid/class_diagram.rb +0 -10
- data/lib/mermaid/er_diagram.rb +0 -9
- data/lib/mermaid/flowchart_diagram/link.rb +0 -46
- data/lib/mermaid/flowchart_diagram/node.rb +0 -36
- data/lib/mermaid/flowchart_diagram/parser.rb +0 -30
- data/lib/mermaid/flowchart_diagram.rb +0 -32
- data/lib/mermaid/gantt_diagram.rb +0 -9
- data/lib/mermaid/git_graph_diagram.rb +0 -9
- data/lib/mermaid/info_flow_diagram.rb +0 -9
- data/lib/mermaid/mindmap_diagram.rb +0 -9
- data/lib/mermaid/pie_diagram.rb +0 -9
- data/lib/mermaid/quadrant_diagram.rb +0 -10
- data/lib/mermaid/requirement_diagram.rb +0 -9
- data/lib/mermaid/sankey_diagram.rb +0 -9
- data/lib/mermaid/sequence_diagram.rb +0 -9
- data/lib/mermaid/state_diagram.rb +0 -9
- data/lib/mermaid/user_journey_diagram.rb +0 -10
- data/lib/mermaid/xy_diagram.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f45d52ec5ba6ee5b68319696a39f2d63457aef75450754a3aa8db9d00664765
|
4
|
+
data.tar.gz: 4567ecd088bfd31d769fc80a5e256e1a169c74c5ad5c349fbef5b4d42fad857b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 984eae28a2bbe392c12a23331a8b69db664252b4bc949858a46fc8d9d4025ecbaab3c7aea0a65926a0b9f5ad14737e3066aa2df8236d96e64c377f6e90de6d3e
|
7
|
+
data.tar.gz: 104f52bd0c05ba3b1ad4ad8df6deec4d594bd08255fdc728c7f547b6627872fbd4fb8cf4692d931511fd1e2202f0b1aa0a24449fcf27e7c1e1fa2e1788e57baa
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## 0.0.2 (2025-04-01)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* add ClassDiagram generator ([364782e](https://github.com/seuros/mermaid-ruby/commit/364782e86827e2fe5745e7177ab954cb5ddc3a6a))
|
9
|
+
* add release flow ([2ed9710](https://github.com/seuros/mermaid-ruby/commit/2ed9710d6f8820a91aa6f19bef4d4388a5b0bc31))
|
10
|
+
* fix diagram inital implementation ([fab6bfa](https://github.com/seuros/mermaid-ruby/commit/fab6bfa94b932902e4664d551406c77c4037f950))
|
11
|
+
* Implemented #to_mermaid functionality for StateDiagram, ClassDiagram, PieDiagram, FlowchartDiagram, GanttDiagram, GitgraphDiagram, and TimelineDiagram by creating renderer modules ([7ab6486](https://github.com/seuros/mermaid-ruby/commit/7ab64865e1cbf6a41df23aa971f8fad79a8ba274))
|
12
|
+
|
13
|
+
|
14
|
+
### Bug Fixes
|
15
|
+
|
16
|
+
* correct releaser ([2eee28c](https://github.com/seuros/mermaid-ruby/commit/2eee28cf78d9c948ea9c8a034ba48e3b12aa0c13))
|
17
|
+
|
3
18
|
## [0.1.0] - 2024-01-23
|
4
19
|
|
5
20
|
- Draft release
|
data/README.md
CHANGED
@@ -1,34 +1,138 @@
|
|
1
|
-
# Mermaid
|
1
|
+
# Mermaid Ruby
|
2
2
|
|
3
|
-
|
3
|
+
[](https://badge.fury.io/rb/mermaid)
|
4
|
+
[](https://github.com/seuros/mermaid-ruby/actions/workflows/ci.yml)
|
4
5
|
|
5
|
-
|
6
|
+
This gem provides Mermaid syntax generation capabilities for diagram objects created using the [`diagram`](https://github.com/seuros/diagram-ruby) gem.
|
7
|
+
|
8
|
+
It achieves this by adding renderer to the `diagram` gem (like `Diagrams::ClassDiagram`, `Diagrams::StateDiagram`, etc.) to add a `#to_mermaid` instance method.
|
6
9
|
|
7
10
|
## Installation
|
8
11
|
|
9
|
-
|
12
|
+
Add these lines to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem 'diagram' # The base gem for creating diagram objects
|
16
|
+
gem 'mermaid' # This gem, for generating Mermaid syntax
|
17
|
+
```
|
10
18
|
|
11
|
-
|
19
|
+
And then execute:
|
12
20
|
|
13
|
-
|
21
|
+
```bash
|
22
|
+
$ bundle install
|
23
|
+
```
|
14
24
|
|
15
|
-
|
25
|
+
Or install it yourself as:
|
16
26
|
|
17
|
-
|
27
|
+
```bash
|
28
|
+
$ gem install diagram mermaid
|
29
|
+
```
|
18
30
|
|
19
31
|
## Usage
|
20
32
|
|
21
|
-
|
33
|
+
Simply require the `mermaid` gem after requiring `diagrams`. This will automatically add the `#to_mermaid` method to the diagram classes.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'diagrams'
|
37
|
+
require 'mermaid' # This applies the patches
|
38
|
+
|
39
|
+
# --- Example: State Diagram ---
|
40
|
+
state_a = Diagrams::Elements::State.new(id: 'A', label: 'State A')
|
41
|
+
state_b = Diagrams::Elements::State.new(id: 'B')
|
42
|
+
transition1 = Diagrams::Elements::Transition.new(source_state_id: '*', target_state_id: 'A')
|
43
|
+
transition2 = Diagrams::Elements::Transition.new(source_state_id: 'A', target_state_id: 'B', label: 'Event X')
|
44
|
+
|
45
|
+
state_diagram = Diagrams::StateDiagram.new(
|
46
|
+
states: [state_a, state_b],
|
47
|
+
transitions: [transition1, transition2]
|
48
|
+
)
|
49
|
+
|
50
|
+
puts state_diagram.to_mermaid
|
51
|
+
# Output:
|
52
|
+
# stateDiagram-v2
|
53
|
+
# A : State A
|
54
|
+
# [*] --> A
|
55
|
+
# A --> B : Event X
|
56
|
+
|
57
|
+
# --- Example: Class Diagram ---
|
58
|
+
class_animal = Diagrams::Elements::ClassEntity.new(name: 'Animal', attributes: ['+String name'])
|
59
|
+
class_dog = Diagrams::Elements::ClassEntity.new(name: 'Dog', attributes: ['+String breed'], methods: ['+bark() void'])
|
60
|
+
rel_inheritance = Diagrams::Elements::Relationship.new(
|
61
|
+
source_class_name: 'Dog',
|
62
|
+
target_class_name: 'Animal',
|
63
|
+
type: 'inheritance'
|
64
|
+
)
|
65
|
+
|
66
|
+
class_diagram = Diagrams::ClassDiagram.new(
|
67
|
+
classes: [class_animal, class_dog],
|
68
|
+
relationships: [rel_inheritance]
|
69
|
+
)
|
70
|
+
|
71
|
+
puts class_diagram.to_mermaid
|
72
|
+
# Output:
|
73
|
+
# classDiagram
|
74
|
+
# class Animal {
|
75
|
+
# +String name
|
76
|
+
# }
|
77
|
+
# class Dog {
|
78
|
+
# +String breed
|
79
|
+
# +bark() void
|
80
|
+
# }
|
81
|
+
# Dog <|-- Animal
|
82
|
+
|
83
|
+
# --- Example: Flowchart ---
|
84
|
+
node1 = Diagrams::Elements::Node.new(id: 'n1', label: 'Start')
|
85
|
+
node2 = Diagrams::Elements::Node.new(id: 'n2', label: 'Process')
|
86
|
+
edge1 = Diagrams::Elements::Edge.new(source_id: 'n1', target_id: 'n2', label: 'Go')
|
87
|
+
|
88
|
+
flowchart = Diagrams::FlowchartDiagram.new(nodes: [node1, node2], edges: [edge1])
|
89
|
+
|
90
|
+
puts flowchart.to_mermaid
|
91
|
+
# Output:
|
92
|
+
# graph TD
|
93
|
+
# n1["Start"]
|
94
|
+
# n2["Process"]
|
95
|
+
# n1 -- "Go" --> n2
|
96
|
+
|
97
|
+
# --- Example: Pie Chart ---
|
98
|
+
slice1 = Diagrams::Elements::Slice.new(label: 'Work', value: 8)
|
99
|
+
slice2 = Diagrams::Elements::Slice.new(label: 'Sleep', value: 8)
|
100
|
+
slice3 = Diagrams::Elements::Slice.new(label: 'Play', value: 8)
|
101
|
+
|
102
|
+
pie_chart = Diagrams::PieDiagram.new(title: 'Daily Routine', slices: [slice1, slice2, slice3])
|
103
|
+
|
104
|
+
puts pie_chart.to_mermaid
|
105
|
+
# Output:
|
106
|
+
# pie
|
107
|
+
# title Daily Routine
|
108
|
+
# "Work" : 8
|
109
|
+
# "Sleep" : 8
|
110
|
+
# "Play" : 8
|
111
|
+
|
112
|
+
# --- Example: Gantt Chart ---
|
113
|
+
task1 = Diagrams::Elements::Task.new(id: 't1', name: 'Phase 1', start_date: '2024-01-01', end_date: '2024-01-10')
|
114
|
+
task2 = Diagrams::Elements::Task.new(id: 't2', name: 'Phase 2', start_date: '2024-01-11', end_date: '2024-01-20')
|
115
|
+
|
116
|
+
gantt_chart = Diagrams::GanttDiagram.new(title: 'Project Timeline', tasks: [task1, task2])
|
117
|
+
|
118
|
+
puts gantt_chart.to_mermaid
|
119
|
+
# Output:
|
120
|
+
# gantt
|
121
|
+
# title Project Timeline
|
122
|
+
# : Phase 1 : t1, 2024-01-01, 2024-01-10
|
123
|
+
# : Phase 2 : t2, 2024-01-11, 2024-01-20
|
124
|
+
|
125
|
+
```
|
22
126
|
|
23
127
|
## Development
|
24
128
|
|
25
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
129
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
26
130
|
|
27
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
131
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `lib/mermaid/version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
28
132
|
|
29
133
|
## Contributing
|
30
134
|
|
31
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
135
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/seuros/mermaid-ruby.
|
32
136
|
|
33
137
|
## License
|
34
138
|
|
data/Rakefile
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
# Module containing Mermaid rendering logic for Diagrams::ClassDiagram
|
5
|
+
module ClassDiagramRenderer
|
6
|
+
# @!method to_mermaid
|
7
|
+
# Generates the Mermaid syntax for the class diagram.
|
8
|
+
# @return [String] The Mermaid syntax string.
|
9
|
+
def to_mermaid
|
10
|
+
mermaid_string = +"classDiagram\n"
|
11
|
+
|
12
|
+
classes.each do |klass|
|
13
|
+
fragment = format_class_entity(klass) # Call private helper method
|
14
|
+
mermaid_string << fragment.to_s << "\n"
|
15
|
+
end
|
16
|
+
|
17
|
+
relationships.each do |rel|
|
18
|
+
mermaid_string << rel.to_mermaid_fragment.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
mermaid_string.strip
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Helper to format ClassEntity for Mermaid
|
27
|
+
def format_class_entity(klass)
|
28
|
+
diagram = "class #{klass.name}"
|
29
|
+
attributes_list = klass[:attributes] || []
|
30
|
+
methods_list = klass[:methods] || []
|
31
|
+
has_members = attributes_list.any? || methods_list.any?
|
32
|
+
diagram += " {\n" if has_members
|
33
|
+
|
34
|
+
attributes_list.each do |attr_str|
|
35
|
+
diagram += " #{attr_str}\n"
|
36
|
+
end
|
37
|
+
methods_list.each do |method_str|
|
38
|
+
diagram += " #{method_str}\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
diagram += "}\n" if has_members
|
42
|
+
diagram
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
module ElementRenderers
|
5
|
+
# Module containing Mermaid rendering logic for Diagrams::Elements::Edge
|
6
|
+
module EdgeRenderer
|
7
|
+
# @!method to_mermaid_fragment
|
8
|
+
# Generates the Mermaid fragment for a flowchart edge.
|
9
|
+
# @return [String] Mermaid syntax fragment.
|
10
|
+
def to_mermaid_fragment
|
11
|
+
if label && !label.empty?
|
12
|
+
"#{source_id} -- \"#{label}\" --> #{target_id}"
|
13
|
+
else
|
14
|
+
"#{source_id} --> #{target_id}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
module ElementRenderers
|
5
|
+
# Module containing Mermaid rendering logic for Diagrams::Elements::Node
|
6
|
+
module NodeRenderer
|
7
|
+
# @!method to_mermaid_fragment
|
8
|
+
# Generates the Mermaid fragment for a flowchart node.
|
9
|
+
# @return [String] Mermaid syntax fragment.
|
10
|
+
def to_mermaid_fragment
|
11
|
+
escaped_label = label.gsub('"', '#quot;')
|
12
|
+
"#{id}[\"#{escaped_label}\"]"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
module ElementRenderers
|
5
|
+
# Module containing Mermaid rendering logic for Diagrams::Elements::Relationship
|
6
|
+
module RelationshipRenderer
|
7
|
+
# Maps relationship type strings to Mermaid symbols
|
8
|
+
MERMAID_RELATIONSHIP_MAP = {
|
9
|
+
'inheritance' => '<|--', 'composition' => '*--', 'aggregation' => 'o--',
|
10
|
+
'association' => '-->', 'dependency' => '..>', 'realization' => '<|..',
|
11
|
+
'link' => '--'
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
# @!method to_mermaid_fragment
|
15
|
+
# Generates the Mermaid fragment for a relationship.
|
16
|
+
# @return [String] Mermaid syntax fragment.
|
17
|
+
def to_mermaid_fragment
|
18
|
+
arrow = MERMAID_RELATIONSHIP_MAP[type] || '--'
|
19
|
+
label_str = label ? " : #{label}" : ''
|
20
|
+
"#{source_class_name} #{arrow} #{target_class_name}#{label_str}\n"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
module ElementRenderers
|
5
|
+
# Module containing Mermaid rendering logic for Diagrams::Elements::Slice
|
6
|
+
module SliceRenderer
|
7
|
+
# @!method to_mermaid_fragment
|
8
|
+
# Generates the Mermaid fragment for a pie chart slice.
|
9
|
+
# @return [String] Mermaid syntax fragment.
|
10
|
+
def to_mermaid_fragment
|
11
|
+
formatted_value = value.to_i == value ? value.to_i : value
|
12
|
+
"\"#{label}\" : #{formatted_value}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
module ElementRenderers
|
5
|
+
# Module containing Mermaid rendering logic for Diagrams::Elements::State
|
6
|
+
module StateRenderer
|
7
|
+
# @!method to_mermaid_fragment
|
8
|
+
# Generates the Mermaid fragment for a state definition.
|
9
|
+
# @return [String] Mermaid syntax fragment.
|
10
|
+
def to_mermaid_fragment
|
11
|
+
label ? "#{id} : #{label}" : id
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
module ElementRenderers
|
5
|
+
# Module containing Mermaid rendering logic for Diagrams::Elements::Task
|
6
|
+
module TaskRenderer
|
7
|
+
# @!method to_mermaid_fragment
|
8
|
+
# Generates the Mermaid fragment for a Gantt task.
|
9
|
+
# @return [String] Mermaid syntax fragment.
|
10
|
+
def to_mermaid_fragment
|
11
|
+
"#{name} :#{id}, #{start_date}, #{end_date}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
module ElementRenderers
|
5
|
+
# Module containing Mermaid rendering logic for Diagrams::Elements::Transition
|
6
|
+
module TransitionRenderer
|
7
|
+
# @!method to_mermaid_fragment
|
8
|
+
# Generates the Mermaid fragment for a transition.
|
9
|
+
# @return [String] Mermaid syntax fragment.
|
10
|
+
def to_mermaid_fragment
|
11
|
+
from_node = source_state_id == '*' ? '[*]' : source_state_id
|
12
|
+
to_node = target_state_id == '*' ? '[*]' : target_state_id
|
13
|
+
label ? "#{from_node} --> #{to_node} : #{label}" : "#{from_node} --> #{to_node}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
# Module containing Mermaid rendering logic for Diagrams::FlowchartDiagram
|
5
|
+
module FlowchartDiagramRenderer
|
6
|
+
# @!method to_mermaid
|
7
|
+
# Generates the Mermaid syntax for the flowchart diagram.
|
8
|
+
# @return [String] The Mermaid syntax string.
|
9
|
+
def to_mermaid
|
10
|
+
mermaid_string = +"graph TD\n"
|
11
|
+
|
12
|
+
nodes.each do |node|
|
13
|
+
mermaid_string << " #{node.to_mermaid_fragment}\n" # Ensure newline after node
|
14
|
+
end
|
15
|
+
|
16
|
+
edges.each do |edge|
|
17
|
+
mermaid_string << " #{edge.to_mermaid_fragment}\n" # Ensure newline after edge
|
18
|
+
end
|
19
|
+
|
20
|
+
mermaid_string # Return the full string including final newline
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
# Module containing Mermaid rendering logic for Diagrams::GanttDiagram
|
5
|
+
module GanttDiagramRenderer
|
6
|
+
# @!method to_mermaid
|
7
|
+
# Generates the Mermaid syntax for the Gantt chart.
|
8
|
+
# @return [String] The Mermaid syntax string.
|
9
|
+
def to_mermaid
|
10
|
+
mermaid_string = +"gantt\n"
|
11
|
+
mermaid_string << "title #{@title}\n" if @title && !@title.empty?
|
12
|
+
tasks.each { |task| mermaid_string << task.to_mermaid_fragment << "\n" }
|
13
|
+
mermaid_string.strip
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
# Module containing Mermaid rendering logic for Diagrams::GitgraphDiagram
|
5
|
+
module GitgraphDiagramRenderer
|
6
|
+
# @!method to_mermaid
|
7
|
+
# Generates the Mermaid syntax for the gitgraph diagram.
|
8
|
+
# @return [String] The Mermaid syntax string.
|
9
|
+
def to_mermaid
|
10
|
+
mermaid_string = +"gitGraph\n"
|
11
|
+
processed_commits = Set.new # Track the current branch in Mermaid output (defaults to 'master')
|
12
|
+
|
13
|
+
# Determine initial branch (default to 'main') and add checkout
|
14
|
+
first_commit_id = commit_order.first
|
15
|
+
# Default to 'main' if no commits or first commit doesn't specify branch
|
16
|
+
# Default to 'main' if no commits exist or first commit doesn't specify branch
|
17
|
+
initial_branch = (first_commit_id ? commits[first_commit_id]&.branch_name : nil) || 'master' # Default to 'master'
|
18
|
+
mermaid_string << " checkout #{initial_branch}\n"
|
19
|
+
current_mermaid_branch = initial_branch
|
20
|
+
|
21
|
+
commit_order.each do |commit_id|
|
22
|
+
commit = commits[commit_id]
|
23
|
+
next unless commit # Skip if commit data is missing
|
24
|
+
|
25
|
+
# --- Determine Branch Context ---
|
26
|
+
commit.branch_name
|
27
|
+
|
28
|
+
# --- Handle Branch Creation & Checkout ---
|
29
|
+
# Determine the branch this commit *should* be on based on its branch_name attribute
|
30
|
+
target_branch_name = commit.branch_name
|
31
|
+
|
32
|
+
# Check if a new branch *starts* at this commit's parent
|
33
|
+
parent_commit_id = commit.parent_ids.first
|
34
|
+
new_branch_starting_here = nil
|
35
|
+
# Only consider branching if the target is NOT master and IS different from current
|
36
|
+
if parent_commit_id && target_branch_name != 'master' && target_branch_name != current_mermaid_branch
|
37
|
+
# Check if a branch object exists that starts at the parent and matches the target name
|
38
|
+
new_branch_starting_here = branches.values.find do |b|
|
39
|
+
b.start_commit_id == parent_commit_id && b.name == target_branch_name
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if new_branch_starting_here
|
44
|
+
# Ensure we are on the parent branch before creating the new one
|
45
|
+
parent_commit = commits[parent_commit_id]
|
46
|
+
parent_branch_name = parent_commit&.branch_name
|
47
|
+
if parent_branch_name && parent_branch_name != current_mermaid_branch
|
48
|
+
mermaid_string << " checkout #{parent_branch_name}\n"
|
49
|
+
current_mermaid_branch = parent_branch_name
|
50
|
+
end
|
51
|
+
mermaid_string << " branch #{target_branch_name}\n"
|
52
|
+
# No checkout here, the next check handles it
|
53
|
+
end
|
54
|
+
|
55
|
+
# Now, handle checkout if needed for the current commit
|
56
|
+
if target_branch_name != current_mermaid_branch
|
57
|
+
# Always checkout if the branch differs from the last known Mermaid branch
|
58
|
+
mermaid_string << " checkout #{target_branch_name}\n"
|
59
|
+
current_mermaid_branch = target_branch_name
|
60
|
+
end
|
61
|
+
|
62
|
+
# --- Handle Merge ---
|
63
|
+
if commit.type == :MERGE && commit.parent_ids.length == 2 && !processed_commits.include?(commit_id)
|
64
|
+
# Identify both parents
|
65
|
+
parent1_id = commit.parent_ids[0]
|
66
|
+
parent2_id = commit.parent_ids[1]
|
67
|
+
parent1_commit = commits[parent1_id]
|
68
|
+
parent2_commit = commits[parent2_id]
|
69
|
+
|
70
|
+
# Find the parent commit whose branch is NOT the current branch
|
71
|
+
source_commit = if parent1_commit&.branch_name != current_mermaid_branch
|
72
|
+
parent1_commit
|
73
|
+
elsif parent2_commit&.branch_name != current_mermaid_branch
|
74
|
+
parent2_commit
|
75
|
+
end
|
76
|
+
source_branch_name = source_commit&.branch_name
|
77
|
+
|
78
|
+
# Ensure source branch is valid and different from target
|
79
|
+
if source_branch_name && source_branch_name != current_mermaid_branch
|
80
|
+
mermaid_string << " merge #{source_branch_name}"
|
81
|
+
mermaid_string << " id: \"#{commit.id}\""
|
82
|
+
mermaid_string << " tag: \"#{commit.tag}\"" if commit.tag
|
83
|
+
mermaid_string << "\n"
|
84
|
+
processed_commits.add(commit_id)
|
85
|
+
else
|
86
|
+
# If source branch can't be determined, generate a regular commit as fallback
|
87
|
+
warn "Could not determine source branch for merge commit #{commit_id}. Generating standard commit."
|
88
|
+
generate_commit_line(mermaid_string, commit, processed_commits) unless processed_commits.include?(commit_id)
|
89
|
+
end
|
90
|
+
|
91
|
+
# --- Handle Standard Commit ---
|
92
|
+
elsif !processed_commits.include?(commit_id)
|
93
|
+
generate_commit_line(mermaid_string, commit, processed_commits)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
mermaid_string.strip
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
# Helper to generate a standard commit line
|
103
|
+
def generate_commit_line(mermaid_string, commit, processed_commits)
|
104
|
+
mermaid_string << ' commit'
|
105
|
+
mermaid_string << " id: \"#{commit.id}\""
|
106
|
+
mermaid_string << " tag: \"#{commit.tag}\"" if commit.tag
|
107
|
+
mermaid_string << " type: #{commit.type.to_s.upcase}" unless commit.type == :NORMAL
|
108
|
+
# Mermaid doesn't directly support messages in the command, they appear on the graph
|
109
|
+
mermaid_string << "\n"
|
110
|
+
processed_commits.add(commit.id)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
# Module containing Mermaid rendering logic for Diagrams::PieDiagram
|
5
|
+
module PieDiagramRenderer
|
6
|
+
# @!method to_mermaid
|
7
|
+
# Generates the Mermaid syntax for the pie chart.
|
8
|
+
# @return [String] The Mermaid syntax string.
|
9
|
+
def to_mermaid
|
10
|
+
mermaid_string = +"pie\n"
|
11
|
+
mermaid_string << "title #{@title}\n" if @title && !@title.empty?
|
12
|
+
slices.each { |slice| mermaid_string << slice.to_mermaid_fragment << "\n" }
|
13
|
+
mermaid_string.strip
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
# Module containing Mermaid rendering logic for Diagrams::StateDiagram
|
5
|
+
module StateDiagramRenderer
|
6
|
+
# @!method to_mermaid
|
7
|
+
# Generates the Mermaid syntax for the state diagram.
|
8
|
+
# @return [String] The Mermaid syntax string.
|
9
|
+
def to_mermaid
|
10
|
+
mermaid_string = +"stateDiagram-v2\n" # Use mutable string
|
11
|
+
|
12
|
+
# Define states with labels first
|
13
|
+
states.each do |state|
|
14
|
+
mermaid_string << " #{state.to_mermaid_fragment}\n" if state.label
|
15
|
+
end
|
16
|
+
|
17
|
+
# Add transitions
|
18
|
+
transitions.each do |transition|
|
19
|
+
mermaid_string << " #{transition.to_mermaid_fragment}\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
mermaid_string.strip # Remove potential trailing newline
|
23
|
+
end
|
24
|
+
|
25
|
+
# Patch validation to allow '*' for start/end states used by Mermaid
|
26
|
+
private
|
27
|
+
|
28
|
+
def validate_elements!
|
29
|
+
# Temporarily filter out transitions involving '*' before calling original validation
|
30
|
+
original_transitions = @transitions
|
31
|
+
@transitions = original_transitions.reject do |t|
|
32
|
+
t.source_state_id == '*' || t.target_state_id == '*'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Call original validation using super
|
36
|
+
super # Calls Diagrams::StateDiagram#validate_elements!
|
37
|
+
ensure
|
38
|
+
# Restore original transitions array regardless of validation outcome
|
39
|
+
@transitions = original_transitions
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mermaid
|
4
|
+
# Module containing Mermaid rendering logic for Diagrams::TimelineDiagram
|
5
|
+
module TimelineDiagramRenderer
|
6
|
+
# @!method to_mermaid
|
7
|
+
# Generates the Mermaid syntax for the timeline diagram.
|
8
|
+
# @return [String] The Mermaid syntax string.
|
9
|
+
def to_mermaid
|
10
|
+
mermaid_string = +"timeline\n"
|
11
|
+
mermaid_string << "title #{@title}\n" if @title && !@title.empty?
|
12
|
+
|
13
|
+
sections.each do |section|
|
14
|
+
# Don't output the default section title if it's the only one and has no specific title
|
15
|
+
unless sections.size == 1 && section.title == Diagrams::TimelineDiagram::DEFAULT_SECTION_TITLE
|
16
|
+
mermaid_string << "section #{section.title}\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
section.periods.each do |period|
|
20
|
+
# Format: Period Label : Event 1 : Event 2 ...
|
21
|
+
event_descriptions = period.events.map(&:description).join(' : ')
|
22
|
+
mermaid_string << " #{period.label} : #{event_descriptions}\n"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
mermaid_string.strip
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/mermaid/version.rb
CHANGED
data/lib/mermaid.rb
CHANGED
@@ -1,17 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'mermaid/version'
|
4
|
-
require '
|
5
|
-
require 'dry-types'
|
6
|
-
require 'dry-struct'
|
4
|
+
require 'diagrams'
|
7
5
|
|
8
|
-
loader = Zeitwerk::Loader.for_gem
|
9
|
-
loader.inflector.inflect(
|
10
|
-
'er_diagram' => 'ERDiagram',
|
11
|
-
'xy_diagram' => 'XYDiagram'
|
12
|
-
)
|
6
|
+
loader = Zeitwerk::Loader.for_gem # Remove Zeitwerk setup
|
13
7
|
loader.setup
|
14
8
|
|
15
|
-
module
|
16
|
-
|
9
|
+
module Diagrams
|
10
|
+
StateDiagram.prepend(Mermaid::StateDiagramRenderer)
|
11
|
+
ClassDiagram.prepend(Mermaid::ClassDiagramRenderer)
|
12
|
+
FlowchartDiagram.prepend(Mermaid::FlowchartDiagramRenderer)
|
13
|
+
PieDiagram.prepend(Mermaid::PieDiagramRenderer)
|
14
|
+
GanttDiagram.prepend(Mermaid::GanttDiagramRenderer)
|
15
|
+
GitgraphDiagram.prepend(Mermaid::GitgraphDiagramRenderer)
|
16
|
+
TimelineDiagram.prepend(Mermaid::TimelineDiagramRenderer) # Add prepend for Timeline
|
17
|
+
module Elements
|
18
|
+
State.prepend(Mermaid::ElementRenderers::StateRenderer)
|
19
|
+
Transition.prepend(Mermaid::ElementRenderers::TransitionRenderer)
|
20
|
+
Relationship.prepend(Mermaid::ElementRenderers::RelationshipRenderer)
|
21
|
+
Node.prepend(Mermaid::ElementRenderers::NodeRenderer)
|
22
|
+
Edge.prepend(Mermaid::ElementRenderers::EdgeRenderer)
|
23
|
+
Slice.prepend(Mermaid::ElementRenderers::SliceRenderer)
|
24
|
+
Task.prepend(Mermaid::ElementRenderers::TaskRenderer)
|
25
|
+
# Add GitCommit, GitBranch, Timeline* prepends if/when renderers are created
|
26
|
+
end
|
17
27
|
end
|