xsdvi 1.0.0 → 1.0.1

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: cbb88134a26f0713dea31aa8032d38e06fc8fe5e9b04b321211dd86fac4eadb5
4
- data.tar.gz: 21cf471f50d28f47267af0cdd85a3733941e3dd23026389dd21b23fbfc6a7330
3
+ metadata.gz: 819798e045b576a5f2b55d8d80e6997c489c3d17988e30bbdace382be737f757
4
+ data.tar.gz: 7889f66439924400696c219fc0011f468580d56ad9a42a9cde21b0ef0d4995d0
5
5
  SHA512:
6
- metadata.gz: 6c7d8578f22756bd8ae89f9f516da49a02ce926579a05fff307d244a47f8ff33dfc595c60d0fec04ba94412f722bad879da8500043f7af89bea870f10ad2ffff
7
- data.tar.gz: 4a74687246d90e2136311111f5046fd768f9347115e2f22cb517adb922c932ca0c508efa0b5fa8ecf0cc8d09e671781b29f85594b31b52836baec98c58e9c76d
6
+ metadata.gz: 997ebdc3af70469940d70e129302edb19f8226be440c94cb7093520107a6ce02a6e8115c6912e9b8cd8a80239efd41f8cb6fcba88c791b40d8df7579024795d8
7
+ data.tar.gz: 27a2ae348887b91af15a75172bb2d42c643384c74b389645385541b81879e369eed9f9ec2f8bb99db8450fe8196fc7dc05f7eda5b5f38dfbbd705a8dae2a6027
data/README.adoc CHANGED
@@ -27,7 +27,7 @@ Ruby projects.
27
27
 
28
28
  == Features
29
29
 
30
- === XSD Component Visualization
30
+ === XSD component visualization
31
31
 
32
32
  * Elements and Attributes: Visual boxes showing element names, types, cardinality (min..max occurrences), required/optional status, and namespace information
33
33
  * Compositors: Graphical representation of sequence (ordered), choice (alternatives), and all (unordered) element groups
@@ -35,7 +35,7 @@ Ruby projects.
35
35
  * Identity Constraints: Visualization of key, keyref, unique constraints with their selectors and fields
36
36
  * Type Information: Display of simple and complex type definitions, base types, and anonymous types
37
37
 
38
- === Interactive SVG Output
38
+ === Interactive SVG output
39
39
 
40
40
  * Hierarchical Layout: Tree-structure visualization with proper indentation and connections
41
41
  * Collapsible/Expandable: JavaScript-enabled expand/collapse functionality for complex schemas (optional)
@@ -43,20 +43,21 @@ Ruby projects.
43
43
  * Documentation Display: Inline display of `<xs:documentation>` annotations
44
44
  * Color-coded Symbols: Different visual styles for elements, attributes, compositors, and constraints
45
45
 
46
- === Flexible Output Options
46
+ === Flexible output options
47
47
 
48
48
  * Single Diagram: Generate one SVG showing the entire schema or a specific root element
49
49
  * Per-Element Diagrams: Generate separate SVG files for each top-level element
50
50
  * Custom Styling: Embed CSS in SVG files or use external stylesheets
51
51
  * Output Directory: Organize generated diagrams in custom folder structures
52
52
 
53
- === Processing Capabilities
53
+ === Processing capabilities
54
54
 
55
55
  * Multiple XSD Files: Process multiple schema files in a single run
56
56
  * Loop Detection: Automatically detects and marks recursive element references
57
57
  * Namespace Handling: Properly displays and distinguishes multiple namespaces
58
58
  * Documentation Extraction: Extracts and formats XSD documentation for display
59
59
  * Large Schema Support: Handles complex, real-world schemas with hundreds of elements
60
+ * Type Resolution: Comprehensive resolution of named types, group references, attribute groups, element references, and type inheritance (extension/restriction)
60
61
 
61
62
  == Installation
62
63
 
@@ -194,6 +195,104 @@ Creates `output/schema.svg` and `output/custom.css`, with the SVG referencing
194
195
  the external stylesheet. Useful for customizing diagram appearance.
195
196
  ====
196
197
 
