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.
Files changed (335) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/rake.yml +15 -0
  3. data/.github/workflows/release.yml +23 -0
  4. data/.github/workflows/svgcheck-compatibility.yml +135 -0
  5. data/.gitignore +12 -0
  6. data/.rspec +3 -0
  7. data/.rubocop.yml +13 -0
  8. data/.rubocop_todo.yml +183 -0
  9. data/CODE_OF_CONDUCT.md +132 -0
  10. data/Gemfile +14 -0
  11. data/README.adoc +1384 -0
  12. data/Rakefile +15 -0
  13. data/config/profiles/base.yml +34 -0
  14. data/config/profiles/lucid_fix.yml +37 -0
  15. data/config/profiles/metanorma.yml +212 -0
  16. data/config/profiles/no_external_css.yml +20 -0
  17. data/config/profiles/svg_1_2_rfc.yml +284 -0
  18. data/config/profiles/svg_1_2_rfc_with_rdf.yml +145 -0
  19. data/config/svgcheck_mapping.yml +180 -0
  20. data/docs/profiles.adoc +547 -0
  21. data/docs/rdf_metadata_support.adoc +212 -0
  22. data/docs/remediation.adoc +732 -0
  23. data/docs/requirements.adoc +709 -0
  24. data/examples/demo.rb +116 -0
  25. data/examples/requirements_demo.rb +240 -0
  26. data/exe/svg_conform +7 -0
  27. data/lib/svg_conform/batch_report.rb +70 -0
  28. data/lib/svg_conform/cli.rb +107 -0
  29. data/lib/svg_conform/commands/check.rb +390 -0
  30. data/lib/svg_conform/commands/profiles.rb +118 -0
  31. data/lib/svg_conform/commands/svgcheck.rb +90 -0
  32. data/lib/svg_conform/commands/svgcheck_compare.rb +92 -0
  33. data/lib/svg_conform/commands/svgcheck_compatibility.rb +43 -0
  34. data/lib/svg_conform/commands/svgcheck_generate.rb +262 -0
  35. data/lib/svg_conform/compatibility/analysis_context.rb +68 -0
  36. data/lib/svg_conform/compatibility/comparison_result.rb +147 -0
  37. data/lib/svg_conform/compatibility/compatibility_analyzer.rb +85 -0
  38. data/lib/svg_conform/compatibility/file_processor.rb +109 -0
  39. data/lib/svg_conform/compatibility/pattern_discovery.rb +319 -0
  40. data/lib/svg_conform/compatibility/report_formatter.rb +359 -0
  41. data/lib/svg_conform/compatibility/svg_analysis_engine.rb +316 -0
  42. data/lib/svg_conform/compatibility/validity_analysis.rb +252 -0
  43. data/lib/svg_conform/compatibility/xml_analysis_engine.rb +198 -0
  44. data/lib/svg_conform/compatibility_analyzer.rb +285 -0
  45. data/lib/svg_conform/conformance_report.rb +267 -0
  46. data/lib/svg_conform/constants.rb +199 -0
  47. data/lib/svg_conform/css_color.rb +262 -0
  48. data/lib/svg_conform/document.rb +203 -0
  49. data/lib/svg_conform/external_checkers/svgcheck/compatibility_engine.rb +166 -0
  50. data/lib/svg_conform/external_checkers/svgcheck/output_generator.rb +101 -0
  51. data/lib/svg_conform/external_checkers/svgcheck/parser.rb +200 -0
  52. data/lib/svg_conform/external_checkers/svgcheck/report_comparator.rb +175 -0
  53. data/lib/svg_conform/external_checkers/svgcheck/report_generator.rb +82 -0
  54. data/lib/svg_conform/external_checkers/svgcheck/validation_pipeline.rb +249 -0
  55. data/lib/svg_conform/external_checkers/svgcheck.rb +56 -0
  56. data/lib/svg_conform/external_checkers.rb +34 -0
  57. data/lib/svg_conform/fixer.rb +56 -0
  58. data/lib/svg_conform/profile.rb +164 -0
  59. data/lib/svg_conform/profiles.rb +60 -0
  60. data/lib/svg_conform/remediation_engine.rb +92 -0
  61. data/lib/svg_conform/remediation_result.rb +36 -0
  62. data/lib/svg_conform/remediation_runner.rb +225 -0
  63. data/lib/svg_conform/remediations/base_remediation.rb +165 -0
  64. data/lib/svg_conform/remediations/color_remediation.rb +226 -0
  65. data/lib/svg_conform/remediations/font_embedding_remediation.rb +145 -0
  66. data/lib/svg_conform/remediations/font_remediation.rb +122 -0
  67. data/lib/svg_conform/remediations/image_embedding_remediation.rb +154 -0
  68. data/lib/svg_conform/remediations/invalid_id_references_remediation.rb +129 -0
  69. data/lib/svg_conform/remediations/namespace_attribute_remediation.rb +244 -0
  70. data/lib/svg_conform/remediations/namespace_remediation.rb +151 -0
  71. data/lib/svg_conform/remediations/no_external_css_remediation.rb +192 -0
  72. data/lib/svg_conform/remediations/style_promotion_remediation.rb +93 -0
  73. data/lib/svg_conform/remediations/viewbox_remediation.rb +127 -0
  74. data/lib/svg_conform/remediations.rb +40 -0
  75. data/lib/svg_conform/report_comparator.rb +772 -0
  76. data/lib/svg_conform/requirements/allowed_elements_requirement.rb +367 -0
  77. data/lib/svg_conform/requirements/base_requirement.rb +98 -0
  78. data/lib/svg_conform/requirements/color_restrictions_requirement.rb +126 -0
  79. data/lib/svg_conform/requirements/element_requirement_config.rb +75 -0
  80. data/lib/svg_conform/requirements/font_family_requirement.rb +133 -0
  81. data/lib/svg_conform/requirements/forbidden_content_requirement.rb +60 -0
  82. data/lib/svg_conform/requirements/id_reference_requirement.rb +133 -0
  83. data/lib/svg_conform/requirements/invalid_id_references_requirement.rb +132 -0
  84. data/lib/svg_conform/requirements/link_validation_requirement.rb +55 -0
  85. data/lib/svg_conform/requirements/namespace_attributes_requirement.rb +211 -0
  86. data/lib/svg_conform/requirements/namespace_requirement.rb +294 -0
  87. data/lib/svg_conform/requirements/no_external_css_requirement.rb +132 -0
  88. data/lib/svg_conform/requirements/no_external_fonts_requirement.rb +121 -0
  89. data/lib/svg_conform/requirements/no_external_images_requirement.rb +91 -0
  90. data/lib/svg_conform/requirements/style_promotion_requirement.rb +72 -0
  91. data/lib/svg_conform/requirements/style_requirement.rb +226 -0
  92. data/lib/svg_conform/requirements/viewbox_required_requirement.rb +96 -0
  93. data/lib/svg_conform/requirements.rb +49 -0
  94. data/lib/svg_conform/semantic_comparator.rb +829 -0
  95. data/lib/svg_conform/validation_context.rb +408 -0
  96. data/lib/svg_conform/validation_result.rb +146 -0
  97. data/lib/svg_conform/validator.rb +91 -0
  98. data/lib/svg_conform/version.rb +5 -0
  99. data/lib/svg_conform.rb +68 -0
  100. data/lib/tasks/fixtures.rake +321 -0
  101. data/lib/tasks/svgcheck.rake +111 -0
  102. data/reference-docs/SVG-1.2-RFC.rnc.txt +1676 -0
  103. data/reference-docs/Scalable Vector Graphics (SVG) 1.1 (Second Edition).html +40764 -0
  104. data/reference-docs/Scalable Vector Graphics (SVG) Tiny 1.2 Specification.html +44591 -0
  105. data/reference-docs/rfc7996.txt +2971 -0
  106. data/sig/svg_conform.rbs +4 -0
  107. data/spec/fixtures/allowed_elements/inputs/basic_violations.svg +21 -0
  108. data/spec/fixtures/allowed_elements/repair/basic_violations.svg +18 -0
  109. data/spec/fixtures/color_restrictions/inputs/basic_violations.svg +23 -0
  110. data/spec/fixtures/color_restrictions/repair/basic_violations.svg +23 -0
  111. data/spec/fixtures/comprehensive/inputs/multiple_violations.svg +21 -0
  112. data/spec/fixtures/comprehensive/repair/multiple_violations.svg +16 -0
  113. data/spec/fixtures/font_family/inputs/basic_violations.svg +17 -0
  114. data/spec/fixtures/font_family/repair/basic_violations.svg +17 -0
  115. data/spec/fixtures/forbidden_content/inputs/basic_violations.svg +27 -0
  116. data/spec/fixtures/forbidden_content/repair/basic_violations.svg +19 -0
  117. data/spec/fixtures/id_reference/inputs/basic_violations.svg +17 -0
  118. data/spec/fixtures/id_reference/repair/basic_violations.svg +15 -0
  119. data/spec/fixtures/link_validation/inputs/basic_violations.svg +20 -0
  120. data/spec/fixtures/link_validation/repair/basic_violations.svg +16 -0
  121. data/spec/fixtures/lucid/inputs/simple.svg +67 -0
  122. data/spec/fixtures/lucid/repair/simple.svg +63 -0
  123. data/spec/fixtures/namespace/inputs/basic_violations.svg +20 -0
  124. data/spec/fixtures/namespace/repair/basic_violations.svg +17 -0
  125. data/spec/fixtures/namespace_attributes/inputs/basic_violations.svg +16 -0
  126. data/spec/fixtures/namespace_attributes/repair/basic_violations.svg +15 -0
  127. data/spec/fixtures/no_external_css/inputs/basic_violations.svg +20 -0
  128. data/spec/fixtures/no_external_css/repair/basic_violations.svg +18 -0
  129. data/spec/fixtures/style/inputs/basic_violations.svg +22 -0
  130. data/spec/fixtures/style/repair/basic_violations.svg +22 -0
  131. data/spec/fixtures/style_promotion/inputs/basic_test.svg +15 -0
  132. data/spec/fixtures/style_promotion/repair/basic_test.svg +15 -0
  133. data/spec/fixtures/svg_1_2_rfc/inputs/allowed_elements_violations.svg +18 -0
  134. data/spec/fixtures/svg_1_2_rfc/inputs/color_restrictions_violations.svg +23 -0
  135. data/spec/fixtures/svgcheck/check/DrawBerry-sample-2.svg.code +1 -0
  136. data/spec/fixtures/svgcheck/check/DrawBerry-sample-2.svg.err +0 -0
  137. data/spec/fixtures/svgcheck/check/DrawBerry-sample-2.svg.out +23 -0
  138. data/spec/fixtures/svgcheck/check/IETF-test.svg.code +1 -0
  139. data/spec/fixtures/svgcheck/check/IETF-test.svg.err +0 -0
  140. data/spec/fixtures/svgcheck/check/IETF-test.svg.out +20 -0
  141. data/spec/fixtures/svgcheck/check/circle.svg.code +1 -0
  142. data/spec/fixtures/svgcheck/check/circle.svg.err +0 -0
  143. data/spec/fixtures/svgcheck/check/circle.svg.out +2 -0
  144. data/spec/fixtures/svgcheck/check/colors.svg.code +1 -0
  145. data/spec/fixtures/svgcheck/check/colors.svg.err +0 -0
  146. data/spec/fixtures/svgcheck/check/colors.svg.out +13 -0
  147. data/spec/fixtures/svgcheck/check/dia-sample-svg.svg.code +1 -0
  148. data/spec/fixtures/svgcheck/check/dia-sample-svg.svg.err +0 -0
  149. data/spec/fixtures/svgcheck/check/dia-sample-svg.svg.out +76 -0
  150. data/spec/fixtures/svgcheck/check/example-dot.svg.code +1 -0
  151. data/spec/fixtures/svgcheck/check/example-dot.svg.err +0 -0
  152. data/spec/fixtures/svgcheck/check/example-dot.svg.out +11 -0
  153. data/spec/fixtures/svgcheck/check/full-tiny.svg.code +1 -0
  154. data/spec/fixtures/svgcheck/check/full-tiny.svg.err +0 -0
  155. data/spec/fixtures/svgcheck/check/full-tiny.svg.out +5835 -0
  156. data/spec/fixtures/svgcheck/check/good.svg.code +1 -0
  157. data/spec/fixtures/svgcheck/check/good.svg.err +0 -0
  158. data/spec/fixtures/svgcheck/check/good.svg.out +1 -0
  159. data/spec/fixtures/svgcheck/check/httpbis-proxy20-fig6.svg.code +1 -0
  160. data/spec/fixtures/svgcheck/check/httpbis-proxy20-fig6.svg.err +0 -0
  161. data/spec/fixtures/svgcheck/check/httpbis-proxy20-fig6.svg.out +5 -0
  162. data/spec/fixtures/svgcheck/check/malformed.svg.code +1 -0
  163. data/spec/fixtures/svgcheck/check/malformed.svg.err +0 -0
  164. data/spec/fixtures/svgcheck/check/malformed.svg.out +8 -0
  165. data/spec/fixtures/svgcheck/check/rfc-svg.svg.code +1 -0
  166. data/spec/fixtures/svgcheck/check/rfc-svg.svg.err +0 -0
  167. data/spec/fixtures/svgcheck/check/rfc-svg.svg.out +1 -0
  168. data/spec/fixtures/svgcheck/check/rfc.xml.code +1 -0
  169. data/spec/fixtures/svgcheck/check/rfc.xml.err +0 -0
  170. data/spec/fixtures/svgcheck/check/rfc.xml.out +2 -0
  171. data/spec/fixtures/svgcheck/check/rgb.svg.code +1 -0
  172. data/spec/fixtures/svgcheck/check/rgb.svg.err +0 -0
  173. data/spec/fixtures/svgcheck/check/rgb.svg.out +9 -0
  174. data/spec/fixtures/svgcheck/check/svg-wordle.svg.code +1 -0
  175. data/spec/fixtures/svgcheck/check/svg-wordle.svg.err +0 -0
  176. data/spec/fixtures/svgcheck/check/svg-wordle.svg.out +508 -0
  177. data/spec/fixtures/svgcheck/check/threshold.svg.code +1 -0
  178. data/spec/fixtures/svgcheck/check/threshold.svg.err +0 -0
  179. data/spec/fixtures/svgcheck/check/threshold.svg.out +20 -0
  180. data/spec/fixtures/svgcheck/check/utf8.svg.code +1 -0
  181. data/spec/fixtures/svgcheck/check/utf8.svg.err +0 -0
  182. data/spec/fixtures/svgcheck/check/utf8.svg.out +162 -0
  183. data/spec/fixtures/svgcheck/check/viewBox-both.svg.code +1 -0
  184. data/spec/fixtures/svgcheck/check/viewBox-both.svg.err +0 -0
  185. data/spec/fixtures/svgcheck/check/viewBox-both.svg.out +4 -0
  186. data/spec/fixtures/svgcheck/check/viewBox-height.svg.code +1 -0
  187. data/spec/fixtures/svgcheck/check/viewBox-height.svg.err +0 -0
  188. data/spec/fixtures/svgcheck/check/viewBox-height.svg.out +3 -0
  189. data/spec/fixtures/svgcheck/check/viewBox-none.svg.code +1 -0
  190. data/spec/fixtures/svgcheck/check/viewBox-none.svg.err +0 -0
  191. data/spec/fixtures/svgcheck/check/viewBox-none.svg.out +3 -0
  192. data/spec/fixtures/svgcheck/check/viewBox-width.svg.code +1 -0
  193. data/spec/fixtures/svgcheck/check/viewBox-width.svg.err +0 -0
  194. data/spec/fixtures/svgcheck/check/viewBox-width.svg.out +3 -0
  195. data/spec/fixtures/svgcheck/inputs/DrawBerry-sample-2.svg +28 -0
  196. data/spec/fixtures/svgcheck/inputs/IETF-test.svg +28 -0
  197. data/spec/fixtures/svgcheck/inputs/circle.svg +3 -0
  198. data/spec/fixtures/svgcheck/inputs/colors.svg +18 -0
  199. data/spec/fixtures/svgcheck/inputs/dia-sample-svg.svg +47 -0
  200. data/spec/fixtures/svgcheck/inputs/example-dot.svg +75 -0
  201. data/spec/fixtures/svgcheck/inputs/full-tiny.svg +16194 -0
  202. data/spec/fixtures/svgcheck/inputs/good.svg +19 -0
  203. data/spec/fixtures/svgcheck/inputs/httpbis-proxy20-fig6.svg +2 -0
  204. data/spec/fixtures/svgcheck/inputs/malformed.svg +11 -0
  205. data/spec/fixtures/svgcheck/inputs/rfc-svg.svg +1028 -0
  206. data/spec/fixtures/svgcheck/inputs/rfc.xml +37 -0
  207. data/spec/fixtures/svgcheck/inputs/rgb.svg +9 -0
  208. data/spec/fixtures/svgcheck/inputs/svg-wordle.svg +330 -0
  209. data/spec/fixtures/svgcheck/inputs/threshold.svg +26 -0
  210. data/spec/fixtures/svgcheck/inputs/utf8.svg +448 -0
  211. data/spec/fixtures/svgcheck/inputs/viewBox-both.svg +3 -0
  212. data/spec/fixtures/svgcheck/inputs/viewBox-height.svg +3 -0
  213. data/spec/fixtures/svgcheck/inputs/viewBox-none.svg +3 -0
  214. data/spec/fixtures/svgcheck/inputs/viewBox-width.svg +3 -0
  215. data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.code +1 -0
  216. data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.err +0 -0
  217. data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.file +0 -0
  218. data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.out +23 -0
  219. data/spec/fixtures/svgcheck/repair/IETF-test.svg.code +1 -0
  220. data/spec/fixtures/svgcheck/repair/IETF-test.svg.err +0 -0
  221. data/spec/fixtures/svgcheck/repair/IETF-test.svg.file +29 -0
  222. data/spec/fixtures/svgcheck/repair/IETF-test.svg.out +20 -0
  223. data/spec/fixtures/svgcheck/repair/circle.svg.code +1 -0
  224. data/spec/fixtures/svgcheck/repair/circle.svg.err +0 -0
  225. data/spec/fixtures/svgcheck/repair/circle.svg.file +4 -0
  226. data/spec/fixtures/svgcheck/repair/circle.svg.out +2 -0
  227. data/spec/fixtures/svgcheck/repair/colors.svg.code +1 -0
  228. data/spec/fixtures/svgcheck/repair/colors.svg.err +0 -0
  229. data/spec/fixtures/svgcheck/repair/colors.svg.file +19 -0
  230. data/spec/fixtures/svgcheck/repair/colors.svg.out +13 -0
  231. data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.code +1 -0
  232. data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.err +0 -0
  233. data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.file +47 -0
  234. data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.out +76 -0
  235. data/spec/fixtures/svgcheck/repair/example-dot.svg.code +1 -0
  236. data/spec/fixtures/svgcheck/repair/example-dot.svg.err +0 -0
  237. data/spec/fixtures/svgcheck/repair/example-dot.svg.file +69 -0
  238. data/spec/fixtures/svgcheck/repair/example-dot.svg.out +11 -0
  239. data/spec/fixtures/svgcheck/repair/good.svg.code +1 -0
  240. data/spec/fixtures/svgcheck/repair/good.svg.err +0 -0
  241. data/spec/fixtures/svgcheck/repair/good.svg.file +0 -0
  242. data/spec/fixtures/svgcheck/repair/good.svg.out +1 -0
  243. data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.code +1 -0
  244. data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.err +0 -0
  245. data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.file +73 -0
  246. data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.out +5 -0
  247. data/spec/fixtures/svgcheck/repair/malformed.svg.code +1 -0
  248. data/spec/fixtures/svgcheck/repair/malformed.svg.err +0 -0
  249. data/spec/fixtures/svgcheck/repair/malformed.svg.file +9 -0
  250. data/spec/fixtures/svgcheck/repair/malformed.svg.out +8 -0
  251. data/spec/fixtures/svgcheck/repair/rfc-svg.svg.code +1 -0
  252. data/spec/fixtures/svgcheck/repair/rfc-svg.svg.err +0 -0
  253. data/spec/fixtures/svgcheck/repair/rfc-svg.svg.file +0 -0
  254. data/spec/fixtures/svgcheck/repair/rfc-svg.svg.out +1 -0
  255. data/spec/fixtures/svgcheck/repair/rfc.xml.code +1 -0
  256. data/spec/fixtures/svgcheck/repair/rfc.xml.err +0 -0
  257. data/spec/fixtures/svgcheck/repair/rfc.xml.file +37 -0
  258. data/spec/fixtures/svgcheck/repair/rfc.xml.out +2 -0
  259. data/spec/fixtures/svgcheck/repair/rgb.svg.code +1 -0
  260. data/spec/fixtures/svgcheck/repair/rgb.svg.err +0 -0
  261. data/spec/fixtures/svgcheck/repair/rgb.svg.file +10 -0
  262. data/spec/fixtures/svgcheck/repair/rgb.svg.out +9 -0
  263. data/spec/fixtures/svgcheck/repair/svg-wordle.svg.code +1 -0
  264. data/spec/fixtures/svgcheck/repair/svg-wordle.svg.err +0 -0
  265. data/spec/fixtures/svgcheck/repair/svg-wordle.svg.file +112 -0
  266. data/spec/fixtures/svgcheck/repair/svg-wordle.svg.out +508 -0
  267. data/spec/fixtures/svgcheck/repair/threshold.svg.code +1 -0
  268. data/spec/fixtures/svgcheck/repair/threshold.svg.err +0 -0
  269. data/spec/fixtures/svgcheck/repair/threshold.svg.file +27 -0
  270. data/spec/fixtures/svgcheck/repair/threshold.svg.out +20 -0
  271. data/spec/fixtures/svgcheck/repair/utf8.svg.code +1 -0
  272. data/spec/fixtures/svgcheck/repair/utf8.svg.err +0 -0
  273. data/spec/fixtures/svgcheck/repair/utf8.svg.file +381 -0
  274. data/spec/fixtures/svgcheck/repair/utf8.svg.out +162 -0
  275. data/spec/fixtures/svgcheck/repair/viewBox-both.svg.code +1 -0
  276. data/spec/fixtures/svgcheck/repair/viewBox-both.svg.err +0 -0
  277. data/spec/fixtures/svgcheck/repair/viewBox-both.svg.file +4 -0
  278. data/spec/fixtures/svgcheck/repair/viewBox-both.svg.out +4 -0
  279. data/spec/fixtures/svgcheck/repair/viewBox-height.svg.code +1 -0
  280. data/spec/fixtures/svgcheck/repair/viewBox-height.svg.err +0 -0
  281. data/spec/fixtures/svgcheck/repair/viewBox-height.svg.file +4 -0
  282. data/spec/fixtures/svgcheck/repair/viewBox-height.svg.out +3 -0
  283. data/spec/fixtures/svgcheck/repair/viewBox-none.svg.code +1 -0
  284. data/spec/fixtures/svgcheck/repair/viewBox-none.svg.err +0 -0
  285. data/spec/fixtures/svgcheck/repair/viewBox-none.svg.file +4 -0
  286. data/spec/fixtures/svgcheck/repair/viewBox-none.svg.out +3 -0
  287. data/spec/fixtures/svgcheck/repair/viewBox-width.svg.code +1 -0
  288. data/spec/fixtures/svgcheck/repair/viewBox-width.svg.err +0 -0
  289. data/spec/fixtures/svgcheck/repair/viewBox-width.svg.file +4 -0
  290. data/spec/fixtures/svgcheck/repair/viewBox-width.svg.out +3 -0
  291. data/spec/fixtures/viewbox_required/inputs/missing_viewbox.svg +10 -0
  292. data/spec/fixtures/viewbox_required/repair/missing_viewbox.svg +10 -0
  293. data/spec/spec_helper.rb +16 -0
  294. data/spec/svg_conform/batch_report_spec.rb +99 -0
  295. data/spec/svg_conform/commands/check_command_spec.rb +90 -0
  296. data/spec/svg_conform/commands/profiles_command_spec.rb +20 -0
  297. data/spec/svg_conform/commands/svgcheck_compare_command_spec.rb +13 -0
  298. data/spec/svg_conform/commands/svgcheck_compatibility_command_spec.rb +13 -0
  299. data/spec/svg_conform/commands/svgcheck_generate_command_spec.rb +14 -0
  300. data/spec/svg_conform/profiles/base_profile_spec.rb +42 -0
  301. data/spec/svg_conform/profiles/lucid_fix_profile_spec.rb +46 -0
  302. data/spec/svg_conform/profiles/lucid_profile_spec.rb +84 -0
  303. data/spec/svg_conform/profiles/metanorma_profile_spec.rb +62 -0
  304. data/spec/svg_conform/profiles/no_external_css_profile_spec.rb +66 -0
  305. data/spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb +200 -0
  306. data/spec/svg_conform/profiles/svg_1_2_rfc_with_rdf_profile_spec.rb +81 -0
  307. data/spec/svg_conform/remediations/color_remediation_spec.rb +95 -0
  308. data/spec/svg_conform/remediations/font_embedding_remediation_spec.rb +20 -0
  309. data/spec/svg_conform/remediations/font_remediation_spec.rb +95 -0
  310. data/spec/svg_conform/remediations/image_embedding_remediation_spec.rb +20 -0
  311. data/spec/svg_conform/remediations/invalid_id_references_remediation_spec.rb +97 -0
  312. data/spec/svg_conform/remediations/namespace_attribute_remediation_spec.rb +97 -0
  313. data/spec/svg_conform/remediations/namespace_remediation_spec.rb +95 -0
  314. data/spec/svg_conform/remediations/no_external_css_remediation_spec.rb +97 -0
  315. data/spec/svg_conform/remediations/style_promotion_remediation_spec.rb +97 -0
  316. data/spec/svg_conform/remediations/viewbox_remediation_spec.rb +95 -0
  317. data/spec/svg_conform/requirements/allowed_elements_requirement_spec.rb +118 -0
  318. data/spec/svg_conform/requirements/color_restrictions_requirement_spec.rb +168 -0
  319. data/spec/svg_conform/requirements/font_family_requirement_spec.rb +188 -0
  320. data/spec/svg_conform/requirements/forbidden_content_requirement_spec.rb +195 -0
  321. data/spec/svg_conform/requirements/id_reference_requirement_spec.rb +78 -0
  322. data/spec/svg_conform/requirements/invalid_id_references_requirement_spec.rb +78 -0
  323. data/spec/svg_conform/requirements/link_validation_requirement_spec.rb +78 -0
  324. data/spec/svg_conform/requirements/namespace_attributes_requirement_spec.rb +86 -0
  325. data/spec/svg_conform/requirements/namespace_requirement_spec.rb +184 -0
  326. data/spec/svg_conform/requirements/no_external_css_requirement_spec.rb +78 -0
  327. data/spec/svg_conform/requirements/no_external_fonts_requirement_spec.rb +20 -0
  328. data/spec/svg_conform/requirements/no_external_images_requirement_spec.rb +20 -0
  329. data/spec/svg_conform/requirements/style_promotion_requirement_spec.rb +78 -0
  330. data/spec/svg_conform/requirements/style_requirement_spec.rb +76 -0
  331. data/spec/svg_conform/requirements/viewbox_required_requirement_spec.rb +165 -0
  332. data/spec/svg_conform_spec.rb +32 -0
  333. data/spec/svgcheck_compatibility_spec.rb +355 -0
  334. data/svg_conform.gemspec +35 -0
  335. metadata +436 -0
