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
data/examples/demo.rb
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Demo script showing SvgConform capabilities
|
|
5
|
+
require_relative "../lib/svg_conform"
|
|
6
|
+
|
|
7
|
+
puts "SvgConform Demo"
|
|
8
|
+
puts "=" * 50
|
|
9
|
+
|
|
10
|
+
# Test with actual fixture files
|
|
11
|
+
fixtures_dir = File.join(__dir__, "..", "spec", "fixtures", "svgcheck",
|
|
12
|
+
"inputs")
|
|
13
|
+
test_files = ["viewBox-height.svg", "colors.svg", "IETF-test.svg", "good.svg"]
|
|
14
|
+
|
|
15
|
+
validator = SvgConform::Validator.new
|
|
16
|
+
|
|
17
|
+
# Show available profiles
|
|
18
|
+
puts "\n1. Available Profiles:"
|
|
19
|
+
puts "-" * 30
|
|
20
|
+
|
|
21
|
+
SvgConform::Profiles.available_profiles.each do |name|
|
|
22
|
+
profile = SvgConform::Profiles.get(name)
|
|
23
|
+
puts "#{name}: #{profile.description} (#{profile.requirement_count} requirements, #{profile.remediation_count} remediations)"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Test each profile with sample files
|
|
27
|
+
test_files.each do |filename|
|
|
28
|
+
file_path = File.join(fixtures_dir, filename)
|
|
29
|
+
next unless File.exist?(file_path)
|
|
30
|
+
|
|
31
|
+
puts "\n#{'=' * 60}"
|
|
32
|
+
puts "Testing file: #{filename}"
|
|
33
|
+
puts "=" * 60
|
|
34
|
+
|
|
35
|
+
# Read and display the SVG content
|
|
36
|
+
svg_content = File.read(file_path)
|
|
37
|
+
puts "\nSVG Content:"
|
|
38
|
+
puts svg_content
|
|
39
|
+
puts
|
|
40
|
+
|
|
41
|
+
# Test each profile
|
|
42
|
+
SvgConform::Profiles.available_profiles.each do |profile_name|
|
|
43
|
+
puts "\n#{profile_name.to_s.upcase} Profile Results:"
|
|
44
|
+
puts "-" * 40
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
result = validator.validate_file(file_path, profile: profile_name)
|
|
48
|
+
|
|
49
|
+
puts "Status: #{result.valid? ? 'VALID ✓' : 'INVALID ✗'}"
|
|
50
|
+
puts "Errors: #{result.error_count}"
|
|
51
|
+
puts "Warnings: #{result.warning_count}"
|
|
52
|
+
|
|
53
|
+
if result.has_errors?
|
|
54
|
+
puts "\nErrors:"
|
|
55
|
+
result.errors.each_with_index do |error, i|
|
|
56
|
+
puts " #{i + 1}. #{error.message} (#{error.requirement_id})"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if result.has_warnings?
|
|
61
|
+
puts "\nWarnings:"
|
|
62
|
+
result.warnings.each_with_index do |warning, i|
|
|
63
|
+
puts " #{i + 1}. #{warning.message} (#{warning.requirement_id})"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Test remediation if available
|
|
68
|
+
if result.fixable?
|
|
69
|
+
puts "\nApplying fixes (#{result.fixable_count} available)..."
|
|
70
|
+
|
|
71
|
+
# Apply fixes using the ValidationResult's built-in fix method
|
|
72
|
+
result.apply_fixes
|
|
73
|
+
|
|
74
|
+
if result.fixed?
|
|
75
|
+
puts "✓ Fixes applied successfully!"
|
|
76
|
+
puts "Fixed SVG preview (first 200 chars):"
|
|
77
|
+
fixed_content = result.fixed_document.to_xml
|
|
78
|
+
puts fixed_content[0..200] + (fixed_content.length > 200 ? "..." : "")
|
|
79
|
+
|
|
80
|
+
# Re-validate the fixed document
|
|
81
|
+
fixed_result = validator.validate(fixed_content,
|
|
82
|
+
profile: profile_name)
|
|
83
|
+
puts "\nRe-validation: #{fixed_result.valid? ? 'VALID ✓' : 'INVALID ✗'}"
|
|
84
|
+
puts "Remaining errors: #{fixed_result.error_count}"
|
|
85
|
+
else
|
|
86
|
+
puts "✗ Could not apply fixes"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
rescue StandardError => e
|
|
90
|
+
puts "ERROR: #{e.message}"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Performance test
|
|
96
|
+
puts "\n#{'=' * 60}"
|
|
97
|
+
puts "Performance Test"
|
|
98
|
+
puts "=" * 60
|
|
99
|
+
|
|
100
|
+
require "benchmark"
|
|
101
|
+
test_file = File.join(fixtures_dir, "good.svg")
|
|
102
|
+
|
|
103
|
+
if File.exist?(test_file)
|
|
104
|
+
time = Benchmark.realtime do
|
|
105
|
+
100.times do
|
|
106
|
+
validator.validate_file(test_file, profile: :svg_1_2_rfc)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
puts "Validated #{test_file} 100 times in #{time.round(3)} seconds"
|
|
111
|
+
puts "Average: #{(time * 1000 / 100).round(2)}ms per validation"
|
|
112
|
+
else
|
|
113
|
+
puts "Performance test skipped - test file not found"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
puts "\nDemo completed!"
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../lib/svg_conform"
|
|
5
|
+
|
|
6
|
+
# Demo script showing the new requirements and remediations system
|
|
7
|
+
class RequirementsDemo
|
|
8
|
+
def run
|
|
9
|
+
puts "=== SvgConform Requirements & Remediations Demo ==="
|
|
10
|
+
puts
|
|
11
|
+
|
|
12
|
+
# Demo 1: Load profile from YAML
|
|
13
|
+
demo_yaml_profile_loading
|
|
14
|
+
|
|
15
|
+
# Demo 2: Validate with requirements
|
|
16
|
+
demo_requirements_validation
|
|
17
|
+
|
|
18
|
+
# Demo 3: Apply remediations
|
|
19
|
+
demo_remediations
|
|
20
|
+
|
|
21
|
+
# Demo 4: Lucid fix scenario
|
|
22
|
+
demo_lucid_fix
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def demo_yaml_profile_loading
|
|
28
|
+
puts "1. Loading Profiles from YAML Configuration"
|
|
29
|
+
puts "=" * 50
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
# Load IETF profile from YAML
|
|
33
|
+
svg_1_2_rfc_profile = SvgConform::ProfileRegistry.load_profile("svg_1_2_rfc")
|
|
34
|
+
puts "✓ Loaded IETF profile: #{svg_1_2_rfc_profile.name}"
|
|
35
|
+
puts " Description: #{svg_1_2_rfc_profile.description}"
|
|
36
|
+
puts " Requirements: #{svg_1_2_rfc_profile.requirement_count}"
|
|
37
|
+
puts " Remediations: #{svg_1_2_rfc_profile.remediation_count}"
|
|
38
|
+
puts
|
|
39
|
+
|
|
40
|
+
# Load Lucid fix profile
|
|
41
|
+
lucid_profile = SvgConform::ProfileRegistry.load_profile("lucid_fix")
|
|
42
|
+
puts "✓ Loaded Lucid Fix profile: #{lucid_profile.name}"
|
|
43
|
+
puts " Description: #{lucid_profile.description}"
|
|
44
|
+
puts " Requirements: #{lucid_profile.requirement_count}"
|
|
45
|
+
puts " Remediations: #{lucid_profile.remediation_count}"
|
|
46
|
+
puts
|
|
47
|
+
|
|
48
|
+
# List available profiles
|
|
49
|
+
available = SvgConform::ProfileRegistry.available_profiles
|
|
50
|
+
puts "Available profiles: #{available.join(', ')}"
|
|
51
|
+
puts
|
|
52
|
+
rescue StandardError => e
|
|
53
|
+
puts "✗ Error loading profiles: #{e.message}"
|
|
54
|
+
puts " This is expected if the requirement classes don't exist yet"
|
|
55
|
+
puts
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def demo_requirements_validation
|
|
60
|
+
puts "2. Requirements-based Validation"
|
|
61
|
+
puts "=" * 50
|
|
62
|
+
|
|
63
|
+
# Create a test SVG with invalid use element
|
|
64
|
+
invalid_svg = <<~SVG
|
|
65
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
66
|
+
<defs>
|
|
67
|
+
<circle id="valid-circle" cx="10" cy="10" r="5"/>
|
|
68
|
+
</defs>
|
|
69
|
+
<use href="#invalid-id"/>
|
|
70
|
+
<use href="#valid-circle"/>
|
|
71
|
+
<rect fill="red" width="50" height="50"/>
|
|
72
|
+
</svg>
|
|
73
|
+
SVG
|
|
74
|
+
|
|
75
|
+
puts "Test SVG with invalid use element:"
|
|
76
|
+
puts invalid_svg
|
|
77
|
+
puts
|
|
78
|
+
|
|
79
|
+
# Create a simple profile with requirements
|
|
80
|
+
profile = SvgConform::Profile.new(:test_requirements,
|
|
81
|
+
"Test Requirements Profile")
|
|
82
|
+
|
|
83
|
+
begin
|
|
84
|
+
# Add invalid ID references requirement
|
|
85
|
+
requirement = SvgConform::Requirements::InvalidIdReferencesRequirement.new
|
|
86
|
+
profile.add_requirement(requirement)
|
|
87
|
+
|
|
88
|
+
# Validate
|
|
89
|
+
document = SvgConform::Document.new(invalid_svg)
|
|
90
|
+
result = profile.validate(document)
|
|
91
|
+
|
|
92
|
+
puts "Validation Results:"
|
|
93
|
+
puts " Valid: #{result.valid?}"
|
|
94
|
+
puts " Errors: #{result.error_count}"
|
|
95
|
+
puts " Warnings: #{result.warning_count}"
|
|
96
|
+
puts
|
|
97
|
+
|
|
98
|
+
if result.errors.any?
|
|
99
|
+
puts "Errors found:"
|
|
100
|
+
result.errors.each_with_index do |error, i|
|
|
101
|
+
puts " #{i + 1}. #{error.message}"
|
|
102
|
+
puts " Node: #{error.node.name}" if error.node
|
|
103
|
+
puts " Data: #{error.data}" if error.data.any?
|
|
104
|
+
end
|
|
105
|
+
puts
|
|
106
|
+
end
|
|
107
|
+
rescue StandardError => e
|
|
108
|
+
puts "✗ Error during validation: #{e.message}"
|
|
109
|
+
puts " This is expected if the requirement classes don't exist yet"
|
|
110
|
+
puts
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def demo_remediations
|
|
115
|
+
puts "3. Applying Remediations"
|
|
116
|
+
puts "=" * 50
|
|
117
|
+
|
|
118
|
+
# Create test SVG with issues
|
|
119
|
+
problematic_svg = <<~SVG
|
|
120
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
|
121
|
+
<defs>
|
|
122
|
+
<circle id="circle1" cx="10" cy="10" r="5"/>
|
|
123
|
+
</defs>
|
|
124
|
+
<use href="#missing-id"/>
|
|
125
|
+
<use href="#circle1"/>
|
|
126
|
+
<use href="#another-missing"/>
|
|
127
|
+
</svg>
|
|
128
|
+
SVG
|
|
129
|
+
|
|
130
|
+
puts "Original SVG with invalid use elements:"
|
|
131
|
+
puts problematic_svg
|
|
132
|
+
puts
|
|
133
|
+
|
|
134
|
+
begin
|
|
135
|
+
# Create profile with requirements and remediations
|
|
136
|
+
profile = SvgConform::Profile.new(:test_remediations,
|
|
137
|
+
"Test Remediations Profile")
|
|
138
|
+
|
|
139
|
+
# Add requirement
|
|
140
|
+
requirement = SvgConform::Requirements::InvalidIdReferencesRequirement.new
|
|
141
|
+
profile.add_requirement(requirement)
|
|
142
|
+
|
|
143
|
+
# Add remediation
|
|
144
|
+
remediation = SvgConform::Remediations::InvalidIdReferencesRemediation.new
|
|
145
|
+
profile.add_remediation(remediation)
|
|
146
|
+
|
|
147
|
+
# Validate first
|
|
148
|
+
document = SvgConform::Document.new(problematic_svg)
|
|
149
|
+
result = profile.validate(document)
|
|
150
|
+
|
|
151
|
+
puts "Validation found #{result.error_count} errors"
|
|
152
|
+
|
|
153
|
+
if result.errors.any?
|
|
154
|
+
# Debug: Show requirement IDs
|
|
155
|
+
puts "Failed requirement IDs: #{result.failed_requirements.map(&:requirement_id)}"
|
|
156
|
+
puts "Available remediations: #{profile.remediations.map do |r|
|
|
157
|
+
"#{r.id} (targets: #{r.target_requirements})"
|
|
158
|
+
end}"
|
|
159
|
+
puts
|
|
160
|
+
|
|
161
|
+
# Apply remediations
|
|
162
|
+
engine = SvgConform::RemediationEngine.new(profile)
|
|
163
|
+
remediation_results = engine.apply_remediations(document, result)
|
|
164
|
+
|
|
165
|
+
puts "Applied #{remediation_results.size} remediations"
|
|
166
|
+
puts "Summary: #{engine.summary}"
|
|
167
|
+
puts
|
|
168
|
+
|
|
169
|
+
puts "Fixed SVG:"
|
|
170
|
+
puts document.to_xml
|
|
171
|
+
puts
|
|
172
|
+
end
|
|
173
|
+
rescue StandardError => e
|
|
174
|
+
puts "✗ Error during remediation: #{e.message}"
|
|
175
|
+
puts " This is expected if the remediation classes don't exist yet"
|
|
176
|
+
puts
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def demo_lucid_fix
|
|
181
|
+
puts "4. Lucid SVG Fix Scenario"
|
|
182
|
+
puts "=" * 50
|
|
183
|
+
|
|
184
|
+
# Simulate a Lucid-generated SVG with invalid use elements
|
|
185
|
+
lucid_svg = <<~SVG
|
|
186
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 100">
|
|
187
|
+
<defs>
|
|
188
|
+
<g id="shape1">
|
|
189
|
+
<rect width="20" height="20" fill="blue"/>
|
|
190
|
+
</g>
|
|
191
|
+
</defs>
|
|
192
|
+
<g>
|
|
193
|
+
<use xlink:href="#shape1" x="10" y="10"/>
|
|
194
|
+
<use xlink:href="#nonexistent1" x="50" y="10"/>
|
|
195
|
+
<use xlink:href="#nonexistent2" x="90" y="10"/>
|
|
196
|
+
<text x="10" y="50">Valid content</text>
|
|
197
|
+
</g>
|
|
198
|
+
</svg>
|
|
199
|
+
SVG
|
|
200
|
+
|
|
201
|
+
puts "Lucid-style SVG with invalid use elements:"
|
|
202
|
+
puts lucid_svg
|
|
203
|
+
puts
|
|
204
|
+
|
|
205
|
+
begin
|
|
206
|
+
# Load the Lucid fix profile
|
|
207
|
+
profile = SvgConform::ProfileRegistry.load_profile("lucid_fix")
|
|
208
|
+
|
|
209
|
+
# Process the SVG
|
|
210
|
+
document = SvgConform::Document.new(lucid_svg)
|
|
211
|
+
result = profile.validate(document)
|
|
212
|
+
|
|
213
|
+
puts "Found #{result.error_count} invalid use elements"
|
|
214
|
+
|
|
215
|
+
if result.errors.any?
|
|
216
|
+
# Apply the Lucid fix
|
|
217
|
+
engine = SvgConform::RemediationEngine.new(profile)
|
|
218
|
+
engine.apply_remediations(document, result)
|
|
219
|
+
|
|
220
|
+
puts "Applied Lucid fix remediations"
|
|
221
|
+
puts "Summary: #{engine.summary}"
|
|
222
|
+
puts
|
|
223
|
+
|
|
224
|
+
puts "Fixed SVG (invalid use elements removed):"
|
|
225
|
+
puts document.to_xml
|
|
226
|
+
puts
|
|
227
|
+
end
|
|
228
|
+
rescue StandardError => e
|
|
229
|
+
puts "✗ Error during Lucid fix: #{e.message}"
|
|
230
|
+
puts " This is expected if the profile/classes don't exist yet"
|
|
231
|
+
puts
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Run the demo
|
|
237
|
+
if __FILE__ == $PROGRAM_NAME
|
|
238
|
+
demo = RequirementsDemo.new
|
|
239
|
+
demo.run
|
|
240
|
+
end
|
data/exe/svg_conform
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module SvgConform
|
|
6
|
+
# Result for a single file in batch processing
|
|
7
|
+
class FileResult < Lutaml::Model::Serializable
|
|
8
|
+
attribute :filename, :string
|
|
9
|
+
attribute :original_path, :string
|
|
10
|
+
attribute :valid_before, :boolean
|
|
11
|
+
attribute :valid_after, :boolean
|
|
12
|
+
attribute :errors_before, :integer
|
|
13
|
+
attribute :errors_after, :integer
|
|
14
|
+
attribute :remediated_path, :string
|
|
15
|
+
attribute :status, :string # "valid", "remediated", "failed", "error"
|
|
16
|
+
attribute :error_message, :string
|
|
17
|
+
|
|
18
|
+
yaml do
|
|
19
|
+
map "filename", to: :filename
|
|
20
|
+
map "original_path", to: :original_path
|
|
21
|
+
map "valid_before", to: :valid_before
|
|
22
|
+
map "valid_after", to: :valid_after
|
|
23
|
+
map "errors_before", to: :errors_before
|
|
24
|
+
map "errors_after", to: :errors_after
|
|
25
|
+
map "remediated_path", to: :remediated_path
|
|
26
|
+
map "status", to: :status
|
|
27
|
+
map "error_message", to: :error_message
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Batch validation/remediation report
|
|
32
|
+
class BatchReport < Lutaml::Model::Serializable
|
|
33
|
+
attribute :directory, :string
|
|
34
|
+
attribute :profile, :string
|
|
35
|
+
attribute :timestamp, :string, default: -> { Time.now.iso8601 }
|
|
36
|
+
attribute :total_files, :integer
|
|
37
|
+
attribute :valid_before, :integer
|
|
38
|
+
attribute :valid_after, :integer
|
|
39
|
+
attribute :remediated, :integer
|
|
40
|
+
attribute :failed, :integer
|
|
41
|
+
attribute :success_rate, :float
|
|
42
|
+
attribute :files, FileResult, collection: true, default: []
|
|
43
|
+
attribute :manifest, :hash, default: {}
|
|
44
|
+
|
|
45
|
+
yaml do
|
|
46
|
+
map "directory", to: :directory
|
|
47
|
+
map "profile", to: :profile
|
|
48
|
+
map "timestamp", to: :timestamp
|
|
49
|
+
map "total_files", to: :total_files
|
|
50
|
+
map "valid_before", to: :valid_before
|
|
51
|
+
map "valid_after", to: :valid_after
|
|
52
|
+
map "remediated", to: :remediated
|
|
53
|
+
map "failed", to: :failed
|
|
54
|
+
map "success_rate", to: :success_rate
|
|
55
|
+
map "files", to: :files
|
|
56
|
+
map "manifest", to: :manifest
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def calculate_statistics
|
|
60
|
+
self.total_files = files.length
|
|
61
|
+
self.valid_before = files.count(&:valid_before)
|
|
62
|
+
self.valid_after = files.count(&:valid_after)
|
|
63
|
+
self.remediated = files.count { |f| f.status == "remediated" }
|
|
64
|
+
self.failed = files.count do |f|
|
|
65
|
+
["failed", "error"].include?(f.status)
|
|
66
|
+
end
|
|
67
|
+
self.success_rate = total_files.zero? ? 0.0 : (valid_after.to_f / total_files * 100).round(1)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "thor"
|
|
4
|
+
require "json"
|
|
5
|
+
require "yaml"
|
|
6
|
+
require "paint"
|
|
7
|
+
require_relative "commands/check"
|
|
8
|
+
require_relative "commands/svgcheck"
|
|
9
|
+
require_relative "commands/profiles"
|
|
10
|
+
|
|
11
|
+
module SvgConform
|
|
12
|
+
# Thor-based CLI for SvgConform with svgcheck-like functionality
|
|
13
|
+
class Cli < Thor
|
|
14
|
+
def initialize(*args)
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
desc "check [*FILES]",
|
|
19
|
+
"Check SVG file(s) validity (single file, multiple files, or directory)"
|
|
20
|
+
long_desc <<~DESC
|
|
21
|
+
Check SVG file validity against a profile.
|
|
22
|
+
|
|
23
|
+
MODES:
|
|
24
|
+
1. Single file: svg_conform check file.svg -p PROFILE
|
|
25
|
+
2. Multiple files: svg_conform check *.svg -p PROFILE
|
|
26
|
+
3. Directory: svg_conform check --directory PATH -p PROFILE
|
|
27
|
+
|
|
28
|
+
By default, only validates without creating remediated files.
|
|
29
|
+
Use --fix to enable automatic remediation.
|
|
30
|
+
|
|
31
|
+
REMEDIATION OUTPUT:
|
|
32
|
+
- Single file: Uses --fix-output (default: FILE.fixed.svg)
|
|
33
|
+
- Multiple files: Requires --output-dir or --in-place
|
|
34
|
+
- Directory: Requires --output-dir or --in-place
|
|
35
|
+
|
|
36
|
+
REPORT FORMATS:
|
|
37
|
+
- table: Human-readable (default for single file)
|
|
38
|
+
- json: JSON format using lutaml-model
|
|
39
|
+
- yaml: YAML format using lutaml-model
|
|
40
|
+
|
|
41
|
+
EXAMPLES:
|
|
42
|
+
svg_conform check file.svg -p metanorma
|
|
43
|
+
svg_conform check *.svg -p metanorma -f --output-dir fixed/
|
|
44
|
+
svg_conform check -d images/ -p metanorma --report-format json --report-output report.json
|
|
45
|
+
svg_conform check -d images/ -p metanorma -f --in-place --force
|
|
46
|
+
DESC
|
|
47
|
+
option :directory, aliases: "-d", type: :string,
|
|
48
|
+
desc: "Directory to scan recursively for SVG files"
|
|
49
|
+
option :profile, aliases: "-p", default: "svg_1_2_rfc",
|
|
50
|
+
desc: "Profile to validate against"
|
|
51
|
+
option :format, default: "table", enum: %w[table yaml json],
|
|
52
|
+
desc: "Output format (single file mode)"
|
|
53
|
+
option :fix, aliases: "-f", type: :boolean, default: false,
|
|
54
|
+
desc: "Create remediated files"
|
|
55
|
+
option :output, aliases: "-o", desc: "Output file (single file mode)"
|
|
56
|
+
option :output_dir, type: :string,
|
|
57
|
+
desc: "Output directory for remediated files (multi-file mode)"
|
|
58
|
+
option :in_place, type: :boolean, default: false,
|
|
59
|
+
desc: "Replace original files (requires --force)"
|
|
60
|
+
option :force, type: :boolean, default: false,
|
|
61
|
+
desc: "Confirm destructive operations (required for --in-place)"
|
|
62
|
+
option :fix_output,
|
|
63
|
+
desc: "Output file for remediated SVG (single file mode, default: FILE.fixed.svg)"
|
|
64
|
+
option :report_format, enum: %w[json yaml],
|
|
65
|
+
desc: "Batch report format (json or yaml)"
|
|
66
|
+
option :report_output, type: :string,
|
|
67
|
+
desc: "Save detailed batch report to file"
|
|
68
|
+
option :manifest, type: :string,
|
|
69
|
+
desc: "Manifest file path (default: manifest.json with --fix)"
|
|
70
|
+
option :quiet, aliases: "-q", type: :boolean, default: false,
|
|
71
|
+
desc: "Suppress per-file output, show summary only"
|
|
72
|
+
option :verbose, aliases: "-v", type: :boolean, default: false,
|
|
73
|
+
desc: "Show detailed progress"
|
|
74
|
+
def check(*files)
|
|
75
|
+
SvgConform::Commands::Check.new(files, options).execute
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
desc "svgcheck SUBCOMMAND",
|
|
79
|
+
"Svgcheck-related commands (compare, compatibility, generate)"
|
|
80
|
+
subcommand "svgcheck", Commands::Svgcheck
|
|
81
|
+
|
|
82
|
+
desc "profiles", "List available validation profiles"
|
|
83
|
+
long_desc <<~DESC
|
|
84
|
+
List all available validation profiles with their descriptions
|
|
85
|
+
and requirements.
|
|
86
|
+
DESC
|
|
87
|
+
option :verbose, aliases: "-v", type: :boolean, default: false,
|
|
88
|
+
desc: "Show detailed information"
|
|
89
|
+
def profiles
|
|
90
|
+
SvgConform::Commands::Profiles.new(options).execute
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
desc "version", "Show version information"
|
|
94
|
+
def version
|
|
95
|
+
puts "SvgConform #{SvgConform::VERSION}"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def method_missing(method_name, *_args)
|
|
101
|
+
puts Paint["Unknown command: #{method_name}", :red]
|
|
102
|
+
puts
|
|
103
|
+
help
|
|
104
|
+
exit 1
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|