svg_conform 0.1.5 → 0.1.7
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 +4 -4
- data/.rubocop_todo.yml +3 -186
- data/Gemfile +2 -2
- data/README.adoc +56 -518
- data/docs/reference_manifest.adoc +3 -2
- data/lib/svg_conform/document.rb +22 -1
- data/lib/svg_conform/node_helpers.rb +72 -0
- data/lib/svg_conform/remediations/base_remediation.rb +5 -35
- data/lib/svg_conform/remediations/namespace_remediation.rb +60 -0
- data/lib/svg_conform/requirements/base_requirement.rb +5 -41
- data/lib/svg_conform/version.rb +1 -1
- data/svg_conform.gemspec +1 -1
- metadata +11 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a671b1d69dd6498470fc03cdaf2488bd3180187a39ef505cef2cb67d76de1725
|
|
4
|
+
data.tar.gz: c915d4ed0894b35293d78ea4a71f326e8985190dac8ae8df55c55b8eb10d1696
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a32f6b36b517598e1a5f95612457c4e9a5386f64a15d6383dfb2e63052a2c58354a24afc730ad3a27b3ce6165c52447872e759655ef33ba8c546c12de2b16fbc
|
|
7
|
+
data.tar.gz: 1f22474906b51fe86cdeadac2817a66b2695bf7b1685370e25e058ed6c66dc9d09b2f95e26526b5a7937b493f2a7e51b3cf7a97b036c4ec0c8a7f7b0d1494801
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,93 +1,26 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2025-11-
|
|
3
|
+
# on 2025-11-26 09:22:57 UTC using RuboCop version 1.81.7.
|
|
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
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
|
-
# Offense count:
|
|
10
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
11
|
-
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
12
|
-
# SupportedStyles: with_first_argument, with_fixed_indentation
|
|
13
|
-
Layout/ArgumentAlignment:
|
|
14
|
-
Exclude:
|
|
15
|
-
- 'lib/svg_conform/document.rb'
|
|
16
|
-
- 'lib/svg_conform/remediations/namespace_attribute_remediation.rb'
|
|
17
|
-
|
|
18
|
-
# Offense count: 5
|
|
9
|
+
# Offense count: 1
|
|
19
10
|
# This cop supports safe autocorrection (--autocorrect).
|
|
20
11
|
# Configuration parameters: EnforcedStyleAlignWith.
|
|
21
12
|
# SupportedStylesAlignWith: either, start_of_block, start_of_line
|
|
22
13
|
Layout/BlockAlignment:
|
|
23
14
|
Exclude:
|
|
24
15
|
- 'spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb'
|
|
25
|
-
- 'spec/svg_conform/requirements/id_reference_state_spec.rb'
|
|
26
|
-
- 'test_remove_ns.rb'
|
|
27
|
-
- 'test_reparse_ns.rb'
|
|
28
|
-
- 'test_string_remove_ns.rb'
|
|
29
16
|
|
|
30
|
-
# Offense count:
|
|
31
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
32
|
-
Layout/BlockEndNewline:
|
|
33
|
-
Exclude:
|
|
34
|
-
- 'benchmark_validation.rb'
|
|
35
|
-
- 'spec/svg_conform/requirements/id_reference_state_spec.rb'
|
|
36
|
-
|
|
37
|
-
# Offense count: 1
|
|
38
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
39
|
-
# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
|
|
40
|
-
Layout/ExtraSpacing:
|
|
41
|
-
Exclude:
|
|
42
|
-
- 'lib/svg_conform/document.rb'
|
|
43
|
-
|
|
44
|
-
# Offense count: 7
|
|
45
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
46
|
-
# Configuration parameters: Width, AllowedPatterns.
|
|
47
|
-
Layout/IndentationWidth:
|
|
48
|
-
Exclude:
|
|
49
|
-
- 'benchmark_validation.rb'
|
|
50
|
-
- 'spec/svg_conform/requirements/id_reference_state_spec.rb'
|
|
51
|
-
- 'test_remove_ns.rb'
|
|
52
|
-
- 'test_reparse_ns.rb'
|
|
53
|
-
- 'test_string_remove_ns.rb'
|
|
54
|
-
|
|
55
|
-
# Offense count: 657
|
|
17
|
+
# Offense count: 643
|
|
56
18
|
# This cop supports safe autocorrection (--autocorrect).
|
|
57
19
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
|
|
58
20
|
# URISchemes: http, https
|
|
59
21
|
Layout/LineLength:
|
|
60
22
|
Enabled: false
|
|
61
23
|
|
|
62
|
-
# Offense count: 2
|
|
63
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
64
|
-
# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator, EnforcedStyleForRationalLiterals.
|
|
65
|
-
# SupportedStylesForExponentOperator: space, no_space
|
|
66
|
-
# SupportedStylesForRationalLiterals: space, no_space
|
|
67
|
-
Layout/SpaceAroundOperators:
|
|
68
|
-
Exclude:
|
|
69
|
-
- 'debug_lucid_detailed.rb'
|
|
70
|
-
- 'debug_namespace_rem.rb'
|
|
71
|
-
|
|
72
|
-
# Offense count: 2
|
|
73
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
74
|
-
# Configuration parameters: EnforcedStyle.
|
|
75
|
-
# SupportedStyles: final_newline, final_blank_line
|
|
76
|
-
Layout/TrailingEmptyLines:
|
|
77
|
-
Exclude:
|
|
78
|
-
- 'examples/document_input_demo.rb'
|
|
79
|
-
- 'spec/svg_conform/validator_input_types_spec.rb'
|
|
80
|
-
|
|
81
|
-
# Offense count: 5
|
|
82
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
83
|
-
# Configuration parameters: AllowInHeredoc.
|
|
84
|
-
Layout/TrailingWhitespace:
|
|
85
|
-
Exclude:
|
|
86
|
-
- 'debug_moxml_ns.rb'
|
|
87
|
-
- 'lib/svg_conform/document.rb'
|
|
88
|
-
- 'lib/svg_conform/remediations/namespace_attribute_remediation.rb'
|
|
89
|
-
- 'test_remove_ns.rb'
|
|
90
|
-
|
|
91
24
|
# Offense count: 2
|
|
92
25
|
# Configuration parameters: AllowedMethods.
|
|
93
26
|
# AllowedMethods: enums
|
|
@@ -133,21 +66,6 @@ Lint/UnreachableCode:
|
|
|
133
66
|
Exclude:
|
|
134
67
|
- 'lib/svg_conform/commands/check.rb'
|
|
135
68
|
|
|
136
|
-
# Offense count: 1
|
|
137
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
138
|
-
# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
|
|
139
|
-
Lint/UnusedBlockArgument:
|
|
140
|
-
Exclude:
|
|
141
|
-
- 'benchmark_validation.rb'
|
|
142
|
-
|
|
143
|
-
# Offense count: 1
|
|
144
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
145
|
-
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
|
|
146
|
-
# NotImplementedExceptions: NotImplementedError
|
|
147
|
-
Lint/UnusedMethodArgument:
|
|
148
|
-
Exclude:
|
|
149
|
-
- 'benchmark_validation.rb'
|
|
150
|
-
|
|
151
69
|
# Offense count: 151
|
|
152
70
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
153
71
|
Metrics/AbcSize:
|
|
@@ -198,19 +116,6 @@ Performance/CollectionLiteralInLoop:
|
|
|
198
116
|
- 'lib/svg_conform/batch_report.rb'
|
|
199
117
|
- 'lib/svg_conform/compatibility/pattern_discovery.rb'
|
|
200
118
|
|
|
201
|
-
# Offense count: 1
|
|
202
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
203
|
-
Performance/RedundantBlockCall:
|
|
204
|
-
Exclude:
|
|
205
|
-
- 'benchmark_validation.rb'
|
|
206
|
-
|
|
207
|
-
# Offense count: 1
|
|
208
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
209
|
-
# Configuration parameters: OnlySumOrWithInitialValue.
|
|
210
|
-
Performance/Sum:
|
|
211
|
-
Exclude:
|
|
212
|
-
- 'benchmark_validation.rb'
|
|
213
|
-
|
|
214
119
|
# Offense count: 9
|
|
215
120
|
# Configuration parameters: IgnoredMetadata.
|
|
216
121
|
RSpec/DescribeClass:
|
|
@@ -260,19 +165,6 @@ Rake/MethodDefinitionInTask:
|
|
|
260
165
|
Exclude:
|
|
261
166
|
- 'lib/tasks/svgcheck.rake'
|
|
262
167
|
|
|
263
|
-
# Offense count: 5
|
|
264
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
265
|
-
# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
|
|
266
|
-
# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
|
|
267
|
-
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
|
|
268
|
-
# FunctionalMethods: let, let!, subject, watch
|
|
269
|
-
# AllowedMethods: lambda, proc, it
|
|
270
|
-
Style/BlockDelimiters:
|
|
271
|
-
Exclude:
|
|
272
|
-
- 'benchmark_validation.rb'
|
|
273
|
-
- 'spec/svg_conform/requirements/id_reference_state_spec.rb'
|
|
274
|
-
- 'spec/svg_conform/validator_input_types_spec.rb'
|
|
275
|
-
|
|
276
168
|
# Offense count: 2
|
|
277
169
|
# This cop supports safe autocorrection (--autocorrect).
|
|
278
170
|
# Configuration parameters: EnforcedStyle, AllowComments.
|
|
@@ -289,28 +181,11 @@ Style/EmptyElse:
|
|
|
289
181
|
Style/FormatStringToken:
|
|
290
182
|
EnforcedStyle: unannotated
|
|
291
183
|
|
|
292
|
-
# Offense count: 2
|
|
293
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
294
|
-
# Configuration parameters: AllowedReceivers.
|
|
295
|
-
# AllowedReceivers: Thread.current
|
|
296
|
-
Style/HashEachMethods:
|
|
297
|
-
Exclude:
|
|
298
|
-
- 'benchmark_validation.rb'
|
|
299
|
-
|
|
300
184
|
# Offense count: 1
|
|
301
185
|
Style/MissingRespondToMissing:
|
|
302
186
|
Exclude:
|
|
303
187
|
- 'lib/svg_conform/cli.rb'
|
|
304
188
|
|
|
305
|
-
# Offense count: 5
|
|
306
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
307
|
-
# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns.
|
|
308
|
-
# SupportedStyles: predicate, comparison
|
|
309
|
-
Style/NumericPredicate:
|
|
310
|
-
Exclude:
|
|
311
|
-
- 'spec/**/*'
|
|
312
|
-
- 'benchmark_validation.rb'
|
|
313
|
-
|
|
314
189
|
# Offense count: 4
|
|
315
190
|
# Configuration parameters: AllowedMethods.
|
|
316
191
|
# AllowedMethods: respond_to_missing?
|
|
@@ -325,61 +200,3 @@ Style/OptionalBooleanParameter:
|
|
|
325
200
|
Style/RedundantCondition:
|
|
326
201
|
Exclude:
|
|
327
202
|
- 'lib/svg_conform/external_checkers/svgcheck/parser.rb'
|
|
328
|
-
|
|
329
|
-
# Offense count: 3
|
|
330
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
331
|
-
Style/RedundantParentheses:
|
|
332
|
-
Exclude:
|
|
333
|
-
- 'benchmark_validation.rb'
|
|
334
|
-
|
|
335
|
-
# Offense count: 3
|
|
336
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
337
|
-
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
|
|
338
|
-
# AllowedMethods: present?, blank?, presence, try, try!
|
|
339
|
-
Style/SafeNavigation:
|
|
340
|
-
Exclude:
|
|
341
|
-
- 'test_remove_ns.rb'
|
|
342
|
-
- 'test_reparse_ns.rb'
|
|
343
|
-
- 'test_string_remove_ns.rb'
|
|
344
|
-
|
|
345
|
-
# Offense count: 6
|
|
346
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
347
|
-
# Configuration parameters: Mode.
|
|
348
|
-
Style/StringConcatenation:
|
|
349
|
-
Exclude:
|
|
350
|
-
- 'benchmark_validation.rb'
|
|
351
|
-
- 'examples/document_input_demo.rb'
|
|
352
|
-
|
|
353
|
-
# Offense count: 23
|
|
354
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
355
|
-
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
|
|
356
|
-
# SupportedStyles: single_quotes, double_quotes
|
|
357
|
-
Style/StringLiterals:
|
|
358
|
-
Exclude:
|
|
359
|
-
- 'debug_lucid_detailed.rb'
|
|
360
|
-
- 'debug_lucid_test.rb'
|
|
361
|
-
- 'debug_moxml_attrs.rb'
|
|
362
|
-
- 'debug_moxml_ns.rb'
|
|
363
|
-
- 'debug_namespace_rem.rb'
|
|
364
|
-
- 'lib/svg_conform/document.rb'
|
|
365
|
-
- 'lib/svg_conform/remediations/namespace_attribute_remediation.rb'
|
|
366
|
-
- 'test_remove_ns.rb'
|
|
367
|
-
- 'test_reparse_ns.rb'
|
|
368
|
-
- 'test_string_remove_ns.rb'
|
|
369
|
-
|
|
370
|
-
# Offense count: 6
|
|
371
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
372
|
-
# Configuration parameters: EnforcedStyle.
|
|
373
|
-
# SupportedStyles: single_quotes, double_quotes
|
|
374
|
-
Style/StringLiteralsInInterpolation:
|
|
375
|
-
Exclude:
|
|
376
|
-
- 'benchmark_validation.rb'
|
|
377
|
-
- 'examples/document_input_demo.rb'
|
|
378
|
-
|
|
379
|
-
# Offense count: 1
|
|
380
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
381
|
-
# Configuration parameters: EnforcedStyleForMultiline.
|
|
382
|
-
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
|
383
|
-
Style/TrailingCommaInHashLiteral:
|
|
384
|
-
Exclude:
|
|
385
|
-
- 'benchmark_validation.rb'
|
data/Gemfile
CHANGED
data/README.adoc
CHANGED
|
@@ -124,6 +124,31 @@ Each remediation action can be linked to a particular requirement to indicate
|
|
|
124
124
|
their relationship, defined in the profile.
|
|
125
125
|
|
|
126
126
|
|
|
127
|
+
=== Two-mode architecture
|
|
128
|
+
|
|
129
|
+
SvgConform uses two distinct operating modes for optimal performance and functionality:
|
|
130
|
+
|
|
131
|
+
**SAX Validation Mode** (always used for validation):
|
|
132
|
+
|
|
133
|
+
* Memory-safe streaming XML parser
|
|
134
|
+
* Constant memory usage regardless of file size
|
|
135
|
+
* Handles files of any size (tested with 100MB+ files)
|
|
136
|
+
* Read-only - cannot modify documents
|
|
137
|
+
|
|
138
|
+
**DOM Remediation Mode** (only when applying fixes):
|
|
139
|
+
|
|
140
|
+
* Full document tree loaded in memory
|
|
141
|
+
* XPath queries and tree modification
|
|
142
|
+
* Memory scales with file size
|
|
143
|
+
* Only used when `fix: true` option is specified
|
|
144
|
+
|
|
145
|
+
This architecture ensures validation is always safe for large files, while modifications
|
|
146
|
+
are only performed when explicitly requested and necessary.
|
|
147
|
+
|
|
148
|
+
See link:docs/sax_validation_mode.adoc[SAX Validation Mode Guide] for details on
|
|
149
|
+
writing SAX-compatible requirements.
|
|
150
|
+
|
|
151
|
+
|
|
127
152
|
=== Reporting
|
|
128
153
|
|
|
129
154
|
SvgConform provides detailed reporting on SVG conformance issues.
|
|
@@ -142,7 +167,6 @@ profile conformance tools.
|
|
|
142
167
|
See <<external_compliance>> for details.
|
|
143
168
|
|
|
144
169
|
|
|
145
|
-
|
|
146
170
|
== Usage
|
|
147
171
|
|
|
148
172
|
=== Installation
|
|
@@ -172,7 +196,9 @@ $ gem install svg_conform
|
|
|
172
196
|
=== Command line usage
|
|
173
197
|
|
|
174
198
|
Details and examples of command line usage can be found in
|
|
175
|
-
|
|
199
|
+
link:docs/cli_guide.adoc[CLI Guide].
|
|
200
|
+
|
|
201
|
+
==== Quick start
|
|
176
202
|
|
|
177
203
|
List available profiles:
|
|
178
204
|
|
|
@@ -202,11 +228,16 @@ Batch process a directory of SVG files:
|
|
|
202
228
|
$ svg_conform check --directory=images/ --profile=metanorma -f --output-dir=fixed/
|
|
203
229
|
----
|
|
204
230
|
|
|
231
|
+
For comprehensive CLI documentation including all options, workflows, and troubleshooting,
|
|
232
|
+
see link:docs/cli_guide.adoc[CLI Guide].
|
|
233
|
+
|
|
205
234
|
|
|
206
235
|
=== Ruby API usage
|
|
207
236
|
|
|
208
237
|
Details and examples of Ruby API usage can be found in
|
|
209
|
-
|
|
238
|
+
link:docs/api_reference.adoc[API Reference].
|
|
239
|
+
|
|
240
|
+
==== Quick start
|
|
210
241
|
|
|
211
242
|
[source,ruby]
|
|
212
243
|
----
|
|
@@ -280,6 +311,9 @@ Benefits:
|
|
|
280
311
|
- **Safe for large files**: Always uses memory-efficient SAX parsing
|
|
281
312
|
- **Backward compatible**: String input still works as before
|
|
282
313
|
|
|
314
|
+
For comprehensive API documentation including all classes, methods, advanced usage,
|
|
315
|
+
and integration patterns, see link:docs/api_reference.adoc[API Reference].
|
|
316
|
+
|
|
283
317
|
|
|
284
318
|
=== Reference manifest
|
|
285
319
|
|
|
@@ -315,521 +349,6 @@ end
|
|
|
315
349
|
See link:docs/reference_manifest.adoc[Reference Manifest Documentation] for complete details.
|
|
316
350
|
|
|
317
351
|
|
|
318
|
-
[[command_line_interface]]
|
|
319
|
-
== Command line interface
|
|
320
|
-
|
|
321
|
-
The `svg_conform` command-line tool provides validation and remediation capabilities for SVG files.
|
|
322
|
-
|
|
323
|
-
=== Basic commands
|
|
324
|
-
|
|
325
|
-
==== List available profiles
|
|
326
|
-
|
|
327
|
-
[source,bash]
|
|
328
|
-
----
|
|
329
|
-
$ svg_conform profiles
|
|
330
|
-
----
|
|
331
|
-
|
|
332
|
-
Show detailed information about profiles:
|
|
333
|
-
|
|
334
|
-
[source,bash]
|
|
335
|
-
----
|
|
336
|
-
$ svg_conform profiles --verbose
|
|
337
|
-
----
|
|
338
|
-
|
|
339
|
-
==== Validate a single SVG file
|
|
340
|
-
|
|
341
|
-
[source,bash]
|
|
342
|
-
----
|
|
343
|
-
$ svg_conform check file.svg --profile=metanorma
|
|
344
|
-
----
|
|
345
|
-
|
|
346
|
-
Options:
|
|
347
|
-
|
|
348
|
-
* `--profile=PROFILE` or `-p`: Profile to validate against (default: `svg_1_2_rfc`)
|
|
349
|
-
* `--format=FORMAT`: Output format: `table` (default), `json`, or `yaml`
|
|
350
|
-
* `--output=FILE` or `-o`: Save report to file
|
|
351
|
-
|
|
352
|
-
Example with JSON output:
|
|
353
|
-
|
|
354
|
-
[source,bash]
|
|
355
|
-
----
|
|
356
|
-
$ svg_conform check file.svg -p metanorma --format=json --output=report.json
|
|
357
|
-
----
|
|
358
|
-
|
|
359
|
-
==== Fix a single SVG file
|
|
360
|
-
|
|
361
|
-
Apply automatic remediations to fix conformance issues:
|
|
362
|
-
|
|
363
|
-
[source,bash]
|
|
364
|
-
----
|
|
365
|
-
$ svg_conform check file.svg --profile=metanorma --fix
|
|
366
|
-
----
|
|
367
|
-
|
|
368
|
-
Specify custom output file:
|
|
369
|
-
|
|
370
|
-
[source,bash]
|
|
371
|
-
----
|
|
372
|
-
$ svg_conform check file.svg -p metanorma -f --fix-output=fixed.svg
|
|
373
|
-
----
|
|
374
|
-
|
|
375
|
-
Options:
|
|
376
|
-
|
|
377
|
-
* `--fix` or `-f`: Enable automatic remediation
|
|
378
|
-
* `--fix-output=FILE`: Output file for remediated SVG (default: `FILE.fixed.svg`)
|
|
379
|
-
|
|
380
|
-
==== Process multiple files
|
|
381
|
-
|
|
382
|
-
Process multiple SVG files at once:
|
|
383
|
-
|
|
384
|
-
[source,bash]
|
|
385
|
-
----
|
|
386
|
-
$ svg_conform check file1.svg file2.svg file3.svg --profile=metanorma
|
|
387
|
-
----
|
|
388
|
-
|
|
389
|
-
With remediation, an output directory is required:
|
|
390
|
-
|
|
391
|
-
[source,bash]
|
|
392
|
-
----
|
|
393
|
-
$ svg_conform check *.svg -p metanorma --fix --output-dir=fixed/
|
|
394
|
-
----
|
|
395
|
-
|
|
396
|
-
==== Process a directory
|
|
397
|
-
|
|
398
|
-
Recursively process all SVG files in a directory:
|
|
399
|
-
|
|
400
|
-
[source,bash]
|
|
401
|
-
----
|
|
402
|
-
$ svg_conform check --directory=images/ --profile=metanorma
|
|
403
|
-
----
|
|
404
|
-
|
|
405
|
-
With remediation:
|
|
406
|
-
|
|
407
|
-
[source,bash]
|
|
408
|
-
----
|
|
409
|
-
$ svg_conform check -d images/ -p metanorma --fix --output-dir=fixed/
|
|
410
|
-
----
|
|
411
|
-
|
|
412
|
-
Replace files in-place (use with caution):
|
|
413
|
-
|
|
414
|
-
[source,bash]
|
|
415
|
-
----
|
|
416
|
-
$ svg_conform check -d images/ -p metanorma --fix --in-place --force
|
|
417
|
-
----
|
|
418
|
-
|
|
419
|
-
==== Batch processing options
|
|
420
|
-
|
|
421
|
-
Additional options for batch processing:
|
|
422
|
-
|
|
423
|
-
* `--quiet` or `-q`: Suppress per-file output, show summary only
|
|
424
|
-
* `--verbose` or `-v`: Show detailed progress
|
|
425
|
-
* `--report-format=FORMAT`: Generate detailed report in `json` or `yaml`
|
|
426
|
-
* `--report-output=FILE`: Save detailed batch report to file
|
|
427
|
-
* `--manifest=FILE`: Generate manifest mapping original to remediated files (default: `manifest.json`)
|
|
428
|
-
|
|
429
|
-
Example with detailed reporting:
|
|
430
|
-
|
|
431
|
-
[source,bash]
|
|
432
|
-
----
|
|
433
|
-
$ svg_conform check -d images/ -p metanorma -f --output-dir=fixed/ \
|
|
434
|
-
--report-format=json --report-output=batch-report.json \
|
|
435
|
-
--manifest=file-mapping.json
|
|
436
|
-
----
|
|
437
|
-
|
|
438
|
-
==== Display version
|
|
439
|
-
|
|
440
|
-
[source,bash]
|
|
441
|
-
----
|
|
442
|
-
$ svg_conform version
|
|
443
|
-
----
|
|
444
|
-
|
|
445
|
-
=== Exit codes
|
|
446
|
-
|
|
447
|
-
* `0`: All files valid or successfully remediated
|
|
448
|
-
* `1`: Validation failures or errors occurred
|
|
449
|
-
|
|
450
|
-
=== Common workflows
|
|
451
|
-
|
|
452
|
-
==== Quality control workflow
|
|
453
|
-
|
|
454
|
-
Check all SVG files before deployment:
|
|
455
|
-
|
|
456
|
-
[source,bash]
|
|
457
|
-
----
|
|
458
|
-
$ svg_conform check -d assets/images/ -p metanorma --quiet
|
|
459
|
-
----
|
|
460
|
-
|
|
461
|
-
==== Batch remediation workflow
|
|
462
|
-
|
|
463
|
-
Fix all non-conforming files:
|
|
464
|
-
|
|
465
|
-
[source,bash]
|
|
466
|
-
----
|
|
467
|
-
# 1. Validate and identify issues
|
|
468
|
-
$ svg_conform check -d images/ -p metanorma --report-format=json \
|
|
469
|
-
--report-output=pre-fix-report.json
|
|
470
|
-
|
|
471
|
-
# 2. Apply fixes
|
|
472
|
-
$ svg_conform check -d images/ -p metanorma --fix --output-dir=fixed/ \
|
|
473
|
-
--manifest=manifest.json
|
|
474
|
-
|
|
475
|
-
# 3. Verify fixes
|
|
476
|
-
$ svg_conform check -d fixed/ -p metanorma --report-format=json \
|
|
477
|
-
--report-output=post-fix-report.json
|
|
478
|
-
----
|
|
479
|
-
|
|
480
|
-
==== Integration with CI/CD
|
|
481
|
-
|
|
482
|
-
Validate SVGs in continuous integration:
|
|
483
|
-
|
|
484
|
-
[source,bash]
|
|
485
|
-
----
|
|
486
|
-
$ svg_conform check -d docs/images/ -p metanorma --quiet
|
|
487
|
-
|
|
488
|
-
# Exit code 0 = pass, 1 = fail
|
|
489
|
-
----
|
|
490
|
-
|
|
491
|
-
=== Complete reference
|
|
492
|
-
|
|
493
|
-
See link:docs/cli_guide.adoc[CLI Guide] for comprehensive documentation including:
|
|
494
|
-
|
|
495
|
-
* All available profiles and their requirements
|
|
496
|
-
* Detailed option descriptions
|
|
497
|
-
* Advanced usage patterns
|
|
498
|
-
* Troubleshooting common issues
|
|
499
|
-
* Integration examples
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
[[ruby_api_reference]]
|
|
503
|
-
== Ruby API reference
|
|
504
|
-
|
|
505
|
-
The SvgConform Ruby API provides programmatic access to SVG validation and remediation.
|
|
506
|
-
|
|
507
|
-
=== Basic validation
|
|
508
|
-
|
|
509
|
-
==== Using the validator
|
|
510
|
-
|
|
511
|
-
[source,ruby]
|
|
512
|
-
----
|
|
513
|
-
require 'svg_conform'
|
|
514
|
-
|
|
515
|
-
validator = SvgConform::Validator.new
|
|
516
|
-
result = validator.validate(svg_content, profile: :metanorma)
|
|
517
|
-
|
|
518
|
-
puts "Valid: #{result.valid?}"
|
|
519
|
-
puts "Errors: #{result.errors.count}"
|
|
520
|
-
puts "Warnings: #{result.warnings.count}"
|
|
521
|
-
|
|
522
|
-
# Access error details
|
|
523
|
-
result.errors.each do |error|
|
|
524
|
-
puts "#{error.requirement_id}: #{error.message}"
|
|
525
|
-
puts " Location: #{error.element}" if error.element
|
|
526
|
-
end
|
|
527
|
-
----
|
|
528
|
-
|
|
529
|
-
==== Loading profiles
|
|
530
|
-
|
|
531
|
-
Load a profile by name:
|
|
532
|
-
|
|
533
|
-
[source,ruby]
|
|
534
|
-
----
|
|
535
|
-
profile = SvgConform::Profiles.get(:svg_1_2_rfc)
|
|
536
|
-
----
|
|
537
|
-
|
|
538
|
-
Available built-in profiles:
|
|
539
|
-
|
|
540
|
-
* `:base` - Minimal SVG validation
|
|
541
|
-
* `:svg_1_2_rfc` - RFC 7996 compliance (IETF XMLRFC documents)
|
|
542
|
-
* `:svg_1_2_rfc_with_rdf` - RFC 7996 with RDF metadata support
|
|
543
|
-
* `:metanorma` - Metanorma document requirements
|
|
544
|
-
* `:lucid` - Lucid profile
|
|
545
|
-
* `:no_external_css` - Disallow external CSS
|
|
546
|
-
|
|
547
|
-
Load a custom profile from file:
|
|
548
|
-
|
|
549
|
-
[source,ruby]
|
|
550
|
-
----
|
|
551
|
-
profile = SvgConform::Profile.load_from_file('path/to/profile.yml')
|
|
552
|
-
----
|
|
553
|
-
|
|
554
|
-
==== Validating with profiles
|
|
555
|
-
|
|
556
|
-
[source,ruby]
|
|
557
|
-
----
|
|
558
|
-
profile = SvgConform::Profiles.get(:metanorma)
|
|
559
|
-
document = SvgConform::Document.new(svg_content)
|
|
560
|
-
result = profile.validate(document)
|
|
561
|
-
|
|
562
|
-
if result.valid?
|
|
563
|
-
puts "SVG is valid!"
|
|
564
|
-
else
|
|
565
|
-
puts "Found #{result.errors.count} errors"
|
|
566
|
-
end
|
|
567
|
-
----
|
|
568
|
-
|
|
569
|
-
=== Applying remediations
|
|
570
|
-
|
|
571
|
-
==== Basic remediation
|
|
572
|
-
|
|
573
|
-
[source,ruby]
|
|
574
|
-
----
|
|
575
|
-
profile = SvgConform::Profiles.get(:metanorma)
|
|
576
|
-
document = SvgConform::Document.from_file('input.svg')
|
|
577
|
-
|
|
578
|
-
# Apply all remediations defined in the profile
|
|
579
|
-
changes = profile.apply_remediations(document)
|
|
580
|
-
|
|
581
|
-
puts "Applied #{changes.length} remediations"
|
|
582
|
-
|
|
583
|
-
# Save the remediated SVG
|
|
584
|
-
File.write('output.svg', document.to_xml)
|
|
585
|
-
----
|
|
586
|
-
|
|
587
|
-
==== Using the remediation runner
|
|
588
|
-
|
|
589
|
-
For more control over the remediation process:
|
|
590
|
-
|
|
591
|
-
[source,ruby]
|
|
592
|
-
----
|
|
593
|
-
profile = SvgConform::Profiles.get(:metanorma)
|
|
594
|
-
runner = SvgConform::RemediationRunner.new(profile: profile)
|
|
595
|
-
|
|
596
|
-
# Run remediation on a file
|
|
597
|
-
result = runner.run_remediation_file('input.svg')
|
|
598
|
-
|
|
599
|
-
if result.success?
|
|
600
|
-
File.write('output.svg', result.remediated_content)
|
|
601
|
-
puts "Fixed #{result.issues_fixed} issues"
|
|
602
|
-
puts "Final validation: #{result.final_validation.valid?}"
|
|
603
|
-
else
|
|
604
|
-
puts "Remediation failed: #{result.error.message}"
|
|
605
|
-
end
|
|
606
|
-
----
|
|
607
|
-
|
|
608
|
-
==== Checking available remediations
|
|
609
|
-
|
|
610
|
-
[source,ruby]
|
|
611
|
-
----
|
|
612
|
-
profile = SvgConform::Profiles.get(:metanorma)
|
|
613
|
-
|
|
614
|
-
puts "Profile has #{profile.remediation_count} remediations available"
|
|
615
|
-
|
|
616
|
-
profile.remediations.each do |remediation|
|
|
617
|
-
puts "- #{remediation.class.name}"
|
|
618
|
-
end
|
|
619
|
-
----
|
|
620
|
-
|
|
621
|
-
=== Working with documents
|
|
622
|
-
|
|
623
|
-
==== Creating documents
|
|
624
|
-
|
|
625
|
-
From a string:
|
|
626
|
-
|
|
627
|
-
[source,ruby]
|
|
628
|
-
----
|
|
629
|
-
document = SvgConform::Document.new(svg_string)
|
|
630
|
-
----
|
|
631
|
-
|
|
632
|
-
From a file:
|
|
633
|
-
|
|
634
|
-
[source,ruby]
|
|
635
|
-
----
|
|
636
|
-
document = SvgConform::Document.from_file('path/to/file.svg')
|
|
637
|
-
----
|
|
638
|
-
|
|
639
|
-
From a DOM node (Nokogiri or Moxml):
|
|
640
|
-
|
|
641
|
-
[source,ruby]
|
|
642
|
-
----
|
|
643
|
-
nokogiri_element = Nokogiri::XML(svg_string).root
|
|
644
|
-
document = SvgConform::Document.from_node(nokogiri_element)
|
|
645
|
-
----
|
|
646
|
-
|
|
647
|
-
==== Document operations
|
|
648
|
-
|
|
649
|
-
[source,ruby]
|
|
650
|
-
----
|
|
651
|
-
# Access the underlying DOM
|
|
652
|
-
root = document.root
|
|
653
|
-
elements = document.find_all('//svg:rect')
|
|
654
|
-
|
|
655
|
-
# Check for specific elements
|
|
656
|
-
has_viewbox = document.root.attribute?('viewBox')
|
|
657
|
-
|
|
658
|
-
# Modify the document
|
|
659
|
-
document.root.set_attribute('width', '500')
|
|
660
|
-
|
|
661
|
-
# Serialize to XML
|
|
662
|
-
xml_string = document.to_xml
|
|
663
|
-
----
|
|
664
|
-
|
|
665
|
-
=== Reference manifest
|
|
666
|
-
|
|
667
|
-
==== Accessing the manifest
|
|
668
|
-
|
|
669
|
-
[source,ruby]
|
|
670
|
-
----
|
|
671
|
-
result = validator.validate(svg_content, profile: :metanorma)
|
|
672
|
-
manifest = result.reference_manifest
|
|
673
|
-
|
|
674
|
-
# Get all defined IDs
|
|
675
|
-
manifest.available_ids.each do |id_def|
|
|
676
|
-
puts "ID: #{id_def.id_value}"
|
|
677
|
-
puts " Element: #{id_def.element_name}"
|
|
678
|
-
puts " Line: #{id_def.line_number}"
|
|
679
|
-
end
|
|
680
|
-
----
|
|
681
|
-
|
|
682
|
-
==== Checking references
|
|
683
|
-
|
|
684
|
-
[source,ruby]
|
|
685
|
-
----
|
|
686
|
-
# Check for unresolved internal references
|
|
687
|
-
if result.has_unresolved_references?
|
|
688
|
-
puts "Unresolved references found:"
|
|
689
|
-
result.unresolved_internal_references.each do |ref|
|
|
690
|
-
puts " #{ref.value} at line #{ref.line_number}"
|
|
691
|
-
end
|
|
692
|
-
end
|
|
693
|
-
|
|
694
|
-
# Check for external references
|
|
695
|
-
if result.has_external_references?
|
|
696
|
-
puts "External references:"
|
|
697
|
-
result.external_references.each do |ref|
|
|
698
|
-
puts " #{ref.value} (#{ref.reference_type})"
|
|
699
|
-
end
|
|
700
|
-
end
|
|
701
|
-
----
|
|
702
|
-
|
|
703
|
-
==== Reference types
|
|
704
|
-
|
|
705
|
-
The manifest classifies references by type:
|
|
706
|
-
|
|
707
|
-
[source,ruby]
|
|
708
|
-
----
|
|
709
|
-
manifest.internal_references.each do |ref|
|
|
710
|
-
case ref.reference_type
|
|
711
|
-
when 'url'
|
|
712
|
-
puts "URL reference: #{ref.value}"
|
|
713
|
-
when 'fragment'
|
|
714
|
-
puts "Fragment reference: #{ref.value}"
|
|
715
|
-
when 'fill'
|
|
716
|
-
puts "Fill attribute: #{ref.value}"
|
|
717
|
-
when 'href'
|
|
718
|
-
puts "Href attribute: #{ref.value}"
|
|
719
|
-
end
|
|
720
|
-
end
|
|
721
|
-
----
|
|
722
|
-
|
|
723
|
-
=== Advanced usage
|
|
724
|
-
|
|
725
|
-
==== Custom validation context
|
|
726
|
-
|
|
727
|
-
[source,ruby]
|
|
728
|
-
----
|
|
729
|
-
context = SvgConform::ValidationContext.new(
|
|
730
|
-
document: document,
|
|
731
|
-
profile: profile
|
|
732
|
-
)
|
|
733
|
-
|
|
734
|
-
# Run specific requirements
|
|
735
|
-
requirement = SvgConform::Requirements::ViewboxRequiredRequirement.new
|
|
736
|
-
errors = requirement.check(context)
|
|
737
|
-
----
|
|
738
|
-
|
|
739
|
-
==== Batch processing
|
|
740
|
-
|
|
741
|
-
[source,ruby]
|
|
742
|
-
----
|
|
743
|
-
validator = SvgConform::Validator.new
|
|
744
|
-
results = {}
|
|
745
|
-
|
|
746
|
-
Dir.glob('images/**/*.svg').each do |file|
|
|
747
|
-
result = validator.validate_file(file, profile: :metanorma)
|
|
748
|
-
results[file] = result
|
|
749
|
-
end
|
|
750
|
-
|
|
751
|
-
# Summary
|
|
752
|
-
valid_count = results.count { |_, r| r.valid? }
|
|
753
|
-
puts "#{valid_count}/#{results.size} files are valid"
|
|
754
|
-
----
|
|
755
|
-
|
|
756
|
-
==== Report generation
|
|
757
|
-
|
|
758
|
-
[source,ruby]
|
|
759
|
-
----
|
|
760
|
-
# Create a conformance report
|
|
761
|
-
report = SvgConform::ConformanceReport.from_svg_conform_result(
|
|
762
|
-
"file.svg",
|
|
763
|
-
result,
|
|
764
|
-
profile: :metanorma
|
|
765
|
-
)
|
|
766
|
-
|
|
767
|
-
# Export as JSON
|
|
768
|
-
json_output = report.to_json
|
|
769
|
-
File.write('report.json', json_output)
|
|
770
|
-
|
|
771
|
-
# Export as YAML
|
|
772
|
-
yaml_output = report.to_yaml
|
|
773
|
-
File.write('report.yaml', yaml_output)
|
|
774
|
-
----
|
|
775
|
-
|
|
776
|
-
=== API classes
|
|
777
|
-
|
|
778
|
-
==== Core classes
|
|
779
|
-
|
|
780
|
-
* `SvgConform::Validator` - Main validation interface
|
|
781
|
-
* `SvgConform::Profile` - Profile definition and management
|
|
782
|
-
* `SvgConform::Document` - SVG document wrapper
|
|
783
|
-
* `SvgConform::ValidationResult` - Validation result container
|
|
784
|
-
* `SvgConform::RemediationRunner` - Remediation execution
|
|
785
|
-
|
|
786
|
-
==== Requirement classes
|
|
787
|
-
|
|
788
|
-
Located in `SvgConform::Requirements`:
|
|
789
|
-
|
|
790
|
-
* `AllowedElementsRequirement` - Element whitelist validation
|
|
791
|
-
* `ColorRestrictionsRequirement` - Color format restrictions
|
|
792
|
-
* `FontFamilyRequirement` - Font family restrictions
|
|
793
|
-
* `ForbiddenContentRequirement` - Forbidden element/attribute check
|
|
794
|
-
* `IdReferenceRequirement` - ID reference validation
|
|
795
|
-
* `InvalidIdReferencesRequirement` - Invalid reference detection
|
|
796
|
-
* `LinkValidationRequirement` - Link validation
|
|
797
|
-
* `NamespaceRequirement` - Namespace validation
|
|
798
|
-
* `NamespaceAttributesRequirement` - Namespace attribute check
|
|
799
|
-
* `NoExternalCssRequirement` - External CSS prohibition
|
|
800
|
-
* `NoExternalFontsRequirement` - External font prohibition
|
|
801
|
-
* `NoExternalImagesRequirement` - External image prohibition
|
|
802
|
-
* `StylePromotionRequirement` - Presentation attribute check
|
|
803
|
-
* `StyleRequirement` - Style attribute validation
|
|
804
|
-
* `ViewboxRequiredRequirement` - ViewBox requirement
|
|
805
|
-
|
|
806
|
-
==== Remediation classes
|
|
807
|
-
|
|
808
|
-
Located in `SvgConform::Remediations`:
|
|
809
|
-
|
|
810
|
-
* `ColorRemediation` - Fix color format issues
|
|
811
|
-
* `FontRemediation` - Fix font family issues
|
|
812
|
-
* `FontEmbeddingRemediation` - Embed external fonts
|
|
813
|
-
* `ImageEmbeddingRemediation` - Embed external images
|
|
814
|
-
* `InvalidIdReferencesRemediation` - Fix invalid references
|
|
815
|
-
* `NamespaceRemediation` - Fix namespace issues
|
|
816
|
-
* `NamespaceAttributeRemediation` - Remove namespace attributes
|
|
817
|
-
* `NoExternalCssRemediation` - Convert external CSS
|
|
818
|
-
* `StylePromotionRemediation` - Promote presentation attributes
|
|
819
|
-
* `ViewboxRemediation` - Add missing ViewBox
|
|
820
|
-
|
|
821
|
-
=== Complete reference
|
|
822
|
-
|
|
823
|
-
See link:docs/api_reference.adoc[API Reference] for comprehensive documentation including:
|
|
824
|
-
|
|
825
|
-
* Complete class hierarchy
|
|
826
|
-
* Detailed method signatures
|
|
827
|
-
* Parameter descriptions
|
|
828
|
-
* Return value specifications
|
|
829
|
-
* Integration patterns
|
|
830
|
-
* Advanced examples
|
|
831
|
-
|
|
832
|
-
|
|
833
352
|
[[external_compliance]]
|
|
834
353
|
== External compliance
|
|
835
354
|
|
|
@@ -841,6 +360,25 @@ SvgConform provides compatibility with existing SVG validation tools:
|
|
|
841
360
|
See link:docs/compatibility.adoc[Compatibility Documentation] for details.
|
|
842
361
|
|
|
843
362
|
|
|
363
|
+
== Documentation
|
|
364
|
+
|
|
365
|
+
=== User documentation
|
|
366
|
+
|
|
367
|
+
* link:docs/cli_guide.adoc[CLI Guide] - Comprehensive command-line usage
|
|
368
|
+
* link:docs/api_reference.adoc[API Reference] - Complete Ruby API documentation
|
|
369
|
+
* link:docs/profiles.adoc[Profile Documentation] - Profile system and built-in profiles
|
|
370
|
+
* link:docs/requirements.adoc[Requirements Reference] - All validation requirements
|
|
371
|
+
* link:docs/remediation.adoc[Remediation Reference] - All automatic remediations
|
|
372
|
+
* link:docs/reference_manifest.adoc[Reference Manifest] - ID and reference tracking
|
|
373
|
+
* link:docs/rdf_metadata_support.adoc[RDF Metadata Support] - RDF/Dublin Core configuration
|
|
374
|
+
|
|
375
|
+
=== Developer documentation
|
|
376
|
+
|
|
377
|
+
* link:docs/sax_validation_mode.adoc[SAX Validation Mode] - Writing SAX-compatible requirements
|
|
378
|
+
* link:CONTINUATION_PLAN.md[Development Plan] - Project roadmap and tasks
|
|
379
|
+
* link:IMPLEMENTATION_STATUS.md[Implementation Status] - Component status tracking
|
|
380
|
+
|
|
381
|
+
|
|
844
382
|
== Development
|
|
845
383
|
|
|
846
384
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
|
@@ -363,8 +363,9 @@ Strongly-typed reference objects with validation scope clearly defined.
|
|
|
363
363
|
|
|
364
364
|
Easy to add new reference types without modifying existing code.
|
|
365
365
|
|
|
366
|
-
==
|
|
366
|
+
== Additional resources
|
|
367
367
|
|
|
368
|
-
* link:../EXTERNAL_REFERENCE_PROPOSAL.md[External Reference Architecture Proposal]
|
|
369
368
|
* link:requirements.adoc[Requirements Documentation]
|
|
369
|
+
* link:api_reference.adoc[API Reference]
|
|
370
|
+
* link:../README.adoc[Main README]
|
|
370
371
|
* link:../config/profiles/metanorma.yml[Metanorma Profile Configuration]
|
data/lib/svg_conform/document.rb
CHANGED
|
@@ -92,7 +92,28 @@ module SvgConform
|
|
|
92
92
|
def to_xml
|
|
93
93
|
# Always generate from current moxml_document state
|
|
94
94
|
# This ensures modifications are reflected in the output
|
|
95
|
-
@moxml_document.to_xml
|
|
95
|
+
xml = @moxml_document.to_xml
|
|
96
|
+
|
|
97
|
+
# Clean up unused namespace declarations if marked by remediations
|
|
98
|
+
if instance_variable_defined?(:@unused_namespace_prefixes)
|
|
99
|
+
prefixes = @unused_namespace_prefixes
|
|
100
|
+
xml = remove_namespace_declarations(xml, prefixes) if prefixes && !prefixes.empty?
|
|
101
|
+
# Clear the marker after cleanup
|
|
102
|
+
remove_instance_variable(:@unused_namespace_prefixes)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
xml
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def remove_namespace_declarations(xml, prefixes)
|
|
109
|
+
# Remove xmlns:prefix="uri" declarations from the XML string
|
|
110
|
+
# This works around Moxml/Nokogiri's inability to remove namespace declarations
|
|
111
|
+
prefixes.reduce(xml) do |result, prefix|
|
|
112
|
+
# Match xmlns:prefix="..." with various quote styles and surrounding whitespace
|
|
113
|
+
# The pattern matches: xmlns:prefix="uri" or xmlns:prefix='uri'
|
|
114
|
+
# It captures leading whitespace to remove it too
|
|
115
|
+
result.gsub(%r{\s+xmlns:#{prefix}=["'][^"']*["']}, "")
|
|
116
|
+
end
|
|
96
117
|
end
|
|
97
118
|
|
|
98
119
|
def dup
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SvgConform
|
|
4
|
+
# Shared helper methods for working with XML nodes
|
|
5
|
+
#
|
|
6
|
+
# This module provides common utilities used by both requirements
|
|
7
|
+
# and remediations to avoid code duplication and ensure consistency.
|
|
8
|
+
module NodeHelpers
|
|
9
|
+
# Check if a node is an element
|
|
10
|
+
# @param node [Object] the node to check
|
|
11
|
+
# @return [Boolean] true if the node is an element
|
|
12
|
+
def element?(node)
|
|
13
|
+
node.respond_to?(:name) && !node.name.nil?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Check if a node is text
|
|
17
|
+
# @param node [Object] the node to check
|
|
18
|
+
# @return [Boolean] true if the node is text
|
|
19
|
+
def text?(node)
|
|
20
|
+
node.respond_to?(:text?) && node.text?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Get attribute value from a node
|
|
24
|
+
# @param node [Object] the node
|
|
25
|
+
# @param name [String] attribute name
|
|
26
|
+
# @return [String, nil] attribute value or nil
|
|
27
|
+
def get_attribute(node, name)
|
|
28
|
+
return nil unless node.respond_to?(:[])
|
|
29
|
+
|
|
30
|
+
node[name]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Set attribute value on a node
|
|
34
|
+
# @param node [Object] the node
|
|
35
|
+
# @param name [String] attribute name
|
|
36
|
+
# @param value [String] attribute value
|
|
37
|
+
# @return [Boolean] true if successful
|
|
38
|
+
def set_attribute(node, name, value)
|
|
39
|
+
return unless node.respond_to?(:[]=)
|
|
40
|
+
|
|
41
|
+
node[name] = value
|
|
42
|
+
true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Check if node has an attribute
|
|
46
|
+
# @param node [Object] the node
|
|
47
|
+
# @param name [String] attribute name
|
|
48
|
+
# @return [Boolean] true if attribute exists
|
|
49
|
+
def has_attribute?(node, name)
|
|
50
|
+
return false unless node.respond_to?(:[])
|
|
51
|
+
|
|
52
|
+
!node[name].nil?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Remove attribute from a node
|
|
56
|
+
# @param node [Object] the node
|
|
57
|
+
# @param name [String] attribute name
|
|
58
|
+
# @return [Boolean] true if successful
|
|
59
|
+
def remove_attribute(node, name)
|
|
60
|
+
if node.respond_to?(:remove_attribute)
|
|
61
|
+
node.remove_attribute(name)
|
|
62
|
+
true
|
|
63
|
+
elsif node.respond_to?(:[]=) && node.respond_to?(:[])
|
|
64
|
+
# Fallback for bracket notation
|
|
65
|
+
node[name] = nil
|
|
66
|
+
true
|
|
67
|
+
else
|
|
68
|
+
false
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
require "lutaml/model"
|
|
4
4
|
require_relative "../remediation_result"
|
|
5
|
+
require_relative "../node_helpers"
|
|
5
6
|
|
|
6
7
|
module SvgConform
|
|
7
8
|
module Remediations
|
|
8
9
|
# Base class for all remediations using lutaml-model serialization
|
|
9
10
|
class BaseRemediation < Lutaml::Model::Serializable
|
|
11
|
+
include SvgConform::NodeHelpers
|
|
12
|
+
|
|
10
13
|
attribute :id, :string
|
|
11
14
|
attribute :description, :string
|
|
12
15
|
attribute :targets, :string, collection: true
|
|
@@ -72,27 +75,8 @@ module SvgConform
|
|
|
72
75
|
|
|
73
76
|
protected
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def get_attribute(node, attr_name)
|
|
80
|
-
return nil unless node.respond_to?(:[])
|
|
81
|
-
|
|
82
|
-
node[attr_name]
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def set_attribute(node, attr_name, value)
|
|
86
|
-
return unless node.respond_to?(:[]=)
|
|
87
|
-
|
|
88
|
-
node[attr_name] = value
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def has_attribute?(node, attr_name)
|
|
92
|
-
return false unless node.respond_to?(:[])
|
|
93
|
-
|
|
94
|
-
!node[attr_name].nil?
|
|
95
|
-
end
|
|
78
|
+
# Helper methods for node manipulation included via NodeHelpers module:
|
|
79
|
+
# element?, text?, get_attribute, set_attribute, has_attribute?, remove_attribute
|
|
96
80
|
|
|
97
81
|
def find_nodes(document, &)
|
|
98
82
|
nodes = []
|
|
@@ -100,20 +84,6 @@ module SvgConform
|
|
|
100
84
|
nodes
|
|
101
85
|
end
|
|
102
86
|
|
|
103
|
-
# Helper method to remove attribute
|
|
104
|
-
def remove_attribute(node, name)
|
|
105
|
-
if node.respond_to?(:remove_attribute)
|
|
106
|
-
node.remove_attribute(name)
|
|
107
|
-
true
|
|
108
|
-
elsif node.respond_to?(:[]=) && node.respond_to?(:[])
|
|
109
|
-
# Fallback for different implementations
|
|
110
|
-
node[name] = nil
|
|
111
|
-
true
|
|
112
|
-
else
|
|
113
|
-
false
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
87
|
# Helper method to remove node
|
|
118
88
|
def remove_node(node)
|
|
119
89
|
return false unless node.respond_to?(:remove)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "base_remediation"
|
|
4
|
+
require "set"
|
|
4
5
|
|
|
5
6
|
module SvgConform
|
|
6
7
|
module Remediations
|
|
@@ -105,6 +106,11 @@ module SvgConform
|
|
|
105
106
|
remove_node(node)
|
|
106
107
|
end
|
|
107
108
|
|
|
109
|
+
# Clean up unused namespace declarations
|
|
110
|
+
# Note: Moxml/Nokogiri don't support removing namespace declarations directly,
|
|
111
|
+
# so we mark the document for post-processing during serialization
|
|
112
|
+
cleanup_unused_namespace_declarations(document)
|
|
113
|
+
|
|
108
114
|
changes
|
|
109
115
|
end
|
|
110
116
|
|
|
@@ -146,6 +152,60 @@ module SvgConform
|
|
|
146
152
|
# Same logic as find_namespace_uri_for_prefix
|
|
147
153
|
find_namespace_uri_for_prefix(node, prefix)
|
|
148
154
|
end
|
|
155
|
+
|
|
156
|
+
def cleanup_unused_namespace_declarations(document)
|
|
157
|
+
# Find which namespace prefixes are still in use
|
|
158
|
+
used_prefixes = find_used_namespace_prefixes(document)
|
|
159
|
+
|
|
160
|
+
# Get the root element
|
|
161
|
+
root = document.respond_to?(:root) ? document.root : document
|
|
162
|
+
return unless root.respond_to?(:namespace_definitions)
|
|
163
|
+
|
|
164
|
+
# Get disallowed namespace prefixes
|
|
165
|
+
disallowed_prefixes = root.namespace_definitions.filter_map do |ns|
|
|
166
|
+
prefix = ns.respond_to?(:prefix) ? ns.prefix : nil
|
|
167
|
+
# Extract namespace URI from Moxml::Namespace object
|
|
168
|
+
uri = ns.respond_to?(:uri) ? ns.uri : nil
|
|
169
|
+
next if prefix.nil? || prefix.empty? # Skip default namespace
|
|
170
|
+
next if allowed_namespaces.include?(uri) # Keep allowed namespaces
|
|
171
|
+
|
|
172
|
+
next if used_prefixes.include?(prefix) # Keep prefixes still in use
|
|
173
|
+
|
|
174
|
+
prefix
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Store the prefixes to remove on the document for later serialization
|
|
178
|
+
# Try to store on Document wrapper first, fallback to moxml_document
|
|
179
|
+
target = document.respond_to?(:instance_variable_set) ? document : root.document
|
|
180
|
+
target&.instance_variable_set(:@unused_namespace_prefixes, disallowed_prefixes)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def find_used_namespace_prefixes(document)
|
|
184
|
+
used_prefixes = Set.new(["xml"]) # xml prefix is always reserved
|
|
185
|
+
|
|
186
|
+
document.traverse do |node|
|
|
187
|
+
next unless node.respond_to?(:name)
|
|
188
|
+
|
|
189
|
+
# Check element name for namespace prefix
|
|
190
|
+
if node.name.include?(":")
|
|
191
|
+
prefix = node.name.split(":").first
|
|
192
|
+
used_prefixes << prefix
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Check attributes for namespace prefixes
|
|
196
|
+
if node.respond_to?(:attributes)
|
|
197
|
+
node.attributes.each do |attr|
|
|
198
|
+
attr_name = attr.respond_to?(:name) ? attr.name : attr.to_s
|
|
199
|
+
if attr_name.include?(":")
|
|
200
|
+
prefix = attr_name.split(":").first
|
|
201
|
+
used_prefixes << prefix
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
used_prefixes
|
|
208
|
+
end
|
|
149
209
|
end
|
|
150
210
|
end
|
|
151
211
|
end
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../node_helpers"
|
|
4
|
+
|
|
3
5
|
module SvgConform
|
|
4
6
|
module Requirements
|
|
5
7
|
# Base class for all validation requirements
|
|
6
8
|
class BaseRequirement < Lutaml::Model::Serializable
|
|
9
|
+
include SvgConform::NodeHelpers
|
|
10
|
+
|
|
7
11
|
attribute :id, :string
|
|
8
12
|
attribute :description, :string
|
|
9
13
|
attribute :type, :string, polymorphic_class: true, default: -> {
|
|
@@ -65,48 +69,8 @@ module SvgConform
|
|
|
65
69
|
true
|
|
66
70
|
end
|
|
67
71
|
|
|
68
|
-
# Helper method to check if a node is an element
|
|
69
|
-
def element?(node)
|
|
70
|
-
node.respond_to?(:name) && !node.name.nil?
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Helper method to check if a node is text
|
|
74
|
-
def text?(node)
|
|
75
|
-
node.respond_to?(:text?) && node.text?
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# Helper method to get attribute value
|
|
79
|
-
def get_attribute(node, name)
|
|
80
|
-
return nil unless node.respond_to?(:attribute)
|
|
81
|
-
|
|
82
|
-
attr = node.attribute(name)
|
|
83
|
-
attr&.value
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# Helper method to set attribute value
|
|
87
|
-
def set_attribute(node, name, value)
|
|
88
|
-
return false unless node.respond_to?(:set_attribute)
|
|
89
|
-
|
|
90
|
-
node.set_attribute(name, value)
|
|
91
|
-
true
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# Helper method to remove attribute
|
|
95
|
-
def remove_attribute(node, name)
|
|
96
|
-
return false unless node.respond_to?(:remove_attribute)
|
|
97
|
-
|
|
98
|
-
node.remove_attribute(name)
|
|
99
|
-
true
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# Helper method to check if attribute exists
|
|
103
|
-
def has_attribute?(node, name)
|
|
104
|
-
return false unless node.respond_to?(:attribute)
|
|
105
|
-
|
|
106
|
-
!node.attribute(name).nil?
|
|
107
|
-
end
|
|
108
|
-
|
|
109
72
|
# Helper method to get all attributes
|
|
73
|
+
# Note: Other attribute helpers are included via NodeHelpers module
|
|
110
74
|
def get_attributes(node)
|
|
111
75
|
return {} unless node.respond_to?(:attributes)
|
|
112
76
|
|
data/lib/svg_conform/version.rb
CHANGED
data/svg_conform.gemspec
CHANGED
|
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
spec.require_paths = ["lib"]
|
|
30
30
|
|
|
31
31
|
spec.add_dependency "lutaml-model", "~> 0.7"
|
|
32
|
-
spec.add_dependency "moxml"
|
|
32
|
+
spec.add_dependency "moxml", "~> 0.1", ">= 0.1.10"
|
|
33
33
|
spec.add_dependency "table_tennis"
|
|
34
34
|
spec.add_dependency "thor"
|
|
35
35
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: svg_conform
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|
|
@@ -28,16 +28,22 @@ dependencies:
|
|
|
28
28
|
name: moxml
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.1'
|
|
31
34
|
- - ">="
|
|
32
35
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
36
|
+
version: 0.1.10
|
|
34
37
|
type: :runtime
|
|
35
38
|
prerelease: false
|
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
40
|
requirements:
|
|
41
|
+
- - "~>"
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '0.1'
|
|
38
44
|
- - ">="
|
|
39
45
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
46
|
+
version: 0.1.10
|
|
41
47
|
- !ruby/object:Gem::Dependency
|
|
42
48
|
name: table_tennis
|
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -138,6 +144,7 @@ files:
|
|
|
138
144
|
- lib/svg_conform/external_checkers/svgcheck/validation_pipeline.rb
|
|
139
145
|
- lib/svg_conform/fast_document_analyzer.rb
|
|
140
146
|
- lib/svg_conform/fixer.rb
|
|
147
|
+
- lib/svg_conform/node_helpers.rb
|
|
141
148
|
- lib/svg_conform/node_index_builder.rb
|
|
142
149
|
- lib/svg_conform/profile.rb
|
|
143
150
|
- lib/svg_conform/profiles.rb
|