198
+ === Comparing Java and Ruby outputs
199
+
200
+ The `compare` command generates side-by-side visual comparisons of Java XsdVi
201
+ v1.3 and Ruby XsdVi outputs. This is useful for validation, documentation, and
202
+ visual quality assurance.
203
+
204
+ ==== Basic comparison
205
+
206
+ [source,shell]
207
+ ----
208
+ xsdvi compare schema.xsd
209
+ ----
210
+
211
+ This command:
212
+
213
+ 1. Automatically downloads Java XsdVi JAR v1.3 (first run only, cached in `~/.xsdvi/`)
214
+ 2. Generates SVGs using both Java and Ruby implementations
215
+ 3. Extracts metadata and symbol counts from both outputs
216
+ 4. Creates an interactive HTML comparison page in `comparisons/<schema>-<timestamp>/`
217
+
218
+ ==== Comparison command options
219
+
220
+ `-r, --root-node-name NAME`::
221
+ Specify the schema root element to visualize (same as `generate` command). Use "all" to generate comparisons for all top-level elements.
222
+
223
+ `-o, --output-path PATH`::
224
+ Specify output directory for comparison files. Default: `comparisons/<schema>-<timestamp>/`
225
+
226
+ `--skip-java`::
227
+ Skip Java generation and use existing Java outputs. Useful when re-running comparison with updated Ruby code.
228
+
229
+ `--skip-ruby`::
230
+ Skip Ruby generation and use existing Ruby outputs. Useful for comparing against manually generated Ruby outputs.
231
+
232
+ `-O, --open`::
233
+ Automatically open the comparison HTML in your default browser after generation.
234
+
235
+ ==== Comparison examples
236
+
237
+ .Basic comparison
238
+ [example]
239
+ ====
240
+ [source,shell]
241
+ ----
242
+ xsdvi compare UnitsML-v1.0.xsd -r UnitsML
243
+ ----
244
+
245
+ Downloads Java XsdVi (if needed), generates SVGs with both implementations, and creates an interactive comparison showing:
246
+
247
+ * Side-by-side SVG iframes
248
+ * Statistics table comparing file sizes and symbol counts
249
+ * Generation time for each implementation
250
+ * Visual diff highlighting any differences
251
+ ====
252
+
253
+ .Compare all elements with auto-open
254
+ [example]
255
+ ====
256
+ [source,shell]
257
+ ----
258
+ xsdvi compare schema.xsd -r all -O
259
+ ----
260
+
261
+ Generates comparison for all top-level elements and automatically opens the comparison page in your browser. The HTML includes an element selector dropdown to switch between different element diagrams.
262
+ ====
263
+
264
+ .Compare using existing Java output
265
+ [example]
266
+ ====
267
+ [source,shell]
268
+ ----
269
+ xsdvi compare schema.xsd --skip-java -o my-comparison
270
+ ----
271
+
272
+ Reuses existing Java output and generates fresh Ruby output, useful during Ruby development to quickly validate changes without regenerating Java outputs.
273
+ ====
274
+
275
+ ==== Comparison output structure
276
+
277
+ After running a comparison, you get:
278
+
279
+ [source]
280
+ ----
281
+ comparisons/<schema>-<timestamp>/
282
+ ├── java/
283
+ │ └── <schema>.svg # Java XsdVi output
284
+ ├── ruby/
285
+ │ └── <schema>.svg # Ruby XsdVi output
286
+ └── comparison.html # Interactive comparison page
287
+ ----
288
+
289
+ The comparison HTML displays:
290
+
291
+ * **Statistics table**: File counts, sizes, symbol counts by type, generation times
292
+ * **Visual indicators**: Green checkmarks for matches, red X for mismatches
293
+ * **Split-screen view**: Java output (left) and Ruby output (right) in synchronized iframes
294
+ * **Element selector**: Dropdown to switch between elements (when using `-r all`)
295
+
197
296
  == Architecture
198
297
 
199
298
  === Core components
@@ -231,15 +330,122 @@ options with built-in help and validation.
231
330
  ----
232
331
  XSD File → XsdHandler (Nokogiri parsing)
233
332
 
234
- Symbol Tree (TreeBuilder)
333
+ Type Registry Collection (complexTypes, simpleTypes, groups, etc.)
334
+
335
+ Symbol Tree Building (TreeBuilder with on-demand type resolution)
235
336
 
