metanorma-plugin-lutaml 0.7.8 → 0.7.9
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.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29510e3dd02119b47d1d179c94d0a954b596dc0255410091d8c0db366e6a4dd3
|
4
|
+
data.tar.gz: b2502ffd6bea597bc56c8882712c58d13e72799eca5387c76329a9ef813d62eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b06a2f0d8be8e9073c3f631b260d8e88525353afb8e4e6cdf11bd6db9d78994543eb6a9acda9a2602212943ff972a700efa7c7d3dc870951cd3f2c6e5a219ff2
|
7
|
+
data.tar.gz: c80c2d456bec408dccb3c621397bc9313e2cc6a53cf7c5671d504737087ebb597b446d2fc043e3deaaf809a0941f0f3b732837bf4b5aee404685d70cd6ab0d27
|
data/Gemfile
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require "coradoc"
|
2
|
-
require "coradoc/input/html"
|
3
2
|
|
4
3
|
module Metanorma
|
5
4
|
module Plugin
|
@@ -7,6 +6,7 @@ module Metanorma
|
|
7
6
|
module Liquid
|
8
7
|
module CustomFilters
|
9
8
|
def html2adoc(input)
|
9
|
+
# Coradoc::ReverseAdoc.convert(input)
|
10
10
|
Coradoc::Input::HTML.convert(input)
|
11
11
|
end
|
12
12
|
|
@@ -0,0 +1,310 @@
|
|
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 "xmi"
|
9
|
+
require "lutaml/xmi"
|
10
|
+
require "metanorma/plugin/lutaml/utils"
|
11
|
+
require "metanorma/plugin/lutaml/asciidoctor/preprocessor"
|
12
|
+
|
13
|
+
module Metanorma
|
14
|
+
module Plugin
|
15
|
+
module Lutaml
|
16
|
+
# Macro for quick rendering of datamodel attributes/values tables
|
17
|
+
# from liquid drop object
|
18
|
+
class LutamlEaXmiPreprocessor <
|
19
|
+
::Asciidoctor::Extensions::Preprocessor
|
20
|
+
MACRO_REGEXP =
|
21
|
+
/\[lutaml_ea_xmi,([^,]+),?(.+)?\]/.freeze
|
22
|
+
LIQUID_INCLUDE_PATH = File.join(
|
23
|
+
Gem.loaded_specs["metanorma-plugin-lutaml"].full_gem_path,
|
24
|
+
"lib", "metanorma", "plugin", "lutaml", "liquid_templates"
|
25
|
+
)
|
26
|
+
DEFAULT_RENDER_INCLUDE = "packages"
|
27
|
+
RENDER_STYLES_INCLUDES = {
|
28
|
+
"default" => "packages",
|
29
|
+
"entity_list" => "packages_entity_list",
|
30
|
+
"entity_list_class" => "packages_entity_list_class",
|
31
|
+
"data_dictionary" => "packages_data_dictionary",
|
32
|
+
}.freeze
|
33
|
+
RENDER_STYLE_ATTRIBUTE = "render_style"
|
34
|
+
SUPPORTED_NESTED_MACRO = %w[
|
35
|
+
before diagram_include_block after include_block package_text
|
36
|
+
].freeze
|
37
|
+
# search document for block `lutaml_ea_xmi`
|
38
|
+
# read include derectives that goes after that in block and transform
|
39
|
+
# into yaml2text blocks
|
40
|
+
def process(document, reader)
|
41
|
+
r = Asciidoctor::PreprocessorNoIfdefsReader.new document, reader.lines
|
42
|
+
input_lines = r.readlines.to_enum
|
43
|
+
Asciidoctor::PreprocessorNoIfdefsReader
|
44
|
+
.new(document, processed_lines(document, input_lines))
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def lutaml_document_from_file_or_cache(document, file_path, yaml_config)
|
50
|
+
full_path = Utils.relative_file_path(document, file_path)
|
51
|
+
if document.attributes["lutaml_xmi_cache"] &&
|
52
|
+
document.attributes["lutaml_xmi_cache"][full_path]
|
53
|
+
return document.attributes["lutaml_xmi_cache"][full_path]
|
54
|
+
end
|
55
|
+
|
56
|
+
yaml_config["ea_extension"]&.each do |ea_extension_path|
|
57
|
+
ea_extension_full_path = File.expand_path(
|
58
|
+
ea_extension_path, File.dirname(file_path)
|
59
|
+
)
|
60
|
+
Xmi::EaRoot.load_extension(ea_extension_full_path)
|
61
|
+
end
|
62
|
+
|
63
|
+
result_document = ::Lutaml::XMI::Parsers::XML.serialize_xmi_to_liquid(
|
64
|
+
File.new(
|
65
|
+
full_path, encoding: "UTF-8"
|
66
|
+
),
|
67
|
+
)
|
68
|
+
|
69
|
+
document.attributes["lutaml_xmi_cache"] ||= {}
|
70
|
+
document.attributes["lutaml_xmi_cache"][full_path] = result_document
|
71
|
+
result_document
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_yaml_config_file(document, file_path)
|
75
|
+
return {} if file_path.nil?
|
76
|
+
|
77
|
+
relative_file_path = Utils.relative_file_path(document, file_path)
|
78
|
+
YAML.safe_load(File.read(relative_file_path, encoding: "UTF-8"))
|
79
|
+
end
|
80
|
+
|
81
|
+
def processed_lines(document, input_lines)
|
82
|
+
result = []
|
83
|
+
loop do
|
84
|
+
result.push(*process_text_blocks(document, input_lines))
|
85
|
+
end
|
86
|
+
result
|
87
|
+
end
|
88
|
+
|
89
|
+
def process_text_blocks(document, input_lines)
|
90
|
+
line = input_lines.next
|
91
|
+
block_match = line.match(MACRO_REGEXP)
|
92
|
+
|
93
|
+
return [line] if block_match.nil?
|
94
|
+
|
95
|
+
yaml_config = parse_yaml_config_file(document, block_match[2])
|
96
|
+
lutaml_document = lutaml_document_from_file_or_cache(document,
|
97
|
+
block_match[1],
|
98
|
+
yaml_config)
|
99
|
+
fill_in_diagrams_attributes(document, lutaml_document)
|
100
|
+
model_representation(
|
101
|
+
lutaml_document, document,
|
102
|
+
collect_additional_context(document, input_lines, input_lines.next),
|
103
|
+
yaml_config
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
def fill_in_entities_refs_attributes(document,
|
108
|
+
lutaml_document, options)
|
109
|
+
# render_style = options.fetch(RENDER_STYLE_ATTRIBUTE, "default")
|
110
|
+
all_children_packages = lutaml_document.packages
|
111
|
+
.map(&:children_packages).flatten
|
112
|
+
package_flat_packages = lambda do |pks|
|
113
|
+
pks.each_with_object({}) do |package, res|
|
114
|
+
res[package.name] = package.xmi_id
|
115
|
+
end
|
116
|
+
end
|
117
|
+
children_pks = package_flat_packages.call(all_children_packages)
|
118
|
+
ref_dictionary = package_flat_packages.call(lutaml_document.packages)
|
119
|
+
.merge(children_pks)
|
120
|
+
%w[class enum data_type].each do |type|
|
121
|
+
package_flat = lambda do |pks|
|
122
|
+
pks.each_with_object({}) do |package, res|
|
123
|
+
plural = type == "class" ? "classes" : "#{type}s"
|
124
|
+
package.send(plural).map do |entity|
|
125
|
+
res["#{type}:#{package.name}:#{entity.name}"] = entity.xmi_id
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
children_pks_diags = package_flat.call(all_children_packages)
|
130
|
+
ref_dictionary = ref_dictionary
|
131
|
+
.merge(package_flat.call(lutaml_document.packages)
|
132
|
+
.merge(children_pks_diags))
|
133
|
+
end
|
134
|
+
document.attributes["lutaml_entity_id"] = ref_dictionary
|
135
|
+
end
|
136
|
+
|
137
|
+
def fill_in_diagrams_attributes(document, lutaml_document)
|
138
|
+
package_flat_diagrams = lambda do |pks|
|
139
|
+
pks.each_with_object({}) do |package, res|
|
140
|
+
package.diagrams.map do |diag|
|
141
|
+
res["#{package.name}:#{diag.name}"] = diag.xmi_id
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
children_pks_diags = package_flat_diagrams.call(
|
146
|
+
lutaml_document.packages.map(&:children_packages).flatten,
|
147
|
+
)
|
148
|
+
|
149
|
+
document.attributes["lutaml_figure_id"] = package_flat_diagrams
|
150
|
+
.call(lutaml_document.packages)
|
151
|
+
.merge(children_pks_diags)
|
152
|
+
end
|
153
|
+
|
154
|
+
def collect_additional_context(document, input_lines, end_mark)
|
155
|
+
additional_context = Hash.new { |hash, key| hash[key] = [] }
|
156
|
+
additional_context["all_macros"] = []
|
157
|
+
block_lines = []
|
158
|
+
while (block_line = input_lines.next) != end_mark
|
159
|
+
block_lines.push(block_line)
|
160
|
+
end
|
161
|
+
processed_lines =
|
162
|
+
process(document, ::Asciidoctor::PreprocessorReader.new(
|
163
|
+
document, block_lines
|
164
|
+
))
|
165
|
+
.read_lines
|
166
|
+
block_document = ::Asciidoctor::Document
|
167
|
+
.new(processed_lines, {}).parse
|
168
|
+
block_document.blocks.each do |block|
|
169
|
+
next unless SUPPORTED_NESTED_MACRO.include?(block.attributes["role"])
|
170
|
+
|
171
|
+
attrs = block.attributes
|
172
|
+
name = attrs.delete("role")
|
173
|
+
package = attrs.delete("package")
|
174
|
+
macro_keyword = [name, package].compact.join(";")
|
175
|
+
block_text = block.lines.length.positive? ? block.lines.join("\n") : ""
|
176
|
+
additional_context[macro_keyword]
|
177
|
+
.push({ "text" => block_text }.merge(attrs))
|
178
|
+
additional_context["all_macros"]
|
179
|
+
.push({ "text" => block_text,
|
180
|
+
"type" => name, "package" => package }.merge(attrs))
|
181
|
+
end
|
182
|
+
additional_context
|
183
|
+
end
|
184
|
+
|
185
|
+
def package_level(lutaml_document, level)
|
186
|
+
return lutaml_document if level <= 0
|
187
|
+
|
188
|
+
package_level(lutaml_document["packages"].first, level - 1)
|
189
|
+
end
|
190
|
+
|
191
|
+
def create_context_object(lutaml_document, additional_context, options)
|
192
|
+
root_package = package_level(lutaml_document.to_liquid,
|
193
|
+
options["package_root_level"] || 1)
|
194
|
+
if options.empty? || options["packages"].nil?
|
195
|
+
return {
|
196
|
+
"render_nested_packages" => true,
|
197
|
+
"packages" => root_package["packages"],
|
198
|
+
"root_packages" => [root_package],
|
199
|
+
"additional_context" => additional_context
|
200
|
+
.merge("external_classes" => options["external_classes"]),
|
201
|
+
"name" => root_package["name"],
|
202
|
+
}
|
203
|
+
end
|
204
|
+
|
205
|
+
all_packages = [root_package, *root_package["children_packages"]]
|
206
|
+
{
|
207
|
+
"packages" => sort_and_filter_out_packages(all_packages, options),
|
208
|
+
"package_entities" => package_entities(options),
|
209
|
+
"package_skip_sections" => package_skip_sections(options),
|
210
|
+
"additional_context" => additional_context
|
211
|
+
.merge("external_classes" => options["external_classes"]),
|
212
|
+
"root_packages" => [root_package],
|
213
|
+
"render_nested_packages" => options["render_nested_packages"] ||
|
214
|
+
false,
|
215
|
+
"name" => root_package["name"],
|
216
|
+
}
|
217
|
+
end
|
218
|
+
|
219
|
+
def package_entities(options)
|
220
|
+
return {} unless options["packages"]
|
221
|
+
|
222
|
+
options["packages"]
|
223
|
+
.find_all { |entity| entity.is_a?(Hash) && entity.values.first["render_entities"] }
|
224
|
+
.map do |entity|
|
225
|
+
[entity.keys.first,
|
226
|
+
entity.values.first["render_entities"].map { |n| [n, true] }.to_h]
|
227
|
+
end.to_h
|
228
|
+
end
|
229
|
+
|
230
|
+
def package_skip_sections(options)
|
231
|
+
return {} unless options["packages"]
|
232
|
+
|
233
|
+
options["packages"]
|
234
|
+
.find_all { |entity| entity.is_a?(Hash) && entity.values.first["skip_tables"] }
|
235
|
+
.map do |entity|
|
236
|
+
[entity.keys.first, entity.values.first["skip_tables"].map do |n|
|
237
|
+
[n, true]
|
238
|
+
end.to_h]
|
239
|
+
end.to_h
|
240
|
+
end
|
241
|
+
|
242
|
+
def sort_and_filter_out_packages(all_packages, options)
|
243
|
+
return all_packages if options["packages"].nil?
|
244
|
+
|
245
|
+
result = []
|
246
|
+
# Step one - filter out all skipped packages
|
247
|
+
options["packages"]
|
248
|
+
.find_all { |entity| entity.is_a?(Hash) && entity["skip"] }
|
249
|
+
.each do |entity|
|
250
|
+
entity_regexp = config_entity_regexp(entity["skip"])
|
251
|
+
all_packages
|
252
|
+
.delete_if { |package| package["name"] =~ entity_regexp }
|
253
|
+
end
|
254
|
+
# Step two - select supplied packages by pattern
|
255
|
+
options["packages"]
|
256
|
+
.find_all { |entity| entity.is_a?(String) || (entity.is_a?(Hash) && !entity["skip"]) }
|
257
|
+
.each do |entity_obj|
|
258
|
+
entity = entity_obj.is_a?(String) ? entity_obj : entity_obj.keys.first
|
259
|
+
entity_regexp = config_entity_regexp(entity)
|
260
|
+
all_packages.each do |package|
|
261
|
+
if package["name"]&.match?(entity_regexp)
|
262
|
+
result.push(package)
|
263
|
+
all_packages
|
264
|
+
.delete_if { |nest_package| nest_package["name"] == package["name"] }
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
result
|
269
|
+
end
|
270
|
+
|
271
|
+
def config_entity_regexp(entity)
|
272
|
+
additional_sym = ".*" if /\*$/.match?(entity)
|
273
|
+
%r{^#{Regexp.escape(entity.delete('*'))}#{additional_sym}$}
|
274
|
+
end
|
275
|
+
|
276
|
+
def model_representation(lutaml_document, document, additional_context,
|
277
|
+
options)
|
278
|
+
fill_in_entities_refs_attributes(document, lutaml_document, options)
|
279
|
+
render_result, errors = Utils.render_liquid_string(
|
280
|
+
template_string: template(options["section_depth"] || 2,
|
281
|
+
options["render_style"],
|
282
|
+
options["include_root"]),
|
283
|
+
context_items: create_context_object(lutaml_document,
|
284
|
+
additional_context,
|
285
|
+
options),
|
286
|
+
context_name: "context",
|
287
|
+
document: document,
|
288
|
+
include_path: LIQUID_INCLUDE_PATH,
|
289
|
+
)
|
290
|
+
Utils.notify_render_errors(document, errors)
|
291
|
+
render_result.split("\n")
|
292
|
+
end
|
293
|
+
|
294
|
+
def template(section_depth, render_style, include_root)
|
295
|
+
include_name = RENDER_STYLES_INCLUDES.fetch(render_style,
|
296
|
+
DEFAULT_RENDER_INCLUDE)
|
297
|
+
result = ""
|
298
|
+
if include_root
|
299
|
+
result += <<~LIQUID
|
300
|
+
{% include "#{include_name}", package_skip_sections: context.package_skip_sections, package_entities: context.package_entities, context: context.root_packages, additional_context: context.additional_context, render_nested_packages: false %}
|
301
|
+
LIQUID
|
302
|
+
end
|
303
|
+
result + <<~LIQUID
|
304
|
+
{% include "#{include_name}", depth: #{section_depth}, package_skip_sections: context.package_skip_sections, package_entities: context.package_entities, context: context, additional_context: context.additional_context, render_nested_packages: context.render_nested_packages %}
|
305
|
+
LIQUID
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
@@ -3,6 +3,7 @@ require "metanorma/plugin/lutaml/lutaml_preprocessor"
|
|
3
3
|
require "metanorma/plugin/lutaml/lutaml_uml_class_preprocessor"
|
4
4
|
require "metanorma/plugin/lutaml/lutaml_uml_attributes_table_preprocessor"
|
5
5
|
require "metanorma/plugin/lutaml/lutaml_uml_datamodel_description_preprocessor"
|
6
|
+
require "metanorma/plugin/lutaml/lutaml_ea_xmi_preprocessor"
|
6
7
|
require "metanorma/plugin/lutaml/lutaml_diagram_block"
|
7
8
|
require "metanorma/plugin/lutaml/lutaml_diagram_block_macro"
|
8
9
|
require "metanorma/plugin/lutaml/lutaml_figure_inline_macro"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metanorma-plugin-lutaml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
@@ -355,6 +355,7 @@ files:
|
|
355
355
|
- lib/metanorma/plugin/lutaml/lutaml_diagram_block.rb
|
356
356
|
- lib/metanorma/plugin/lutaml/lutaml_diagram_block_macro.rb
|
357
357
|
- lib/metanorma/plugin/lutaml/lutaml_ea_diagram_block_macro.rb
|
358
|
+
- lib/metanorma/plugin/lutaml/lutaml_ea_xmi_preprocessor.rb
|
358
359
|
- lib/metanorma/plugin/lutaml/lutaml_figure_inline_macro.rb
|
359
360
|
- lib/metanorma/plugin/lutaml/lutaml_gml_dictionary_base.rb
|
360
361
|
- lib/metanorma/plugin/lutaml/lutaml_gml_dictionary_block.rb
|