svg_conform 0.1.1 → 0.1.2

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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +273 -10
  3. data/README.adoc +7 -8
  4. data/examples/readme_usage.rb +67 -0
  5. data/examples/requirements_demo.rb +4 -4
  6. data/lib/svg_conform/document.rb +7 -1
  7. data/lib/svg_conform/element_proxy.rb +101 -0
  8. data/lib/svg_conform/fast_document_analyzer.rb +82 -0
  9. data/lib/svg_conform/node_index_builder.rb +47 -0
  10. data/lib/svg_conform/requirements/allowed_elements_requirement.rb +202 -0
  11. data/lib/svg_conform/requirements/base_requirement.rb +27 -0
  12. data/lib/svg_conform/requirements/color_restrictions_requirement.rb +53 -0
  13. data/lib/svg_conform/requirements/font_family_requirement.rb +18 -0
  14. data/lib/svg_conform/requirements/forbidden_content_requirement.rb +26 -0
  15. data/lib/svg_conform/requirements/id_reference_requirement.rb +96 -0
  16. data/lib/svg_conform/requirements/invalid_id_references_requirement.rb +91 -0
  17. data/lib/svg_conform/requirements/link_validation_requirement.rb +30 -0
  18. data/lib/svg_conform/requirements/namespace_attributes_requirement.rb +59 -0
  19. data/lib/svg_conform/requirements/namespace_requirement.rb +74 -0
  20. data/lib/svg_conform/requirements/no_external_css_requirement.rb +74 -0
  21. data/lib/svg_conform/requirements/no_external_fonts_requirement.rb +58 -0
  22. data/lib/svg_conform/requirements/no_external_images_requirement.rb +40 -0
  23. data/lib/svg_conform/requirements/style_requirement.rb +12 -0
  24. data/lib/svg_conform/requirements/viewbox_required_requirement.rb +72 -0
  25. data/lib/svg_conform/sax_document.rb +46 -0
  26. data/lib/svg_conform/sax_validation_handler.rb +158 -0
  27. data/lib/svg_conform/validation_context.rb +84 -2
  28. data/lib/svg_conform/validator.rb +74 -6
  29. data/lib/svg_conform/version.rb +1 -1
  30. data/lib/svg_conform.rb +1 -0
  31. metadata +8 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ccf420a3e00222240dcc3f07c6af8ca2433e1e355fc2d14a3f250c81dc8accf0
4
- data.tar.gz: 1adfc48ed569e13d1d4f0929e22558bde3abb8239cd19f4f95f7a5e86321db7a
3
+ metadata.gz: 43ff84b9d1f47a6a2bd92624483c0445bd3f77d29f0fc36f2c02116a40111bc2
4
+ data.tar.gz: be072c8772885cd746ee623e028e00517dfcac93250a00f4015cb7122d94739a
5
5
  SHA512:
6
- metadata.gz: 7c71c121b3e79519ab5453152b86a21e2dba29cf4c43a6f62521796b474571ec9808b1b522f606df4c70dd8e3ddc4d02467bf693f2578731b832084dfb70f630
7
- data.tar.gz: f95e84b684c86fdc2235c39b86283bde8de5aaa565c6a454bb6181cae1549a2ea1d5e5ca20840902bdb3660fe2eaf0c151368a9c329655059343acbe0a9e2801
6
+ metadata.gz: 0ee8ad3bfab5a2aec10b32caa23141967aa25112e0393ed39242ab83a5f123bb317190392df347f7f4a8665af61bf7de4b09eb3283c4c140e372af1177ba924b
7
+ data.tar.gz: 20d1871024c131298aa2462bd849e07dfb16b73f2f61913da8f9c2d21b43e87fcfe5ae6ed298971091c0f85734efe8a36790432ccdb18c8878dafc25d238a348
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2025-10-12 09:36:25 UTC using RuboCop version 1.81.1.
3
+ # on 2025-11-18 13:36:55 UTC using RuboCop version 1.81.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -14,13 +14,116 @@ Layout/BlockAlignment:
14
14
  Exclude:
15
15
  - 'spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb'
16
16
 
17
- # Offense count: 513
17
+ # Offense count: 1
18
+ # This cop supports safe autocorrection (--autocorrect).
19
+ # Configuration parameters: AllowForAlignment.
20
+ Layout/CommentIndentation:
21
+ Exclude:
22
+ - 'lib/svg_conform/validation_context.rb'
23
+
24
+ # Offense count: 1
25
+ # This cop supports safe autocorrection (--autocorrect).
26
+ Layout/ElseAlignment:
27
+ Exclude:
28
+ - 'lib/svg_conform/requirements/namespace_attributes_requirement.rb'
29
+
30
+ # Offense count: 17
31
+ # This cop supports safe autocorrection (--autocorrect).
32
+ Layout/EmptyLineAfterGuardClause:
33
+ Exclude:
34
+ - 'analyze_error_nodes.rb'
35
+ - 'check_duplicates.rb'
36
+ - 'check_position_collisions.rb'
37
+ - 'check_unique_positions.rb'
38
+ - 'compare_errors.rb'
39
+ - 'debug_object_ids.rb'
40
+ - 'debug_utf8.rb'
41
+ - 'find_all_elements.rb'
42
+ - 'find_missing_errors.rb'
43
+ - 'lib/svg_conform/fast_document_analyzer.rb'
44
+ - 'lib/svg_conform/node_index_builder.rb'
45
+ - 'lib/svg_conform/requirements/id_reference_requirement.rb'
46
+ - 'lib/svg_conform/sax_validation_handler.rb'
47
+
48
+ # Offense count: 1
49
+ # This cop supports safe autocorrection (--autocorrect).
50
+ # Configuration parameters: EnforcedStyleAlignWith, Severity.
51
+ # SupportedStylesAlignWith: keyword, variable, start_of_line
52
+ Layout/EndAlignment:
53
+ Exclude:
54
+ - 'lib/svg_conform/requirements/namespace_attributes_requirement.rb'
55
+
56
+ # Offense count: 21
57
+ # This cop supports safe autocorrection (--autocorrect).
58
+ # Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
59
+ Layout/ExtraSpacing:
60
+ Exclude:
61
+ - 'find_missing_errors.rb'
62
+ - 'lib/svg_conform/element_proxy.rb'
63
+ - 'lib/svg_conform/requirements/id_reference_requirement.rb'
64
+ - 'lib/svg_conform/requirements/invalid_id_references_requirement.rb'
65
+ - 'lib/svg_conform/sax_validation_handler.rb'
66
+ - 'lib/svg_conform/validation_context.rb'
67
+ - 'lib/svg_conform/validator.rb'
68
+
69
+ # Offense count: 1
70
+ # This cop supports safe autocorrection (--autocorrect).
71
+ Layout/HeredocIndentation:
72
+ Exclude:
73
+ - 'test_sax_basic.rb'
74
+
75
+ # Offense count: 1
76
+ # This cop supports safe autocorrection (--autocorrect).
77
+ # Configuration parameters: EnforcedStyle.
78
+ # SupportedStyles: normal, indented_internal_methods
79
+ Layout/IndentationConsistency:
80
+ Exclude:
81
+ - 'lib/svg_conform/validation_context.rb'
82
+
83
+ # Offense count: 1
84
+ # This cop supports safe autocorrection (--autocorrect).
85
+ # Configuration parameters: Width, AllowedPatterns.
86
+ Layout/IndentationWidth:
87
+ Exclude:
88
+ - 'lib/svg_conform/requirements/namespace_attributes_requirement.rb'
89
+
90
+ # Offense count: 604
18
91
  # This cop supports safe autocorrection (--autocorrect).
19
92
  # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
20
93
  # URISchemes: http, https
21
94
  Layout/LineLength:
22
95
  Enabled: false
23
96
 
