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,321 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+
5
+ namespace :fixtures do
6
+ desc "Generate YAML conformance reports for all test fixtures"
7
+ task :generate_reports do
8
+ puts "Generating YAML conformance reports for all test fixtures..."
9
+
10
+ require_relative "../svg_conform"
11
+
12
+ # Create reports directory
13
+ reports_dir = "spec/fixtures/reports"
14
+ FileUtils.mkdir_p(reports_dir)
15
+
16
+ # Get all test files
17
+ input_dir = "spec/fixtures/svgcheck/inputs"
18
+ test_files = Dir.glob("#{input_dir}/*.{svg,xml}").map do |f|
19
+ File.basename(f)
20
+ end
21
+
22
+ puts "Found #{test_files.length} test files to process..."
23
+
24
+ success_count = 0
25
+ error_count = 0
26
+
27
+ test_files.each do |filename|
28
+ puts "Processing #{filename}..."
29
+
30
+ # Read the input file
31
+ input_path = "#{input_dir}/#{filename}"
32
+
33
+ # Read expected error output if it exists
34
+ error_file = filename.sub(/\.(svg|xml)$/, ".err")
35
+ error_path = "spec/fixtures/svgcheck/expected_dynamic/#{error_file}"
36
+
37
+ error_content = ""
38
+ error_content = File.read(error_path) if File.exist?(error_path)
39
+
40
+ # Generate svgcheck report
41
+ svgcheck_report = SvgConform::ConformanceReport.from_svgcheck_result(
42
+ filename,
43
+ error_content,
44
+ )
45
+
46
+ # Save svgcheck report
47
+ svgcheck_yaml_path = "#{reports_dir}/#{filename}.svgcheck.yml"
48
+ svgcheck_report.save_to_file(svgcheck_yaml_path)
49
+
50
+ # Generate svg_conform report
51
+ begin
52
+ # Load and validate with svg_conform using the convenience method
53
+ validation_result = SvgConform.validate_file(input_path,
54
+ profile: :svg_1_2_rfc)
55
+
56
+ svg_conform_report = SvgConform::ConformanceReport.from_svg_conform_result(
57
+ filename,
58
+ validation_result,
59
+ profile: "svg_1_2_rfc",
60
+ )
61
+
62
+ # Save svg_conform report
63
+ svg_conform_yaml_path = "#{reports_dir}/#{filename}.svg_conform.yml"
64
+ svg_conform_report.save_to_file(svg_conform_yaml_path)
65
+
66
+ puts " āœ… Generated both reports for #{filename}"
67
+ success_count += 1
68
+ rescue StandardError => e
69
+ puts " āŒ Error generating svg_conform report for #{filename}: #{e.message}"
70
+
71
+ # Still save a minimal svg_conform report
72
+ error_report = SvgConform::ConformanceReport.new
73
+ error_report.filename = filename
74
+ error_report.tool = "svg_conform"
75
+ error_report.version = SvgConform::VERSION
76
+ error_report.timestamp = Time.now.iso8601
77
+ error_report.valid = false
78
+ error_report.errors = SvgConform::IssueSummary.new
79
+ error_report.errors.total_count = 1
80
+ error_report.errors.by_requirement = { "parse_error" => 1 }
81
+ error_report.errors.sample_issues = [
82
+ SvgConform::ConformanceIssue.new(
83
+ type: "error",
84
+ requirement_id: "parse_error",
85
+ message: e.message,
86
+ element: "document",
87
+ line: 1,
88
+ ),
89
+ ]
90
+ error_report.warnings = SvgConform::IssueSummary.new
91
+ error_report.warnings.total_count = 0
92
+ error_report.warnings.by_requirement = {}
93
+ error_report.warnings.sample_issues = []
94
+
95
+ svg_conform_yaml_path = "#{reports_dir}/#{filename}.svg_conform.yml"
96
+ error_report.save_to_file(svg_conform_yaml_path)
97
+
98
+ puts " āš ļø Generated error report for #{filename}"
99
+ error_count += 1
100
+ end
101
+ end
102
+
103
+ puts "\n#{'=' * 60}"
104
+ puts "FIXTURE REPORT GENERATION SUMMARY"
105
+ puts "=" * 60
106
+ puts "Total files processed: #{test_files.length}"
107
+ puts "Successful reports: #{success_count}"
108
+ puts "Error reports: #{error_count}"
109
+ puts "Reports saved to: #{reports_dir}/"
110
+
111
+ # List generated files
112
+ puts "\nGenerated files:"
113
+ Dir.glob("#{reports_dir}/*").sort.each do |f|
114
+ puts " - #{File.basename(f)}"
115
+ end
116
+
117
+ puts "\nāœ… Fixture report generation complete!"
118
+ end
119
+
120
+ desc "Validate all fixture reports can be loaded"
121
+ task :validate_reports do
122
+ puts "Validating all fixture reports can be loaded..."
123
+
124
+ require_relative "../svg_conform"
125
+
126
+ reports_dir = "spec/fixtures/reports"
127
+ unless Dir.exist?(reports_dir)
128
+ puts "āŒ Reports directory not found. Run 'rake fixtures:generate_reports' first."
129
+ exit 1
130
+ end
131
+
132
+ report_files = Dir.glob("#{reports_dir}/*.yml")
133
+ if report_files.empty?
134
+ puts "āŒ No report files found. Run 'rake fixtures:generate_reports' first."
135
+ exit 1
136
+ end
137
+
138
+ puts "Found #{report_files.length} report files to validate..."
139
+
140
+ success_count = 0
141
+ error_count = 0
142
+
143
+ report_files.each do |report_file|
144
+ filename = File.basename(report_file)
145
+ print "Validating #{filename}... "
146
+
147
+ begin
148
+ report = SvgConform::ConformanceReport.load_from_file(report_file)
149
+
150
+ # Basic validation
151
+ raise "Missing filename" unless report.filename
152
+ raise "Missing tool" unless report.tool
153
+ raise "Missing timestamp" unless report.timestamp
154
+ raise "Missing errors summary" unless report.errors
155
+ raise "Missing warnings summary" unless report.warnings
156
+
157
+ puts "āœ…"
158
+ success_count += 1
159
+ rescue StandardError => e
160
+ puts "āŒ #{e.message}"
161
+ error_count += 1
162
+ end
163
+ end
164
+
165
+ puts "\n#{'=' * 60}"
166
+ puts "FIXTURE REPORT VALIDATION SUMMARY"
167
+ puts "=" * 60
168
+ puts "Total reports: #{report_files.length}"
169
+ puts "Valid reports: #{success_count}"
170
+ puts "Invalid reports: #{error_count}"
171
+
172
+ if error_count.positive?
173
+ puts "\nāŒ Some reports failed validation!"
174
+ exit 1
175
+ else
176
+ puts "\nāœ… All reports are valid!"
177
+ end
178
+ end
179
+
180
+ desc "Compare fixture reports between tools"
181
+ task :compare_reports do
182
+ puts "Comparing fixture reports between svg_conform and svgcheck..."
183
+
184
+ require_relative "../svg_conform"
185
+
186
+ reports_dir = "spec/fixtures/reports"
187
+ unless Dir.exist?(reports_dir)
188
+ puts "āŒ Reports directory not found. Run 'rake fixtures:generate_reports' first."
189
+ exit 1
190
+ end
191
+
192
+ # Get all base filenames (without tool suffix)
193
+ base_files = Dir.glob("#{reports_dir}/*.svg_conform.yml").map do |f|
194
+ File.basename(f, ".svg_conform.yml")
195
+ end
196
+
197
+ puts "Found #{base_files.length} test cases to compare..."
198
+
199
+ identical_count = 0
200
+ different_count = 0
201
+ differences = []
202
+
203
+ base_files.each do |base_filename|
204
+ svg_conform_path = "#{reports_dir}/#{base_filename}.svg_conform.yml"
205
+ svgcheck_path = "#{reports_dir}/#{base_filename}.svgcheck.yml"
206
+
207
+ next unless File.exist?(svg_conform_path) && File.exist?(svgcheck_path)
208
+
209
+ puts "Comparing #{base_filename}..."
210
+
211
+ begin
212
+ svg_conform_report = SvgConform::ConformanceReport.load_from_file(svg_conform_path)
213
+ svgcheck_report = SvgConform::ConformanceReport.load_from_file(svgcheck_path)
214
+
215
+ comparison = svg_conform_report.compare_with(svgcheck_report)
216
+
217
+ if comparison[:identical]
218
+ puts " āœ… Reports are identical"
219
+ identical_count += 1
220
+ else
221
+ puts " āŒ Reports differ:"
222
+ comparison[:differences].each { |diff| puts " - #{diff}" }
223
+ different_count += 1
224
+ differences << {
225
+ file: base_filename,
226
+ differences: comparison[:differences],
227
+ }
228
+ end
229
+ rescue StandardError => e
230
+ puts " āŒ Error comparing reports: #{e.message}"
231
+ different_count += 1
232
+ differences << {
233
+ file: base_filename,
234
+ differences: ["Comparison error: #{e.message}"],
235
+ }
236
+ end
237
+ end
238
+
239
+ puts "\n#{'=' * 60}"
240
+ puts "FIXTURE REPORT COMPARISON SUMMARY"
241
+ puts "=" * 60
242
+ puts "Total comparisons: #{base_files.length}"
243
+ puts "Identical reports: #{identical_count}"
244
+ puts "Different reports: #{different_count}"
245
+ puts "Compatibility rate: #{((identical_count.to_f / base_files.length) * 100).round(1)}%"
246
+
247
+ if differences.any?
248
+ puts "\nFiles with differences:"
249
+ differences.each do |diff|
250
+ puts " - #{diff[:file]}:"
251
+ diff[:differences].each { |d| puts " #{d}" }
252
+ end
253
+ end
254
+
255
+ puts "\n#{different_count.positive? ? 'āŒ' : 'āœ…'} Comparison complete!"
256
+ end
257
+
258
+ desc "Clean all generated fixture reports"
259
+ task :clean_reports do
260
+ puts "Cleaning all generated fixture reports..."
261
+
262
+ reports_dir = "spec/fixtures/reports"
263
+ if Dir.exist?(reports_dir)
264
+ FileUtils.rm_rf(reports_dir)
265
+ puts "āœ… Cleaned #{reports_dir}/"
266
+ else
267
+ puts "āš ļø Reports directory doesn't exist"
268
+ end
269
+ end
270
+
271
+ desc "Regenerate all fixture reports (clean + generate)"
272
+ task regenerate_reports: %i[clean_reports generate_reports]
273
+
274
+ desc "Full fixture workflow (generate + validate + compare)"
275
+ task all: %i[generate_reports validate_reports compare_reports]
276
+
277
+ desc "Show fixture report statistics"
278
+ task :stats do
279
+ puts "Fixture Report Statistics"
280
+ puts "=" * 40
281
+
282
+ require_relative "../svg_conform"
283
+
284
+ reports_dir = "spec/fixtures/reports"
285
+ unless Dir.exist?(reports_dir)
286
+ puts "āŒ Reports directory not found. Run 'rake fixtures:generate_reports' first."
287
+ exit 1
288
+ end
289
+
290
+ svg_conform_reports = Dir.glob("#{reports_dir}/*.svg_conform.yml")
291
+ svgcheck_reports = Dir.glob("#{reports_dir}/*.svgcheck.yml")
292
+
293
+ puts "Total svg_conform reports: #{svg_conform_reports.length}"
294
+ puts "Total svgcheck reports: #{svgcheck_reports.length}"
295
+
296
+ # Analyze error counts
297
+ total_svg_conform_errors = 0
298
+ total_svgcheck_errors = 0
299
+
300
+ svg_conform_reports.each do |report_file|
301
+ report = SvgConform::ConformanceReport.load_from_file(report_file)
302
+ total_svg_conform_errors += report.errors.total_count
303
+ rescue StandardError
304
+ # Skip invalid reports
305
+ end
306
+
307
+ svgcheck_reports.each do |report_file|
308
+ report = SvgConform::ConformanceReport.load_from_file(report_file)
309
+ total_svgcheck_errors += report.errors.total_count
310
+ rescue StandardError
311
+ # Skip invalid reports
312
+ end
313
+
314
+ puts "Total svg_conform errors: #{total_svg_conform_errors}"
315
+ puts "Total svgcheck errors: #{total_svgcheck_errors}"
316
+ puts "Average errors per file (svg_conform): #{(total_svg_conform_errors.to_f / svg_conform_reports.length).round(2)}"
317
+ puts "Average errors per file (svgcheck): #{(total_svgcheck_errors.to_f / svgcheck_reports.length).round(2)}"
318
+
319
+ puts "\nāœ… Statistics complete!"
320
+ end
321
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../svg_conform/external_checkers"
4
+
5
+ namespace :svgcheck do
6
+ desc "Generate svgcheck outputs for test files"
7
+ task :generate, [:mode] do |_t, args|
8
+ mode = args[:mode] || "both"
9
+
10
+ puts "šŸ”§ Generating svgcheck outputs (mode: #{mode})..."
11
+
12
+ checker = SvgConform::ExternalCheckers::Svgcheck::Checker.new
13
+
14
+ unless checker.available?
15
+ puts "āŒ svgcheck not available. Please ensure Python 3 and svgcheck are installed."
16
+ exit 1
17
+ end
18
+
19
+ generator = SvgConform::ExternalCheckers::Svgcheck::OutputGenerator.new
20
+ test_files = find_test_files
21
+
22
+ if test_files.empty?
23
+ puts "āŒ No test files found in svgcheck/svgcheck/Tests"
24
+ exit 1
25
+ end
26
+
27
+ puts "šŸ“Š Found #{test_files.length} test files"
28
+
29
+ success_count = 0
30
+ error_count = 0
31
+
32
+ test_files.each do |filename|
33
+ puts "šŸ“„ Processing #{filename}..."
34
+
35
+ begin
36
+ results = generator.generate(filename, mode: mode.to_sym)
37
+
38
+ if results.values.all? { |result| result[:success] }
39
+ success_count += 1
40
+ puts " āœ… Success"
41
+ else
42
+ error_count += 1
43
+ puts " āŒ Failed"
44
+ results.each do |result_mode, result|
45
+ puts " #{result_mode}: #{result[:error]}" unless result[:success]
46
+ end
47
+ end
48
+ rescue StandardError => e
49
+ error_count += 1
50
+ puts " āŒ Error: #{e.message}"
51
+ end
52
+ end
53
+
54
+ puts "\nšŸ“ˆ GENERATION SUMMARY:"
55
+ puts " āœ… Successfully generated: #{success_count}"
56
+ puts " āŒ Failed: #{error_count}"
57
+ puts " šŸ“ Output directory: spec/fixtures/svgcheck"
58
+ end
59
+
60
+ desc "Compare svg_conform validation against svgcheck outputs"
61
+ task :compare do
62
+ puts "šŸ” Comparing svg_conform validation against svgcheck outputs..."
63
+
64
+ comparator = SvgConform::ExternalCheckers::Svgcheck::ReportComparator.new
65
+ results = comparator.compare_all_test_files
66
+
67
+ puts "\nšŸ“Š COMPARISON SUMMARY:"
68
+ puts " šŸ“„ Total files processed: #{results[:total_files]}"
69
+ puts " āœ… Matching reports: #{results[:matching]}"
70
+ puts " āŒ Different reports: #{results[:different]}"
71
+ puts " āš ļø Errors: #{results[:errors]}"
72
+
73
+ if results[:different].positive?
74
+ puts "\nšŸ” Files with differences:"
75
+ results[:differences].each do |file, diff|
76
+ puts " #{file}: #{diff[:summary]}"
77
+ end
78
+ end
79
+ end
80
+
81
+ desc "Validate profile configuration against svgcheck source"
82
+ task :validate_profile do
83
+ puts "šŸ” Validating svg_1_2_rfc profile against svgcheck source..."
84
+
85
+ validator = SvgConform::ExternalCheckers::Svgcheck::ProfileValidator.new
86
+ results = validator.validate_profile("config/profiles/svg_1_2_rfc.yml")
87
+
88
+ puts "\nšŸ“Š VALIDATION SUMMARY:"
89
+ puts " āœ… Matching configurations: #{results[:matches]}"
90
+ puts " āŒ Mismatched configurations: #{results[:mismatches]}"
91
+ puts " āš ļø Missing configurations: #{results[:missing]}"
92
+
93
+ if results[:issues].any?
94
+ puts "\nšŸ” Issues found:"
95
+ results[:issues].each do |issue|
96
+ puts " #{issue[:type]}: #{issue[:message]}"
97
+ end
98
+ end
99
+ end
100
+
101
+ private
102
+
103
+ def find_test_files
104
+ test_dir = "svgcheck/svgcheck/Tests"
105
+ return [] unless Dir.exist?(test_dir)
106
+
107
+ # Find all .svg and .xml files
108
+ pattern = File.join(test_dir, "*.{svg,xml}")
109
+ Dir.glob(pattern).map { |path| File.basename(path) }.sort
110
+ end
111
+ end