metanorma-plugin-lutaml 0.1.0 → 0.2.0

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: 0e854f55d18dbd63e113f74e940689320384a8840912ef16f7a6880e13672ee6
4
- data.tar.gz: ebf477f3262b209fc4edad4b1908b911d7737d343c2eb42383207de0aeb30b2d
3
+ metadata.gz: cf1f2a866187d3c88f1948cfee8cac317fd17aa01a6ed3896470689b5dc644d1
4
+ data.tar.gz: 47752b4c4b8cd0fc9f086d83a00dbad165940650ef14353c860b3cbe8c22dd41
5
5
  SHA512:
6
- metadata.gz: e530b0648b11116825ac6f1435f5c8d533102bbd212b6e4ab4d4c81d3378d67cb2c39ce32dffe5585d8801b34e2b8a647809fd2eafbdd879e27a01b975f3888e
7
- data.tar.gz: 5a216d14209e1183b19c1301c7273639f379ab1d7e025a7ded83f135a46a5834568bb154335d8bd7cfc33c967825ae5d7b38c96289d0047c8c74cee3b9b2f0ca
6
+ metadata.gz: b2c871c4788077d0e853813452119c8639fc8d539103a312be1781f17d0e22968b29d28ac62f78f887fc4714123ff598f42b591c8747b14c48ae5c034f356c6a
7
+ data.tar.gz: f1545cb37a21c5ec2f00078b9e556bcba25197409a4e42902734cdc378d6b3e1a1822abf4d13f0e92d55c1ad22c58b87e60a90b3873bf088987dc47233404328
@@ -0,0 +1,81 @@
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
+ name: rake
4
+
5
+ on:
6
+ push:
7
+ branches: [ main ]
8
+ tags: [ v* ]
9
+ pull_request:
10
+
11
+ jobs:
12
+ rake:
13
+ name: Test on Ruby ${{ matrix.ruby }} ${{ matrix.os }}
14
+ runs-on: ${{ matrix.os }}
15
+ continue-on-error: ${{ matrix.experimental }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ ruby: [ '2.6', '2.5', '2.4' ]
20
+ os: [ ubuntu-latest, windows-latest, macos-latest ]
21
+ experimental: [ false ]
22
+ include:
23
+ - ruby: '2.7'
24
+ os: 'ubuntu-latest'
25
+ experimental: true
26
+ - ruby: '2.7'
27
+ os: 'windows-latest'
28
+ experimental: true
29
+ - ruby: '2.7'
30
+ os: 'macos-latest'
31
+ experimental: true
32
+ steps:
33
+ - uses: actions/checkout@master
34
+
35
+ - name: Use Ruby
36
+ uses: ruby/setup-ruby@v1
37
+ with:
38
+ ruby-version: ${{ matrix.ruby }}
39
+ bundler-cache: true
40
+
41
+ - name: Update gems
42
+ run: bundle install --jobs 4 --retry 3
43
+
44
+ - name: Install Grpahviz Ubuntu
45
+ if: matrix.os == 'ubuntu-latest'
46
+ run: sudo apt-get install graphviz
47
+
48
+ - name: Install Grpahviz macOS
49
+ if: matrix.os == 'macos-latest'
50
+ run: brew install graphviz
51
+
52
+ - name: Install Grpahviz Windows
53
+ if: matrix.os == 'windows-latest'
54
+ uses: nick-invision/retry@v1
55
+ with:
56
+ polling_interval_seconds: 5
57
+ timeout_minutes: 5
58
+ max_attempts: 3
59
+ command: choco install --no-progress graphviz --version 2.38.0.20190211
60
+
61
+ - name: Check dot command
62
+ if: matrix.os == 'windows-latest'
63
+ run: |
64
+ dot -?
65
+
66
+ - name: Run specs
67
+ run: bundle exec rake
68
+
69
+ notify:
70
+ name: Trigger notify workflow
71
+ needs: rake
72
+ runs-on: ubuntu-latest
73
+ steps:
74
+ - name: Trigger notify workflow
75
+ uses: Sibz/github-status-action@v1
76
+ with:
77
+ authToken: ${{ secrets.GITHUB_TOKEN }}
78
+ context: 'tests-passed-successfully'
79
+ description: 'Tests passed successfully'
80
+ state: 'success'
81
+ sha: ${{ github.event.pull_request.head.sha || github.sha }}
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  Gemfile.lock
2
2
  .rspec_status
3
+ spec/assets/lutaml
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in metanorma-plugin-lutaml.gemspec
4
4
  gemspec
5
+
@@ -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
 
@@ -71,6 +73,82 @@ Will produce this output:
71
73
  === my_type5
72
74
  -----
73
75
 
76
+ This macro also supports `.lutaml` files.
77
+
78
+ === Usage, `lutaml_datamodel_attributes_table` macro
79
+
80
+ This macro allows to quickly render datamodel attributes/values tables. Given `example.lutaml` file with the content:
81
+
82
+ [source,java]
83
+ ----
84
+ diagram MyView {
85
+ title "my diagram"
86
+
87
+ enum AddressClassProfile {
88
+ imlicistAttributeProfile: CharacterString [0..1] {
89
+ definition
90
+ this is multiline with `ascidoc`
91
+ end definition
92
+ }
93
+ }
94
+
95
+ class AttributeProfile {
96
+ +addressClassProfile: CharacterString [0..1]
97
+ imlicistAttributeProfile: CharacterString [0..1] {
98
+ definition this is attribute definition
99
+ }
100
+ }
101
+ }
102
+ ----
103
+
104
+ And the `lutaml_datamodel_attributes_table` macro:
105
+
106
+ [source,adoc]
107
+ -----
108
+ [lutaml_datamodel_attributes_table, example.lutaml, AttributeProfile]
109
+ -----
110
+
111
+ Will produce this output:
112
+
113
+ [source,adoc]
114
+ -----
115
+ === AttributeProfile
116
+
117
+
118
+ .AttributeProfile attributes
119
+ |===
120
+ |Name |Definition |Mandatory/ Optional/ Conditional |Max Occur |Data Type
121
+
122
+ |addressClassProfile |TODO: enum 's definition |M |1 | `CharacterString`
123
+
124
+ |imlicistAttributeProfile |this is attribute definition with multiply lines |M |1 | `CharacterString`
125
+
126
+ |===
127
+ -----
128
+
129
+ In case of "enumeration"(AddressClassProfile) entity:
130
+
131
+ [source,adoc]
132
+ -----
133
+ [lutaml_datamodel_attributes_table, example.lutaml, AddressClassProfile]
134
+ -----
135
+
136
+ Will produce this output:
137
+
138
+ [source,adoc]
139
+ -----
140
+ === AddressClassProfile
141
+
142
+
143
+ .AddressClassProfile values
144
+ |===
145
+ |Name |Definition
146
+
147
+ |imlicistAttributeProfile |this is multiline with `ascidoc`
148
+
149
+ |===
150
+ -----
151
+
74
152
  == Documentation
75
153
 
76
154
  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_datamodel_attributes_table_preprocessor"
4
+ require "metanorma/plugin/lutaml/lutaml_diagram_block"
3
5
 
4
6
  module Metanorma
5
7
  module Plugin
@@ -0,0 +1,104 @@
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_datamodel_attributes_table,path/to/lutaml,EntityName]
15
+ class LutamlDatamodelAttributesTablePreprocessor < Asciidoctor::Extensions::Preprocessor
16
+ MARCO_REGEXP =
17
+ /\[lutaml_datamodel_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
+ rescue => e
33
+ require 'byebug'
34
+ byebug
35
+ i =10
36
+ end
37
+
38
+ def processed_lines(document, input_lines)
39
+ input_lines.each_with_object([]) do |line, result|
40
+ if match = line.match(MARCO_REGEXP)
41
+ lutaml_path = match[1]
42
+ entity_name = match[3]
43
+ result.push(*parse_marco(lutaml_path, entity_name, document))
44
+ else
45
+ result.push(line)
46
+ end
47
+ end
48
+ end
49
+
50
+ def parse_marco(lutaml_path, entity_name, document)
51
+ lutaml_document = lutaml_document_from_file(document, lutaml_path)
52
+ .serialized_document
53
+ entities = [lutaml_document['classes'], lutaml_document['enums']]
54
+ .compact
55
+ .flatten
56
+ entity_definition = entities.find do |klass|
57
+ klass['name'] == entity_name.strip
58
+ end
59
+ model_representation(entity_definition, document)
60
+ end
61
+
62
+ def model_representation(entity_definition, document)
63
+ render_result, errors = Utils.render_liquid_string(
64
+ template_string: table_template,
65
+ context_items: entity_definition,
66
+ context_name: 'definition'
67
+ )
68
+ Utils.notify_render_errors(document, errors)
69
+ render_result.split("\n")
70
+ end
71
+
72
+ def table_template
73
+ <<~TEMPLATE
74
+ === {{ definition.name }}
75
+ {{ definition.definition }}
76
+
77
+ {% if definition.attributes %}
78
+ {% if definition.keyword == 'enumeration' %}
79
+ .{{ definition.name }} values
80
+ |===
81
+ |Name |Definition
82
+
83
+ {% for item in definition.attributes %}
84
+ |{{ item.name }} |{{ item.definition }}
85
+ {% endfor %}
86
+ |===
87
+ {% else %}
88
+ .{{ definition.name }} attributes
89
+ |===
90
+ |Name |Definition |Mandatory/ Optional/ Conditional |Max Occur |Data Type
91
+
92
+ {% for item in definition.attributes %}
93
+ |{{ 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 }}`
94
+ {% endfor %}
95
+ |===
96
+ {% endif %}
97
+ {% endif %}
98
+
99
+ TEMPLATE
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,86 @@
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
+ end
27
+
28
+ def process(parent, reader, attrs)
29
+ uml_document = ::Lutaml::Uml::Parsers::Dsl.parse(lutaml_temp(reader))
30
+ filename = generate_file(parent, reader, uml_document)
31
+ through_attrs = generate_attrs(attrs)
32
+ through_attrs["target"] = filename
33
+ through_attrs["title"] = uml_document.caption
34
+ create_image_block(parent, through_attrs)
35
+ rescue => e
36
+ abort(parent, reader, attrs, e.message)
37
+ end
38
+
39
+ private
40
+
41
+ def lutaml_temp(reader)
42
+ temp_file = Tempfile.new(['lutaml', '.lutaml'])
43
+ temp_file.puts(reader.read)
44
+ temp_file.rewind
45
+ temp_file
46
+ end
47
+
48
+ # if no :imagesdir: leave image file in lutaml
49
+ def generate_file(parent, reader, uml_document)
50
+ formatter = ::Lutaml::Uml::Formatter::Graphviz.new
51
+ formatter.type = :png
52
+
53
+ imagesdir = if parent.document.attr('imagesdir')
54
+ File.join(parent.document.attr('imagesdir'), 'lutaml')
55
+ else
56
+ 'lutaml'
57
+ end
58
+ result_path = Utils.relative_file_path(parent.document, imagesdir)
59
+ result_pathname = Pathname.new(result_path)
60
+ result_pathname.mkpath
61
+ File.writable?(result_pathname) or raise "Destination path #{result_path} not writable for Lutaml!"
62
+
63
+ outfile = Tempfile.new(['lutaml', '.png'])
64
+ outfile.binmode
65
+ outfile.puts(formatter.format(uml_document))
66
+
67
+ # Warning: metanorma/metanorma-standoc#187
68
+ # Windows Ruby 2.4 will crash if a Tempfile is "mv"ed.
69
+ # This is why we need to copy and then unlink.
70
+ filename = File.basename(outfile.path)
71
+ FileUtils.cp(outfile, result_pathname) && outfile.unlink
72
+
73
+ File.join(result_pathname, filename)
74
+ end
75
+
76
+ def generate_attrs(attrs)
77
+ through_attrs = %w(id align float title role width height alt).
78
+ inject({}) do |memo, key|
79
+ memo[key] = attrs[key] if attrs.has_key? key
80
+ memo
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -4,6 +4,7 @@ require "liquid"
4
4
  require "asciidoctor"
5
5
  require "asciidoctor/reader"
6
6
  require "lutaml"
7
+ require "metanorma/plugin/lutaml/utils"
7
8
 
8
9
  module Metanorma
9
10
  module Plugin
@@ -20,7 +21,7 @@ module Metanorma
20
21
 
21
22
  def content_from_file(document, file_path)
22
23
  ::Lutaml::Parser
23
- .parse(File.new(relative_file_path(document, file_path),
24
+ .parse(File.new(Utils.relative_file_path(document, file_path),
24
25
  encoding: "UTF-8"))
25
26
  end
26
27
 
@@ -34,15 +35,6 @@ module Metanorma
34
35
  result
35
36
  end
36
37
 
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
38
  def process_text_blocks(document, input_lines)
47
39
  line = input_lines.next
48
40
  block_match = line.match(/^\[lutaml,(.+?),(.+?)\]/)
@@ -81,32 +73,14 @@ module Metanorma
81
73
  context_items:,
82
74
  context_name:,
83
75
  document:)
84
- render_result, errors = render_liquid_string(
76
+ render_result, errors = Utils.render_liquid_string(
85
77
  template_string: context_lines.join("\n"),
86
78
  context_items: context_items,
87
79
  context_name: context_name
88
80
  )
89
- notify_render_errors(document, errors)
81
+ Utils.notify_render_errors(document, errors)
90
82
  render_result.split("\n")
91
83
  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
84
  end
111
85
  end
112
86
  end
@@ -0,0 +1,37 @@
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
+ end
35
+ end
36
+ end
37
+ 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.0".freeze
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-plugin-lutaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
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: 2020-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -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,7 +251,10 @@ files:
250
251
  - bin/console
251
252
  - bin/setup
252
253
  - lib/metanorma-plugin-lutaml.rb
254
+ - lib/metanorma/plugin/lutaml/lutaml_datamodel_attributes_table_preprocessor.rb
255
+ - lib/metanorma/plugin/lutaml/lutaml_diagram_block.rb
253
256
  - lib/metanorma/plugin/lutaml/lutaml_preprocessor.rb
257
+ - lib/metanorma/plugin/lutaml/utils.rb
254
258
  - lib/metanorma/plugin/lutaml/version.rb
255
259
  - metanorma-plugin-lutaml.gemspec
256
260
  homepage: https://github.com/metanorma/metanorma-plugin-lutaml
@@ -272,7 +276,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
272
276
  - !ruby/object:Gem::Version
273
277
  version: '0'
274
278
  requirements: []
275
- rubygems_version: 3.0.3
279
+ rubygems_version: 3.0.6
276
280
  signing_key:
277
281
  specification_version: 4
278
282
  summary: Metanorma plugin for LutaML