97
+ # Offense count: 28
98
+ # This cop supports safe autocorrection (--autocorrect).
99
+ # Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator, EnforcedStyleForRationalLiterals.
100
+ # SupportedStylesForExponentOperator: space, no_space
101
+ # SupportedStylesForRationalLiterals: space, no_space
102
+ Layout/SpaceAroundOperators:
103
+ Exclude:
104
+ - 'benchmark_sax.rb'
105
+ - 'benchmark_validation.rb'
106
+ - 'check_clippath_font.rb'
107
+ - 'check_unique_positions.rb'
108
+ - 'count_elements.rb'
109
+ - 'final_demo.rb'
110
+ - 'test_remediation.rb'
111
+
112
+ # Offense count: 32
113
+ # This cop supports safe autocorrection (--autocorrect).
114
+ # Configuration parameters: AllowInHeredoc.
115
+ Layout/TrailingWhitespace:
116
+ Exclude:
117
+ - 'analyze_error_nodes.rb'
118
+ - 'check_clippath_font.rb'
119
+ - 'debug_positions.rb'
120
+ - 'debug_utf8.rb'
121
+ - 'final_demo.rb'
122
+ - 'find_missing_errors.rb'
123
+ - 'lib/svg_conform/fast_document_analyzer.rb'
124
+ - 'lib/svg_conform/sax_document.rb'
125
+ - 'test_sax_basic.rb'
126
+
24
127
  # Offense count: 2
25
128
  # Configuration parameters: AllowedMethods.
26
129
  # AllowedMethods: enums
@@ -28,7 +131,7 @@ Lint/ConstantDefinitionInBlock:
28
131
  Exclude:
29
132
  - 'spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb'
30
133
 
31
- # Offense count: 18
134
+ # Offense count: 19
32
135
  # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
33
136
  Lint/DuplicateBranch:
34
137
  Exclude:
@@ -38,30 +141,65 @@ Lint/DuplicateBranch:
38
141
  - 'lib/svg_conform/semantic_comparator.rb'
39
142
  - 'lib/svg_conform/validation_context.rb'
40
143
  - 'lib/svg_conform/validation_result.rb'
144
+ - 'lib/svg_conform/validator.rb'
41
145
 
42
146
  # Offense count: 2
43
147
  Lint/DuplicateCaseCondition:
44
148
  Exclude:
45
149
  - 'lib/svg_conform/semantic_comparator.rb'
46
150
 
47
- # Offense count: 1
151
+ # Offense count: 2
48
152
  Lint/DuplicateMethods:
49
153
  Exclude:
154
+ - 'lib/svg_conform/sax_validation_handler.rb'
50
155
  - 'lib/svg_conform/validation_context.rb'
51
156
 
52
- # Offense count: 3
157
+ # Offense count: 1
158
+ # This cop supports safe autocorrection (--autocorrect).
159
+ Lint/IdentityComparison:
160
+ Exclude:
161
+ - 'lib/svg_conform/fast_document_analyzer.rb'
162
+
163
+ # Offense count: 4
53
164
  # Configuration parameters: AllowedParentClasses.
54
165
  Lint/MissingSuper:
55
166
  Exclude:
56
167
  - 'lib/svg_conform/compatibility/pattern_discovery.rb'
57
168
  - 'lib/svg_conform/compatibility/validity_analysis.rb'
169
+ - 'lib/svg_conform/sax_validation_handler.rb'
170
+
171
+ # Offense count: 3
172
+ # This cop supports safe autocorrection (--autocorrect).
173
+ Lint/ScriptPermission:
174
+ Exclude:
175
+ - 'benchmark_validation.rb'
176
+ - 'final_demo.rb'
177
+ - 'test_remediation.rb'
58
178
 
59
179
  # Offense count: 1
60
180
  Lint/UnreachableCode:
61
181
  Exclude:
62
182
  - 'lib/svg_conform/commands/check.rb'
63
183
 
