xsdvi 1.0.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 +7 -0
- data/LICENSE +30 -0
- data/README.adoc +317 -0
- data/exe/xsdvi +6 -0
- data/lib/xsdvi/cli.rb +163 -0
- data/lib/xsdvi/svg/generator.rb +93 -0
- data/lib/xsdvi/svg/symbol.rb +234 -0
- data/lib/xsdvi/svg/symbols/all.rb +46 -0
- data/lib/xsdvi/svg/symbols/any.rb +59 -0
- data/lib/xsdvi/svg/symbols/any_attribute.rb +58 -0
- data/lib/xsdvi/svg/symbols/attribute.rb +64 -0
- data/lib/xsdvi/svg/symbols/choice.rb +46 -0
- data/lib/xsdvi/svg/symbols/element.rb +91 -0
- data/lib/xsdvi/svg/symbols/field.rb +42 -0
- data/lib/xsdvi/svg/symbols/key.rb +46 -0
- data/lib/xsdvi/svg/symbols/keyref.rb +49 -0
- data/lib/xsdvi/svg/symbols/loop.rb +35 -0
- data/lib/xsdvi/svg/symbols/schema.rb +42 -0
- data/lib/xsdvi/svg/symbols/selector.rb +42 -0
- data/lib/xsdvi/svg/symbols/sequence.rb +48 -0
- data/lib/xsdvi/svg/symbols/unique.rb +46 -0
- data/lib/xsdvi/tree/builder.rb +31 -0
- data/lib/xsdvi/tree/element.rb +62 -0
- data/lib/xsdvi/utils/resource_loader.rb +21 -0
- data/lib/xsdvi/utils/width_calculator.rb +23 -0
- data/lib/xsdvi/utils/writer.rb +29 -0
- data/lib/xsdvi/version.rb +5 -0
- data/lib/xsdvi/xsd_handler.rb +323 -0
- data/lib/xsdvi.rb +30 -0
- data/resources/svg/defined_symbols.svg +9 -0
- data/resources/svg/doctype.txt +1 -0
- data/resources/svg/menu_buttons.svg +7 -0
- data/resources/svg/script.js +265 -0
- data/resources/svg/style.css +29 -0
- data/resources/svg/style.html +3 -0
- data/resources/svg/style.xml +1 -0
- data/resources/svg/svg_end.txt +1 -0
- data/resources/svg/svg_start.txt +1 -0
- data/resources/svg/title.txt +1 -0
- data/resources/svg/xml_declaration.xml +1 -0
- metadata +113 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../symbol"
|
|
4
|
+
|
|
5
|
+
module Xsdvi
|
|
6
|
+
module SVG
|
|
7
|
+
module Symbols
|
|
8
|
+
# Symbol for XSD keyref identity constraint
|
|
9
|
+
class Keyref < Symbol
|
|
10
|
+
attr_accessor :name, :namespace, :refer
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
super
|
|
14
|
+
@name = nil
|
|
15
|
+
@namespace = nil
|
|
16
|
+
@refer = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def draw
|
|
20
|
+
process_description
|
|
21
|
+
draw_g_start
|
|
22
|
+
print("<rect class='shadow' x='3' y='3' width='#{width}' " \
|
|
23
|
+
"height='#{height}' rx='9'/>")
|
|
24
|
+
print("<rect class='boxkeyref' x='0' y='0' width='#{width}' " \
|
|
25
|
+
"height='#{height}' rx='9'/>")
|
|
26
|
+
print("<text class='visible' x='5' y='13'>#{namespace}</text>") if namespace
|
|
27
|
+
print("<text class='strong' x='5' y='27'>keyref: #{name}</text>") if name
|
|
28
|
+
print("<text class='visible' x='5' y='41'>refer: #{refer}</text>") if refer
|
|
29
|
+
draw_description(41)
|
|
30
|
+
draw_connection
|
|
31
|
+
draw_use
|
|
32
|
+
draw_g_end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def calculate_width
|
|
36
|
+
calc = Utils::WidthCalculator.new(MIN_WIDTH)
|
|
37
|
+
calc.new_width(15, name, 8)
|
|
38
|
+
calc.new_width(15, namespace)
|
|
39
|
+
calc.new_width(15, refer, 7)
|
|
40
|
+
calc.width
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def calculate_height
|
|
44
|
+
MAX_HEIGHT
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../symbol"
|
|
4
|
+
|
|
5
|
+
module Xsdvi
|
|
6
|
+
module SVG
|
|
7
|
+
module Symbols
|
|
8
|
+
# Symbol for recursive loop references
|
|
9
|
+
class Loop < Symbol
|
|
10
|
+
def draw
|
|
11
|
+
draw_g_start
|
|
12
|
+
print("<rect class='boxloop' x='0' y='12' width='#{width}' " \
|
|
13
|
+
"height='#{height}' rx='9'/>")
|
|
14
|
+
print("<polygon class='filled' points='#{(width / 2) + 3},8 " \
|
|
15
|
+
"#{(width / 2) - 2},12 #{(width / 2) + 3},17'/>")
|
|
16
|
+
print("<polygon class='filled' points='#{width - 5},24 " \
|
|
17
|
+
"#{width},19 #{width + 5},24'/>")
|
|
18
|
+
print("<text x='10' y='27'>LOOP</text>")
|
|
19
|
+
draw_connection
|
|
20
|
+
draw_g_end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def calculate_width
|
|
24
|
+
calc = Utils::WidthCalculator.new(MIN_WIDTH)
|
|
25
|
+
calc.new_width(25, 4)
|
|
26
|
+
calc.width
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def calculate_height
|
|
30
|
+
MIN_HEIGHT
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../symbol"
|
|
4
|
+
|
|
5
|
+
module Xsdvi
|
|
6
|
+
module SVG
|
|
7
|
+
module Symbols
|
|
8
|
+
# Symbol for XSD schema root
|
|
9
|
+
class Schema < Symbol
|
|
10
|
+
def prepare_box
|
|
11
|
+
# Schema root positioning
|
|
12
|
+
@x_position = 20
|
|
13
|
+
@y_position = 50
|
|
14
|
+
@width = calculate_width
|
|
15
|
+
@height = calculate_height
|
|
16
|
+
|
|
17
|
+
# Set highest to 50 so children start at 50
|
|
18
|
+
# Must use Symbol.highest_y_position, not self.class
|
|
19
|
+
Symbol.highest_y_position = 50
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def draw
|
|
23
|
+
draw_g_start
|
|
24
|
+
print("<rect class='boxschema' x='0' y='12' width='#{width}' height='#{height}'/>")
|
|
25
|
+
print("<text x='5' y='27'><tspan class='big'>/ </tspan>schema</text>")
|
|
26
|
+
draw_use
|
|
27
|
+
draw_g_end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def calculate_width
|
|
31
|
+
calc = Utils::WidthCalculator.new(MIN_WIDTH)
|
|
32
|
+
calc.new_width(15, 8)
|
|
33
|
+
calc.width
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def calculate_height
|
|
37
|
+
MIN_HEIGHT
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../symbol"
|
|
4
|
+
|
|
5
|
+
module Xsdvi
|
|
6
|
+
module SVG
|
|
7
|
+
module Symbols
|
|
8
|
+
# Symbol for XSD selector
|
|
9
|
+
class Selector < Symbol
|
|
10
|
+
attr_accessor :xpath
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
super
|
|
14
|
+
@xpath = nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def draw
|
|
18
|
+
draw_g_start
|
|
19
|
+
print("<rect class='shadow' x='3' y='3' width='#{width}' " \
|
|
20
|
+
"height='#{height}' rx='9'/>")
|
|
21
|
+
print("<rect class='boxselector' x='0' y='0' width='#{width}' " \
|
|
22
|
+
"height='#{height}' rx='9'/>")
|
|
23
|
+
print("<text class='strong' x='5' y='13'>selector</text>")
|
|
24
|
+
print("<text class='visible' x='5' y='27'>#{xpath}</text>") if xpath
|
|
25
|
+
draw_connection
|
|
26
|
+
draw_g_end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def calculate_width
|
|
30
|
+
calc = Utils::WidthCalculator.new(MIN_WIDTH)
|
|
31
|
+
calc.new_width(15, 8)
|
|
32
|
+
calc.new_width(15, xpath)
|
|
33
|
+
calc.width
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def calculate_height
|
|
37
|
+
MID_HEIGHT
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../symbol"
|
|
4
|
+
|
|
5
|
+
module Xsdvi
|
|
6
|
+
module SVG
|
|
7
|
+
module Symbols
|
|
8
|
+
# Symbol for XSD sequence compositor
|
|
9
|
+
class Sequence < Symbol
|
|
10
|
+
attr_accessor :cardinality
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
super
|
|
14
|
+
@cardinality = nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def draw
|
|
18
|
+
process_description
|
|
19
|
+
draw_g_start
|
|
20
|
+
print("<rect class='boxcompositor' x='0' y='8' width='#{width}' " \
|
|
21
|
+
"height='#{height}' rx='9'/>")
|
|
22
|
+
print("<circle cx='#{(width / 2) + 12}' cy='14' r='2'/>")
|
|
23
|
+
print("<circle cx='#{(width / 2) + 12}' cy='23' r='2'/>")
|
|
24
|
+
print("<circle cx='#{(width / 2) + 12}' cy='32' r='2'/>")
|
|
25
|
+
print("<text class='small' x='#{width / 2}' y='17'>1</text>")
|
|
26
|
+
print("<text class='small' x='#{width / 2}' y='26'>2</text>")
|
|
27
|
+
print("<text class='small' x='#{width / 2}' y='35'>3</text>")
|
|
28
|
+
print("<line x1='#{(width / 2) + 12}' y1='14' x2='#{(width / 2) + 12}' y2='32'/>")
|
|
29
|
+
print("<text x='5' y='52'>#{cardinality}</text>") if cardinality
|
|
30
|
+
draw_description(52)
|
|
31
|
+
draw_connection
|
|
32
|
+
draw_use
|
|
33
|
+
draw_g_end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def calculate_width
|
|
37
|
+
calc = Utils::WidthCalculator.new(MIN_WIDTH)
|
|
38
|
+
calc.new_width(15, cardinality)
|
|
39
|
+
calc.width
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def calculate_height
|
|
43
|
+
MID_HEIGHT
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../symbol"
|
|
4
|
+
|
|
5
|
+
module Xsdvi
|
|
6
|
+
module SVG
|
|
7
|
+
module Symbols
|
|
8
|
+
# Symbol for XSD unique identity constraint
|
|
9
|
+
class Unique < Symbol
|
|
10
|
+
attr_accessor :name, :namespace
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
super
|
|
14
|
+
@name = nil
|
|
15
|
+
@namespace = nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def draw
|
|
19
|
+
process_description
|
|
20
|
+
draw_g_start
|
|
21
|
+
print("<rect class='shadow' x='3' y='3' width='#{width}' " \
|
|
22
|
+
"height='#{height}' rx='9'/>")
|
|
23
|
+
print("<rect class='boxunique' x='0' y='0' width='#{width}' " \
|
|
24
|
+
"height='#{height}' rx='9'/>")
|
|
25
|
+
print("<text class='visible' x='5' y='13'>#{namespace}</text>") if namespace
|
|
26
|
+
print("<text class='strong' x='5' y='27'>unique: #{name}</text>") if name
|
|
27
|
+
draw_description(27)
|
|
28
|
+
draw_connection
|
|
29
|
+
draw_use
|
|
30
|
+
draw_g_end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def calculate_width
|
|
34
|
+
calc = Utils::WidthCalculator.new(MIN_WIDTH)
|
|
35
|
+
calc.new_width(15, name, 8)
|
|
36
|
+
calc.new_width(15, namespace)
|
|
37
|
+
calc.width
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def calculate_height
|
|
41
|
+
MID_HEIGHT
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Xsdvi
|
|
4
|
+
module Tree
|
|
5
|
+
# Builds a tree structure
|
|
6
|
+
class Builder
|
|
7
|
+
attr_accessor :root
|
|
8
|
+
attr_reader :parent
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@parent = nil
|
|
12
|
+
@root = nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def append_child(child)
|
|
16
|
+
parent.add_child(child)
|
|
17
|
+
child.parent = parent
|
|
18
|
+
@parent = child
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def level_up
|
|
22
|
+
@parent = parent.parent
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def set_root(new_root)
|
|
26
|
+
@parent = new_root
|
|
27
|
+
@root = new_root
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Xsdvi
|
|
4
|
+
module Tree
|
|
5
|
+
# Represents a node in the tree structure
|
|
6
|
+
class Element
|
|
7
|
+
attr_accessor :parent
|
|
8
|
+
attr_reader :children
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@parent = nil
|
|
12
|
+
@children = []
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def index
|
|
16
|
+
return 1 unless parent?
|
|
17
|
+
|
|
18
|
+
parent.children.index(self) + 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def parent?
|
|
22
|
+
!parent.nil?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def last_child
|
|
26
|
+
children.last
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def last_child?
|
|
30
|
+
return true unless parent?
|
|
31
|
+
|
|
32
|
+
parent.children.last == self
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def first_child?
|
|
36
|
+
return true unless parent?
|
|
37
|
+
|
|
38
|
+
parent.children.first == self
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def add_child(child)
|
|
42
|
+
children << child
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def children?
|
|
46
|
+
!children.empty?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def code
|
|
50
|
+
buffer = []
|
|
51
|
+
element = self
|
|
52
|
+
while element.parent?
|
|
53
|
+
buffer.unshift(element.index)
|
|
54
|
+
buffer.unshift("_")
|
|
55
|
+
element = element.parent
|
|
56
|
+
end
|
|
57
|
+
buffer.unshift("_1")
|
|
58
|
+
buffer.join
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Xsdvi
|
|
4
|
+
module Utils
|
|
5
|
+
# Helper class for loading resource files
|
|
6
|
+
class ResourceLoader
|
|
7
|
+
def read_resource_file(resource_file)
|
|
8
|
+
resource_path = File.join(
|
|
9
|
+
File.dirname(__FILE__),
|
|
10
|
+
"../../..",
|
|
11
|
+
"resources",
|
|
12
|
+
resource_file,
|
|
13
|
+
)
|
|
14
|
+
File.read(resource_path)
|
|
15
|
+
rescue Errno::ENOENT => e
|
|
16
|
+
warn "Resource file not found: #{resource_path}"
|
|
17
|
+
raise e
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Xsdvi
|
|
4
|
+
module Utils
|
|
5
|
+
# Calculates width for SVG elements based on text content
|
|
6
|
+
class WidthCalculator
|
|
7
|
+
attr_reader :width
|
|
8
|
+
|
|
9
|
+
def initialize(min_width)
|
|
10
|
+
@width = min_width
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def new_width(char_width, text, additional = 0)
|
|
14
|
+
return unless text
|
|
15
|
+
|
|
16
|
+
text_length = text.is_a?(String) ? text.length : text
|
|
17
|
+
calculated_width = char_width + (text_length * 6) + additional
|
|
18
|
+
|
|
19
|
+
@width = calculated_width if calculated_width > @width
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Xsdvi
|
|
4
|
+
module Utils
|
|
5
|
+
# Helper class for writing output files
|
|
6
|
+
class Writer
|
|
7
|
+
DEFAULT_CHARSET = "UTF-8"
|
|
8
|
+
|
|
9
|
+
attr_reader :writer
|
|
10
|
+
|
|
11
|
+
def initialize(uri = nil, charset_name = DEFAULT_CHARSET)
|
|
12
|
+
new_writer(uri, charset_name) if uri
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def close
|
|
16
|
+
writer&.close
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def append(content)
|
|
20
|
+
writer&.write(content)
|
|
21
|
+
writer
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def new_writer(uri, charset_name = DEFAULT_CHARSET)
|
|
25
|
+
@writer = File.open(uri, "w:#{charset_name}")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|