@@ -0,0 +1,252 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module SvgConform
6
+ module Compatibility
7
+ # Model for validity analysis results
8
+ class ValidityAnalysis < Lutaml::Model::Serializable
9
+ attribute :svg_conform_valid, :boolean
10
+ attribute :svgcheck_valid, :boolean
11
+ attribute :validity_match, :boolean
12
+ attribute :mismatch_reasons, :string, collection: true
13
+ attribute :requirement_differences, :string, collection: true
14
+
15
+ def initialize(svg_conform_valid:, svgcheck_valid:)
16
+ @svg_conform_valid = svg_conform_valid
17
+ @svgcheck_valid = svgcheck_valid
18
+ @validity_match = svg_conform_valid == svgcheck_valid
19
+ @mismatch_reasons = []
20
+ @requirement_differences = []
21
+ end
22
+
23
+ def add_mismatch_reason(reason)
24
+ @mismatch_reasons << reason
25
+ end
26
+
27
+ def add_requirement_difference(difference)
28
+ @requirement_differences << difference
29
+ end
30
+
31
+ def mismatch?
32
+ !@validity_match
33
+ end
34
+
35
+ def both_valid?
36
+ @svg_conform_valid && @svgcheck_valid
37
+ end
38
+
39
+ def both_invalid?
40
+ !@svg_conform_valid && !@svgcheck_valid
41
+ end
42
+
43
+ def svg_conform_stricter?
44
+ !@svg_conform_valid && @svgcheck_valid
45
+ end
46
+
47
+ def svgcheck_stricter?
48
+ @svg_conform_valid && !@svgcheck_valid
49
+ end
50
+ end
51
+
52
+ # Model for semantic pattern analysis
53
+ class SemanticPattern < Lutaml::Model::Serializable
54
+ attribute :pattern_type, :string
55
+ attribute :svg_conform_message, :string
56
+ attribute :svgcheck_message, :string
57
+ attribute :semantic_key, :string
58
+ attribute :confidence_score, :float
59
+ attribute :mapped, :boolean
60
+
61
+ def initialize(pattern_type:, svg_conform_message:, svgcheck_message:)
62
+ @pattern_type = pattern_type
63
+ @svg_conform_message = svg_conform_message
64
+ @svgcheck_message = svgcheck_message
65
+ @mapped = false
66
+ @confidence_score = 0.0
67
+ end
68
+
69
+ def map_to_semantic_key(key, confidence = 1.0)
70
+ @semantic_key = key
71
+ @confidence_score = confidence
72
+ @mapped = true
73
+ end
74
+
75
+ def unmapped?
76
+ !@mapped
77
+ end
78
+ end
79
+
80
+ # Enhanced validity analyzer following model-driven architecture
81
+ class ValidityAnalyzer
82
+ attr_reader :analysis_results
83
+
84
+ def initialize
85
+ @analysis_results = []
86
+ end
87
+
88
+ def analyze_validity_mismatch(svg_conform_result, svgcheck_result,
89
+ filename)
90
+ # Handle different result types
91
+ svg_conform_valid = if svg_conform_result.respond_to?(:valid?)
92
+ svg_conform_result.valid?
93
+ else
94
+ svg_conform_result.valid
95
+ end
96
+
97
+ svgcheck_valid = if svgcheck_result.respond_to?(:valid?)
98
+ svgcheck_result.valid?
99
+ else
100
+ svgcheck_result.valid
101
+ end
102
+
103
+ analysis = ValidityAnalysis.new(
104
+ svg_conform_valid: svg_conform_valid,
105
+ svgcheck_valid: svgcheck_valid,
106
+ )
107
+
108
+ if analysis.mismatch?
109
+ investigate_mismatch_reasons(analysis, svg_conform_result,
110
+ svgcheck_result, filename)
111
+ end
112
+
113
+ @analysis_results << analysis
114
+ analysis
115
+ end
116
+
117
+ def analyze_semantic_patterns(svg_conform_issues, svgcheck_issues)
118
+ patterns = []
119
+
120
+ svg_conform_issues.each do |svg_issue|
121
+ svgcheck_issues.each do |svg_issue_check|
122
+ pattern = SemanticPattern.new(
123
+ pattern_type: determine_pattern_type(svg_issue, svg_issue_check),
124
+ svg_conform_message: svg_issue.to_s,
125
+ svgcheck_message: svg_issue_check.to_s,
126
+ )
127
+
128
+ # Try to map to existing semantic keys
129
+ map_semantic_pattern(pattern)
130
+ patterns << pattern
131
+ end
132
+ end
133
+
134
+ patterns
135
+ end
136
+
137
+ private
138
+
139
+ def investigate_mismatch_reasons(analysis, svg_conform_result,
140
+ svgcheck_result, _filename)
141
+ if analysis.svg_conform_stricter?
142
+ analysis.add_mismatch_reason("SvgConform stricter validation")
143
+ analyze_svg_conform_requirements(analysis, svg_conform_result)
144
+ elsif analysis.svgcheck_stricter?
145
+ analysis.add_mismatch_reason("Svgcheck stricter validation")
146
+ analyze_svgcheck_requirements(analysis, svgcheck_result)
147
+ end
148
+ end
149
+
150
+ def analyze_svg_conform_requirements(analysis, result)
151
+ # Analyze which specific requirements are failing
152
+ return unless result.respond_to?(:issues)
153
+
154
+ result.issues.each do |issue|
155
+ requirement_type = extract_requirement_type(issue)
156
+ analysis.add_requirement_difference(
157
+ "SvgConform requirement: #{requirement_type}",
158
+ )
159
+ end
160
+ end
161
+
162
+ def analyze_svgcheck_requirements(analysis, result)
163
+ # Analyze svgcheck specific requirements
164
+ return unless result.respond_to?(:messages)
165
+
166
+ result.messages.each do |message|
167
+ requirement_type = extract_svgcheck_requirement_type(message)
168
+ analysis.add_requirement_difference(
169
+ "Svgcheck requirement: #{requirement_type}",
170
+ )
171
+ end
172
+ end
173
+
174
+ def extract_requirement_type(issue)
175
+ case issue.to_s
176
+ when /namespace/i
177
+ "namespace_requirement"
178
+ when /viewbox/i
179
+ "viewbox_requirement"
180
+ when /font/i
181
+ "font_requirement"
182
+ when /color/i
183
+ "color_requirement"
184
+ else
185
+ "unknown_requirement"
186
+ end
187
+ end
188
+
189
+ def extract_svgcheck_requirement_type(message)
190
+ case message.to_s
191
+ when /namespace/i
192
+ "namespace_validation"
193
+ when /viewbox/i
194
+ "viewbox_validation"
195
+ when /font/i
196
+ "font_validation"
197
+ when /color/i
198
+ "color_validation"
199
+ else
200
+ "unknown_validation"
201
+ end
202
+ end
203
+
204
+ def determine_pattern_type(svg_issue, svgcheck_issue)
205
+ svg_type = extract_requirement_type(svg_issue)
206
+ svgcheck_type = extract_svgcheck_requirement_type(svgcheck_issue)
207
+
208
+ if svg_type.gsub("_requirement", "") ==
209
+ svgcheck_type.gsub("_validation", "")
210
+ "equivalent_validation"
211
+ else
212
+ "different_validation"
213
+ end
214
+ end
215
+
216
+ def map_semantic_pattern(pattern)
217
+ # Enhanced semantic mapping logic
218
+ semantic_key = determine_semantic_key(pattern)
219
+ return unless semantic_key
220
+
221
+ confidence = calculate_mapping_confidence(pattern, semantic_key)
222
+ pattern.map_to_semantic_key(semantic_key, confidence)
223
+ end
224
+
225
+ def determine_semantic_key(pattern)
226
+ # Use existing semantic comparator logic
227
+ SvgConform::SemanticComparator.new
228
+
229
+ # This would need to be enhanced to work with the pattern model
230
+ # For now, return a basic mapping
231
+ case pattern.pattern_type
232
+ when "equivalent_validation"
233
+ "validation_equivalent"
234
+ when "different_validation"
235
+ "validation_different"
236
+ end
237
+ end
238
+
239
+ def calculate_mapping_confidence(pattern, _semantic_key)
240
+ # Calculate confidence based on pattern similarity
241
+ case pattern.pattern_type
242
+ when "equivalent_validation"
243
+ 0.9
244
+ when "different_validation"
245
+ 0.5
246
+ else
247
+ 0.1
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end
@@ -0,0 +1,198 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../semantic_comparator"
4
+ require_relative "../remediation_runner"
5
+
6
+ module SvgConform
7
+ module Compatibility
8
+ # Handles XML-specific analysis operations for embedded SVG elements
9
+ class XmlAnalysisEngine
10
+ def initialize(context, file_processor)
11
+ @context = context
12
+ @file_processor = file_processor
13
+ end
14
+
15
+ def analyze_file(filename, svgcheck_report)
16
+ input_file = @file_processor.input_file_path(filename)
17
+ doc = parse_xml_file(input_file)
18
+ return nil unless doc
19
+
20
+ svg_elements = extract_svg_elements(doc)
21
+ return nil if svg_elements.empty?
22
+
23
+ display_analysis_header(filename, svg_elements.length)
24
+ process_svg_elements(svg_elements, filename, svgcheck_report)
25
+ end
26
+
27
+ private
28
+
29
+ def parse_xml_file(input_file)
30
+ require "moxml"
31
+ xml_content = File.read(input_file)
32
+ moxml = Moxml.new
33
+ moxml.parse(xml_content)
34
+ rescue StandardError => e
35
+ puts "❌ Error parsing XML file: #{e.message}"
36
+ nil
37
+ end
38
+
39
+ def extract_svg_elements(doc)
40
+ svg_elements = doc.xpath("//svg:svg", "svg" => "http://www.w3.org/2000/svg")
41
+
42
+ puts "❌ No SVG elements found in XML file" if svg_elements.empty?
43
+
44
+ svg_elements
45
+ end
46
+
47
+ def display_analysis_header(filename, element_count)
48
+ mode_icon = @context.repair_mode? ? "🔧" : "📋"
49
+ mode_text = @context.repair_mode? ? "Repair Analysis" : "Analysis"
50
+
51
+ puts Paint["#{mode_icon} XML File #{mode_text}: #{filename}", :cyan,
52
+ :bold]
53
+ puts "Found #{element_count} embedded SVG element(s)"
54
+ puts
55
+ end
56
+
57
+ def process_svg_elements(svg_elements, filename, svgcheck_report)
58
+ svg_elements.each_with_index do |svg_element, index|
59
+ puts Paint["🔍 Analyzing SVG Element #{index + 1}:", :blue, :bold]
60
+ process_single_svg_element(svg_element, filename, index,
61
+ svgcheck_report)
62
+ end
63
+ end
64
+
65
+ def process_single_svg_element(svg_element, filename, index,
66
+ svgcheck_report)
67
+ svg_content = svg_element.to_xml
68
+ element_filename = "#{filename}#svg#{index + 1}"
69
+
70
+ require "tempfile"
71
+ temp_file = Tempfile.new(["embedded_svg", ".svg"])
72
+
73
+ begin
74
+ temp_file.write(svg_content)
75
+ temp_file.close
76
+
77
+ if @context.repair_mode?
78
+ process_embedded_svg_repair(element_filename, svg_content,
79
+ svgcheck_report)
80
+ else
81
+ process_embedded_svg_validation(element_filename, temp_file.path,
82
+ svgcheck_report)
83
+ end
84
+ ensure
85
+ temp_file.unlink
86
+ end
87
+ end
88
+
89
+ def process_embedded_svg_validation(element_filename, temp_file_path,
90
+ svgcheck_report)
91
+ svg_conform_result = run_validation(temp_file_path)
92
+ svg_conform_report = create_conformance_report(element_filename,
93
+ svg_conform_result)
94
+
95
+ if @context.semantic_analysis?
96
+ build_semantic_validation_result(element_filename,
97
+ svg_conform_report, svgcheck_report)
98
+ else
99
+ build_basic_validation_result(element_filename, svg_conform_report,
100
+ svgcheck_report)
101
+ end
102
+ end
103
+
104
+ def process_embedded_svg_repair(element_filename, svg_content,
105
+ svgcheck_report)
106
+ remediation_runner = SvgConform::RemediationRunner.new(profile: @context.profile)
107
+ svg_conform_result = remediation_runner.run_remediation(svg_content,
108
+ filename: element_filename)
109
+
110
+ if @context.semantic_analysis?
111
+ build_semantic_repair_result(element_filename, svg_conform_result,
112
+ svgcheck_report)
113
+ else
114
+ build_basic_repair_result(element_filename, svg_conform_result,
115
+ svgcheck_report)
116
+ end
117
+ end
118
+
119
+ def run_validation(temp_file_path)
120
+ validator = SvgConform::Validator.new
121
+ validator.validate_file(temp_file_path, profile: @context.profile)
122
+ end
123
+
124
+ def create_conformance_report(filename, svg_conform_result)
125
+ SvgConform::ConformanceReport.from_svg_conform_result(
126
+ filename,
127
+ svg_conform_result,
128
+ profile: @context.profile,
129
+ use_svgcheck_mapping: true,
130
+ )
131
+ end
132
+
133
+ def build_semantic_validation_result(filename, svg_conform_report,
134
+ svgcheck_report)
135
+ validation_comparison = SvgConform::SemanticComparator.compare_validation_results(
136
+ svg_conform_report,
137
+ svgcheck_report,
138
+ )
139
+
140
+ ComparisonResult.new(
141
+ filename: filename,
142
+ type: :semantic_validation,
143
+ validation_comparison: validation_comparison,
144
+ )
145
+ end
146
+
147
+ def build_basic_validation_result(filename, svg_conform_report,
148
+ svgcheck_report)
149
+ ComparisonResult.new(
150
+ filename: filename,
151
+ type: :basic_validation,
152
+ svg_conform_result: svg_conform_report,
153
+ svgcheck_result: svgcheck_report,
154
+ )
155
+ end
156
+
157
+ def build_semantic_repair_result(filename, svg_conform_result,
158
+ svgcheck_report)
159
+ svg_conform_report = svg_conform_result.generate_conformance_report
160
+ validation_comparison = SvgConform::SemanticComparator.compare_validation_results(
161
+ svg_conform_report,
162
+ svgcheck_report,
163
+ )
164
+
165
+ content_comparison = build_content_comparison(svg_conform_result,
166
+ svgcheck_report)
167
+
168
+ ComparisonResult.new(
169
+ filename: filename,
170
+ type: :semantic_repair,
171
+ validation_comparison: validation_comparison,
172
+ content_comparison: content_comparison,
173
+ xml_equivalence: nil, # XML files don't have repaired file comparison
174
+ )
175
+ end
176
+
177
+ def build_basic_repair_result(filename, svg_conform_result,
178
+ svgcheck_report)
179
+ ComparisonResult.new(
180
+ filename: filename,
181
+ type: :basic_repair,
182
+ svg_conform_result: svg_conform_result,
183
+ svgcheck_result: svgcheck_report,
184
+ )
185
+ end
186
+
187
+ def build_content_comparison(svg_conform_result, svgcheck_report)
188
+ return nil unless svgcheck_report.respond_to?(:remediated_content) &&
189
+ svg_conform_result.remediated_content
190
+
191
+ SvgConform::SemanticComparator.compare_remediated_content(
192
+ svg_conform_result.remediated_content,
193
+ svgcheck_report.remediated_content,
194
+ )
195
+ end
196
+ end
197
+ end
198
+ end