64
- # Offense count: 126
184
+ # Offense count: 4
185
+ # This cop supports safe autocorrection (--autocorrect).
186
+ # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
187
+ # NotImplementedExceptions: NotImplementedError
188
+ Lint/UnusedMethodArgument:
189
+ Exclude:
190
+ - 'lib/svg_conform/element_proxy.rb'
191
+ - 'lib/svg_conform/requirements/id_reference_requirement.rb'
192
+ - 'lib/svg_conform/requirements/invalid_id_references_requirement.rb'
193
+ - 'lib/svg_conform/sax_validation_handler.rb'
194
+
195
+ # Offense count: 1
196
+ # This cop supports safe autocorrection (--autocorrect).
197
+ # Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
198
+ Lint/UselessAccessModifier:
199
+ Exclude:
200
+ - 'lib/svg_conform/requirements/namespace_attributes_requirement.rb'
201
+
202
+ # Offense count: 147
65
203
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
66
204
  Metrics/AbcSize:
67
205
  Enabled: false
@@ -72,17 +210,17 @@ Metrics/AbcSize:
72
210
  Metrics/BlockLength:
73
211
  Max: 253
74
212
 
75
- # Offense count: 3
213
+ # Offense count: 8
76
214
  # Configuration parameters: CountBlocks, CountModifierForms.
77
215
  Metrics/BlockNesting:
78
216
  Max: 4
79
217
 
80
- # Offense count: 105
218
+ # Offense count: 125
81
219
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
82
220
  Metrics/CyclomaticComplexity:
83
221
  Enabled: false
84
222
 
85
- # Offense count: 220
223
+ # Offense count: 257
86
224
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
87
225
  Metrics/MethodLength:
88
226
  Max: 154
@@ -92,11 +230,18 @@ Metrics/MethodLength:
92
230
  Metrics/ParameterLists:
93
231
  Max: 9
94
232
 
95
- # Offense count: 83
233
+ # Offense count: 101
96
234
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
97
235
  Metrics/PerceivedComplexity:
98
236
  Enabled: false
99
237
 
238
+ # Offense count: 4
239
+ # Configuration parameters: EnforcedStyle, AllowedIdentifiers, AllowedPatterns, ForbiddenIdentifiers, ForbiddenPatterns.
240
+ # SupportedStyles: snake_case, camelCase
241
+ Naming/VariableName:
242
+ Exclude:
243
+ - 'check_clippath_font.rb'
244
+
100
245
  # Offense count: 2
101
246
  # Configuration parameters: MinSize.
102
247
  Performance/CollectionLiteralInLoop:
@@ -104,6 +249,12 @@ Performance/CollectionLiteralInLoop:
104
249
  - 'lib/svg_conform/batch_report.rb'
105
250
  - 'lib/svg_conform/compatibility/pattern_discovery.rb'
106
251
 
252
+ # Offense count: 1
253
+ # This cop supports unsafe autocorrection (--autocorrect-all).
254
+ Performance/UnfreezeString:
255
+ Exclude:
256
+ - 'lib/svg_conform/element_proxy.rb'
257
+
107
258
  # Offense count: 8
108
259
  # Configuration parameters: IgnoredMetadata.
109
260
  RSpec/DescribeClass:
@@ -146,6 +297,14 @@ Rake/MethodDefinitionInTask:
146
297
  Exclude:
147
298
  - 'lib/tasks/svgcheck.rake'
148
299
 
300
+ # Offense count: 3
301
+ # This cop supports unsafe autocorrection (--autocorrect-all).
302
+ Style/CombinableLoops:
303
+ Exclude:
304
+ - 'check_duplicates.rb'
305
+ - 'compare_errors.rb'
306
+ - 'find_missing_errors.rb'
307
+
149
308
  # Offense count: 2
150
309
  # This cop supports safe autocorrection (--autocorrect).
151
310
  # Configuration parameters: EnforcedStyle, AllowComments.
@@ -167,6 +326,19 @@ Style/MissingRespondToMissing:
167
326
  Exclude:
168
327
  - 'lib/svg_conform/cli.rb'
169
328
 