236
337
  Symbol Processing (prepare_box, calculate dimensions)
237
338
 
238
- SVG Generation (Generator.draw)
339
+ SVG Generation (recursive drawing)
239
340
 
240
341
  SVG File Output
241
342
  ----
242
343
 
344
+ === Type resolution architecture
345
+
346
+ The type resolution system is the core feature that enables XSDVI to correctly process all XSD schema structures. It resolves references to named types, groups, and elements, and handles type inheritance patterns.
347
+
348
+ ==== Resolution mechanisms
349
+
350
+ The system implements six resolution mechanisms:
351
+
352
+ *Type Registry System*
353
+
354
+ All named type and group definitions are collected during schema parsing into hash-based registries for O(1) lookup performance:
355
+
356
+ * Complex types (`<xs:complexType name="...">`)
357
+ * Simple types (`<xs:simpleType name="...">`)
358
+ * Groups (`<xs:group name="...">`)
359
+ * Attribute groups (`<xs:attributeGroup name="...">`)
360
+ * Global elements (`<xs:element name="...">`)
361
+
362
+ *Named Type Resolution*
363
+
364
+ Resolves type references in element declarations:
365
+
366
+ [source,xml]
367
+ ----
368
+ <xs:element name="Foo" type="BarType"/>
369
+ ----
370
+
371
+ The system:
372
+
373
+ 1. Strips namespace prefixes from type names
374
+ 2. Checks if the type is a W3C builtin (string, boolean, decimal, etc.)
375
+ 3. Looks up custom types in the complex/simple type registries
376
+ 4. Processes the resolved type definition inline
377
+
378
+ *Group Reference Resolution*
379
+
380
+ Resolves group references in compositors:
381
+
382
+ [source,xml]
383
+ ----
384
+ <xs:sequence>
385
+ <xs:group ref="CommonElements"/>
386
+ </xs:sequence>
387
+ ----
388
+
389
+ The referenced group's contents are expanded inline, maintaining proper tree hierarchy.
390
+
391
+ *Attribute Group Reference Resolution*
392
+
393
+ Resolves attribute group references:
394
+
395
+ [source,xml]
396
+ ----
397
+ <xs:complexType>
398
+ <xs:attributeGroup ref="CommonAttributes"/>
399
+ </xs:complexType>
400
+ ----
401
+
402
+ Supports nested attribute group references (recursive resolution).
403
+
404
+ *Element Reference Resolution*
405
+
406
+ Resolves element references with proper cardinality:
407
+
408
+ [source,xml]
409
+ ----
410
+ <xs:element ref="CommonElement" minOccurs="0" maxOccurs="unbounded"/>
411
+ ----
412
+
413
+ The system preserves cardinality constraints while resolving to the element definition.
414
+
415
+ *Extension and Restriction Processing*
416
+
417
+ Handles type inheritance via `complexContent` and `simpleContent`:
418
+
419
+ [source,xml]
420
+ ----
421
+ <xs:complexType name="ExtendedType">
422
+ <xs:complexContent>
423
+ <xs:extension base="BaseType">
424
+ <xs:sequence>
425
+ <!-- Additional elements -->
426
+ </xs:sequence>
427
+ </xs:extension>
428
+ </xs:complexContent>
429
+ </xs:complexType>
430
+ ----
431
+
432
+ The system:
433
+
434
+ 1. Resolves the base type from registries
435
+ 2. Processes base type structure first (inherited elements/attributes)
436
+ 3. Processes extension-specific additions
437
+ 4. Maintains single inheritance hierarchy
438
+
439
+ ==== Performance characteristics
440
+
441
+ * Registry collection: O(n) where n = total XSD nodes
442
+ * Type lookup: O(1) hash access
443
+ * Recursive resolution: Bounded by schema depth
444
+ * Loop detection prevents infinite recursion
445
+ * On-demand resolution (lazy evaluation)
446
+
447
+ This architecture enables XSDVI to correctly process 100% of XSD schema structures, matching the Java version's capabilities.
448
+
243
449
 
244
450
  == Differences from Java version
245
451
 
@@ -295,6 +501,158 @@ Run rubocop:
295
501
  bundle exec rubocop
296
502
  ----
297
503
 
