metanorma-plugin-lutaml 0.1.0 → 0.2.4.alpha

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e854f55d18dbd63e113f74e940689320384a8840912ef16f7a6880e13672ee6
4
- data.tar.gz: ebf477f3262b209fc4edad4b1908b911d7737d343c2eb42383207de0aeb30b2d
3
+ metadata.gz: c060a247f01300f4fe46b58671a07a8f0e3a80f53e64974ccd07208e181e0eaa
4
+ data.tar.gz: dcf58ee6f298d24ad2493bd65c62a549a2673717ce8a9404695caad20d32e069
5
5
  SHA512:
6
- metadata.gz: e530b0648b11116825ac6f1435f5c8d533102bbd212b6e4ab4d4c81d3378d67cb2c39ce32dffe5585d8801b34e2b8a647809fd2eafbdd879e27a01b975f3888e
7
- data.tar.gz: 5a216d14209e1183b19c1301c7273639f379ab1d7e025a7ded83f135a46a5834568bb154335d8bd7cfc33c967825ae5d7b38c96289d0047c8c74cee3b9b2f0ca
6
+ metadata.gz: 5061cc833de5a8d4742095e5491f66ab608bdac3042ecc601cdc26e89f5ff258aa34650b3b19e3eb3b38b50be01b3f866e18f15adda02000278e6a5864cf1b34
7
+ data.tar.gz: 3be917c68c0fd6b0157f6578e40f61da433b262629950f76d09b2b2cf9e4cc5f7955d9066a0930f337ec7beb9426790d650bfb632cf9abf570f3431360855ca6
@@ -0,0 +1,65 @@
1
+ name: rake
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ tags: [ v* ]
7
+ pull_request:
8
+
9
+ jobs:
10
+ rake:
11
+ name: Test on Ruby ${{ matrix.ruby }} ${{ matrix.os }}
12
+ runs-on: ${{ matrix.os }}
13
+ continue-on-error: ${{ matrix.experimental }}
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ ruby: [ '2.6', '2.5', '2.4' ]
18
+ os: [ ubuntu-latest, windows-latest, macos-latest ]
19
+ experimental: [ false ]
20
+ include:
21
+ - ruby: '2.7'
22
+ os: 'ubuntu-latest'
23
+ experimental: true
24
+ - ruby: '2.7'
25
+ os: 'windows-latest'
26
+ experimental: true
27
+ - ruby: '2.7'
28
+ os: 'macos-latest'
29
+ experimental: true
30
+ steps:
31
+ - uses: actions/checkout@master
32
+
33
+ - name: Use Ruby
34
+ uses: ruby/setup-ruby@v1
35
+ with:
36
+ ruby-version: ${{ matrix.ruby }}
37
+ bundler-cache: true
38
+
39
+ - name: Update gems
40
+ run: bundle install --jobs 4 --retry 3
41
+
42
+ - name: Install Grpahviz Ubuntu
43
+ if: matrix.os == 'ubuntu-latest'
44
+ run: sudo apt-get install graphviz
45
+
46
+ - name: Install Grpahviz macOS
47
+ if: matrix.os == 'macos-latest'
48
+ run: brew install graphviz
49
+
50
+ - name: Install Grpahviz Windows
51
+ if: matrix.os == 'windows-latest'
52
+ uses: nick-invision/retry@v1
53
+ with:
54
+ polling_interval_seconds: 5
55
+ timeout_minutes: 5
56
+ max_attempts: 3
57
+ command: choco install --no-progress graphviz
58
+
59
+ - name: Check dot command
60
+ if: matrix.os == 'windows-latest'
61
+ run: |
62
+ dot -?
63
+
64
+ - name: Run specs
65
+ run: bundle exec rake
data/.gitignore CHANGED
@@ -1,2 +1,4 @@
1
1
  Gemfile.lock
2
2
  .rspec_status
3
+ spec/assets/lutaml
4
+ test.err
data/README.adoc CHANGED
@@ -1,5 +1,7 @@
1
1
  = metanorma-plugin-lutaml
2
2
 
3
+ image:https://github.com/metanorma/metanorma-plugin-lutaml/workflows/rake/badge.svg["Build Status", link="https://github.com/metanorma/metanorma-plugin-lutaml/actions?workflow=rake"]
4
+
3
5
  == Functionality
