svg_conform 0.1.8 → 0.1.9
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 +9 -71
- data/config/profiles/metanorma.yml +3 -0
- data/docs/profiles.adoc +14 -0
- data/docs/requirements.adoc +56 -0
- data/lib/svg_conform/requirements/allowed_elements_requirement.rb +71 -9
- data/lib/svg_conform/version.rb +1 -1
- data/spec/svg_conform/requirements/allowed_elements_requirement_spec.rb +63 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e4879f5648a06585ca68ae1430f928c327b267c3de96e92ae54333a002127243
|
|
4
|
+
data.tar.gz: 7fb876639e3d0d935020089981803d43e2648131bf7a074b0b127605c99009ff
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ca32f36fb1bcb98fc25be20fc237291f5fa0efedd55c71cb62b8862e60c3628f05673a0d16def9deda237e4a3b53312c78e39d3daf2bb42700e58f388a2d38c8
|
|
7
|
+
data.tar.gz: '0086cffd30f8c81aba4e157caf6a0bfe197f4ce597971941e4ddcc136f0ac7cf11460eb8e4103094a6636aa546c5d687c0f724697e441c509a94e1697bc41857'
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,80 +1,26 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-01-
|
|
3
|
+
# on 2026-01-22 08:33:31 UTC using RuboCop version 1.82.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
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/validation_context.rb'
|
|
16
|
-
|
|
17
|
-
# Offense count: 2
|
|
9
|
+
# Offense count: 1
|
|
18
10
|
# This cop supports safe autocorrection (--autocorrect).
|
|
19
11
|
# Configuration parameters: EnforcedStyleAlignWith.
|
|
20
12
|
# SupportedStylesAlignWith: either, start_of_block, start_of_line
|
|
21
13
|
Layout/BlockAlignment:
|
|
22
14
|
Exclude:
|
|
23
|
-
- 'lib/svg_conform/sax_validation_handler.rb'
|
|
24
15
|
- 'spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb'
|
|
25
16
|
|
|
26
|
-
# Offense count:
|
|
27
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
28
|
-
Layout/BlockEndNewline:
|
|
29
|
-
Exclude:
|
|
30
|
-
- 'lib/svg_conform/sax_validation_handler.rb'
|
|
31
|
-
|
|
32
|
-
# Offense count: 1
|
|
33
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
34
|
-
Layout/ElseAlignment:
|
|
35
|
-
Exclude:
|
|
36
|
-
- 'lib/svg_conform/requirements/no_external_css_requirement.rb'
|
|
37
|
-
|
|
38
|
-
# Offense count: 1
|
|
39
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
40
|
-
# Configuration parameters: EnforcedStyleAlignWith.
|
|
41
|
-
# SupportedStylesAlignWith: keyword, variable, start_of_line
|
|
42
|
-
Layout/EndAlignment:
|
|
43
|
-
Exclude:
|
|
44
|
-
- 'lib/svg_conform/requirements/no_external_css_requirement.rb'
|
|
45
|
-
|
|
46
|
-
# Offense count: 4
|
|
47
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
48
|
-
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
|
49
|
-
# SupportedHashRocketStyles: key, separator, table
|
|
50
|
-
# SupportedColonStyles: key, separator, table
|
|
51
|
-
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
|
52
|
-
Layout/HashAlignment:
|
|
53
|
-
Exclude:
|
|
54
|
-
- 'lib/svg_conform/validation_context.rb'
|
|
55
|
-
|
|
56
|
-
# Offense count: 4
|
|
57
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
58
|
-
# Configuration parameters: Width, AllowedPatterns.
|
|
59
|
-
Layout/IndentationWidth:
|
|
60
|
-
Exclude:
|
|
61
|
-
- 'lib/svg_conform/requirements/no_external_css_requirement.rb'
|
|
62
|
-
- 'lib/svg_conform/sax_validation_handler.rb'
|
|
63
|
-
|
|
64
|
-
# Offense count: 643
|
|
17
|
+
# Offense count: 647
|
|
65
18
|
# This cop supports safe autocorrection (--autocorrect).
|
|
66
19
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
67
20
|
# URISchemes: http, https
|
|
68
21
|
Layout/LineLength:
|
|
69
22
|
Enabled: false
|
|
70
23
|
|
|
71
|
-
# Offense count: 2
|
|
72
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
73
|
-
# Configuration parameters: AllowInHeredoc.
|
|
74
|
-
Layout/TrailingWhitespace:
|
|
75
|
-
Exclude:
|
|
76
|
-
- 'lib/svg_conform/validation_context.rb'
|
|
77
|
-
|
|
78
24
|
# Offense count: 2
|
|
79
25
|
# Configuration parameters: AllowedMethods.
|
|
80
26
|
# AllowedMethods: enums
|
|
@@ -124,12 +70,12 @@ Lint/UnreachableCode:
|
|
|
124
70
|
Exclude:
|
|
125
71
|
- 'lib/svg_conform/commands/check.rb'
|
|
126
72
|
|
|
127
|
-
# Offense count:
|
|
73
|
+
# Offense count: 151
|
|
128
74
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
129
75
|
Metrics/AbcSize:
|
|
130
76
|
Enabled: false
|
|
131
77
|
|
|
132
|
-
# Offense count:
|
|
78
|
+
# Offense count: 24
|
|
133
79
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
|
|
134
80
|
# AllowedMethods: refine
|
|
135
81
|
Metrics/BlockLength:
|
|
@@ -140,12 +86,12 @@ Metrics/BlockLength:
|
|
|
140
86
|
Metrics/BlockNesting:
|
|
141
87
|
Max: 4
|
|
142
88
|
|
|
143
|
-
# Offense count:
|
|
89
|
+
# Offense count: 127
|
|
144
90
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
145
91
|
Metrics/CyclomaticComplexity:
|
|
146
92
|
Enabled: false
|
|
147
93
|
|
|
148
|
-
# Offense count:
|
|
94
|
+
# Offense count: 263
|
|
149
95
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
150
96
|
Metrics/MethodLength:
|
|
151
97
|
Max: 154
|
|
@@ -155,7 +101,7 @@ Metrics/MethodLength:
|
|
|
155
101
|
Metrics/ParameterLists:
|
|
156
102
|
Max: 9
|
|
157
103
|
|
|
158
|
-
# Offense count:
|
|
104
|
+
# Offense count: 101
|
|
159
105
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
160
106
|
Metrics/PerceivedComplexity:
|
|
161
107
|
Enabled: false
|
|
@@ -193,7 +139,7 @@ RSpec/DescribeClass:
|
|
|
193
139
|
- 'spec/svg_conform/references/integration_spec.rb'
|
|
194
140
|
- 'spec/svgcheck_compatibility_spec.rb'
|
|
195
141
|
|
|
196
|
-
# Offense count:
|
|
142
|
+
# Offense count: 139
|
|
197
143
|
# Configuration parameters: CountAsOne.
|
|
198
144
|
RSpec/ExampleLength:
|
|
199
145
|
Max: 53
|
|
@@ -258,11 +204,3 @@ Style/OptionalBooleanParameter:
|
|
|
258
204
|
Style/RedundantCondition:
|
|
259
205
|
Exclude:
|
|
260
206
|
- 'lib/svg_conform/external_checkers/svgcheck/parser.rb'
|
|
261
|
-
|
|
262
|
-
# Offense count: 1
|
|
263
|
-
# This cop supports safe autocorrection (--autocorrect).
|
|
264
|
-
# Configuration parameters: EnforcedStyleForMultiline.
|
|
265
|
-
# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
|
|
266
|
-
Style/TrailingCommaInArguments:
|
|
267
|
-
Exclude:
|
|
268
|
-
- 'lib/svg_conform/sax_validation_handler.rb'
|
|
@@ -16,6 +16,8 @@ requirements:
|
|
|
16
16
|
allowed_namespaces:
|
|
17
17
|
- "http://www.w3.org/2000/svg"
|
|
18
18
|
- "" # Default namespace (no prefix)
|
|
19
|
+
allowed_attribute_patterns:
|
|
20
|
+
- "on*" # Allow event handler attributes (onmouseover, onmouseout, etc.) per issue #57
|
|
19
21
|
element_configs:
|
|
20
22
|
# Direct encoding from svgcheck word_properties.py elements dictionary
|
|
21
23
|
- tag: "svg"
|
|
@@ -156,6 +158,7 @@ requirements:
|
|
|
156
158
|
description: "Validates ID references point to existing elements"
|
|
157
159
|
|
|
158
160
|
# Forbidden content - no multimedia, scripting, etc.
|
|
161
|
+
# Note: onmouseover, onmouseout, onfocus, onblur are intentionally allowed per issue #57
|
|
159
162
|
- id: "forbidden_content"
|
|
160
163
|
type: "ForbiddenContentRequirement"
|
|
161
164
|
description: "Prohibits multimedia, scripting content"
|
data/docs/profiles.adoc
CHANGED
|
@@ -268,10 +268,24 @@ See link:remediation.adoc#namespace-attribute-remediation[NamespaceAttributeReme
|
|
|
268
268
|
* **Flexible colors**: Any colors allowed (unlike RFC 7996 black/white restriction)
|
|
269
269
|
* **Flexible fonts**: Any font families allowed (unlike RFC 7996 generic-only restriction)
|
|
270
270
|
* **Flexible styles**: Any CSS styles allowed
|
|
271
|
+
* **Event handlers allowed**: Supports event attributes (`on*`) for interactivity
|
|
271
272
|
* **Self-contained resources**: All CSS and fonts must be embedded
|
|
272
273
|
* **Structural compliance**: Proper namespaces and viewBox required
|
|
273
274
|
* **No external dependencies**: External CSS and fonts strictly prohibited
|
|
274
275
|
|
|
276
|
+
**Event Handler Support**:
|
|
277
|
+
|
|
278
|
+
The metanorma profile allows SVG event handler attributes (e.g., `onmouseover`, `onmouseout`, `onfocus`, `onblur`) for interactive elements. This is configured using wildcard attribute patterns:
|
|
279
|
+
|
|
280
|
+
[source,yaml]
|
|
281
|
+
----
|
|
282
|
+
requirements:
|
|
283
|
+
- type: "AllowedElementsRequirement"
|
|
284
|
+
id: "allowed_elements"
|
|
285
|
+
allowed_attribute_patterns:
|
|
286
|
+
- "on*" # Allow all event handler attributes
|
|
287
|
+
----
|
|
288
|
+
|
|
275
289
|
**Requirements**:
|
|
276
290
|
[source,yaml]
|
|
277
291
|
----
|
data/docs/requirements.adoc
CHANGED
|
@@ -174,6 +174,62 @@ foreign). Used with `skip_foreign_namespaces`. Default: `[]`.
|
|
|
174
174
|
namespaces. When `true`, RDF namespace elements are considered valid and
|
|
175
175
|
skipped. Default: `false`.
|
|
176
176
|
|
|
177
|
+
`allowed_attribute_patterns`:: List of wildcard attribute patterns to exempt from
|
|
178
|
+
validation. Attributes matching any pattern will be allowed regardless of whether
|
|
179
|
+
they appear in element `attributes` lists. Patterns support suffix wildcards (`*`).
|
|
180
|
+
Default: `[]`.
|
|
181
|
+
|
|
182
|
+
* **Common patterns**:
|
|
183
|
+
+
|
|
184
|
+
**`"on*"`**:: Allows all event handler attributes (`onclick`, `onmouseover`, `onmouseout`, etc.)
|
|
185
|
+
**`"data-*"`**:: Allows all `data-` custom attributes
|
|
186
|
+
|
|
187
|
+
* **Precedence**: When an attribute matches both an allowed pattern and an
|
|
188
|
+
element-specific disallowed attribute (prefixed with `!`), the allowed pattern
|
|
189
|
+
takes precedence and a warning is emitted during validation.
|
|
190
|
+
|
|
191
|
+
==== Wildcard attribute patterns
|
|
192
|
+
|
|
193
|
+
.Using allowed_attribute_patterns to exempt event handler attributes
|
|
194
|
+
[example]
|
|
195
|
+
====
|
|
196
|
+
[source,yaml]
|
|
197
|
+
----
|
|
198
|
+
- id: "svg_elements_with_events"
|
|
199
|
+
type: "AllowedElementsRequirement"
|
|
200
|
+
description: "Restrict to allowed SVG elements but allow event handlers"
|
|
201
|
+
allowed_attribute_patterns:
|
|
202
|
+
- "on*" # Allow all event handler attributes
|
|
203
|
+
- "data-*" # Allow all data-* custom attributes
|
|
204
|
+
check_attributes: true
|
|
205
|
+
element_configs:
|
|
206
|
+
- tag: "polygon"
|
|
207
|
+
attributes: ["points", "id", "fill"]
|
|
208
|
+
# !onclick is disallowed, but on* pattern takes precedence with warning
|
|
209
|
+
- tag: "rect"
|
|
210
|
+
attributes: ["x", "y", "width", "height"]
|
|
211
|
+
----
|
|
212
|
+
====
|
|
213
|
+
|
|
214
|
+
With this configuration:
|
|
215
|
+
* Event attributes (`onclick`, `onmouseover`, etc.) are allowed on all elements
|
|
216
|
+
* `data-*` custom attributes are allowed on all elements
|
|
217
|
+
* Other attributes not in element `attributes` lists are still rejected
|
|
218
|
+
|
|
219
|
+
.Conflict detection warning
|
|
220
|
+
[example]
|
|
221
|
+
====
|
|
222
|
+
When an allowed pattern conflicts with an element-specific disallowed attribute
|
|
223
|
+
(prefixed with `!`), a warning is emitted:
|
|
224
|
+
|
|
225
|
+
[source,text]
|
|
226
|
+
----
|
|
227
|
+
Configuration warning in svg_elements_with_events: Element 'polygon' has
|
|
228
|
+
disallowed attributes [onclick] that match allowed_attribute_patterns [on*].
|
|
229
|
+
Allowed patterns take precedence over element-specific disallowed attributes.
|
|
230
|
+
----
|
|
231
|
+
====
|
|
232
|
+
|
|
177
233
|
==== Configuration
|
|
178
234
|
|
|
179
235
|
.Example configuration of AllowedElementsRequirement
|
|
@@ -8,20 +8,19 @@ module SvgConform
|
|
|
8
8
|
# Validates that only allowed SVG elements and their attributes are used
|
|
9
9
|
class AllowedElementsRequirement < BaseRequirement
|
|
10
10
|
attribute :type, :string, default: -> { "AllowedElementsRequirement" }
|
|
11
|
-
attribute :element_configs, ElementRequirementConfig, collection: true,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
[]
|
|
16
|
-
}
|
|
11
|
+
attribute :element_configs, ElementRequirementConfig, collection: true,
|
|
12
|
+
initialize_empty: true
|
|
13
|
+
attribute :disallowed_elements, :string, collection: true,
|
|
14
|
+
initialize_empty: true
|
|
17
15
|
attribute :check_attributes, :boolean, default: false
|
|
18
16
|
attribute :check_invalid_attributes, :boolean, default: false
|
|
17
|
+
attribute :allowed_attribute_patterns, :string, collection: true,
|
|
18
|
+
initialize_empty: true
|
|
19
19
|
attribute :check_parent_child, :boolean, default: false
|
|
20
20
|
attribute :parent_child_rules, :string, default: -> { {} }
|
|
21
21
|
attribute :skip_foreign_namespaces, :boolean, default: false
|
|
22
|
-
attribute :allowed_namespaces, :string, collection: true,
|
|
23
|
-
|
|
24
|
-
}
|
|
22
|
+
attribute :allowed_namespaces, :string, collection: true,
|
|
23
|
+
initialize_empty: true
|
|
25
24
|
attribute :allow_rdf_metadata, :boolean, default: false
|
|
26
25
|
|
|
27
26
|
# RDF-related namespaces (same as in NamespaceRequirement for consistency)
|
|
@@ -41,13 +40,51 @@ module SvgConform
|
|
|
41
40
|
map "disallowed_elements", to: :disallowed_elements
|
|
42
41
|
map "check_attributes", to: :check_attributes
|
|
43
42
|
map "check_invalid_attributes", to: :check_invalid_attributes
|
|
43
|
+
map "allowed_attribute_patterns", to: :allowed_attribute_patterns
|
|
44
44
|
map "check_parent_child", to: :check_parent_child
|
|
45
45
|
map "skip_foreign_namespaces", to: :skip_foreign_namespaces
|
|
46
46
|
map "allowed_namespaces", to: :allowed_namespaces
|
|
47
47
|
map "allow_rdf_metadata", to: :allow_rdf_metadata
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
# Check for configuration conflicts and emit warnings
|
|
51
|
+
def validate_configuration
|
|
52
|
+
return if allowed_attribute_patterns.empty? || !element_configs&.any?
|
|
53
|
+
|
|
54
|
+
element_configs.each do |element_config|
|
|
55
|
+
next unless element_config&.attr
|
|
56
|
+
|
|
57
|
+
disallowed_attrs = []
|
|
58
|
+
element_config.attr.each do |attribute|
|
|
59
|
+
if attribute.start_with?("!")
|
|
60
|
+
disallowed_attrs << attribute[1..].downcase
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
next if disallowed_attrs.empty?
|
|
65
|
+
|
|
66
|
+
# Check if any disallowed attribute matches an allowed pattern
|
|
67
|
+
conflicts = disallowed_attrs.select do |disallowed|
|
|
68
|
+
matches_allowed_pattern?(disallowed)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
if conflicts.any?
|
|
72
|
+
warn "Configuration warning in #{id}: " \
|
|
73
|
+
"Element '#{element_config.tag}' has disallowed attributes [#{conflicts.join(', ')}] " \
|
|
74
|
+
"that match allowed_attribute_patterns [#{allowed_attribute_patterns.join(', ')}]. " \
|
|
75
|
+
"Allowed patterns take precedence over element-specific disallowed attributes."
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
50
80
|
def check(node, context)
|
|
81
|
+
# Validate configuration once on first use
|
|
82
|
+
@_config_validated ||= false
|
|
83
|
+
unless @_config_validated
|
|
84
|
+
validate_configuration
|
|
85
|
+
@_config_validated = true
|
|
86
|
+
end
|
|
87
|
+
|
|
51
88
|
return unless element?(node)
|
|
52
89
|
|
|
53
90
|
# Skip foreign namespace elements if configured (let NamespaceRequirement handle them)
|
|
@@ -121,6 +158,13 @@ module SvgConform
|
|
|
121
158
|
end
|
|
122
159
|
|
|
123
160
|
def validate_sax_element(element, context)
|
|
161
|
+
# Validate configuration once on first use
|
|
162
|
+
@_config_validated ||= false
|
|
163
|
+
unless @_config_validated
|
|
164
|
+
validate_configuration
|
|
165
|
+
@_config_validated = true
|
|
166
|
+
end
|
|
167
|
+
|
|
124
168
|
# Skip if parent is structurally invalid (matches DOM behavior)
|
|
125
169
|
if element.parent && context.node_structurally_invalid?(element.parent)
|
|
126
170
|
# Mark this element as invalid too since it won't be in final document
|
|
@@ -202,6 +246,18 @@ module SvgConform
|
|
|
202
246
|
disallowed_elements&.include?(element_name) || false
|
|
203
247
|
end
|
|
204
248
|
|
|
249
|
+
# Check if an attribute name matches any of the allowed_attribute_patterns
|
|
250
|
+
def matches_allowed_pattern?(attr_name)
|
|
251
|
+
allowed_attribute_patterns.any? do |pattern|
|
|
252
|
+
if pattern.end_with?("*")
|
|
253
|
+
prefix = pattern[0..-2] # Remove trailing *
|
|
254
|
+
attr_name.downcase.start_with?(prefix)
|
|
255
|
+
else
|
|
256
|
+
attr_name.downcase == pattern
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
205
261
|
def invalid_parent_child?(parent_name, child_name)
|
|
206
262
|
return false unless element_configs&.any?
|
|
207
263
|
|
|
@@ -290,6 +346,9 @@ module SvgConform
|
|
|
290
346
|
# Check if matches data-* pattern (wildcard pattern)
|
|
291
347
|
next if attr_name.start_with?("data-")
|
|
292
348
|
|
|
349
|
+
# Check if matches allowed attribute patterns (wildcard patterns)
|
|
350
|
+
next if matches_allowed_pattern?(attr_name)
|
|
351
|
+
|
|
293
352
|
# Check if explicitly disallowed
|
|
294
353
|
if disallowed_attrs.include?(attr_name)
|
|
295
354
|
errors << {
|
|
@@ -437,6 +496,9 @@ module SvgConform
|
|
|
437
496
|
next if attr.namespace
|
|
438
497
|
next if attr_name.start_with?("data-")
|
|
439
498
|
|
|
499
|
+
# Check if matches allowed attribute patterns (wildcard patterns)
|
|
500
|
+
next if matches_allowed_pattern?(attr_name)
|
|
501
|
+
|
|
440
502
|
# Check if explicitly disallowed
|
|
441
503
|
if disallowed_attrs.include?(attr_name)
|
|
442
504
|
errors << {
|
data/lib/svg_conform/version.rb
CHANGED
|
@@ -114,5 +114,68 @@ RSpec.describe SvgConform::Requirements::AllowedElementsRequirement do
|
|
|
114
114
|
|
|
115
115
|
expect(requirement).to be_a(described_class)
|
|
116
116
|
end
|
|
117
|
+
|
|
118
|
+
it "accepts allowed_attribute_patterns for wildcard attribute exemption" do
|
|
119
|
+
requirement = described_class.new(
|
|
120
|
+
id: "test_patterns",
|
|
121
|
+
description: "Test with allowed patterns",
|
|
122
|
+
allowed_attribute_patterns: ["on*", "data-*"],
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
expect(requirement.allowed_attribute_patterns).to eq(["on*", "data-*"])
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "allows attributes matching allowed_attribute_patterns" do
|
|
129
|
+
svg_with_event_handlers = <<~SVG
|
|
130
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
131
|
+
<polygon points="10,10 90,10 50,90"
|
|
132
|
+
onmouseout="handleOut()"
|
|
133
|
+
onmouseover="handleOver()"
|
|
134
|
+
data-custom="value"/>
|
|
135
|
+
<rect x="10" y="10" width="20" height="20" onclick="forbidden()"/>
|
|
136
|
+
</svg>
|
|
137
|
+
SVG
|
|
138
|
+
|
|
139
|
+
document = SvgConform::Document.from_content(svg_with_event_handlers)
|
|
140
|
+
requirement = described_class.new(
|
|
141
|
+
id: "test_patterns",
|
|
142
|
+
description: "Test with allowed patterns",
|
|
143
|
+
allowed_attribute_patterns: ["on*"], # Allow all event attributes
|
|
144
|
+
check_attributes: true,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
148
|
+
requirement.validate_document(document, context)
|
|
149
|
+
|
|
150
|
+
# onmouseout and onmouseover should be allowed (match "on*" pattern)
|
|
151
|
+
# onclick should also be allowed (matches "on*" pattern)
|
|
152
|
+
# data-custom should NOT be allowed (not in allowed attributes, not in pattern)
|
|
153
|
+
expect(context.errors).to be_empty
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it "warns when allowed_attribute_patterns conflicts with element-specific disallowed attributes" do
|
|
157
|
+
# Create a requirement with conflicting configuration
|
|
158
|
+
requirement = described_class.new(
|
|
159
|
+
id: "test_conflict",
|
|
160
|
+
description: "Test with conflicting patterns",
|
|
161
|
+
allowed_attribute_patterns: ["on*"], # Allows all event attributes
|
|
162
|
+
element_configs: [
|
|
163
|
+
SvgConform::Requirements::ElementRequirementConfig.new(
|
|
164
|
+
tag: "polygon",
|
|
165
|
+
attr: ["points", "!onclick"], # onclick is disallowed on polygon
|
|
166
|
+
),
|
|
167
|
+
],
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# Trigger validation by calling check and capture stderr
|
|
171
|
+
document = SvgConform::Document.from_content(
|
|
172
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><polygon points="10,10 90,10 50,90"/></svg>',
|
|
173
|
+
)
|
|
174
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
175
|
+
|
|
176
|
+
expect { requirement.check(document.root, context) }
|
|
177
|
+
.to output(/Configuration warning.*onclick.*allowed_attribute_patterns.*Allowed patterns take precedence/m)
|
|
178
|
+
.to_stderr
|
|
179
|
+
end
|
|
117
180
|
end
|
|
118
181
|
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.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|