lutaml-uml 0.2.8 → 0.2.9

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: ef28b2562bcae4b385b3be898a71d6c326c59d5167c94ee1231932df060d5eee
4
- data.tar.gz: 39519359dc16f9532379b5ce15aef7e8ed6d37a1ae5afa2e22253c025505d0ab
3
+ metadata.gz: 7e25b300c9a636999a7861a78ea5c677d1c0c6767180a81f8b63cc6f9af2f8aa
4
+ data.tar.gz: b78902b23e27ec296913e2943c5fb966d17268f6c28e2b1c50409450e0310ed8
5
5
  SHA512:
6
- metadata.gz: 8b2464f9bc2d0f95a3baf5025ca2853537e6abd175a62be6f4f427e7f5f3e13f75f7ec9d2f7c9a675bd17be67b913da3a0b690c806e63a12f0633187471a6ec6
7
- data.tar.gz: 72a944718bd7c57c8146197f10810b40a4026cf71150f65b0ce7c17158bf046815ce71da1845c8b9d6d720521fa693fb006a50c8e02fac31b44ad8ae2b521fc3
6
+ metadata.gz: 287de7e6b28b6ff2c1dffab0db3a4503257c3b75c00409cd56184629875f3196e9a91dee7acb21a8cf1d1e484a59a9d5188836d33002599d8a4407da4a51f68c
7
+ data.tar.gz: 14f5782e4d85885c3fca50f486cf8107648fac50e50acdeb2d931dc6a68c4e0e8fe1c9b9927dfd4449a02186ea36a969d1591fd55712334dca72cb49d7fba103
@@ -18,7 +18,7 @@ jobs:
18
18
  strategy:
19
19
  fail-fast: false
20
20
  matrix:
21
- ruby: [ '2.6', '2.5', '2.4' ]
21
+ ruby: [ '2.6', '2.5' ]
22
22
  experimental: [false]
23
23
  include:
24
24
  - ruby: '2.7'
data/README.adoc CHANGED
@@ -8,20 +8,19 @@ Lutaml is a language for specifying UML class diagrams and a tool for converting
8
8
 
9
9
  ### RubyGems: `gem install lutaml-uml`
10
10
 
11
- ## Executable
11
+ ## Language
12
12
 
13
- [source,sh]
14
- --
15
- # Convert example.lutaml to example.png
16
- $ lutaml-uml --type png --output . example.lutaml
13
+ See link:LUTAML.adoc[LUTAML.adoc]
17
14
 
18
- # Display detailed help message
19
- $ lutaml-uml --help
20
- --
15
+ ## Usage
21
16
 
22
- ## Language
17
+ Converter executables are available:
18
+
19
+ * PlantUML WSD to LutaML UML: `lutaml-wsd2uml`
20
+ * LutaML YAML to LutaML UML: `lutaml-yaml2uml`
21
+
22
+ EXAMPLE: `lutaml-wsd2uml mn/metanorma-model-standoc/models/StandardDoc_Blocks_New.wsd`
23
23
 
24
- See link:LUTAML.adoc[LUTAML.adoc]
25
24
 
26
25
  ## Development
27
26
 
