metanorma-plugin-lutaml 0.4.2 → 0.4.6

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.
@@ -0,0 +1,113 @@
1
+ {% for package in context.packages %}
2
+ {% assign package_name = package.name | downcase | replace: ":", "" | replace: " ", "_" %}
3
+ {% if additional_context.before and additional_context.before.size > 0 %}
4
+ {% for before in additional_context.before %}
5
+ {{ before.text }}
6
+ {% endfor %}
7
+ {% endif %}
8
+ {% capture equalsigns %}{% for count in (1..depth) %}={% endfor %}{% endcapture %}{{equalsigns}} {{ package.name }}
9
+ [[rc_{{ package_name }}-model_section]]
10
+ {{equalsigns}}= {{ package.name }}
11
+
12
+ {% assign before_package_key = 'before;' | append: package.name %}
13
+ {% if additional_context[before_package_key] and additional_context[before_package_key].size > 0 %}
14
+ {% for before in additional_context[before_package_key] %}
15
+ {{ before.text }}
16
+ {% endfor %}
17
+ {% endif %}
18
+ {% if additional_context.diagram_include_block %}
19
+ {% for diagram_include_block in additional_context.diagram_include_block %}
20
+ {% include "diagrams_block", package_name: package_name, image_base_path: diagram_include_block.base_path, text: diagram_include_block.text %}
21
+ {% endfor %}
22
+ {% endif %}
23
+
24
+ {% if additional_context.include_block and additional_context.include_block.size > 0 %}
25
+ {% for block in additional_context.include_block %}
26
+ {% capture block_filename %}{{ block.base_path }}{{ package_name }}{% endcapture %}
27
+ {% capture block_content %}{% include block_filename %}{% endcapture %}
28
+ {% unless block_content contains "Liquid error" %}
29
+ {% if block.text %}
30
+ {{ block.text }}
31
+ {% endif %}
32
+ {{ block_content }}
33
+ {% endunless %}
34
+ {% endfor %}
35
+ {% endif %}
36
+
37
+ {% assign include_block_package_key = 'include_block;' | append: package.name %}
38
+ {% if additional_context[include_block_package_key] and additional_context[include_block_package_key].size > 0 %}
39
+ {% for block in additional_context[include_block_package_key] %}
40
+ {% capture block_filename %}{{ block.base_path }}{{ package_name }}{% endcapture %}
41
+ {% capture block_content %}{% include block_filename %}{% endcapture %}
42
+ {% unless block_content contains "Liquid error" %}
43
+ {% if block.text %}
44
+ {{ block.text }}
45
+ {% endif %}
46
+ {{ block_content }}
47
+ {% endunless %}
48
+ {% endfor %}
49
+ {% endif %}
50
+
51
+ {{equalsigns}}= Class Definitions
52
+ {% if package.classes.size > 0 %}
53
+ .Classes used in {{ package.name }}
54
+ [cols="2a,6a",options="header"]
55
+ |===
56
+ |Class |Description
57
+
58
+ {% for klass in package.classes %}
59
+ |<<{{ klass.name }}-section,{{ klass.name }}>>
60
+ «{{ klass.stereotype }}»
61
+ |{{ klass.definition }}
62
+
63
+ {% endfor %}
64
+ |===
65
+ {% endif %}
66
+
67
+ {% if package.data_types.size > 0 %}
68
+ .Data Types used in {{ package.name }}
69
+ [cols="2,6",options="header"]
70
+ |===
71
+ |Name |Description
72
+
73
+ {% for klass in package.data_types %}
74
+ |<<{{ klass.name }}-section,{{ klass.name }}>>
75
+ |{{ klass.definition }}
76
+
77
+ {% endfor %}
78
+
79
+ |===
80
+ {% endif %}
81
+
82
+ {% if package.enums.size > 0 %}
83
+ .Enumerated Classes used in {{ package.name }}
84
+ [cols="2a,6a",options="header"]
85
+ |===
86
+ |Name |Description
87
+
88
+ {% for klass in package.enums %}
89
+ |<<{{ klass.name }}-section,{{ klass.name }}>>
90
+ |{{ klass.definition }}
91
+
92
+ {% endfor %}
93
+
94
+ |===
95
+ {% endif %}
96
+
97
+ {% assign after_package_key = 'after;' | append: package.name %}
98
+ {% if additional_context[after_package_key] %}
99
+ {{equalsigns}}= Additional Information
100
+ {% for after in additional_context[after_package_key] %}
101
+ {{ after.text }}
102
+ {% endfor %}
103
+ {% endif %}
104
+ {% if package.packages.size > 0 and render_nested_packages %}
105
+ {% assign nested_depth = depth | plus: 1 %}{% include "packages_entity_list", depth: nested_depth, context: package %}
106
+ {% endif %}
107
+ {% endfor %}
108
+
109
+ {% if additional_context.after and additional_context.after.size > 0 %}
110
+ {% for after in additional_context.after %}
111
+ {{ after.text }}
112
+ {% endfor %}
113
+ {% endif %}
@@ -0,0 +1,63 @@
1
+ {% assign is_klass_spare = klass.name | slice: 0,5 %}
2
+ {% if is_klass_spare == 'old: ' %}{% continue %}
3
+ {% elsif is_klass_spare == 'Spare' %}{% continue %}
4
+ {% endif %}
5
+ {% assign klass_name = klass.name | downcase | replace: ':', '' | replace: ' ', '_' %}
6
+ [[tab-P-{{ package_name }}-E-{{ klass_name }}]]
7
+ .Elements of {{ package.name }}::{{ klass.name }}
8
+ [width="100%",cols="a,a,a,a,a,a,a,a"]
9
+ |===
10
+
11
+ h|Name: 7+| {{ klass.name }}
12
+
13
+ h|Definition: 7+| {{ klass.definition | html2adoc }}
14
+
15
+ h|Stereotype: 7+| {{ klass.stereotype | default: 'interface' }}
16
+
17
+ {% assign inherited = klass.associations | where: "member_end_type", "inheritance" %}
18
+ {% if inherited.size > 0 %}
19
+ h|Inheritance from: 7+| {{ inherited | map: 'member_end' | join: ", " }}
20
+ {% endif %}
21
+
22
+ {% assign generalizations = klass.associations | where: "member_end_type", "generalization" %}
23
+ {% if generalizations.size > 0 %}
24
+ h|Generalization of: 7+| {{ generalizations | map: 'member_end' | join: ", " }}
25
+ {% endif %}
26
+
27
+ h|Abstract: 7+| {{ klass.is_abstract }}
28
+ {% assign aggregations = klass.associations | where: "member_end_type", "aggregation" %}
29
+ {% if aggregations.size > 0 %}
30
+ .{{aggregations.size | plus: 1}}+h|Associations:
31
+ 4+|_Association with:_
32
+ |_Obligation_
33
+ | _Maximum occurrence_
34
+ |_Provides:_
35
+
36
+ {% for assoc in aggregations %}
37
+ 4+| {{assoc.member_end}}
38
+ | {% if assoc.member_end_cardinality %}{{ assoc.member_end_cardinality.min }}{% endif %}
39
+ | {% if assoc.member_end_cardinality %}{{ assoc.member_end_cardinality.max }}{% endif %}
40
+ | {{ assoc.member_end_attribute_name }}
41
+
42
+ {% endfor %}
43
+ {% else %}
44
+
45
+ .1+h|Associations: 7+| (none)
46
+ {% endif %}
47
+ {% if klass.values.size > 0 %}
48
+ .{{klass.values.size | plus: 1}}+h|Values:
49
+ | _Name_
50
+ 6+| _Definition_
51
+
52
+ {% for value in klass.values %}
53
+ | {{value.name}}
54
+ 6+| {{ value.definition | html2adoc }}
55
+
56
+ {% endfor %}
57
+ {% else %}
58
+ .1+h|Values:
59
+ 7+| (none)
60
+ {% endif %}
61
+
62
+
63
+ |===
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "liquid"
4
+ require "asciidoctor"
5
+ require "asciidoctor/reader"
6
+ require "lutaml"
7
+ require "lutaml/uml"
8
+ require "lutaml/formatter"
9
+ require "metanorma/plugin/lutaml/utils"
10
+
11
+ module Metanorma
12
+ module Plugin
13
+ module Lutaml
14
+ module LutamlDiagramBase
15
+ def process(parent, reader, attrs)
16
+ uml_document = ::Lutaml::Uml::Parsers::Dsl.parse(lutaml_file(parent.document, reader))
17
+ filename = generate_file(parent, reader, uml_document)
18
+ through_attrs = generate_attrs(attrs)
19
+ through_attrs["target"] = filename
20
+ through_attrs["title"] = uml_document.caption
21
+ create_image_block(parent, through_attrs)
22
+ rescue StandardError => e
23
+ abort(parent, reader, attrs, e.message)
24
+ end
25
+
26
+ def lutaml_file(reader)
27
+ raise 'Implement me!'
28
+ end
29
+
30
+ protected
31
+
32
+ def abort(parent, reader, attrs, msg)
33
+ warn(msg)
34
+ attrs["language"] = "lutaml"
35
+ source = reader.respond_to?(:source) ? reader.source : reader
36
+ create_listing_block(
37
+ parent,
38
+ source,
39
+ attrs.reject { |k, _v| k == 1 }
40
+ )
41
+ end
42
+
43
+ # if no :imagesdir: leave image file in lutaml
44
+ def generate_file(parent, _reader, uml_document)
45
+ formatter = ::Lutaml::Formatter::Graphviz.new
46
+ formatter.type = :png
47
+
48
+ imagesdir = if parent.document.attr("imagesdir")
49
+ File.join(parent.document.attr("imagesdir"), "lutaml")
50
+ else
51
+ "lutaml"
52
+ end
53
+ result_path = Utils.relative_file_path(parent.document, imagesdir)
54
+ result_pathname = Pathname.new(result_path)
55
+ result_pathname.mkpath
56
+ File.writable?(result_pathname) || raise("Destination path #{result_path} not writable for Lutaml!")
57
+
58
+ outfile = Tempfile.new(["lutaml", ".png"])
59
+ outfile.binmode
60
+ outfile.puts(formatter.format(uml_document))
61
+
62
+ # Warning: metanorma/metanorma-standoc#187
63
+ # Windows Ruby 2.4 will crash if a Tempfile is "mv"ed.
64
+ # This is why we need to copy and then unlink.
65
+ filename = File.basename(outfile.path)
66
+ FileUtils.cp(outfile, result_pathname) && outfile.unlink
67
+
68
+ File.join(result_pathname, filename)
69
+ end
70
+
71
+ def generate_attrs(attrs)
72
+ %w(id align float title role width height alt)
73
+ .reduce({}) do |memo, key|
74
+ memo[key] = attrs[key] if attrs.has_key? key
75
+ memo
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,40 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "liquid"
4
- require "asciidoctor"
5
- require "asciidoctor/reader"
6
- require "lutaml"
7
- require "lutaml/uml"
8
- require "metanorma/plugin/lutaml/utils"
3
+ require "metanorma/plugin/lutaml/lutaml_diagram_base"
9
4
 
