metanorma-plugin-lutaml 0.1.0 → 0.2.0

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: 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