vectory 0.8.0 → 0.8.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/docs.yml +59 -0
  3. data/.github/workflows/links.yml +99 -0
  4. data/.github/workflows/rake.yml +5 -1
  5. data/.github/workflows/release.yml +7 -3
  6. data/.gitignore +5 -0
  7. data/.rubocop.yml +11 -3
  8. data/.rubocop_todo.yml +252 -0
  9. data/Gemfile +4 -2
  10. data/README.adoc +23 -1
  11. data/Rakefile +13 -0
  12. data/docs/Gemfile +18 -0
  13. data/docs/_config.yml +179 -0
  14. data/docs/features/conversion.adoc +205 -0
  15. data/docs/features/external-dependencies.adoc +305 -0
  16. data/docs/features/format-detection.adoc +173 -0
  17. data/docs/features/index.adoc +205 -0
  18. data/docs/getting-started/core-concepts.adoc +214 -0
  19. data/docs/getting-started/index.adoc +37 -0
  20. data/docs/getting-started/installation.adoc +318 -0
  21. data/docs/getting-started/quick-start.adoc +160 -0
  22. data/docs/guides/error-handling.adoc +400 -0
  23. data/docs/guides/index.adoc +197 -0
  24. data/docs/index.adoc +146 -0
  25. data/docs/lychee.toml +25 -0
  26. data/docs/reference/api.adoc +355 -0
  27. data/docs/reference/index.adoc +189 -0
  28. data/docs/understanding/architecture.adoc +277 -0
  29. data/docs/understanding/index.adoc +148 -0
  30. data/docs/understanding/inkscape-wrapper.adoc +270 -0
  31. data/lib/vectory/capture.rb +165 -37
  32. data/lib/vectory/cli.rb +2 -0
  33. data/lib/vectory/configuration.rb +177 -0
  34. data/lib/vectory/conversion/ghostscript_strategy.rb +77 -0
  35. data/lib/vectory/conversion/inkscape_strategy.rb +124 -0
  36. data/lib/vectory/conversion/strategy.rb +58 -0
  37. data/lib/vectory/conversion.rb +104 -0
  38. data/lib/vectory/datauri.rb +1 -1
  39. data/lib/vectory/emf.rb +17 -5
  40. data/lib/vectory/eps.rb +45 -3
  41. data/lib/vectory/errors.rb +25 -0
  42. data/lib/vectory/file_magic.rb +2 -2
  43. data/lib/vectory/ghostscript_wrapper.rb +160 -0
  44. data/lib/vectory/image_resize.rb +2 -2
  45. data/lib/vectory/inkscape_wrapper.rb +205 -0
  46. data/lib/vectory/pdf.rb +76 -0
  47. data/lib/vectory/platform.rb +105 -0
  48. data/lib/vectory/ps.rb +47 -3
  49. data/lib/vectory/svg.rb +46 -3
  50. data/lib/vectory/svg_document.rb +40 -24
  51. data/lib/vectory/system_call.rb +36 -9
  52. data/lib/vectory/vector.rb +3 -23
  53. data/lib/vectory/version.rb +1 -1
  54. data/lib/vectory.rb +16 -11
  55. metadata +34 -3
  56. data/lib/vectory/inkscape_converter.rb +0 -141
