metanorma-plugin-lutaml 0.7.45 → 0.7.50

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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +3 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop_todo.yml +11 -3
  5. data/Gemfile +0 -1
  6. data/README.adoc +4 -0
  7. data/docs/usages/enterprise_architect_uml.adoc +173 -0
  8. data/lib/metanorma/plugin/lutaml/base_preprocessor.rb +1 -1
  9. data/lib/metanorma/plugin/lutaml/cache_registry.rb +22 -0
  10. data/lib/metanorma/plugin/lutaml/config.rb +1 -1
  11. data/lib/metanorma/plugin/lutaml/express_remark_adapter.rb +114 -0
  12. data/lib/metanorma/plugin/lutaml/express_remarks_decorator.rb +6 -0
  13. data/lib/metanorma/plugin/lutaml/lutaml_diagram_base.rb +2 -3
  14. data/lib/metanorma/plugin/lutaml/lutaml_ea_diagram_block_macro.rb +27 -6
  15. data/lib/metanorma/plugin/lutaml/lutaml_ea_uml_preprocessor.rb +79 -0
  16. data/lib/metanorma/plugin/lutaml/lutaml_ea_xmi_base.rb +59 -4
  17. data/lib/metanorma/plugin/lutaml/lutaml_ea_xmi_preprocessor.rb +4 -4
  18. data/lib/metanorma/plugin/lutaml/lutaml_preprocessor.rb +7 -61
  19. data/lib/metanorma/plugin/lutaml/lutaml_uml_datamodel_description_preprocessor.rb +3 -4
  20. data/lib/metanorma/plugin/lutaml/lutaml_xmi_uml_preprocessor.rb +5 -4
  21. data/lib/metanorma/plugin/lutaml/lutaml_xsd_preprocessor.rb +1 -21
  22. data/lib/metanorma/plugin/lutaml/utils.rb +1 -1
  23. data/lib/metanorma/plugin/lutaml/version.rb +1 -1
  24. data/lib/metanorma/plugin/lutaml/xmi_cache.rb +44 -67
  25. data/lib/metanorma/plugin/lutaml/xmi_parse_cache.rb +60 -0
  26. data/lib/metanorma-plugin-lutaml.rb +10 -0
  27. data/metanorma-plugin-lutaml.gemspec +3 -1
  28. metadata +38 -12
  29. data/.github/workflows/rake.yml +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ecadace3879b75e1ec4f08f435da722a2151c32a419fed84476646f2dc7314f6
4
- data.tar.gz: bc0e618b7252c140a1b9acc404194f2fdfa30e65c8b4ae8823c6bc19222a4a8a
3
+ metadata.gz: f27b6ec54fcac0ddd7555f3058124ff88197ebed8b616200deacb2e62ab796d5
4
+ data.tar.gz: b765db1783fd82e76ffcd22c3ec8340d335dfcc27058da3be7ce5127a0ca1136
5
5
  SHA512:
6
- metadata.gz: 8d621151fd02cf3582d75366b8fc943f51286357d95584863c3158b7911b082dfaa877919505ba3483219d5c08eeae1ad449fe9862f0aa63b3507f08764f9a3a
7
- data.tar.gz: 54823d6d7ae810e8791dc27d3dec120a44eb224fadce8ccedbd4884d4d8a28c54127bb1e8bf6b2c54e0c740085c52c5968d1e8181964902371cee15f329b990e
6
+ metadata.gz: 5c2ab27419d029d9b28a8fc6a03ee906505718d64a91cb405a4af15cb4761918b50c2d84668d33bd68ce2c444c72e6ae29a701367d98d5de0e0b35489741abdf
7
+ data.tar.gz: '0112029fbc5e4998a3a5ec2e19b0785db703b02eb379902ef47c720e2799965491d06947e40d35222694b81a8a2a5fbd432edeadf5a4d4ba55c87d8d4337c0d0'
@@ -19,6 +19,9 @@ jobs:
19
19
  uses: metanorma/ci/.github/workflows/rubygems-release.yml@main
20
20
  with:
21
21
  next_version: ${{ github.event.inputs.next_version }}