10
5
  module Metanorma
11
6
  module Plugin
12
7
  module Lutaml
13
8
  class LutamlDiagramBlock < Asciidoctor::Extensions::BlockProcessor
9
+ include LutamlDiagramBase
10
+
14
11
  use_dsl
15
12
  named :lutaml_diagram
16
13
  on_context :literal
17
14
  parse_content_as :raw
18
15
 
19
- def abort(parent, reader, attrs, msg)
20
- warn(msg)
21
- attrs["language"] = "lutaml"
22
- create_listing_block(
23
- parent,
24
- reader.source,
25
- attrs.reject { |k, _v| k == 1 }
26
- )
27
- end
16
+ def lutaml_file(document, reader)
28
17
 
29
- def process(parent, reader, attrs)
30
- uml_document = ::Lutaml::Uml::Parsers::Dsl.parse(lutaml_temp(parent.document, reader))
31
- filename = generate_file(parent, reader, uml_document)
32
- through_attrs = generate_attrs(attrs)
33
- through_attrs["target"] = filename
34
- through_attrs["title"] = uml_document.caption
35
- create_image_block(parent, through_attrs)
36
- rescue StandardError => e
37
- abort(parent, reader, attrs, e.message)
18
+ lutaml_temp(document, reader)
38
19
  end