4
6
 
5
7
  Metanorma plugin that allows you to access lutaml objects from a Metanorma document
@@ -11,7 +13,7 @@ Metanorma plugin that allows you to access lutaml objects from a Metanorma docum
11
13
  $ gem install metanorma-plugin-lutaml
12
14
  ----
13
15
 
14
- === Usage
16
+ === Usage, `lutaml` macro
15
17
 
16
18
  Given `example.exp` file with the content:
17
19
 
@@ -58,6 +60,14 @@ And the `lutaml` macro block:
58
60
  ----
59
61
  -----
60
62
 
63
+ Where:
64
+
65
+ * content within the block is called the "`template`";
66
+
67
+ * `{example.exp}` is the location of the exp schema file that contains data to be loaded. Location of the file is computed relative to the source directory that `[lutaml]` is used (e.g., if `[lutaml,example.exp,my_context]` is invoked in an `.adoc` file located at `/foo/bar/doc.adoc`, the data file is expected to be found at `/foo/bar/example.exp`);
68
+
69
+ * `{my_context}` is the name where the EXPRESS Repository read from the .exp file can be accessed with. Context object is a serialized Expressir::Model::Repository object with all variable names available. See https://github.com/lutaml/expressir[Expressir] docs for reference. `{my_context}` has `schemas` method to access Expressir https://github.com/lutaml/expressir/blob/master/lib/expressir/model/schema.rb[schemas]
70
+
61
71
  Will produce this output:
62
72
 
63
73
  [source,adoc]
@@ -71,6 +81,82 @@ Will produce this output:
71
81
  === my_type5
72
82
  -----
73
83
 
84
+ This macro also supports `.lutaml` files.
85
+
86
+ === Usage, `lutaml_uml_attributes_table` macro
87
+
88
+ This macro allows to quickly render datamodel attributes/values tables. Given `example.lutaml` file with the content:
89
+
90
+ [source,java]
91
+ ----
92
+ diagram MyView {
93
+ title "my diagram"
94
+
95
+ enum AddressClassProfile {
96
+ imlicistAttributeProfile: CharacterString [0..1] {
97
+ definition
98
+ this is multiline with `ascidoc`
99
+ end definition
100
+ }
101
+ }
102
+
103
+ class AttributeProfile {
104
+ +addressClassProfile: CharacterString [0..1]
105
+ imlicistAttributeProfile: CharacterString [0..1] {
106
+ definition this is attribute definition
107
+ }
108
+ }
109
+ }
110
+ ----
111
+
112
+ And the `lutaml_uml_attributes_table` macro:
113
+
114
+ [source,adoc]
115
+ -----
116
+ [lutaml_uml_attributes_table, example.lutaml, AttributeProfile]
117
+ -----
118
+
119
+ Will produce this output:
120
+
121
+ [source,adoc]
122
+ -----
123
+ === AttributeProfile
124
+
125
+
126
+ .AttributeProfile attributes
127
+ |===
128
+ |Name |Definition |Mandatory/ Optional/ Conditional |Max Occur |Data Type
129
+
130
+ |addressClassProfile |TODO: enum 's definition |M |1 | `CharacterString`
131
+
132
+ |imlicistAttributeProfile |this is attribute definition with multiply lines |M |1 | `CharacterString`
133
+
134
+ |===
135
+ -----
136
+
137
+ In case of "enumeration"(AddressClassProfile) entity:
138
+
139
+ [source,adoc]
140
+ -----
141
+ [lutaml_uml_attributes_table, example.lutaml, AddressClassProfile]
142
+ -----
143
+
144
+ Will produce this output:
145
+
146
+ [source,adoc]
147
+ -----
148
+ === AddressClassProfile
149
+
150
+
151
+ .AddressClassProfile values
152
+ |===
153
+ |Name |Definition
154
+
155
+ |imlicistAttributeProfile |this is multiline with `ascidoc`
156
+
157
+ |===
158
+ -----
159
+
74
160
  == Documentation
75
161
 
76
162
  See https://www.metanorma.com.
@@ -1,5 +1,7 @@
1
1
  require "metanorma/plugin/lutaml/version"
