svg_conform 0.2.4 → 0.2.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.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/rake.yml +4 -1
  4. data/Gemfile +6 -3
  5. data/Gemfile.lock +211 -0
  6. data/TODO.issue-100/00-overview.md +135 -0
  7. data/TODO.issue-100/01-build-lens-core-v1.md +92 -0
  8. data/TODO.issue-100/02-adopt-lens-core-in-svg.md +123 -0
  9. data/TODO.issue-100/03-ship-svg-1-1-full-static.md +138 -0
  10. data/TODO.issue-100/04-ship-svg-2-secure-static.md +131 -0
  11. data/TODO.issue-100/05-freeze-candidate-and-handoff.md +108 -0
  12. data/TODO.issue-100/90-progress.md +65 -0
  13. data/config/profiles/metanorma.yml +4 -4
  14. data/config/profiles/svg_1_1_full_static.yml +69 -0
  15. data/config/profiles/svg_2_secure_static.yml +55 -0
  16. data/config/requirements/processing_features_static.yml +29 -0
  17. data/data/svg_1_1/manifest.yml +7 -0
  18. data/data/svg_1_1/svg11-flat-20110816.dtd +5664 -0
  19. data/docs/api_reference.adoc +19 -1
  20. data/docs/cli_guide.adoc +35 -45
  21. data/docs/diagnostics.adoc +73 -0
  22. data/docs/lens_core_handoff.adoc +84 -0
  23. data/docs/profiles.adoc +94 -1
  24. data/lib/svg_conform/cli.rb +3 -4
  25. data/lib/svg_conform/commands/check.rb +11 -60
  26. data/lib/svg_conform/conformance_report.rb +79 -1
  27. data/lib/svg_conform/diagnostics/lens_core_adapter.rb +200 -0
  28. data/lib/svg_conform/document.rb +12 -1
  29. data/lib/svg_conform/external_checkers/svgcheck/parser.rb +1 -3
  30. data/lib/svg_conform/node_helpers.rb +1 -1
  31. data/lib/svg_conform/profile.rb +11 -2
  32. data/lib/svg_conform/quality_metrics/complexity_calculator.rb +3 -3
  33. data/lib/svg_conform/quality_metrics/configuration.rb +4 -2
  34. data/lib/svg_conform/references/base_reference.rb +153 -0
  35. data/lib/svg_conform/references/reference_manifest.rb +1 -2
  36. data/lib/svg_conform/report_comparator.rb +4 -4
  37. data/lib/svg_conform/requirements/base_requirement.rb +6 -0
  38. data/lib/svg_conform/requirements/external_references_requirement.rb +234 -0
  39. data/lib/svg_conform/requirements/link_validation_requirement.rb +2 -0
  40. data/lib/svg_conform/requirements/processing_features_requirement.rb +175 -0
  41. data/lib/svg_conform/requirements/svg_1_1_document_requirement.rb +213 -0
  42. data/lib/svg_conform/requirements.rb +6 -0
  43. data/lib/svg_conform/sax_document.rb +8 -4
  44. data/lib/svg_conform/sax_validation_handler.rb +22 -1
  45. data/lib/svg_conform/validation/css2_core_grammar.rb +359 -0
  46. data/lib/svg_conform/validation/css_references.rb +122 -0
  47. data/lib/svg_conform/validation/error_tracker.rb +40 -9
  48. data/lib/svg_conform/validation/svg_1_1_document_conformance.rb +154 -0
  49. data/lib/svg_conform/validation_context.rb +25 -5
  50. data/lib/svg_conform/validation_result.rb +91 -16
  51. data/lib/svg_conform/version.rb +1 -1
  52. data/lib/svg_conform/yaml_io.rb +20 -0
  53. data/lib/svg_conform.rb +25 -0
  54. data/spec/fixtures/diagnostics/external-reference-info.svg +6 -0
  55. data/spec/fixtures/plantuml/README.adoc +11 -0
  56. data/spec/fixtures/plantuml/unit-type.svg +1 -0
  57. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/animation.svg +4 -0
  58. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/css-grammar.svg +4 -0
  59. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/dtd-attribute.svg +4 -0
  60. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/dtd-content-model.svg +4 -0
  61. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/interaction.svg +4 -0
  62. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/malformed-xml.svg +4 -0
  63. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/script.svg +5 -0
  64. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/wrong-namespace.svg +4 -0
  65. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/wrong-version.svg +4 -0
  66. data/spec/fixtures/profiles/svg_1_1_full_static/invalid/xml-stylesheet.svg +5 -0
  67. data/spec/fixtures/profiles/svg_1_1_full_static/valid/css.svg +5 -0
  68. data/spec/fixtures/profiles/svg_1_1_full_static/valid/foreign-metadata.svg +6 -0
  69. data/spec/fixtures/profiles/svg_1_1_full_static/valid/minimal-full.svg +5 -0
  70. data/spec/fixtures/profiles/svg_1_1_full_static/valid/xml-stylesheet.svg +5 -0
  71. data/spec/fixtures/profiles/svg_2_secure_static/invalid/animation.svg +4 -0
  72. data/spec/fixtures/profiles/svg_2_secure_static/invalid/css-import.svg +4 -0
  73. data/spec/fixtures/profiles/svg_2_secure_static/invalid/css-url.svg +4 -0
  74. data/spec/fixtures/profiles/svg_2_secure_static/invalid/data-bad-png.svg +4 -0
  75. data/spec/fixtures/profiles/svg_2_secure_static/invalid/data-empty-png.svg +4 -0
  76. data/spec/fixtures/profiles/svg_2_secure_static/invalid/data-malformed-base64.svg +4 -0
  77. data/spec/fixtures/profiles/svg_2_secure_static/invalid/data-malformed-percent.svg +4 -0
  78. data/spec/fixtures/profiles/svg_2_secure_static/invalid/data-unsupported-type.svg +4 -0
  79. data/spec/fixtures/profiles/svg_2_secure_static/invalid/file-like-fragment.svg +4 -0
  80. data/spec/fixtures/profiles/svg_2_secure_static/invalid/http.svg +4 -0
  81. data/spec/fixtures/profiles/svg_2_secure_static/invalid/https.svg +4 -0
  82. data/spec/fixtures/profiles/svg_2_secure_static/invalid/interaction.svg +4 -0
  83. data/spec/fixtures/profiles/svg_2_secure_static/invalid/protocol-relative.svg +4 -0
  84. data/spec/fixtures/profiles/svg_2_secure_static/invalid/relative-file-fragment.svg +4 -0
  85. data/spec/fixtures/profiles/svg_2_secure_static/invalid/relative-file.svg +4 -0
  86. data/spec/fixtures/profiles/svg_2_secure_static/invalid/script.svg +4 -0
  87. data/spec/fixtures/profiles/svg_2_secure_static/invalid/svg-data-excessive-nesting.svg +4 -0
  88. data/spec/fixtures/profiles/svg_2_secure_static/invalid/svg-data-malformed-xml.svg +4 -0
  89. data/spec/fixtures/profiles/svg_2_secure_static/invalid/svg-data-nested-external.svg +4 -0
  90. data/spec/fixtures/profiles/svg_2_secure_static/invalid/urn.svg +4 -0
  91. data/spec/fixtures/profiles/svg_2_secure_static/invalid/xml-stylesheet.svg +5 -0
  92. data/spec/fixtures/profiles/svg_2_secure_static/valid/jpeg-base64.svg +4 -0
  93. data/spec/fixtures/profiles/svg_2_secure_static/valid/jpeg-percent.svg +4 -0
  94. data/spec/fixtures/profiles/svg_2_secure_static/valid/png-base64.svg +4 -0
  95. data/spec/fixtures/profiles/svg_2_secure_static/valid/png-percent.svg +4 -0
  96. data/spec/fixtures/profiles/svg_2_secure_static/valid/same-document-fragment.svg +4 -0
  97. data/spec/fixtures/profiles/svg_2_secure_static/valid/svg-base64.svg +4 -0
  98. data/spec/fixtures/profiles/svg_2_secure_static/valid/svg-percent.svg +4 -0
  99. data/spec/fixtures/quality_metrics/aliases.yml +7 -0
  100. data/spec/svg_conform/commands/check_command_spec.rb +22 -2
  101. data/spec/svg_conform/commands/profiles_command_spec.rb +18 -0
  102. data/spec/svg_conform/conformance_report_spec.rb +90 -0
  103. data/spec/svg_conform/diagnostics/lens_core_adapter_spec.rb +136 -0
  104. data/spec/svg_conform/gemspec_spec.rb +34 -0
  105. data/spec/svg_conform/profiles/metanorma_profile_spec.rb +48 -0
  106. data/spec/svg_conform/profiles/svg_1_1_full_static_profile_spec.rb +146 -0
  107. data/spec/svg_conform/profiles/svg_2_secure_static_profile_spec.rb +150 -0
  108. data/spec/svg_conform/profiles_plantuml_spec.rb +81 -0
  109. data/spec/svg_conform/quality_metrics/configuration_spec.rb +82 -0
  110. data/spec/svg_conform/references/data_uri_reference_spec.rb +97 -0
  111. data/spec/svg_conform/references/integration_spec.rb +30 -0
  112. data/spec/svg_conform/references/reference_classifier_spec.rb +17 -0
  113. data/spec/svg_conform/requirements/external_references_requirement_spec.rb +109 -0
  114. data/spec/svg_conform/requirements/link_validation_requirement_spec.rb +16 -0
  115. data/spec/svg_conform/requirements/processing_features_requirement_spec.rb +75 -0
  116. data/spec/svg_conform/requirements/svg_1_1_document_requirement_spec.rb +141 -0
  117. data/spec/svg_conform/requirements/text_as_path_requirement_spec.rb +9 -5
  118. data/spec/svg_conform/validation/css2_core_grammar_spec.rb +116 -0
  119. data/spec/svg_conform/validation/svg_1_1_document_conformance_spec.rb +144 -0
  120. data/spec/svg_conform/validation_context_source_plumbing_spec.rb +122 -0
  121. data/spec/svg_conform/validation_context_spec.rb +39 -0
  122. data/spec/svg_conform/validation_result_spec.rb +123 -0
  123. data/spec/svg_conform/yaml_io_spec.rb +41 -0
  124. data/svg_conform.gemspec +4 -2
  125. metadata +120 -6
