ukiryu 0.1.1 → 0.1.3

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 (113) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +58 -14
  3. data/.gitignore +3 -0
  4. data/.rubocop_todo.yml +170 -79
  5. data/Gemfile +1 -1
  6. data/README.adoc +1603 -576
  7. data/docs/.gitignore +1 -0
  8. data/docs/Gemfile +10 -0
  9. data/docs/INDEX.adoc +261 -0
  10. data/docs/_config.yml +180 -0
  11. data/docs/advanced/custom-tool-classes.adoc +581 -0
  12. data/docs/advanced/index.adoc +20 -0
  13. data/docs/features/configuration.adoc +657 -0
  14. data/docs/features/index.adoc +31 -0
  15. data/docs/features/platform-support.adoc +488 -0
  16. data/docs/getting-started/core-concepts.adoc +666 -0
  17. data/docs/getting-started/index.adoc +36 -0
  18. data/docs/getting-started/installation.adoc +216 -0
  19. data/docs/getting-started/quick-start.adoc +258 -0
  20. data/docs/guides/env-var-sets.adoc +388 -0
  21. data/docs/guides/index.adoc +20 -0
  22. data/docs/interfaces/cli.adoc +609 -0
  23. data/docs/interfaces/index.adoc +153 -0
  24. data/docs/interfaces/ruby-api.adoc +538 -0
  25. data/docs/lychee.toml +49 -0
  26. data/docs/reference/configuration-options.adoc +720 -0
  27. data/docs/reference/error-codes.adoc +634 -0
  28. data/docs/reference/index.adoc +20 -0
  29. data/docs/reference/ruby-api.adoc +1217 -0
  30. data/docs/understanding/index.adoc +20 -0
  31. data/lib/ukiryu/cli.rb +43 -58
  32. data/lib/ukiryu/cli_commands/base_command.rb +16 -27
  33. data/lib/ukiryu/cli_commands/cache_command.rb +100 -0
  34. data/lib/ukiryu/cli_commands/commands_command.rb +8 -8
  35. data/lib/ukiryu/cli_commands/commands_command.rb.fixed +1 -1
  36. data/lib/ukiryu/cli_commands/config_command.rb +49 -7
  37. data/lib/ukiryu/cli_commands/definitions_command.rb +254 -0
  38. data/lib/ukiryu/cli_commands/describe_command.rb +13 -7
  39. data/lib/ukiryu/cli_commands/describe_command.rb.fixed +1 -1
  40. data/lib/ukiryu/cli_commands/docs_command.rb +148 -0
  41. data/lib/ukiryu/cli_commands/exec_inline_command.rb.fixed +1 -1
  42. data/lib/ukiryu/cli_commands/extract_command.rb +2 -2
  43. data/lib/ukiryu/cli_commands/info_command.rb +7 -7
  44. data/lib/ukiryu/cli_commands/lint_command.rb +167 -0
  45. data/lib/ukiryu/cli_commands/list_command.rb +6 -6
  46. data/lib/ukiryu/cli_commands/opts_command.rb +2 -2
  47. data/lib/ukiryu/cli_commands/opts_command.rb.fixed +1 -1
  48. data/lib/ukiryu/cli_commands/register_command.rb +144 -0
  49. data/lib/ukiryu/cli_commands/resolve_command.rb +124 -0
  50. data/lib/ukiryu/cli_commands/run_command.rb +38 -14
  51. data/lib/ukiryu/cli_commands/run_file_command.rb +2 -2
  52. data/lib/ukiryu/cli_commands/system_command.rb +50 -32
  53. data/lib/ukiryu/cli_commands/validate_command.rb +452 -51
  54. data/lib/ukiryu/cli_commands/which_command.rb +5 -5
  55. data/lib/ukiryu/command_builder.rb +81 -23
  56. data/lib/ukiryu/config/env_provider.rb +3 -3
  57. data/lib/ukiryu/config/env_schema.rb +6 -6
  58. data/lib/ukiryu/config.rb +11 -11
  59. data/lib/ukiryu/definition/definition_cache.rb +238 -0
  60. data/lib/ukiryu/definition/definition_composer.rb +257 -0
  61. data/lib/ukiryu/definition/definition_linter.rb +460 -0
  62. data/lib/ukiryu/definition/definition_validator.rb +320 -0
  63. data/lib/ukiryu/definition/discovery.rb +239 -0
  64. data/lib/ukiryu/definition/documentation_generator.rb +429 -0
  65. data/lib/ukiryu/definition/lint_issue.rb +168 -0
  66. data/lib/ukiryu/definition/loader.rb +139 -0
  67. data/lib/ukiryu/definition/metadata.rb +159 -0
  68. data/lib/ukiryu/definition/source.rb +87 -0
  69. data/lib/ukiryu/definition/sources/file.rb +138 -0
  70. data/lib/ukiryu/definition/sources/string.rb +88 -0
  71. data/lib/ukiryu/definition/validation_result.rb +158 -0
  72. data/lib/ukiryu/definition/version_resolver.rb +194 -0
  73. data/lib/ukiryu/definition.rb +40 -0
  74. data/lib/ukiryu/errors.rb +6 -0
  75. data/lib/ukiryu/execution_context.rb +11 -11
  76. data/lib/ukiryu/executor.rb +6 -0
  77. data/lib/ukiryu/extractors/extractor.rb +6 -5
  78. data/lib/ukiryu/extractors/help_parser.rb +13 -19
  79. data/lib/ukiryu/logger.rb +3 -1
  80. data/lib/ukiryu/models/command_definition.rb +3 -3
  81. data/lib/ukiryu/models/command_info.rb +1 -1
  82. data/lib/ukiryu/models/components.rb +1 -3
  83. data/lib/ukiryu/models/env_var_definition.rb +11 -3
  84. data/lib/ukiryu/models/flag_definition.rb +15 -0
  85. data/lib/ukiryu/models/option_definition.rb +7 -7
  86. data/lib/ukiryu/models/platform_profile.rb +6 -3
  87. data/lib/ukiryu/models/routing.rb +1 -1
  88. data/lib/ukiryu/models/tool_definition.rb +2 -4
  89. data/lib/ukiryu/models/tool_metadata.rb +6 -6
  90. data/lib/ukiryu/models/validation_result.rb +1 -1
  91. data/lib/ukiryu/models/version_compatibility.rb +6 -3
  92. data/lib/ukiryu/models/version_detection.rb +10 -1
  93. data/lib/ukiryu/{registry.rb → register.rb} +54 -38
  94. data/lib/ukiryu/register_auto_manager.rb +268 -0
  95. data/lib/ukiryu/schema_validator.rb +31 -10
  96. data/lib/ukiryu/shell/base.rb +18 -0
  97. data/lib/ukiryu/shell/bash.rb +19 -1
  98. data/lib/ukiryu/shell/cmd.rb +11 -1
  99. data/lib/ukiryu/shell/powershell.rb +11 -1
  100. data/lib/ukiryu/shell.rb +1 -1
  101. data/lib/ukiryu/tool.rb +107 -95
  102. data/lib/ukiryu/tool_index.rb +22 -22
  103. data/lib/ukiryu/tools/base.rb +12 -25
  104. data/lib/ukiryu/tools/generator.rb +7 -7
  105. data/lib/ukiryu/tools.rb +3 -3
  106. data/lib/ukiryu/type.rb +20 -5
  107. data/lib/ukiryu/version.rb +1 -1
  108. data/lib/ukiryu/version_detector.rb +21 -2
  109. data/lib/ukiryu.rb +6 -3
  110. data/ukiryu-proposal.md +41 -41
  111. data/ukiryu.gemspec +1 -0
  112. metadata +64 -8
  113. data/.gitmodules +0 -3
