svg_conform 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/rake.yml +15 -0
- data/.github/workflows/release.yml +23 -0
- data/.github/workflows/svgcheck-compatibility.yml +135 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/.rubocop_todo.yml +183 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/Gemfile +14 -0
- data/README.adoc +1384 -0
- data/Rakefile +15 -0
- data/config/profiles/base.yml +34 -0
- data/config/profiles/lucid_fix.yml +37 -0
- data/config/profiles/metanorma.yml +212 -0
- data/config/profiles/no_external_css.yml +20 -0
- data/config/profiles/svg_1_2_rfc.yml +284 -0
- data/config/profiles/svg_1_2_rfc_with_rdf.yml +145 -0
- data/config/svgcheck_mapping.yml +180 -0
- data/docs/profiles.adoc +547 -0
- data/docs/rdf_metadata_support.adoc +212 -0
- data/docs/remediation.adoc +732 -0
- data/docs/requirements.adoc +709 -0
- data/examples/demo.rb +116 -0
- data/examples/requirements_demo.rb +240 -0
- data/exe/svg_conform +7 -0
- data/lib/svg_conform/batch_report.rb +70 -0
- data/lib/svg_conform/cli.rb +107 -0
- data/lib/svg_conform/commands/check.rb +390 -0
- data/lib/svg_conform/commands/profiles.rb +118 -0
- data/lib/svg_conform/commands/svgcheck.rb +90 -0
- data/lib/svg_conform/commands/svgcheck_compare.rb +92 -0
- data/lib/svg_conform/commands/svgcheck_compatibility.rb +43 -0
- data/lib/svg_conform/commands/svgcheck_generate.rb +262 -0
- data/lib/svg_conform/compatibility/analysis_context.rb +68 -0
- data/lib/svg_conform/compatibility/comparison_result.rb +147 -0
- data/lib/svg_conform/compatibility/compatibility_analyzer.rb +85 -0
- data/lib/svg_conform/compatibility/file_processor.rb +109 -0
- data/lib/svg_conform/compatibility/pattern_discovery.rb +319 -0
- data/lib/svg_conform/compatibility/report_formatter.rb +359 -0
- data/lib/svg_conform/compatibility/svg_analysis_engine.rb +316 -0
- data/lib/svg_conform/compatibility/validity_analysis.rb +252 -0
- data/lib/svg_conform/compatibility/xml_analysis_engine.rb +198 -0
- data/lib/svg_conform/compatibility_analyzer.rb +285 -0
- data/lib/svg_conform/conformance_report.rb +267 -0
- data/lib/svg_conform/constants.rb +199 -0
- data/lib/svg_conform/css_color.rb +262 -0
- data/lib/svg_conform/document.rb +203 -0
- data/lib/svg_conform/external_checkers/svgcheck/compatibility_engine.rb +166 -0
- data/lib/svg_conform/external_checkers/svgcheck/output_generator.rb +101 -0
- data/lib/svg_conform/external_checkers/svgcheck/parser.rb +200 -0
- data/lib/svg_conform/external_checkers/svgcheck/report_comparator.rb +175 -0
- data/lib/svg_conform/external_checkers/svgcheck/report_generator.rb +82 -0
- data/lib/svg_conform/external_checkers/svgcheck/validation_pipeline.rb +249 -0
- data/lib/svg_conform/external_checkers/svgcheck.rb +56 -0
- data/lib/svg_conform/external_checkers.rb +34 -0
- data/lib/svg_conform/fixer.rb +56 -0
- data/lib/svg_conform/profile.rb +164 -0
- data/lib/svg_conform/profiles.rb +60 -0
- data/lib/svg_conform/remediation_engine.rb +92 -0
- data/lib/svg_conform/remediation_result.rb +36 -0
- data/lib/svg_conform/remediation_runner.rb +225 -0
- data/lib/svg_conform/remediations/base_remediation.rb +165 -0
- data/lib/svg_conform/remediations/color_remediation.rb +226 -0
- data/lib/svg_conform/remediations/font_embedding_remediation.rb +145 -0
- data/lib/svg_conform/remediations/font_remediation.rb +122 -0
- data/lib/svg_conform/remediations/image_embedding_remediation.rb +154 -0
- data/lib/svg_conform/remediations/invalid_id_references_remediation.rb +129 -0
- data/lib/svg_conform/remediations/namespace_attribute_remediation.rb +244 -0
- data/lib/svg_conform/remediations/namespace_remediation.rb +151 -0
- data/lib/svg_conform/remediations/no_external_css_remediation.rb +192 -0
- data/lib/svg_conform/remediations/style_promotion_remediation.rb +93 -0
- data/lib/svg_conform/remediations/viewbox_remediation.rb +127 -0
- data/lib/svg_conform/remediations.rb +40 -0
- data/lib/svg_conform/report_comparator.rb +772 -0
- data/lib/svg_conform/requirements/allowed_elements_requirement.rb +367 -0
- data/lib/svg_conform/requirements/base_requirement.rb +98 -0
- data/lib/svg_conform/requirements/color_restrictions_requirement.rb +126 -0
- data/lib/svg_conform/requirements/element_requirement_config.rb +75 -0
- data/lib/svg_conform/requirements/font_family_requirement.rb +133 -0
- data/lib/svg_conform/requirements/forbidden_content_requirement.rb +60 -0
- data/lib/svg_conform/requirements/id_reference_requirement.rb +133 -0
- data/lib/svg_conform/requirements/invalid_id_references_requirement.rb +132 -0
- data/lib/svg_conform/requirements/link_validation_requirement.rb +55 -0
- data/lib/svg_conform/requirements/namespace_attributes_requirement.rb +211 -0
- data/lib/svg_conform/requirements/namespace_requirement.rb +294 -0
- data/lib/svg_conform/requirements/no_external_css_requirement.rb +132 -0
- data/lib/svg_conform/requirements/no_external_fonts_requirement.rb +121 -0
- data/lib/svg_conform/requirements/no_external_images_requirement.rb +91 -0
- data/lib/svg_conform/requirements/style_promotion_requirement.rb +72 -0
- data/lib/svg_conform/requirements/style_requirement.rb +226 -0
- data/lib/svg_conform/requirements/viewbox_required_requirement.rb +96 -0
- data/lib/svg_conform/requirements.rb +49 -0
- data/lib/svg_conform/semantic_comparator.rb +829 -0
- data/lib/svg_conform/validation_context.rb +408 -0
- data/lib/svg_conform/validation_result.rb +146 -0
- data/lib/svg_conform/validator.rb +91 -0
- data/lib/svg_conform/version.rb +5 -0
- data/lib/svg_conform.rb +68 -0
- data/lib/tasks/fixtures.rake +321 -0
- data/lib/tasks/svgcheck.rake +111 -0
- data/reference-docs/SVG-1.2-RFC.rnc.txt +1676 -0
- data/reference-docs/Scalable Vector Graphics (SVG) 1.1 (Second Edition).html +40764 -0
- data/reference-docs/Scalable Vector Graphics (SVG) Tiny 1.2 Specification.html +44591 -0
- data/reference-docs/rfc7996.txt +2971 -0
- data/sig/svg_conform.rbs +4 -0
- data/spec/fixtures/allowed_elements/inputs/basic_violations.svg +21 -0
- data/spec/fixtures/allowed_elements/repair/basic_violations.svg +18 -0
- data/spec/fixtures/color_restrictions/inputs/basic_violations.svg +23 -0
- data/spec/fixtures/color_restrictions/repair/basic_violations.svg +23 -0
- data/spec/fixtures/comprehensive/inputs/multiple_violations.svg +21 -0
- data/spec/fixtures/comprehensive/repair/multiple_violations.svg +16 -0
- data/spec/fixtures/font_family/inputs/basic_violations.svg +17 -0
- data/spec/fixtures/font_family/repair/basic_violations.svg +17 -0
- data/spec/fixtures/forbidden_content/inputs/basic_violations.svg +27 -0
- data/spec/fixtures/forbidden_content/repair/basic_violations.svg +19 -0
- data/spec/fixtures/id_reference/inputs/basic_violations.svg +17 -0
- data/spec/fixtures/id_reference/repair/basic_violations.svg +15 -0
- data/spec/fixtures/link_validation/inputs/basic_violations.svg +20 -0
- data/spec/fixtures/link_validation/repair/basic_violations.svg +16 -0
- data/spec/fixtures/lucid/inputs/simple.svg +67 -0
- data/spec/fixtures/lucid/repair/simple.svg +63 -0
- data/spec/fixtures/namespace/inputs/basic_violations.svg +20 -0
- data/spec/fixtures/namespace/repair/basic_violations.svg +17 -0
- data/spec/fixtures/namespace_attributes/inputs/basic_violations.svg +16 -0
- data/spec/fixtures/namespace_attributes/repair/basic_violations.svg +15 -0
- data/spec/fixtures/no_external_css/inputs/basic_violations.svg +20 -0
- data/spec/fixtures/no_external_css/repair/basic_violations.svg +18 -0
- data/spec/fixtures/style/inputs/basic_violations.svg +22 -0
- data/spec/fixtures/style/repair/basic_violations.svg +22 -0
- data/spec/fixtures/style_promotion/inputs/basic_test.svg +15 -0
- data/spec/fixtures/style_promotion/repair/basic_test.svg +15 -0
- data/spec/fixtures/svg_1_2_rfc/inputs/allowed_elements_violations.svg +18 -0
- data/spec/fixtures/svg_1_2_rfc/inputs/color_restrictions_violations.svg +23 -0
- data/spec/fixtures/svgcheck/check/DrawBerry-sample-2.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/DrawBerry-sample-2.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/DrawBerry-sample-2.svg.out +23 -0
- data/spec/fixtures/svgcheck/check/IETF-test.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/IETF-test.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/IETF-test.svg.out +20 -0
- data/spec/fixtures/svgcheck/check/circle.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/circle.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/circle.svg.out +2 -0
- data/spec/fixtures/svgcheck/check/colors.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/colors.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/colors.svg.out +13 -0
- data/spec/fixtures/svgcheck/check/dia-sample-svg.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/dia-sample-svg.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/dia-sample-svg.svg.out +76 -0
- data/spec/fixtures/svgcheck/check/example-dot.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/example-dot.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/example-dot.svg.out +11 -0
- data/spec/fixtures/svgcheck/check/full-tiny.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/full-tiny.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/full-tiny.svg.out +5835 -0
- data/spec/fixtures/svgcheck/check/good.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/good.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/good.svg.out +1 -0
- data/spec/fixtures/svgcheck/check/httpbis-proxy20-fig6.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/httpbis-proxy20-fig6.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/httpbis-proxy20-fig6.svg.out +5 -0
- data/spec/fixtures/svgcheck/check/malformed.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/malformed.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/malformed.svg.out +8 -0
- data/spec/fixtures/svgcheck/check/rfc-svg.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/rfc-svg.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/rfc-svg.svg.out +1 -0
- data/spec/fixtures/svgcheck/check/rfc.xml.code +1 -0
- data/spec/fixtures/svgcheck/check/rfc.xml.err +0 -0
- data/spec/fixtures/svgcheck/check/rfc.xml.out +2 -0
- data/spec/fixtures/svgcheck/check/rgb.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/rgb.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/rgb.svg.out +9 -0
- data/spec/fixtures/svgcheck/check/svg-wordle.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/svg-wordle.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/svg-wordle.svg.out +508 -0
- data/spec/fixtures/svgcheck/check/threshold.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/threshold.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/threshold.svg.out +20 -0
- data/spec/fixtures/svgcheck/check/utf8.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/utf8.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/utf8.svg.out +162 -0
- data/spec/fixtures/svgcheck/check/viewBox-both.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/viewBox-both.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/viewBox-both.svg.out +4 -0
- data/spec/fixtures/svgcheck/check/viewBox-height.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/viewBox-height.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/viewBox-height.svg.out +3 -0
- data/spec/fixtures/svgcheck/check/viewBox-none.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/viewBox-none.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/viewBox-none.svg.out +3 -0
- data/spec/fixtures/svgcheck/check/viewBox-width.svg.code +1 -0
- data/spec/fixtures/svgcheck/check/viewBox-width.svg.err +0 -0
- data/spec/fixtures/svgcheck/check/viewBox-width.svg.out +3 -0
- data/spec/fixtures/svgcheck/inputs/DrawBerry-sample-2.svg +28 -0
- data/spec/fixtures/svgcheck/inputs/IETF-test.svg +28 -0
- data/spec/fixtures/svgcheck/inputs/circle.svg +3 -0
- data/spec/fixtures/svgcheck/inputs/colors.svg +18 -0
- data/spec/fixtures/svgcheck/inputs/dia-sample-svg.svg +47 -0
- data/spec/fixtures/svgcheck/inputs/example-dot.svg +75 -0
- data/spec/fixtures/svgcheck/inputs/full-tiny.svg +16194 -0
- data/spec/fixtures/svgcheck/inputs/good.svg +19 -0
- data/spec/fixtures/svgcheck/inputs/httpbis-proxy20-fig6.svg +2 -0
- data/spec/fixtures/svgcheck/inputs/malformed.svg +11 -0
- data/spec/fixtures/svgcheck/inputs/rfc-svg.svg +1028 -0
- data/spec/fixtures/svgcheck/inputs/rfc.xml +37 -0
- data/spec/fixtures/svgcheck/inputs/rgb.svg +9 -0
- data/spec/fixtures/svgcheck/inputs/svg-wordle.svg +330 -0
- data/spec/fixtures/svgcheck/inputs/threshold.svg +26 -0
- data/spec/fixtures/svgcheck/inputs/utf8.svg +448 -0
- data/spec/fixtures/svgcheck/inputs/viewBox-both.svg +3 -0
- data/spec/fixtures/svgcheck/inputs/viewBox-height.svg +3 -0
- data/spec/fixtures/svgcheck/inputs/viewBox-none.svg +3 -0
- data/spec/fixtures/svgcheck/inputs/viewBox-width.svg +3 -0
- data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.file +0 -0
- data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.out +23 -0
- data/spec/fixtures/svgcheck/repair/IETF-test.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/IETF-test.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/IETF-test.svg.file +29 -0
- data/spec/fixtures/svgcheck/repair/IETF-test.svg.out +20 -0
- data/spec/fixtures/svgcheck/repair/circle.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/circle.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/circle.svg.file +4 -0
- data/spec/fixtures/svgcheck/repair/circle.svg.out +2 -0
- data/spec/fixtures/svgcheck/repair/colors.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/colors.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/colors.svg.file +19 -0
- data/spec/fixtures/svgcheck/repair/colors.svg.out +13 -0
- data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.file +47 -0
- data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.out +76 -0
- data/spec/fixtures/svgcheck/repair/example-dot.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/example-dot.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/example-dot.svg.file +69 -0
- data/spec/fixtures/svgcheck/repair/example-dot.svg.out +11 -0
- data/spec/fixtures/svgcheck/repair/good.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/good.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/good.svg.file +0 -0
- data/spec/fixtures/svgcheck/repair/good.svg.out +1 -0
- data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.file +73 -0
- data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.out +5 -0
- data/spec/fixtures/svgcheck/repair/malformed.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/malformed.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/malformed.svg.file +9 -0
- data/spec/fixtures/svgcheck/repair/malformed.svg.out +8 -0
- data/spec/fixtures/svgcheck/repair/rfc-svg.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/rfc-svg.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/rfc-svg.svg.file +0 -0
- data/spec/fixtures/svgcheck/repair/rfc-svg.svg.out +1 -0
- data/spec/fixtures/svgcheck/repair/rfc.xml.code +1 -0
- data/spec/fixtures/svgcheck/repair/rfc.xml.err +0 -0
- data/spec/fixtures/svgcheck/repair/rfc.xml.file +37 -0
- data/spec/fixtures/svgcheck/repair/rfc.xml.out +2 -0
- data/spec/fixtures/svgcheck/repair/rgb.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/rgb.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/rgb.svg.file +10 -0
- data/spec/fixtures/svgcheck/repair/rgb.svg.out +9 -0
- data/spec/fixtures/svgcheck/repair/svg-wordle.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/svg-wordle.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/svg-wordle.svg.file +112 -0
- data/spec/fixtures/svgcheck/repair/svg-wordle.svg.out +508 -0
- data/spec/fixtures/svgcheck/repair/threshold.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/threshold.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/threshold.svg.file +27 -0
- data/spec/fixtures/svgcheck/repair/threshold.svg.out +20 -0
- data/spec/fixtures/svgcheck/repair/utf8.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/utf8.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/utf8.svg.file +381 -0
- data/spec/fixtures/svgcheck/repair/utf8.svg.out +162 -0
- data/spec/fixtures/svgcheck/repair/viewBox-both.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/viewBox-both.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/viewBox-both.svg.file +4 -0
- data/spec/fixtures/svgcheck/repair/viewBox-both.svg.out +4 -0
- data/spec/fixtures/svgcheck/repair/viewBox-height.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/viewBox-height.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/viewBox-height.svg.file +4 -0
- data/spec/fixtures/svgcheck/repair/viewBox-height.svg.out +3 -0
- data/spec/fixtures/svgcheck/repair/viewBox-none.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/viewBox-none.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/viewBox-none.svg.file +4 -0
- data/spec/fixtures/svgcheck/repair/viewBox-none.svg.out +3 -0
- data/spec/fixtures/svgcheck/repair/viewBox-width.svg.code +1 -0
- data/spec/fixtures/svgcheck/repair/viewBox-width.svg.err +0 -0
- data/spec/fixtures/svgcheck/repair/viewBox-width.svg.file +4 -0
- data/spec/fixtures/svgcheck/repair/viewBox-width.svg.out +3 -0
- data/spec/fixtures/viewbox_required/inputs/missing_viewbox.svg +10 -0
- data/spec/fixtures/viewbox_required/repair/missing_viewbox.svg +10 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/svg_conform/batch_report_spec.rb +99 -0
- data/spec/svg_conform/commands/check_command_spec.rb +90 -0
- data/spec/svg_conform/commands/profiles_command_spec.rb +20 -0
- data/spec/svg_conform/commands/svgcheck_compare_command_spec.rb +13 -0
- data/spec/svg_conform/commands/svgcheck_compatibility_command_spec.rb +13 -0
- data/spec/svg_conform/commands/svgcheck_generate_command_spec.rb +14 -0
- data/spec/svg_conform/profiles/base_profile_spec.rb +42 -0
- data/spec/svg_conform/profiles/lucid_fix_profile_spec.rb +46 -0
- data/spec/svg_conform/profiles/lucid_profile_spec.rb +84 -0
- data/spec/svg_conform/profiles/metanorma_profile_spec.rb +62 -0
- data/spec/svg_conform/profiles/no_external_css_profile_spec.rb +66 -0
- data/spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb +200 -0
- data/spec/svg_conform/profiles/svg_1_2_rfc_with_rdf_profile_spec.rb +81 -0
- data/spec/svg_conform/remediations/color_remediation_spec.rb +95 -0
- data/spec/svg_conform/remediations/font_embedding_remediation_spec.rb +20 -0
- data/spec/svg_conform/remediations/font_remediation_spec.rb +95 -0
- data/spec/svg_conform/remediations/image_embedding_remediation_spec.rb +20 -0
- data/spec/svg_conform/remediations/invalid_id_references_remediation_spec.rb +97 -0
- data/spec/svg_conform/remediations/namespace_attribute_remediation_spec.rb +97 -0
- data/spec/svg_conform/remediations/namespace_remediation_spec.rb +95 -0
- data/spec/svg_conform/remediations/no_external_css_remediation_spec.rb +97 -0
- data/spec/svg_conform/remediations/style_promotion_remediation_spec.rb +97 -0
- data/spec/svg_conform/remediations/viewbox_remediation_spec.rb +95 -0
- data/spec/svg_conform/requirements/allowed_elements_requirement_spec.rb +118 -0
- data/spec/svg_conform/requirements/color_restrictions_requirement_spec.rb +168 -0
- data/spec/svg_conform/requirements/font_family_requirement_spec.rb +188 -0
- data/spec/svg_conform/requirements/forbidden_content_requirement_spec.rb +195 -0
- data/spec/svg_conform/requirements/id_reference_requirement_spec.rb +78 -0
- data/spec/svg_conform/requirements/invalid_id_references_requirement_spec.rb +78 -0
- data/spec/svg_conform/requirements/link_validation_requirement_spec.rb +78 -0
- data/spec/svg_conform/requirements/namespace_attributes_requirement_spec.rb +86 -0
- data/spec/svg_conform/requirements/namespace_requirement_spec.rb +184 -0
- data/spec/svg_conform/requirements/no_external_css_requirement_spec.rb +78 -0
- data/spec/svg_conform/requirements/no_external_fonts_requirement_spec.rb +20 -0
- data/spec/svg_conform/requirements/no_external_images_requirement_spec.rb +20 -0
- data/spec/svg_conform/requirements/style_promotion_requirement_spec.rb +78 -0
- data/spec/svg_conform/requirements/style_requirement_spec.rb +76 -0
- data/spec/svg_conform/requirements/viewbox_required_requirement_spec.rb +165 -0
- data/spec/svg_conform_spec.rb +32 -0
- data/spec/svgcheck_compatibility_spec.rb +355 -0
- data/svg_conform.gemspec +35 -0
- metadata +436 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require "canon"
|
|
5
|
+
|
|
6
|
+
RSpec.describe SvgConform::Requirements::ColorRestrictionsRequirement do
|
|
7
|
+
let(:fixtures_dir) { "spec/fixtures/color_restrictions" }
|
|
8
|
+
|
|
9
|
+
# Get all fixture files that have both input and expected repair versions
|
|
10
|
+
fixture_files = Dir.glob("spec/fixtures/color_restrictions/inputs/*.svg").select do |input_file|
|
|
11
|
+
basename = File.basename(input_file)
|
|
12
|
+
File.exist?("spec/fixtures/color_restrictions/repair/#{basename}")
|
|
13
|
+
end.map do |f|
|
|
14
|
+
File.basename(f, ".svg")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
fixture_files.each do |fixture_name|
|
|
18
|
+
describe "fixture: #{fixture_name}" do
|
|
19
|
+
let(:input_file) do
|
|
20
|
+
"spec/fixtures/color_restrictions/inputs/#{fixture_name}.svg"
|
|
21
|
+
end
|
|
22
|
+
let(:expected_output_file) do
|
|
23
|
+
"spec/fixtures/color_restrictions/repair/#{fixture_name}.svg"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "validates input file and identifies color violations" do
|
|
27
|
+
skip "Input file not found" unless File.exist?(input_file)
|
|
28
|
+
|
|
29
|
+
document = SvgConform::Document.from_file(input_file)
|
|
30
|
+
requirement = described_class.new(
|
|
31
|
+
id: "color_restrictions",
|
|
32
|
+
description: "Test color restrictions requirement",
|
|
33
|
+
allowed_colors: %w[black white],
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
37
|
+
requirement.validate_document(document, context)
|
|
38
|
+
|
|
39
|
+
expect(context.errors).not_to be_empty
|
|
40
|
+
puts "Found #{context.errors.count} color violations in #{fixture_name}"
|
|
41
|
+
|
|
42
|
+
context.errors.each do |error|
|
|
43
|
+
expect(error.requirement_id).to eq("color_restrictions")
|
|
44
|
+
expect(error.message).to be_a(String)
|
|
45
|
+
expect(error.message).not_to be_empty
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "correctly identifies specific color violations" do
|
|
50
|
+
skip "Input file not found" unless File.exist?(input_file)
|
|
51
|
+
|
|
52
|
+
document = SvgConform::Document.from_file(input_file)
|
|
53
|
+
requirement = described_class.new(
|
|
54
|
+
id: "color_restrictions",
|
|
55
|
+
description: "Test color restrictions requirement",
|
|
56
|
+
grayscale_only: true,
|
|
57
|
+
allowed_colors: %w[black white gray grey silver],
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
61
|
+
requirement.validate_document(document, context)
|
|
62
|
+
|
|
63
|
+
# Check that errors are specific to invalid colors
|
|
64
|
+
context.errors.each do |error|
|
|
65
|
+
expect(error.message).to match(/color|fill|stroke/i)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "passes validation for documents with only allowed colors" do
|
|
70
|
+
# Create a simple valid document for testing
|
|
71
|
+
valid_svg = <<~SVG
|
|
72
|
+
<?xml version="1.0"?>
|
|
73
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
74
|
+
<rect x="10" y="10" width="20" height="20" fill="black" stroke="white"/>
|
|
75
|
+
<circle cx="50" cy="50" r="10" fill="black"/>
|
|
76
|
+
<text x="10" y="80" fill="white">Test</text>
|
|
77
|
+
</svg>
|
|
78
|
+
SVG
|
|
79
|
+
|
|
80
|
+
document = SvgConform::Document.from_content(valid_svg)
|
|
81
|
+
requirement = described_class.new(
|
|
82
|
+
id: "color_restrictions",
|
|
83
|
+
description: "Test color restrictions requirement",
|
|
84
|
+
allowed_colors: %w[black white],
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
88
|
+
requirement.validate_document(document, context)
|
|
89
|
+
|
|
90
|
+
expect(context.errors).to be_empty
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
describe "configuration" do
|
|
96
|
+
it "accepts custom allowed colors list" do
|
|
97
|
+
requirement = described_class.new(
|
|
98
|
+
id: "test_color_restrictions",
|
|
99
|
+
description: "Test with custom colors",
|
|
100
|
+
allowed_colors: %w[red green blue],
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
expect(requirement.allowed_colors).to eq(%w[red green blue])
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "supports different modes" do
|
|
107
|
+
requirement = described_class.new(
|
|
108
|
+
id: "test_color_restrictions",
|
|
109
|
+
description: "Test mode",
|
|
110
|
+
mode: "custom_mode",
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
expect(requirement.mode).to eq("custom_mode")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "has default mode" do
|
|
117
|
+
requirement = described_class.new(
|
|
118
|
+
id: "test_color_restrictions",
|
|
119
|
+
description: "Test requirement",
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
expect(requirement.mode).to eq("black_white_only")
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
describe "color validation logic" do
|
|
127
|
+
let(:requirement) do
|
|
128
|
+
described_class.new(
|
|
129
|
+
id: "test_color_restrictions",
|
|
130
|
+
description: "Test color restrictions",
|
|
131
|
+
grayscale_only: true,
|
|
132
|
+
allowed_colors: %w[black white gray grey silver],
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "detects invalid colors in fill attributes" do
|
|
137
|
+
invalid_svg = <<~SVG
|
|
138
|
+
<?xml version="1.0"?>
|
|
139
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
140
|
+
<rect x="10" y="10" width="20" height="20" fill="red"/>
|
|
141
|
+
</svg>
|
|
142
|
+
SVG
|
|
143
|
+
|
|
144
|
+
document = SvgConform::Document.from_content(invalid_svg)
|
|
145
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
146
|
+
requirement.validate_document(document, context)
|
|
147
|
+
|
|
148
|
+
expect(context.errors).not_to be_empty
|
|
149
|
+
expect(context.errors.first.message).to match(/red/i)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "detects invalid colors in stroke attributes" do
|
|
153
|
+
invalid_svg = <<~SVG
|
|
154
|
+
<?xml version="1.0"?>
|
|
155
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
156
|
+
<rect x="10" y="10" width="20" height="20" stroke="blue"/>
|
|
157
|
+
</svg>
|
|
158
|
+
SVG
|
|
159
|
+
|
|
160
|
+
document = SvgConform::Document.from_content(invalid_svg)
|
|
161
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
162
|
+
requirement.validate_document(document, context)
|
|
163
|
+
|
|
164
|
+
expect(context.errors).not_to be_empty
|
|
165
|
+
expect(context.errors.first.message).to match(/blue/i)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require "canon"
|
|
5
|
+
|
|
6
|
+
RSpec.describe SvgConform::Requirements::FontFamilyRequirement do
|
|
7
|
+
let(:fixtures_dir) { "spec/fixtures/font_family" }
|
|
8
|
+
|
|
9
|
+
# Get all fixture files that have both input and expected repair versions
|
|
10
|
+
fixture_files = Dir.glob("spec/fixtures/font_family/inputs/*.svg").select do |input_file|
|
|
11
|
+
basename = File.basename(input_file)
|
|
12
|
+
File.exist?("spec/fixtures/font_family/repair/#{basename}")
|
|
13
|
+
end.map do |f|
|
|
14
|
+
File.basename(f, ".svg")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
fixture_files.each do |fixture_name|
|
|
18
|
+
describe "fixture: #{fixture_name}" do
|
|
19
|
+
let(:input_file) do
|
|
20
|
+
"spec/fixtures/font_family/inputs/#{fixture_name}.svg"
|
|
21
|
+
end
|
|
22
|
+
let(:expected_output_file) do
|
|
23
|
+
"spec/fixtures/font_family/repair/#{fixture_name}.svg"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "validates input file and identifies font family violations" do
|
|
27
|
+
skip "Input file not found" unless File.exist?(input_file)
|
|
28
|
+
|
|
29
|
+
document = SvgConform::Document.from_file(input_file)
|
|
30
|
+
requirement = described_class.new(
|
|
31
|
+
id: "font_family",
|
|
32
|
+
description: "Test font family requirement",
|
|
33
|
+
allowed_families: %w[serif sans-serif monospace],
|
|
34
|
+
default_family: "sans-serif",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
38
|
+
requirement.validate_document(document, context)
|
|
39
|
+
|
|
40
|
+
expect(context.errors).not_to be_empty
|
|
41
|
+
puts "Found #{context.errors.count} font family violations in #{fixture_name}"
|
|
42
|
+
|
|
43
|
+
context.errors.each do |error|
|
|
44
|
+
expect(error.requirement_id).to eq("font_family")
|
|
45
|
+
expect(error.message).to be_a(String)
|
|
46
|
+
expect(error.message).not_to be_empty
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "correctly identifies specific font family violations" do
|
|
51
|
+
skip "Input file not found" unless File.exist?(input_file)
|
|
52
|
+
|
|
53
|
+
document = SvgConform::Document.from_file(input_file)
|
|
54
|
+
requirement = described_class.new(
|
|
55
|
+
id: "font_family",
|
|
56
|
+
description: "Test font family requirement",
|
|
57
|
+
allowed_families: %w[serif sans-serif monospace],
|
|
58
|
+
default_family: "sans-serif",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
62
|
+
requirement.validate_document(document, context)
|
|
63
|
+
|
|
64
|
+
# Check that errors are specific to invalid font families
|
|
65
|
+
context.errors.each do |error|
|
|
66
|
+
expect(error.message).to match(/font.*family|Invalid font family/i)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "passes validation for documents with only allowed font families" do
|
|
71
|
+
# Create a simple valid document for testing
|
|
72
|
+
valid_svg = <<~SVG
|
|
73
|
+
<?xml version="1.0"?>
|
|
74
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
75
|
+
<text x="10" y="20" font-family="serif">Serif Text</text>
|
|
76
|
+
<text x="10" y="40" font-family="sans-serif">Sans Serif Text</text>
|
|
77
|
+
<text x="10" y="60" font-family="monospace">Monospace Text</text>
|
|
78
|
+
</svg>
|
|
79
|
+
SVG
|
|
80
|
+
|
|
81
|
+
document = SvgConform::Document.from_content(valid_svg)
|
|
82
|
+
requirement = described_class.new(
|
|
83
|
+
id: "font_family",
|
|
84
|
+
description: "Test font family requirement",
|
|
85
|
+
allowed_families: %w[serif sans-serif monospace],
|
|
86
|
+
default_family: "sans-serif",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
90
|
+
requirement.validate_document(document, context)
|
|
91
|
+
|
|
92
|
+
expect(context.errors).to be_empty
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe "configuration" do
|
|
98
|
+
it "accepts custom allowed font families list" do
|
|
99
|
+
requirement = described_class.new(
|
|
100
|
+
id: "test_font_family",
|
|
101
|
+
description: "Test with custom font families",
|
|
102
|
+
allowed_families: %w[Arial Helvetica Times],
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
expect(requirement.allowed_families).to eq(%w[Arial Helvetica Times])
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "supports default fallback configuration" do
|
|
109
|
+
requirement = described_class.new(
|
|
110
|
+
id: "test_font_family",
|
|
111
|
+
description: "Test default fallback",
|
|
112
|
+
default_fallback: "serif",
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
expect(requirement.default_fallback).to eq("serif")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "has default allowed families" do
|
|
119
|
+
requirement = described_class.new(
|
|
120
|
+
id: "test_font_family",
|
|
121
|
+
description: "Test requirement",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
expect(requirement.allowed_families).to eq(%w[serif sans-serif monospace])
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
describe "font family validation logic" do
|
|
129
|
+
let(:requirement) do
|
|
130
|
+
described_class.new(
|
|
131
|
+
id: "test_font_family",
|
|
132
|
+
description: "Test font family requirement",
|
|
133
|
+
allowed_families: %w[serif sans-serif monospace],
|
|
134
|
+
default_family: "sans-serif",
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "detects invalid font families in font-family attributes" do
|
|
139
|
+
invalid_svg = <<~SVG
|
|
140
|
+
<?xml version="1.0"?>
|
|
141
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
142
|
+
<text x="10" y="20" font-family="Times New Roman">Invalid Font</text>
|
|
143
|
+
</svg>
|
|
144
|
+
SVG
|
|
145
|
+
|
|
146
|
+
document = SvgConform::Document.from_content(invalid_svg)
|
|
147
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
148
|
+
requirement.validate_document(document, context)
|
|
149
|
+
|
|
150
|
+
expect(context.errors).not_to be_empty
|
|
151
|
+
expect(context.errors.first.message).to match(/Times New Roman/i)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "does not check style attributes (handled by StylePromotionRequirement to avoid duplication)" do
|
|
155
|
+
# FontFamilyRequirement only checks font-family attributes
|
|
156
|
+
# Style properties are handled by StylePromotionRequirement
|
|
157
|
+
svg_with_style = <<~SVG
|
|
158
|
+
<?xml version="1.0"?>
|
|
159
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
160
|
+
<text x="10" y="20" style="font-family: Arial">Font in Style</text>
|
|
161
|
+
</svg>
|
|
162
|
+
SVG
|
|
163
|
+
|
|
164
|
+
document = SvgConform::Document.from_content(svg_with_style)
|
|
165
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
166
|
+
requirement.validate_document(document, context)
|
|
167
|
+
|
|
168
|
+
# Should not detect errors in style attributes (that's StylePromotionRequirement's job)
|
|
169
|
+
expect(context.errors).to be_empty
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it "handles font family lists correctly" do
|
|
173
|
+
invalid_svg = <<~SVG
|
|
174
|
+
<?xml version="1.0"?>
|
|
175
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
176
|
+
<text x="10" y="20" font-family="Arial, sans-serif">Mixed Font List</text>
|
|
177
|
+
</svg>
|
|
178
|
+
SVG
|
|
179
|
+
|
|
180
|
+
document = SvgConform::Document.from_content(invalid_svg)
|
|
181
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
182
|
+
requirement.validate_document(document, context)
|
|
183
|
+
|
|
184
|
+
expect(context.errors).not_to be_empty
|
|
185
|
+
expect(context.errors.first.message).to match(/Arial/i)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require "canon"
|
|
5
|
+
|
|
6
|
+
RSpec.describe SvgConform::Requirements::ForbiddenContentRequirement do
|
|
7
|
+
let(:fixtures_dir) { "spec/fixtures/forbidden_content" }
|
|
8
|
+
|
|
9
|
+
# Get all fixture files that have both input and expected repair versions
|
|
10
|
+
fixture_files = Dir.glob("spec/fixtures/forbidden_content/inputs/*.svg").select do |input_file|
|
|
11
|
+
basename = File.basename(input_file)
|
|
12
|
+
File.exist?("spec/fixtures/forbidden_content/repair/#{basename}")
|
|
13
|
+
end.map do |f|
|
|
14
|
+
File.basename(f, ".svg")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
fixture_files.each do |fixture_name|
|
|
18
|
+
describe "fixture: #{fixture_name}" do
|
|
19
|
+
let(:input_file) do
|
|
20
|
+
"spec/fixtures/forbidden_content/inputs/#{fixture_name}.svg"
|
|
21
|
+
end
|
|
22
|
+
let(:expected_output_file) do
|
|
23
|
+
"spec/fixtures/forbidden_content/repair/#{fixture_name}.svg"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "validates input file and identifies forbidden content violations" do
|
|
27
|
+
skip "Input file not found" unless File.exist?(input_file)
|
|
28
|
+
|
|
29
|
+
document = SvgConform::Document.from_file(input_file)
|
|
30
|
+
requirement = described_class.new(
|
|
31
|
+
id: "forbidden_content",
|
|
32
|
+
description: "Test forbidden content requirement",
|
|
33
|
+
forbidden_elements: %w[script audio video animate animateColor],
|
|
34
|
+
forbidden_attributes: %w[onclick onmouseover onload onerror],
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
38
|
+
requirement.validate_document(document, context)
|
|
39
|
+
|
|
40
|
+
expect(context.errors).not_to be_empty
|
|
41
|
+
puts "Found #{context.errors.count} forbidden content violations in #{fixture_name}"
|
|
42
|
+
|
|
43
|
+
context.errors.each do |error|
|
|
44
|
+
expect(error.requirement_id).to eq("forbidden_content")
|
|
45
|
+
expect(error.message).to be_a(String)
|
|
46
|
+
expect(error.message).not_to be_empty
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "correctly identifies specific forbidden content violations" do
|
|
51
|
+
skip "Input file not found" unless File.exist?(input_file)
|
|
52
|
+
|
|
53
|
+
document = SvgConform::Document.from_file(input_file)
|
|
54
|
+
requirement = described_class.new(
|
|
55
|
+
id: "forbidden_content",
|
|
56
|
+
description: "Test forbidden content requirement",
|
|
57
|
+
forbidden_elements: %w[script audio video animate animateColor],
|
|
58
|
+
forbidden_attributes: %w[onclick onmouseover onload onerror],
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
62
|
+
requirement.validate_document(document, context)
|
|
63
|
+
|
|
64
|
+
# Check that errors are specific to forbidden elements or attributes
|
|
65
|
+
context.errors.each do |error|
|
|
66
|
+
expect(error.message).to match(/Forbidden.*element|Forbidden.*attribute/i)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "passes validation for documents without forbidden content" do
|
|
71
|
+
# Create a simple valid document for testing
|
|
72
|
+
valid_svg = <<~SVG
|
|
73
|
+
<?xml version="1.0"?>
|
|
74
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
75
|
+
<g>
|
|
76
|
+
<rect x="10" y="10" width="20" height="20" fill="black"/>
|
|
77
|
+
<circle cx="50" cy="50" r="10" fill="black"/>
|
|
78
|
+
<text x="10" y="80">Safe Content</text>
|
|
79
|
+
</g>
|
|
80
|
+
</svg>
|
|
81
|
+
SVG
|
|
82
|
+
|
|
83
|
+
document = SvgConform::Document.from_content(valid_svg)
|
|
84
|
+
requirement = described_class.new(
|
|
85
|
+
id: "forbidden_content",
|
|
86
|
+
description: "Test forbidden content requirement",
|
|
87
|
+
forbidden_elements: %w[script audio video animate animateColor],
|
|
88
|
+
forbidden_attributes: %w[onclick onmouseover onload onerror],
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
92
|
+
requirement.validate_document(document, context)
|
|
93
|
+
|
|
94
|
+
expect(context.errors).to be_empty
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe "configuration" do
|
|
100
|
+
it "accepts custom forbidden elements list" do
|
|
101
|
+
requirement = described_class.new(
|
|
102
|
+
id: "test_forbidden_content",
|
|
103
|
+
description: "Test with custom forbidden elements",
|
|
104
|
+
forbidden_elements: %w[script iframe embed],
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
expect(requirement.forbidden_elements).to eq(%w[script iframe embed])
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "accepts custom forbidden attributes list" do
|
|
111
|
+
requirement = described_class.new(
|
|
112
|
+
id: "test_forbidden_content",
|
|
113
|
+
description: "Test with custom forbidden attributes",
|
|
114
|
+
forbidden_attributes: %w[onclick onload href],
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
expect(requirement.forbidden_attributes).to eq(%w[onclick onload href])
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "can be instantiated with basic parameters" do
|
|
121
|
+
requirement = described_class.new(
|
|
122
|
+
id: "test_forbidden_content",
|
|
123
|
+
description: "Test requirement",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
expect(requirement).to be_a(described_class)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe "forbidden content validation logic" do
|
|
131
|
+
let(:requirement) do
|
|
132
|
+
described_class.new(
|
|
133
|
+
id: "test_forbidden_content",
|
|
134
|
+
description: "Test forbidden content requirement",
|
|
135
|
+
forbidden_elements: %w[script audio video],
|
|
136
|
+
forbidden_attributes: %w[onclick onmouseover],
|
|
137
|
+
)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "detects forbidden elements" do
|
|
141
|
+
invalid_svg = <<~SVG
|
|
142
|
+
<?xml version="1.0"?>
|
|
143
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
144
|
+
<script>alert('forbidden');</script>
|
|
145
|
+
<rect x="10" y="10" width="20" height="20"/>
|
|
146
|
+
</svg>
|
|
147
|
+
SVG
|
|
148
|
+
|
|
149
|
+
document = SvgConform::Document.from_content(invalid_svg)
|
|
150
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
151
|
+
requirement.validate_document(document, context)
|
|
152
|
+
|
|
153
|
+
expect(context.errors).not_to be_empty
|
|
154
|
+
expect(context.errors.first.message).to match(/script/i)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it "detects forbidden attributes" do
|
|
158
|
+
invalid_svg = <<~SVG
|
|
159
|
+
<?xml version="1.0"?>
|
|
160
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
161
|
+
<rect x="10" y="10" width="20" height="20" onclick="handleClick()"/>
|
|
162
|
+
</svg>
|
|
163
|
+
SVG
|
|
164
|
+
|
|
165
|
+
document = SvgConform::Document.from_content(invalid_svg)
|
|
166
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
167
|
+
requirement.validate_document(document, context)
|
|
168
|
+
|
|
169
|
+
expect(context.errors).not_to be_empty
|
|
170
|
+
expect(context.errors.first.message).to match(/onclick/i)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it "detects multiple forbidden items in one document" do
|
|
174
|
+
invalid_svg = <<~SVG
|
|
175
|
+
<?xml version="1.0"?>
|
|
176
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
177
|
+
<script>alert('forbidden');</script>
|
|
178
|
+
<audio src="sound.mp3"/>
|
|
179
|
+
<rect x="10" y="10" width="20" height="20" onclick="handleClick()" onmouseover="hover()"/>
|
|
180
|
+
</svg>
|
|
181
|
+
SVG
|
|
182
|
+
|
|
183
|
+
document = SvgConform::Document.from_content(invalid_svg)
|
|
184
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
185
|
+
requirement.validate_document(document, context)
|
|
186
|
+
|
|
187
|
+
expect(context.errors.count).to be >= 4 # script, audio, onclick, onmouseover
|
|
188
|
+
forbidden_items = context.errors.map(&:message).join(" ")
|
|
189
|
+
expect(forbidden_items).to match(/script/i)
|
|
190
|
+
expect(forbidden_items).to match(/audio/i)
|
|
191
|
+
expect(forbidden_items).to match(/onclick/i)
|
|
192
|
+
expect(forbidden_items).to match(/onmouseover/i)
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require "canon"
|
|
5
|
+
|
|
6
|
+
RSpec.describe SvgConform::Requirements::IdReferenceRequirement do
|
|
7
|
+
let(:fixtures_dir) { "spec/fixtures/id_reference" }
|
|
8
|
+
|
|
9
|
+
# Get all fixture files that have both input and expected repair versions
|
|
10
|
+
fixture_files = Dir.glob("spec/fixtures/id_reference/inputs/*.svg").select do |input_file|
|
|
11
|
+
basename = File.basename(input_file)
|
|
12
|
+
File.exist?("spec/fixtures/id_reference/repair/#{basename}")
|
|
13
|
+
end.map do |f|
|
|
14
|
+
File.basename(f, ".svg")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
fixture_files.each do |fixture_name|
|
|
18
|
+
describe "fixture: #{fixture_name}" do
|
|
19
|
+
let(:input_file) do
|
|
20
|
+
"spec/fixtures/id_reference/inputs/#{fixture_name}.svg"
|
|
21
|
+
end
|
|
22
|
+
let(:expected_output_file) do
|
|
23
|
+
"spec/fixtures/id_reference/repair/#{fixture_name}.svg"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "validates input file and identifies violations" do
|
|
27
|
+
skip "Input file not found" unless File.exist?(input_file)
|
|
28
|
+
|
|
29
|
+
document = SvgConform::Document.from_file(input_file)
|
|
30
|
+
requirement = described_class.new(
|
|
31
|
+
id: "id_reference",
|
|
32
|
+
description: "Test id reference requirement",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
36
|
+
requirement.validate_document(document, context)
|
|
37
|
+
|
|
38
|
+
expect(context.errors).not_to be_empty
|
|
39
|
+
puts "Found #{context.errors.count} id reference violations in #{fixture_name}"
|
|
40
|
+
|
|
41
|
+
context.errors.each do |error|
|
|
42
|
+
expect(error.requirement_id).to eq("id_reference")
|
|
43
|
+
expect(error.message).to be_a(String)
|
|
44
|
+
expect(error.message).not_to be_empty
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "correctly identifies specific violations" do
|
|
49
|
+
skip "Input file not found" unless File.exist?(input_file)
|
|
50
|
+
|
|
51
|
+
document = SvgConform::Document.from_file(input_file)
|
|
52
|
+
requirement = described_class.new(
|
|
53
|
+
id: "id_reference",
|
|
54
|
+
description: "Test id reference requirement",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
context = SvgConform::ValidationContext.new(document, nil)
|
|
58
|
+
requirement.validate_document(document, context)
|
|
59
|
+
|
|
60
|
+
# Check that errors are relevant to this requirement
|
|
61
|
+
context.errors.each do |error|
|
|
62
|
+
expect(error.message).not_to be_empty
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe "configuration" do
|
|
69
|
+
it "can be instantiated with basic parameters" do
|
|
70
|
+
requirement = described_class.new(
|
|
71
|
+
id: "test_id_reference",
|
|
72
|
+
description: "Test requirement",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
expect(requirement).to be_a(described_class)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|