22
+ release_command: |
23
+ bundle install
24
+ bundle exec rake release
22
25
  secrets:
23
26
  rubygems-api-key: ${{ secrets.METANORMA_CI_RUBYGEMS_API_KEY }}
24
27
  pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
data/.gitignore CHANGED
@@ -4,6 +4,7 @@ spec/assets/lutaml
4
4
  test.err
5
5
  test.err.html
6
6
  TODO.cleanup/
7
+ TODO.optimize/
7
8
  pkg/
8
9
 
9
10
  .rubocop-https--*
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2026-05-15 01:32:12 UTC using RuboCop version 1.86.1.
3
+ # on 2026-05-15 10:38:23 UTC using RuboCop version 1.86.2.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -37,7 +37,7 @@ Metrics/CyclomaticComplexity:
37
37
  Exclude:
38
38
  - 'lib/metanorma/plugin/lutaml/utils.rb'
39
39
 
40
- # Offense count: 7
40
+ # Offense count: 8
41
41
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
42
42
  Metrics/MethodLength:
43
43
  Max: 19
@@ -81,7 +81,7 @@ RSpec/ContextWording:
81
81
  - 'spec/metanorma/plugin/lutaml/macros_data2text_spec.rb'
82
82
  - 'spec/support/shared_examples/structured_data_2_text_preprocessor.rb'
83
83
 
84
- # Offense count: 44
84
+ # Offense count: 47
85
85
  # Configuration parameters: CountAsOne.
86
86
  RSpec/ExampleLength:
87
87
  Max: 26
@@ -157,3 +157,11 @@ RSpec/SpecFilePathFormat:
157
157
  RSpec/SubjectDeclaration:
158
158
  Exclude:
159
159
  - 'spec/metanorma/plugin/lutaml/config/root_spec.rb'
160
+
161
+ # Offense count: 2
162
+ # This cop supports safe autocorrection (--autocorrect).
163
+ # Configuration parameters: EnforcedStyleForMultiline.
164
+ # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
165
+ Style/TrailingCommaInArguments:
166
+ Exclude:
167
+ - 'spec/metanorma/plugin/lutaml/express_remark_adapter_spec.rb'
data/Gemfile CHANGED
@@ -14,7 +14,6 @@ end
14
14
 
15
15
  gem "canon"
16
16
  gem "html2doc", github: "metanorma/html2doc", branch: "main"
17
- gem "lutaml"
18
17
  gem "metanorma", github: "metanorma/metanorma", branch: "main"
19
18
  gem "metanorma-standoc", github: "metanorma/metanorma-standoc", branch: "main"
20
19
  gem "rake"
data/README.adoc CHANGED
@@ -12,6 +12,8 @@ within a Metanorma document:
12
12
  * EXPRESS files (`*.exp`)
13
13
  * LutaML-UML files (`*.lutaml`)
14
14
  * Enterprise Architect exported UML files in XMI format (`*.xmi`)
15
+ * Enterprise Architect QEA files (`*.qea`)
16
+ * Enterprise Architect LUR files (`*.lur`)
15
17
  * LutaML GML Dictionary files (`*.xml`)
16
18
  * JSON or YAML files (`*.json|*.yml|*.yaml`)
17
19
  * XML Schema files (`*.xsd`)
@@ -31,6 +33,8 @@ link:docs/usages/lutaml-uml.adoc[Usage with LutaML files by lutaml_diagram]
31
33
 
32
34
  link:docs/usages/enterprise_architect.adoc[Usage with Enterprise Architect XMI files by lutaml_ea_xmi, lutaml_ea_diagram, lutaml_klass_table or lutaml_enum_table]
33
35
 
36
+ link:docs/usages/enterprise_architect_uml.adoc[Usage with Enterprise Architect UML files (XMI, QEA, LUR) by lutaml_ea_uml]
37
+
34
38
  link:docs/usages/lutaml-gml.adoc[Usage with LutaML GML Dictionary by lutaml_gml_dictionary]
35
39
 
36
40
  link:docs/usages/json_yaml.adoc[Usage with JSON or YAML files by data2text, yaml2text or json2text]
