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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e9b3ce23d274ff457c34d3c5a9e2bf73d12d8cd4de898a061f6a3522bb45439
4
- data.tar.gz: 79a063b985b79fa7b835bbc73acd0ada7761c496f058bcfc8d455882cb6d95ea
3
+ metadata.gz: 56a196838fa30ab8585b1834d115bf6ff99b4b81d33176975b75dc7f5c5cd5bd
4
+ data.tar.gz: 458ce39ccac1e11b1dee74289e9e85a06a4ec5fa2faceaa78869ca18cc8dae77
5
5
  SHA512:
6
- metadata.gz: 20896ef23b4b4a2258e3803a9d07bca26778f495aa57dfdd5bcd878ac6db1c09d139a066b7e6dde086e25b1c4a77b74266ae7f51f251613c783a4be7d38771da
7
- data.tar.gz: b10b0ce496d8ac08e4cd83d85065c94292f4846dcaf27544fdc122fba228c9303395076d42e2fd5eecc12090f16faeb564b0300c7bc40ea37f3648dae433ec25
6
+ metadata.gz: 780fa1199a23d199cb8f04d1a1b9b79d416f8aed0a2b442f02baccd370830d76d80fee12c2061e9424c9dd294059f5709b50a0eac7ac9b24fd4b492f54caa839
7
+ data.tar.gz: 1582258a02474a3ee351b935afc686a78ed8c82f1cc72efefde7c003110bfaa8fd4189d979b2070e61509d5d4997208b7644daf529c6e221c9e187e4e3def057
data/Gemfile CHANGED
@@ -6,4 +6,8 @@ git_source(:github) { |repo| "https://github.com/#{repo}" }
6
6
 
7
7
  gemspec
8
8
 
9
- eval_gemfile("Gemfile.devel") rescue nil
9
+ begin
10
+ eval_gemfile("Gemfile.devel")
11
+ rescue StandardError
12
+ nil
13
+ end
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` macro
31
+ === Usage of the `lutaml` command
32
32
 
33
- Given an `example.exp` EXPRESS file with the content:
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` macro block:
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
@@ -15,7 +15,7 @@ module Metanorma
15
15
  end
16
16
 
17
17
  def identify(input)
18
- input.split(/(?=[A-Z])/).map(&:downcase).join('-')
18
+ input.split(/(?=[A-Z])/).map(&:downcase).join("-")
19
19
  end
20
20
  end
21
21
  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
- raise FileSystemError, "No such template '#{template_path}'" unless File.exist?(full_path)
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
- raise ::Liquid::FileSystemError, "Illegal template name '#{template_path}'" unless %r{\A[^./][a-zA-Z0-9_/]+\z}.match?(template_path)
22
-
23
- result_path = if template_path.include?('/')
24
- roots
25
- .map do |root|
26
- patterns.map do |pattern|
27
- File.join(root, File.dirname(template_path), pattern % File.basename(template_path))
28
- end
29
- end
30
- .flatten
31
- .find { |path| File.file?(path) }
32
- else
33
- roots
34
- .map do |root|
35
- patterns.map do |pattern|
36
- File.join(root, pattern % template_path)
37
- end
38
- end
39
- .flatten
40
- .find { |path| File.file?(path) }
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? { |root| File.expand_path(result_path).start_with?(File.expand_path(root)) }
44
- raise ::Liquid::FileSystemError, "Illegal template path '#{File.expand_path(result_path)}'"
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 document, reader.lines
19
+ r = Asciidoctor::PreprocessorNoIfdefsReader.new(document,
20
+ reader.lines)
20
21
  input_lines = r.readlines.to_enum
