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
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: cbb88134a26f0713dea31aa8032d38e06fc8fe5e9b04b321211dd86fac4eadb5
|
|
4
|
+
data.tar.gz: 21cf471f50d28f47267af0cdd85a3733941e3dd23026389dd21b23fbfc6a7330
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6c7d8578f22756bd8ae89f9f516da49a02ce926579a05fff307d244a47f8ff33dfc595c60d0fec04ba94412f722bad879da8500043f7af89bea870f10ad2ffff
|
|
7
|
+
data.tar.gz: 4a74687246d90e2136311111f5046fd768f9347115e2f22cb517adb922c932ca0c508efa0b5fa8ecf0cc8d09e671781b29f85594b31b52836baec98c58e9c76d
|
data/LICENSE
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Copyright (c) Ribose Inc. All rights reserved.
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
|
4
|
+
modification, are permitted provided that the following conditions
|
|
5
|
+
are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
11
|
+
notice, this list of conditions and the following disclaimer in
|
|
12
|
+
the documentation and/or other materials provided with the
|
|
13
|
+
distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of Ribose nor the names of its contributors may
|
|
16
|
+
be used to endorse or promote products derived from this software
|
|
17
|
+
without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
20
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
21
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
22
|
+
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
23
|
+
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
24
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
25
|
+
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
26
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
28
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
29
|
+
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
30
|
+
POSSIBILITY OF SUCH DAMAGE.
|
data/README.adoc
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
= XSDVI Ruby
|
|
2
|
+
|
|
3
|
+
image:https://img.shields.io/gem/v/xsdvi.svg[Gem Version]
|
|
4
|
+
image:https://img.shields.io/badge/license-MIT-blue.svg[License]
|
|
5
|
+
|
|
6
|
+
== Purpose
|
|
7
|
+
|
|
8
|
+
XSDVI (XML Schema Definition Visualizer) is a Ruby gem that transforms W3C XML
|
|
9
|
+
Schema (XSD) files into interactive, hierarchical SVG diagrams. It provides a
|
|
10
|
+
visual representation of complex XML Schema structures, making it easier to
|
|
11
|
+
understand schema relationships, element hierarchies, attribute requirements,
|
|
12
|
+
and data type definitions.
|
|
13
|
+
|
|
14
|
+
The tool parses XSD files and generates SVG diagrams that display:
|
|
15
|
+
|
|
16
|
+
* Element structures with their types, cardinality, and attributes
|
|
17
|
+
* Compositor relationships (sequence, choice, all)
|
|
18
|
+
* Type hierarchies and inheritance
|
|
19
|
+
* Identity constraints (key, keyref, unique)
|
|
20
|
+
* Namespace information
|
|
21
|
+
* Documentation annotations from the schema
|
|
22
|
+
* Recursive references with loop detection
|
|
23
|
+
|
|
24
|
+
This is a pure Ruby port of the original Java XsdVi tool, providing the same
|
|
25
|
+
functionality with modern Ruby idioms and gemification for easy integration into
|
|
26
|
+
Ruby projects.
|
|
27
|
+
|
|
28
|
+
== Features
|
|
29
|
+
|
|
30
|
+
=== XSD Component Visualization
|
|
31
|
+
|
|
32
|
+
* Elements and Attributes: Visual boxes showing element names, types, cardinality (min..max occurrences), required/optional status, and namespace information
|
|
33
|
+
* Compositors: Graphical representation of sequence (ordered), choice (alternatives), and all (unordered) element groups
|
|
34
|
+
* Wildcards: Display of `<any>` and `<anyAttribute>` with namespace constraints and processing modes
|
|
35
|
+
* Identity Constraints: Visualization of key, keyref, unique constraints with their selectors and fields
|
|
36
|
+
* Type Information: Display of simple and complex type definitions, base types, and anonymous types
|
|
37
|
+
|
|
38
|
+
=== Interactive SVG Output
|
|
39
|
+
|
|
40
|
+
* Hierarchical Layout: Tree-structure visualization with proper indentation and connections
|
|
41
|
+
* Collapsible/Expandable: JavaScript-enabled expand/collapse functionality for complex schemas (optional)
|
|
42
|
+
* Clickable Elements: Navigate between related schema components
|
|
43
|
+
* Documentation Display: Inline display of `<xs:documentation>` annotations
|
|
44
|
+
* Color-coded Symbols: Different visual styles for elements, attributes, compositors, and constraints
|
|
45
|
+
|
|
46
|
+
=== Flexible Output Options
|
|
47
|
+
|
|
48
|
+
* Single Diagram: Generate one SVG showing the entire schema or a specific root element
|
|
49
|
+
* Per-Element Diagrams: Generate separate SVG files for each top-level element
|
|
50
|
+
* Custom Styling: Embed CSS in SVG files or use external stylesheets
|
|
51
|
+
* Output Directory: Organize generated diagrams in custom folder structures
|
|
52
|
+
|
|
53
|
+
=== Processing Capabilities
|
|
54
|
+
|
|
55
|
+
* Multiple XSD Files: Process multiple schema files in a single run
|
|
56
|
+
* Loop Detection: Automatically detects and marks recursive element references
|
|
57
|
+
* Namespace Handling: Properly displays and distinguishes multiple namespaces
|
|
58
|
+
* Documentation Extraction: Extracts and formats XSD documentation for display
|
|
59
|
+
* Large Schema Support: Handles complex, real-world schemas with hundreds of elements
|
|
60
|
+
|
|
61
|
+
== Installation
|
|
62
|
+
|
|
63
|
+
Add this line to your application's Gemfile:
|
|
64
|
+
|
|
65
|
+
[source,ruby]
|
|
66
|
+
----
|
|
67
|
+
gem 'xsdvi'
|
|
68
|
+
----
|
|
69
|
+
|
|
70
|
+
And then execute:
|
|
71
|
+
|
|
72
|
+
[source,shell]
|
|
73
|
+
----
|
|
74
|
+
bundle install
|
|
75
|
+
----
|
|
76
|
+
|
|
77
|
+
Or install it yourself as:
|
|
78
|
+
|
|
79
|
+
[source,shell]
|
|
80
|
+
----
|
|
81
|
+
gem install xsdvi
|
|
82
|
+
----
|
|
83
|
+
|
|
84
|
+
== Usage
|
|
85
|
+
|
|
86
|
+
=== Basic usage
|
|
87
|
+
|
|
88
|
+
Generate an SVG diagram from an XSD file:
|
|
89
|
+
|
|
90
|
+
[source,shell]
|
|
91
|
+
----
|
|
92
|
+
xsdvi generate schema.xsd
|
|
93
|
+
----
|
|
94
|
+
|
|
95
|
+
This creates `schema.svg` in the current directory, showing all top-level
|
|
96
|
+
elements and their hierarchical structure.
|
|
97
|
+
|
|
98
|
+
=== Generate diagram for specific root element
|
|
99
|
+
|
|
100
|
+
[source,shell]
|
|
101
|
+
----
|
|
102
|
+
xsdvi generate schema.xsd -r UnitsML
|
|
103
|
+
----
|
|
104
|
+
|
|
105
|
+
This generates a diagram starting from the `UnitsML` element, showing its
|
|
106
|
+
complete structure and all nested elements.
|
|
107
|
+
|
|
108
|
+
=== Generate separate SVG for each element
|
|
109
|
+
|
|
110
|
+
[source,shell]
|
|
111
|
+
----
|
|
112
|
+
xsdvi generate schema.xsd -r all -o -p output/diagrams
|
|
113
|
+
----
|
|
114
|
+
|
|
115
|
+
This creates individual SVG files for each top-level element in the
|
|
116
|
+
`output/diagrams` directory.
|
|
117
|
+
|
|
118
|
+
=== Command-line options
|
|
119
|
+
|
|
120
|
+
`-r, --root-node-name NAME`::
|
|
121
|
+
Specify the schema root element name to visualize. Use "all" to generate
|
|
122
|
+
diagrams for all top-level elements. If omitted, generates a complete schema
|
|
123
|
+
diagram showing all elements.
|
|
124
|
+
|
|
125
|
+
`-o, --one-node-only`::
|
|
126
|
+
Generate diagram showing only the specified element without its children
|
|
127
|
+
(single-level view). Automatically enabled when using `-r all`. This mode hides
|
|
128
|
+
the expand/collapse control buttons.
|
|
129
|
+
|
|
130
|
+
`-p, --output-path PATH`::
|
|
131
|
+
Specify output directory for generated SVG files. The tool automatically creates
|
|
132
|
+
the directory if it doesn't exist. If omitted, files are created in the current
|
|
133
|
+
directory.
|
|
134
|
+
|
|
135
|
+
`--embody-style`::
|
|
136
|
+
Embed CSS styling directly in each SVG file (default: true). This creates
|
|
137
|
+
self-contained SVG files that display correctly without external dependencies.
|
|
138
|
+
|
|
139
|
+
`--generate-style FILE`::
|
|
140
|
+
Generate an external CSS file with the specified name and reference it from SVG
|
|
141
|
+
files. Useful when generating multiple diagrams that should share styling.
|
|
142
|
+
|
|
143
|
+
`--use-style URL`::
|
|
144
|
+
Reference an existing external CSS file at the specified URL in generated SVG
|
|
145
|
+
files. The CSS file must be accessible when the SVG is viewed.
|
|
146
|
+
|
|
147
|
+
=== Examples
|
|
148
|
+
|
|
149
|
+
.Generate full schema diagram with root element
|
|
150
|
+
[example]
|
|
151
|
+
====
|
|
152
|
+
[source,shell]
|
|
153
|
+
----
|
|
154
|
+
xsdvi generate UnitsML-v1.0.xsd -r UnitsML
|
|
155
|
+
----
|
|
156
|
+
|
|
157
|
+
Creates `UnitsML.svg` showing the complete structure starting from the UnitsML
|
|
158
|
+
root element, including all nested elements, attributes, and constraints.
|
|
159
|
+
====
|
|
160
|
+
|
|
161
|
+
.Generate diagram for single element only
|
|
162
|
+
[example]
|
|
163
|
+
====
|
|
164
|
+
[source,shell]
|
|
165
|
+
----
|
|
166
|
+
xsdvi generate UnitsML-v1.0.xsd -r Quantity -o
|
|
167
|
+
----
|
|
168
|
+
|
|
169
|
+
Creates `Quantity.svg` showing only the Quantity element definition without
|
|
170
|
+
expanding its children, useful for focused documentation.
|
|
171
|
+
====
|
|
172
|
+
|
|
173
|
+
.Generate separate diagrams for all top-level elements
|
|
174
|
+
[example]
|
|
175
|
+
====
|
|
176
|
+
[source,shell]
|
|
177
|
+
----
|
|
178
|
+
xsdvi generate UnitsML-v1.0.xsd -r all -o -p images/SVG
|
|
179
|
+
----
|
|
180
|
+
|
|
181
|
+
Creates individual SVG files (`Quantity.svg`, `Unit.svg`, etc.) in the
|
|
182
|
+
`images/SVG` directory, one for each top-level element in the schema.
|
|
183
|
+
====
|
|
184
|
+
|
|
185
|
+
.Generate diagram using external CSS
|
|
186
|
+
[example]
|
|
187
|
+
====
|
|
188
|
+
[source,shell]
|
|
189
|
+
----
|
|
190
|
+
xsdvi generate schema.xsd --generate-style custom.css -p output
|
|
191
|
+
----
|
|
192
|
+
|
|
193
|
+
Creates `output/schema.svg` and `output/custom.css`, with the SVG referencing
|
|
194
|
+
the external stylesheet. Useful for customizing diagram appearance.
|
|
195
|
+
====
|
|
196
|
+
|
|
197
|
+
== Architecture
|
|
198
|
+
|
|
199
|
+
=== Core components
|
|
200
|
+
|
|
201
|
+
TreeElement and TreeBuilder:: Manage the tree structure representing the XSD
|
|
202
|
+
schema hierarchy. TreeElement provides parent-child relationships, traversal
|
|
203
|
+
methods, and unique node identification.
|
|
204
|
+
|
|
205
|
+
XsdHandler:: Parses XSD files using Nokogiri and builds the symbol tree
|
|
206
|
+
structure. Handles all XSD constructs including elements, attributes,
|
|
207
|
+
compositors, wildcards, and identity constraints. Performs loop detection for
|
|
208
|
+
recursive schemas.
|
|
209
|
+
|
|
210
|
+
Symbol classes::
|
|
211
|
+
14 specialized symbol types representing different XSD constructs:
|
|
212
|
+
+
|
|
213
|
+
* Element, Attribute - schema components
|
|
214
|
+
* Choice, Sequence, All - compositors
|
|
215
|
+
* Any, AnyAttribute - wildcards
|
|
216
|
+
* Key, Keyref, Unique - identity constraints
|
|
217
|
+
* Selector, Field - constraint components
|
|
218
|
+
* Loop - recursive reference indicator
|
|
219
|
+
* Schema - root container
|
|
220
|
+
|
|
221
|
+
SVG::Generator:: Generates SVG output files from the symbol tree. Manages
|
|
222
|
+
layout, styling, resource loading, and recursive symbol drawing. Produces
|
|
223
|
+
interactive diagrams with JavaScript-enabled expand/collapse functionality.
|
|
224
|
+
|
|
225
|
+
CLI:: Thor-based command-line interface providing easy access to all generation
|
|
226
|
+
options with built-in help and validation.
|
|
227
|
+
|
|
228
|
+
=== Data flow
|
|
229
|
+
|
|
230
|
+
[source]
|
|
231
|
+
----
|
|
232
|
+
XSD File → XsdHandler (Nokogiri parsing)
|
|
233
|
+
↓
|
|
234
|
+
Symbol Tree (TreeBuilder)
|
|
235
|
+
↓
|
|
236
|
+
Symbol Processing (prepare_box, calculate dimensions)
|
|
237
|
+
↓
|
|
238
|
+
SVG Generation (Generator.draw)
|
|
239
|
+
↓
|
|
240
|
+
SVG File Output
|
|
241
|
+
----
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
== Differences from Java version
|
|
245
|
+
|
|
246
|
+
=== Text wrapping
|
|
247
|
+
|
|
248
|
+
The Ruby implementation uses a custom text wrapping algorithm that produces
|
|
249
|
+
slightly different line breaks compared to Apache Commons Text
|
|
250
|
+
`WordUtils.wrap()`. The Ruby version optimizes for keeping related content
|
|
251
|
+
together when it fits within the line width, while maintaining valid XML
|
|
252
|
+
structure.
|
|
253
|
+
|
|
254
|
+
Impact: Documentation text may wrap at different character positions, but
|
|
255
|
+
the visual output and functionality remain identical. The Ruby version ensures
|
|
256
|
+
HTML tags and entities in documentation are not broken across lines, improving
|
|
257
|
+
SVG validity.
|
|
258
|
+
|
|
259
|
+
Example:
|
|
260
|
+
|
|
261
|
+
Java may break HTML tags mid-structure:
|
|
262
|
+
|
|
263
|
+
[source,xml]
|
|
264
|
+
----
|
|
265
|
+
<text>See <a</text>
|
|
266
|
+
<text>href="...">text</a>.</text>
|
|
267
|
+
----
|
|
268
|
+
|
|
269
|
+
Ruby keeps tags together for better validity:
|
|
270
|
+
|
|
271
|
+
[source,xml]
|
|
272
|
+
----
|
|
273
|
+
<text>See <a href="...">text</a>.</text>
|
|
274
|
+
----
|
|
275
|
+
|
|
276
|
+
Both outputs are functionally equivalent and render correctly in SVG viewers.
|
|
277
|
+
The Ruby approach actually produces more semantically correct output by
|
|
278
|
+
preserving the integrity of embedded HTML elements.
|
|
279
|
+
|
|
280
|
+
== Development
|
|
281
|
+
|
|
282
|
+
After checking out the repo, run `bundle install` to install dependencies.
|
|
283
|
+
|
|
284
|
+
Run tests:
|
|
285
|
+
|
|
286
|
+
[source,shell]
|
|
287
|
+
----
|
|
288
|
+
bundle exec rspec
|
|
289
|
+
----
|
|
290
|
+
|
|
291
|
+
Run rubocop:
|
|
292
|
+
|
|
293
|
+
[source,shell]
|
|
294
|
+
----
|
|
295
|
+
bundle exec rubocop
|
|
296
|
+
----
|
|
297
|
+
|
|
298
|
+
== Contributing
|
|
299
|
+
|
|
300
|
+
Bug reports and pull requests are welcome on GitHub at
|
|
301
|
+
https://github.com/metanorma/xsdvi-ruby
|
|
302
|
+
|
|
303
|
+
== Copyright and license
|
|
304
|
+
|
|
305
|
+
Copyright https://www.ribose.com[Ribose Inc.]
|
|
306
|
+
|
|
307
|
+
The gem is available as open source under the Ribose 3-Clause BSD License.
|
|
308
|
+
|
|
309
|
+
== Acknowledgments
|
|
310
|
+
|
|
311
|
+
This is a Ruby port of the Metanorma version of the XsdVi tool, which is itself
|
|
312
|
+
a fork of the original XsdVi Java tool created by Václav Slavìtínský. See the
|
|
313
|
+
original project at https://sourceforge.net/projects/xsdvi/
|
|
314
|
+
|
|
315
|
+
The Ruby port maintains compatibility with the Java version's output format
|
|
316
|
+
while providing a pure Ruby implementation suitable for modern Ruby applications
|
|
317
|
+
and workflows.
|
data/exe/xsdvi
ADDED
data/lib/xsdvi/cli.rb
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "thor"
|
|
4
|
+
|
|
5
|
+
module Xsdvi
|
|
6
|
+
# Command-line interface for XSDVI
|
|
7
|
+
class CLI < Thor
|
|
8
|
+
def self.exit_on_failure?
|
|
9
|
+
true
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
desc "generate INPUT [INPUT2...] [OPTIONS]",
|
|
13
|
+
"Generate SVG diagrams from XSD schema files"
|
|
14
|
+
method_option :root_node_name,
|
|
15
|
+
type: :string,
|
|
16
|
+
aliases: "-r",
|
|
17
|
+
desc: "Schema root node name (or 'all' for all elements)"
|
|
18
|
+
method_option :one_node_only,
|
|
19
|
+
type: :boolean,
|
|
20
|
+
aliases: "-o",
|
|
21
|
+
desc: "Show only one element"
|
|
22
|
+
method_option :output_path,
|
|
23
|
+
type: :string,
|
|
24
|
+
aliases: "-p",
|
|
25
|
+
desc: "Output folder path"
|
|
26
|
+
method_option :embody_style,
|
|
27
|
+
type: :boolean,
|
|
28
|
+
default: true,
|
|
29
|
+
desc: "Embody CSS style in SVG (default: true)"
|
|
30
|
+
method_option :generate_style,
|
|
31
|
+
type: :string,
|
|
32
|
+
desc: "Generate CSS file with specified name"
|
|
33
|
+
method_option :use_style,
|
|
34
|
+
type: :string,
|
|
35
|
+
desc: "Use external CSS file at specified URL"
|
|
36
|
+
def generate(*inputs)
|
|
37
|
+
if inputs.empty?
|
|
38
|
+
puts "Error: No input files specified"
|
|
39
|
+
exit(1)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Validate input files exist
|
|
43
|
+
inputs.each do |input|
|
|
44
|
+
unless File.exist?(input)
|
|
45
|
+
puts "Error: XSD file '#{input}' not found!"
|
|
46
|
+
exit(1)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Process options
|
|
51
|
+
root_node_name = options[:root_node_name]
|
|
52
|
+
one_node_only = options[:one_node_only]
|
|
53
|
+
one_node_only = true if root_node_name == "all"
|
|
54
|
+
output_path = options[:output_path]
|
|
55
|
+
|
|
56
|
+
# Determine style mode
|
|
57
|
+
style_mode = determine_style_mode(options)
|
|
58
|
+
|
|
59
|
+
# Process each input file
|
|
60
|
+
builder = Tree::Builder.new
|
|
61
|
+
xsd_handler = XsdHandler.new(builder)
|
|
62
|
+
writer_helper = Utils::Writer.new
|
|
63
|
+
svg_generator = SVG::Generator.new(writer_helper)
|
|
64
|
+
|
|
65
|
+
svg_generator.hide_menu_buttons = one_node_only
|
|
66
|
+
|
|
67
|
+
apply_style_settings(svg_generator, style_mode, options)
|
|
68
|
+
|
|
69
|
+
inputs.each do |input|
|
|
70
|
+
process_input_file(
|
|
71
|
+
input,
|
|
72
|
+
xsd_handler,
|
|
73
|
+
svg_generator,
|
|
74
|
+
builder,
|
|
75
|
+
writer_helper,
|
|
76
|
+
root_node_name,
|
|
77
|
+
one_node_only,
|
|
78
|
+
output_path,
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
default_task :generate
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def determine_style_mode(options)
|
|
88
|
+
return :generate_style if options[:generate_style]
|
|
89
|
+
return :use_style if options[:use_style]
|
|
90
|
+
|
|
91
|
+
:embody_style
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def apply_style_settings(svg_generator, style_mode, options)
|
|
95
|
+
case style_mode
|
|
96
|
+
when :embody_style
|
|
97
|
+
puts "The style will be embodied"
|
|
98
|
+
svg_generator.embody_style = true
|
|
99
|
+
when :generate_style
|
|
100
|
+
style_url = options[:generate_style]
|
|
101
|
+
puts "Generating style #{style_url}..."
|
|
102
|
+
svg_generator.embody_style = false
|
|
103
|
+
svg_generator.style_uri = style_url
|
|
104
|
+
svg_generator.print_extern_style
|
|
105
|
+
puts "Done."
|
|
106
|
+
when :use_style
|
|
107
|
+
style_url = options[:use_style]
|
|
108
|
+
puts "Using external style #{style_url}"
|
|
109
|
+
svg_generator.embody_style = false
|
|
110
|
+
svg_generator.style_uri = style_url
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def process_input_file(input, xsd_handler, svg_generator, builder,
|
|
115
|
+
writer_helper, root_node_name, one_node_only,
|
|
116
|
+
output_path)
|
|
117
|
+
puts "Parsing #{input}..."
|
|
118
|
+
|
|
119
|
+
xsd_handler.root_node_name = root_node_name
|
|
120
|
+
xsd_handler.one_node_only = one_node_only
|
|
121
|
+
|
|
122
|
+
# Parse and process XSD
|
|
123
|
+
xsd_handler.process_file(input)
|
|
124
|
+
|
|
125
|
+
puts "Processing XML Schema model..."
|
|
126
|
+
|
|
127
|
+
# Generate output filename
|
|
128
|
+
output_file = generate_output_filename(
|
|
129
|
+
input,
|
|
130
|
+
root_node_name,
|
|
131
|
+
one_node_only,
|
|
132
|
+
output_path,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
puts "Drawing SVG #{output_file}..."
|
|
136
|
+
writer_helper.new_writer(output_file)
|
|
137
|
+
|
|
138
|
+
if builder.root
|
|
139
|
+
svg_generator.draw(builder.root)
|
|
140
|
+
puts "Done."
|
|
141
|
+
else
|
|
142
|
+
warn "SVG is empty!"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def generate_output_filename(input, root_node_name, one_node_only,
|
|
147
|
+
output_path)
|
|
148
|
+
basename = File.basename(input, ".*")
|
|
149
|
+
filename = if root_node_name && one_node_only
|
|
150
|
+
"#{root_node_name}.svg"
|
|
151
|
+
else
|
|
152
|
+
"#{basename}.svg"
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
if output_path
|
|
156
|
+
FileUtils.mkdir_p(output_path)
|
|
157
|
+
File.join(output_path, filename)
|
|
158
|
+
else
|
|
159
|
+
filename
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../utils/resource_loader"
|
|
4
|
+
|
|
5
|
+
module Xsdvi
|
|
6
|
+
module SVG
|
|
7
|
+
# Generates SVG files from symbol trees
|
|
8
|
+
class Generator
|
|
9
|
+
attr_accessor :writer, :embody_style, :style_uri, :hide_menu_buttons
|
|
10
|
+
|
|
11
|
+
def initialize(writer)
|
|
12
|
+
@writer = writer
|
|
13
|
+
@embody_style = true
|
|
14
|
+
@style_uri = nil
|
|
15
|
+
@hide_menu_buttons = false
|
|
16
|
+
@resource_loader = Utils::ResourceLoader.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def draw(root_symbol)
|
|
20
|
+
# Reset class variables before drawing
|
|
21
|
+
Symbol.reset_class_variables
|
|
22
|
+
|
|
23
|
+
svg_begin
|
|
24
|
+
draw_symbol(root_symbol)
|
|
25
|
+
svg_end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def print_extern_style
|
|
29
|
+
writer.new_writer(style_uri)
|
|
30
|
+
print(load_resource("svg/style.css"))
|
|
31
|
+
writer.close
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def print(string)
|
|
35
|
+
writer.append("#{string}\n")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def svg_begin
|
|
41
|
+
print(load_resource("svg/xml_declaration.xml"))
|
|
42
|
+
print_style_ref unless embody_style
|
|
43
|
+
print(load_resource("svg/doctype.txt"))
|
|
44
|
+
print(load_resource("svg/svg_start.txt"))
|
|
45
|
+
print(load_resource("svg/title.txt"))
|
|
46
|
+
|
|
47
|
+
script = load_resource("svg/script.js")
|
|
48
|
+
script = script.gsub("%HEIGHT_SUM%", (Symbol::MAX_HEIGHT + Symbol::Y_INDENT).to_s)
|
|
49
|
+
script = script.gsub("%HEIGHT_HALF%", (Symbol::MAX_HEIGHT / 2).to_s)
|
|
50
|
+
print(script)
|
|
51
|
+
|
|
52
|
+
print_defs(embody_style, true)
|
|
53
|
+
print(load_resource("svg/menu_buttons.svg")) unless hide_menu_buttons
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def svg_end
|
|
57
|
+
print(load_resource("svg/svg_end.txt"))
|
|
58
|
+
writer.close
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def print_style_ref
|
|
62
|
+
style_template = load_resource("svg/style.xml")
|
|
63
|
+
print(style_template.gsub("%STYLE_URI%", style_uri))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def print_embodied_style
|
|
67
|
+
style_template = load_resource("svg/style.html")
|
|
68
|
+
style = load_resource("svg/style.css")
|
|
69
|
+
print(style_template.gsub("%STYLE%", style))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def print_defs(style, symbols)
|
|
73
|
+
print("<defs>")
|
|
74
|
+
print_embodied_style if style
|
|
75
|
+
print(load_resource("svg/defined_symbols.svg")) if symbols
|
|
76
|
+
print("</defs>")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def draw_symbol(symbol)
|
|
80
|
+
symbol.svg = self
|
|
81
|
+
symbol.prepare_box
|
|
82
|
+
symbol.draw
|
|
83
|
+
symbol.children.each do |child|
|
|
84
|
+
draw_symbol(child)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def load_resource(path)
|
|
89
|
+
@resource_loader.read_resource_file(path)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|