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,188 @@
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 "metanorma/plugin/lutaml/utils"
9
+
10
+ module Metanorma
11
+ module Plugin
12
+ module Lutaml
13
+ # Macro for quick rendering of datamodel attributes/values table
14
+ # @example [lutaml_uml_attributes_table,path/to/lutaml,EntityName]
15
+ class LutamlUmlDatamodelDescriptionPreprocessor <
16
+ Asciidoctor::Extensions::Preprocessor
17
+ MARCO_REGEXP =
18
+ /\[lutaml_uml_datamodel_description,([^,]+),?(.+)?\]/
19
+ LIQUID_INCLUDE_PATH = File.join(
20
+ Gem.loaded_specs["metanorma-plugin-lutaml"].full_gem_path,
21
+ "lib", "metanorma", "plugin", "lutaml", "liquid_templates"
22
+ )
23
+ DEFAULT_RENDER_INCLUDE = 'packages'.freeze
24
+ RENDER_STYLES_INCLUDES = {
25
+ 'default' => 'packages',
26
+ 'entity_list' => 'packages_entity_list',
27
+ 'data_dictionary' => 'packages_data_dictionary'
28
+ }.freeze
29
+ SUPPORTED_NESTED_MACRO = %w[
30
+ before diagram_include_block after include_block].freeze
31
+ # search document for block `lutaml_uml_datamodel_description`
32
+ # read include derectives that goes after that in block and transform
33
+ # into yaml2text blocks
34
+ def process(document, reader)
35
+ input_lines = reader.readlines.to_enum
36
+ Asciidoctor::Reader.new(processed_lines(document, input_lines))
37
+ end
38
+
39
+ private
40
+
41
+ def lutaml_document_from_file(document, file_path)
42
+ ::Lutaml::Parser
43
+ .parse(File.new(Utils.relative_file_path(document, file_path),
44
+ encoding: "UTF-8"))
45
+ .first
46
+ end
47
+
48
+ def parse_yaml_config_file(document, file_path)
49
+ return {} if file_path.nil?
50
+
51
+ relative_file_path = Utils.relative_file_path(document, file_path)
52
+ YAML.load(File.read(relative_file_path, encoding: "UTF-8"))
53
+ end
54
+
55
+ def processed_lines(document, input_lines)
56
+ result = []
57
+ loop do
58
+ result.push(*process_text_blocks(document, input_lines))
59
+ end
60
+ result
61
+ end
62
+
63
+ def process_text_blocks(document, input_lines)
64
+ line = input_lines.next
65
+ block_match = line.match(MARCO_REGEXP)
66
+ return [line] if block_match.nil?
67
+
68
+ lutaml_document = lutaml_document_from_file(document, block_match[1])
69
+ fill_in_diagrams_attributes(document, lutaml_document)
70
+ model_representation(
71
+ lutaml_document,
72
+ document,
73
+ collect_additional_context(input_lines, input_lines.next),
74
+ parse_yaml_config_file(document, block_match[2]))
75
+ end
76
+
77
+ def fill_in_diagrams_attributes(document, lutaml_document_wrapper)
78
+ lutaml_document = lutaml_document_wrapper.original_document
79
+ package_flat_diagrams = lambda do |pks|
80
+ pks.each_with_object({}) do |package, res|
81
+ package.diagrams.map { |diag| res["#{package.name}:#{diag.name}"] = diag.xmi_id }
82
+ end
83
+ end
84
+ children_pks_daigs = package_flat_diagrams.call(lutaml_document.packages.map(&:children_packages).flatten)
85
+ document.attributes['lutaml_figure_id'] = package_flat_diagrams.call(lutaml_document.packages)
86
+ .merge(children_pks_daigs)
87
+ end
88
+
89
+ def collect_additional_context(input_lines, end_mark)
90
+ additional_context = Hash.new { |hash, key| hash[key] = [] }
91
+ block_lines = []
92
+ while (block_line = input_lines.next) != end_mark
93
+ block_lines.push(block_line)
94
+ end
95
+ block_document = (Asciidoctor::Document.new(block_lines, {})).parse
96
+ block_document.blocks.each do |block|
97
+ next unless SUPPORTED_NESTED_MACRO.include?(block.attributes['role'])
98
+
99
+ attrs = block.attributes
100
+ name = attrs.delete('role')
101
+ package = attrs.delete('package')
102
+ macro_keyword = [name, package].compact.join(";")
103
+ block_text = block.lines.length > 0 ? block.lines[1..-2].join("\n") : ''
104
+ additional_context[macro_keyword].push({ 'text' => block_text }.merge(attrs))
105
+ end
106
+ additional_context
107
+ end
108
+
109
+ def package_level(lutaml_document, level)
110
+ return lutaml_document if level <= 0
111
+
112
+ package_level(lutaml_document['packages'].first, level - 1)
113
+ end
114
+
115
+ def create_context_object(lutaml_document, additional_context, options)
116
+ root_package = package_level(lutaml_document.to_liquid, options['package_root_level'] || 1)
117
+ if options.length.zero? || options['packages'].nil?
118
+ return {
119
+ 'render_nested_packages' => true,
120
+ "packages" => root_package['packages'],
121
+ "additional_context" => additional_context
122
+ }
123
+ end
124
+
125
+ all_packages = [root_package, *root_package['children_packages']]
126
+ {
127
+ "packages" => sort_and_filter_out_packages(all_packages, options),
128
+ "additional_context" => additional_context
129
+ }
130
+ end
131
+
132
+ def sort_and_filter_out_packages(all_packages, options)
133
+ return all_packages if options['packages'].nil?
134
+
135
+ result = []
136
+ # Step one - filter out all skipped packages
137
+ options['packages']
138
+ .find_all { |entity| entity.is_a?(Hash) && entity['skip'] }
139
+ .each do |entity|
140
+ entity_regexp = config_entity_regexp(entity['skip'])
141
+ all_packages
142
+ .delete_if {|package| package['name'] =~ entity_regexp }
143
+ end
144
+ # Step two - select supplied packages by pattern
145
+ options['packages']
146
+ .find_all { |entity| entity.is_a?(String) }
147
+ .each do |entity|
148
+ entity_regexp = config_entity_regexp(entity)
149
+ all_packages.each.with_index do |package|
150
+ if package['name'] =~ entity_regexp
151
+ result.push(package)
152
+ all_packages
153
+ .delete_if {|nest_package| nest_package['name'] == package['name'] }
154
+ end
155
+ end
156
+ end
157
+ result
158
+ end
159
+
160
+ def config_entity_regexp(entity)
161
+ additional_sym = '.*' if entity =~ /\*$/
162
+ %r{^#{Regexp.escape(entity.gsub('*', ''))}#{additional_sym}$}
163
+ end
164
+
165
+ def model_representation(lutaml_document, document, additional_context, options)
166
+ render_result, errors = Utils.render_liquid_string(
167
+ template_string: table_template(options['section_depth'] || 2, options['render_style']),
168
+ context_items: create_context_object(lutaml_document,
169
+ additional_context,
170
+ options),
171
+ context_name: "context",
172
+ document: document,
173
+ include_path: LIQUID_INCLUDE_PATH
174
+ )
175
+ Utils.notify_render_errors(document, errors)
176
+ render_result.split("\n")
177
+ end
178
+
179
+ def table_template(section_depth, render_style)
180
+ include_name = RENDER_STYLES_INCLUDES.fetch(render_style, DEFAULT_RENDER_INCLUDE)
181
+ <<~LIQUID
182
+ {% include "#{include_name}", depth: #{section_depth}, context: context, additional_context: context.additional_context, render_nested_packages: context.render_nested_packages %}
183
+ LIQUID
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -1,5 +1,6 @@
1
1
  require "expressir/express/cache"
2
2
  require "metanorma/plugin/lutaml/liquid/custom_filters"
3
+ require "metanorma/plugin/lutaml/liquid/multiply_local_file_system"
3
4
 
4
5
  ::Liquid::Template.register_filter(Metanorma::Plugin::Lutaml::Liquid::CustomFilters)
5
6
 
@@ -22,10 +23,11 @@ module Metanorma
22
23
  end
23
24
 
24
25
  def render_liquid_string(template_string:, context_items:,
25
- context_name:, document:)
26
+ context_name:, document:, include_path: nil)
26
27
  liquid_template = ::Liquid::Template.parse(template_string)
27
28
  # Allow includes for the template
28
- liquid_template.registers[:file_system] = ::Liquid::LocalFileSystem.new(Utils.relative_file_path(document, ""))
29
+ include_paths = [Utils.relative_file_path(document, ""), include_path].compact
30
+ liquid_template.registers[:file_system] = ::Metanorma::Plugin::Lutaml::Liquid::LocalFileSystem.new(include_paths, ["_%s.liquid", "_%s.adoc"])
29
31
  rendered_string = liquid_template
30
32
  .render(context_name => context_items,
31
33
  strict_variables: true,
@@ -1,7 +1,7 @@
1
1
  module Metanorma
2
2
  module Plugin
3
3
  module Lutaml
4
- VERSION = "0.4.2".freeze
4
+ VERSION = "0.4.6".freeze
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-plugin-lutaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-07-16 00:00:00.000000000 Z
11
+ date: 2021-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -257,9 +257,22 @@ files:
257
257
  - lib/metanorma-plugin-lutaml.rb
258
258
  - lib/metanorma/plugin/lutaml/express_remarks_decorator.rb
259
259
  - lib/metanorma/plugin/lutaml/liquid/custom_filters.rb
260
+ - lib/metanorma/plugin/lutaml/liquid/multiply_local_file_system.rb
261
+ - lib/metanorma/plugin/lutaml/liquid_templates/_diagrams_block.liquid
262
+ - lib/metanorma/plugin/lutaml/liquid_templates/_packages.liquid
263
+ - lib/metanorma/plugin/lutaml/liquid_templates/_packages_class.liquid
264
+ - lib/metanorma/plugin/lutaml/liquid_templates/_packages_data_dictionary.liquid
265
+ - lib/metanorma/plugin/lutaml/liquid_templates/_packages_data_dictionary_classes.liquid
266
+ - lib/metanorma/plugin/lutaml/liquid_templates/_packages_data_type.liquid
267
+ - lib/metanorma/plugin/lutaml/liquid_templates/_packages_entity_list.liquid
268
+ - lib/metanorma/plugin/lutaml/liquid_templates/_packages_enum.liquid
269
+ - lib/metanorma/plugin/lutaml/lutaml_diagram_base.rb
260
270
  - lib/metanorma/plugin/lutaml/lutaml_diagram_block.rb
271
+ - lib/metanorma/plugin/lutaml/lutaml_diagram_block_macro.rb
272
+ - lib/metanorma/plugin/lutaml/lutaml_figure_inline_macro.rb
261
273
  - lib/metanorma/plugin/lutaml/lutaml_preprocessor.rb
262
274
  - lib/metanorma/plugin/lutaml/lutaml_uml_attributes_table_preprocessor.rb
275
+ - lib/metanorma/plugin/lutaml/lutaml_uml_datamodel_description_preprocessor.rb
263
276
  - lib/metanorma/plugin/lutaml/utils.rb
264
277
  - lib/metanorma/plugin/lutaml/version.rb
265
278
  - metanorma-plugin-lutaml.gemspec