metanorma-plugin-lutaml 0.6.0 → 0.6.2
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 +4 -4
- data/Gemfile +5 -1
- data/README.adoc +62 -3
- data/lib/metanorma/plugin/lutaml/express_remarks_decorator.rb +1 -1
- data/lib/metanorma/plugin/lutaml/liquid/custom_filters.rb +1 -1
- data/lib/metanorma/plugin/lutaml/liquid/multiply_local_file_system.rb +38 -23
- data/lib/metanorma/plugin/lutaml/lutaml_preprocessor.rb +176 -96
- data/lib/metanorma/plugin/lutaml/lutaml_uml_attributes_table_preprocessor.rb +1 -1
- data/lib/metanorma/plugin/lutaml/lutaml_uml_class_preprocessor.rb +3 -3
- data/lib/metanorma/plugin/lutaml/lutaml_uml_datamodel_description_preprocessor.rb +4 -3
- data/lib/metanorma/plugin/lutaml/utils.rb +67 -48
- data/lib/metanorma/plugin/lutaml/version.rb +1 -1
- data/metanorma-plugin-lutaml.gemspec +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 56a196838fa30ab8585b1834d115bf6ff99b4b81d33176975b75dc7f5c5cd5bd
|
|
4
|
+
data.tar.gz: 458ce39ccac1e11b1dee74289e9e85a06a4ec5fa2faceaa78869ca18cc8dae77
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 780fa1199a23d199cb8f04d1a1b9b79d416f8aed0a2b442f02baccd370830d76d80fee12c2061e9424c9dd294059f5709b50a0eac7ac9b24fd4b492f54caa839
|
|
7
|
+
data.tar.gz: 1582258a02474a3ee351b935afc686a78ed8c82f1cc72efefde7c003110bfaa8fd4189d979b2070e61509d5d4997208b7644daf529c6e221c9e187e4e3def057
|
data/Gemfile
CHANGED
data/README.adoc
CHANGED
|
@@ -28,9 +28,9 @@ LutaML supports accessing EXPRESS models via the
|
|
|
28
28
|
https://github.com/lutaml/expressir[Expressir] parser.
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
=== Usage of the `lutaml`
|
|
31
|
+
=== Usage of the `lutaml` command
|
|
32
32
|
|
|
33
|
-
Given an `example.exp` EXPRESS file with
|
|
33
|
+
Given an `example.exp` EXPRESS file with content:
|
|
34
34
|
|
|
35
35
|
[source,exp]
|
|
36
36
|
----
|
|
@@ -57,7 +57,7 @@ SCHEMA test_schema 'test';
|
|
|
57
57
|
END_SCHEMA;
|
|
58
58
|
----
|
|
59
59
|
|
|
60
|
-
And the `lutaml`
|
|
60
|
+
And the `lutaml` block:
|
|
61
61
|
|
|
62
62
|
[source,adoc]
|
|
63
63
|
-----
|
|
@@ -137,6 +137,7 @@ Example of usage:
|
|
|
137
137
|
= Document title
|
|
138
138
|
Author
|
|
139
139
|
:lutaml-express-index: index_name; /path/to/express_files; cache=/path/to/cache_file.yaml
|
|
140
|
+
|
|
140
141
|
[lutaml,index_name,context]
|
|
141
142
|
----
|
|
142
143
|
{% for schema in context.schemas %}
|
|
@@ -145,6 +146,64 @@ Author
|
|
|
145
146
|
----
|
|
146
147
|
-----
|
|
147
148
|
|
|
149
|
+
=== Using `config.yaml`
|
|
150
|
+
|
|
151
|
+
This functionality allows `[lutaml_express]` blocks to load a full set of
|
|
152
|
+
EXPRESS schemas in one index, and then provide a select ("filter") option
|
|
153
|
+
per-block via a separate YAML file.
|
|
154
|
+
|
|
155
|
+
[source,adoc]
|
|
156
|
+
----
|
|
157
|
+
:lutaml-express-index: schemas_1; schemas_all.yaml;
|
|
158
|
+
|
|
159
|
+
[lutaml_express,schemas_1,repo,leveloffset=+1,config_yaml=select.yaml]
|
|
160
|
+
---
|
|
161
|
+
{% assign selected = repo.schemas | where: "selected" %}
|
|
162
|
+
{% render "templates/resources/schema" for selected as schema %}
|
|
163
|
+
---
|
|
164
|
+
----
|
|
165
|
+
|
|
166
|
+
Where `schemas_all.yml` provides all schemas:
|
|
167
|
+
|
|
168
|
+
[source,yaml]
|
|
169
|
+
----
|
|
170
|
+
---
|
|
171
|
+
schemas:
|
|
172
|
+
action_schema:
|
|
173
|
+
path: "../../schemas/resources/action_schema/action_schema.exp"
|
|
174
|
+
application_context_schema:
|
|
175
|
+
path: "../../schemas/resources/application_context_schema/application_context_schema.exp"
|
|
176
|
+
approval_schema:
|
|
177
|
+
path: "../../schemas/resources/approval_schema/approval_schema.exp"
|
|
178
|
+
...
|
|
179
|
+
----
|
|
180
|
+
|
|
181
|
+
And `select.yaml` only selects 2 schemas:
|
|
182
|
+
|
|
183
|
+
[source,yaml]
|
|
184
|
+
----
|
|
185
|
+
---
|
|
186
|
+
schemas:
|
|
187
|
+
- action_schema
|
|
188
|
+
- application_context_schema
|
|
189
|
+
----
|
|
190
|
+
|
|
191
|
+
The resulting block adds the `select` attribute to every schema of the the
|
|
192
|
+
"context" object, which allows you to filter those out for complex operations
|
|
193
|
+
via Liquid:
|
|
194
|
+
|
|
195
|
+
[source,liquid]
|
|
196
|
+
----
|
|
197
|
+
[lutaml_express,schemas_1,repo,leveloffset=+1,config_yaml=select.yaml]
|
|
198
|
+
---
|
|
199
|
+
{% assign selected = repo.schemas | where: "selected" %}
|
|
200
|
+
... do things with `selected` ...
|
|
201
|
+
----
|
|
202
|
+
|
|
203
|
+
NOTE: This functionality is used in the ISO 10303 SRL to load the full schema
|
|
204
|
+
set at once but only render the selected schemas in individual documents.
|
|
205
|
+
|
|
206
|
+
|
|
148
207
|
== Usage with UML
|
|
149
208
|
|
|
150
209
|
=== Rendering a LutaML view: `lutaml_diagram`
|
|
@@ -48,7 +48,7 @@ module Metanorma
|
|
|
48
48
|
# When we are dealing with a relative path of a template:
|
|
49
49
|
# ../path/to/file we need to transform it into
|
|
50
50
|
# the absolute one because `image::` macro wont understand it other way
|
|
51
|
-
prefixed_path = File.absolute_path(prefixed_path) if prefixed_path.start_with?(
|
|
51
|
+
prefixed_path = File.absolute_path(prefixed_path) if prefixed_path.start_with?("../")
|
|
52
52
|
full_path = File.expand_path(prefixed_path)
|
|
53
53
|
"#{$1}#{$2}#{full_path}#{$4}"
|
|
54
54
|
end
|
|
@@ -12,36 +12,51 @@ module Metanorma
|
|
|
12
12
|
|
|
13
13
|
def read_template_file(template_path)
|
|
14
14
|
full_path = full_path(template_path)
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
unless File.exist?(full_path)
|
|
17
|
+
raise FileSystemError, "No such template '#{template_path}'"
|
|
18
|
+
end
|
|
16
19
|
|
|
17
20
|
File.read(full_path)
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
def full_path(template_path)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
24
|
+
unless %r{\A[^./][a-zA-Z0-9_/]+\z}.match?(template_path)
|
|
25
|
+
raise ::Liquid::FileSystemError,
|
|
26
|
+
"Illegal template name '#{template_path}'"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
result_path = if template_path.include?("/")
|
|
30
|
+
roots
|
|
31
|
+
.map do |root|
|
|
32
|
+
patterns.map do |pattern|
|
|
33
|
+
File.join(root, File.dirname(template_path),
|
|
34
|
+
pattern % File.basename(template_path))
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
.flatten
|
|
38
|
+
.find { |path| File.file?(path) }
|
|
39
|
+
else
|
|
40
|
+
roots
|
|
41
|
+
.map do |root|
|
|
42
|
+
patterns.map do |pattern|
|
|
43
|
+
File.join(root, pattern % template_path)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
.flatten
|
|
47
|
+
.find { |path| File.file?(path) }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if result_path.nil?
|
|
51
|
+
raise ::Liquid::FileSystemError,
|
|
52
|
+
"No documents in template path '#{File.expand_path(template_path)}'"
|
|
41
53
|
end
|
|
42
54
|
|
|
43
|
-
unless roots.any?
|
|
44
|
-
|
|
55
|
+
unless roots.any? do |root|
|
|
56
|
+
File.expand_path(result_path).start_with?(File.expand_path(root))
|
|
57
|
+
end
|
|
58
|
+
raise ::Liquid::FileSystemError,
|
|
59
|
+
"Illegal template path '#{File.expand_path(result_path)}'"
|
|
45
60
|
end
|
|
46
61
|
|
|
47
62
|
result_path
|
|
@@ -16,164 +16,244 @@ module Metanorma
|
|
|
16
16
|
REMARKS_ATTRIBUTE = "remarks"
|
|
17
17
|
|
|
18
18
|
def process(document, reader)
|
|
19
|
-
r = Asciidoctor::PreprocessorNoIfdefsReader.new
|
|
19
|
+
r = Asciidoctor::PreprocessorNoIfdefsReader.new(document,
|
|
20
|
+
reader.lines)
|
|
20
21
|
input_lines = r.readlines.to_enum
|
|
21
|
-
|
|
22
|
+
|
|
23
|
+
has_lutaml = input_lines.any? { |line| lutaml?(line) }
|
|
22
24
|
express_indexes = Utils.parse_document_express_indexes(
|
|
23
|
-
document,
|
|
25
|
+
document,
|
|
26
|
+
input_lines,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
result_content = process_input_lines(
|
|
30
|
+
document: document,
|
|
31
|
+
input_lines: input_lines,
|
|
32
|
+
express_indexes: express_indexes,
|
|
24
33
|
)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
|
|
35
|
+
log(document, result_content) if has_lutaml
|
|
36
|
+
|
|
28
37
|
Asciidoctor::PreprocessorNoIfdefsReader.new(document, result_content)
|
|
29
38
|
end
|
|
30
39
|
|
|
31
40
|
protected
|
|
32
41
|
|
|
33
|
-
def log(
|
|
34
|
-
File.open("#{
|
|
35
|
-
|
|
36
|
-
f.write(result.join("\n"))
|
|
42
|
+
def log(doc, text)
|
|
43
|
+
File.open("#{doc.attr('docfile')}.lutaml.log.txt", "w:UTF-8") do |f|
|
|
44
|
+
f.write(text.join("\n"))
|
|
37
45
|
end
|
|
38
46
|
end
|
|
39
47
|
|
|
40
48
|
def lutaml?(line)
|
|
41
|
-
line.match(/^\[(?:\blutaml\b|\blutaml_express\b),([^,]+)?,?([^,]+)
|
|
49
|
+
line.match(/^\[(?:\blutaml\b|\blutaml_express\b),(?<index_names>[^,]+)?,?(?<context_name>[^,]+)?(?<options>,.*)?\]/)
|
|
42
50
|
end
|
|
43
51
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
File.new(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
def load_lutaml_file(document, file_path)
|
|
53
|
+
::Lutaml::Parser.parse(
|
|
54
|
+
File.new(
|
|
55
|
+
Utils.relative_file_path(document, file_path),
|
|
56
|
+
encoding: "UTF-8",
|
|
57
|
+
),
|
|
58
|
+
)
|
|
50
59
|
end
|
|
51
60
|
|
|
52
61
|
private
|
|
53
62
|
|
|
54
|
-
def
|
|
63
|
+
def process_input_lines(
|
|
64
|
+
document:,
|
|
65
|
+
input_lines:,
|
|
66
|
+
express_indexes:
|
|
67
|
+
)
|
|
68
|
+
|
|
55
69
|
result = []
|
|
56
70
|
loop do
|
|
57
|
-
result
|
|
58
|
-
|
|
71
|
+
result.push(
|
|
72
|
+
*process_text_blocks(
|
|
59
73
|
document,
|
|
60
74
|
input_lines,
|
|
61
75
|
express_indexes,
|
|
62
|
-
)
|
|
76
|
+
),
|
|
77
|
+
)
|
|
63
78
|
end
|
|
64
79
|
result
|
|
65
80
|
end
|
|
66
81
|
|
|
67
82
|
def process_text_blocks(document, input_lines, express_indexes)
|
|
68
83
|
line = input_lines.next
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
block_header_match = lutaml?(line)
|
|
85
|
+
|
|
86
|
+
return [line] if block_header_match.nil?
|
|
87
|
+
|
|
88
|
+
index_names = block_header_match[:index_names].split(";").map(&:strip)
|
|
89
|
+
context_name = block_header_match[:context_name].strip
|
|
90
|
+
|
|
91
|
+
options = block_header_match[:options] &&
|
|
92
|
+
parse_options(block_header_match[:options].to_s.strip) || {}
|
|
71
93
|
|
|
72
94
|
end_mark = input_lines.next
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
95
|
+
|
|
96
|
+
render_template(
|
|
97
|
+
document: document,
|
|
98
|
+
lines: extract_block_lines(input_lines, end_mark),
|
|
99
|
+
index_names: index_names,
|
|
100
|
+
context_name: context_name,
|
|
101
|
+
options: options,
|
|
102
|
+
indexes: express_indexes,
|
|
103
|
+
)
|
|
79
104
|
end
|
|
80
105
|
|
|
81
|
-
def
|
|
82
|
-
|
|
106
|
+
def extract_block_lines(input_lines, end_mark)
|
|
107
|
+
block = []
|
|
83
108
|
while (block_line = input_lines.next) != end_mark
|
|
84
|
-
|
|
109
|
+
block.push(block_line)
|
|
85
110
|
end
|
|
86
|
-
|
|
111
|
+
block
|
|
87
112
|
end
|
|
88
113
|
|
|
89
|
-
def
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
114
|
+
def gather_context_items(index_names:, document:, indexes:)
|
|
115
|
+
index_names.map do |path|
|
|
116
|
+
# TODO: Rephrase of the below TODO message.
|
|
117
|
+
# ::Lutaml::Parser.parse(file_list) can return an Array or just one.
|
|
118
|
+
# TODO: decide how to handle expressir multiply file parse as one
|
|
119
|
+
# object and lutaml
|
|
120
|
+
|
|
121
|
+
# Does this condition ever happen? That is only if the `lutaml-express-index` condition is not set
|
|
122
|
+
if indexes[path]
|
|
123
|
+
indexes[path][:serialized_hash] ||= indexes[path][:wrapper].to_liquid
|
|
95
124
|
else
|
|
96
|
-
|
|
125
|
+
wrapper = load_lutaml_file(document, path)
|
|
126
|
+
indexes[path] = {
|
|
127
|
+
wrapper: wrapper,
|
|
128
|
+
serialized_hash: wrapper.to_liquid,
|
|
129
|
+
}
|
|
97
130
|
end
|
|
131
|
+
|
|
132
|
+
indexes[path]
|
|
98
133
|
end
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def parse_yaml_config_file(document, file_path)
|
|
137
|
+
return nil if file_path.nil?
|
|
138
|
+
|
|
139
|
+
relative_file_path = Utils.relative_file_path(document, file_path)
|
|
140
|
+
YAML.safe_load(File.read(relative_file_path, encoding: "UTF-8"))
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def decorate_schema_object(schema:, document:, indexes:, index_names:,
|
|
144
|
+
selected:, options:)
|
|
145
|
+
# Mark a schema as "selected" with `.selected`
|
|
146
|
+
schema["selected"] = true if selected
|
|
147
|
+
|
|
148
|
+
# Provide pretty-formatted code under `.formatted`
|
|
149
|
+
_, index_found_value = indexes.detect do |_k, _v|
|
|
150
|
+
_
|
|
111
151
|
end
|
|
112
|
-
|
|
152
|
+
|
|
153
|
+
schema["formatted"] = index_found_value[:wrapper].original_document.schemas.detect do |s|
|
|
154
|
+
s.id == schema["id"]
|
|
155
|
+
end.to_s(no_remarks: true)
|
|
156
|
+
|
|
157
|
+
# Decorate the remaining things
|
|
158
|
+
decorate_context_items(
|
|
159
|
+
schema,
|
|
160
|
+
options.merge(
|
|
161
|
+
"relative_path_prefix" =>
|
|
162
|
+
Utils.relative_file_path(document,
|
|
163
|
+
File.dirname(schema["file"])),
|
|
164
|
+
),
|
|
165
|
+
) || {}
|
|
113
166
|
end
|
|
114
167
|
|
|
115
|
-
def
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
168
|
+
def render_template(document:, lines:, context_name:, index_names:,
|
|
169
|
+
options:, indexes:)
|
|
170
|
+
config_yaml_path = options.delete("config_yaml")
|
|
171
|
+
config_yaml = if config_yaml_path
|
|
172
|
+
parse_yaml_config_file(document, config_yaml_path)
|
|
173
|
+
else
|
|
174
|
+
{}
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
selected_schemas = config_yaml["schemas"]
|
|
178
|
+
|
|
179
|
+
gather_context_items(
|
|
180
|
+
index_names: index_names,
|
|
181
|
+
document: document,
|
|
182
|
+
indexes: indexes,
|
|
183
|
+
).map do |items|
|
|
184
|
+
serialized_hash = items[:serialized_hash]
|
|
185
|
+
|
|
186
|
+
serialized_hash["schemas"]&.map! do |schema|
|
|
187
|
+
decorate_schema_object(
|
|
188
|
+
schema: schema,
|
|
189
|
+
document: document,
|
|
190
|
+
index_names: index_names,
|
|
191
|
+
indexes: indexes,
|
|
192
|
+
selected: selected_schemas && selected_schemas.include?(schema["id"]),
|
|
193
|
+
options: options,
|
|
194
|
+
)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
render_block(
|
|
198
|
+
document: document,
|
|
199
|
+
block_lines: lines,
|
|
200
|
+
context_items: serialized_hash,
|
|
201
|
+
context_name: context_name,
|
|
202
|
+
)
|
|
203
|
+
end.flatten
|
|
131
204
|
rescue StandardError => e
|
|
132
|
-
|
|
205
|
+
raise e
|
|
206
|
+
document.logger.warn("Failed to parse LutaML block: #{e.message}")
|
|
133
207
|
[]
|
|
134
208
|
end
|
|
135
209
|
|
|
136
210
|
def parse_options(options_string)
|
|
137
211
|
options_string
|
|
138
212
|
.to_s
|
|
139
|
-
.scan(
|
|
213
|
+
.scan(/,\s*([^=]+?)=(\s*[^,]+)/)
|
|
140
214
|
.map { |elem| elem.map(&:strip) }
|
|
141
215
|
.to_h
|
|
142
216
|
end
|
|
143
217
|
|
|
144
|
-
def
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
.to_h
|
|
218
|
+
def decorate_context_item(key, val, options)
|
|
219
|
+
if key == REMARKS_ATTRIBUTE
|
|
220
|
+
return [
|
|
221
|
+
key,
|
|
222
|
+
val&.map do |remark|
|
|
223
|
+
Metanorma::Plugin::Lutaml::ExpressRemarksDecorator
|
|
224
|
+
.call(remark, options)
|
|
225
|
+
end,
|
|
226
|
+
]
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
case val
|
|
230
|
+
when Hash
|
|
231
|
+
[key, decorate_context_items(val, options)]
|
|
232
|
+
when Array
|
|
233
|
+
[key, val.map { |n| decorate_context_items(n, options) }]
|
|
234
|
+
else
|
|
235
|
+
[key, val]
|
|
236
|
+
end
|
|
164
237
|
end
|
|
165
238
|
|
|
166
|
-
def
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
239
|
+
def decorate_context_items(item, options)
|
|
240
|
+
return item unless item.is_a?(Hash)
|
|
241
|
+
|
|
242
|
+
item.map do |(key, val)|
|
|
243
|
+
decorate_context_item(key, val, options)
|
|
244
|
+
end.to_h
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def render_block(block_lines:, context_items:, context_name:, document:)
|
|
170
248
|
render_result, errors = Utils.render_liquid_string(
|
|
171
|
-
template_string:
|
|
249
|
+
template_string: block_lines.join("\n"),
|
|
172
250
|
context_items: context_items,
|
|
173
251
|
context_name: context_name,
|
|
174
252
|
document: document,
|
|
175
253
|
)
|
|
254
|
+
|
|
176
255
|
Utils.notify_render_errors(document, errors)
|
|
256
|
+
|
|
177
257
|
render_result.split("\n")
|
|
178
258
|
end
|
|
179
259
|
end
|
|
@@ -9,7 +9,7 @@ module Metanorma
|
|
|
9
9
|
# @example [lutaml_uml_attributes_table,path/to/lutaml,EntityName]
|
|
10
10
|
class LutamlUmlAttributesTablePreprocessor < LutamlUmlClassPreprocessor
|
|
11
11
|
MACRO_REGEXP =
|
|
12
|
-
/\[lutaml_uml_attributes_table,([^,]+),?([^,]+),?(.+?)?\]
|
|
12
|
+
/\[lutaml_uml_attributes_table,([^,]+),?([^,]+),?(.+?)?\]/.freeze
|
|
13
13
|
|
|
14
14
|
# rubocop:disable Layout/IndentHeredoc
|
|
15
15
|
def template(options)
|
|
@@ -15,7 +15,7 @@ module Metanorma
|
|
|
15
15
|
# @example [lutaml_uml_class,path/to/lutaml,EntityName]
|
|
16
16
|
class LutamlUmlClassPreprocessor < ::Asciidoctor::Extensions::Preprocessor
|
|
17
17
|
MACRO_REGEXP =
|
|
18
|
-
/\[lutaml_uml_class,([^,]+),?([^,]+),?(.+?)?\]
|
|
18
|
+
/\[lutaml_uml_class,([^,]+),?([^,]+),?(.+?)?\]/.freeze
|
|
19
19
|
|
|
20
20
|
def get_macro_regexp
|
|
21
21
|
self.class.const_get(:MACRO_REGEXP)
|
|
@@ -109,9 +109,9 @@ module Metanorma
|
|
|
109
109
|
|
|
110
110
|
<<~TEMPLATE
|
|
111
111
|
{% if definition.keyword == 'enumeration' %}
|
|
112
|
-
#{equalsigns(depth)
|
|
112
|
+
#{"#{equalsigns(depth)} Enumeration: {{ definition.name }}" unless skip_headers}
|
|
113
113
|
{% else %}
|
|
114
|
-
#{equalsigns(depth)
|
|
114
|
+
#{"#{equalsigns(depth)} Class: {{ definition.name }}" unless skip_headers}
|
|
115
115
|
{% endif %}
|
|
116
116
|
|
|
117
117
|
#{equalsigns(depth + 1)} Description
|
|
@@ -16,7 +16,7 @@ module Metanorma
|
|
|
16
16
|
class LutamlUmlDatamodelDescriptionPreprocessor <
|
|
17
17
|
::Asciidoctor::Extensions::Preprocessor
|
|
18
18
|
MACRO_REGEXP =
|
|
19
|
-
/\[lutaml_uml_datamodel_description,([^,]+),?(.+)?\]
|
|
19
|
+
/\[lutaml_uml_datamodel_description,([^,]+),?(.+)?\]/.freeze
|
|
20
20
|
LIQUID_INCLUDE_PATH = File.join(
|
|
21
21
|
Gem.loaded_specs["metanorma-plugin-lutaml"].full_gem_path,
|
|
22
22
|
"lib", "metanorma", "plugin", "lutaml", "liquid_templates"
|
|
@@ -92,7 +92,7 @@ module Metanorma
|
|
|
92
92
|
def fill_in_entities_refs_attributes(document, lutaml_document_wrapper,
|
|
93
93
|
options)
|
|
94
94
|
lutaml_document = lutaml_document_wrapper.original_document
|
|
95
|
-
|
|
95
|
+
options.fetch(RENDER_STYLE_ATTRIBUTE, "default")
|
|
96
96
|
all_children_packages = lutaml_document.packages
|
|
97
97
|
.map(&:children_packages).flatten
|
|
98
98
|
package_flat_packages = lambda do |pks|
|
|
@@ -201,7 +201,8 @@ options)
|
|
|
201
201
|
end
|
|
202
202
|
|
|
203
203
|
def package_entities(options)
|
|
204
|
-
options["packages"]
|
|
204
|
+
return {} unless options["packages"]
|
|
205
|
+
|
|
205
206
|
options["packages"]
|
|
206
207
|
.find_all { |entity| entity.is_a?(Hash) && entity.values.first["render_entities"] }
|
|
207
208
|
.map do |entity|
|
|
@@ -27,16 +27,22 @@ module Metanorma
|
|
|
27
27
|
def render_liquid_string(template_string:, context_items:,
|
|
28
28
|
context_name:, document:, include_path: nil)
|
|
29
29
|
liquid_template = ::Liquid::Template.parse(template_string)
|
|
30
|
+
|
|
30
31
|
# Allow includes for the template
|
|
31
|
-
include_paths = [
|
|
32
|
-
|
|
32
|
+
include_paths = [
|
|
33
|
+
Utils.relative_file_path(document, ""),
|
|
34
|
+
include_path,
|
|
35
|
+
].compact
|
|
36
|
+
|
|
33
37
|
liquid_template.registers[:file_system] =
|
|
34
38
|
::Metanorma::Plugin::Lutaml::Liquid::LocalFileSystem
|
|
35
39
|
.new(include_paths, ["_%s.liquid", "_%s.adoc"])
|
|
40
|
+
|
|
36
41
|
rendered_string = liquid_template
|
|
37
42
|
.render(context_name => context_items,
|
|
38
43
|
strict_variables: true,
|
|
39
44
|
error_mode: :warn)
|
|
45
|
+
|
|
40
46
|
[rendered_string, liquid_template.errors]
|
|
41
47
|
end
|
|
42
48
|
|
|
@@ -48,37 +54,50 @@ module Metanorma
|
|
|
48
54
|
end
|
|
49
55
|
end
|
|
50
56
|
|
|
51
|
-
def
|
|
52
|
-
force_read
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
def load_express_repositories(path:, cache_path:, document:,
|
|
58
|
+
force_read: false)
|
|
59
|
+
cache_full_path = cache_path &&
|
|
60
|
+
Utils.relative_file_path(document, cache_path)
|
|
61
|
+
|
|
62
|
+
# If there is cache and "force read" not set.
|
|
57
63
|
if !force_read && cache_full_path && File.file?(cache_full_path)
|
|
58
|
-
return
|
|
64
|
+
return load_express_repo_from_cache(cache_full_path)
|
|
59
65
|
end
|
|
60
66
|
|
|
67
|
+
# If there is no cache or "force read" is set.
|
|
61
68
|
full_path = Utils.relative_file_path(document, path)
|
|
62
|
-
|
|
69
|
+
lutaml_wrapper = load_express_repo_from_path(document, full_path)
|
|
70
|
+
|
|
63
71
|
if cache_full_path && !File.file?(cache_full_path)
|
|
64
|
-
|
|
65
|
-
|
|
72
|
+
save_express_repo_to_cache(
|
|
73
|
+
cache_full_path,
|
|
74
|
+
lutaml_wrapper.original_document,
|
|
75
|
+
document,
|
|
76
|
+
)
|
|
66
77
|
end
|
|
67
|
-
|
|
78
|
+
|
|
79
|
+
lutaml_wrapper
|
|
68
80
|
rescue Expressir::Error
|
|
69
81
|
FileUtils.rm_rf(cache_full_path)
|
|
70
|
-
|
|
82
|
+
|
|
83
|
+
load_express_repositories(
|
|
84
|
+
path: path,
|
|
85
|
+
cache_path: cache_path,
|
|
86
|
+
document: document,
|
|
87
|
+
force_read: true,
|
|
88
|
+
)
|
|
71
89
|
rescue StandardError => e
|
|
72
90
|
document.logger.warn("Failed to load #{full_path}: #{e.message}")
|
|
73
|
-
|
|
91
|
+
raise e
|
|
92
|
+
# nil
|
|
74
93
|
end
|
|
75
94
|
|
|
76
|
-
def
|
|
95
|
+
def load_express_repo_from_cache(path)
|
|
77
96
|
::Lutaml::Parser
|
|
78
97
|
.parse(File.new(path), ::Lutaml::Parser::EXPRESS_CACHE_PARSE_TYPE)
|
|
79
98
|
end
|
|
80
99
|
|
|
81
|
-
def
|
|
100
|
+
def save_express_repo_to_cache(path, repository, document)
|
|
82
101
|
root_path = Pathname.new(relative_file_path(document, ""))
|
|
83
102
|
Expressir::Express::Cache
|
|
84
103
|
.to_file(path,
|
|
@@ -86,43 +105,28 @@ force_read = false)
|
|
|
86
105
|
root_path: root_path)
|
|
87
106
|
end
|
|
88
107
|
|
|
89
|
-
def
|
|
90
|
-
if File.directory?(path)
|
|
91
|
-
return express_from_folder(path)
|
|
92
|
-
end
|
|
108
|
+
def load_express_repo_from_path(document, path)
|
|
109
|
+
return load_express_from_folder(path) if File.directory?(path)
|
|
93
110
|
|
|
94
|
-
|
|
111
|
+
load_express_from_index(document, path)
|
|
95
112
|
end
|
|
96
113
|
|
|
97
|
-
def
|
|
114
|
+
def load_express_from_folder(folder)
|
|
98
115
|
files = Dir["#{folder}/*.exp"].map do |nested_path|
|
|
99
116
|
File.new(nested_path, encoding: "UTF-8")
|
|
100
117
|
end
|
|
101
118
|
::Lutaml::Parser.parse(files)
|
|
102
119
|
end
|
|
103
120
|
|
|
104
|
-
def
|
|
105
|
-
serialized = wrapper.to_liquid
|
|
106
|
-
serialized["schemas"].map! do |j|
|
|
107
|
-
j.merge(
|
|
108
|
-
"relative_path_prefix" => Utils
|
|
109
|
-
.relative_file_path(document, File.dirname(j["file"])),
|
|
110
|
-
"formatted" => wrapper.original_document
|
|
111
|
-
.schemas.detect {|s| s.id == j["id"] }.to_s(no_remarks: true)
|
|
112
|
-
)
|
|
113
|
-
end
|
|
114
|
-
serialized
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def express_from_index(document, path)
|
|
121
|
+
def load_express_from_index(document, path)
|
|
118
122
|
yaml_content = YAML.safe_load(File.read(path))
|
|
119
123
|
root_path = yaml_content["path"]
|
|
120
|
-
schemas_paths = yaml_content
|
|
121
|
-
.fetch("schemas")
|
|
124
|
+
schemas_paths = yaml_content["schemas"]
|
|
122
125
|
.map do |(schema_name, schema_values)|
|
|
123
126
|
schema_values["path"] || File.join(root_path.to_s,
|
|
124
127
|
"#{schema_name}.exp")
|
|
125
128
|
end
|
|
129
|
+
|
|
126
130
|
files_to_load = schemas_paths.map do |path|
|
|
127
131
|
File.new(Utils.relative_file_path(document, path),
|
|
128
132
|
encoding: "UTF-8")
|
|
@@ -134,20 +138,35 @@ force_read = false)
|
|
|
134
138
|
express_indexes = {}
|
|
135
139
|
loop do
|
|
136
140
|
line = input_lines.next
|
|
141
|
+
|
|
142
|
+
# Finished parsing document attributes
|
|
137
143
|
break if line.empty?
|
|
138
144
|
|
|
139
145
|
match = line.match(LUTAML_EXP_IDX_TAG)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
next unless match
|
|
147
|
+
|
|
148
|
+
name = match[:index_name]&.strip
|
|
149
|
+
path = match[:index_path]&.strip
|
|
150
|
+
cache = match[:cache_path]&.strip
|
|
151
|
+
|
|
152
|
+
unless name && path
|
|
153
|
+
raise StandardError.new("No name and path set in `:lutaml-express-index:` attribute.")
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
lutaml_expressir_wrapper = load_express_repositories(
|
|
157
|
+
path: path,
|
|
158
|
+
cache_path: cache,
|
|
159
|
+
document: document,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
if lutaml_expressir_wrapper
|
|
163
|
+
express_indexes[name] = {
|
|
164
|
+
wrapper: lutaml_expressir_wrapper,
|
|
165
|
+
serialized_hash: nil,
|
|
166
|
+
}
|
|
149
167
|
end
|
|
150
168
|
end
|
|
169
|
+
|
|
151
170
|
express_indexes
|
|
152
171
|
rescue StopIteration
|
|
153
172
|
express_indexes
|
|
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
|
|
|
30
30
|
spec.add_dependency "liquid"
|
|
31
31
|
spec.add_dependency "lutaml"
|
|
32
32
|
spec.add_dependency "relaton-cli"
|
|
33
|
-
spec.add_dependency "reverse_adoc"
|
|
33
|
+
spec.add_dependency "reverse_adoc", "~> 0.3.7"
|
|
34
34
|
|
|
35
35
|
spec.add_development_dependency "debug"
|
|
36
36
|
spec.add_development_dependency "equivalent-xml"
|
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.6.
|
|
4
|
+
version: 0.6.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-
|
|
11
|
+
date: 2024-05-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: asciidoctor
|
|
@@ -84,16 +84,16 @@ dependencies:
|
|
|
84
84
|
name: reverse_adoc
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
|
-
- - "
|
|
87
|
+
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version:
|
|
89
|
+
version: 0.3.7
|
|
90
90
|
type: :runtime
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
|
-
- - "
|
|
94
|
+
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version:
|
|
96
|
+
version: 0.3.7
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
98
|
name: debug
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|