svg_conform 0.1.11 → 0.2.0
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/.github/workflows/release.yml +1 -0
- data/.rubocop_todo.yml +74 -41
- data/CLAUDE.md +115 -0
- data/Gemfile +2 -0
- data/README.adoc +164 -0
- data/config/profiles/metanorma.yml +7 -0
- data/config/quality_metrics.yml +212 -0
- data/docs/image_quality.adoc +526 -0
- data/docs/performance.adoc +31 -0
- data/docs/profiles.adoc +3 -1
- data/docs/requirements.adoc +123 -0
- data/lib/svg_conform/cli.rb +19 -7
- data/lib/svg_conform/commands/check.rb +41 -45
- data/lib/svg_conform/commands/profiles.rb +3 -3
- data/lib/svg_conform/commands/quality.rb +249 -0
- data/lib/svg_conform/commands/svgcheck_compare.rb +29 -37
- data/lib/svg_conform/commands/svgcheck_compatibility.rb +11 -6
- 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/base_requirement.rb +3 -3
- 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/commands/check_command_spec.rb +2 -2
- 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 +0 -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 +38 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2dd3f8b58d869e1375f4ec0e5c0c212d36dc5ae64ab91873ccc896acb9bd42b7
|
|
4
|
+
data.tar.gz: 184b07a501eb1bae6fc1691849df9f2fbb0693c340149822b35a0129b47ae2c0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9db79546df082674dbfbe29bd010e7a676765bd08366e26af6da279d9b56d01a907e259178ef1b3009340aa22eb785098790b49aa1cb81525831d9b60ac8e962
|
|
7
|
+
data.tar.gz: '091d729bffcc2716bcce077e5509afbce8971329c1479e86bc8c2968ac540742c161f3a3f369c78fa0f76bdf6f5de84439b6c773349656f1466da4d3175e5ca5'
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-
|
|
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
|
-
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
12
|
-
# SupportedStyles: with_first_argument, with_fixed_indentation
|
|
13
|
-
Layout/ArgumentAlignment:
|
|
14
|
-
Exclude:
|
|
15
|
-
- 'lib/svg_conform/requirements/invalid_id_references_requirement.rb'
|
|
16
|
-
|
|
17
9
|
# Offense count: 1
|
|
18
10
|
# This cop supports safe autocorrection (--autocorrect).
|
|
19
11
|
# Configuration parameters: EnforcedStyleAlignWith.
|
|
@@ -22,30 +14,19 @@ Layout/BlockAlignment:
|
|
|
22
14
|
Exclude:
|
|
23
15
|
- 'spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb'
|
|
24
16
|
|
|
25
|
-
# Offense count:
|
|
26
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
27
|
-
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
|
28
|
-
# SupportedHashRocketStyles: key, separator, table
|
|
29
|
-
# SupportedColonStyles: key, separator, table
|
|
30
|
-
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
|
31
|
-
Layout/HashAlignment:
|
|
32
|
-
Exclude:
|
|
33
|
-
- 'spec/svg_conform/validation_context_spec.rb'
|
|
34
|
-
|
|
35
|
-
# Offense count: 662
|
|
17
|
+
# Offense count: 667
|
|
36
18
|
# This cop supports safe autocorrection (--autocorrect).
|
|
37
19
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
38
20
|
# URISchemes: http, https
|
|
39
21
|
Layout/LineLength:
|
|
40
22
|
Enabled: false
|
|
41
23
|
|
|
42
|
-
# Offense count:
|
|
24
|
+
# Offense count: 9
|
|
43
25
|
# This cop supports safe autocorrection (--autocorrect).
|
|
44
26
|
# Configuration parameters: AllowInHeredoc.
|
|
45
27
|
Layout/TrailingWhitespace:
|
|
46
28
|
Exclude:
|
|
47
|
-
- '
|
|
48
|
-
- 'spec/svg_conform/validation_context_spec.rb'
|
|
29
|
+
- 'spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb'
|
|
49
30
|
|
|
50
31
|
# Offense count: 3
|
|
51
32
|
# Configuration parameters: AllowedMethods.
|
|
@@ -73,12 +54,20 @@ Lint/DuplicateCaseCondition:
|
|
|
73
54
|
Exclude:
|
|
74
55
|
- 'lib/svg_conform/semantic_comparator.rb'
|
|
75
56
|
|
|
76
|
-
# Offense count:
|
|
57
|
+
# Offense count: 2
|
|
77
58
|
Lint/DuplicateMethods:
|
|
78
59
|
Exclude:
|
|
79
60
|
- 'lib/svg_conform/sax_validation_handler.rb'
|
|
61
|
+
- 'spec/svg_conform/validation_context_spec.rb'
|
|
80
62
|
|
|
81
|
-
# 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
|
|
82
71
|
Lint/HashCompareByIdentity:
|
|
83
72
|
Exclude:
|
|
84
73
|
- 'lib/svg_conform/document_analyzer.rb'
|
|
@@ -91,17 +80,12 @@ Lint/MissingSuper:
|
|
|
91
80
|
- 'lib/svg_conform/compatibility/validity_analysis.rb'
|
|
92
81
|
- 'lib/svg_conform/sax_validation_handler.rb'
|
|
93
82
|
|
|
94
|
-
# Offense count:
|
|
95
|
-
Lint/UnreachableCode:
|
|
96
|
-
Exclude:
|
|
97
|
-
- 'lib/svg_conform/commands/check.rb'
|
|
98
|
-
|
|
99
|
-
# Offense count: 146
|
|
83
|
+
# Offense count: 160
|
|
100
84
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
101
85
|
Metrics/AbcSize:
|
|
102
86
|
Enabled: false
|
|
103
87
|
|
|
104
|
-
# Offense count:
|
|
88
|
+
# Offense count: 25
|
|
105
89
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
|
106
90
|
# AllowedMethods: refine
|
|
107
91
|
Metrics/BlockLength:
|
|
@@ -112,26 +96,38 @@ Metrics/BlockLength:
|
|
|
112
96
|
Metrics/BlockNesting:
|
|
113
97
|
Max: 4
|
|
114
98
|
|
|
115
|
-
# Offense count:
|
|
99
|
+
# Offense count: 138
|
|
116
100
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
117
101
|
Metrics/CyclomaticComplexity:
|
|
118
102
|
Enabled: false
|
|
119
103
|
|
|
120
|
-
# Offense count:
|
|
104
|
+
# Offense count: 276
|
|
121
105
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
122
106
|
Metrics/MethodLength:
|
|
123
107
|
Max: 154
|
|
124
108
|
|
|
125
|
-
# Offense count:
|
|
109
|
+
# Offense count: 8
|
|
126
110
|
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
|
127
111
|
Metrics/ParameterLists:
|
|
128
112
|
Max: 9
|
|
129
113
|
|
|
130
|
-
# Offense count:
|
|
114
|
+
# Offense count: 112
|
|
131
115
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
132
116
|
Metrics/PerceivedComplexity:
|
|
133
117
|
Enabled: false
|
|
134
118
|
|
|
119
|
+
# Offense count: 9
|
|
120
|
+
# Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
|
|
121
|
+
# AllowedMethods: call
|
|
122
|
+
# WaywardPredicates: infinite?, nonzero?
|
|
123
|
+
Naming/PredicateMethod:
|
|
124
|
+
Exclude:
|
|
125
|
+
- 'lib/svg_conform/compatibility/file_processor.rb'
|
|
126
|
+
- 'lib/svg_conform/node_helpers.rb'
|
|
127
|
+
- 'lib/svg_conform/remediations/base_remediation.rb'
|
|
128
|
+
- 'lib/svg_conform/requirements/style_requirement.rb'
|
|
129
|
+
- 'lib/svg_conform/semantic_comparator.rb'
|
|
130
|
+
|
|
135
131
|
# Offense count: 2
|
|
136
132
|
# Configuration parameters: MinSize.
|
|
137
133
|
Performance/CollectionLiteralInLoop:
|
|
@@ -161,13 +157,18 @@ RSpec/DescribeClass:
|
|
|
161
157
|
# Offense count: 157
|
|
162
158
|
# Configuration parameters: CountAsOne.
|
|
163
159
|
RSpec/ExampleLength:
|
|
164
|
-
Max:
|
|
160
|
+
Max: 43
|
|
165
161
|
|
|
166
162
|
# Offense count: 3
|
|
167
163
|
RSpec/LeakyConstantDeclaration:
|
|
168
164
|
Exclude:
|
|
169
165
|
- 'spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb'
|
|
170
166
|
|
|
167
|
+
# Offense count: 1
|
|
168
|
+
RSpec/LeakyLocalVariable:
|
|
169
|
+
Exclude:
|
|
170
|
+
- 'spec/svgcheck_compatibility_spec.rb'
|
|
171
|
+
|
|
171
172
|
# Offense count: 2
|
|
172
173
|
# Configuration parameters: .
|
|
173
174
|
# SupportedStyles: have_received, receive
|
|
@@ -183,11 +184,31 @@ RSpec/MultipleDescribes:
|
|
|
183
184
|
RSpec/MultipleExpectations:
|
|
184
185
|
Max: 8
|
|
185
186
|
|
|
187
|
+
# Offense count: 11
|
|
188
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
189
|
+
RSpec/Output:
|
|
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'
|
|
200
|
+
|
|
186
201
|
# Offense count: 1
|
|
187
202
|
Rake/MethodDefinitionInTask:
|
|
188
203
|
Exclude:
|
|
189
204
|
- 'lib/tasks/svgcheck.rake'
|
|
190
205
|
|
|
206
|
+
# Offense count: 3
|
|
207
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
208
|
+
Style/ComparableClamp:
|
|
209
|
+
Exclude:
|
|
210
|
+
- 'lib/svg_conform/css_color.rb'
|
|
211
|
+
|
|
191
212
|
# Offense count: 2
|
|
192
213
|
# This cop supports safe autocorrection (--autocorrect).
|
|
193
214
|
# Configuration parameters: EnforcedStyle, AllowComments.
|
|
@@ -197,17 +218,29 @@ Style/EmptyElse:
|
|
|
197
218
|
- 'lib/svg_conform/remediations/namespace_remediation.rb'
|
|
198
219
|
- 'lib/svg_conform/requirements/style_requirement.rb'
|
|
199
220
|
|
|
200
|
-
# Offense count:
|
|
221
|
+
# Offense count: 13
|
|
201
222
|
# This cop supports safe autocorrection (--autocorrect).
|
|
202
223
|
# Configuration parameters: MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
|
|
203
224
|
# SupportedStyles: annotated, template, unannotated
|
|
204
225
|
Style/FormatStringToken:
|
|
205
226
|
EnforcedStyle: unannotated
|
|
206
227
|
|
|
228
|
+
# Offense count: 2
|
|
229
|
+
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
230
|
+
Style/HashSlice:
|
|
231
|
+
Exclude:
|
|
232
|
+
- 'spec/svg_conform_spec.rb'
|
|
233
|
+
|
|
234
|
+
# Offense count: 1
|
|
235
|
+
# Configuration parameters: AllowedClasses.
|
|
236
|
+
Style/OneClassPerFile:
|
|
237
|
+
Exclude:
|
|
238
|
+
- 'lib/svg_conform/compatibility/report_formatter.rb'
|
|
239
|
+
|
|
207
240
|
# Offense count: 1
|
|
208
|
-
Style/
|
|
241
|
+
Style/OpenStructUse:
|
|
209
242
|
Exclude:
|
|
210
|
-
- 'lib/svg_conform/
|
|
243
|
+
- 'lib/svg_conform/validator.rb'
|
|
211
244
|
|
|
212
245
|
# Offense count: 4
|
|
213
246
|
# Configuration parameters: AllowedMethods.
|
|
@@ -219,7 +252,7 @@ Style/OptionalBooleanParameter:
|
|
|
219
252
|
# Offense count: 1
|
|
220
253
|
# This cop supports safe autocorrection (--autocorrect).
|
|
221
254
|
# Configuration parameters: AllowedMethods.
|
|
222
|
-
# AllowedMethods: nonzero?
|
|
255
|
+
# AllowedMethods: infinite?, nonzero?
|
|
223
256
|
Style/RedundantCondition:
|
|
224
257
|
Exclude:
|
|
225
258
|
- 'lib/svg_conform/external_checkers/svgcheck/parser.rb'
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Build/Test Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install dependencies
|
|
9
|
+
bin/setup
|
|
10
|
+
|
|
11
|
+
# Run tests
|
|
12
|
+
rake spec
|
|
13
|
+
|
|
14
|
+
# Run a single spec file
|
|
15
|
+
bundle exec rspec spec/svg_conform/validator_spec.rb
|
|
16
|
+
|
|
17
|
+
# Run tests with detailed output
|
|
18
|
+
bundle exec rspec --format documentation
|
|
19
|
+
|
|
20
|
+
# Run linting
|
|
21
|
+
rake rubocop
|
|
22
|
+
|
|
23
|
+
# Run both tests and linting
|
|
24
|
+
rake
|
|
25
|
+
|
|
26
|
+
# Run a specific test by line number
|
|
27
|
+
bundle exec rspec spec/svg_conform/validator_spec.rb:42
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Architecture
|
|
31
|
+
|
|
32
|
+
### Two-Mode Validation System
|
|
33
|
+
|
|
34
|
+
SvgConform uses two distinct operating modes:
|
|
35
|
+
|
|
36
|
+
1. **SAX Validation Mode** (always used for validation):
|
|
37
|
+
- Memory-safe streaming XML parser
|
|
38
|
+
- Constant memory regardless of file size
|
|
39
|
+
- Handles files of any size (tested with 100MB+)
|
|
40
|
+
- Read-only, cannot modify documents
|
|
41
|
+
- Implemented via `SaxDocument` and `SaxValidationHandler`
|
|
42
|
+
|
|
43
|
+
2. **DOM Remediation Mode** (only when applying fixes):
|
|
44
|
+
- Full document tree loaded in memory
|
|
45
|
+
- XPath queries and tree modification
|
|
46
|
+
- Memory scales with file size
|
|
47
|
+
- Only activated when `fix: true` is specified
|
|
48
|
+
|
|
49
|
+
### Core Classes
|
|
50
|
+
|
|
51
|
+
- `Validator` - Main entry point; normalizes all inputs to SAX validation
|
|
52
|
+
- `SaxDocument` - SAX-based document wrapper for memory-safe validation
|
|
53
|
+
- `Document` - DOM-based document wrapper for modifications
|
|
54
|
+
- `Profile` - Collection of requirements and remediations; loaded from YAML
|
|
55
|
+
- `Profiles` - Factory for loading/retrieving profile instances
|
|
56
|
+
- `ValidationContext` - Carries state during validation (errors, data collected)
|
|
57
|
+
- `ValidationResult` - Holds validation outcomes after checking
|
|
58
|
+
- `ConformanceReport` - Formats validation results for output
|
|
59
|
+
|
|
60
|
+
### Requirements System
|
|
61
|
+
|
|
62
|
+
Requirements validate SVG documents. All requirements must support SAX validation:
|
|
63
|
+
|
|
64
|
+
- Requirements inherit from `BaseRequirement` in `lib/svg_conform/requirements/`
|
|
65
|
+
- Must implement `validate_sax_element(element, context)` for immediate checks
|
|
66
|
+
- Can optionally implement `collect_sax_data()` + `validate_sax_complete()` for deferred validation (e.g., cross-reference checks)
|
|
67
|
+
- Use `context.data` hash for per-document state (not instance variables - they leak across validations)
|
|
68
|
+
- Never attempt DOM operations in SAX callbacks
|
|
69
|
+
|
|
70
|
+
Key requirement classes: `NamespaceRequirement`, `ViewboxRequiredRequirement`, `IdReferenceRequirement`, `ForbiddenContentRequirement`, `ColorRestrictionsRequirement`, etc.
|
|
71
|
+
|
|
72
|
+
### Remediations System
|
|
73
|
+
|
|
74
|
+
Remediations fix validation failures. They run in DOM mode:
|
|
75
|
+
|
|
76
|
+
- Inherit from `BaseRemediation` in `lib/svg_conform/remediations/`
|
|
77
|
+
- Linked to requirements via `targets` array in profile YAML
|
|
78
|
+
- Only execute when `should_execute?(failed_requirements)` returns true
|
|
79
|
+
|
|
80
|
+
### Profile Configuration
|
|
81
|
+
|
|
82
|
+
Profiles are defined in YAML under `config/profiles/`:
|
|
83
|
+
- `base.yml` - Common requirements shared by other profiles
|
|
84
|
+
- `metanorma.yml`, `svg_1_2_rfc.yml`, etc. - Specific profile definitions
|
|
85
|
+
- Profile class map is built dynamically from filesystem in `Profile.build_class_map`
|
|
86
|
+
|
|
87
|
+
Profiles support `import` to inherit from other profiles (e.g., `metanorma` imports `base`).
|
|
88
|
+
|
|
89
|
+
### CLI Structure
|
|
90
|
+
|
|
91
|
+
- `lib/svg_conform/cli.rb` - Thor-based CLI entry point
|
|
92
|
+
- `lib/svg_conform/commands/check.rb` - Main validation command
|
|
93
|
+
- `lib/svg_conform/commands/profiles.rb` - Profile listing command
|
|
94
|
+
- `lib/svg_conform/commands/svgcheck.rb` - SVGCheck compatibility subcommands
|
|
95
|
+
|
|
96
|
+
### Input Handling
|
|
97
|
+
|
|
98
|
+
The `Validator` accepts multiple input types and always uses SAX:
|
|
99
|
+
- String (XML content) → parsed directly with SAX
|
|
100
|
+
- Moxml/Nokogiri documents → serialized once, then SAX validated
|
|
101
|
+
- Document/Element objects → same serialization approach
|
|
102
|
+
|
|
103
|
+
This ensures memory safety for large files regardless of input type.
|
|
104
|
+
|
|
105
|
+
### Key Files
|
|
106
|
+
|
|
107
|
+
- `lib/svg_conform.rb` - Main require file with autoloads
|
|
108
|
+
- `lib/svg_conform/element_proxy.rb` - Lightweight SAX element representation
|
|
109
|
+
- `lib/svg_conform/validation_context.rb` - Validation state container
|
|
110
|
+
- `lib/svg_conform/sax_document.rb` - SAX document wrapper
|
|
111
|
+
- `lib/svg_conform/sax_validation_handler.rb` - SAX callback handler
|
|
112
|
+
|
|
113
|
+
### Error Handling Pattern
|
|
114
|
+
|
|
115
|
+
The CLI uses `exit 1` for error exits. When improving error handling, prefer raising proper Ruby exceptions (`ValidationError`, `ProfileError`, `ArgumentError`) rather than using `exit`/`abort` directly, as Thor provides mechanisms for displaying errors gracefully to users.
|
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
|
|
|
@@ -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"
|