svg_conform 0.1.12 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +33 -109
- data/Gemfile +2 -0
- data/README.adoc +164 -0
- data/config/profiles/metanorma.yml +21 -14
- data/config/quality_metrics.yml +212 -0
- data/docs/image_quality.adoc +526 -0
- data/docs/performance.adoc +31 -0
- data/docs/profiles.adoc +33 -1
- data/docs/requirements.adoc +178 -0
- data/lib/svg_conform/cli.rb +5 -0
- data/lib/svg_conform/commands/quality.rb +249 -0
- data/lib/svg_conform/compatibility/report_formatter.rb +3 -5
- data/lib/svg_conform/compatibility_analyzer.rb +3 -3
- data/lib/svg_conform/document_analyzer.rb +9 -4
- data/lib/svg_conform/external_checkers/svgcheck/validation_pipeline.rb +5 -5
- data/lib/svg_conform/image_quality_analyzer.rb +225 -0
- data/lib/svg_conform/quality_metrics/complexity_calculator.rb +98 -0
- data/lib/svg_conform/quality_metrics/complexity_metrics.rb +56 -0
- data/lib/svg_conform/quality_metrics/configuration.rb +342 -0
- data/lib/svg_conform/quality_metrics/error_analyzer.rb +90 -0
- data/lib/svg_conform/quality_metrics/error_breakdown.rb +80 -0
- data/lib/svg_conform/quality_metrics/feature_detector.rb +55 -0
- data/lib/svg_conform/quality_metrics/feature_flags.rb +65 -0
- data/lib/svg_conform/quality_metrics/quality_calculator.rb +130 -0
- data/lib/svg_conform/quality_metrics/quality_report_formatter.rb +70 -0
- data/lib/svg_conform/quality_metrics/quality_result.rb +101 -0
- data/lib/svg_conform/quality_metrics/quality_score.rb +76 -0
- data/lib/svg_conform/quality_report.rb +342 -0
- data/lib/svg_conform/remediations/color_remediation.rb +1 -3
- data/lib/svg_conform/remediations/viewbox_remediation.rb +5 -9
- data/lib/svg_conform/requirements/invalid_id_references_requirement.rb +1 -1
- data/lib/svg_conform/requirements/style_requirement.rb +3 -2
- data/lib/svg_conform/requirements/text_as_path_requirement.rb +98 -0
- data/lib/svg_conform/requirements.rb +2 -0
- data/lib/svg_conform/sax_validation_handler.rb +3 -3
- data/lib/svg_conform/semantic_comparator.rb +3 -3
- data/lib/svg_conform/validation_result.rb +1 -1
- data/lib/svg_conform/version.rb +1 -1
- data/lib/svg_conform.rb +23 -0
- data/lib/tasks/fixtures.rake +1 -1
- data/spec/svg_conform/profiles/lucid_profile_spec.rb +0 -2
- data/spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb +9 -9
- data/spec/svg_conform/requirements/allowed_elements_requirement_spec.rb +120 -1
- data/spec/svg_conform/requirements/color_restrictions_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/font_family_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/forbidden_content_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/id_reference_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/invalid_id_references_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/link_validation_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/namespace_attributes_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/namespace_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/no_external_css_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/style_promotion_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/style_requirement_spec.rb +0 -1
- data/spec/svg_conform/requirements/text_as_path_requirement_spec.rb +142 -0
- data/spec/svg_conform/requirements/viewbox_required_requirement_spec.rb +0 -1
- data/spec/svg_conform_spec.rb +2 -2
- data/spec/svgcheck_compatibility_spec.rb +5 -13
- data/svg_conform.gemspec +3 -1
- metadata +37 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 136c672fbb6005495a240d2d8b7f30000fae008cd16fff6bfe51a74e7dbe2262
|
|
4
|
+
data.tar.gz: 679452859b709b2e9ef78916918ea9e58040ebfb382291b8c6543b9062a5ee09
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 26a32728202834b61e892d78ef87bb6bae0030e768414985cfe0bfa208da9fa21828035fe6f247225c6cd37a299dff6fe91863c70137c528d7e24a9aade3250e
|
|
7
|
+
data.tar.gz: 47b4ba1d348244438817269403a2b5b09019687024849e691ff6fe4dcbb9d4fed1a322f132758af38f8ba1310fb0666cc5d9dbaeef93192a8edaf19df66bb1c9
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-04-
|
|
3
|
+
# on 2026-04-09 13:07:51 UTC using RuboCop version 1.86.0.
|
|
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: 1
|
|
10
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
11
|
-
Gemspec/RequireMFA:
|
|
12
|
-
Exclude:
|
|
13
|
-
- 'svg_conform.gemspec'
|
|
14
|
-
|
|
15
9
|
# Offense count: 1
|
|
16
10
|
# This cop supports safe autocorrection (--autocorrect).
|
|
17
11
|
# Configuration parameters: EnforcedStyleAlignWith.
|
|
@@ -20,44 +14,19 @@ Layout/BlockAlignment:
|
|
|
20
14
|
Exclude:
|
|
21
15
|
- 'spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb'
|
|
22
16
|
|
|
23
|
-
# Offense count:
|
|
24
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
25
|
-
# Configuration parameters: EnforcedStyle.
|
|
26
|
-
# SupportedStyles: leading, trailing
|
|
27
|
-
Layout/LineContinuationLeadingSpace:
|
|
28
|
-
Exclude:
|
|
29
|
-
- 'spec/svgcheck_compatibility_spec.rb'
|
|
30
|
-
|
|
31
|
-
# Offense count: 5
|
|
32
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
33
|
-
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
34
|
-
# SupportedStyles: aligned, indented
|
|
35
|
-
Layout/LineEndStringConcatenationIndentation:
|
|
36
|
-
Exclude:
|
|
37
|
-
- 'lib/svg_conform/external_checkers/svgcheck/validation_pipeline.rb'
|
|
38
|
-
- 'spec/svgcheck_compatibility_spec.rb'
|
|
39
|
-
|
|
40
|
-
# Offense count: 649
|
|
17
|
+
# Offense count: 667
|
|
41
18
|
# This cop supports safe autocorrection (--autocorrect).
|
|
42
19
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
43
20
|
# URISchemes: http, https
|
|
44
21
|
Layout/LineLength:
|
|
45
22
|
Enabled: false
|
|
46
23
|
|
|
47
|
-
# Offense count:
|
|
24
|
+
# Offense count: 9
|
|
48
25
|
# This cop supports safe autocorrection (--autocorrect).
|
|
49
|
-
|
|
26
|
+
# Configuration parameters: AllowInHeredoc.
|
|
27
|
+
Layout/TrailingWhitespace:
|
|
50
28
|
Exclude:
|
|
51
|
-
- '
|
|
52
|
-
- 'lib/svg_conform/semantic_comparator.rb'
|
|
53
|
-
- 'lib/svg_conform/validation_result.rb'
|
|
54
|
-
|
|
55
|
-
# Offense count: 1
|
|
56
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
57
|
-
# Configuration parameters: RequireParenthesesForMethodChains.
|
|
58
|
-
Lint/AmbiguousRange:
|
|
59
|
-
Exclude:
|
|
60
|
-
- 'lib/svg_conform/compatibility/report_formatter.rb'
|
|
29
|
+
- 'spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb'
|
|
61
30
|
|
|
62
31
|
# Offense count: 3
|
|
63
32
|
# Configuration parameters: AllowedMethods.
|
|
@@ -91,7 +60,14 @@ Lint/DuplicateMethods:
|
|
|
91
60
|
- 'lib/svg_conform/sax_validation_handler.rb'
|
|
92
61
|
- 'spec/svg_conform/validation_context_spec.rb'
|
|
93
62
|
|
|
94
|
-
# Offense count:
|
|
63
|
+
# Offense count: 1
|
|
64
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
65
|
+
# Configuration parameters: AllowComments.
|
|
66
|
+
Lint/EmptyConditionalBody:
|
|
67
|
+
Exclude:
|
|
68
|
+
- 'spec/svgcheck_compatibility_spec.rb'
|
|
69
|
+
|
|
70
|
+
# Offense count: 1
|
|
95
71
|
Lint/HashCompareByIdentity:
|
|
96
72
|
Exclude:
|
|
97
73
|
- 'lib/svg_conform/document_analyzer.rb'
|
|
@@ -104,24 +80,12 @@ Lint/MissingSuper:
|
|
|
104
80
|
- 'lib/svg_conform/compatibility/validity_analysis.rb'
|
|
105
81
|
- 'lib/svg_conform/sax_validation_handler.rb'
|
|
106
82
|
|
|
107
|
-
# Offense count:
|
|
108
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
109
|
-
Lint/RedundantDirGlobSort:
|
|
110
|
-
Exclude:
|
|
111
|
-
- 'lib/tasks/fixtures.rake'
|
|
112
|
-
|
|
113
|
-
# Offense count: 1
|
|
114
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
115
|
-
Lint/SuppressedExceptionInNumberConversion:
|
|
116
|
-
Exclude:
|
|
117
|
-
- 'lib/svg_conform/remediations/viewbox_remediation.rb'
|
|
118
|
-
|
|
119
|
-
# Offense count: 145
|
|
83
|
+
# Offense count: 160
|
|
120
84
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
121
85
|
Metrics/AbcSize:
|
|
122
86
|
Enabled: false
|
|
123
87
|
|
|
124
|
-
# Offense count:
|
|
88
|
+
# Offense count: 25
|
|
125
89
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
|
126
90
|
# AllowedMethods: refine
|
|
127
91
|
Metrics/BlockLength:
|
|
@@ -132,22 +96,22 @@ Metrics/BlockLength:
|
|
|
132
96
|
Metrics/BlockNesting:
|
|
133
97
|
Max: 4
|
|
134
98
|
|
|
135
|
-
# Offense count:
|
|
99
|
+
# Offense count: 138
|
|
136
100
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
137
101
|
Metrics/CyclomaticComplexity:
|
|
138
102
|
Enabled: false
|
|
139
103
|
|
|
140
|
-
# Offense count:
|
|
104
|
+
# Offense count: 276
|
|
141
105
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
142
106
|
Metrics/MethodLength:
|
|
143
107
|
Max: 154
|
|
144
108
|
|
|
145
|
-
# Offense count:
|
|
109
|
+
# Offense count: 8
|
|
146
110
|
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
|
147
111
|
Metrics/ParameterLists:
|
|
148
112
|
Max: 9
|
|
149
113
|
|
|
150
|
-
# Offense count:
|
|
114
|
+
# Offense count: 112
|
|
151
115
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
152
116
|
Metrics/PerceivedComplexity:
|
|
153
117
|
Enabled: false
|
|
@@ -171,12 +135,6 @@ Performance/CollectionLiteralInLoop:
|
|
|
171
135
|
- 'lib/svg_conform/batch_report.rb'
|
|
172
136
|
- 'lib/svg_conform/compatibility/pattern_discovery.rb'
|
|
173
137
|
|
|
174
|
-
# Offense count: 2
|
|
175
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
176
|
-
Performance/MapCompact:
|
|
177
|
-
Exclude:
|
|
178
|
-
- 'lib/svg_conform/remediations/viewbox_remediation.rb'
|
|
179
|
-
|
|
180
138
|
# Offense count: 9
|
|
181
139
|
# Configuration parameters: IgnoredMetadata.
|
|
182
140
|
RSpec/DescribeClass:
|
|
@@ -199,7 +157,7 @@ RSpec/DescribeClass:
|
|
|
199
157
|
# Offense count: 157
|
|
200
158
|
# Configuration parameters: CountAsOne.
|
|
201
159
|
RSpec/ExampleLength:
|
|
202
|
-
Max:
|
|
160
|
+
Max: 43
|
|
203
161
|
|
|
204
162
|
# Offense count: 3
|
|
205
163
|
RSpec/LeakyConstantDeclaration:
|
|
@@ -226,10 +184,19 @@ RSpec/MultipleDescribes:
|
|
|
226
184
|
RSpec/MultipleExpectations:
|
|
227
185
|
Max: 8
|
|
228
186
|
|
|
229
|
-
# Offense count:
|
|
187
|
+
# Offense count: 11
|
|
230
188
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
231
189
|
RSpec/Output:
|
|
232
|
-
|
|
190
|
+
Exclude:
|
|
191
|
+
- 'spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb'
|
|
192
|
+
- 'spec/svg_conform/remediations/color_remediation_spec.rb'
|
|
193
|
+
- 'spec/svg_conform/remediations/font_remediation_spec.rb'
|
|
194
|
+
- 'spec/svg_conform/remediations/invalid_id_references_remediation_spec.rb'
|
|
195
|
+
- 'spec/svg_conform/remediations/namespace_attribute_remediation_spec.rb'
|
|
196
|
+
- 'spec/svg_conform/remediations/namespace_remediation_spec.rb'
|
|
197
|
+
- 'spec/svg_conform/remediations/no_external_css_remediation_spec.rb'
|
|
198
|
+
- 'spec/svg_conform/remediations/style_promotion_remediation_spec.rb'
|
|
199
|
+
- 'spec/svg_conform/remediations/viewbox_remediation_spec.rb'
|
|
233
200
|
|
|
234
201
|
# Offense count: 1
|
|
235
202
|
Rake/MethodDefinitionInTask:
|
|
@@ -251,20 +218,13 @@ Style/EmptyElse:
|
|
|
251
218
|
- 'lib/svg_conform/remediations/namespace_remediation.rb'
|
|
252
219
|
- 'lib/svg_conform/requirements/style_requirement.rb'
|
|
253
220
|
|
|
254
|
-
# Offense count:
|
|
221
|
+
# Offense count: 13
|
|
255
222
|
# This cop supports safe autocorrection (--autocorrect).
|
|
256
223
|
# Configuration parameters: MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
|
|
257
224
|
# SupportedStyles: annotated, template, unannotated
|
|
258
225
|
Style/FormatStringToken:
|
|
259
226
|
EnforcedStyle: unannotated
|
|
260
227
|
|
|
261
|
-
# Offense count: 1
|
|
262
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
263
|
-
# Configuration parameters: AllowSplatArgument.
|
|
264
|
-
Style/HashConversion:
|
|
265
|
-
Exclude:
|
|
266
|
-
- 'lib/svg_conform/sax_validation_handler.rb'
|
|
267
|
-
|
|
268
228
|
# Offense count: 2
|
|
269
229
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
270
230
|
Style/HashSlice:
|
|
@@ -289,18 +249,6 @@ Style/OptionalBooleanParameter:
|
|
|
289
249
|
Exclude:
|
|
290
250
|
- 'lib/svg_conform/semantic_comparator.rb'
|
|
291
251
|
|
|
292
|
-
# Offense count: 1
|
|
293
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
294
|
-
Style/PartitionInsteadOfDoubleSelect:
|
|
295
|
-
Exclude:
|
|
296
|
-
- 'lib/svg_conform/requirements/style_requirement.rb'
|
|
297
|
-
|
|
298
|
-
# Offense count: 1
|
|
299
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
300
|
-
Style/ReduceToHash:
|
|
301
|
-
Exclude:
|
|
302
|
-
- 'lib/svg_conform/requirements/base_requirement.rb'
|
|
303
|
-
|
|
304
252
|
# Offense count: 1
|
|
305
253
|
# This cop supports safe autocorrection (--autocorrect).
|
|
306
254
|
# Configuration parameters: AllowedMethods.
|
|
@@ -308,27 +256,3 @@ Style/ReduceToHash:
|
|
|
308
256
|
Style/RedundantCondition:
|
|
309
257
|
Exclude:
|
|
310
258
|
- 'lib/svg_conform/external_checkers/svgcheck/parser.rb'
|
|
311
|
-
|
|
312
|
-
# Offense count: 2
|
|
313
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
314
|
-
Style/RedundantFormat:
|
|
315
|
-
Exclude:
|
|
316
|
-
- 'lib/svg_conform/compatibility/report_formatter.rb'
|
|
317
|
-
|
|
318
|
-
# Offense count: 2
|
|
319
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
320
|
-
Style/SelectByKind:
|
|
321
|
-
Exclude:
|
|
322
|
-
- 'lib/svg_conform/sax_validation_handler.rb'
|
|
323
|
-
|
|
324
|
-
# Offense count: 1
|
|
325
|
-
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
326
|
-
Style/SelectByRegexp:
|
|
327
|
-
Exclude:
|
|
328
|
-
- 'lib/svg_conform/remediations/color_remediation.rb'
|
|
329
|
-
|
|
330
|
-
# Offense count: 1
|
|
331
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
332
|
-
Style/SuperArguments:
|
|
333
|
-
Exclude:
|
|
334
|
-
- 'lib/svg_conform/requirements/invalid_id_references_requirement.rb'
|
data/Gemfile
CHANGED
data/README.adoc
CHANGED
|
@@ -33,6 +33,7 @@ SvgConform is distributed as a Ruby gem.
|
|
|
33
33
|
* **100% SVGCheck compatibility**: Perfect error report matching with Python svgcheck tool
|
|
34
34
|
* **Configurable RDF metadata support**: Choose strict or permissive RDF/Dublin Core handling
|
|
35
35
|
* **Generic namespace handling**: Configuration-driven foreign namespace validation
|
|
36
|
+
* **Text-as-path detection**: Warns when text is rendered as outlined path glyphs (quality check)
|
|
36
37
|
|
|
37
38
|
|
|
38
39
|
== Concepts
|
|
@@ -360,6 +361,168 @@ SvgConform provides compatibility with existing SVG validation tools:
|
|
|
360
361
|
See link:docs/compatibility.adoc[Compatibility Documentation] for details.
|
|
361
362
|
|
|
362
363
|
|
|
364
|
+
[[image_quality]]
|
|
365
|
+
== Image quality metric
|
|
366
|
+
|
|
367
|
+
SvgConform provides a quality metric system for analyzing and scoring SVG files
|
|
368
|
+
across multiple dimensions:
|
|
369
|
+
|
|
370
|
+
* **Quality Score (0-100)**: Composite score based on error density, severity, and remediability
|
|
371
|
+
* **Quality Level**: EXCELLENT, GOOD, FAIR, POOR, or CRITICAL
|
|
372
|
+
* **Error Breakdown**: Counts by severity (critical, high, medium, low) and remediability
|
|
373
|
+
* **Complexity Index**: 1-10 scale based on element count and advanced features
|
|
374
|
+
* **Feature Detection**: Base64 images, foreign namespaces, masks, clip paths, external refs
|
|
375
|
+
|
|
376
|
+
Reports are fully object-oriented: the same report object supports `to_yaml`, `to_json`,
|
|
377
|
+
and colorful terminal rendering.
|
|
378
|
+
|
|
379
|
+
[IMPORTANT]
|
|
380
|
+
.Quality depends on validation profile
|
|
381
|
+
====
|
|
382
|
+
The quality score is calculated based on validation errors, which depend on the
|
|
383
|
+
chosen profile. Different profiles have different rules, so the same SVG file
|
|
384
|
+
may receive different quality scores under different profiles.
|
|
385
|
+
|
|
386
|
+
Example: `colors.svg` scores 60 (FAIR) under `svg_1_2_rfc` but 100 (EXCELLENT)
|
|
387
|
+
under `metanorma` because the profiles have different color restrictions.
|
|
388
|
+
====
|
|
389
|
+
|
|
390
|
+
[source,bash]
|
|
391
|
+
----
|
|
392
|
+
# Integrated into main CLI (svg_conform quality analyze)
|
|
393
|
+
svg_conform quality analyze image.svg
|
|
394
|
+
|
|
395
|
+
# Output as YAML
|
|
396
|
+
svg_conform quality analyze image.svg -- --format yaml
|
|
397
|
+
|
|
398
|
+
# Batch analyze a directory
|
|
399
|
+
svg_conform quality batch ./svgs -- --output quality_report.csv
|
|
400
|
+
|
|
401
|
+
# With different profile (affects quality score!)
|
|
402
|
+
svg_conform quality analyze image.svg -- --profile metanorma
|
|
403
|
+
----
|
|
404
|
+
|
|
405
|
+
[source,ruby]
|
|
406
|
+
----
|
|
407
|
+
# Single file analysis - returns SvgQualityReport object
|
|
408
|
+
analyzer = SvgConform::ImageQualityAnalyzer.new
|
|
409
|
+
report = analyzer.analyze('image.svg')
|
|
410
|
+
|
|
411
|
+
# Three output formats from the same object
|
|
412
|
+
puts report.render # Colorful terminal output
|
|
413
|
+
puts report.to_yaml # YAML serialization
|
|
414
|
+
puts report.to_json # JSON serialization
|
|
415
|
+
|
|
416
|
+
# Access attributes directly
|
|
417
|
+
puts "Quality: #{report.quality_score} (#{report.quality_level})"
|
|
418
|
+
puts "Errors: #{report.error_count} (#{report.remediable_errors} remediable)"
|
|
419
|
+
puts "Complexity: #{report.complexity_index}/10"
|
|
420
|
+
|
|
421
|
+
# Batch analysis - returns SvgQualityBatchReport object
|
|
422
|
+
batch = analyzer.analyze_batch('./svgs')
|
|
423
|
+
puts batch.render # Summary with distribution chart
|
|
424
|
+
puts batch.to_yaml # Full YAML with all reports
|
|
425
|
+
|
|
426
|
+
# Filter and process reports
|
|
427
|
+
poor_files = batch.reports.select { |r| r.quality_level == :poor }
|
|
428
|
+
----
|
|
429
|
+
|
|
430
|
+
For detailed documentation including custom configuration and CLI options, see
|
|
431
|
+
link:docs/image_quality.adoc[Image Quality Metric Documentation].
|
|
432
|
+
|
|
433
|
+
=== CLI output examples
|
|
434
|
+
|
|
435
|
+
.Single file analysis with default profile (svg_1_2_rfc)
|
|
436
|
+
[source,text]
|
|
437
|
+
----
|
|
438
|
+
$ svg_conform quality analyze spec/fixtures/svgcheck/inputs/colors.svg
|
|
439
|
+
|
|
440
|
+
📊 SVG Quality Report: colors.svg
|
|
441
|
+
|
|
442
|
+
⚠️ Quality: 60 (FAIR)
|
|
443
|
+
🔶 Content Health: moderate_issues
|
|
444
|
+
|
|
445
|
+
📁 File: 1.41 KB (small)
|
|
446
|
+
📐 Elements: 17
|
|
447
|
+
🔢 Complexity: 1.0/10
|
|
448
|
+
|
|
449
|
+
Errors: 12
|
|
450
|
+
🔧 Remediable: 12
|
|
451
|
+
⚠️ Non-remediable: 0
|
|
452
|
+
|
|
453
|
+
Breakdown:
|
|
454
|
+
● Medium: 12
|
|
455
|
+
----
|
|
456
|
+
|
|
457
|
+
.Same file with metanorma profile (no color restrictions)
|
|
458
|
+
[source,text]
|
|
459
|
+
----
|
|
460
|
+
$ svg_conform quality analyze spec/fixtures/svgcheck/inputs/colors.svg -- --profile metanorma
|
|
461
|
+
|
|
462
|
+
📊 SVG Quality Report: colors.svg
|
|
463
|
+
|
|
464
|
+
✨ Quality: 100 (EXCELLENT)
|
|
465
|
+
✅ Content Health: good
|
|
466
|
+
|
|
467
|
+
📁 File: 1.41 KB (small)
|
|
468
|
+
📐 Elements: 17
|
|
469
|
+
🔢 Complexity: 1.0/10
|
|
470
|
+
|
|
471
|
+
Errors: 0
|
|
472
|
+
🔧 Remediable: 0
|
|
473
|
+
⚠️ Non-remediable: 0
|
|
474
|
+
----
|
|
475
|
+
|
|
476
|
+
.Single file analysis (YAML output)
|
|
477
|
+
[source,yaml]
|
|
478
|
+
----
|
|
479
|
+
$ svg_conform quality analyze spec/fixtures/svgcheck/inputs/colors.svg -- --format yaml
|
|
480
|
+
|
|
481
|
+
---
|
|
482
|
+
file_path: spec/fixtures/svgcheck/inputs/colors.svg
|
|
483
|
+
quality_score: 60
|
|
484
|
+
quality_level: :fair
|
|
485
|
+
error_count: 12
|
|
486
|
+
remediable_errors: 12
|
|
487
|
+
...
|
|
488
|
+
----
|
|
489
|
+
|
|
490
|
+
.Single file analysis (JSON output)
|
|
491
|
+
[source,json]
|
|
492
|
+
----
|
|
493
|
+
$ svg_conform quality analyze spec/fixtures/svgcheck/inputs/colors.svg -- --format json
|
|
494
|
+
|
|
495
|
+
{"file_path":"spec/fixtures/svgcheck/inputs/colors.svg","quality_score":60,...}
|
|
496
|
+
----
|
|
497
|
+
|
|
498
|
+
.Batch summary (terminal output with distribution chart)
|
|
499
|
+
[source,text]
|
|
500
|
+
----
|
|
501
|
+
$ svg_conform quality batch spec/fixtures/svgcheck/inputs -- --summary-only
|
|
502
|
+
|
|
503
|
+
📊 SVG Quality Batch Report
|
|
504
|
+
|
|
505
|
+
📁 Total Files: 19
|
|
506
|
+
✅ Successful: 19
|
|
507
|
+
|
|
508
|
+
Quality Distribution
|
|
509
|
+
|
|
510
|
+
✨ EXCELLENT ██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 2 (10.5%)
|
|
511
|
+
👍 GOOD ██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 2 (10.5%)
|
|
512
|
+
⚠️ FAIR ████████████████████████████████████████ 13 (68.4%)
|
|
513
|
+
😟 POOR ██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 2 (10.5%)
|
|
514
|
+
💥 CRITICAL ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0 (0.0%)
|
|
515
|
+
|
|
516
|
+
Summary
|
|
517
|
+
|
|
518
|
+
📈 Average Quality Score: 61.6/100
|
|
519
|
+
📊 Average Errors/File: 204.3
|
|
520
|
+
|
|
521
|
+
🔧 Total Remediable: 3872
|
|
522
|
+
⚠️ Total Non-remediable: 10
|
|
523
|
+
----
|
|
524
|
+
|
|
525
|
+
|
|
363
526
|
== Documentation
|
|
364
527
|
|
|
365
528
|
=== User documentation
|
|
@@ -371,6 +534,7 @@ See link:docs/compatibility.adoc[Compatibility Documentation] for details.
|
|
|
371
534
|
* link:docs/remediation.adoc[Remediation Reference] - All automatic remediations
|
|
372
535
|
* link:docs/reference_manifest.adoc[Reference Manifest] - ID and reference tracking
|
|
373
536
|
* link:docs/rdf_metadata_support.adoc[RDF Metadata Support] - RDF/Dublin Core configuration
|
|
537
|
+
* link:docs/image_quality.adoc[Image Quality Metric] - Quality scoring and analysis
|
|
374
538
|
|
|
375
539
|
=== Developer documentation
|
|
376
540
|
|
|
@@ -21,7 +21,7 @@ requirements:
|
|
|
21
21
|
element_configs:
|
|
22
22
|
# Direct encoding from svgcheck word_properties.py elements dictionary
|
|
23
23
|
- tag: "svg"
|
|
24
|
-
attributes: ["version", "baseProfile", "width", "viewBox", "preserveAspectRatio", "snapshotTime", "height", "id", "role", "break", "color-rendering", "fill-rule", "overflow", "data-name"]
|
|
24
|
+
attributes: ["version", "baseProfile", "width", "viewBox", "preserveAspectRatio", "snapshotTime", "height", "id", "role", "break", "color-rendering", "fill-rule", "overflow", "data-name", "clip-path", "mask"]
|
|
25
25
|
required_attributes: ["version", "baseProfile"]
|
|
26
26
|
attribute_values:
|
|
27
27
|
version: ["1.2"]
|
|
@@ -34,37 +34,37 @@ requirements:
|
|
|
34
34
|
attributes: ["id", "role", "shape-rendering", "text-rendering", "buffered-rendering", "visibility", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "fill-rule"]
|
|
35
35
|
allowed_children: ["text"]
|
|
36
36
|
- tag: "path"
|
|
37
|
-
attributes: ["d", "pathLength", "stroke-miterlimit", "id", "role", "fill", "style", "transform", "font-size", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
37
|
+
attributes: ["d", "pathLength", "stroke-miterlimit", "id", "role", "fill", "style", "transform", "font-size", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
|
|
38
38
|
allowed_children: ["title", "desc"]
|
|
39
39
|
- tag: "rect"
|
|
40
|
-
attributes: ["x", "y", "width", "height", "rx", "ry", "stroke-miterlimit", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
40
|
+
attributes: ["x", "y", "width", "height", "rx", "ry", "stroke-miterlimit", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
|
|
41
41
|
allowed_children: ["title", "desc"]
|
|
42
42
|
- tag: "circle"
|
|
43
|
-
attributes: ["cx", "cy", "r", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
43
|
+
attributes: ["cx", "cy", "r", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
|
|
44
44
|
allowed_children: ["title", "desc"]
|
|
45
45
|
- tag: "line"
|
|
46
|
-
attributes: ["x1", "y1", "x2", "y2", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
46
|
+
attributes: ["x1", "y1", "x2", "y2", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
|
|
47
47
|
allowed_children: ["title", "desc"]
|
|
48
48
|
- tag: "ellipse"
|
|
49
|
-
attributes: ["cx", "cy", "rx", "ry", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
49
|
+
attributes: ["cx", "cy", "rx", "ry", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
|
|
50
50
|
allowed_children: ["title", "desc"]
|
|
51
51
|
- tag: "polyline"
|
|
52
|
-
attributes: ["points", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
52
|
+
attributes: ["points", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
|
|
53
53
|
allowed_children: ["title", "desc"]
|
|
54
54
|
- tag: "polygon"
|
|
55
|
-
attributes: ["points", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
55
|
+
attributes: ["points", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
|
|
56
56
|
allowed_children: ["title", "desc"]
|
|
57
57
|
- tag: "solidColor"
|
|
58
|
-
attributes: ["id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
58
|
+
attributes: ["id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
|
|
59
59
|
allowed_children: ["title", "desc"]
|
|
60
60
|
- tag: "textArea"
|
|
61
|
-
attributes: ["x", "y", "width", "height", "auto", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
61
|
+
attributes: ["x", "y", "width", "height", "auto", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
|
|
62
62
|
allowed_children: ["desc", "title", "tspan", "text", "a"]
|
|
63
63
|
- tag: "text"
|
|
64
|
-
attributes: ["x", "y", "rotate", "id", "role", "fill", "style", "transform", "font-size", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "font-stretch", "writing-mode", "text-decoration"]
|
|
64
|
+
attributes: ["x", "y", "rotate", "id", "role", "fill", "style", "transform", "font-size", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "font-stretch", "writing-mode", "text-decoration", "clip-path", "mask"]
|
|
65
65
|
allowed_children: ["desc", "title", "tspan", "text", "a"]
|
|
66
66
|
- tag: "g"
|
|
67
|
-
attributes: ["label", "class", "id", "role", "fill", "style", "transform", "fill-rule", "visibility", "base", "lang", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "data-name"]
|
|
67
|
+
attributes: ["label", "class", "id", "role", "fill", "style", "transform", "fill-rule", "visibility", "base", "lang", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "data-name", "clip-path", "mask"]
|
|
68
68
|
allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc", "image"]
|
|
69
69
|
- tag: "defs"
|
|
70
70
|
attributes: ["id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
@@ -97,7 +97,7 @@ requirements:
|
|
|
97
97
|
attributes: ["type", "media", "title", "id", "class"]
|
|
98
98
|
allowed_children: []
|
|
99
99
|
- tag: "use"
|
|
100
|
-
attributes: ["x", "y", "href", "xlink:href", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
100
|
+
attributes: ["x", "y", "href", "xlink:href", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
|
|
101
101
|
allowed_children: ["title", "desc"]
|
|
102
102
|
- tag: "a"
|
|
103
103
|
attributes: ["id", "role", "fill", "transform", "fill-rule", "target", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
@@ -108,7 +108,7 @@ requirements:
|
|
|
108
108
|
- tag: "tbreak"
|
|
109
109
|
attributes: ["id", "role", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
|
|
110
110
|
- tag: "image"
|
|
111
|
-
attributes: ["x", "y", "width", "height", "href", "xlink:href", "preserveAspectRatio", "id", "class", "style", "transform"]
|
|
111
|
+
attributes: ["x", "y", "width", "height", "href", "xlink:href", "preserveAspectRatio", "id", "class", "style", "transform", "clip-path", "mask"]
|
|
112
112
|
allowed_children: ["title", "desc"]
|
|
113
113
|
check_attributes: true
|
|
114
114
|
check_invalid_attributes: true
|
|
@@ -187,6 +187,13 @@ requirements:
|
|
|
187
187
|
check_image_elements: true
|
|
188
188
|
check_style_images: true
|
|
189
189
|
|
|
190
|
+
# Text-as-path detection - warns when text is rendered as outlined paths
|
|
191
|
+
- id: "text_as_path"
|
|
192
|
+
type: "TextAsPathRequirement"
|
|
193
|
+
description: "Detects text rendered as outlined paths instead of native <text> elements"
|
|
194
|
+
min_d_length: 500
|
|
195
|
+
min_bezier: 5
|
|
196
|
+
|
|
190
197
|
remediations:
|
|
191
198
|
# ViewBox auto-generation
|
|
192
199
|
- id: "viewbox_generation"
|