329
+ # Offense count: 6
330
+ # This cop supports unsafe autocorrection (--autocorrect-all).
331
+ # Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns.
332
+ # SupportedStyles: predicate, comparison
333
+ Style/NumericPredicate:
334
+ Exclude:
335
+ - 'spec/**/*'
336
+ - 'benchmark_validation.rb'
337
+ - 'check_unique_positions.rb'
338
+ - 'lib/svg_conform/validation_context.rb'
339
+ - 'test_remediation.rb'
340
+ - 'test_sax_basic.rb'
341
+
170
342
  # Offense count: 4
171
343
  # Configuration parameters: AllowedMethods.
172
344
  # AllowedMethods: respond_to_missing?
@@ -174,6 +346,12 @@ Style/OptionalBooleanParameter:
174
346
  Exclude:
175
347
  - 'lib/svg_conform/semantic_comparator.rb'
176
348
 
349
+ # Offense count: 1
350
+ # This cop supports safe autocorrection (--autocorrect).
351
+ Style/RedundantAssignment:
352
+ Exclude:
353
+ - 'lib/svg_conform/fast_document_analyzer.rb'
354
+
177
355
  # Offense count: 1
178
356
  # This cop supports safe autocorrection (--autocorrect).
179
357
  # Configuration parameters: AllowedMethods.
@@ -181,3 +359,88 @@ Style/OptionalBooleanParameter:
181
359
  Style/RedundantCondition:
182
360
  Exclude:
183
361
  - 'lib/svg_conform/external_checkers/svgcheck/parser.rb'
362
+
363
+ # Offense count: 1
364
+ # This cop supports unsafe autocorrection (--autocorrect-all).
365
+ Style/RedundantInterpolation:
366
+ Exclude:
367
+ - 'analyze_error_nodes.rb'
368
+
369
+ # Offense count: 2
370
+ # This cop supports safe autocorrection (--autocorrect).
371
+ # Configuration parameters: EnforcedStyle.
372
+ # SupportedStyles: implicit, explicit
373
+ Style/RescueStandardError:
374
+ Exclude:
375
+ - 'debug_node_coverage.rb'
376
+ - 'test_sax_basic.rb'
377
+
378
+ # Offense count: 3
379
+ # This cop supports unsafe autocorrection (--autocorrect-all).
380
+ # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
381
+ # AllowedMethods: present?, blank?, presence, try, try!
382
+ Style/SafeNavigation:
383
+ Exclude:
384
+ - 'count_elements.rb'
385
+ - 'lib/svg_conform/fast_document_analyzer.rb'
386
+
387
+ # Offense count: 4
388
+ # This cop supports unsafe autocorrection (--autocorrect-all).
389
+ # Configuration parameters: Mode.
390
+ Style/StringConcatenation:
391
+ Exclude:
392
+ - 'benchmark_sax.rb'
393
+ - 'benchmark_validation.rb'
394
+ - 'final_demo.rb'
395
+ - 'test_remediation.rb'
396
+
397
+ # Offense count: 78
398
+ # This cop supports safe autocorrection (--autocorrect).
399
+ # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
400
+ # SupportedStyles: single_quotes, double_quotes
401
+ Style/StringLiterals:
402
+ Enabled: false
403
+
404
+ # Offense count: 34
405
+ # This cop supports safe autocorrection (--autocorrect).
406
+ # Configuration parameters: EnforcedStyleForMultiline.
407
+ # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
408
+ Style/TrailingCommaInArguments:
409
+ Exclude:
410
+ - 'lib/svg_conform/requirements/allowed_elements_requirement.rb'
411
+ - 'lib/svg_conform/requirements/color_restrictions_requirement.rb'
412
+ - 'lib/svg_conform/requirements/font_family_requirement.rb'
413
+ - 'lib/svg_conform/requirements/forbidden_content_requirement.rb'
414
+ - 'lib/svg_conform/requirements/id_reference_requirement.rb'
415
+ - 'lib/svg_conform/requirements/invalid_id_references_requirement.rb'
416
+ - 'lib/svg_conform/requirements/link_validation_requirement.rb'
417
+ - 'lib/svg_conform/requirements/namespace_attributes_requirement.rb'
418
+ - 'lib/svg_conform/requirements/namespace_requirement.rb'
419
+ - 'lib/svg_conform/requirements/no_external_css_requirement.rb'
420
+ - 'lib/svg_conform/requirements/no_external_fonts_requirement.rb'
421
+ - 'lib/svg_conform/requirements/no_external_images_requirement.rb'
422
+ - 'lib/svg_conform/requirements/viewbox_required_requirement.rb'
423
+ - 'lib/svg_conform/sax_validation_handler.rb'
424
+ - 'lib/svg_conform/validator.rb'
425
+
426
+ # Offense count: 12
427
+ # This cop supports safe autocorrection (--autocorrect).
428
+ # Configuration parameters: EnforcedStyleForMultiline.
429
+ # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
430
+ Style/TrailingCommaInHashLiteral:
431
+ Exclude:
432
+ - 'debug_positions.rb'
433
+ - 'lib/svg_conform/requirements/allowed_elements_requirement.rb'
434
+ - 'lib/svg_conform/requirements/color_restrictions_requirement.rb'
435
+ - 'lib/svg_conform/requirements/namespace_requirement.rb'
436
+ - 'lib/svg_conform/requirements/viewbox_required_requirement.rb'
437
+ - 'lib/svg_conform/validator.rb'
438
+
439
+ # Offense count: 4
440
+ # This cop supports unsafe autocorrection (--autocorrect-all).
441
+ Style/ZeroLengthPredicate:
442
+ Exclude:
443
+ - 'benchmark_validation.rb'
444
+ - 'lib/svg_conform/validation_context.rb'
445
+ - 'test_remediation.rb'
446
+ - 'test_sax_basic.rb'
data/README.adoc CHANGED
@@ -212,7 +212,7 @@ Details and examples of Ruby API usage can be found in
212
212
  require 'svg_conform'