@@ -0,0 +1,173 @@
1
+
2
+ == Usage with Enterprise Architect UML files (XMI, QEA, LUR) by lutaml_ea_uml
3
+
4
+ === General
5
+
6
+ The `lutaml_ea_uml` command renders UML data models from Enterprise Architect
7
+ files using custom Liquid templates. It supports three file formats:
8
+
9
+ * XMI (`*.xmi`) -- Enterprise Architect XML Metadata Interchange export
10
+ * QEA (`*.qea`) -- Enterprise Architect native database format
11
+ * LUR (`*.lur`) -- Enterprise Architect model exchange format
12
+
13
+ The command parses the file into a Liquid template context, allowing full
14
+ control over the rendered output through custom Liquid templates.
15
+
16
+
17
+ === Basic usage
18
+
19
+ [source,adoc]
20
+ ----
21
+ [lutaml_ea_uml,path/to/example.xmi]
22
+ --
23
+ Name of the Lutaml UML Document: {{ context.name }}
24
+
25
+ Number of packages: {{ context.packages | size }}
26
+ --
27
+ ----
28
+
29
+ Where:
30
+
31
+ * `path/to/example.xmi` -- path to the XMI, QEA, or LUR file to render.
32
+
33
+ The content between `--` delimiters is a Liquid template. The parsed UML
34
+ document is available as `context` by default.
35
+
36
+
37
+ === Usage with a configuration file
38
+
39
+ [source,adoc]
40
+ ----
41
+ [lutaml_ea_uml,path/to/example.xmi,path/to/config.yml]
42
+ --
43
+ Name of the Lutaml UML Document: {{ my_uml_document.name }}
44
+
45
+ Number of packages: {{ my_uml_document.packages | size }}
46
+
47
+ {% render "package", package: my_uml_document.packages.first %}
48
+ --
49
+ ----
50
+
51
+ Where:
52
+
53
+ * `path/to/example.xmi` -- path to the XMI, QEA, or LUR file.
54
+ * `path/to/config.yml` -- path to the YAML configuration file.
55
+
56
+
57
+ === Configuration file format
58
+
59
+ [source,yaml]
60
+ ----
61
+ ---
62
+ ea_extension:
63
+ - "CityGML_MDG_Technology.xml"
64
+ - "ISO19103MDG v1.0.0-beta.xml"
65
+ context_name: my_uml_document
66
+ template_path: "path/to/liquid/templates"
67
+ guidance: "path/to/guidance.yml"
68
+ ----
69
+
70
+ Where:
71
+
72
+ * `ea_extension` -- optional, list of EA extension XML files to load. Some
73
+ XMI/QEA/LUR files contain elements that cannot be resolved by default (e.g.
74
+ CityGML elements). Load their definitions here. Paths are relative to the
75
+ config YAML file.
76
+
77
+ * `context_name` -- optional, the Liquid context variable name for the parsed
78
+ document. Defaults to `context`. When set, the document is accessible as
79
+ `{{ my_uml_document }}` instead of `{{ context }}`.
80
+
81
+ * `template_path` -- optional, path to a directory containing custom Liquid
82
+ templates. When specified, `render` tags in the block content will use
83
+ templates from this directory.
84
+
85
+ * `guidance` -- optional, path to a YAML guidance file for adding annotations
86
+ to rendered output.
87
+
88
+
89
+ === Usage with document index
90
+
91
+ You can define an XMI/QEA/LUR file index at the document level and reference
92
+ it by name:
93
+
94
+ [source,adoc]
95
+ ----
96
+ :lutaml-xmi-index: my-model; /path/to/example.qea
97
+
98
+ [lutaml_ea_uml,index=my-model]
99
+ --
100
+ Name: {{ context.name }}
101
+ --
102
+ ----
103
+
104
+ Syntax for the index attribute:
105
+
106
+ [source,adoc]
107
+ ----
108
+ :lutaml-xmi-index: index_name; file_path[; config=config_path]
109
+ ----
110
+
111
+ Where:
112
+
113
+ * `index_name` -- name to reference later with `index=`.
114
+ * `file_path` -- path to the XMI, QEA, or LUR file.
115
+ * `config_path` -- optional, path to the configuration YAML file.
116
+
117
+
118
+ === Liquid template context
119
+
120
+ The parsed UML document is exposed to Liquid templates with the following
121
+ structure:
122
+
123
+ * `context.name` -- name of the root UML model.
124
+ * `context.packages` -- array of packages in the model.
125
+ * `context.packages.first.name` -- name of a package.
126
+ * `context.packages.first.packages` -- nested sub-packages.
127
+ * `context.packages.first.classes` -- array of classes in a package.
128
+ * `context.packages.first.classes.first.name` -- name of a class.
129
+ * `context.packages.first.classes.first.attributes` -- array of attributes.
130
+ * `context.packages.first.classes.first.associations` -- array of associations.
131
+
132
+ When `context_name` is set in the configuration, replace `context` with the
133
+ configured name (e.g. `my_uml_document`).
134
+
135
+
136
+ === Example: rendering class tables with a custom template
137
+
138
+ Given a custom template at `templates/_klass.liquid`:
139
+
140
+ [source,liquid]
141
+ ----
142
+ {% for package in context.packages %}
143
+ == {{ package.name }}
144
+
145
+ {% for klass in package.classes %}
146
+ === {{ klass.name }}
147
+
148
+ {{ klass.definition | html2adoc }}
149
+
150
+ [cols="a,a"]
151
+ |===
152
+ | Attribute | Type
153
+
154
+ {% for attr in klass.owned_props %}
155
+ | {{ attr.name }} | {{ attr.type }}
156
+ {% endfor %}
157
+
158
+ |===
159
+ {% endfor %}
160
+ {% endfor %}
161
+ ----
162
+
163
+ The AsciiDoc block would be:
164
+
165
+ [source,adoc]
166
+ ----
167
+ [lutaml_ea_uml,path/to/example.xmi,path/to/config.yml]
168
+ --
169
+ {% render "klass", context: context %}
170
+ --
171
+ ----
172
+
173
+ Where the config specifies `template_path` pointing to the templates directory.
@@ -171,7 +171,7 @@ module Metanorma
171
171
  )