@@ -0,0 +1,400 @@
1
+ ---
2
+ layout: default
3
+ title: Error Handling
4
+ parent: Guides
5
+ nav_order: 1
6
+ ---
7
+ = Error Handling
8
+
9
+ Common errors and how to resolve them.
10
+
11
+ == Purpose
12
+
13
+ This guide covers common errors you may encounter when using Vectory and how to resolve them.
14
+
15
+ == Error Classes
16
+
17
+ Vectory uses a structured error hierarchy:
18
+
19
+ [source,ruby]
20
+ ----
21
+ Vectory::Error # Base error class
22
+ ├── SystemCallError # External tool execution failures
23
+ ├── NotWrittenToDiskError # Accessing path before write
24
+ ├── ParsingError # Content parsing failures
25
+ ├── InkscapeNotFoundError # Inkscape not available
26
+ ├── ConversionError # Conversion failures with diagnostics
27
+ └── InkscapeQueryError # Dimension query failures
28
+ ----
29
+
30
+ == Common Errors
31
+
32
+ === Inkscape Not Found
33
+
34
+ [source,ruby]
35
+ ----
36
+ Vectory::InkscapeNotFoundError: Inkscape not found in PATH
37
+ ----
38
+
39
+ **Causes**:
40
+
41
+ * Inkscape not installed
42
+ * Inkscape not in system PATH
43
+ * Custom path not configured
44
+
45
+ **Solutions**:
46
+
47
+ . Install Inkscape:
48
+ +
49
+ [source,shell]
50
+ ----
51
+ # macOS
52
+ brew install --cask inkscape
53
+
54
+ # Ubuntu/Debian
55
+ sudo apt install inkscape
56
+
57
+ # Windows
58
+ # Download from https://inkscape.org/release/
59
+ ----
60
+
61
+ . Verify installation:
62
+ +
63
+ [source,shell]
64
+ ----
65
+ inkscape --version
66
+ ----
67
+
68
+ . Set custom path:
69
+ +
70
+ [source,ruby]
71
+ ----
72
+ ENV["INKSCAPE_PATH"] = "/custom/path/to/inkscape"
73
+ ----
74
+
75
+ === Ghostscript Not Found
76
+
77
+ [source,ruby]
78
+ ----
79
+ Vectory::SystemCallError: Ghostscript conversion failed
80
+ ----
81
+
82
+ **Causes**:
83
+
84
+ * Ghostscript not installed
85
+ * Ghostscript not in system PATH
86
+
87
+ **Solutions**:
88
+
89
+ . Install Ghostscript:
90
+ +
91
+ [source,shell]
92
+ ----
93
+ # macOS
94
+ brew install ghostscript
95
+
96
+ # Ubuntu/Debian
97
+ sudo apt install ghostscript
98
+
99
+ # Windows
100
+ # Download from https://www.ghostscript.com/download/gsdnld.html
101
+ ----
102
+
103
+ . Verify installation:
104
+ +
105
+ [source,shell]
106
+ ----
107
+ gs --version
108
+ ----
109
+
110
+ === Conversion Timeout
111
+
112
+ [source,ruby]
113
+ ----
114
+ Vectory::SystemCallError: Command timed out: inkscape
115
+ ----
116
+
117
+ **Causes**:
118
+
119
+ * Large file being processed
120
+ * Complex vector graphics
121
+ * System resource constraints
122
+ * Inkscape hanging on macOS
123
+
124
+ **Solutions**:
125
+
126
+ . Check if file is valid:
127
+ +
128
+ [source,ruby]
129
+ ----
130
+ # Verify file can be opened
131
+ File.open("diagram.eps", "r") { |f| f.read(100) }
132
+ ----
133
+
134
+ . Increase timeout:
135
+ +
136
+ [source,ruby]
137
+ ----
138
+ # Default timeout is 60 seconds
139
+ # For larger files, you may need to wait longer
140
+ ----
141
+
142
+ . On macOS, ensure `DISPLAY=""` is set (automatic in Vectory)
143
+
144
+ === Not Written to Disk Error
145
+
146
+ [source,ruby]
147
+ ----
148
+ Vectory::NotWrittenToDiskError: File has not been written to disk yet
149
+ ----
150
+
151
+ **Causes**:
152
+
153
+ * Accessing `path` before calling `write()`
154
+
155
+ **Solution**:
156
+
157
+ [source,ruby]
158
+ ----
159
+ eps = Vectory::Eps.from_path("diagram.eps")
160
+
161
+ # WRONG: This raises error
162
+ puts eps.path # => NotWrittenToDiskError
163
+
164
+ # CORRECT: Write first, then access path
165
+ eps.write("output.eps")
166
+ puts eps.path # => "output.eps"
167
+ ----
168
+
169
+ === Parsing Error
170
+
171
+ [source,ruby]
172
+ ----
173
+ Vectory::ParsingError: Unable to detect file format
174
+ ----
175
+
176
+ **Causes**:
177
+
178
+ * Invalid file content
179
+ * Corrupted file
180
+ * Unsupported format
181
+
182
+ **Solutions**:
183
+
184
+ . Verify file format:
185
+ +
186
+ [source,ruby]
187
+ ----
188
+ content = File.read("unknown_file", 100)
189
+ puts content # Check first 100 bytes
190
+ ----
191
+
192
+ . Use explicit format:
193
+ +
194
+ [source,ruby]
195
+ ----
196
+ # Force format if detection fails
197
+ svg = Vectory::Svg.from_path("diagram") # Treat as SVG
198
+ ----
199
+
200
+ === Dimension Query Failed
201
+
202
+ [source,ruby]
203
+ ----
204
+ Vectory::InkscapeQueryError: Failed to query dimensions
205
+ ----
206
+
207
+ **Causes**:
208
+
209
+ * Invalid input file
210
+ * Inkscape version incompatibility
211
+
212
+ **Solutions**:
213
+
214
+ . Verify file is valid:
215
+ +
216
+ [source,ruby]
217
+ ----
218
+ # Try converting first
219
+ svg = Vectory::Svg.from_path("diagram.svg")
220
+ # If conversion works, file is valid
221
+ ----
222
+
223
+ . Check Inkscape version:
224
+ +
225
+ [source,ruby]
226
+ ----
227
+ inkscape = Vectory::InkscapeWrapper.instance
228
+ puts inkscape.version # Should be 0.92 or later
229
+ ----
230
+
231
+ ## Error Handling Patterns
232
+
233
+ === Rescue Specific Errors
234
+
235
+ [source,ruby]
236
+ ----
237
+ begin
238
+ svg = Vectory::Eps.from_path("diagram.eps").to_svg
239
+ rescue Vectory::InkscapeNotFoundError => e
240
+ puts "Inkscape not found: #{e.message}"
241
+ rescue Vectory::ConversionError => e
242
+ puts "Conversion failed: #{e.message}"
243
+ puts "Diagnostics: #{e.diagnostics}"
244
+ rescue Vectory::Error => e
245
+ puts "Vectory error: #{e.message}"
246
+ end
247
+ ----
248
+
249
+ === Retry Logic
250
+
251
+ [source,ruby]
252
+ ----
253
+ require 'vectory'
254
+
255
+ def convert_with_retry(input, output, max_retries = 3)
256
+ retries = 0
257
+
258
+ begin
259
+ svg = Vectory::Eps.from_path(input).to_svg
260
+ svg.write(output)
261
+ rescue Vectory::SystemCallError => e
262
+ retries += 1
263
+ if retries < max_retries
264
+ puts "Retry #{retries}/#{max_retries}..."
265
+ sleep 1
266
+ retry
267
+ else
268
+ raise
269
+ end
270
+ end
271
+ end
272
+ ----
273
+
274
+ === Validation Before Conversion
275
+
276
+ [source,ruby]
277
+ ----
278
+ def validate_file(path)
279
+ # Check file exists
280
+ raise "File not found: #{path}" unless File.exist?(path)
281
+
282
+ # Check file readable
283
+ raise "File not readable: #{path}" unless File.readable?(path)
284
+
285
+ # Try to detect format
286
+ content = File.read(path, 100)
287
+ format = Vectory::FileMagic.detect_format(content)
288
+
289
+ if format == :unknown
290
+ raise "Unable to detect format: #{path}"
291
+ end
292
+
293
+ true
294
+ end
295
+
296
+ # Usage
297
+ begin
298
+ validate_file("diagram.eps")
299
+ svg = Vectory::Eps.from_path("diagram.eps").to_svg
300
+ rescue RuntimeError => e
301
+ puts "Validation failed: #{e.message}"
302
+ end
303
+ ----
304
+
305
+ ## Debugging
306
+
307
+ === Enable Debug Logging
308
+
309
+ [source,ruby]
310
+ ----
311
+ # Enable logging
312
+ ENV["VECTORY_LOG"] = "1"
313
+
314
+ require 'vectory'
315
+
316
+ # Now all external tool commands are logged
317
+ svg = Vectory::Eps.from_path("diagram.eps").to_svg
318
+ # Logs: [DEBUG] Executing: inkscape ...
319
+ ----
320
+
321
+ === Check Tool Availability
322
+
323
+ [source,ruby]
324
+ ----
325
+ require 'vectory'
326
+
327
+ # Check all tools
328
+ inkscape = Vectory::InkscapeWrapper.instance
329
+ puts "Inkscape: #{inkscape.available? ? "OK" : "MISSING"}"
330
+ puts " Path: #{inkscape.executable}"
331
+ puts " Version: #{inkscape.version}"
332
+
333
+ gs = Vectory::GhostscriptWrapper.instance
334
+ puts "Ghostscript: #{gs.available? ? "OK" : "MISSING"}"
335
+ puts " Path: #{gs.executable}"
336
+ ----
337
+
338
+ ### Test Conversion Simple File
339
+
340
+ [source,ruby]
341
+ ----
342
+ # Create simple SVG for testing
343
+ test_svg = '<svg width="100" height="100"><rect width="100" height="100" fill="red"/></svg>'
344
+
345
+ File.write("test.svg", test_svg)
346
+
347
+ # Test conversion
348
+ begin
349
+ svg = Vectory::Svg.from_path("test.svg")
350
+ eps = svg.to_eps
351
+ puts "Conversion successful!"
352
+ rescue => e
353
+ puts "Conversion failed: #{e.message}"
354
+ ensure
355
+ File.delete("test.svg") if File.exist?("test.svg")
356
+ end
357
+ ----
358
+
359
+ ## Platform-Specific Issues
360
+
361
+ ### macOS
362
+
363
+ **Inkscape timeout**:
364
+
365
+ [source,ruby]
366
+ ----
367
+ # Vectory automatically sets this, but you can also set manually
368
+ ENV["DISPLAY"] = ""
369
+ ----
370
+
371
+ ### Windows
372
+
373
+ **Inkscape 1.3.1+ EPS issues**:
374
+
375
+ * Use Inkscape 1.3.0 instead
376
+ * Download from: https://inkscape.org/gallery/item/inkscape-1.3.0/
377
+
378
+ **Process management**:
379
+
380
+ [source,ruby]
381
+ ----
382
+ # Windows uses taskkill instead of Process.kill
383
+ # This is handled automatically by Vectory
384
+ ----
385
+
386
+ ### Linux
387
+
388
+ **Permission errors**:
389
+
390
+ [source,shell]
391
+ ----
392
+ # Ensure proper permissions
393
+ chmod +x diagrams/*
394
+ ----
395
+
396
+ ## See Also
397
+
398
+ * link:../features/external-dependencies/[External Dependencies] - Tool requirements
399
+ * link:../understanding/error-classes/[Error Classes] - Error hierarchy
400
+ * link:../reference/api/[API Reference] - Method documentation
@@ -0,0 +1,197 @@
1
+ ---
2
+ layout: default
3
+ title: Guides
4
+ nav_order: 6
5
+ has_children: true
6
+ ---
7
+ = Guides
8
+
9
+ Step-by-step guides for common Vectory tasks.
10
+
11
+ == Overview
12
+
13
+ This section provides practical, task-oriented guides for using Vectory. Each guide focuses on a specific use case with detailed examples.
14
+
15
+ == Getting Started Guides
16
+
17
+ link:batch-processing[**Batch Processing Images**]::
18
+ Convert multiple images in a directory.
19
+ +
20
+ Iterate through files, convert formats, handle errors.
21
+
22
+ link:error-handling[**Error Handling**]::
23
+ Common errors and how to resolve them.
24
+ +
25
+ Missing tools, conversion failures, timeout issues.
26
+
27
+ link:dimension-query[**Querying Image Dimensions**]::
28
+ Get image dimensions without full conversion.
29
+ +
30
+ Fast dimension retrieval for validation.
31
+
32
+ == Conversion Guides
33
+
34
+ link:eps-to-svg[**Converting EPS to SVG**]::
35
+ Complete EPS to SVG conversion workflow.
36
+ +
37
+ Ghostscript + Inkscape pipeline, bounding box preservation.
38
+
39
+ link:svg-to-emf[**Converting SVG to EMF**]::
40
+ SVG to EMF conversion for Windows compatibility.
41
+ +
42
+ Inkscape conversion, quality considerations.
43
+
44
+ link:emf-to-svg[**Converting EMF to SVG**]::
45
+ EMF to SVG conversion workflow.
46
+ +
47
+ emf2svg integration, output validation.
48
+
49
+ == Integration Guides
50
+
51
+ link:metanorma-integration[**Metanorma Integration**]::
52
+ Using Vectory with Metanorma documents.
53
+ +
54
+ SVG mapping, link rewriting, XML processing.
55
+
56
+ link:rails-integration[**Rails Integration**]::
57
+ Using Vectory in Ruby on Rails applications.
58
+ +
59
+ Active Storage integration, background jobs.
60
+
61
+ link:cli-integration[**Command-Line Integration**]::
62
+ Using Vectory in shell scripts and CI/CD.
63
+ +
64
+ One-liners, batch processing, error handling.
65
+
66
+ == Advanced Guides
67
+
68
+ link:custom-configuration[**Custom Configuration**]::
69
+ Configuring Vectory for specific needs.
70
+ +
71
+ Environment variables, tool paths, timeout settings.
72
+
73
+ link:performance-optimization[**Performance Optimization**]::
74
+ Tips for faster conversions.
75
+ +
76
+ Caching, batch processing, parallel execution.
77
+
78
+ link:debugging[**Debugging Conversion Issues**]::
79
+ Troubleshooting failed conversions.
80
+ +
81
+ Verbose logging, intermediate file inspection.
82
+
83
+ == Quick Reference Guides
84
+
85
+ === Common Conversions
86
+
87
+ [cols="1,1,1a"]
88
+ |===
89
+ |Input Format|Output Format|Method
90
+
91
+ |EPS
92
+ |SVG
93
+ |`Vectory::Eps.from_path(file).to_svg`
94
+
95
+ |PS
96
+ |SVG
97
+ |`Vectory::Ps.from_path(file).to_svg`
98
+
99
+ |EMF
100
+ |SVG
101
+ |`Vectory::Emf.from_path(file).to_svg`
102
+
103
+ |SVG
104
+ |EPS
105
+ |`Vectory::Svg.from_path(file).to_eps`
106
+
107
+ |SVG
108
+ |PDF
109
+ |`Vectory::Svg.from_path(file).to_pdf`
110
+ |===
111
+
112
+ === Error Resolution
113
+
114
+ [cols="1,2a"]
115
+ |===
116
+ |Error|Solution
117
+
118
+ |`InkscapeNotFoundError`
119
+ |Install Inkscape and ensure it's in PATH
120
+
121
+ |`SystemCallError` (timeout)
122
+ |Increase timeout or check input file
123
+
124
+ |`ParsingError`
125
+ |Verify file format and content
126
+
127
+ |`NotWrittenToDiskError`
128
+ |Call `write()` before accessing `path`
129
+ |===
130
+
131
+ == Example Workflows
132
+
133
+ === Basic Conversion Workflow
134
+
135
+ . Load image from file
136
+ . Convert to desired format
137
+ . Write to output location
138
+
139
+ [source,ruby]
140
+ ----
141
+ require 'vectory'
142
+
143
+ # Load EPS file
144
+ eps = Vectory::Eps.from_path("input.eps")
145
+
146
+ # Convert to SVG
147
+ svg = eps.to_svg
148
+
149
+ # Write to file
150
+ svg.write("output.svg")
151
+ ----
152
+
153
+ === Batch Conversion Workflow
154
+
155
+ . Iterate through input directory
156
+ . Detect file format
157
+ . Convert to target format
158
+ . Handle errors gracefully
159
+
160
+ [source,ruby]
161
+ ----
162
+ require 'vectory'
163
+
164
+ Dir["input/*.eps"].each do |file|
165
+ begin
166
+ svg = Vectory::Eps.from_path(file).to_svg
167
+ svg.write(File.join("output", File.basename(file, ".eps") + ".svg"))
168
+ puts "Converted: #{file}"
169
+ rescue Vectory::Error => e
170
+ warn "Failed to convert #{file}: #{e.message}"
171
+ end
172
+ end
173
+ ----
174
+
175
+ === Dimension Query Workflow
176
+
177
+ . Load image
178
+ . Query dimensions
179
+ . Use dimensions for validation or layout
180
+
181
+ [source,ruby]
182
+ ----
183
+ require 'vectory'
184
+
185
+ eps = Vectory::Eps.from_path("diagram.eps")
186
+ width, height = eps.dimensions
187
+
188
+ if width > 1000 || height > 1000
189
+ puts "Warning: Image dimensions are large"
190
+ end
191
+ ----
192
+
193
+ == See Also
194
+
195
+ * link:../features/[Features] - Feature documentation
196
+ * link:../understanding/[Understanding] - Internal architecture
197
+ * link:../reference/[Reference] - Complete API documentation