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.
@@ -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