504
+ === Testing
505
+
506
+ ==== Test suite overview
507
+
508
+ The XSDVI Ruby test suite provides comprehensive validation of all functionality with 46 tests across two categories:
509
+
510
+ * **Integration tests** (14 tests): Validate complete end-to-end processing and compare outputs with Java version
511
+ * **Type resolution tests** (32 tests): Validate all 7 type resolution mechanisms
512
+
513
+ ==== Running tests
514
+
515
+ *Run all tests*
516
+
517
+ [source,shell]
518
+ ----
519
+ bundle exec rspec
520
+ ----
521
+
522
+ *Run specific test file*
523
+
524
+ [source,shell]
525
+ ----
526
+ # Type resolution tests only
527
+ bundle exec rspec spec/xsdvi/type_resolution_spec.rb
528
+
529
+ # Output comparison tests only
530
+ bundle exec rspec spec/xsdvi/output_comparison_spec.rb
531
+ ----
532
+
533
+ *Run with documentation format*
534
+
535
+ [source,shell]
536
+ ----
537
+ bundle exec rspec --format documentation
538
+ ----
539
+
540
+ *Run specific test group*
541
+
542
+ [source,shell]
543
+ ----
544
+ bundle exec rspec spec/xsdvi/type_resolution_spec.rb -e "Named Type Resolution"
545
+ ----
546
+
547
+ ==== Type resolution test coverage
548
+
549
+ The type resolution test suite validates that XSDVI Ruby correctly processes all XSD schema constructs:
550
+
551
+ *7 Resolution Mechanisms Tested:*
552
+
553
+ 1. **Named Type Resolution** - Complex and simple type references
554
+ 2. **Group Reference Resolution** - Model group (`<xs:group ref="...">`) expansion
555
+ 3. **Attribute Group Reference Resolution** - Attribute group references including nested
556
+ 4. **Element Reference Resolution** - Global element references with cardinality
557
+ 5. **Extension/Restriction Resolution** - Type inheritance via `complexContent`/`simpleContent`
558
+ 6. **Identity Constraint Resolution** - Key, keyref, unique, selector, field
559
+ 7. **Circular Reference Resolution** - Self-referencing and mutual circular references
560
+
561
+ *Test Fixtures:*
562
+
563
+ The test suite uses 7 XSD fixture files in `spec/fixtures/type_resolution/`:
564
+
565
+ * `named_types.xsd` - Type reference resolution
566
+ * `group_refs.xsd` - Group reference expansion
567
+ * `attribute_groups.xsd` - Attribute group references
568
+ * `element_refs.xsd` - Element references with cardinality
569
+ * `inheritance.xsd` - Extension and restriction
570
+ * `identity_constraints.xsd` - Key/keyref/unique constraints
571
+ * `circular.xsd` - Circular reference handling
572
+
573
+ For detailed test documentation, see `spec/xsdvi/TYPE_RESOLUTION_TESTING.md`.
574
+
575
+ ==== Generating comparison files
576
+
577
+ To validate that XSDVI Ruby produces output identical to the Java version:
578
+
579
+ *Generate Ruby output for UnitsML schema*
580
+
581
+ [source,shell]
582
+ ----
583
+ xsdvi generate spec/fixtures/UnitsML-v1.0-csd04.xsd -r UnitsML \
584
+ -p spec/fixtures/ruby
585
+ ----
586
+
587
+ *Generate Ruby output for all elements*
588
+
589
+ [source,shell]
590
+ ----
591
+ xsdvi generate spec/fixtures/UnitsML-v1.0-csd04.xsd -r all -o \
592
+ -p spec/fixtures/ruby/all
593
+ ----
594
+
595
+ *Generate Ruby output for TestXMLEntities*
596
+
597
+ [source,shell]
598
+ ----
599
+ xsdvi generate spec/fixtures/TestXMLEntities.xsd \
600
+ -p spec/fixtures/ruby
601
+ ----
602
+
603
+ *Compare with Java version*
604
+
605
+ The test suite automatically compares Ruby outputs with Java reference outputs in `spec/fixtures/java/`. The comparison normalizes known differences (text wrapping) and validates structural equivalence:
606
+
607
+ [source,shell]
608
+ ----
609
+ bundle exec rspec spec/xsdvi/output_comparison_spec.rb
610
+ ----
611
+
612
+ *Manual comparison*
613
+
614
+ You can manually compare outputs using diff tools:
615
+
616
+ [source,shell]
617
+ ----
618
+ # Compare UnitsML outputs
619
+ diff spec/fixtures/java/UnitsML-v1.0-csd04.svg \
620
+ spec/fixtures/ruby/UnitsML-v1.0-csd04.svg
621
+
622
+ # Compare specific element
623
+ diff spec/fixtures/java/all/Quantity.svg \
624
+ spec/fixtures/ruby/all/Quantity.svg
625
+ ----
626
+
627
+ Note: Direct diff will show text wrapping differences. Use the RSpec comparison tests for structural validation.
628
+
629
+ *Generating fresh Java comparison files*
630
+
631
+ If you need to regenerate Java version outputs (requires Java XsdVi):
632
+
633
+ [source,shell]
634
+ ----
635
+ # Assuming Java xsdvi.jar is available
636
+ java -jar xsdvi.jar --in spec/fixtures/UnitsML-v1.0-csd04.xsd \
637
+ --root UnitsML --out spec/fixtures/java/UnitsML-v1.0-csd04.svg
638
+
639
+ # For all elements
640
+ java -jar xsdvi.jar --in spec/fixtures/UnitsML-v1.0-csd04.xsd \
641
+ --root all --one-node-only --out spec/fixtures/java/all
642
+ ----
643
+
644
+ ==== Test validation approach
645
+
646
+ The test suite uses Canon gem for XML-aware comparison that:
647
+
648
+ * Normalizes whitespace differences
649
+ * Handles attribute ordering variations
650
+ * Validates structural equivalence
651
+ * Ignores text wrapping differences in `data-desc-*` attributes
652
+ * Focuses on semantic correctness rather than byte-identical output
653
+
654
+ This ensures that XSDVI Ruby produces functionally identical diagrams to the Java version while allowing minor presentational differences.
655
+
298
656
  == Contributing
