graphy 0.1.0 → 0.1.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/.gitignore +1 -0
- data/README.md +9 -5
- data/examples/example00.rb +7 -7
- data/examples/example00.rb.png +0 -0
- data/examples/example01.rb +1 -1
- data/examples/example01.rb.png +0 -0
- data/examples/example02.rb +3 -4
- data/examples/example02.rb.png +0 -0
- data/examples/example03.rb +15 -0
- data/examples/example03.rb.png +0 -0
- data/lib/graphy.rb +2 -1
- data/lib/graphy/diagram.rb +75 -0
- data/lib/graphy/dsl.rb +12 -55
- data/lib/graphy/entity.rb +12 -4
- data/lib/graphy/node.rb +49 -19
- data/lib/graphy/registry.rb +28 -0
- data/lib/graphy/version.rb +1 -1
- metadata +6 -4
- data/Gemfile.lock +0 -25
- data/lib/graphy/dependency.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90422fd37ee6183c87ab531c8841bfea10d9da59385f10f9d440b4095aeb24a8
|
4
|
+
data.tar.gz: 8bcb771712386cbeb5f9d2fb2e9e76030c9a6a18e79d8550f3bf28610d7d4624
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5980d5b6a4c0ef3ef5867a11cf91b8c927431803c8f2d74b6b091b2d789b06fa1715cce4b6b6db927708bafb61c405e47027945388a087fc4e1c35232401d102
|
7
|
+
data.tar.gz: 3526fbda93e7ad3a960eb4e722024a89d1633414f45eeac5309ca7f8f2d7e223c9a900954d9ef05db4de543e256fc0d437ed33ec9bb3084f0e8daa92a08ac3cd
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Graphy
|
2
2
|
|
3
|
-
|
3
|
+
DSL to create graph diagrams as code
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -23,7 +23,7 @@ Or install it yourself as:
|
|
23
23
|
### Module
|
24
24
|
|
25
25
|
```ruby
|
26
|
-
Graphy.define '
|
26
|
+
Graphy.define 'Life View' do
|
27
27
|
entity 'Friendly'
|
28
28
|
namespace "Animal Kingdom" do
|
29
29
|
entity 'Animal' do
|
@@ -31,12 +31,12 @@ Graphy.define 'UML View' do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
entity 'Dog', 'Animal' do
|
34
|
-
|
34
|
+
attrs :color
|
35
35
|
uses 'Friendly'
|
36
36
|
end
|
37
37
|
|
38
38
|
entity 'Cat', 'Animal' do
|
39
|
-
|
39
|
+
meths :scratch
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -44,10 +44,13 @@ Graphy.define 'UML View' do
|
|
44
44
|
end
|
45
45
|
```
|
46
46
|
|
47
|
+

|
48
|
+
|
49
|
+
|
47
50
|
### State machine
|
48
51
|
|
49
52
|
```ruby
|
50
|
-
Graphy.define 'State machine' do
|
53
|
+
Graphy.define 'State machine', orientation: :horizontal do
|
51
54
|
node 'A'
|
52
55
|
node 'B', shape: 'diamond'
|
53
56
|
node 'C'
|
@@ -62,6 +65,7 @@ Graphy.define 'State machine' do
|
|
62
65
|
write(png: 'steps.png')
|
63
66
|
end
|
64
67
|
```
|
68
|
+