data/bin/plantuml2lutaml CHANGED
@@ -27,6 +27,7 @@ ASSOCIATION_MAPPINGS = {
27
27
  in_comment_block = false
28
28
 
29
29
  def transform_line(line)
30
+ line = line.gsub(/^\s*'/, '** ').gsub(/\|[\sa-zA-Z]+$/, '')
30
31
  return sync_puts(line, 2) if ASSOCIATION_MAPPINGS.keys.none? { |key| line =~ key }
31
32
 
32
33
  owner_type, member_type = ASSOCIATION_MAPPINGS.detect { |(key, _value)| line =~ key }.last.split(",")
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # Script to convert plantuml files into LutaML syntax
6
+ # Usage: bin/plantuml2lutaml /path/to/plantuml.wsd
7
+
8
+ file_path = ARGV[0]
9
+ FILE_NAME = File.basename(file_path, ".wsd")
10
+ wsd_file = File.new(ARGV[0])
11
+
12
+ def sync_puts(line, level = 0)
13
+ $stdout.puts("#{''.rjust(level)}#{line}")
14
+ $stdout.flush
15
+ end
16
+
17
+ SKIPPED_LINES_REGEXP = /^(@startuml|'\*{7}|note|@enduml|\!|'\/)/
18
+ COMMENT_START = /\/'/
19
+ COMMENT_END = /'\//
20
+ ASSOCIATION_MAPPINGS = {
21
+ /-\|>/ => ",inheritance",
22
+ /<\|-/ => "inheritance,",
23
+ /->/ => ",direct",
24
+ /<-/ => "direct,",
25
+ }.freeze
26
+
27
+ in_comment_block = false
28
+
29
+ def transform_line(line)
30
+ line = line.gsub(/^\s*'/, '** ').gsub(/\|[\sa-zA-Z]+$/, '')
31
+ return sync_puts(line, 2) if ASSOCIATION_MAPPINGS.keys.none? { |key| line =~ key }
32
+
33
+ owner_type, member_type = ASSOCIATION_MAPPINGS.detect { |(key, _value)| line =~ key }.last.split(",")
34
+ blocks = line.split(" ")
35
+ owner = blocks.first
36
+ member = blocks.last
37
+ sync_puts("association {", 2)
38
+ sync_puts("owner #{owner}", 4)
39
+ sync_puts("member #{member}", 4)
40
+ sync_puts("owner_type #{owner_type}", 4) if !owner_type.to_s.empty?
41
+ sync_puts("member_type #{member_type}", 4) if !member_type.to_s.empty?
42
+ sync_puts("}", 2)
43
+ end
44
+
45
+ sync_puts("diagram #{FILE_NAME} {")
46
+ wsd_file.readlines.each do |line|
47
+ if line.match?(COMMENT_START)
48
+ in_comment_block = true
49
+ end
50
+
51
+ if line.match?(COMMENT_END)
52
+ in_comment_block = false
53
+ end
54
+
55
+ next if in_comment_block || line =~ SKIPPED_LINES_REGEXP
56
+
57
+ transform_line(line)
58
+ end
59
+ sync_puts("}")
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # Script to convert datamodel yaml files into LutaML syntax
6
+ # Usage: bin/yaml2lutaml /path/to/datamodel/view/file.yml
7
+
8
+ require "yaml"
9
+
10
+ view_yaml = YAML.safe_load(File.read(ARGV[0]))
11
+ models_path = File.expand_path("../../models", ARGV[0])
12
+
13
+ def sync_puts(line, level = 0)
14
+ $stdout.puts("#{''.rjust(level)}#{line}")
15
+ $stdout.flush
16
+ end
17
+
18
+ encountered_relations = Hash.new { |h, key| h[key] = [] }
19
+ # relations:
20
+ # - target: AttributeProfile
21
+ # relationship:
22
+ # source:
23
+ # type: aggregation
24
+ # attribute:
25
+ # addressClassProfile:
26
+ # target:
27
+ # type: direct
28
+ # attribute:
29
+ # attributeProfile:
30
+ # cardinality:
31
+ # min: 0
32
+ # max: '*'
33
+ def process_association(owner, values, encountered_relations)
34
+ target_name = values["target"]
35
+ return if encountered_relations[owner].include?(target_name)
36
+
37
+ encountered_relations[owner].push(target_name)
38
+ sync_puts("association {", 2)
39
+
40
+ relationship_block = values["relationship"] || {}
41
+
42
+ if relationship_block["source"] && relationship_block["source"]["type"]
43
+ source = relationship_block["source"]
44
+ sync_puts("owner_type #{source['type']}", 4)
45
+ if source["attribute"]
46
+ source_attribute_name = source["attribute"].keys.first
47
+ owner += "##{source_attribute_name}"
48
+ if source["attribute"][source_attribute_name] && source["attribute"][source_attribute_name]["cardinality"]
49
+ cardinality = source["attribute"][source_attribute_name]["cardinality"]
50
+ owner += " [#{cardinality['min']}..#{cardinality['max']}]"
51
+ end
52
+ end
53
+ end
54
+ sync_puts("owner #{owner}", 4)
55
+
56
+ member = target_name
57
+ if relationship_block["target"]
58
+ target = relationship_block["target"]
59
+ type = target["type"] || "direct"
60
+ sync_puts("member_type #{type}", 4)
61
+ if target["attribute"]
62
+ target_attribute_name = target["attribute"].keys.first
63
+ member += "##{target_attribute_name}"
64
+ if target["attribute"][target_attribute_name] && target["attribute"][target_attribute_name]["cardinality"]
65
+ cardinality = target["attribute"][target_attribute_name]["cardinality"]
66
+ member += " [#{cardinality['min']}..#{cardinality['max']}]"
67
+ end
68
+ end
69
+ else
70
+ sync_puts("member_type direct", 4)
71
+ end
72
+ sync_puts("member #{member}", 4)
73
+
74
+ sync_puts("}", 2)
75
+ end
76
+ sync_puts("diagram #{File.basename(ARGV[0], 'yml')[0..-2]} {")
77
+ sync_puts("title '#{view_yaml['title']}'", 2)
78
+ sync_puts("caption '#{view_yaml['caption']}'", 2)
79
+
80
+ # Class associations notations
81
+ view_yaml["relations"]&.each do |values|
82
+ process_association(values["source"], values, encountered_relations)
83
+ end
84
+
85
+ view_yaml["imports"].keys.each do |entry|
86
+ import = YAML.safe_load(File.read(File.join(models_path, "#{entry}.yml")))
87
+ import_name = import["name"] || File.basename(entry)
88
+ # Class notation
89
+ sync_puts("#{import['modelType']} #{import_name} {", 2)
90
+ if import["definition"]
91
+ definition = <<~TEXT
92
+ definition {
93
+ #{import['definition']}
94
+ }
95
+ TEXT
96
+ sync_puts(definition, 4)
97
+ end
98
+ import["values"]&.each_pair do |key, values|
99
+ result_string = key
100
+ if values["definition"]
101
+ result_string += <<~TEXT
102
+ {
103
+ definition {
104
+ #{values['definition']}
105
+ }
106
+ }
107
+ TEXT
108
+ end
109
+ sync_puts(result_string, 4)
110
+ end
111
+ import["attributes"]&.each_pair do |key, values|
112
+ definition = values["definition"]
113
+ cardinality = if values["cardinality"]
114
+ cardinality_val = values["cardinality"]
115
+ "[#{cardinality_val['min']}..#{cardinality_val['max']}]"
116
+ else
117
+ ""
118
+ end
119
+ result_string = "+#{key}"
120
+ if values["type"]
121
+ result_string += ": #{values['type']}"
122
+ end
123
+ if cardinality
124
+ result_string += " #{cardinality}"
125
+ end
126
+ if definition
127
+ result_string += <<~TEXT
128
+ {
129
+ definition
130
+ #{definition}
131
+ end definition
132
+ }
133
+ TEXT
134
+ end
135
+ sync_puts(result_string, 4)
136
+ end
137
+ sync_puts("}", 2)
138
+
139
+ # Associations notations
140
+ import["relations"]&.each do |values|
141
+ process_association(import_name, values, encountered_relations)
142
+ end
143
+ end
144
+ sync_puts("}")
data/lib/lutaml/uml.rb CHANGED
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "lutaml/uml/version"
4
- require "lutaml/uml/interface/command_line"
4
+ require "lutaml/uml/parsers/dsl"
5
+ require "lutaml/uml/parsers/yaml"
6
+ require "lutaml/uml/parsers/attribute"
7
+ require "lutaml/uml/formatter"
5
8
 
6
9
  module Lutaml
7
10
  module Uml
8
11
  class Error < StandardError; end
9
- # Your code goes here...
10
12
  end
11
13
  end
@@ -63,7 +63,7 @@ module Lutaml
63
63
  rule(:spaces) { match("\s").repeat(1) }
64
64
  rule(:spaces?) { spaces.maybe }
65
65
  rule(:whitespace) do
66
- (match("\s") | match("\r?\n") | match("\r") | str(";")).repeat(1)
66
+ (match("\s") | match(" ") | match("\r?\n") | match("\r") | str(";")).repeat(1)
67
67
  end
68
68
  rule(:whitespace?) { whitespace.maybe }
69
69
  rule(:name) { match["a-zA-Z0-9 _-"].repeat(1) }
@@ -322,6 +322,7 @@ module Lutaml
322
322
  match['"\''].maybe >>
323
323
  class_name.as(:name) >>
324
324
  match['"\''].maybe >>
325
+ attribute_keyword? >>
325
326
  enum_body?
326
327
  end
327
328
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lutaml
4
4
  module Uml
5
- VERSION = "0.2.8"
5
+ VERSION = "0.2.9"
6
6
  end
7
7
  end
data/lutaml-uml.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.bindir = "exe"
24
24
  spec.require_paths = ["lib"]
25
- spec.executables = %w[lutaml-uml]
25
+ spec.executables = %w[lutaml-wsd2uml lutaml-yaml2uml]
26
26
 
27
27
  spec.add_runtime_dependency "hashie", "~> 4.1.0"
28
28
  spec.add_runtime_dependency "parslet", "~> 1.7.1"
@@ -3,7 +3,7 @@ diagram MyView {
3
3
 
4
4
  enum MyEnum {}
5
5
 
6
- enum AddressClassProfile {
6
+ enum AddressClassProfile <<my_keyword>> {
7
7
  +addressClassProfile: CharacterString
8
8
  }
9
9
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lutaml-uml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.2.9
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-11-29 00:00:00.000000000 Z
11
+ date: 2021-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hashie
@@ -168,7 +168,8 @@ description: UML model module for LutaML.
168
168
  email:
169
169
  - open.source@ribose.com'
170
170
  executables:
171
- - lutaml-uml
171
+ - lutaml-wsd2uml
172
+ - lutaml-yaml2uml
172
173
  extensions: []
173
174
  extra_rdoc_files: []
174
175
  files:
@@ -188,7 +189,8 @@ files:
188
189
  - bin/plantuml2lutaml
189
190
  - bin/setup
190
191
  - bin/yaml2lutaml
191
- - exe/lutaml-uml
192
+ - exe/lutaml-wsd2uml
193
+ - exe/lutaml-yaml2uml
192
194
  - lib/lutaml/layout/engine.rb
193
195
  - lib/lutaml/layout/graph_viz_engine.rb
194
196
  - lib/lutaml/uml.rb
@@ -214,8 +216,6 @@ files:
214
216
  - lib/lutaml/uml/has_attributes.rb
215
217
  - lib/lutaml/uml/has_members.rb
216
218
  - lib/lutaml/uml/instance.rb
217
- - lib/lutaml/uml/interface/base.rb
218
- - lib/lutaml/uml/interface/command_line.rb
219
219
  - lib/lutaml/uml/model.rb
220
220
  - lib/lutaml/uml/node/base.rb
221
221
  - lib/lutaml/uml/node/class_node.rb
@@ -319,7 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
319
319
  - !ruby/object:Gem::Version
320
320
  version: '0'
321
321
  requirements: []
322
- rubygems_version: 3.0.6
322
+ rubygems_version: 3.0.3
323
323
  signing_key:
324
324
  specification_version: 4
325
325
  summary: UML model module for LutaML.
data/exe/lutaml-uml DELETED
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: UTF-8
3
- # frozen_string_literal: true
4
-
5
- # resolve bin path, ignoring symlinks
6
- require "pathname"
7
- bin_file = Pathname.new(__FILE__).realpath
8
-
9
- # add self to libpath
10
- $:.unshift File.expand_path("../../lib", bin_file)
11
-
12
- # Fixes https://github.com/rubygems/rubygems/issues/1420
13
- require "rubygems/specification"
14
-
15
- class Gem::Specification
16
- def this; self; end
17
- end
18
-
19
- require "lutaml/uml/interface/command_line"
20
-
21
- Lutaml::Uml::Interface::CommandLine.run
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "optparse"
4
- require "lutaml/uml/has_attributes"
5
-
6
- module Lutaml
7
- module Uml
8
- module Interface
9
- class Base
10
- def self.run(attributes = {})
11
- new(attributes).run
12
- end
13
-
14
- include HasAttributes
15
-
16
- # rubocop:disable Rails/ActiveRecordAliases
17
- def initialize(attributes = {})
18
- update_attributes(attributes)
19
- end
20
- # rubocop:enable Rails/ActiveRecordAliases
21
-
22
- def run
23
- raise NotImplementedError
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,265 +0,0 @@
1
- require "optparse"
2
- require "pathname"
3
- require "lutaml/uml/interface/base"
4
- require "lutaml/uml/parsers/dsl"
5
- require "lutaml/uml/parsers/yaml"
6
- require "lutaml/uml/parsers/attribute"
7
- require "lutaml/uml/formatter"
8
-
9
- module Lutaml
10
- module Uml
11
- module Interface
12
- class CommandLine < Base
13
- class Error < StandardError; end
14
- class FileError < Error; end
15
- class NotSupportedInputFormat < Error; end
16
-
17
- SUPPORTED_FORMATS = %w[yaml dsl].freeze
18
- DEFAULT_INPUT_FORMAT = "dsl".freeze
19
-
20
- def initialize(attributes = {})
21
- @formatter = Formatter::Graphviz.new
22
- @verbose = false
23
- @option_parser = OptionParser.new
24
-
25
- setup_parser_options
26
-
27
- super
28
- end
29
-
30
- def output_path=(value)
31
- @output_path = determine_output_path_value(value)
32
- end
33
-
34
- def determine_output_path_value(value)
35
- unless value.nil? || @output_path = value.is_a?(Pathname)
36
- return Pathname.new(value.to_s)
37
- end
38
-
39
- value
40
- end
41
-
42
- def paths=(values)
43
- @paths = values.to_a.map { |path| Pathname.new(path) }
44
- end
45
-
46
- def formatter=(value)
47
- value = value.to_s.strip.downcase.to_sym
48
- value = Formatter.find_by(name: value)
49
- raise Error, "Formatter not found: #{value}" if value.nil?
50
-
51
- @formatter = value
52
- end
53
-
54
- def input_format=(value)
55
- if value.nil?
56
- @input_format = DEFAULT_INPUT_FORMAT
57
- return
58
- end
59
-
60
- @input_format = SUPPORTED_FORMATS.detect { |n| n == value }
61
- raise(NotSupportedInputFormat, value) if @input_format.nil?
62
- end
63
-
64
- def run
65
- args = ARGV.dup # TODO: This is hacky
66
- begin
67
- @option_parser.parse!(args)
68
- rescue StandardError
69
- nil
70
- end
71
- setup_parser_formatter_options
72
- @option_parser.parse!
73
-
74
- self.paths = ARGV
75
- @formatter.type = @type
76
-
77
- if @output_path&.file? && @paths.length > 1
78
- raise Error,
79
- 'Output path must be a directory \
80
- if multiple input files are given'
81
- end
82
-
83
- @paths.each do |input_path|
84
- unless input_path.exist?
85
- raise FileError, "File does not exist: #{input_path}"
86
- end
87
-
88
- document = if @input_format == "yaml"
89
- Parsers::Yaml.parse(input_path)
90
- else
91
- Parsers::Dsl.parse(File.new(input_path))
92
- end
93
- result = @formatter.format(document)
94
-
95
- if @output_path
96
- output_path = @output_path
97
- if output_path.directory?
98
- output_path = output_path.join(input_path
99
- .basename(".*").to_s +
100
- ".#{@formatter.type}")
101
- end
102
-
103
- output_path.open("w+") { |file| file.write(result) }
104
- else
105
- puts result
106
- end
107
- end
108
- end
109
-
110
- protected
111
-
112
- def text_bold(body = nil)
113
- text_effect(1, body)
114
- end
115
-
116
- def text_italic(body = nil)
117
- text_effect(3, body)
118
- end
119
-
120
- def text_bold_italic(body = nil)
121
- text_bold(text_italic(body))
122
- end
123
-
124
- def text_underline(body = nil)
125
- text_effect(4, body)
126
- end
127
-
128
- def text_effect(num, body = nil)
129
- result = "\e[#{num}m"
130
- result << "#{body}#{text_reset}" unless body.nil?
131
-
132
- result
133
- end
134
-
135
- def text_reset
136
- "\e[0m"
137
- end
138
-
139
- def setup_parser_options
140
- @option_parser.banner = ""
141
- format_desc = "The output formatter (Default: '#{@formatter.name}')"
142
- @option_parser
143
- .on("-f",
144
- "--formatter VALUE",
145
- format_desc) do |value|
146
- self.formatter = value
147
- end
148
- @option_parser
149
- .on("-t", "--type VALUE", "The output format type") do |value|
150
- @type = value
151
- end
152
- @option_parser
153
- .on("-o", "--output VALUE", "The output path") do |value|
154
- self.output_path = value
155
- end
156
- @option_parser
157
- .on("-i", "--input-format VALUE", "The input format") do |value|
158
- self.input_format = value
159
- end
160
- @option_parser
161
- .on("-h", "--help", "Prints this help") do
162
- print_help
163
- exit
164
- end
165
- end
166
-
167
- def setup_parser_formatter_options
168
- case @formatter.name
169
- when :graphviz
170
- @option_parser.on("-g", "--graph VALUE") do |value|
171
- Parsers::Attribute.parse(value).each do |key, attr_value|
172
- @formatter.graph[key] = attr_value
173
- end
174
- end
175
-
176
- @option_parser.on("-e", "--edge VALUE") do |value|
177
- Parsers::Attribute.parse(value).each do |key, attr_value|
178
- @formatter.edge[key] = attr_value
179
- end
180
- end
181
-
182
- @option_parser.on("-n", "--node VALUE") do |value|
183
- Parsers::Attribute.parse(value).each do |key, attr_value|
184
- @formatter.node[key] = attr_value
185
- end
186
- end
187
-
188
- @option_parser.on("-a", "--all VALUE") do |value|
189
- Parsers::Attribute.parse(value).each do |key, attr_value|
190
- @formatter.graph[key] = attr_value
191
- @formatter.edge[key] = attr_value
192
- @formatter.node[key] = attr_value
193
- end
194
- end
195
- end
196
- end
197
-
198
- def print_help
199
- puts <<~HELP
200
- #{text_bold('Usage:')} lutaml-uml [options] PATHS
201
-
202
- #{text_bold('Overview:')} Generate output from UML Class Diagram language files
203
-
204
- #{text_bold('Options:')}
205
- #{@option_parser}
206
- #{text_bold('Paths:')}
207
-
208
- UCD can accept multiple paths for parsing for easier batch processing.
209
-
210
- The location of the output by default is standard output.
211
-
212
- The output can be directed to a path with #{text_bold_italic('--output')}, which can be a file or a directory.
213
- If the output path is a directory, then the filename will be the same as the input filename,
214
- with it's file extension substituted with the #{text_bold_italic('--type')}.
215
-
216
- #{text_underline('Examples')}
217
-
218
- `lutaml-uml project.lutaml`
219
-
220
- Produces DOT notation, sent to standard output
221
-
222
- `lutaml-uml -o . project.lutaml`
223
-
224
- Produces DOT notation, written to #{text_italic('./project.dot')}
225
-
226
- `lutaml-uml -o ./diagram.dot project.lutaml`
227
-
228
- Produces DOT notation, written to #{text_italic('./diagram.dot')}
229
-
230
- `lutaml-uml -o ./diagram.png project.lutaml`
231
-
232
- Produces PNG image, written to #{text_italic('./diagram.png')}
233
-
234
- `lutaml-uml -t png -o . project.lutaml`
235
-
236
- Produces PNG image, written to #{text_italic('./project.png')}
237
-
238
- `lutaml-uml -t png -o . project.lutaml-uml core_ext.lutaml`
239
-
240
- Produces PNG images, written to #{text_italic('./project.png')} and #{text_italic('./core_ext.png')}
241
-
242
- #{text_bold('Formatters:')}
243
-
244
- #{text_underline('Graphviz')}
245
-
246
- Generates DOT notation and can use the DOT notation to generate any format Graphviz can produce.
247
-
248
- The output format is based on #{text_bold_italic('--type')}, which by default is "dot".
249
- If #{text_bold_italic('--type')} is not given and #{text_bold_italic('--output')} is, the file extension of the #{text_bold_italic('--output')} path will be used.
250
-
251
- Valid types/extensions are: #{Formatter::Graphviz::VALID_TYPES.join(', ')}
252
-
253
- #{text_bold('Options:')}
254
-
255
- -g, --graph VALUE The graph attributes
256
- -e, --edge VALUE The edge attributes
257
- -n, --node VALUE The node attributes
258
- -a, --all VALUE Set attributes for graph, edge, and node
259
-
260
- HELP
261
- end
262
- end
263
- end
264
- end
265
- end