@@ -0,0 +1,581 @@
1
+ ---
2
+ layout: default
3
+ title: Custom Tool Classes
4
+ parent: Advanced
5
+ nav_order: 3
6
+ ---
7
+
8
+ == Custom Tool Classes
9
+
10
+ You can extend Ukiryu tool classes to create custom behavior specific to your application's needs.
11
+
12
+ // Purpose
13
+ == Purpose
14
+
15
+ This page documents how to create custom tool classes by extending Ukiryu's generated tool classes using standard Ruby inheritance.
16
+
17
+ // References
18
+ == References
19
+
20
+ * link:/interfaces/ruby-api[Ruby API Documentation]
21
+ * link:/advanced/writing-profiles[Writing Tool Profiles]
22
+
23
+ // Concepts
24
+ == Concepts
25
+
26
+ * **Tool class inheritance**: Standard Ruby subclassing of dynamically generated tool classes
27
+ * **Domain-specific wrappers**: Custom methods that encapsulate common workflows
28
+ * **Direct inheritance**: Subclassing the tool class for full access to all methods
29
+ * **Wrapper pattern**: Composing the tool class for isolation and flexibility
30
+
31
+ // Getting Tool Classes
32
+ == Getting Tool Classes
33
+
34
+ Ukiryu provides two ways to access tool classes:
35
+
36
+ === Traditional API (Instance-based)
37
+
38
+ Returns an instance of the tool:
39
+
40
+ [source,ruby]
41
+ ----
42
+ tool = Ukiryu::Tool.get(:inkscape)
43
+ result = tool.execute(:export, { inputs: ['input.svg'], output: 'output.png' })
44
+ ----
45
+
46
+ Use this when: You need quick, one-off tool execution without customization.
47
+
48
+ === OOP API (Class-based)
49
+
50
+ Returns the tool class for subclassing:
51
+
52
+ [source,ruby]
53
+ ----
54
+ inkscape_class = Ukiryu::Tools.get_class(:inkscape)
55
+ # Or use it directly for inheritance
56
+ class MyTool < Ukiryu::Tools.get_class(:inkscape)
57
+ end
58
+ ----
59
+
60
+ Use this when: You want to create custom tool classes with specialized behavior.
61
+
62
+ // Direct Inheritance Pattern
63
+ == Direct Inheritance Pattern
64
+
65
+ Subclass the tool class directly to add custom methods while retaining full access to all tool functionality.
66
+
67
+ === Basic Example
68
+
69
+ Create a specialized thumbnail generator:
70
+
71
+ [source,ruby]
72
+ ----
73
+ class ThumbnailInkscape < Ukiryu::Tools.get_class(:inkscape)
74
+ def generate_thumbnail(input, output, size: 150)
75
+ execute(:export, {
76
+ inputs: [input],
77
+ output: output,
78
+ width: size,
79
+ height: size,
80
+ dpi: 72
81
+ })
82
+ end
83
+ end
84
+
85
+ # Use your custom tool
86
+ tool = ThumbnailInkscape.new
87
+ tool.generate_thumbnail('drawing.svg', 'thumbnail.png', size: 200)
88
+ ----
89
+
90
+ === Multiple Specialized Methods
91
+
92
+ Create a tool with multiple domain-specific operations:
93
+
94
+ [source,ruby]
95
+ ----
96
+ class AssetGenerator < Ukiryu::Tools.get_class(:inkscape)
97
+ # Generate icons for web use
98
+ def icon_set(input, basename)
99
+ execute(:export, inputs: [input], output: "#{basename}_icon.png", width: 32, height: 32)
100
+ execute(:export, inputs: [input], output: "#{basename}_icon@2x.png", width: 64, height: 64)
101
+ end
102
+
103
+ # Generate high-resolution export
104
+ def print_export(input, output)
105
+ execute(:export, {
106
+ inputs: [input],
107
+ output: output,
108
+ dpi: 300,
109
+ export_text_to_path: true
110
+ })
111
+ end
112
+
113
+ # Generate optimized web image
114
+ def web_image(input, output)
115
+ execute(:export, {
116
+ inputs: [input],
117
+ output: output,
118
+ dpi: 96
119
+ })
120
+ end
121
+ end
122
+
123
+ tool = AssetGenerator.new
124
+ tool.icon_set('logo.svg', 'app')
125
+ tool.print_export('document.svg', 'document-print.png')
126
+ tool.web_image('banner.svg', 'banner.png')
127
+ ----
128
+
129
+ === Parameter Templates
130
+
131
+ Create methods that pre-configure common parameter sets:
132
+
133
+ [source,ruby]
134
+ ----
135
+ class PdfConverter < Ukiryu::Tools.get_class(:inkscape)
136
+ def convert_to_pdf(input, output, options = {})
137
+ params = {
138
+ inputs: [input],
139
+ output: output,
140
+ export_text_to_path: true,
141
+ export_ignore_filters: false
142
+ }.merge(options)
143
+
144
+ execute(:export, params)
145
+ end
146
+ end
147
+
148
+ # Use default settings
149
+ tool = PdfConverter.new
150
+ tool.convert_to_pdf('drawing.svg', 'drawing.pdf')
151
+
152
+ # Override specific settings
153
+ tool.convert_to_pdf('drawing.svg', 'drawing.pdf', export_text_to_path: false)
154
+ ----
155
+
156
+ // Wrapper Pattern
157
+ == Wrapper Pattern
158
+
159
+ Compose the tool class instead of inheriting, providing complete isolation from the underlying tool implementation.
160
+
161
+ === When to Use Wrapper Pattern
162
+
163
+ Use the wrapper pattern when you need:
164
+
165
+ * Complete isolation from tool API changes
166
+ * Selective exposure of tool methods
167
+ * Custom error handling
168
+ * Integration with non-Ukiryu code
169
+
170
+ === Basic Wrapper
171
+
172
+ Create a clean interface that exposes only what you need:
173
+
174
+ [source,ruby]
175
+ ----
176
+ class ThumbnailService
177
+ def initialize
178
+ @tool = Ukiryu::Tools.get_class(:inkscape).new
179
+ end
180
+
181
+ def create(input, output, size: 150)
182
+ result = @tool.execute(:export, {
183
+ inputs: [input],
184
+ output: output,
185
+ width: size,
186
+ height: size
187
+ })
188
+
189
+ raise "Thumbnail generation failed: #{result.stderr}" unless result.success?
190
+
191
+ result
192
+ end
193
+
194
+ def batch_create(inputs, output_dir, size: 150)
195
+ inputs.map do |input|
196
+ basename = File.basename(input, '.svg')
197
+ output = File.join(output_dir, "#{basename}_thumb.png")
198
+ create(input, output, size: size)
199
+ end
200
+ end
201
+ end
202
+
203
+ service = ThumbnailService.new
204
+ service.create('drawing.svg', 'drawing_thumb.png')
205
+ service.batch_create(Dir['*.svg'], 'thumbnails', size: 200)
206
+ ----
207
+
208
+ === Method Forwarding
209
+
210
+ Use `method_missing` to forward undefined methods to the wrapped tool:
211
+
212
+ [source,ruby]
213
+ ----
214
+ class InkscapeWrapper
215
+ def initialize(tool_class: Ukiryu::Tools.get_class(:inkscape))
216
+ @tool = tool_class.new
217
+ end
218
+
219
+ # Custom methods
220
+ def quick_export(input, output)
221
+ @tool.execute(:export, inputs: [input], output: output, dpi: 96)
222
+ end
223
+
224
+ # Forward all other methods to the tool
225
+ def method_missing(name, *args, &block)
226
+ @tool.send(name, *args, &block)
227
+ end
228
+
229
+ def respond_to_missing?(name, include_private = false)
230
+ @tool.respond_to?(name, include_private) || super
231
+ end
232
+ end
233
+
234
+ wrapper = InkscapeWrapper.new
235
+ wrapper.quick_export('file.svg', 'file.png') # Custom method
236
+ wrapper.execute(:query, inputs: ['file.svg']) # Forwarded method
237
+ wrapper.version # Forwarded method
238
+ ----
239
+
240
+ === Multi-Tool Wrapper
241
+
242
+ Wrap multiple tools in a single cohesive interface:
243
+
244
+ [source,ruby]
245
+ ----
246
+ class GraphicsPipeline
247
+ def initialize
248
+ @inkscape = Ukiryu::Tools.get_class(:inkscape).new
249
+ @imagemagick = Ukiryu::Tools.get_class(:imagemagick).new
250
+ end
251
+
252
+ def svg_to_optimized_png(input, output)
253
+ # Export SVG to PNG with Inkscape
254
+ @inkscape.execute(:export, inputs: [input], output: output, dpi: 150)
255
+
256
+ # Optimize with ImageMagick
257
+ @imagemagick.execute(:mogrify, inputs: [output], strip: true, quality: 85)
258
+ end
259
+
260
+ def batch_convert(input_dir, output_dir)
261
+ Dir[File.join(input_dir, '*.svg')].each do |input|
262
+ basename = File.basename(input, '.svg')
263
+ output = File.join(output_dir, "#{basename}.png")
264
+ svg_to_optimized_png(input, output)
265
+ end
266
+ end
267
+ end
268
+
269
+ pipeline = GraphicsPipeline.new
270
+ pipeline.svg_to_optimized_png('drawing.svg', 'drawing.png')
271
+ pipeline.batch_convert('assets/svg', 'assets/png')
272
+ ----
273
+
274
+ // Pattern Comparison
275
+ == Pattern Comparison
276
+
277
+ === By Use Case
278
+
279
+ [cols="1,1,4"]
280
+ |===
281
+ |Use Case |Recommended Pattern |Rationale
282
+
283
+ |Application-specific tools
284
+ |Direct Inheritance
285
+ |Full access to tool methods, minimal boilerplate
286
+
287
+ |Library/API design
288
+ |Wrapper Pattern
289
+ |Isolation from API changes, controlled interface
290
+
291
+ |Internal scripts
292
+ |Direct Inheritance
293
+ |Quick implementation, direct tool access
294
+
295
+ |Complex workflows
296
+ |Wrapper Pattern
297
+ |Custom orchestration, multi-tool composition
298
+
299
+ |Testing/mocking
300
+ |Wrapper Pattern
301
+ |Easy to inject mock tool implementations
302
+ |===
303
+
304
+ === By Characteristic
305
+
306
+ [cols="1,1,1"]
307
+ |===
308
+ |Characteristic |Direct Inheritance |Wrapper Pattern
309
+
310
+ |Tool method access
311
+ |All methods available
312
+ |Selective exposure
313
+
314
+ |Isolation from changes
315
+ |Low (inherits API changes)
316
+ |High (controlled interface)
317
+
318
+ |Boilerplate code
319
+ |Minimal
320
+ |More (forwarding needed)
321
+
322
+ |Customization flexibility
323
+ |High (can override methods)
324
+ |High (any interface design)
325
+
326
+ |Testing ease
327
+ |Moderate
328
+ |High (easy to mock)
329
+
330
+ |Learning curve
331
+ |Low (standard inheritance)
332
+ |Moderate (composition patterns)
333
+ |===
334
+
335
+ // Best Practices
336
+ == Best Practices
337
+
338
+ === Naming Conventions
339
+
340
+ Use descriptive names that indicate the tool's purpose:
341
+
342
+ [source,ruby]
343
+ ----
344
+ # Good - descriptive and specific
345
+ class ThumbnailInkscape < Ukiryu::Tools.get_class(:inkscape)
346
+ end
347
+
348
+ class AssetGenerator < Ukiryu::Tools.get_class(:inkscape)
349
+ end
350
+
351
+ class PdfConverter < Ukiryu::Tools.get_class(:inkscape)
352
+ end
353
+
354
+ # Avoid - too generic
355
+ class MyTool < Ukiryu::Tools.get_class(:inkscape)
356
+ end
357
+
358
+ class CustomInkscape < Ukiryu::Tools.get_class(:inkscape)
359
+ end
360
+ ----
361
+
362
+ === Error Handling
363
+
364
+ Add appropriate error handling for custom methods:
365
+
366
+ [source,ruby]
367
+ ----
368
+ class RobustExporter < Ukiryu::Tools.get_class(:inkscape)
369
+ def safe_export(input, output, options = {})
370
+ raise ArgumentError, "Input file not found: #{input}" unless File.exist?(input)
371
+
372
+ result = execute(:export, {
373
+ inputs: [input],
374
+ output: output
375
+ }.merge(options))
376
+
377
+ unless result.success?
378
+ raise "Export failed: #{result.stderr}"
379
+ end
380
+
381
+ result
382
+ end
383
+ end
384
+ ----
385
+
386
+ === Documentation
387
+
388
+ Document your custom methods clearly:
389
+
390
+ [source,ruby]
391
+ ----
392
+ class DocumentConverter < Ukiryu::Tools.get_class(:inkscape)
393
+ # Convert SVG to PDF with print-optimized settings
394
+ #
395
+ # @param input [String] Path to input SVG file
396
+ # @param output [String] Path to output PDF file
397
+ # @return [Result] Execution result
398
+ # @raise [RuntimeError] If conversion fails
399
+ #
400
+ # Uses 300 DPI and exports text to paths for print compatibility.
401
+ def to_pdf(input, output)
402
+ execute(:export, {
403
+ inputs: [input],
404
+ output: output,
405
+ dpi: 300,
406
+ export_text_to_path: true
407
+ }).tap do |result|
408
+ raise "PDF conversion failed" unless result.success?
409
+ end
410
+ end
411
+ end
412
+ ----
413
+
414
+ === Configuration
415
+
416
+ Use class-level configuration for defaults:
417
+
418
+ [source,ruby]
419
+ ----
420
+ class ConfigurableConverter < Ukiryu::Tools.get_class(:inkscape)
421
+ class << self
422
+ attr_accessor :default_dpi, :default_format
423
+
424
+ def configure
425
+ yield self
426
+ end
427
+ end
428
+
429
+ self.default_dpi = 96
430
+ self.default_format = :png
431
+
432
+ def convert(input, output, options = {})
433
+ params = {
434
+ inputs: [input],
435
+ output: output,
436
+ dpi: self.class.default_dpi
437
+ }.merge(options)
438
+
439
+ execute(:export, params)
440
+ end
441
+ end
442
+
443
+ # Configure globally
444
+ ConfigurableConverter.configure do |config|
445
+ config.default_dpi = 300
446
+ config.default_format = :svg
447
+ end
448
+
449
+ tool = ConfigurableConverter.new
450
+ tool.convert('file.svg', 'file.png') # Uses 300 DPI default
451
+ ----
452
+
453
+ // Reload Behavior
454
+ == Reload Behavior
455
+
456
+ Tool classes are generated once when the application starts and remain cached for the lifetime of the process.
457
+
458
+ === Profile Updates
459
+
460
+ When tool profiles are updated:
461
+
462
+ * New methods/parameters are available after application restart
463
+ * Existing custom classes continue to work with the updated profiles
464
+ * Removed methods will cause `NoMethodError` until the custom class is updated
465
+
466
+ === Development Workflow
467
+
468
+ For development, restart your application after profile changes:
469
+
470
+ [source,bash]
471
+ ----
472
+ # In development
473
+ bundle exec rackup -s thin -O
474
+
475
+ # After profile changes, restart (Ctrl+C then run again)
476
+ ----
477
+
478
+ For production, deploy updated code and profiles together:
479
+
480
+ [source,bash]
481
+ ----
482
+ # Deploy updated profiles and code
483
+ git pull
484
+ bundle exec pumactl -P tmp/pids/puma.pid phased-restart
485
+ ----
486
+
487
+ // Complete Example
488
+ == Complete Example
489
+
490
+ A complete asset pipeline using custom tool classes:
491
+
492
+ [source,ruby]
493
+ ----
494
+ # lib/asset_pipeline.rb
495
+
496
+ require 'ukiryu'
497
+
498
+ # SVG to PNG converter with standard web settings
499
+ class WebAssetConverter < Ukiryu::Tools.get_class(:inkscape)
500
+ # Standard web-optimized PNG
501
+ def web_png(input, output)
502
+ execute(:export, {
503
+ inputs: [input],
504
+ output: output,
505
+ dpi: 96,
506
+ export_text_to_path: false
507
+ })
508
+ end
509
+
510
+ # High-DPI (Retina) version
511
+ def high_dpi_png(input, output, scale: 2)
512
+ execute(:export, {
513
+ inputs: [input],
514
+ output: output,
515
+ dpi: 96 * scale
516
+ })
517
+ end
518
+
519
+ # Icon set generation
520
+ def icon_set(input, basename, sizes: [16, 32, 64, 128, 256])
521
+ sizes.each do |size|
522
+ execute(:export, {
523
+ inputs: [input],
524
+ output: "#{basename}_#{size}x#{size}.png",
525
+ width: size,
526
+ height: size,
527
+ dpi: 96
528
+ })
529
+ end
530
+ end
531
+ end
532
+
533
+ # Asset pipeline that orchestrates conversion
534
+ class AssetPipeline
535
+ def initialize(source_dir, output_dir)
536
+ @source_dir = source_dir
537
+ @output_dir = output_dir
538
+ @converter = WebAssetConverter.new
539
+ end
540
+
541
+ def process_all
542
+ ensure_output_dir
543
+
544
+ svg_files.each do |svg_file|
545
+ basename = File.basename(svg_file, '.svg')
546
+ process_asset(svg_file, basename)
547
+ end
548
+ end
549
+
550
+ private
551
+
552
+ def ensure_output_dir
553
+ FileUtils.mkdir_p(@output_dir)
554
+ end
555
+
556
+ def svg_files
557
+ Dir[File.join(@source_dir, '*.svg')]
558
+ end
559
+
560
+ def process_asset(input_file, basename)
561
+ output_file = File.join(@output_dir, "#{basename}.png")
562
+
563
+ puts "Processing #{basename}..."
564
+ @converter.web_png(input_file, output_file)
565
+ puts " ✓ Created #{basename}.png"
566
+ end
567
+ end
568
+
569
+ # Usage
570
+ if __FILE__ == $PROGRAM_NAME
571
+ pipeline = AssetPipeline.new('assets/svg', 'assets/png')
572
+ pipeline.process_all
573
+ end
574
+ ----
575
+
576
+ // See Also
577
+ == See Also
578
+
579
+ * link:/interfaces/ruby-api[Ruby API] - Tool class reference
580
+ * link:/advanced/writing-profiles[Writing Tool Profiles] - Creating custom tool definitions
581
+ * link:/features/configuration[Configuration Methods] - Setting up tool behavior
@@ -0,0 +1,20 @@
1
+ ---
2
+ layout: default
3
+ title: Advanced
4
+ nav_order: 7
5
+ has_children: true
6
+ ---
7
+
8
+ = Advanced
9
+
10
+ Advanced topics for extending and customizing Ukiryu.
11
+
12
+ // Overview
13
+ == Overview
14
+
15
+ This section covers advanced usage and extension:
16
+
17
+ * link:/advanced/writing-profiles[Writing Tool Profiles] - Create custom tool profiles
18
+ * link:/advanced/tool-versions[Tool Version Management] - Multiple versions and compatibility
19
+ * link:/advanced/platform-handling[Platform-Specific Handling] - Advanced platform adaptation
20
+ * link:/advanced/performance[Performance Optimization] - Caching and optimization