jekyll-archimate 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- <<-END.gsub(/^ {6}/, '')
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(site.data["archimate"]["catalog"]))}
43
+ #{render_rows(elements)}
40
44
  </tbody>
41
45
  </table>
42
- END
46
+ TABLE
43
47
  end
44
48
 
45
- def elements(catalog)
46
- @element_types.map { |element_type| catalog[element_type] }.flatten.compact
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
- <<-END
63
+ <<-TABLE_ROW
53
64
  <tr>
54
- <td><span class="badge badge-primary">#{element["type"]}</span> #{element["name"]}</td>
55
- <td>#{@converter.convert(element["documentation"]).gsub(/<\/?p[^>]*>/, '').chomp if element["documentation"]}</td>
56
- <td>#{render_properties(element["properties"])}</td>
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
- END
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
- <<~END
80
- <table class="table table-condensed table-hover table-striped">
81
- <caption>#{caption}</caption>
82
- <thead>
83
- <tr>
84
- <th>&nbsp;</th>
85
- <th class="success" scope="col" colspan="#{@callers.size}">Callers</th>
86
- </tr>
87
- <tr>
88
- <th class="info" scope="col">Callees</th>
89
- #{@callers.map { |ac| "<th class=\"success\" scope=\"col\" style=\"text-transform: capitalize\">#{ac.name}</th>" }.join("\n")}
90
- </tr>
91
- </thead>
92
- <tbody>
93
- #{render_rows.strip}
94
- </tbody>
95
- </table>
96
- END
33
+ <<~TABLE
34
+ <table class="table table-condensed table-hover table-striped">
35
+ <caption>#{caption}</caption>
36
+ <thead>
37
+ <tr>
38
+ <th>&nbsp;</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
- <<~END
103
- <tr>
104
- <th class="info" scope="row">#{callee.name}</th>
105
- #{@callers.map { |caller| cell_content(caller, callee) }.join("")}
106
- </tr>
107
- END
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
- "<td></td>"
115
- else
116
- derived = rels.all? { |rel| rel.derived }
117
- span_class = derived ? "text-danger" : "text-primary"
118
- tooltip = "#{caller.name} &rarr; #{}#{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} &rarr; #{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}">&crarr; calls</span>
123
75
  </a>
124
76
  </td>
125
- END
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,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Archimate
5
+ # Represents the overall model
6
+ class ModelEntity < EntityBase
7
+ def attr_hash
8
+ super.merge(
9
+ type: "Model"
10
+ )
11
+ end
12
+ end
13
+ end
14
+ end
@@ -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