172
172
  parsed_template.assigns["schemas_order"] =
173
173
  options["selected_schemas"]
174
- parsed_template.render.split("\n", -1)
174
+ parsed_template.render
175
175
  end.flatten
176
176
  rescue StandardError => e
177
177
  ::Metanorma::Util.log(
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Plugin
5
+ module Lutaml
6
+ module CacheRegistry
7
+ def self.xmi_cache
8
+ XmiCache::XMI_PARSE_CACHE
9
+ end
10
+
11
+ def self.xsd_cache
12
+ LutamlXsdPreprocessor::CACHE
13
+ end
14
+
15
+ def self.clear_all
16
+ xmi_cache.clear
17
+ xsd_cache.clear
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "yaml"
4
- require "lutaml"
4
+ require "lutaml/uml"
5
5
  require "lutaml/model"
6
6
 
7
7
  module Metanorma
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "expressir"
4
+
5
+ module Metanorma
6
+ module Plugin
7
+ module Lutaml
8
+ module ExpressRemarkAdapter
9
+ def self.relative_path_prefix(options, model)
10
+ return if options.nil? || options["document"].nil?
11
+
12
+ document = options["document"]
13
+ file_path = File.dirname(model.file)
14
+ docfile_directory = File.dirname(
15
+ document.attributes["docfile"] || ".",
16
+ )
17
+ resolved = document.path_resolver
18
+ .system_path(file_path, docfile_directory)
19
+ File.expand_path(resolved, docfile_directory)
20
+ end
21
+
22
+ def self.for(model)
23
+ case model
24
+ when Expressir::Model::Cache
25
+ CachedRepoAdapter.new(model)
26
+ when Expressir::Model::Repository, Expressir::Model::ExpFile
27
+ RepoAdapter.new(model)
28
+ when Expressir::Model::ModelElement
29
+ ModelAdapter.new(model)
30
+ else
31
+ NullAdapter.new(model)
32
+ end
33
+ end
34
+
35
+ class Base
36
+ def initialize(model)
37
+ @model = model
38
+ end
39
+
40
+ def unwrap
41
+ @model
42
+ end
43
+
44
+ def decorate_remarks(options)
45
+ decorate_own_remarks(options)
46
+ decorate_child_remark_items(options)
47
+ traverse_children(options)
48
+ end
49
+
50
+ private
51
+
52
+ def decorate_own_remarks(options)
53
+ @model.remarks = ExpressRemarksDecorator.decorate_array(
54
+ @model.remarks, options
55
+ )
56
+ end
57
+
58
+ def decorate_child_remark_items(options)
59
+ return unless @model.is_a?(Expressir::Model::HasRemarkItems)
60
+
61
+ @model.remark_items&.each do |ri|
62
+ ri.remarks = ExpressRemarksDecorator.decorate_array(
63
+ ri.remarks, options
64
+ )
65
+ end
66
+ end
67
+
68
+ def traverse_children(options)
69
+ @model.children&.each do |child|
70
+ next unless traversable?(child)
71
+
72
+ ExpressRemarkAdapter.for(child).decorate_remarks(options)
73
+ end
74
+ end
75
+
76
+ def traversable?(child)
77
+ child.is_a?(Expressir::Model::ModelElement) &&
78
+ !child.is_a?(Expressir::Model::Declarations::RemarkItem)
79
+ end
80
+ end
81
+
82
+ class RepoAdapter < Base
83
+ def decorate_remarks(options)
84
+ @model.schemas.each do |schema|
85
+ options["relative_path_prefix"] =
86
+ ExpressRemarkAdapter.relative_path_prefix(options, schema)
87
+ ExpressRemarkAdapter.for(schema).decorate_remarks(options)
88
+ end
89
+ end
90
+ end
91
+
92
+ class CachedRepoAdapter < Base
93
+ def unwrap
94
+ @model.content
95
+ end
96
+
97
+ def decorate_remarks(options)
98
+ ExpressRemarkAdapter.for(@model.content).decorate_remarks(options)
99
+ end
100
+ end
101
+
102
+ class ModelAdapter < Base; end
103
+
104
+ class NullAdapter
105
+ def initialize(_model); end
106
+
107
+ def unwrap; end
108
+
109
+ def decorate_remarks(_options); end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -24,6 +24,12 @@ module Metanorma
24
24
  new(remark, options).call
25
25
  end
26
26
 
27
+ def self.decorate_array(remarks, options)
28
+ return [] unless remarks
29
+
30
+ remarks.map { |remark| call(remark, options) }
31
+ end
32
+
27
33
  def initialize(remark, options)
28
34
  @remark = remark
29
35
  @options = options
@@ -3,16 +3,15 @@
3
3
  require "liquid"
4
4
  require "asciidoctor"
5
5
  require "asciidoctor/reader"
6
- require "lutaml"
7
6
  require "lutaml/uml"
8
- require "lutaml/formatter"
7
+ require "lutaml/lml"
9
8
 
10
9
  module Metanorma
11
10
  module Plugin
12
11
  module Lutaml
13
12
  module LutamlDiagramBase
14
13
  def process(parent, reader, attrs)
15
- uml_document = ::Lutaml::Uml::Parsers::Dsl
14
+ uml_document = ::Lutaml::Lml::Parser
16
15
  .parse(lutaml_file(parent.document, reader))
17
16
  filename = generate_file(parent, reader, uml_document)
18
17
  through_attrs = generate_attrs(attrs)
@@ -27,24 +27,45 @@ module Metanorma
27
27
  private
28
28
 
29
29
  def parse_result_document(full_path, guidance = nil)
30
- ::Lutaml::Xmi::Parsers::Xml.serialize_xmi_to_liquid(
31
- File.new(full_path, encoding: "UTF-8"),
30
+ ::Ea::Xmi::Parser.serialize_to_liquid(
31
+ full_path,
32
32
  guidance,
33
33
  )
34
34
  end
35
35
 
36
- def get_original_document(parent, index = nil)
36
+ def get_original_document(parent, index = nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
37
37
  path = get_path_from_index(parent, index) if index
38
38
 
39
39
  if index && path
40
- doc = lutaml_document_from_file_or_cache(
40
+ return lutaml_document_from_file_or_cache(
41
41
  parent.document, path,
42
42
  Metanorma::Plugin::Lutaml::Config::Root.new
43
43
  )
44
44
  end
45
45
 
46
- doc ||= parent.document.attributes["lutaml_xmi_cache"].values.first
47
- doc
46
+ # get the first document from lutaml_xmi_cache
47
+ first_path = parent
48
+ .document.attributes["lutaml_xmi_cache"]&.keys&.first
49
+ if first_path
50
+ return lutaml_document_from_file_or_cache(
51
+ parent.document, first_path,
52
+ Metanorma::Plugin::Lutaml::Config::Root.new
53
+ )
54
+ end
55
+
56
+ # get the first document from the first lutaml_xmi_index
57
+ first_index = parent
58
+ .document.attributes["lutaml_xmi_index"]&.keys&.first
59
+
60
+ return unless first_index
61
+
62
+ path_from_index = get_path_from_index(parent, first_index)
63
+ return unless path_from_index
64
+
65
+ lutaml_document_from_file_or_cache(
66
+ parent.document, path_from_index,
67
+ Metanorma::Plugin::Lutaml::Config::Root.new
68
+ )
48
69
  end
49
70
 
50
71
  def img_src_path(document, attrs, diagram)
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "liquid"
4
+ require "asciidoctor"
5
+ require "asciidoctor/reader"
6
+ require "lutaml/uml"
7
+ require_relative "utils"
8
+ require "metanorma/plugin/lutaml/asciidoctor/preprocessor"
9
+ require "metanorma/plugin/lutaml/lutaml_ea_xmi_base"
10
+
11
+ module Metanorma
12
+ module Plugin
13
+ module Lutaml
14
+ # Macro for rendering Lutaml::Uml models which are parsing from
15
+ # XMI/QEA/LUR file
16
+ class LutamlEaUmlPreprocessor < ::Asciidoctor::Extensions::Preprocessor
17
+ include LutamlEaXmiBase
18
+
19
+ MACRO_REGEXP = /\[lutaml_ea_uml,([^,]+),?(.+)?\]/
20
+
21
+ private
22
+
23
+ def parse_result_document(full_path, _guidance)
24
+ case File.extname(full_path).downcase
25
+ when ".xmi"
26
+ ::Ea::Xmi::Parser.parse(full_path)
27
+ when ".qea"
28
+ ::Ea.to_uml(full_path)
29
+ when ".lur"
30
+ repo = ::Lutaml::UmlRepository::Repository.from_file(full_path)
31
+ repo.document
32
+ end
33
+ end
34
+
35
+ def process_text_blocks(document, input_lines) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
36
+ line = input_lines.next
37
+
38
+ process_xmi_index_lines(document, line)
39
+ block_match = line.match(get_macro_regexp)
40
+
41
+ return [line] if block_match.nil?
42
+
43
+ config_yaml_path = block_match[2]&.strip
44
+ filepath_or_index = block_match[1]&.strip
45
+
46
+ lutaml_document, yaml_config = load_lutaml_doc_and_config(
47
+ document,
48
+ filepath_or_index,
49
+ config_yaml_path,
50
+ )
51
+
52
+ block_lines = collect_block_lines(input_lines, input_lines.next)
53
+
54
+ render_result, errors = Utils.render_liquid_string(
55
+ template_string: block_lines.join("\n"),
56
+ contexts: create_default_context_object(
57
+ lutaml_document, yaml_config
58
+ ),
59
+ document: document,
60
+ include_path: template_path(document, yaml_config.template_path),
61
+ )
62
+ Utils.notify_render_errors(document, errors)
63
+
64
+ render_result.split("\n")
65
+ end
66
+
67
+ def create_default_context_object(uml_document, options)
68
+ context_name = "context"
69
+ if options.context_name
70
+ context_name = options.context_name
71
+ end
72
+ contexts = {}
73
+ contexts[context_name] = uml_document.to_liquid
74
+ contexts
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -39,6 +39,61 @@ module Metanorma
39
39
 
40
40
  private
41
41
 
42
+ def lutaml_document_from_file_or_cache(document, file_path, yaml_config, yaml_config_path = nil) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Layout/LineLength,Metrics/PerceivedComplexity
43
+ full_path = Utils.relative_file_path(document, file_path)
44
+ if document.attributes["lutaml_xmi_cache"] &&
45
+ document.attributes["lutaml_xmi_cache"][full_path]
46
+ return document.attributes["lutaml_xmi_cache"][full_path]
47
+ end
48
+
49
+ guidance = get_guidance(document, yaml_config.guidance)
50
+ result_document = parse_result_document(full_path, guidance)
51
+
52
+ # load EA extensions for Xmi::EaRoot
53
+ yaml_config.ea_extension&.each do |ea_extension_path|
54
+ # resolve paths of ea extensions based on the location of
55
+ # config yaml file
56
+ ea_extension_full_path = File.expand_path(
57
+ ea_extension_path, File.dirname(yaml_config_path)
58
+ )
59
+
60
+ # unload the extension if it is already loaded
61
+ xmi_doc = Nokogiri::XML(File.read(ea_extension_full_path))
62
+ extension_id = Xmi::EaRoot.get_module_name(xmi_doc)
63
+ if Xmi::EaRoot.extension_loaded?(extension_id)
64
+ Xmi::EaRoot.unload_extension(extension_id)
65
+ end
66
+
67
+ Xmi::EaRoot.load_extension(ea_extension_full_path)
68
+ end
69
+
70
+ # store in document.attributes as cache
71
+ document.attributes["lutaml_xmi_cache"] ||= {}
72
+ document.attributes["lutaml_xmi_cache"][full_path] = result_document
73
+
74
+ result_document
75
+ end
76
+
77
+ def get_guidance(document, guidance_config)
78
+ return unless guidance_config
79
+
80
+ guidance_yaml = Utils.relative_file_path(document, guidance_config)
81
+ guidance = Metanorma::Plugin::Lutaml::Config::Guidance.from_yaml(
82
+ File.read(guidance_yaml, encoding: "UTF-8"),
83
+ )
84
+ guidance.to_yaml_hash
85
+ end
86
+
87
+ def parse_yaml_config_file(document, file_path)
88
+ return Metanorma::Plugin::Lutaml::Config::Root.new if file_path.nil?
89
+
90
+ relative_file_path = Utils.relative_file_path(document, file_path)
91
+
92
+ Metanorma::Plugin::Lutaml::Config::Root.from_yaml(
93
+ File.read(relative_file_path, encoding: "UTF-8"),
94
+ )
95
+ end
96
+
42
97
  def get_xmi_path(parent, target, attrs)
43
98
  return get_path_from_index(parent, attrs["index"]) if attrs["index"]
44
99
 
@@ -106,8 +161,8 @@ module Metanorma
106
161
  )
107
162
  end
108
163
 
109
- def load_lutaml_doc_and_config(document, xmi_or_index, config_yaml_path) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
110
- index = xmi_or_index.match(/index=(.*)/)
164
+ def load_lutaml_doc_and_config(document, filepath_or_index, config_yaml_path) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Layout/LineLength
165
+ index = filepath_or_index.match(/index=(.*)/)
111
166
 
112
167
  if index
113
168
  index_name = index[1]
@@ -121,7 +176,7 @@ module Metanorma
121
176
  )
122
177
  end
123
178
 
124
- xmi_or_index = document
179
+ filepath_or_index = document
125
180
  .attributes["lutaml_xmi_index"][index_name][:path]
126
181
  config_yaml_path = document
127
182
  .attributes["lutaml_xmi_index"][index_name][:config]
@@ -130,7 +185,7 @@ module Metanorma
130
185
  yaml_config = parse_yaml_config_file(document, config_yaml_path)
131
186
  lutaml_document = lutaml_document_from_file_or_cache(
132
187
  document,
133
- xmi_or_index,
188
+ filepath_or_index,
134
189
  yaml_config,
135
190
  Utils.relative_file_path(document, config_yaml_path),
136
191
  )