39
20
 
40
21
  private
@@ -45,42 +26,6 @@ module Metanorma
45
26
  temp_file.rewind
46
27
  temp_file
47
28
  end
48
-
49
- # if no :imagesdir: leave image file in lutaml
50
- def generate_file(parent, _reader, uml_document)
51
- formatter = ::Lutaml::Uml::Formatter::Graphviz.new
52
- formatter.type = :png
53
-
54
- imagesdir = if parent.document.attr("imagesdir")
55
- File.join(parent.document.attr("imagesdir"), "lutaml")
56
- else
57
- "lutaml"
58
- end
59
- result_path = Utils.relative_file_path(parent.document, imagesdir)
60
- result_pathname = Pathname.new(result_path)
61
- result_pathname.mkpath
62
- File.writable?(result_pathname) || raise("Destination path #{result_path} not writable for Lutaml!")
63
-
64
- outfile = Tempfile.new(["lutaml", ".png"])
65
- outfile.binmode
66
- outfile.puts(formatter.format(uml_document))
67
-
68
- # Warning: metanorma/metanorma-standoc#187
69
- # Windows Ruby 2.4 will crash if a Tempfile is "mv"ed.
70
- # This is why we need to copy and then unlink.
71
- filename = File.basename(outfile.path)
72
- FileUtils.cp(outfile, result_pathname) && outfile.unlink
73
-
74
- File.join(result_pathname, filename)
75
- end
76
-
77
- def generate_attrs(attrs)
78
- %w(id align float title role width height alt)
79
- .reduce({}) do |memo, key|
80
- memo[key] = attrs[key] if attrs.has_key? key
81
- memo
82
- end
83
- end
84
29
  end
85
30
  end