213
213
 
214
214
  # Load a profile and validate
215
- profile = SvgConform::Profile.load_from_file("config/profiles/svg_1_2_rfc.yml")
215
+ profile = SvgConform::Profiles.get(:svg_1_2_rfc)
216
216
  document = SvgConform::Document.new(svg_content)
217
217
  result = profile.validate(document)
218
218
 
@@ -221,11 +221,10 @@ puts "Errors: #{result.errors.count}"
221
221
  puts "Warnings: #{result.warnings.count}"
222
222
 
223
223
  # Apply remediations to fix issues
224
- if !result.valid? && profile.has_remediations?
225
- engine = SvgConform::RemediationEngine.new(profile)
226
- remediation_results = engine.apply_remediations(document, result)
224
+ if !result.valid? && profile.remediation_count > 0
225
+ changes = profile.apply_remediations(document)
227
226
 
228
- puts "Applied #{remediation_results.length} remediations"
227
+ puts "Applied #{changes.length} remediations"
229
228
  puts "Fixed SVG:"
230
229
  puts document.to_xml
231
230
  end
@@ -1026,9 +1025,9 @@ document = SvgConform::Document.new(svg_content)
1026
1025
  result = profile.validate(document)
1027
1026
 
1028
1027
  # Apply remediations if needed
1029
- if !result.valid? && profile.has_remediations?
1030
- engine = SvgConform::RemediationEngine.new(profile)
1031
- remediation_results = engine.apply_remediations(document, result)
1028
+ if !result.valid? && profile.remediation_count > 0
1029
+ changes = profile.apply_remediations(document)
1030
+ puts "Applied #{changes.length} remediations"
1032
1031
  end
1033
1032
  ----