@@ -0,0 +1,138 @@
1
+ # 03 — Ship SVG 1.1 Full/static
2
+
3
+ Effort: **8–12 person-days**
4
+
5
+ Repository: `claricle/svg_conform`
6
+
7
+ Depends on: Card 02
8
+
9
+ ## Purpose
10
+
11
+ Add an opt-in profile for SVG 1.1 Full documents under static processing. The
12
+ profile validates the Recommendation's document grammar instead of treating an
13
+ element allow-list as standards conformance, and it behaves the same through
14
+ the repository's DOM and SAX entry points.
15
+
16
+ ## Requirement matrix
17
+
18
+ Add `config/profiles/svg_1_1_full_static.yml` with this stable matrix. Every
19
+ entry carries its listed normative URI and emits an error with its own ID.
20
+
21
+ | Requirement ID | Rule | Normative citation |
22
+ | --- | --- | --- |
23
+ | `svg11.document.xml` | The source is well-formed XML and exposes its original declaration, doctype, and processing instructions to document-level validation. | `https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGDocuments` |
24
+ | `svg11.document.root` | The document element is `svg` in `http://www.w3.org/2000/svg`. | `https://www.w3.org/TR/2011/REC-SVG11-20110816/struct.html#SVGElement` |
25
+ | `svg11.document.version` | The root declares SVG version `1.1`. | `https://www.w3.org/TR/2011/REC-SVG11-20110816/struct.html#SVGElementVersionAttribute` |
26
+ | `svg11.document.grammar` | After the Appendix G.2 foreign-namespace transform, elements, attributes, content models, and required values validate against the pinned SVG 1.1 Full flat DTD. | `https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGDocuments` |
27
+ | `svg11.document.css2` | Style attributes and style sheets accepted by the document conform to the CSS 2 core grammar required by SVG 1.1; this checks syntax, not browser rendering or every CSS property semantic. | `https://www.w3.org/TR/2008/REC-CSS2-20080411/grammar.html` |
28
+ | `svg11.document.xml_stylesheet` | `xml-stylesheet` processing instructions obey their Recommendation's pseudo-attribute syntax and SVG applicability rules. | `https://www.w3.org/TR/1999/REC-xml-stylesheet-19990629/` |
29
+ | `svg11.processing.script` | Static mode rejects script elements and event-handler attributes. | `https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGViewers` |
30
+ | `svg11.processing.animation` | Static mode rejects SVG animation elements and animation-timing attributes. | `https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGViewers` |
31
+ | `svg11.processing.interaction` | Static mode rejects interaction-only event attributes and cursor behavior. | `https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGViewers` |
32
+
33
+ The profile's `specification_uri` is the dated SVG 1.1 Second Edition
34
+ Recommendation. Profile and requirement citations flow into LensCore reports.
35
+
36
+ ## Source-level validation plumbing
37
+
38
+ Document conformance needs bytes that parsed DOMs can discard. Add an optional
39
+ `source` and `source_path` to `ValidationContext`, retain the original content
40
+ in `Document`, and pass `SaxDocument#content` into `SaxValidationHandler`.
41
+ Extend `BaseRequirement` with a no-op
42
+ `validate_source(source, context)` hook. Invoke it exactly once before DOM
43
+ traversal or SAX element dispatch; source diagnostics then share the normal
44
+ tracker and LensCore adapter.
45
+
46
+ For `Document.from_node`, serialize the node and mark the source as serialized
47
+ so a source-sensitive requirement can report that a declaration/doctype/PI
48
+ claim cannot be proved instead of silently accepting it. File and string entry
49
+ points retain exact input bytes. Add focused parity specs for file and string
50
+ entry points in both modes.
51
+
52
+ ## Validators and shared processing requirement
53
+
54
+ - Vendor the dated flat DTD at
55
+ `data/svg_1_1/svg11-flat-20110816.dtd`. Add
56
+ `data/svg_1_1/manifest.yml` with its W3C source URL, retrieval date, and
57
+ computed SHA-256. Resolution is local-only: external entity or network access
58
+ during validation is an error.
59
+ - Add `SvgConform::Validation::Svg11DocumentConformance` in
60
+ `lib/svg_conform/validation/svg_1_1_document_conformance.rb` and expose it
61
+ through `Svg11DocumentRequirement`. Implement the Appendix G.2 transform in
62
+ an isolated helper and validate the transformed copy; never rewrite the
63
+ caller's document.
64
+ - Add a focused CSS 2 core tokenizer/parser at
65
+ `lib/svg_conform/validation/css2_core_grammar.rb` and reuse it for style
66
+ attributes, style elements, and applicable stylesheet content. Keep property
67
+ support and rendering semantics outside this syntax check.
68
+ - Add `ProcessingFeaturesRequirement` in
69
+ `lib/svg_conform/requirements/processing_features_requirement.rb`. Its YAML
70
+ configuration names `script`, `animation`, and `interaction` categories and
71
+ their separate IDs/citations. Implement DOM and SAX paths once here. Card 04
72
+ consumes the same serialized requirement unchanged.
73
+ - Require both new requirement files from `lib/svg_conform/requirements.rb` and
74
+ include them in `SvgConform::Requirements.all`. The existing
75
+ `Profile::REQUIREMENTS_CLASS_MAP` discovers their files, and
76
+ `ProfileCompiler` loads and precomputes them; cover those existing mechanisms
77
+ in the profile spec rather than adding a competing registry.
78
+
79
+ ### Open implementation question resolved by this card
80
+
81
+ Before building the grammar validator, run four tiny probes (valid document,
82
+ invalid content model, external-entity attempt, and Appendix G.2 foreign
83
+ content) against the currently bundled Moxml/Leptris stack. Record the result in
84
+ the validator spec. If that stack cannot perform offline validating-DTD checks,
85
+ select the smallest maintained Ruby-compatible validating XML library, add it
86
+ to `svg_conform.gemspec` and `Gemfile`, and lock it. Selection criteria are the
87
+ four probes, supported Ruby versions, no network/entity resolution, and no
88
+ shelling out. Do not substitute a hand-maintained element list for DTD
89
+ validation.
90
+
91
+ ## Corpus, tests, and documentation
92
+
93
+ Create `spec/fixtures/profiles/svg_1_1_full_static/` with small fixtures that
94
+ isolate each matrix row:
95
+
96
+ - valid minimal Full, CSS, XML-stylesheet, and foreign-metadata documents;
97
+ - invalid malformed-XML source (for `svg11.document.xml`), root/namespace,
98
+ version, DTD content-model, attribute, CSS grammar, and XML-stylesheet cases;
99
+ - one invalid script, animation, and interaction case.
100
+
101
+ Add `spec/svg_conform/validation/svg_1_1_document_conformance_spec.rb`,
102
+ `spec/svg_conform/validation/css2_core_grammar_spec.rb`,
103
+ `spec/svg_conform/requirements/svg_1_1_document_requirement_spec.rb`,
104
+ `spec/svg_conform/requirements/processing_features_requirement_spec.rb`, and
105
+ `spec/svg_conform/profiles/svg_1_1_full_static_profile_spec.rb`. The profile spec
106
+ runs every fixture through DOM and SAX, compares validity and stable requirement
107
+ IDs, and asserts that all errors have the normative citation. Update
108
+ the existing `docs/profiles.adoc`, `docs/cli_guide.adoc`, and the profile-list
109
+ command coverage with
110
+ the profile ID, scope, citations, non-goals, and example command.
111
+
112
+ ## Done when
113
+
114
+ - `svg_1_1_full_static` is discoverable and opt-in; no existing profile or
115
+ default selection changes.
116
+ - All nine matrix rows have a stable ID, normative citation, isolated invalid
117
+ fixture, and matching DOM/SAX result.
118
+ - Valid SVG 1.1 Full fixtures pass local DTD, CSS, and stylesheet checks without
119
+ network access; invalid grammar is rejected by the appropriate requirement.
120
+ - Appendix G.2 foreign content is handled on a validation copy, and an external
121
+ entity attempt cannot read a file or make a network request.
122
+ - Script, animation, and interaction categories are enforced by the serialized
123
+ shared `ProcessingFeaturesRequirement` in both validation modes.
124
+ - Profile documentation states exactly what Full/static covers and does not
125
+ claim Tiny, Basic, rendering, or remediation support.
126
+ - All changed Ruby passes the repository linter and the gem builds.
127
+
128
+ ```sh
129
+ bundle exec rspec spec/svg_conform/validation/svg_1_1_document_conformance_spec.rb spec/svg_conform/validation/css2_core_grammar_spec.rb spec/svg_conform/requirements/svg_1_1_document_requirement_spec.rb spec/svg_conform/requirements/processing_features_requirement_spec.rb spec/svg_conform/profiles/svg_1_1_full_static_profile_spec.rb spec/svg_conform/commands/profiles_command_spec.rb
130
+ bundle exec svg_conform check spec/fixtures/profiles/svg_1_1_full_static/valid/minimal-full.svg --profile svg_1_1_full_static --format json
131
+ bundle exec rubocop
132
+ bundle exec rake build
133
+ ```
134
+
135
+ ## Status
136
+
137
+ State: done
138
+ PR: https://github.com/claricle/svg_conform/pull/109
@@ -0,0 +1,131 @@
1
+ # 04 — Ship SVG 2 secure-static
2
+
3
+ Effort: **4–6 person-days**
4
+
5
+ Repository: `claricle/svg_conform`
6
+
7
+ Depends on: Cards 02 and 03
8
+
9
+ ## Purpose
10
+
11
+ Add an opt-in SVG 2 profile for the dated Candidate Recommendation's
12
+ secure-static processing mode. Reuse the shared processing-feature requirement
13
+ and the established reference classifier rather than creating a second URI
14
+ model.
15
+
16
+ ## Requirement matrix
17
+
18
+ Add `config/profiles/svg_2_secure_static.yml` with the dated SVG 2 Candidate
19
+ Recommendation as its `specification_uri` and these stable errors:
20
+
21
+ | Requirement ID | Rule | Normative citation |
22
+ | --- | --- | --- |
23
+ | `svg2.secure_static.script` | Reject script elements and event-handler attributes. | `https://www.w3.org/TR/2026/CR-SVG2-20261006/conform.html#secure-static-mode` |
24
+ | `svg2.secure_static.animation` | Reject SVG/CSS animation and animation-timing features. | `https://www.w3.org/TR/2026/CR-SVG2-20261006/conform.html#secure-static-mode` |
25
+ | `svg2.secure_static.interaction` | Reject interaction-only event and cursor behavior. | `https://www.w3.org/TR/2026/CR-SVG2-20261006/conform.html#secure-static-mode` |
26
+ | `svg2.secure_static.external_reference` | Permit same-document fragment references and supported self-contained data URLs; reject references that require another document, local file, or network resource. | `https://www.w3.org/TR/2026/CR-SVG2-20261006/conform.html#secure-static-mode` |
27
+
28
+ The first three rows configure Card 03's
29
+ `ProcessingFeaturesRequirement`; do not fork the class or its YAML shape for
30
+ SVG 2.
31
+
32
+ ## Reference boundary
33
+
34
+ Add `ExternalReferencesRequirement` at
35
+ `lib/svg_conform/requirements/external_references_requirement.rb`. It calls the
36
+ existing public API unchanged:
37
+
38
+ ```ruby
39
+ SvgConform::References::ReferenceClassifier.classify(
40
+ href_value,
41
+ element_name:,
42
+ attribute_name:,
43
+ line_number: nil,
44
+ column_number: nil
45
+ )
46
+ ```
47
+
48
+ Keep `InternalFragmentReference`, `DataUriReference`, `UrnReference`,
49
+ `ExternalUrlReference`, and `RelativePathReference` as the returned types, and
50
+ keep `LinkValidationRequirement` on the same classifier. Add behavior to
51
+ `DataUriReference` rather than introducing a second data-URL parser.
52
+
53
+ The requirement inspects:
54
+
55
+ - `href`, `xlink:href`, and SVG URI/IRI-bearing presentation attributes;
56
+ - CSS `url(...)` and `@import` tokens in style attributes and style elements;
57
+ - `xml-stylesheet` processing instructions via Card 03's source hook.
58
+
59
+ Classification is explicit:
60
+
61
+ - `#fragment` in the current document is allowed; the existing link requirement
62
+ still reports a missing fragment target.
63
+ - HTTP(S), protocol-relative URLs, URNs, and relative paths with a resource
64
+ component (including `other.svg#id`) are rejected.
65
+ - A data URL is allowed only when it decodes without external access and its
66
+ media type is `image/png`, `image/jpeg`, or `image/svg+xml`. Raster payloads
67
+ must be non-empty and syntactically decodable; an SVG payload must decode to
68
+ one complete well-formed SVG document. Both base64 and percent-encoded forms
69
+ are covered. Malformed encodings, unsupported media types, and nested external
70
+ references in SVG data URLs are rejected.
71
+ - Empty references and non-resource lexical values retain their existing
72
+ classifier behavior and are not reclassified merely to satisfy this profile.
73
+
74
+ Nested `image/svg+xml` validation applies the external-reference rule with a
75
+ depth limit and cycle guard, but does not recursively run the entire parent
76
+ profile. It reports the outer source location and a JSON-safe nested failure
77
+ reason.
78
+
79
+ ## Corpus, tests, and documentation
80
+
81
+ Create `spec/fixtures/profiles/svg_2_secure_static/` with a small, enumerated
82
+ corpus:
83
+
84
+ - valid same-document fragments;
85
+ - valid base64 and percent-encoded PNG/JPEG data URLs;
86
+ - valid base64 and percent-encoded self-contained SVG data URLs;
87
+ - invalid HTTP(S), protocol-relative, relative-file, file-like fragment, URN,
88
+ CSS `url`, CSS `@import`, and XML-stylesheet references;
89
+ - invalid malformed/unsupported data URLs and SVG data URLs with malformed XML,
90
+ nested external content, or excessive nesting;
91
+ - one invalid fixture per script, animation, and interaction row.
92
+
93
+ Extend the existing `spec/svg_conform/references/reference_classifier_spec.rb`,
94
+ `spec/svg_conform/references/integration_spec.rb`, and
95
+ `spec/svg_conform/requirements/link_validation_requirement_spec.rb`. Add
96
+ `spec/svg_conform/references/data_uri_reference_spec.rb`,
97
+ `spec/svg_conform/requirements/external_references_requirement_spec.rb`, and
98
+ `spec/svg_conform/profiles/svg_2_secure_static_profile_spec.rb`. Run the corpus
99
+ through DOM and SAX paths and compare validity, stable IDs, and citations. Update
100
+ the existing `docs/profiles.adoc` and `docs/cli_guide.adoc` with the exact
101
+ accepted-reference table,
102
+ dated citation, profile non-goals, and example command.
103
+
104
+ ## Done when
105
+
106
+ - `svg_2_secure_static` is discoverable and opt-in; no existing profile or
107
+ default selection changes.
108
+ - All four matrix rows have stable IDs, the dated secure-static citation,
109
+ isolated invalid fixtures, and matching DOM/SAX reports.
110
+ - Same-document fragments and all six supported data-URL form/media
111
+ combinations pass, while every enumerated external or malformed case fails
112
+ with `svg2.secure_static.external_reference`.
113
+ - `ReferenceClassifier.classify` retains its signature and typed returns;
114
+ existing `LinkValidationRequirement` integration specs continue to pass.
115
+ - Processing-feature behavior comes from the unchanged serialized requirement
116
+ introduced by Card 03.
117
+ - Documentation describes secure-static resource behavior without claiming
118
+ complete SVG 2 document, rendering, or CSS conformance.
119
+ - All changed Ruby passes the repository linter and the gem builds.
120
+
121
+ ```sh
122
+ bundle exec rspec spec/svg_conform/references/reference_classifier_spec.rb spec/svg_conform/references/data_uri_reference_spec.rb spec/svg_conform/references/integration_spec.rb spec/svg_conform/requirements/link_validation_requirement_spec.rb spec/svg_conform/requirements/external_references_requirement_spec.rb spec/svg_conform/requirements/processing_features_requirement_spec.rb spec/svg_conform/profiles/svg_2_secure_static_profile_spec.rb spec/svg_conform/commands/profiles_command_spec.rb
123
+ bundle exec svg_conform check spec/fixtures/profiles/svg_2_secure_static/valid/same-document-fragment.svg --profile svg_2_secure_static --format json
124
+ bundle exec rubocop
125
+ bundle exec rake build
126
+ ```
127
+
128
+ ## Status
129
+
130
+ State: done
131
+ PR: https://github.com/claricle/svg_conform/pull/107
@@ -0,0 +1,108 @@
1
+ # 05 — Freeze the candidate and adoption handoff
2
+
3
+ Effort: **2–4 person-days**
4
+
5
+ Repositories: `claricle/lens_core`, then `claricle/svg_conform`
6
+
7
+ Depends on: Cards 01–04
8
+
9
+ ## Purpose
10
+
11
+ Freeze the v1 candidate against real svg_conform output, pin the round-trip
12
+ corpus, and leave enough format-neutral evidence for another lens to adopt
13
+ LensCore without loading SVG code. The endpoint is ready to tag; gem publication
14
+ and adopter migrations are outside this issue.
15
+
16
+ ## Golden corpus
17
+
18
+ In LensCore, add:
19
+
20
+ - `spec/fixtures/v1/golden/svg_conform/svg-1.1-invalid-grammar.json`, exported
21
+ from the Card 03 invalid grammar fixture;
22
+ - `spec/fixtures/v1/golden/svg_conform/svg-2-external-reference.json`, exported
23
+ from the Card 04 external-reference fixture;
24
+ - `spec/fixtures/v1/golden/svg_conform/svg-four-channel-library.json`, exported
25
+ through the public adapter from a focused result containing an error, validity
26
+ error, warning, and info;
27
+ - `spec/fixtures/v1/golden/examples/xml-location.json` and
28
+ `binary-location.json`, format-neutral examples that exercise the two location
29
+ forms without claiming adoption by another lens;
30
+ - `spec/fixtures/v1/golden/manifest.yml`, recording each file's SHA-256,
31
+ producer/version, source fixture, schema version, exact svg_conform commit for
32
+ SVG exports, and the exact pre-freeze LensCore contract commit used to render
33
+ them.
34
+
35
+ All goldens omit timestamps. Add `script/refresh_svg_goldens`, which takes an
36
+ svg_conform checkout path, refuses a checkout whose HEAD does not match the
37
+ manifest's expected commit, invokes the public adapter/renderers, canonicalizes
38
+ through LensCore, and updates only the three SVG JSON files and their hashes.
39
+ The script must not clone, fetch, publish, or write outside LensCore.
40
+
41
+ ## Freeze and host-only evidence
42
+
43
+ - Add `spec/lens_core/round_trip_spec.rb` for canonical value and formatting
44
+ round trips, and add `spec/lens_core/golden_corpus_spec.rb` to validate every
45
+ manifest entry against the v1 schema, parse it, render it, and compare bytes
46
+ with the input. Also prove that summary counts equal the diagnostics and that
47
+ profile, citation, context, remediation, and present location fields survive.
48
+ - Add a minimal fixture app at `spec/fixtures/host_app/` whose bundle contains
49
+ only LensCore and Ruby standard libraries. Its check reads the complete golden
50
+ directory, reports profile/count/location information, and never requires
51
+ svg_conform; exercise it from `spec/lens_core/host_only_spec.rb`.
52
+ - Commit the LensCore corpus, checks, and documentation as the immutable freeze
53
+ candidate. Do not try to write that commit's own SHA into a file in the same
54
+ commit.
55
+ - In svg_conform, update the `Gemfile` Git ref and generated `Gemfile.lock` to
56
+ that final LensCore freeze commit. Add `docs/lens_core_handoff.adoc` with the
57
+ exact LensCore freeze commit, schema path and SHA-256, golden manifest path,
58
+ canonical parse/render calls, compatibility/error rules, and the exact
59
+ earlier svg_conform producer commit named by the manifest. Explicitly label
60
+ the binary report as a contract example, not PNG/EMF/PostScript implementation
61
+ evidence.
62
+ - Re-run the Card 02 adapter specs and the two profile specs against that exact
63
+ freeze commit; no API/schema shim may remain only in an uncommitted LensCore
64
+ checkout.
65
+
66
+ If the SVG exports reveal a contract defect, fix schema/model/docs together and
67
+ commit the corrected LensCore contract first. Update svg_conform's temporary pin
68
+ and record a new producer commit, then regenerate all corpus hashes and repeat
69
+ both repositories' focused checks before declaring the later LensCore freeze
70
+ commit immutable.
71
+
72
+ ## Done when
73
+
74
+ - The manifest names exact immutable generation commits and SHA-256 values for
75
+ the schema and every golden; the svg_conform lockfile and handoff name the
76
+ later immutable LensCore freeze commit, so no branch-only or working-tree
77
+ dependency remains.
78
+ - Every canonical JSON golden validates and parse/renders byte-for-byte, and the
79
+ four-channel report proves infos and validity errors are retained.
80
+ - The host-only fixture reads XML and binary location examples using LensCore
81
+ alone and has no SVG or other-lens dependency.
82
+ - svg_conform's lockfile resolves the same frozen LensCore commit named by the
83
+ handoff, and focused adapter/SVG 1.1/SVG 2 specs pass at that pin.
84
+ - The handoff clearly separates completed contract/SVG evidence from future
85
+ EMF, PNG, PostScript, release, and publication work.
86
+ - LensCore and svg_conform each pass their changed-Ruby lint and gem build.
87
+
88
+ In `claricle/lens_core`:
89
+
90
+ ```sh
91
+ bundle exec rspec spec/lens_core/golden_corpus_spec.rb spec/lens_core/round_trip_spec.rb spec/lens_core/host_only_spec.rb
92
+ bundle exec ruby -Ilib spec/fixtures/host_app/read_reports.rb spec/fixtures/v1/golden
93
+ bundle exec rubocop
94
+ bundle exec rake build
95
+ ```
96
+
97
+ In `claricle/svg_conform`:
98
+
99
+ ```sh
100
+ bundle exec rspec spec/svg_conform/diagnostics/lens_core_adapter_spec.rb spec/svg_conform/profiles/svg_1_1_full_static_profile_spec.rb spec/svg_conform/profiles/svg_2_secure_static_profile_spec.rb
101
+ bundle exec rubocop
102
+ bundle exec rake build
103
+ ```
104
+
105
+ ## Status
106
+
107
+ State: done
108
+ PR: https://github.com/claricle/svg_conform/pull/110
@@ -0,0 +1,65 @@
1
+ # Issue 100 — Progress and handoff
2
+
3
+ ## Current state
4
+
5
+ Planning is complete. Implementation has not started, and every work card is
6
+ `todo` with no PR. The execution order is:
7
+
8
+ | Card | State | Effort | Next dependency |
9
+ | --- | --- | --- | --- |
10
+ | 01 — Build LensCore diagnostics v1 | todo | 4–7 person-days | none |
11
+ | 02 — Adopt LensCore in svg_conform | todo | 3–5 person-days | Card 01 candidate commit |
12
+ | 03 — Ship SVG 1.1 Full/static | todo | 8–12 person-days | Card 02 adapter/citations |
13
+ | 04 — Ship SVG 2 secure-static | todo | 4–6 person-days | Card 02 diagnostics and Card 03 shared plumbing |
14
+ | 05 — Freeze the candidate and adoption handoff | todo | 2–4 person-days | Cards 01–04 complete |
15
+
16
+ Overall: **21–34 person-days**.
17
+
18
+ The next action is Card 01. Card 02 must pin a real candidate commit before SVG
19
+ integration starts; Card 05 replaces that temporary pin with the final frozen
20
+ candidate commit.
21
+
22
+ ## Known implementation questions
23
+
24
+ - Card 03 must establish whether the existing Moxml/Leptris stack can perform
25
+ validating, offline SVG 1.1 DTD checks. Its four-probe spike has explicit
26
+ selection criteria and owns any dependency decision; no parser library is
27
+ assumed in advance.
28
+ - SVG 1.1 source-sensitive rules require original declarations, doctypes, and
29
+ processing instructions. Card 03 owns the source hook for both DOM and SAX so
30
+ the implementation does not infer these from an already-normalized tree.
31
+ - The dated SVG 2 source is remote normative material. Card 04 pins citations
32
+ and fixture behavior; it does not copy an untracked local snapshot into the
33
+ profile.
34
+
35
+ ## Scope deliberately left out
36
+
37
+ This plan's scope is LensCore, svg_conform adoption, and the two SVG profiles.
38
+ The following are outside it:
39
+
40
+ - **Actual EMF, PNG, and PostScript migrations, dependencies, and report
41
+ goldens.** Those belong to their separate tracker issues. Card 05 supplies the
42
+ exact LensCore commit, schema digest, SVG exports, host-only proof, and generic
43
+ binary-location example they need, without claiming those repositories have
44
+ adopted the contract.
45
+ - **PNG-specific full-report migration, inaccessible-field work, and a
46
+ PNG-only RuboCop command.** No PNG files are in scope, so inventing PNG API or
47
+ fixture requirements here would be unverified cross-repository design.
48
+ - **EMF spec paths that do not exist in the target repository.** The plan does
49
+ not cite or require nonexistent tests; the format-neutral binary example is
50
+ the only evidence needed for this contract issue.
51
+ - **PostScript implementation.** The final scope excludes it entirely, so there
52
+ is no placeholder adapter or speculative field map.
53
+ - **Lens-family release and dependency audit commands.** Publishing LensCore,
54
+ replacing temporary Git pins with a released gem constraint, changing every
55
+ lens gemspec/lockfile, and running their release checks happen after this
56
+ issue. Card 05 ends at an immutable, ready-to-tag candidate and observable
57
+ handoff.
58
+
59
+ ## Verification handoff
60
+
61
+ The commands on Cards 01–05 are prospective implementation checks. They are
62
+ focused by design: targeted specs and fixtures, changed-repository RuboCop, and
63
+ gem builds only. No full suite, corpus sweep, or fuzzer is required. Card 05 is
64
+ the final integration gate and must record immutable commits and digests rather
65
+ than branch names.
@@ -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", "clip-path", "mask"]
24
+ attributes: ["version", "baseProfile", "width", "viewBox", "preserveAspectRatio", "snapshotTime", "height", "id", "role", "break", "color-rendering", "fill-rule", "overflow", "data-name", "clip-path", "mask", "contentStyleType", "zoomAndPan"]
25
25
  required_attributes: ["version", "baseProfile"]
26
26
  attribute_values:
27
27
  version: ["1.2"]
@@ -61,13 +61,13 @@ requirements:
61
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", "clip-path", "mask"]
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", "textLength", "lengthAdjust"]
65
65
  allowed_children: ["desc", "title", "tspan", "text", "a"]
66
66
  - tag: "g"
67
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
- attributes: ["id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
70
+ attributes: ["id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "clip-path", "mask"]
71
71
  allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc", "style", "clipPath", "linearGradient", "radialGradient", "pattern", "marker", "mask", "filter", "image"]
72
72
  - tag: "clipPath"
73
73
  attributes: ["id", "clipPathUnits", "class", "style"]
@@ -100,7 +100,7 @@ requirements:
100
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
- attributes: ["id", "role", "fill", "transform", "fill-rule", "target", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
103
+ attributes: ["id", "role", "fill", "transform", "fill-rule", "target", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "title", "clip-path", "mask"]
104
104
  allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc"]
105
105
  - tag: "tspan"
106
106
  attributes: ["x", "y", "id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "letter-spacing"]
@@ -0,0 +1,69 @@
1
+ name: "svg_1_1_full_static"
2
+ description: "SVG 1.1 Full (Second Edition) document grammar under static processing"
3
+ specification_uri: "https://www.w3.org/TR/2011/REC-SVG11-20110816/"
4
+ specification_label: "Scalable Vector Graphics (SVG) 1.1 (Second Edition)"
5
+
6
+ requirements:
7
+ - id: "svg11.document.xml"
8
+ type: "Svg11DocumentRequirement"
9
+ rule: "xml"
10
+ description: "The source is well-formed XML and exposes its original declaration, doctype, and processing instructions"
11
+ citation_uri: "https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGDocuments"
12
+ citation_label: "Conforming SVG Documents"
13
+ - id: "svg11.document.root"
14
+ type: "Svg11DocumentRequirement"
15
+ rule: "root"
16
+ description: "The document element is svg in the SVG namespace"
17
+ citation_uri: "https://www.w3.org/TR/2011/REC-SVG11-20110816/struct.html#SVGElement"
18
+ citation_label: "The svg element"
19
+ - id: "svg11.document.version"
20
+ type: "Svg11DocumentRequirement"
21
+ rule: "version"
22
+ description: "The root declares SVG version 1.1"
23
+ citation_uri: "https://www.w3.org/TR/2011/REC-SVG11-20110816/struct.html#SVGElementVersionAttribute"
24
+ citation_label: "The version attribute"
25
+ - id: "svg11.document.grammar"
26
+ type: "Svg11DocumentRequirement"
27
+ rule: "grammar"
28
+ description: "Elements, attributes and content models validate against the pinned SVG 1.1 Full flat DTD after the Appendix G.2 foreign-namespace transform"
29
+ citation_uri: "https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGDocuments"
30
+ citation_label: "Conforming SVG Documents"
31
+ - id: "svg11.document.css2"
32
+ type: "Svg11DocumentRequirement"
33
+ rule: "css2"
34
+ description: "Style attributes and style sheets conform to the CSS 2 core grammar (syntax only)"
35
+ citation_uri: "https://www.w3.org/TR/2008/REC-CSS2-20080411/grammar.html"
36
+ citation_label: "CSS 2 grammar"
37
+ - id: "svg11.document.xml_stylesheet"
38
+ type: "Svg11DocumentRequirement"
39
+ rule: "xml_stylesheet"
40
+ description: "xml-stylesheet processing instructions obey their pseudo-attribute syntax and SVG applicability"
41
+ citation_uri: "https://www.w3.org/TR/1999/REC-xml-stylesheet-19990629/"
42
+ citation_label: "Associating Style Sheets with XML documents"
43
+ - id: "svg11.processing"
44
+ type: "ProcessingFeaturesRequirement"
45
+ description: "Static processing rejects script, animation and interaction"
46
+ categories:
47
+ - name: "script"
48
+ id: "svg11.processing.script"
49
+ citation: "https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGViewers"
50
+ description: "Static mode rejects script elements and event-handler attributes"
51
+ elements: ["script"]
52
+ attributes:
53
+ [onabort, onerror, onload, onresize, onscroll, onunload, onzoom]
54
+ - name: "animation"
55
+ id: "svg11.processing.animation"
56
+ citation: "https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGViewers"
57
+ description: "Static mode rejects animation elements and animation-timing attributes"
58
+ elements: [animate, animateColor, animateMotion, animateTransform, set, mpath]
59
+ attributes:
60
+ [begin, end, dur, min, max, restart, repeatCount, repeatDur, calcMode,
61
+ keyTimes, keySplines, onbegin, onend, onrepeat]
62
+ - name: "interaction"
63
+ id: "svg11.processing.interaction"
64
+ citation: "https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGViewers"
65
+ description: "Static mode rejects interaction-only event attributes and cursor behavior"
66
+ elements: ["cursor"]
67
+ attributes:
68
+ [onactivate, onclick, onfocusin, onfocusout, onmousedown, onmousemove,
69
+ onmouseout, onmouseover, onmouseup, cursor]
@@ -0,0 +1,55 @@
1
+ name: "svg_2_secure_static"
2
+ description: "Opt-in SVG 2 secure-static processing mode: no script, animation, interaction or external resources"
3
+ specification_uri: "https://www.w3.org/TR/2026/CR-SVG2-20261006/"
4
+ specification_label: "Scalable Vector Graphics (SVG) 2, Candidate Recommendation 6 October 2026"
5
+
6
+ # Scope: secure-static resource behavior only. This is not a complete SVG 2
7
+ # document, rendering or CSS conformance check.
8
+ requirements:
9
+ # Same shape as config/requirements/processing_features_static.yml;
10
+ # only ids, citations and the feature lists differ.
11
+ - id: "svg2.secure_static.processing"
12
+ type: "ProcessingFeaturesRequirement"
13
+ description: "Secure-static mode rejects script, animation and interaction"
14
+ categories:
15
+ - name: "script"
16
+ id: "svg2.secure_static.script"
17
+ citation: "https://www.w3.org/TR/2026/CR-SVG2-20261006/conform.html#secure-static-mode"
18
+ description: "Secure-static mode rejects script elements and event-handler attributes"
19
+ elements: ["script"]
20
+ attributes:
21
+ [onabort, onerror, onload, onresize, onscroll, onunload, onzoom]
22
+ - name: "animation"
23
+ id: "svg2.secure_static.animation"
24
+ citation: "https://www.w3.org/TR/2026/CR-SVG2-20261006/conform.html#secure-static-mode"
25
+ description: "Secure-static mode rejects SVG/CSS animation and animation-timing features"
26
+ elements: [animate, animateColor, animateMotion, animateTransform, set, mpath, discard]
27
+ attributes:
28
+ [begin, end, dur, min, max, restart, repeatCount, repeatDur, calcMode,
29
+ keyTimes, keySplines, onbegin, onend, onrepeat]
30
+ attribute_patterns:
31
+ - "\\Aanimation(-.+)?\\z"
32
+ - "\\Atransition(-.+)?\\z"
33
+ - name: "interaction"
34
+ id: "svg2.secure_static.interaction"
35
+ citation: "https://www.w3.org/TR/2026/CR-SVG2-20261006/conform.html#secure-static-mode"
36
+ description: "Secure-static mode rejects interaction-only event attributes and cursor behavior"
37
+ elements: ["cursor"]
38
+ attributes:
39
+ [onactivate, onauxclick, onblur, onclick, ondblclick, onfocus,
40
+ onfocusin, onfocusout, onkeydown, onkeypress, onkeyup, onmousedown,
41
+ onmouseenter, onmouseleave, onmousemove, onmouseout, onmouseover,
42
+ onmouseup, onwheel, ontouchstart, ontouchend, ontouchmove,
43
+ ontouchcancel, cursor]
44
+ # Every other event-handler attribute (onpointerdown, ondragstart, ...).
45
+ # An attribute is reported by the first category that lists it, so the
46
+ # named script and animation handlers above keep their own ids.
47
+ attribute_patterns:
48
+ - "\\Aon.+\\z"
49
+
50
+ - id: "svg2.secure_static.external_reference"
51
+ type: "ExternalReferencesRequirement"
52
+ description: "Permits same-document fragments and self-contained image data URLs; rejects references to another document, local file or network resource"
53
+ citation_uri: "https://www.w3.org/TR/2026/CR-SVG2-20261006/conform.html#secure-static-mode"
54
+ citation_label: "SVG 2 CR, secure static mode"
55
+ max_data_uri_depth: 3
@@ -0,0 +1,29 @@
1
+ # Static-processing categories for ProcessingFeaturesRequirement.
2
+ # Profiles copy this requirement entry into their `requirements` list.
3
+ id: "svg11.processing"
4
+ type: "ProcessingFeaturesRequirement"
5
+ description: "Static processing rejects script, animation and interaction"
6
+ categories:
7
+ - name: "script"
8
+ id: "svg11.processing.script"
9
+ citation: "https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGViewers"
10
+ description: "Static mode rejects script elements and event-handler attributes"
11
+ elements: ["script"]
12
+ attributes:
13
+ [onabort, onerror, onload, onresize, onscroll, onunload, onzoom]
14
+ - name: "animation"
15
+ id: "svg11.processing.animation"
16
+ citation: "https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGViewers"
17
+ description: "Static mode rejects animation elements and animation-timing attributes"
18
+ elements: [animate, animateColor, animateMotion, animateTransform, set, mpath]
19
+ attributes:
20
+ [begin, end, dur, min, max, restart, repeatCount, repeatDur, calcMode,
21
+ keyTimes, keySplines, onbegin, onend, onrepeat]
22
+ - name: "interaction"
23
+ id: "svg11.processing.interaction"
24
+ citation: "https://www.w3.org/TR/2011/REC-SVG11-20110816/conform.html#ConformingSVGViewers"
25
+ description: "Static mode rejects interaction-only event attributes and cursor behavior"
26
+ elements: ["cursor"]
27
+ attributes:
28
+ [onactivate, onclick, onfocusin, onfocusout, onmousedown, onmousemove,
29
+ onmouseout, onmouseover, onmouseup, cursor]
@@ -0,0 +1,7 @@
1
+ # Vendored SVG 1.1 (Second Edition, 16 August 2011) flat DTD.
2
+ # Validation resolves this file locally; no network or external entity access.
3
+ files:
4
+ - path: svg11-flat-20110816.dtd
5
+ source_url: https://www.w3.org/Graphics/SVG/1.1/DTD/svg11-flat-20110816.dtd
6
+ retrieved: 2026-10-23
7
+ sha256: 7c22266d65655a7d359e9e79a107d156e64b29a87491313be2092bd66cab3b9b