86
31
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "metanorma/plugin/lutaml/lutaml_diagram_base"
4
+
5
+ module Metanorma
6
+ module Plugin
7
+ module Lutaml
8
+ class LutamlDiagramBlockMacro < Asciidoctor::Extensions::BlockMacroProcessor
9
+ include LutamlDiagramBase
10
+
11
+ use_dsl
12
+ named :lutaml_diagram
13
+
14
+ def lutaml_file(document, file_path)
15
+ File.new(Utils.relative_file_path(document, file_path))
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Plugin
5
+ module Lutaml
6
+ class LutamlFigureInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
7
+ include LutamlDiagramBase
8
+
9
+ use_dsl
10
+ named :lutaml_figure
11
+
12
+ def process(parent, _target, attrs)
13
+ diagram_key = [attrs["package"], attrs["name"]].compact.join(":")
14
+ return if parent.document.attributes['lutaml_figure_id'].nil?
15
+ xmi_id = parent.document.attributes['lutaml_figure_id'][diagram_key]
16
+ return unless xmi_id
17
+
18
+ %Q(<xref target="figure-#{xmi_id}"></xref>)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -14,7 +14,7 @@ module Metanorma
14
14
  # @example [lutaml_uml_attributes_table,path/to/lutaml,EntityName]
15
15
  class LutamlUmlAttributesTablePreprocessor < Asciidoctor::Extensions::Preprocessor
16
16
  MARCO_REGEXP =
17
- /\[lutaml_uml_attributes_table,([^,]+),?(.+)?,([^,]+),?(.+)?\]/
17
+ /\[lutaml_uml_attributes_table,([^,]+),?([^,]+),?(.+?)?\]/
18
18
  # search document for block `datamodel_attributes_table`
19
19
  # read include derectives that goes after that in block and transform
20
20
  # into yaml2text blocks
@@ -36,15 +36,16 @@ module Metanorma
36
36
  input_lines.each_with_object([]) do |line, result|
37
37
  if match = line.match(MARCO_REGEXP)
38
38
  lutaml_path = match[1]
39
- entity_name = match[3]
40
- result.push(*parse_marco(lutaml_path, entity_name, document))
39
+ entity_name = match[2]
40
+ skip_headers = match[3]
41
+ result.push(*parse_marco(lutaml_path, entity_name, document, skip_headers))
41
42
  else
42
43
  result.push(line)
43
44
  end
44
45
  end
45
46
  end
46
47
 
47
- def parse_marco(lutaml_path, entity_name, document)
48
+ def parse_marco(lutaml_path, entity_name, document, skip_headers)
48
49
  lutaml_document = lutaml_document_from_file(document, lutaml_path)
49
50
  .serialized_document
50
51
  entities = [lutaml_document["classes"], lutaml_document["enums"]]
@@ -53,12 +54,12 @@ module Metanorma
53
54
  entity_definition = entities.detect do |klass|
54
55
  klass["name"] == entity_name.strip
55
56
  end
56
- model_representation(entity_definition, document)
57
+ model_representation(entity_definition, document, skip_headers)
57
58
  end
58
59
 
59
- def model_representation(entity_definition, document)
60
+ def model_representation(entity_definition, document, skip_headers)
60
61
  render_result, errors = Utils.render_liquid_string(
61
- template_string: table_template,
62
+ template_string: table_template(skip_headers),
62
63
  context_items: entity_definition,
63
64
  context_name: "definition",
64
65
  document: document
@@ -68,9 +69,9 @@ module Metanorma
68
69
  end
69
70
 
70
71
  # rubocop:disable Layout/IndentHeredoc
71
- def table_template
72
+ def table_template(skip_headers)
72
73
  <<~TEMPLATE
73
- === {{ definition.name }}
74
+ #{"=== {{ definition.name }}" unless skip_headers}
74
75
  {{ definition.definition }}
75
76
 
76
77
  {% if definition.attributes %}
@@ -89,7 +90,7 @@ module Metanorma
89
90
  |Name |Definition |Mandatory/ Optional/ Conditional |Max Occur |Data Type
90
91
 
91
92
  {% for item in definition.attributes %}
92
- |{{ item.name }} |{% if item.definition %}{{ item.definition }}{% else %}TODO: enum {{ key }}'s definition{% endif %} |{% if item.cardinality.min == "0" %}O{% else %}M{% endif %} |{% if item.cardinality.max == "*" %}N{% else %}1{% endif %} |{% if item.origin %}<<{{ item.origin }}>>{% endif %} `{{ item.type }}`
93
+ |{{ item.name }} |{% if item.definition %}{{ item.definition }}{% endif %} |{% if item.cardinality.min == "0" %}O{% else %}M{% endif %} |{% if item.cardinality.max == "*" %}N{% else %}1{% endif %} |{% if item.origin %}<<{{ item.origin }}>>{% endif %} `{{ item.type }}`
93
94
  {% endfor %}
94
95
  |===
95
96
  {% endif %}