1034
1033
 
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Working example based on README.adoc Ruby API usage section
5
+ require_relative "../lib/svg_conform"
6
+
7
+ puts "=" * 60
8
+ puts "README Ruby API Usage Example"
9
+ puts "=" * 60
10
+ puts
11
+
12
+ # Sample SVG content with some issues
13
+ svg_content = <<~SVG
14
+ <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
15
+ <rect fill="red" width="50" height="50"/>
16
+ <circle fill="blue" cx="75" cy="75" r="20"/>
17
+ </svg>
18
+ SVG
19
+
20
+ puts "Test SVG content:"
21
+ puts svg_content
22
+ puts
23
+
24
+ # Load a profile and validate
25
+ profile = SvgConform::Profiles.get(:svg_1_2_rfc)
26
+ document = SvgConform::Document.new(svg_content)
27
+ result = profile.validate(document)
28
+
29
+ puts "Validation Results:"
30
+ puts "Valid: #{result.valid?}"
31
+ puts "Errors: #{result.errors.count}"
32
+ puts "Warnings: #{result.warnings.count}"
33
+ puts
34
+
35
+ if result.errors.any?
36
+ puts "Error details:"
37
+ result.errors.each_with_index do |error, i|
38
+ puts " #{i + 1}. [#{error.requirement_id}] #{error.message}"
39
+ end
40
+ puts
41
+ end
42
+
43
+ # Apply remediations to fix issues
44
+ if !result.valid? && profile.remediation_count.positive?
45
+ puts "Applying remediations (profile has #{profile.remediation_count} remediations)..."
46
+ changes = profile.apply_remediations(document)
47
+
48
+ puts "Applied #{changes.length} remediations"
49
+ puts
50
+
51
+ puts "Fixed SVG:"
52
+ puts document.to_xml
53
+ puts
54
+
55
+ # Re-validate to confirm fixes
56
+ result_after = profile.validate(document)
57
+ puts "Re-validation after fixes:"
58
+ puts "Valid: #{result_after.valid?}"
59
+ puts "Errors: #{result_after.errors.count}"
60
+ else
61
+ puts "Document is already valid or no remediations available"
62
+ end
63
+
64
+ puts
65
+ puts "=" * 60
66
+ puts "Example complete!"
67
+ puts "=" * 60
@@ -30,7 +30,7 @@ class RequirementsDemo
30
30
 
31
31
  begin
32
32
  # Load IETF profile from YAML
33
- svg_1_2_rfc_profile = SvgConform::ProfileRegistry.load_profile("svg_1_2_rfc")
33
+ svg_1_2_rfc_profile = SvgConform::Profiles.get(:svg_1_2_rfc)
34
34
  puts "✓ Loaded IETF profile: #{svg_1_2_rfc_profile.name}"
35
35
  puts " Description: #{svg_1_2_rfc_profile.description}"
36
36
  puts " Requirements: #{svg_1_2_rfc_profile.requirement_count}"
@@ -38,7 +38,7 @@ class RequirementsDemo
38
38
  puts
39
39
 
40
40
  # Load Lucid fix profile
41
- lucid_profile = SvgConform::ProfileRegistry.load_profile("lucid_fix")
41
+ lucid_profile = SvgConform::Profiles.get(:lucid_fix)
42
42
  puts "✓ Loaded Lucid Fix profile: #{lucid_profile.name}"
43
43
  puts " Description: #{lucid_profile.description}"
44
44
  puts " Requirements: #{lucid_profile.requirement_count}"
@@ -46,7 +46,7 @@ class RequirementsDemo
46
46
  puts
47
47
 
48
48
  # List available profiles
49
- available = SvgConform::ProfileRegistry.available_profiles
49
+ available = SvgConform::Profiles.available_profiles
50
50
  puts "Available profiles: #{available.join(', ')}"
51
51
  puts
52
52
  rescue StandardError => e
@@ -204,7 +204,7 @@ class RequirementsDemo
204
204
 
205
205
  begin
206
206
  # Load the Lucid fix profile
207
- profile = SvgConform::ProfileRegistry.load_profile("lucid_fix")
207
+ profile = SvgConform::Profiles.get(:lucid_fix)
208
208
 
209
209
  # Process the SVG
210
210
  document = SvgConform::Document.new(lucid_svg)
@@ -16,6 +16,7 @@ module SvgConform
16
16
  @content = content_or_path
17
17
  end
18
18
 
19
+ @xpath_cache = {}
19
20
  parse_document
20
21
  end
21
22
 