299
657
 
300
658
  Bug reports and pull requests are welcome on GitHub at
data/lib/xsdvi/cli.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "thor"
4
+ require "fileutils"
4
5
 
5
6
  module Xsdvi
6
7
  # Command-line interface for XSDVI
@@ -67,16 +68,102 @@ module Xsdvi
67
68
  apply_style_settings(svg_generator, style_mode, options)
68
69
 
69
70
  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
- )
71
+ # Special handling for -r all: generate file for each element
72
+ if root_node_name == "all"
73
+ process_all_elements(
74
+ input,
75
+ xsd_handler,
76
+ svg_generator,
77
+ builder,
78
+ writer_helper,
79
+ output_path,
80
+ )
81
+ else
82
+ process_input_file(
83
+ input,
84
+ xsd_handler,
85
+ svg_generator,
86
+ builder,
87
+ writer_helper,
88
+ root_node_name,
89
+ one_node_only,
90
+ output_path,
91
+ )
92
+ end
93
+ end
94
+ end
95
+
96
+ desc "compare INPUT", "Compare Java and Ruby XsdVi outputs side-by-side"
97
+ method_option :root_node_name,
98
+ type: :string,
99
+ aliases: "-r",
100
+ desc: "Schema root node name (or 'all' for all elements)"
101
+ method_option :output_path,
102
+ type: :string,
103
+ aliases: "-o",
104
+ desc: "Output directory (default: ./comparisons/<name>-<timestamp>)"
105
+ method_option :skip_java,
106
+ type: :boolean,
107
+ default: false,
108
+ desc: "Skip Java generation (use existing output)"
109
+ method_option :skip_ruby,
110
+ type: :boolean,
111
+ default: false,
112
+ desc: "Skip Ruby generation (use existing output)"
113
+ method_option :open,
114
+ type: :boolean,
115
+ default: false,
116
+ aliases: "-O",
117
+ desc: "Open comparison HTML in browser automatically"
118
+ def compare(input)
119
+ unless File.exist?(input)
120
+ puts "Error: XSD file '#{input}' not found!"
121
+ exit(1)
122
+ end
123
+
124
+ puts "=" * 60
125
+ puts "XsdVi Comparison Tool"
126
+ puts "=" * 60
127
+ puts "Schema: #{input}"
128
+ puts ""
129
+
130
+ begin
131
+ generator = Comparison::DualGenerator.new(input, options)
132
+ result = generator.generate
133
+
134
+ puts ""
135
+ puts "=" * 60
136
+ puts "Comparison Complete!"
137
+ puts "=" * 60
138
+ puts ""
139
+ puts "Output directory: #{result[:output_dir]}"
140
+ puts "HTML comparison: #{result[:html_file]}"
141
+ puts ""
142
+
143
+ if result[:java][:file_count] && result[:java][:generation_time] && result[:java][:generation_time]
144
+ puts "Java: #{result[:java][:total_size_kb]} KB, " \
145
+ "#{result[:java][:file_count]} file(s), " \
146
+ "#{result[:java][:generation_time]}s"
147
+ end
148
+
149
+ if result[:ruby][:file_count] && result[:ruby][:generation_time] && result[:ruby][:generation_time]
150
+ puts "Ruby: #{result[:ruby][:total_size_kb]} KB, " \
151
+ "#{result[:ruby][:file_count]} file(s), " \
152
+ "#{result[:ruby][:generation_time]}s"
153
+ end
154
+
155
+ puts ""
156
+
157
+ if options[:open]
158
+ open_in_browser(result[:html_file])
159
+ else
160
+ puts "Open #{result[:html_file]} in your browser to view the comparison"
161
+ end
162
+ rescue StandardError => e
163
+ puts ""
164
+ puts "Error: #{e.message}"
165
+ puts e.backtrace.first(5).join("\n") if ENV["DEBUG"]
166
+ exit(1)
80
167
  end
