jekyll-archimate 0.2.2 → 0.2.3
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/lib/jekyll-archimate.rb +23 -1
- data/lib/jekyll/archimate/application_interaction_matrix_tag.rb +42 -50
- data/lib/jekyll/archimate/archimate_cache.rb +34 -57
- data/lib/jekyll/archimate/archimate_diagram_tag.rb +6 -4
- data/lib/jekyll/archimate/archimate_generator.rb +31 -0
- data/lib/jekyll/archimate/archimate_index_generator.rb +29 -0
- data/lib/jekyll/archimate/archimate_svg_generator.rb +53 -0
- data/lib/jekyll/archimate/catalog_tag.rb +23 -12
- data/lib/jekyll/archimate/conditional_file.rb +45 -0
- data/lib/jekyll/archimate/diagram_entity.rb +19 -0
- data/lib/jekyll/archimate/element_entity.rb +26 -0
- data/lib/jekyll/archimate/entity_base.rb +29 -0
- data/lib/jekyll/archimate/folder.rb +29 -0
- data/lib/jekyll/archimate/json_file.rb +18 -0
- data/lib/jekyll/archimate/matrix_tag.rb +34 -84
- data/lib/jekyll/archimate/model_entity.rb +14 -0
- data/lib/jekyll/archimate/relationship_entity.rb +24 -0
- data/lib/jekyll/archimate/svg_file.rb +18 -0
- data/lib/jekyll/archimate/unified_model.rb +47 -0
- data/lib/jekyll/archimate/version.rb +3 -1
- metadata +15 -3
- data/lib/jekyll/archimate/archimate_hook.rb +0 -265
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Jekyll
|
2
4
|
module Archimate
|
3
5
|
# Insert a diagram from the ArchiMate model.
|
@@ -9,6 +11,7 @@ module Jekyll
|
|
9
11
|
attr_reader :caption
|
10
12
|
attr_reader :element_types
|
11
13
|
attr_reader :markup
|
14
|
+
attr_reader :model
|
12
15
|
|
13
16
|
def initialize(tag_name, markup, tokens)
|
14
17
|
@markup = markup
|
@@ -20,12 +23,13 @@ module Jekyll
|
|
20
23
|
|
21
24
|
def render(context)
|
22
25
|
@context = context
|
26
|
+
@model = ArchimateCache.instance.model
|
23
27
|
scan_attributes(context)
|
24
28
|
render_table
|
25
29
|
end
|
26
30
|
|
27
31
|
def render_table
|
28
|
-
<<-
|
32
|
+
<<-TABLE.gsub(/^ {6}/, '')
|
29
33
|
<table>
|
30
34
|
<caption>#{caption}</caption>
|
31
35
|
<thead>
|
@@ -36,26 +40,33 @@ module Jekyll
|
|
36
40
|
</tr>
|
37
41
|
</thead>
|
38
42
|
<tbody>
|
39
|
-
#{render_rows(elements
|
43
|
+
#{render_rows(elements)}
|
40
44
|
</tbody>
|
41
45
|
</table>
|
42
|
-
|
46
|
+
TABLE
|
43
47
|
end
|
44
48
|
|
45
|
-
def elements
|
46
|
-
@element_types
|
49
|
+
def elements
|
50
|
+
@element_types
|
51
|
+
.map do |element_type|
|
52
|
+
model
|
53
|
+
.elements
|
54
|
+
.select { |el| el.type == element_type }
|
55
|
+
end
|
56
|
+
.flatten
|
57
|
+
.compact
|
47
58
|
end
|
48
59
|
|
49
60
|
def render_rows(elements)
|
50
61
|
return "<tr><td colspan=\"3\">No Items</td></tr>" if elements.empty?
|
51
62
|
elements.map do |element|
|
52
|
-
<<-
|
63
|
+
<<-TABLE_ROW
|
53
64
|
<tr>
|
54
|
-
<td><span class="badge badge-primary">#{element
|
55
|
-
<td>#{@converter.convert(element
|
56
|
-
<td>#{render_properties(element
|
65
|
+
<td><span class="badge badge-primary">#{element.type}</span> #{element.name}</td>
|
66
|
+
<td>#{@converter.convert(element.documentation.to_s).gsub(%r{</?p[^>]*>}, '').chomp if element.documentation}</td>
|
67
|
+
<td>#{render_properties(element.properties)}</td>
|
57
68
|
</tr>
|
58
|
-
|
69
|
+
TABLE_ROW
|
59
70
|
end.join("")
|
60
71
|
end
|
61
72
|
|
@@ -78,7 +89,8 @@ module Jekyll
|
|
78
89
|
end
|
79
90
|
|
80
91
|
caption = attributes['caption']&.gsub!(/\A"|"\Z/, '')
|
81
|
-
@caption = @converter.convert(caption).gsub(/<\/?p[^>]*>/, '').chomp if @caption
|
92
|
+
# @caption = @converter.convert(caption).gsub(/<\/?p[^>]*>/, '').chomp if @caption
|
93
|
+
@caption = @converter.convert(caption).gsub(%r{</?p[^>]*>}, '').chomp if @caption
|
82
94
|
element_type = attributes['type']
|
83
95
|
element_type = element_type.gsub!(/\A"|"\Z/, '') if element_type
|
84
96
|
@element_types = element_type.split(",").map(&:strip)
|
@@ -98,4 +110,3 @@ module Jekyll
|
|
98
110
|
end
|
99
111
|
|
100
112
|
Liquid::Template.register_tag("catalog", Jekyll::Archimate::CatalogTag)
|
101
|
-
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Archimate
|
5
|
+
# Persists an ArchiMate diagram to a file
|
6
|
+
class ConditionalFile
|
7
|
+
attr_reader :site
|
8
|
+
attr_reader :dir
|
9
|
+
attr_reader :name
|
10
|
+
attr_reader :filename
|
11
|
+
attr_reader :archimate_file
|
12
|
+
attr_reader :relative_path
|
13
|
+
|
14
|
+
def initialize(site, dir, name, archimate_file)
|
15
|
+
@site = site
|
16
|
+
@dir = dir
|
17
|
+
@name = name
|
18
|
+
@archimate_file = archimate_file
|
19
|
+
@filename = File.join(site.source, dir, name)
|
20
|
+
@relative_path = File.join(dir, name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def needs_write?(content)
|
24
|
+
return true unless File.exist?(filename)
|
25
|
+
return true if archimate_file.modified_time.to_i > File.mtime(filename).to_i
|
26
|
+
File.read(filename) != content
|
27
|
+
end
|
28
|
+
|
29
|
+
# Writes content to filename if
|
30
|
+
# * File doesn't exit
|
31
|
+
# * Or File content is different than content
|
32
|
+
def write(content)
|
33
|
+
return unless needs_write?(content)
|
34
|
+
Jekyll.logger.info "Rendering #{relative_path}"
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def write_file(content)
|
40
|
+
File.open(filename, "w") { |file| file.write(content) }
|
41
|
+
site.static_files << Jekyll::StaticFile.new(site, site.source, dir, name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Archimate
|
5
|
+
# Represents an ArchiMate Diagram
|
6
|
+
class DiagramEntity < EntityBase
|
7
|
+
def attr_hash
|
8
|
+
super.merge(
|
9
|
+
type: "Diagram",
|
10
|
+
path: "svg/#{entity.id}.svg",
|
11
|
+
viewpoint: entity.viewpoint,
|
12
|
+
elements: entity.elements.map(&:id),
|
13
|
+
relationships: entity.relationships.map(&:id),
|
14
|
+
views: []
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Archimate
|
5
|
+
# Represents an ArchiMate Element
|
6
|
+
class ElementEntity < EntityBase
|
7
|
+
def attr_hash
|
8
|
+
super.merge(
|
9
|
+
type: "Element",
|
10
|
+
element_type: entity.type,
|
11
|
+
relationships: element_relationships,
|
12
|
+
views: model.diagrams.select { |dia| dia.element_ids.include?(entity.id) }.map(&:id)
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def element_relationships
|
19
|
+
model.relationships.select do |rel|
|
20
|
+
rel.source&.id == entity.id || rel.target&.id == entity.id
|
21
|
+
end
|
22
|
+
.map(&:id)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Archimate
|
5
|
+
# Base class for ArchiMate Entities: Model, Diagram, Element, Relationship
|
6
|
+
class EntityBase
|
7
|
+
attr_reader :entity
|
8
|
+
attr_reader :model
|
9
|
+
|
10
|
+
def initialize(entity, model: nil)
|
11
|
+
@entity = entity
|
12
|
+
@model = model
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_h
|
16
|
+
Archimate.hash_purge(attr_hash)
|
17
|
+
end
|
18
|
+
|
19
|
+
def attr_hash
|
20
|
+
{
|
21
|
+
id: entity.id,
|
22
|
+
name: entity.name,
|
23
|
+
documentation: entity.documentation&.to_h,
|
24
|
+
properties: entity.properties.map(&:to_h)
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Archimate
|
5
|
+
# Represents an ArchiMate Organizing Folder
|
6
|
+
class Folder
|
7
|
+
attr_reader :folder
|
8
|
+
|
9
|
+
def initialize(folder)
|
10
|
+
@folder = folder
|
11
|
+
end
|
12
|
+
|
13
|
+
# This item check is necessary because some models seem to contain
|
14
|
+
# an item that is a string rather than an element of some sort.
|
15
|
+
def items
|
16
|
+
folder.items.map { |item| item.is_a?(String) ? item : item.id }
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
Archimate.hash_purge(
|
21
|
+
id: folder.id,
|
22
|
+
name: folder.name.to_s,
|
23
|
+
folders: folder.organizations.map { |child| Folder.new(child).to_h },
|
24
|
+
diagrams: items
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Archimate
|
5
|
+
# Writes any object that can be hashified (with to_h) to a JSON file
|
6
|
+
class JsonFile
|
7
|
+
def initialize(filename)
|
8
|
+
@filename = filename
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(obj)
|
12
|
+
File.open(@filename, "wb") do |file|
|
13
|
+
file.write(JSON.generate(obj.to_h))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Jekyll
|
2
4
|
module Archimate
|
3
5
|
# Insert a diagram from the ArchiMate model.
|
@@ -5,12 +7,13 @@ module Jekyll
|
|
5
7
|
# {% matrix plateau:"Today" | caption: "Today's Application Interaction" }
|
6
8
|
#
|
7
9
|
class MatrixTag < Liquid::Tag
|
10
|
+
EMPTY_CELL = "<td></td>"
|
11
|
+
|
8
12
|
attr_reader :context
|
9
13
|
attr_reader :caption
|
10
14
|
attr_reader :element_types
|
11
15
|
attr_reader :markup
|
12
16
|
|
13
|
-
|
14
17
|
def initialize(tag_name, markup, tokens)
|
15
18
|
@markup = markup
|
16
19
|
@context = nil
|
@@ -26,104 +29,52 @@ module Jekyll
|
|
26
29
|
render_table
|
27
30
|
end
|
28
31
|
|
29
|
-
# Here I want all of the Serving relationships between 2 app components
|
30
|
-
# included or derived.
|
31
|
-
#
|
32
|
-
# attrs:
|
33
|
-
# source_selector: Element selector for source elements
|
34
|
-
# target_selector: Element selector for target elements
|
35
|
-
# relationship_selector
|
36
|
-
def application_interaction
|
37
|
-
model = site.data["archimate_model"]
|
38
|
-
dr_engine = ::Archimate::DerivedRelations.new(model)
|
39
|
-
|
40
|
-
relationship_filter = lambda { |rel| rel.weight >= ::Archimate::DataModel::Serving::WEIGHT }
|
41
|
-
|
42
|
-
plateau_today = dr_engine.element_by_name("Today")
|
43
|
-
today_rels = model.relationships.select do |rel|
|
44
|
-
rel.source.id == plateau_today.id &&
|
45
|
-
%w{CompositionRelationship AggregationRelationship}.include?(rel.type) &&
|
46
|
-
rel.target.type == "ApplicationComponent"
|
47
|
-
end
|
48
|
-
today_apps = today_rels.map { |rel| rel.target }
|
49
|
-
source_filter = lambda { |el| }
|
50
|
-
target_filter = lambda { |el| today_apps.map(&:id).include?(el.id) }
|
51
|
-
stop_filter = lambda { |el| el.type == "ApplicationComponent" }
|
52
|
-
|
53
|
-
concrete_rels = model.relationships.select { |rel|
|
54
|
-
rel.type == "ServingRelationship" &&
|
55
|
-
today_apps.include?(rel.source.id) &&
|
56
|
-
today_apps.include?(rel.target.id)
|
57
|
-
}
|
58
|
-
|
59
|
-
derived_rels = dr_engine.derived_relations(
|
60
|
-
today_apps,
|
61
|
-
relationship_filter,
|
62
|
-
target_filter,
|
63
|
-
stop_filter
|
64
|
-
)
|
65
|
-
|
66
|
-
@all_rels = [concrete_rels, derived_rels].flatten
|
67
|
-
|
68
|
-
@callers = @all_rels.map(&:source).uniq.sort { |a, b| a.name.to_s <=> b.name.to_s }
|
69
|
-
@callees = @all_rels.map(&:target).uniq.sort { |a, b| a.name.to_s <=> b.name.to_s }
|
70
|
-
end
|
71
|
-
|
72
|
-
def matrix_data
|
73
|
-
model = site.data["archimate_model"]
|
74
|
-
dr_engine = ::Archimate::DerivedRelations.new(model)
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
32
|
def render_table
|
79
|
-
<<~
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
33
|
+
<<~TABLE
|
34
|
+
<table class="table table-condensed table-hover table-striped">
|
35
|
+
<caption>#{caption}</caption>
|
36
|
+
<thead>
|
37
|
+
<tr>
|
38
|
+
<th> </th>
|
39
|
+
<th class="success" scope="col" colspan="#{@callers.size}">Callers</th>
|
40
|
+
</tr>
|
41
|
+
<tr>
|
42
|
+
<th class="info" scope="col">Callees</th>
|
43
|
+
#{@callers.map { |ac| "<th class=\"success\" scope=\"col\" style=\"text-transform: capitalize\">#{ac.name}</th>" }.join("\n")}
|
44
|
+
</tr>
|
45
|
+
</thead>
|
46
|
+
<tbody>
|
47
|
+
#{render_rows.strip}
|
48
|
+
</tbody>
|
49
|
+
</table>
|
50
|
+
TABLE
|
97
51
|
end
|
98
52
|
|
99
53
|
def render_rows
|
100
54
|
return "<tr><td>No Items</td></tr>" if @callees.empty?
|
101
55
|
@callees.map do |callee|
|
102
|
-
<<~
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
56
|
+
<<~TABLE_ROW
|
57
|
+
<tr>
|
58
|
+
<th class="info" scope="row">#{callee.name}</th>
|
59
|
+
#{@callers.map { |caller| cell_content(caller, callee) }.join('')}
|
60
|
+
</tr>
|
61
|
+
TABLE_ROW
|
108
62
|
end.join("")
|
109
63
|
end
|
110
64
|
|
111
65
|
def cell_content(caller, callee)
|
112
66
|
rels = @all_rels.select { |rel| rel.source == caller && rel.target == callee }
|
113
|
-
if rels.empty?
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
tooltip = "#{caller.name} → #{}#{callee.name} #{"(derived)" if derived}"
|
119
|
-
cell = <<~END
|
67
|
+
return EMPTY_CELL if rels.empty?
|
68
|
+
derived = rels.all?(&:derived)
|
69
|
+
span_class = derived ? "text-danger" : "text-primary"
|
70
|
+
tooltip = "#{caller.name} → #{callee.name} #{'(derived)' if derived}"
|
71
|
+
<<~TABLE_CELL
|
120
72
|
<td>
|
121
73
|
<a href="#" data-toggle="tooltip" data-placement="top" title="#{tooltip}">
|
122
74
|
<span class="#{span_class}">↵ calls</span>
|
123
75
|
</a>
|
124
76
|
</td>
|
125
|
-
|
126
|
-
end
|
77
|
+
TABLE_CELL
|
127
78
|
end
|
128
79
|
|
129
80
|
def scan_attributes(context)
|
@@ -157,4 +108,3 @@ module Jekyll
|
|
157
108
|
end
|
158
109
|
|
159
110
|
Liquid::Template.register_tag("matrix", Jekyll::Archimate::MatrixTag)
|
160
|
-
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Archimate
|
5
|
+
# Represents an ArchiMate Relationship
|
6
|
+
class RelationshipEntity < EntityBase
|
7
|
+
def attr_hash
|
8
|
+
super.merge(
|
9
|
+
type: "Relationship",
|
10
|
+
relationship_type: entity.type,
|
11
|
+
source: entity.source&.id,
|
12
|
+
target: entity.target&.id,
|
13
|
+
views: relationship_views
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def relationship_views
|
20
|
+
model.diagrams.select { |dia| dia.relationship_ids.include?(entity.id) }.map(&:id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|