@@ -36,7 +37,8 @@ module SvgConform
36
37
  end
37
38
 
38
39
  def xpath(path, namespaces = {})
39
- @moxml_document.xpath(path, namespaces)
40
+ cache_key = [path, namespaces].hash
41
+ @xpath_cache[cache_key] ||= @moxml_document.xpath(path, namespaces)
40
42
  end
41
43
 
42
44
  def traverse(&)
@@ -60,6 +62,10 @@ module SvgConform
60
62
  Document.from_content(to_xml)
61
63
  end
62
64
 
65
+ def clear_cache
66
+ @xpath_cache.clear
67
+ end
68
+
63
69
  def valid_xml?
64
70
  !@moxml_document.nil?
65
71
  rescue StandardError
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SvgConform
4
+ # Lightweight attribute representation for SAX parsing
5
+ class SaxAttribute
6
+ attr_reader :name, :value
7
+
8
+ def initialize(name, value)
9
+ @name = name
10
+ @value = value
11
+ end
12
+
13
+ def namespace
14
+ nil # Simplified for now
15
+ end
16
+ end
17
+
18
+ # Lightweight element representation during SAX parsing
19
+ # Provides a node-like interface for validation requirements
20
+ # without the overhead of full DOM tree
21
+ class ElementProxy
22
+ attr_reader :name, :position, :path, :parent, :raw_attributes
23
+ attr_accessor :text_content, :child_counters
24
+
25
+ def initialize(name:, attributes:, position:, path:, parent:)
26
+ @name = name
27
+ @raw_attributes = attributes # Hash of attribute name => value
28
+ @position = position
29
+ @path = path # Array of parent path parts
30
+ @parent = parent
31
+ @text_content = String.new # Mutable string
32
+ @child_counters = {} # Track child element positions
33
+ end
34
+
35
+ # Build full path ID for this element
36
+ def path_id
37
+ parts = @path + ["#{@name}[#{@position}]"]
38
+ "/#{parts.join('/')}"
39
+ end
40
+
41
+ # Return attributes as array of SaxAttribute objects (for compatibility)
42
+ def attributes
43
+ @raw_attributes.map { |name, value| SaxAttribute.new(name, value) }
44
+ end
45
+
46
+ # Check if this element has a specific attribute
47
+ def attribute(name)
48
+ value = @raw_attributes[name] || @raw_attributes[name.to_s]
49
+ value ? SaxAttribute.new(name, value) : nil
50
+ end
51
+
52
+ # Get attribute value (alias for compatibility)
53
+ def [](name)
54
+ @raw_attributes[name] || @raw_attributes[name.to_s]
55
+ end
56
+
57
+ # Check if attribute exists
58
+ def has_attribute?(name)
59
+ @raw_attributes.key?(name) || @raw_attributes.key?(name.to_s)
60
+ end
61
+
62
+ # Get namespace from attributes or parent
63
+ def namespace
64
+ @raw_attributes['xmlns'] || @parent&.namespace
65
+ end
66
+
67
+ # Check if this is a text node (always false for ElementProxy)
68
+ def text?
69
+ false
70
+ end
71
+
72
+ # Support dynamic attribute access
73
+ def method_missing(method, *args)
74
+ if method.to_s.end_with?('?')
75
+ # Boolean check
76
+ has_attribute?(method.to_s.chomp('?'))
77
+ else
78
+ # Attribute access
79
+ @attributes[method.to_s] || @attributes[method.to_sym]
80
+ end
81
+ end
82
+
83
+ def respond_to_missing?(method, include_private = false)
84
+ @raw_attributes.key?(method.to_s) || @raw_attributes.key?(method.to_sym) || super
85
+ end
86
+
87
+ # For compatibility with validation context
88
+ def line
89
+ nil # SAX doesn't provide line numbers easily
90
+ end
91
+
92
+ def column
93
+ nil
94
+ end
95
+
96
+ # Provide a stable identifier for this element
97
+ def element_id
98
+ path_id
99
+ end
100
+ end
101
+ end