81
168
  end
82
169
 
@@ -84,6 +171,52 @@ module Xsdvi
84
171
 
85
172
  private
86
173
 
174
+ def process_all_elements(input, xsd_handler, svg_generator, builder,
175
+ writer_helper, output_path)
176
+ # First, parse the schema to get all element names
177
+ doc = Nokogiri::XML(File.read(input))
178
+ element_names = xsd_handler.get_elements_names(doc)
179
+
180
+ if element_names.empty?
181
+ warn "No root elements found in schema!"
182
+ return
183
+ end
184
+
185
+ puts "Generating #{element_names.size} diagrams for all elements..."
186
+
187
+ # Generate a separate diagram for each element
188
+ element_names.each do |elem_name|
189
+ # Reset builder for each element
190
+ builder = Tree::Builder.new
191
+ xsd_handler = XsdHandler.new(builder)
192
+ xsd_handler.root_node_name = elem_name
193
+ xsd_handler.one_node_only = true
194
+ xsd_handler.set_schema_namespace(doc, elem_name)
195
+
196
+ # Process the schema with this specific root element
197
+ xsd_handler.process_file(input)
198
+
199
+ # Generate output filename
200
+ output_file = generate_output_filename(
201
+ input,
202
+ elem_name,
203
+ true, # one_node_only
204
+ output_path,
205
+ )
206
+
207
+ writer_helper.new_writer(output_file)
208
+
209
+ if builder.root
210
+ svg_generator.draw(builder.root)
211
+ puts " Generated #{output_file}"
212
+ else
213
+ warn " Skipped #{elem_name} (empty)"
214
+ end
215
+ end
216
+
217
+ puts "Done."
218
+ end
219
+
87
220
  def determine_style_mode(options)
88
221
  return :generate_style if options[:generate_style]
89
222
  return :use_style if options[:use_style]
@@ -159,5 +292,24 @@ module Xsdvi
159
292
  filename
160
293
  end
161
294
  end
295
+
296
+ def open_in_browser(file)
297
+ puts "Opening comparison in browser..."
298
+
299
+ # Get absolute path for browser
300
+ abs_path = File.expand_path(file)
301
+
302
+ case RbConfig::CONFIG["host_os"]
303
+ when /darwin/
304
+ system("open", abs_path)
305
+ when /linux/
306
+ system("xdg-open", abs_path)
307
+ when /mswin|mingw|cygwin/
308
+ system("start", abs_path)
309
+ else
310
+ puts "Unable to auto-open browser on this platform"
311
+ puts "Please open #{file} manually"
312
+ end
313
+ end
162
314
  end
163
315
  end