|
65
69
|
|
66
70
|
## Development
|
67
71
|
|
data/examples/example00.rb
CHANGED
@@ -2,12 +2,12 @@ require 'bundler/setup'
|
|
2
2
|
require 'graphviz/dsl'
|
3
3
|
|
4
4
|
digraph :example do
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
cluster_0 do
|
6
|
+
graph[label: 'Animal Kingdom']
|
7
|
+
animal << dog
|
8
|
+
animal << cat
|
9
|
+
end
|
10
|
+
friendly << dog
|
11
11
|
|
12
|
-
|
12
|
+
output(png: "#{$0}.png")
|
13
13
|
end
|
data/examples/example00.rb.png
CHANGED
Binary file
|
data/examples/example01.rb
CHANGED
data/examples/example01.rb.png
CHANGED
Binary file
|
data/examples/example02.rb
CHANGED
@@ -2,18 +2,17 @@ require 'bundler/setup'
|
|
2
2
|
require 'graphy'
|
3
3
|
|
4
4
|
Graphy.define 'Life View' do
|
5
|
-
entity 'Friendly'
|
6
5
|
entity 'Animal' do
|
7
|
-
|
6
|
+
attrs :name, :other
|
8
7
|
end
|
9
8
|
|
10
9
|
entity 'Dog', 'Animal' do
|
11
|
-
|
10
|
+
attrs :color
|
12
11
|
uses 'Friendly'
|
13
12
|
end
|
14
13
|
|
15
14
|
entity 'Cat', 'Animal' do
|
16
|
-
|
15
|
+
meths :scratch
|
17
16
|
end
|
18
17
|
|
19
18
|
write png: "#{$0}.png"
|
data/examples/example02.rb.png
CHANGED
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'graphy'
|
3
|
+
|
4
|
+
Graphy.define 'Life View' do
|
5
|
+
entity 'Friendly'
|
6
|
+
namespace 'Animal Kingdom' do
|
7
|
+
entity 'Animal'
|
8
|
+
entity 'Dog', 'Animal' do
|
9
|
+
uses 'Friendly'
|
10
|
+
end
|
11
|
+
entity 'Cat', 'Animal'
|
12
|
+
end
|
13
|
+
|
14
|
+
write png: "#{$0}.png"
|
15
|
+
end
|
Binary file
|
data/lib/graphy.rb
CHANGED
@@ -0,0 +1,75 @@
|
|
1
|
+
module Graphy
|
2
|
+
## GraphViz wrapper
|
3
|
+
class Diagram
|
4
|
+
attr_accessor :graph, :edges
|
5
|
+
|
6
|
+
GRAPH_ATTRIBUTES = {
|
7
|
+
ranksep: 0.5,
|
8
|
+
nodesep: 0.4,
|
9
|
+
pad: '0.4,0.4',
|
10
|
+
margin: '0,0',
|
11
|
+
concentrate: true,
|
12
|
+
labelloc: :t,
|
13
|
+
fontsize: 14,
|
14
|
+
fontname: 'Arial BoldMT',
|
15
|
+
splines: 'spline'
|
16
|
+
}
|
17
|
+
|
18
|
+
NODE_ATTRIBUTES = {
|
19
|
+
shape: "Mrecord",
|
20
|
+
fontsize: 12,
|
21
|
+
fontname: "ArialMT",
|
22
|
+
margin: "0.07,0.05",
|
23
|
+
penwidth: 1.0
|
24
|
+
}
|
25
|
+
|
26
|
+
EDGE_ATTRIBUTES = {
|
27
|
+
fontname: "ArialMT",
|
28
|
+
fontsize: 10,
|
29
|
+
arrowsize: 0.9,
|
30
|
+
penwidth: 1.0,
|
31
|
+
labelangle: 32,
|
32
|
+
labeldistance: 1.8,
|
33
|
+
}
|
34
|
+
|
35
|
+
def initialize(name, options = {})
|
36
|
+
graph_opts = {
|
37
|
+
parent: options[:parent],
|
38
|
+
type: options[:parent]&.type
|
39
|
+
}.compact
|
40
|
+
@graph = GraphViz.new(name, **graph_opts)
|
41
|
+
|
42
|
+
GRAPH_ATTRIBUTES.each { |attribute, value| @graph[attribute] = value }
|
43
|
+
NODE_ATTRIBUTES.each { |attribute, value| @graph.node[attribute] = value }
|
44
|
+
EDGE_ATTRIBUTES.each { |attribute, value| @graph.edge[attribute] = value }
|
45
|
+
|
46
|
+
@graph[:rankdir] = options[:orientation] == :horizonal ? :LR : :TB
|
47
|
+
@graph[:label] = "#{name}\\n\\n"
|
48
|
+
@edges = []
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_node(name)
|
52
|
+
graph.search_node(name)
|
53
|
+
end
|
54
|
+
|
55
|
+
def node_exists?(name)
|
56
|
+
!!get_node(name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def draw_node(name, options = {})
|
60
|
+
graph.add_nodes(name, options)
|
61
|
+
end
|
62
|
+
|
63
|
+
def draw_edge(from, to, options)
|
64
|
+
graph.add_edges(from, to, options)
|
65
|
+
end
|
66
|
+
|
67
|
+
def draw_graph(diagram)
|
68
|
+
graph.add_graph(diagram.graph)
|
69
|
+
end
|
70
|
+
|
71
|
+
def write(options = {})
|
72
|
+
graph.output(options)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/graphy/dsl.rb
CHANGED
@@ -1,24 +1,14 @@
|
|
1
1
|
module Graphy
|
2
2
|
class Dsl
|
3
|
-
|
4
|
-
@edges = []
|
5
|
-
|
6
|
-
def self.registry
|
7
|
-
@registry
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.edges
|
11
|
-
@edges
|
12
|
-
end
|
3
|
+
attr_accessor :diagram
|
13
4
|
|
14
5
|
def initialize(name, options = {}, &block)
|
15
|
-
@
|
16
|
-
instance_eval(&block) if
|
6
|
+
@diagram = Diagram.new(name, options, &block)
|
7
|
+
instance_eval(&block) if block_given?
|
17
8
|
end
|
18
9
|
|
19
10
|
def namespace(name, &block)
|
20
|
-
|
21
|
-
graph.add_graph(Dsl.new(name, opts, &block).graph)
|
11
|
+
diagram.draw_graph(Dsl.new(name, { parent: diagram.graph }, &block).diagram)
|
22
12
|
end
|
23
13
|
|
24
14
|
def component(name, &block)
|
@@ -30,55 +20,22 @@ module Graphy
|
|
30
20
|
end
|
31
21
|
|
32
22
|
def node(name, shape: 'circle', &block)
|
33
|
-
|
34
|
-
|
35
|
-
node = Node.new(name, graph: graph, shape: shape)
|
36
|
-
node.instance_eval(&block) if block_given?
|
37
|
-
Dsl.registry[name] = node
|
23
|
+
options = {diagram: diagram, shape: shape}
|
24
|
+
Node.for(name, **options).build(&block)
|
38
25
|
end
|
39
26
|
|
40
27
|
def entity(name, parent = nil, &block)
|
41
|
-
|
42
|
-
|
43
|
-
entity
|
44
|
-
entity.add_dependency(parent, type: :parent) if parent
|
45
|
-
entity.instance_eval(&block) if block_given?
|
46
|
-
Dsl.registry[name] = entity
|
47
|
-
end
|
48
|
-
|
49
|
-
def step(from, to:, options: {})
|
50
|
-
return if Dsl.edges.any? { |x| [from, to] == x }
|
51
|
-
source = Dsl.registry[from].graph_node
|
52
|
-
dest = Dsl.registry[to].graph_node
|
53
|
-
return if source.nil? || dest.nil?
|
54
|
-
|
55
|
-
Dsl.edges << [from, to]
|
56
|
-
graph.add_edge(source, dest, options)
|
28
|
+
entity = Entity.new(name: name, diagram: diagram)
|
29
|
+
entity.build(&block)
|
30
|
+
entity.add_dependency(parent, color: 'blue') if parent
|
57
31
|
end
|
58
32
|
|
59
|
-
def
|
60
|
-
|
61
|
-
@graph
|
33
|
+
def step(from, to:, **options)
|
34
|
+
Node.for(from, diagram: diagram).add_dependency(to, **options)
|
62
35
|
end
|
63
36
|
|
64
37
|
def write(options = {})
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
private
|
69
|
-
|
70
|
-
def build
|
71
|
-
Dsl.registry.each do |name, node|
|
72
|
-
node.dependencies.each do |dep|
|
73
|
-
step(dep.ref, to: name, options: dep.edge_attributes)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def map_options(options = {})
|
79
|
-
align = options.delete(:align)
|
80
|
-
rankdir = align == :horizontal ? 'LR' : nil
|
81
|
-
options.merge(rankdir: rankdir).compact
|
38
|
+
diagram.write(options)
|
82
39
|
end
|
83
40
|
end
|
84
41
|
end
|
data/lib/graphy/entity.rb
CHANGED
@@ -1,16 +1,24 @@
|
|
1
1
|
module Graphy
|
2
2
|
class Entity < Node
|
3
|
-
def initialize(
|
4
|
-
super(
|
3
|
+
def initialize(**params)
|
4
|
+
super(**params.merge(shape: 'Mrecord'))
|
5
5
|
@attributes = []
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
8
|
+
def attrs(*values)
|
9
9
|
@attributes = values
|
10
10
|
end
|
11
11
|
|
12
|
+
def meths(*values)
|
13
|
+
@attributes << values.map { |x| "#{x}()"}
|
14
|
+
end
|
15
|
+
|
12
16
|
protected
|
13
17
|
|
18
|
+
def draw_edge(dependency, **options)
|
19
|
+
diagram.draw_edge(dependency.gnode, gnode, options)
|
20
|
+
end
|
21
|
+
|
14
22
|
def label
|
15
23
|
"{ #{name} #{attributes_label} }"
|
16
24
|
end
|
@@ -19,7 +27,7 @@ module Graphy
|
|
19
27
|
|
20
28
|
def attributes_label
|
21
29
|
return if @attributes.empty?
|
22
|
-
"| #{@attributes.join("\n")}"
|
30
|
+
"| #{@attributes.join("\n")}"
|
23
31
|
end
|
24
32
|
end
|
25
33
|
end
|
data/lib/graphy/node.rb
CHANGED
@@ -1,38 +1,68 @@
|
|
1
1
|
module Graphy
|
2
2
|
class Node
|
3
|
-
attr_accessor :
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
attr_accessor :name, :shape, :diagram
|
4
|
+
|
5
|
+
def self.for(node, **params)
|
6
|
+
case node
|
7
|
+
when Entity, Node
|
8
|
+
node
|
9
|
+
when String
|
10
|
+
self.new(**params.merge(name: node))
|
11
|
+
else
|
12
|
+
raise 'Invalid node class'
|
13
|
+
end
|
9
14
|
end
|
10
15
|
|
11
|
-
def
|
12
|
-
@
|
16
|
+
def initialize(**params)
|
17
|
+
@name = params[:name].to_s
|
18
|
+
@diagram = params[:diagram]
|
19
|
+
@shape = params.fetch(:shape, 'circle')
|
13
20
|
end
|
14
21
|
|
15
|
-
def add_dependency(dependency,
|
16
|
-
|
22
|
+
def add_dependency(dependency, **options)
|
23
|
+
dependency = self.class.for(dependency, diagram: diagram)
|
24
|
+
return if Registry.edge?(self, dependency)
|
25
|
+
|
26
|
+
Registry.add_edge(self, dependency)
|
27
|
+
draw_edge(dependency, **options)
|
17
28
|
end
|
18
29
|
alias :uses :add_dependency
|
19
30
|
|
31
|
+
def build(&block)
|
32
|
+
instance_eval(&block) if block_given?
|
33
|
+
gnode
|
34
|
+
end
|
35
|
+
|
36
|
+
def gnode
|
37
|
+
@gnode ||= find_or_draw
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
"#{self.class}<#{name}>"
|
42
|
+
end
|
43
|
+
|
20
44
|
protected
|
21
45
|
|
22
|
-
def
|
46
|
+
def draw_edge(dependency, **options)
|
47
|
+
diagram.draw_edge(gnode, dependency.gnode, options)
|
48
|
+
end
|
49
|
+
|
50
|
+
def node_params
|
23
51
|
{
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
fontname: 'Helvetica',
|
28
|
-
style: style,
|
29
|
-
fillcolor: fillcolor,
|
30
|
-
label: label
|
31
|
-
}.compact
|
52
|
+
label: label,
|
53
|
+
shape: shape
|
54
|
+
}
|
32
55
|
end
|
33
56
|
|
34
57
|
def label
|
35
58
|
"#{name}\n"
|
36
59
|
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def find_or_draw
|
64
|
+
return diagram.get_node(name) if diagram.node_exists?(name)
|
65
|
+
diagram.draw_node(name, node_params)
|
66
|
+
end
|
37
67
|
end
|
38
68
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Graphy
|
4
|
+
class Registry
|
5
|
+
include Singleton
|
6
|
+
attr_accessor :edges
|
7
|
+
|
8
|
+
def self.edge?(source, destiny)
|
9
|
+
instance.edge?(source, destiny)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.add_edge(source, destiny)
|
13
|
+
instance.add_edge(source, destiny)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@edges = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def edge?(source, destiny)
|
21
|
+
edges.key?("#{source}->#{destiny}")
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_edge(source, destiny, options = {})
|
25
|
+
self.edges["#{source}->#{destiny}"] = options
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/graphy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: graphy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luis Ezcurdia Razo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-graphviz
|
@@ -35,7 +35,6 @@ files:
|
|
35
35
|
- ".travis.yml"
|
36
36
|
- CODE_OF_CONDUCT.md
|
37
37
|
- Gemfile
|
38
|
-
- Gemfile.lock
|
39
38
|
- LICENSE.txt
|
40
39
|
- README.md
|
41
40
|
- Rakefile
|
@@ -47,12 +46,15 @@ files:
|
|
47
46
|
- examples/example01.rb.png
|
48
47
|
- examples/example02.rb
|
49
48
|
- examples/example02.rb.png
|
49
|
+
- examples/example03.rb
|
50
|
+
- examples/example03.rb.png
|
50
51
|
- graphy.gemspec
|
51
52
|
- lib/graphy.rb
|
52
|
-
- lib/graphy/
|
53
|
+
- lib/graphy/diagram.rb
|
53
54
|
- lib/graphy/dsl.rb
|
54
55
|
- lib/graphy/entity.rb
|
55
56
|
- lib/graphy/node.rb
|
57
|
+
- lib/graphy/registry.rb
|
56
58
|
- lib/graphy/version.rb
|
57
59
|
homepage: https://github.com/3zcurdia/graphy
|
58
60
|
licenses:
|
data/Gemfile.lock
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
arq (0.1.0)
|
5
|
-
ruby-graphviz (~> 1.2.0)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
minitest (5.14.2)
|
11
|
-
rake (12.3.3)
|
12
|
-
rexml (3.2.4)
|
13
|
-
ruby-graphviz (1.2.5)
|
14
|
-
rexml
|
15
|
-
|
16
|
-
PLATFORMS
|
17
|
-
ruby
|
18
|
-
|
19
|
-
DEPENDENCIES
|
20
|
-
arq!
|
21
|
-
minitest (~> 5.0)
|
22
|
-
rake (~> 12.0)
|
23
|
-
|
24
|
-
BUNDLED WITH
|
25
|
-
2.1.4
|
data/lib/graphy/dependency.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
module Graphy
|
2
|
-
class Dependency
|
3
|
-
def self.for(reference, type: nil)
|
4
|
-
case type
|
5
|
-
when :parent
|
6
|
-
Parent
|
7
|
-
else
|
8
|
-
Default
|
9
|
-
end.new(reference)
|
10
|
-
end
|
11
|
-
|
12
|
-
class Default
|
13
|
-
attr_accessor :ref
|
14
|
-
def initialize(ref)
|
15
|
-
@ref = ref
|
16
|
-
end
|
17
|
-
|
18
|
-
def edge_attributes
|
19
|
-
{}
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class Parent < Default
|
24
|
-
def edge_attributes
|
25
|
-
{ style: 'dotted', color: 'blue' }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|