21
- has_lutaml = !input_lines.select { |x| lutaml?(x) }.empty?
22
+
23
+ has_lutaml = input_lines.any? { |line| lutaml?(line) }
22
24
  express_indexes = Utils.parse_document_express_indexes(
23
- document, input_lines
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
- result_content = processed_lines(document, input_lines,
26
- express_indexes)
27
- has_lutaml and log(document, result_content)
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(document, result)
34
- File.open("#{document.attr('docfile')}.lutaml.log.txt",
35
- "w:UTF-8") do |f|
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 content_from_files(document, file_paths)
45
- file_list = file_paths.map do |file_path|
46
- File.new(Utils.relative_file_path(document, file_path),
47
- encoding: "UTF-8")
48
- end
49
- ::Lutaml::Parser.parse(file_list)
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 processed_lines(document, input_lines, express_indexes)
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
- .push(*process_text_blocks(
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
- block_match = lutaml?(line)
70
- return [line] if block_match.nil?
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
- parse_template(document,
74
- collect_internal_block_lines(document,
75
- input_lines,
76
- end_mark),
77
- block_match,
78
- express_indexes)
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 collect_internal_block_lines(_document, input_lines, end_mark)
82
- current_block = []
106
+ def extract_block_lines(input_lines, end_mark)
107
+ block = []
83
108
  while (block_line = input_lines.next) != end_mark
84
- current_block.push(block_line)
109
+ block.push(block_line)
85
110
  end
86
- current_block
111
+ block
87
112
  end
88
113
 
89
- def contexts_items(block_match, document, express_indexes)
90
- contexts_names = block_match[1].split(";").map(&:strip)
91
- file_paths = []
92
- result = contexts_names.each_with_object([]) do |path, res|
93
- if express_indexes[path]
94
- res.push(express_indexes[path])
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
- file_paths.push(path)
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
- if !file_paths.empty?
100
- from_files = content_from_files(document, file_paths)
101
- # TODO: decide how to handle expressir multiply file parse as one object and lutaml
102
- if from_files.is_a?(Array)
103
- result.push(*from_files.map(&:to_liquid))
104
- else
105
- from_files = from_files.to_liquid
106
- from_files["schemas"] = from_files["schemas"].map do |n|
107
- n.merge("relative_path_prefix" => Utils.relative_file_path(document, File.dirname(n["file"])))
108
- end
109
- result.push(from_files)
110
- end
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
- result
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 parse_template(document, current_block, block_match,
116
- express_indexes)
117
- options = parse_options(block_match[3])
118
- contexts_items(block_match, document, express_indexes)
119
- .map do |items|
120
- if items["schemas"]
121
- items["schemas"] = items["schemas"].map do |j|
122
- opts = options.merge("relative_path_prefix" => j["relative_path_prefix"])
123
- decorate_context_items(j, opts)
124
- end
125
- end
126
- parse_context_block(document: document,
127
- context_lines: current_block,
128
- context_items: items,
129
- context_name: block_match[2].strip)
130
- end.flatten
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
- document.logger.warn("Failed to parse lutaml block: #{e.message}")
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(/(.+?)=(\s?[^\s]+)/)
213
+ .scan(/,\s*([^=]+?)=(\s*[^,]+)/)
140
214
  .map { |elem| elem.map(&:strip) }
141
215
  .to_h
142
216
  end
143
217
 
144
- def decorate_context_items(context_items, options)
145
- return context_items if !context_items.is_a?(Hash)
146
-
147
- context_items
148
- .map do |(key, val)|
149
- if val.is_a?(Hash)
150
- [key, decorate_context_items(val, options)]
151
- elsif key == REMARKS_ATTRIBUTE
152
- [key,
153
- val&.map do |remark|
154
- Metanorma::Plugin::Lutaml::ExpressRemarksDecorator
155
- .call(remark, options)
156
- end]
157
- elsif val.is_a?(Array)
158
- [key, val.map { |n| decorate_context_items(n, options) }]
159
- else
160
- [key, val]
161
- end
162
- end
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 parse_context_block(context_lines:,
167
- context_items:,
168
- context_name:,
169
- document:)
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: context_lines.join("\n"),
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) + ' Enumeration: {{ definition.name }}' unless skip_headers}
112
+ #{"#{equalsigns(depth)} Enumeration: {{ definition.name }}" unless skip_headers}
113
113
  {% else %}
114
- #{equalsigns(depth) + ' Class: {{ definition.name }}' unless skip_headers}
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
- render_style = options.fetch(RENDER_STYLE_ATTRIBUTE, "default")
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"] or return {}
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 = [Utils.relative_file_path(document, ""),
32
- include_path].compact
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 process_express_index(path, cache_path, document,
52
- force_read = false)
53
- if cache_path
54
- cache_full_path = Utils.relative_file_path(document,
55
- cache_path)
56
- end
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 express_from_cache(cache_full_path)
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
- wrapper = express_from_path(document, full_path)
69
+ lutaml_wrapper = load_express_repo_from_path(document, full_path)
70
+
63
71
  if cache_full_path && !File.file?(cache_full_path)
64
- express_write_cache(cache_full_path, wrapper.original_document,
65
- document)
72
+ save_express_repo_to_cache(
73
+ cache_full_path,
74
+ lutaml_wrapper.original_document,
75
+ document,
76
+ )
66
77
  end
67
- wrapper
78
+
79
+ lutaml_wrapper
68
80
  rescue Expressir::Error
69
81
  FileUtils.rm_rf(cache_full_path)
70
- process_express_index(path, cache_path, document, true)
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
- nil
91
+ raise e
92
+ # nil
74
93
  end
75
94
 
76
- def express_from_cache(path)
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 express_write_cache(path, repository, document)
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 express_from_path(document, path)
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
- express_from_index(document, path)
111
+ load_express_from_index(document, path)
95
112
  end
96
113
 
97
- def express_from_folder(folder)
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 express_decorate_wrapper(wrapper, document)
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
- if match
141
- name = match[:index_name]
142
- path = match[:index_path]
143
- cache = match[:cache_path]
144
- repositories = process_express_index(path.strip, cache, document)
145
- if repositories
146
- express_indexes[name.strip] =
147
- express_decorate_wrapper(repositories, document)
148
- end
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
@@ -1,7 +1,7 @@
1
1
  module Metanorma
2
2
  module Plugin
3
3
  module Lutaml
4
- VERSION = "0.6.0".freeze
4
+ VERSION = "0.6.2".freeze
5
5
  end
6
6
  end
7
7
  end
@@ -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.0
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-04-23 00:00:00.000000000 Z
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: '0'
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: '0'
96
+ version: 0.3.7
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: debug
99
99
  requirement: !ruby/object:Gem::Requirement