2
2
  require "metanorma/plugin/lutaml/lutaml_preprocessor"
3
+ require "metanorma/plugin/lutaml/lutaml_uml_attributes_table_preprocessor"
4
+ require "metanorma/plugin/lutaml/lutaml_diagram_block"
3
5
 
4
6
  module Metanorma
5
7
  module Plugin
@@ -0,0 +1,73 @@
1
+ module Metanorma
2
+ module Plugin
3
+ module Lutaml
4
+ class ExpressRemarksDecorator
5
+ RELATIVE_PREFIX_MACRO_REGEXP = /^(\* <<express.+?>>;|link|image|video|audio|include)(:+)?(?![^\/:]+:\/\/|[A-Z]:\/|\/)([^:\[]+)(\[.*\])?$/.freeze
6
+
7
+ attr_reader :remark, :options
8
+
9
+ def self.call(remark, options)
10
+ new(remark, options).call
11
+ end
12
+
13
+ def initialize(remark, options)
14
+ @remark = remark
15
+ @options = options
16
+ end
17
+
18
+ def call
19
+ result = remark
20
+ if options["leveloffset"]
21
+ result = process_remark_offsets(result, options["leveloffset"].to_i)
22
+ end
23
+ if options["relative_path_prefix"]
24
+ result = update_relative_paths(result,
25
+ options["relative_path_prefix"])
26
+ end
27
+ result
28
+ end
29
+
30
+ private
31
+
32
+ def update_relative_paths(string, path_prefix)
33
+ string
34
+ .split("\n")
35
+ .map do |line|
36
+ if line.match?(RELATIVE_PREFIX_MACRO_REGEXP)
37
+ prefix_relative_paths(line, path_prefix)
38
+ else
39
+ line
40
+ end
41
+ end
42
+ .join("\n")
43
+ end
44
+
45
+ def prefix_relative_paths(line, path_prefix)
46
+ line.gsub(RELATIVE_PREFIX_MACRO_REGEXP) do |_match|
47
+ prefixed_path = File.join(path_prefix, $3.strip)
48
+ "#{$1}#{$2}#{prefixed_path}#{$4}"
49
+ end
50
+ end
51
+
52
+ def process_remark_offsets(string, offset)
53
+ string
54
+ .split("\n")
55
+ .map do |line|
56
+ if line.match?(/^=/)
57
+ set_string_offsets(line, offset)
58
+ else
59
+ line
60
+ end
61
+ end
62
+ .join("\n")
63
+ end
64
+
65
+ def set_string_offsets(string, offset)
66
+ return "#{'=' * offset}#{string}" if offset.positive?
67
+
68
+ string.gsub(/^={#{offset * -1}}/, "")
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,87 @@
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
+ class LutamlDiagramBlock < Asciidoctor::Extensions::BlockProcessor
14
+ use_dsl
15
+ named :lutaml_diagram
16
+ on_context :literal
17
+ parse_content_as :raw
18
+
19
+ def abort(parent, reader, attrs, msg)
20
+ warn(msg)
21
+ attrs["language"] = "lutaml"
22
+ create_listing_block(
23
+ parent,
24
+ reader.source,
25
+ attrs.reject { |k, _v| k == 1 }
26
+ )
27
+ end
28
+
29
+ def process(parent, reader, attrs)
30
+ uml_document = ::Lutaml::Uml::Parsers::Dsl.parse(lutaml_temp(reader))
31
+ filename = generate_file(parent, reader, uml_document)
32
+ through_attrs = generate_attrs(attrs)
33
+ through_attrs["target"] = filename
34
+ through_attrs["title"] = uml_document.caption
35
+ create_image_block(parent, through_attrs)
36
+ rescue StandardError => e
37
+ abort(parent, reader, attrs, e.message)
38
+ end
39
+
40
+ private
41
+
42
+ def lutaml_temp(reader)
43
+ temp_file = Tempfile.new(["lutaml", ".lutaml"])
44
+ temp_file.puts(reader.read)
45
+ temp_file.rewind
46
+ temp_file
47
+ end
48
+
49
+ # if no :imagesdir: leave image file in lutaml
50
+ def generate_file(parent, _reader, uml_document)
51
+ formatter = ::Lutaml::Uml::Formatter::Graphviz.new
52
+ formatter.type = :png
53
+
54
+ imagesdir = if parent.document.attr("imagesdir")
55
+ File.join(parent.document.attr("imagesdir"), "lutaml")
56
+ else
57
+ "lutaml"
58
+ end
59
+ result_path = Utils.relative_file_path(parent.document, imagesdir)
60
+ result_pathname = Pathname.new(result_path)
61
+ result_pathname.mkpath
62
+ File.writable?(result_pathname) || raise("Destination path #{result_path} not writable for Lutaml!")
63
+
64
+ outfile = Tempfile.new(["lutaml", ".png"])
65
+ outfile.binmode
66
+ outfile.puts(formatter.format(uml_document))
67
+
68
+ # Warning: metanorma/metanorma-standoc#187
69
+ # Windows Ruby 2.4 will crash if a Tempfile is "mv"ed.
70
+ # This is why we need to copy and then unlink.
71
+ filename = File.basename(outfile.path)
72
+ FileUtils.cp(outfile, result_pathname) && outfile.unlink
73
+
74
+ File.join(result_pathname, filename)
75
+ end
76
+
77
+ def generate_attrs(attrs)
78
+ %w(id align float title role width height alt)
79
+ .reduce({}) do |memo, key|
80
+ memo[key] = attrs[key] if attrs.has_key? key
81
+ memo
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -4,48 +4,53 @@ require "liquid"
4
4
  require "asciidoctor"
5
5
  require "asciidoctor/reader"
6
6
  require "lutaml"
7
+ require "metanorma/plugin/lutaml/utils"
8
+ require "metanorma/plugin/lutaml/utils"
9
+ require "metanorma/plugin/lutaml/express_remarks_decorator"
7
10
 
8
11
  module Metanorma
9
12
  module Plugin
10
13
  module Lutaml
11
14
  # Class for processing Lutaml files
12
15
  class LutamlPreprocessor < Asciidoctor::Extensions::Preprocessor
16
+ REMARKS_ATTRIBUTE = "remarks".freeze
13
17
 
14
18
  def process(document, reader)
15
19
  input_lines = reader.readlines.to_enum
16
- Asciidoctor::Reader.new(processed_lines(document, input_lines))
20
+ express_indexes = Utils.parse_document_express_indexes(
21
+ document,
22
+ input_lines
23
+ )
24
+ Asciidoctor::Reader
25
+ .new(processed_lines(document, input_lines, express_indexes))
17
26
  end
18
27
 
19
28
  protected
20
29
 
21
30
  def content_from_file(document, file_path)
22
31
  ::Lutaml::Parser
23
- .parse(File.new(relative_file_path(document, file_path),
32
+ .parse(File.new(Utils.relative_file_path(document, file_path),
24
33
  encoding: "UTF-8"))
25
34
  end
26
35
 
27
36
  private
28
37
 
29
- def processed_lines(document, input_lines)
38
+ def processed_lines(document, input_lines, express_indexes)
30
39
  result = []
31
40
  loop do
32
- result.push(*process_text_blocks(document, input_lines))
41
+ result
42
+ .push(*process_text_blocks(
43
+ document,
44
+ input_lines,
45
+ express_indexes
46
+ ))
33
47
  end
34
48
  result
35
49
  end
36
50
 
37
- def relative_file_path(document, file_path)
38
- docfile_directory = File.dirname(
39
- document.attributes["docfile"] || "."
40
- )
41
- document
42
- .path_resolver
43
- .system_path(file_path, docfile_directory)
44
- end
45
-
46
- def process_text_blocks(document, input_lines)
51
+ def process_text_blocks(document, input_lines, express_indexes)
47
52
  line = input_lines.next
48
- block_match = line.match(/^\[lutaml,(.+?),(.+?)\]/)
53
+ block_match = line.match(/^\[lutaml,([^,]+)?,?([^,]+)?,?([^,]+)?\]/)
49
54
  return [line] if block_match.nil?
50
55
 
51
56
  end_mark = input_lines.next
@@ -53,7 +58,8 @@ module Metanorma
53
58
  collect_internal_block_lines(document,
54
59
  input_lines,
55
60
  end_mark),
56
- block_match)
61
+ block_match,
62
+ express_indexes)
57
63
  end
58
64
 
59
65
  def collect_internal_block_lines(_document, input_lines, end_mark)
@@ -64,49 +70,74 @@ module Metanorma
64
70
  current_block
65
71
  end
66
72
 
67
- def parse_template(document, current_block, block_match)
68
- context_items = content_from_file(document, block_match[1])
69
- parse_context_block(document: document,
70
- context_lines: current_block,
71
- context_items: context_items,
72
- context_name: block_match[2].strip)
73
+ def contexts_items(block_match, document, express_indexes)
74
+ contexts_names = block_match[1].split(";").map(&:strip)
75
+ contexts_names.each_with_object([]) do |path, res|
76
+ if express_indexes[path]
77
+ res.push(*express_indexes[path])
78
+ else
79
+ res.push(content_from_file(document, path).to_liquid)
80
+ end
81
+ end
82
+ end
83
+
84
+ def parse_template(document, current_block, block_match, express_indexes)
85
+ options = parse_options(block_match[3])
86
+ .merge("relative_path_prefix" => File.dirname(block_match[1]))
87
+ contexts_items(block_match, document, express_indexes)
88
+ .map do |context_items|
89
+ parse_context_block(document: document,
90
+ context_lines: current_block,
91
+ context_items: decorate_context_items(context_items, options),
92
+ context_name: block_match[2].strip)
93
+ end.flatten
73
94
  rescue StandardError => e
74
- document.logger
75
- .warn("Failed to parse lutaml \
76
- block: #{e.message}")
95
+ document.logger.warn("Failed to parse lutaml block: #{e.message}")
77
96
  []
78
97
  end
79
98
 
99
+ def parse_options(options_string)
100
+ options_string
101
+ .to_s
102
+ .scan(/(.+?)=(\s?[^\s]+)/)
103
+ .map { |elem| elem.map(&:strip) }
104
+ .to_h
105
+ end
106
+
107
+ def decorate_context_items(context_items, options)
108
+ return context_items if !context_items.is_a?(Hash)
109
+
110
+ context_items
111
+ .map do |(key, val)|
112
+ if val.is_a?(Hash)
113
+ [key, decorate_context_items(val, options)]
114
+ elsif key == REMARKS_ATTRIBUTE
115
+ [key,
116
+ val&.map do |remark|
117
+ Metanorma::Plugin::Lutaml::ExpressRemarksDecorator
118
+ .call(remark, options)
119
+ end]
120
+ elsif val.is_a?(Array)
121
+ [key, val.map { |n| decorate_context_items(n, options) }]
122
+ else
123
+ [key, val]
124
+ end
125
+ end
126
+ .to_h
127
+ end
128
+
80
129
  def parse_context_block(context_lines:,
81
130
  context_items:,
82
131
  context_name:,
83
132
  document:)
84
- render_result, errors = render_liquid_string(
133
+ render_result, errors = Utils.render_liquid_string(
85
134
  template_string: context_lines.join("\n"),
86
135
  context_items: context_items,
87
136
  context_name: context_name
88
137
  )
89
- notify_render_errors(document, errors)
138
+ Utils.notify_render_errors(document, errors)
90
139
  render_result.split("\n")
91
140
  end
92
-
93
- def render_liquid_string(template_string:, context_items:,
94
- context_name:)
95
- liquid_template = Liquid::Template.parse(template_string)
96
- rendered_string = liquid_template
97
- .render(context_name => context_items,
98
- strict_variables: true,
99
- error_mode: :warn)
100
- [rendered_string, liquid_template.errors]
101
- end
102
-
103
- def notify_render_errors(document, errors)
104
- errors.each do |error_obj|
105
- document
106
- .logger
107
- .warn("Liquid render error: #{error_obj.message}")
108
- end
109
- end
110
141
  end
111
142
  end
112
143
  end
@@ -0,0 +1,102 @@
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 LutamlUmlAttributesTablePreprocessor < Asciidoctor::Extensions::Preprocessor
16
+ MARCO_REGEXP =
17
+ /\[lutaml_uml_attributes_table,([^,]+),?(.+)?,([^,]+),?(.+)?\]/
18
+ # search document for block `datamodel_attributes_table`
19
+ # read include derectives that goes after that in block and transform
20
+ # into yaml2text blocks
21
+ def process(document, reader)
22
+ input_lines = reader.readlines.to_enum
23
+ Asciidoctor::Reader.new(processed_lines(document, input_lines))
24
+ end
25
+
26
+ private
27
+
28
+ def lutaml_document_from_file(document, file_path)
29
+ ::Lutaml::Parser
30
+ .parse(File.new(Utils.relative_file_path(document, file_path),
31
+ encoding: "UTF-8"))
32
+ end
33
+
34
+ def processed_lines(document, input_lines)
35
+ input_lines.each_with_object([]) do |line, result|
36
+ if match = line.match(MARCO_REGEXP)
37
+ lutaml_path = match[1]
38
+ entity_name = match[3]
39
+ result.push(*parse_marco(lutaml_path, entity_name, document))
40
+ else
41
+ result.push(line)
42
+ end
43
+ end
44
+ end
45
+
46
+ def parse_marco(lutaml_path, entity_name, document)
47
+ lutaml_document = lutaml_document_from_file(document, lutaml_path)
48
+ .serialized_document
49
+ entities = [lutaml_document["classes"], lutaml_document["enums"]]
50
+ .compact
51
+ .flatten
52
+ entity_definition = entities.detect do |klass|
53
+ klass["name"] == entity_name.strip
54
+ end
55
+ model_representation(entity_definition, document)
56
+ end
57
+
58
+ def model_representation(entity_definition, document)
59
+ render_result, errors = Utils.render_liquid_string(
60
+ template_string: table_template,
61
+ context_items: entity_definition,
62
+ context_name: "definition"
63
+ )
64
+ Utils.notify_render_errors(document, errors)
65
+ render_result.split("\n")
66
+ end
67
+
68
+ # rubocop:disable Layout/IndentHeredoc
69
+ def table_template
70
+ <<~TEMPLATE
71
+ === {{ definition.name }}
72
+ {{ definition.definition }}
73
+
74
+ {% if definition.attributes %}
75
+ {% if definition.keyword == 'enumeration' %}
76
+ .{{ definition.name }} values
77
+ |===
78
+ |Name |Definition
79
+
80
+ {% for item in definition.attributes %}
81
+ |{{ item.name }} |{{ item.definition }}
82
+ {% endfor %}
83
+ |===
84
+ {% else %}
85
+ .{{ definition.name }} attributes
86
+ |===
87
+ |Name |Definition |Mandatory/ Optional/ Conditional |Max Occur |Data Type
88
+
89
+ {% for item in definition.attributes %}
90
+ |{{ item.name }} |{% if item.definition %}{{ item.definition }}{% else %}TODO: enum {{ key }}'s definition{% endif %} |{% if item.cardinality.min == "0" %}O{% else %}M{% endif %} |{% if item.cardinality.max == "*" %}N{% else %}1{% endif %} |{% if item.origin %}<<{{ item.origin }}>>{% endif %} `{{ item.type }}`
91
+ {% endfor %}
92
+ |===
93
+ {% endif %}
94
+ {% endif %}
95
+
96
+ TEMPLATE
97
+ end
98
+ # rubocop:enable Layout/IndentHeredoc
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,74 @@
1
+ module Metanorma
2
+ module Plugin
3
+ module Lutaml
4
+ # Helpers for lutaml macroses
5
+ module Utils
6
+ module_function
7
+
8
+ def relative_file_path(document, file_path)
9
+ docfile_directory = File.dirname(
10
+ document.attributes["docfile"] || "."
11
+ )
12
+ document
13
+ .path_resolver
14
+ .system_path(file_path, docfile_directory)
15
+ end
16
+
17
+ def render_liquid_string(template_string:, context_items:,
18
+ context_name:)
19
+ liquid_template = Liquid::Template.parse(template_string)
20
+ rendered_string = liquid_template
21
+ .render(context_name => context_items,
22
+ strict_variables: true,
23
+ error_mode: :warn)
24
+ [rendered_string, liquid_template.errors]
25
+ end
26
+
27
+ def notify_render_errors(document, errors)
28
+ errors.each do |error_obj|
29
+ document
30
+ .logger
31
+ .warn("Liquid render error: #{error_obj.message}")
32
+ end
33
+ end
34
+
35
+ def process_express_index(folder, name, idxs, document)
36
+ idxs[name] = []
37
+ Dir["#{Utils.relative_file_path(document, folder)}/*"].each do |path|
38
+ next if [".", ".."].include?(path)
39
+
40
+ begin
41
+ idxs[name]
42
+ .push(::Lutaml::Parser.parse(File.new(path, encoding: "UTF-8")).to_liquid)
43
+ rescue StandardError => e
44
+ document.logger.warn("Failed to load #{path}: #{e.message}")
45
+ end
46
+ end
47
+ end
48
+
49
+ def parse_document_express_indexes(document, input_lines)
50
+ express_indexes = {}
51
+ loop do
52
+ line = input_lines.next
53
+ break if line.length.zero?
54
+
55
+ _, name, folder = line.match(/^:lutaml-express-index:(.+?);(.+?)$/)&.to_a
56
+ if folder && name
57
+ process_express_index(
58
+ folder.strip.gsub(";", ""),
59
+ name.strip,
60
+ express_indexes,
61
+ document
62
+ )
63
+ end
64
+ end
65
+ express_indexes
66
+ rescue StopIteration
67
+ express_indexes
68
+ ensure
69
+ input_lines.rewind
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -1,7 +1,7 @@
1
1
  module Metanorma
2
2
  module Plugin
3
3
  module Lutaml
4
- VERSION = "0.1.0".freeze
4
+ VERSION = "0.2.4.alpha".freeze
5
5
  end
6
6
  end
7
7
  end
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.require_paths = ["lib"]
25
25
 
26
26
  spec.add_dependency "liquid"
27
- spec.add_dependency "lutaml", "~> 0.3.0"
27
+ spec.add_dependency "lutaml", "0.4.1.pre.alpha"
28
28
  spec.add_dependency "lutaml-uml", "~> 0.2.0"
29
29
  spec.add_dependency "metanorma"
30
30
  spec.add_dependency "relaton-cli"
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.1.0
4
+ version: 0.2.4.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-10-28 00:00:00.000000000 Z
11
+ date: 2021-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: lutaml
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 0.3.0
33
+ version: 0.4.1.pre.alpha
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 0.3.0
40
+ version: 0.4.1.pre.alpha
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: lutaml-uml
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -241,6 +241,7 @@ executables: []
241
241
  extensions: []
242
242
  extra_rdoc_files: []
243
243
  files:
244
+ - ".github/workflows/rake.yml"
244
245
  - ".gitignore"
245
246
  - CODE_OF_CONDUCT.md
246
247
  - Gemfile
@@ -250,9 +251,14 @@ files:
250
251
  - bin/console
251
252
  - bin/setup
252
253
  - lib/metanorma-plugin-lutaml.rb
254
+ - lib/metanorma/plugin/lutaml/express_remarks_decorator.rb
255
+ - lib/metanorma/plugin/lutaml/lutaml_diagram_block.rb
253
256
  - lib/metanorma/plugin/lutaml/lutaml_preprocessor.rb
257
+ - lib/metanorma/plugin/lutaml/lutaml_uml_attributes_table_preprocessor.rb
258
+ - lib/metanorma/plugin/lutaml/utils.rb
254
259
  - lib/metanorma/plugin/lutaml/version.rb
255
260
  - metanorma-plugin-lutaml.gemspec
261
+ - pkg/metanorma-plugin-lutaml-0.2.0.gem
256
262
  homepage: https://github.com/metanorma/metanorma-plugin-lutaml
257
263
  licenses:
258
264
  - BSD-2-Clause
@@ -268,9 +274,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
268
274
  version: '0'
269
275
  required_rubygems_version: !ruby/object:Gem::Requirement
270
276
  requirements:
271
- - - ">="
277
+ - - ">"
272
278
  - !ruby/object:Gem::Version
273
- version: '0'
279
+ version: 1.3.1
274
280
  requirements: []
275
281
  rubygems_version: 3.0.3
276
282
  signing_key: