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,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "tmpdir"
5
+
6
+ RSpec.describe SvgConform::ValidationContext, "#source" do
7
+ let(:source) do
8
+ <<~XML
9
+ <?xml version="1.0" encoding="UTF-8"?>
10
+ <!-- exact bytes -->
11
+ <?xml-stylesheet href="a.css" type="text/css"?>
12
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.1"><rect width="1" height="1"/></svg>
13
+ XML
14
+ end
15
+
16
+ let(:recorder_class) do
17
+ Class.new(SvgConform::Requirements::BaseRequirement) do
18
+ attr_accessor :calls
19
+
20
+ def validate_source(source, context)
21
+ (@calls ||= []) << {
22
+ source: source, path: context.source_path,
23
+ serialized: context.source_serialized?, order: :source
24
+ }
25
+ end
26
+
27
+ def validate_sax_element(_element, _context)
28
+ (@calls ||= []) << { order: :element }
29
+ end
30
+
31
+ def check(_node, _context)
32
+ (@calls ||= []) << { order: :element }
33
+ end
34
+ end
35
+ end
36
+
37
+ let(:requirement) { recorder_class.new(id: "rec") }
38
+ let(:profile) { SvgConform::Profile.new(name: "rec", requirements: [requirement]) }
39
+
40
+ def sources_seen
41
+ requirement.calls.select { |c| c[:order] == :source }
42
+ end
43
+
44
+ it "keeps the BaseRequirement hook a no-op" do
45
+ base = SvgConform::Requirements::BaseRequirement.new(id: "b")
46
+ expect(base.validate_source("x", nil)).to be_nil
47
+ end
48
+
49
+ it "stores source and path on ValidationContext" do
50
+ ctx = described_class.new(nil, nil, source: "s",
51
+ source_path: "p.svg")
52
+ expect([ctx.source, ctx.source_path, ctx.source_serialized?])
53
+ .to eq(["s", "p.svg", false])
54
+ expect(described_class.new(nil, nil).source).to be_nil
55
+ end
56
+
57
+ it "retains exact content in Document for string and file inputs" do
58
+ Dir.mktmpdir do |dir|
59
+ path = File.join(dir, "a.svg")
60
+ File.write(path, source)
61
+ expect(SvgConform::Document.from_content(source).source).to eq(source)
62
+ from_file = SvgConform::Document.from_file(path)
63
+ expect(from_file.source).to eq(source)
64
+ expect(from_file.source_serialized?).to be(false)
65
+ end
66
+ end
67
+
68
+ it "marks Document.from_node source as serialized" do
69
+ node = SvgConform::Document.from_content(source).moxml_document
70
+ doc = SvgConform::Document.from_node(node)
71
+ expect(doc.source_serialized?).to be(true)
72
+ expect(doc.source).to include("<svg")
73
+ end
74
+
75
+ it "passes SaxDocument content into the handler" do
76
+ SvgConform::SaxDocument.from_content(source).validate_with_profile(profile)
77
+ expect(sources_seen.size).to eq(1)
78
+ expect(sources_seen.first).to include(source: source, path: nil,
79
+ serialized: false)
80
+ end
81
+
82
+ it "calls validate_source exactly once, before elements, in DOM and SAX" do
83
+ profile.validate(SvgConform::Document.from_content(source))
84
+ dom_orders = requirement.calls.map { |c| c[:order] }
85
+ expect(dom_orders.first).to eq(:source)
86
+ expect(dom_orders.count(:source)).to eq(1)
87
+
88
+ requirement.calls = []
89
+ SvgConform::SaxDocument.from_content(source).validate_with_profile(profile)
90
+ sax_orders = requirement.calls.map { |c| c[:order] }
91
+ expect(sax_orders.first).to eq(:source)
92
+ expect(sax_orders.count(:source)).to eq(1)
93
+ end
94
+
95
+ it "gives file entry points identical source and path in both modes" do
96
+ Dir.mktmpdir do |dir|
97
+ path = File.join(dir, "a.svg")
98
+ File.write(path, source)
99
+
100
+ profile.validate_file(path)
101
+ sax = sources_seen.first
102
+ requirement.calls = []
103
+ profile.validate(SvgConform::Document.from_file(path))
104
+ dom = sources_seen.first
105
+
106
+ expect(sax).to include(source: source, path: path, serialized: false)
107
+ expect(dom).to eq(sax)
108
+ end
109
+ end
110
+
111
+ it "flags serialized source for DOM built from a node" do
112
+ node = SvgConform::Document.from_content(source).moxml_document
113
+ profile.validate(SvgConform::Document.from_node(node))
114
+ expect(sources_seen.first[:serialized]).to be(true)
115
+ end
116
+
117
+ it "still runs source validation when SAX parsing fails" do
118
+ SvgConform::SaxDocument.from_content("<svg><unclosed>")
119
+ .validate_with_profile(profile)
120
+ expect(sources_seen.size).to eq(1)
121
+ end
122
+ end
@@ -258,6 +258,45 @@ RSpec.describe SvgConform::ValidationContext do
258
258
 
259
259
  expect(context.infos.first.message).to eq("test notice")
260
260
  end
261
+
262
+ it "stores an explicit requirement ID on the info issue" do
263
+ context.add_notice(rule: nil, node: Object.new, message: "n",
264
+ requirement_id: "my_requirement")
265
+
266
+ expect(context.infos.first.requirement_id).to eq("my_requirement")
267
+ end
268
+
269
+ it "keeps existing calls working without a requirement ID" do
270
+ context.add_notice(rule: Struct.new(:id).new("test_rule"),
271
+ node: Object.new, message: "n")
272
+
273
+ expect(context.infos.first.requirement_id).to eq("test_rule")
274
+ end
275
+ end
276
+
277
+ describe "#add_external_reference_notice" do
278
+ let(:reference) do
279
+ SvgConform::References::ReferenceClassifier.classify(
280
+ "https://example.com/x", element_name: "a", attribute_name: "href"
281
+ )
282
+ end
283
+
284
+ it "stores the explicit requirement ID and JSON-safe data" do
285
+ context.add_external_reference_notice(node: Object.new,
286
+ reference: reference,
287
+ requirement_id: "link_validation")
288
+
289
+ info = context.infos.first
290
+ expect(info.requirement_id).to eq("link_validation")
291
+ expect(info.data[:reference][:value]).to eq("https://example.com/x")
292
+ end
293
+
294
+ it "keeps existing calls working" do
295
+ context.add_external_reference_notice(node: Object.new,
296
+ reference: reference)
297
+
298
+ expect(context.infos.size).to eq(1)
299
+ end
261
300
  end
262
301
 
263
302
  describe "#has_errors?" do
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "json"
5
+
6
+ RSpec.describe SvgConform::ValidationResult do
7
+ let(:fixture) { File.expand_path("../fixtures/diagnostics/external-reference-info.svg", __dir__) }
8
+ let(:invalid_svg) { '<svg xmlns="http://www.w3.org/2000/svg"><rect width="5" height="5" fill="red"/></svg>' }
9
+ let(:info_result) { SvgConform::Validator.new.validate_file(fixture, profile: :svg_1_2_rfc) }
10
+ let(:invalid_result) { SvgConform::Validator.new.validate(invalid_svg, profile: :svg_1_2_rfc) }
11
+
12
+ it "exposes infos and info_count without affecting validity" do
13
+ expect(info_result.infos.size).to eq(1)
14
+ expect(info_result.info_count).to eq(1)
15
+ expect(info_result).to be_valid
16
+ end
17
+
18
+ it "counts validity errors as errors and keeps valid? tied to them" do
19
+ context = SvgConform::ValidationContext.new(nil, SvgConform::Profile.new(name: "p"))
20
+ context.add_error(node: nil, message: "v", requirement_id: "r", severity: :validity_error)
21
+ result = described_class.new(nil, SvgConform::Profile.new(name: "p"), context)
22
+
23
+ expect(result.error_count).to eq(1)
24
+ expect(result).not_to be_valid
25
+ end
26
+
27
+ context "with lens_core installed" do
28
+ before do
29
+ unless SvgConform.lens_core_available?
30
+ skip "the optional lens_core gem is not installed"
31
+ end
32
+ end
33
+
34
+ it "builds the canonical report with an optional timestamp" do
35
+ report = info_result.to_lens_core_report(timestamp: "2026-10-23T01:02:03Z")
36
+
37
+ expect(report.summary["infos"]).to eq(1)
38
+ expect(report.to_h["timestamp"]).to eq("2026-10-23T01:02:03Z")
39
+ end
40
+
41
+ it "counts validity errors in the canonical report" do
42
+ context = SvgConform::ValidationContext.new(nil, SvgConform::Profile.new(name: "p"))
43
+ context.add_error(node: nil, message: "v", requirement_id: "r", severity: :validity_error)
44
+ result = described_class.new(nil, SvgConform::Profile.new(name: "p"), context)
45
+
46
+ expect(result.to_lens_core_report.summary["errors"]).to eq(1)
47
+ end
48
+
49
+ it "projects to_json from the canonical report plus compatibility extensions" do
50
+ parsed = JSON.parse(info_result.to_json)
51
+ canonical = info_result.to_lens_core_report.to_h
52
+
53
+ expect(parsed).to include(canonical.except("file"))
54
+ expect(parsed.keys).to include("fixes_applied", "fixable", "reference_manifest")
55
+ expect(LensCore::Parsers::Json.parse(info_result.to_json).summary["infos"]).to eq(1)
56
+ expect(info_result.to_s(format: :json)).to eq(info_result.to_json)
57
+ end
58
+
59
+ it "keeps to_h callable with symbol keys" do
60
+ hash = info_result.to_h
61
+
62
+ expect(hash[:valid]).to be(true)
63
+ expect(hash[:reference_manifest]).to have_key(:available_ids)
64
+ expect(hash[:diagnostics].first[:severity]).to eq("info")
65
+ end
66
+
67
+ it "renders text from the human renderer and includes the info" do
68
+ text = info_result.to_s
69
+
70
+ expect(text).to include("VALID: 0 errors, 0 warnings, 1 info")
71
+ expect(text).to include("info link_validation")
72
+ expect(invalid_result.to_s).to include("INVALID")
73
+ end
74
+
75
+ it "renders YAML from the canonical report" do
76
+ expect(LensCore::Parsers::Yaml.parse(info_result.to_yaml).summary["infos"]).to eq(1)
77
+ end
78
+ end
79
+
80
+ context "without lens_core" do
81
+ before do
82
+ if SvgConform.lens_core_available?
83
+ skip "lens_core is installed; the plain serializers are not in effect"
84
+ end
85
+ end
86
+
87
+ it "raises a clear error from to_lens_core_report" do
88
+ expect { info_result.to_lens_core_report }
89
+ .to raise_error(SvgConform::Error, /lens_core is not installed/)
90
+ end
91
+
92
+ it "serializes the plain structural shape as JSON" do
93
+ parsed = JSON.parse(info_result.to_json)
94
+
95
+ expect(parsed).to include("file", "profile", "valid", "errors", "warnings")
96
+ expect(parsed["valid"]).to be(true)
97
+ expect(parsed["errors"]).to eq([])
98
+ end
99
+
100
+ it "keeps to_h callable with symbol keys" do
101
+ hash = info_result.to_h
102
+
103
+ expect(hash[:valid]).to be(true)
104
+ expect(hash[:reference_manifest]).to have_key(:available_ids)
105
+ expect(hash).to have_key(:errors)
106
+ end
107
+
108
+ it "renders the plain text report" do
109
+ text = info_result.to_s
110
+
111
+ expect(text).to include("SVG Conformance Report")
112
+ expect(text).to include("Status: VALID")
113
+ expect(text).to include("✓ Document is valid")
114
+ expect(invalid_result.to_s).to include("Status: INVALID")
115
+ end
116
+
117
+ it "renders YAML from the structural shape" do
118
+ parsed = YAML.safe_load(info_result.to_yaml)
119
+
120
+ expect(parsed["valid"]).to be(true)
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "tmpdir"
5
+
6
+ RSpec.describe SvgConform::YamlIO do
7
+ def with_yaml(text)
8
+ Dir.mktmpdir do |dir|
9
+ path = File.join(dir, "t.yml")
10
+ File.write(path, text)
11
+ yield path
12
+ end
13
+ end
14
+
15
+ let(:aliased) { "a: &x {k: 1}\nb: *x\nc: :sym\n" }
16
+
17
+ it "loads aliases and permitted Symbols like Psych" do
18
+ with_yaml(aliased) do |path|
19
+ expect(described_class.safe_load_file(
20
+ path, permitted_classes: [Symbol], aliases: true
21
+ )).to eq("a" => { "k" => 1 }, "b" => { "k" => 1 }, "c" => :sym)
22
+ end
23
+ end
24
+
25
+ it "rejects aliases unless aliases: true" do
26
+ with_yaml(aliased) do |path|
27
+ expect do
28
+ described_class.safe_load_file(path, permitted_classes: [Symbol])
29
+ end.to raise_error(Yeptris::Psych::AliasesError)
30
+ end
31
+ end
32
+
33
+ it "loads the bundled quality config through Configuration" do
34
+ expect(SvgConform::QualityMetrics::Configuration.default).not_to be_nil
35
+ end
36
+
37
+ it "dumps byte-identical to Psych for a manifest-like hash" do
38
+ h = { "a" => :b, "c" => [1, "x: y", nil], "d" => { "e" => 1.5 } }
39
+ expect(described_class.dump(h)).to eq(Psych.dump(h))
40
+ end
41
+ end
data/svg_conform.gemspec CHANGED
@@ -29,9 +29,11 @@ Gem::Specification.new do |spec|
29
29
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ["lib"]
31
31
 
32
- spec.add_dependency "lutaml-model", "~> 0.8.0"
33
- spec.add_dependency "moxml", "~> 0.5"
32
+ spec.add_dependency "lutaml-model", "~> 0.8.155"
33
+ spec.add_dependency "moxml", "~> 0.6.0"
34
+ spec.add_dependency "nokogiri", "~> 1.16"
34
35
  spec.add_dependency "rainbow"
35
36
  spec.add_dependency "table_tennis"
36
37
  spec.add_dependency "thor"
38
+ spec.add_dependency "yeptris", "~> 0.6.36"
37
39
  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.2.4
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-17 00:00:00.000000000 Z
11
+ date: 2026-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model
@@ -16,28 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.8.0
19
+ version: 0.8.155
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.8.0
26
+ version: 0.8.155
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: moxml
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.5'
33
+ version: 0.6.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.5'
40
+ version: 0.6.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.16'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.16'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rainbow
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,20 @@ dependencies:
80
94
  - - ">="
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: yeptris
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.6.36
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.6.36
83
111
  description:
84
112
  email:
85
113
  - open.source@ribose.com
@@ -88,6 +116,7 @@ executables:
88
116
  extensions: []
89
117
  extra_rdoc_files: []
90
118
  files:
119
+ - ".gitattributes"
91
120
  - ".github/workflows/rake.yml"
92
121
  - ".github/workflows/release.yml"
93
122
  - ".github/workflows/svgcheck-compatibility.yml"
@@ -98,20 +127,35 @@ files:
98
127
  - CLAUDE.md
99
128
  - CODE_OF_CONDUCT.md
100
129
  - Gemfile
130
+ - Gemfile.lock
101
131
  - README.adoc
102
132
  - Rakefile
133
+ - TODO.issue-100/00-overview.md
134
+ - TODO.issue-100/01-build-lens-core-v1.md
135
+ - TODO.issue-100/02-adopt-lens-core-in-svg.md
136
+ - TODO.issue-100/03-ship-svg-1-1-full-static.md
137
+ - TODO.issue-100/04-ship-svg-2-secure-static.md
138
+ - TODO.issue-100/05-freeze-candidate-and-handoff.md
139
+ - TODO.issue-100/90-progress.md
103
140
  - benchmark/performance_comparison.rb
104
141
  - config/profiles/base.yml
105
142
  - config/profiles/lucid_fix.yml
106
143
  - config/profiles/metanorma.yml
107
144
  - config/profiles/no_external_css.yml
145
+ - config/profiles/svg_1_1_full_static.yml
108
146
  - config/profiles/svg_1_2_rfc.yml
109
147
  - config/profiles/svg_1_2_rfc_with_rdf.yml
148
+ - config/profiles/svg_2_secure_static.yml
110
149
  - config/quality_metrics.yml
150
+ - config/requirements/processing_features_static.yml
111
151
  - config/svgcheck_mapping.yml
152
+ - data/svg_1_1/manifest.yml
153
+ - data/svg_1_1/svg11-flat-20110816.dtd
112
154
  - docs/api_reference.adoc
113
155
  - docs/cli_guide.adoc
156
+ - docs/diagnostics.adoc
114
157
  - docs/image_quality.adoc
158
+ - docs/lens_core_handoff.adoc
115
159
  - docs/performance.adoc
116
160
  - docs/profiles.adoc
117
161
  - docs/rdf_metadata_support.adoc
@@ -148,6 +192,7 @@ files:
148
192
  - lib/svg_conform/conformance_report.rb
149
193
  - lib/svg_conform/constants.rb
150
194
  - lib/svg_conform/css_color.rb
195
+ - lib/svg_conform/diagnostics/lens_core_adapter.rb
151
196
  - lib/svg_conform/document.rb
152
197
  - lib/svg_conform/document_analyzer.rb
153
198
  - lib/svg_conform/element_proxy.rb
@@ -208,6 +253,7 @@ files:
208
253
  - lib/svg_conform/requirements/base_requirement.rb
209
254
  - lib/svg_conform/requirements/color_restrictions_requirement.rb
210
255
  - lib/svg_conform/requirements/element_requirement_config.rb
256
+ - lib/svg_conform/requirements/external_references_requirement.rb
211
257
  - lib/svg_conform/requirements/font_family_requirement.rb
212
258
  - lib/svg_conform/requirements/forbidden_content_requirement.rb
213
259
  - lib/svg_conform/requirements/id_collection_requirement.rb
@@ -219,22 +265,28 @@ files:
219
265
  - lib/svg_conform/requirements/no_external_css_requirement.rb
220
266
  - lib/svg_conform/requirements/no_external_fonts_requirement.rb
221
267
  - lib/svg_conform/requirements/no_external_images_requirement.rb
268
+ - lib/svg_conform/requirements/processing_features_requirement.rb
222
269
  - lib/svg_conform/requirements/style_promotion_requirement.rb
223
270
  - lib/svg_conform/requirements/style_requirement.rb
271
+ - lib/svg_conform/requirements/svg_1_1_document_requirement.rb
224
272
  - lib/svg_conform/requirements/text_as_path_requirement.rb
225
273
  - lib/svg_conform/requirements/viewbox_required_requirement.rb
226
274
  - lib/svg_conform/sax_document.rb
227
275
  - lib/svg_conform/sax_validation_handler.rb
228
276
  - lib/svg_conform/semantic_comparator.rb
277
+ - lib/svg_conform/validation/css2_core_grammar.rb
278
+ - lib/svg_conform/validation/css_references.rb
229
279
  - lib/svg_conform/validation/error_tracker.rb
230
280
  - lib/svg_conform/validation/node_id_manager.rb
231
281
  - lib/svg_conform/validation/structural_invalidity_tracker.rb
282
+ - lib/svg_conform/validation/svg_1_1_document_conformance.rb
232
283
  - lib/svg_conform/validation/tracker_factory.rb
233
284
  - lib/svg_conform/validation_context.rb
234
285
  - lib/svg_conform/validation_issue.rb
235
286
  - lib/svg_conform/validation_result.rb
236
287
  - lib/svg_conform/validator.rb
237
288
  - lib/svg_conform/version.rb
289
+ - lib/svg_conform/yaml_io.rb
238
290
  - lib/tasks/fixtures.rake
239
291
  - lib/tasks/svgcheck.rake
240
292
  - reference-docs/SVG-1.2-RFC.rnc.txt
@@ -248,6 +300,7 @@ files:
248
300
  - spec/fixtures/color_restrictions/repair/basic_violations.svg
249
301
  - spec/fixtures/comprehensive/inputs/multiple_violations.svg
250
302
  - spec/fixtures/comprehensive/repair/multiple_violations.svg
303
+ - spec/fixtures/diagnostics/external-reference-info.svg
251
304
  - spec/fixtures/font_family/inputs/basic_violations.svg
252
305
  - spec/fixtures/font_family/repair/basic_violations.svg
253
306
  - spec/fixtures/forbidden_content/inputs/basic_violations.svg
@@ -264,6 +317,51 @@ files:
264
317
  - spec/fixtures/namespace_attributes/repair/basic_violations.svg
265
318
  - spec/fixtures/no_external_css/inputs/basic_violations.svg
266
319
  - spec/fixtures/no_external_css/repair/basic_violations.svg
320
+ - spec/fixtures/plantuml/README.adoc
321
+ - spec/fixtures/plantuml/unit-type.svg
322
+ - spec/fixtures/profiles/svg_1_1_full_static/invalid/animation.svg
323
+ - spec/fixtures/profiles/svg_1_1_full_static/invalid/css-grammar.svg
324
+ - spec/fixtures/profiles/svg_1_1_full_static/invalid/dtd-attribute.svg
325
+ - spec/fixtures/profiles/svg_1_1_full_static/invalid/dtd-content-model.svg
326
+ - spec/fixtures/profiles/svg_1_1_full_static/invalid/interaction.svg
327
+ - spec/fixtures/profiles/svg_1_1_full_static/invalid/malformed-xml.svg
328
+ - spec/fixtures/profiles/svg_1_1_full_static/invalid/script.svg
329
+ - spec/fixtures/profiles/svg_1_1_full_static/invalid/wrong-namespace.svg
330
+ - spec/fixtures/profiles/svg_1_1_full_static/invalid/wrong-version.svg
331
+ - spec/fixtures/profiles/svg_1_1_full_static/invalid/xml-stylesheet.svg
332
+ - spec/fixtures/profiles/svg_1_1_full_static/valid/css.svg
333
+ - spec/fixtures/profiles/svg_1_1_full_static/valid/foreign-metadata.svg
334
+ - spec/fixtures/profiles/svg_1_1_full_static/valid/minimal-full.svg
335
+ - spec/fixtures/profiles/svg_1_1_full_static/valid/xml-stylesheet.svg
336
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/animation.svg
337
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/css-import.svg
338
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/css-url.svg
339
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/data-bad-png.svg
340
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/data-empty-png.svg
341
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/data-malformed-base64.svg
342
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/data-malformed-percent.svg
343
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/data-unsupported-type.svg
344
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/file-like-fragment.svg
345
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/http.svg
346
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/https.svg
347
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/interaction.svg
348
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/protocol-relative.svg
349
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/relative-file-fragment.svg
350
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/relative-file.svg
351
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/script.svg
352
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/svg-data-excessive-nesting.svg
353
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/svg-data-malformed-xml.svg
354
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/svg-data-nested-external.svg
355
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/urn.svg
356
+ - spec/fixtures/profiles/svg_2_secure_static/invalid/xml-stylesheet.svg
357
+ - spec/fixtures/profiles/svg_2_secure_static/valid/jpeg-base64.svg
358
+ - spec/fixtures/profiles/svg_2_secure_static/valid/jpeg-percent.svg
359
+ - spec/fixtures/profiles/svg_2_secure_static/valid/png-base64.svg
360
+ - spec/fixtures/profiles/svg_2_secure_static/valid/png-percent.svg
361
+ - spec/fixtures/profiles/svg_2_secure_static/valid/same-document-fragment.svg
362
+ - spec/fixtures/profiles/svg_2_secure_static/valid/svg-base64.svg
363
+ - spec/fixtures/profiles/svg_2_secure_static/valid/svg-percent.svg
364
+ - spec/fixtures/quality_metrics/aliases.yml
267
365
  - spec/fixtures/style/inputs/basic_violations.svg
268
366
  - spec/fixtures/style/repair/basic_violations.svg
269
367
  - spec/fixtures/style_promotion/inputs/basic_test.svg
@@ -438,13 +536,21 @@ files:
438
536
  - spec/svg_conform/commands/svgcheck_compare_command_spec.rb
439
537
  - spec/svg_conform/commands/svgcheck_compatibility_command_spec.rb
440
538
  - spec/svg_conform/commands/svgcheck_generate_command_spec.rb
539
+ - spec/svg_conform/conformance_report_spec.rb
540
+ - spec/svg_conform/diagnostics/lens_core_adapter_spec.rb
541
+ - spec/svg_conform/gemspec_spec.rb
441
542
  - spec/svg_conform/profiles/base_profile_spec.rb
442
543
  - spec/svg_conform/profiles/lucid_fix_profile_spec.rb
443
544
  - spec/svg_conform/profiles/lucid_profile_spec.rb
444
545
  - spec/svg_conform/profiles/metanorma_profile_spec.rb
445
546
  - spec/svg_conform/profiles/no_external_css_profile_spec.rb
547
+ - spec/svg_conform/profiles/svg_1_1_full_static_profile_spec.rb
446
548
  - spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb
447
549
  - spec/svg_conform/profiles/svg_1_2_rfc_with_rdf_profile_spec.rb
550
+ - spec/svg_conform/profiles/svg_2_secure_static_profile_spec.rb
551
+ - spec/svg_conform/profiles_plantuml_spec.rb
552
+ - spec/svg_conform/quality_metrics/configuration_spec.rb
553
+ - spec/svg_conform/references/data_uri_reference_spec.rb
448
554
  - spec/svg_conform/references/integration_spec.rb
449
555
  - spec/svg_conform/references/reference_classifier_spec.rb
450
556
  - spec/svg_conform/references/reference_manifest_spec.rb
@@ -460,6 +566,7 @@ files:
460
566
  - spec/svg_conform/remediations/viewbox_remediation_spec.rb
461
567
  - spec/svg_conform/requirements/allowed_elements_requirement_spec.rb
462
568
  - spec/svg_conform/requirements/color_restrictions_requirement_spec.rb
569
+ - spec/svg_conform/requirements/external_references_requirement_spec.rb
463
570
  - spec/svg_conform/requirements/font_family_requirement_spec.rb
464
571
  - spec/svg_conform/requirements/forbidden_content_requirement_spec.rb
465
572
  - spec/svg_conform/requirements/id_reference_requirement_spec.rb
@@ -471,12 +578,19 @@ files:
471
578
  - spec/svg_conform/requirements/no_external_css_requirement_spec.rb
472
579
  - spec/svg_conform/requirements/no_external_fonts_requirement_spec.rb
473
580
  - spec/svg_conform/requirements/no_external_images_requirement_spec.rb
581
+ - spec/svg_conform/requirements/processing_features_requirement_spec.rb
474
582
  - spec/svg_conform/requirements/style_promotion_requirement_spec.rb
475
583
  - spec/svg_conform/requirements/style_requirement_spec.rb
584
+ - spec/svg_conform/requirements/svg_1_1_document_requirement_spec.rb
476
585
  - spec/svg_conform/requirements/text_as_path_requirement_spec.rb
477
586
  - spec/svg_conform/requirements/viewbox_required_requirement_spec.rb
587
+ - spec/svg_conform/validation/css2_core_grammar_spec.rb
588
+ - spec/svg_conform/validation/svg_1_1_document_conformance_spec.rb
589
+ - spec/svg_conform/validation_context_source_plumbing_spec.rb
478
590
  - spec/svg_conform/validation_context_spec.rb
591
+ - spec/svg_conform/validation_result_spec.rb
479
592
  - spec/svg_conform/validator_input_types_spec.rb
593
+ - spec/svg_conform/yaml_io_spec.rb
480
594
  - spec/svg_conform_spec.rb
481
595
  - spec/svgcheck_compatibility_spec.rb
482
596
  - svg_conform.gemspec