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,732 @@
1
+ = SVG Remediations
2
+ :toc: left
3
+ :toclevels: 3
4
+ :sectlinks:
5
+ :sectanchors:
6
+ :source-highlighter: rouge
7
+
8
+ == Overview
9
+
10
+ **Remediations** are automatic fixing actions that can resolve requirement failures. Each remediation targets one or more specific requirements through a mapping system.
11
+
12
+ Remediations are configured with specific parameters to customize their behavior and can be mapped to requirements using the `targets` configuration in profile YAML files.
13
+
14
+ == Remediation System
15
+
16
+ === Targeting System
17
+
18
+ Remediations are mapped to requirements using the `targets` configuration:
19
+
20
+ [source,yaml]
21
+ ----
22
+ remediations:
23
+ - id: "fix_invalid_colors"
24
+ type: "ColorRemediation"
25
+ description: "Convert invalid colors to black or white"
26
+ targets: ["color_restrictions"] # Maps to ColorRestrictionsRequirement
27
+ ----
28
+
29
+ This mapping system allows:
30
+ * **Targeted fixes**: Remediations only run when their target requirements fail
31
+ * **Flexible configuration**: Multiple remediations can target the same requirement
32
+ * **Conditional application**: Remediations can be enabled/disabled per profile
33
+
34
+ === Remediation Types
35
+
36
+ Remediations are categorized by the type of fix they apply:
37
+
38
+ **Convert**: Transform invalid content to valid alternatives
39
+ **Remove**: Delete non-compliant elements or attributes
40
+ **Add**: Insert missing required content
41
+ **Promote**: Change content structure while preserving meaning
42
+
43
+ == Available remediations
44
+
45
+ SvgConform provides 9 different remediation types that automatically fix validation violations.
46
+
47
+ === Content conversion remediations
48
+
49
+ [[color-remediation]]
50
+ ==== ColorRemediation
51
+
52
+ Converts invalid colors to allowed alternatives using the enhanced CssColor system with threshold-based conversion.
53
+
54
+ **Configuration Options**:
55
+
56
+ `conversion_strategy`:: Strategy for color conversion: `"threshold"`, `"nearest"`, or `"strict"`. Default: `"threshold"`.
57
+ `fallback_color`:: Default color when conversion is not possible. Default: `"black"`.
58
+ `preserve_transparency`:: Boolean flag to preserve alpha channel information. Default: `false`.
59
+
60
+ Configuration:
61
+ [source,yaml]
62
+ ----
63
+ - id: "fix_colors"
64
+ type: "ColorRemediation"
65
+ description: "Convert colors to allowed equivalents"
66
+ targets: ["color_restrictions"]
67
+ config:
68
+ conversion_strategy: "threshold"
69
+ fallback_color: "black"
70
+ preserve_transparency: false
71
+ ----
72
+
73
+ Where,
74
+
75
+ `targets`:: List of requirement IDs that this remediation addresses.
76
+
77
+ .Using ColorRemediation with threshold-based conversion
78
+ [example]
79
+ ====
80
+ [source,yaml]
81
+ ----
82
+ remediations:
83
+ - id: "color_conversion"
84
+ type: "ColorRemediation"
85
+ description: "Convert colors to black and white using RGB threshold"
86
+ targets: ["color_restrictions"]
87
+ config:
88
+ conversion_strategy: "threshold"
89
+ fallback_color: "black"
90
+ ----
91
+ ====
92
+
93
+ When the target ColorRestrictionsRequirement has a `black_and_white_threshold` configured, the remediation applies threshold-based conversion:
94
+ - RGB sum ≤ threshold → converted to `black`
95
+ - RGB sum > threshold → converted to `white`
96
+
97
+ **Targets**: link:requirements.adoc#color-restrictions-requirement[ColorRestrictionsRequirement] violations
98
+ **Remediation Type**: Convert
99
+ **Confidence**: Automatic
100
+
101
+ Features:
102
+ * **Smart color conversion** using CssColor equivalence and threshold logic
103
+ * **Threshold-based conversion**: When `black_and_white_threshold` is configured, applies RGB sum logic
104
+ * **Preserves color intent** when possible (dark → black, light → white)
105
+ * **Handles all color formats**: named, hex, RGB, percentage RGB, short hex, mixed formats
106
+ * **Case-insensitive processing**: Handles uppercase color names and hex values
107
+ * Updates both attributes and style properties
108
+
109
+ [[font-remediation]]
110
+ ==== FontRemediation
111
+
112
+ Maps font families to generic alternatives.
113
+
114
+ **Configuration Options**:
115
+
116
+ `font_mapping`:: Hash mapping specific font names to generic alternatives.
117
+ `default_family`:: Default font family for unmapped fonts. Default: `"sans-serif"`.
118
+ `preserve_fallbacks`:: Boolean flag to preserve existing font fallback lists. Default: `true`.
119
+ `case_sensitive`:: Boolean flag for case-sensitive font name matching. Default: `false`.
120
+
121
+ Configuration:
122
+ [source,yaml]
123
+ ----
124
+ - id: "fix_fonts"
125
+ type: "FontRemediation"
126
+ description: "Convert to generic font families"
127
+ targets: ["font_family"]
128
+ config:
129
+ default_family: "sans-serif"
130
+ preserve_fallbacks: true
131
+ case_sensitive: false
132
+ font_mapping:
133
+ "Arial": "sans-serif"
134
+ "Helvetica": "sans-serif"
135
+ "Times": "serif"
136
+ "Times New Roman": "serif"
137
+ "Courier": "monospace"
138
+ "Courier New": "monospace"
139
+ ----
140
+
141
+ **Targets**: link:requirements.adoc#font-family-requirement[FontFamilyRequirement] violations
142
+ **Remediation Type**: Convert
143
+ **Confidence**: Automatic
144
+
145
+ Features:
146
+ * Configurable font family mappings
147
+ * Handles comma-separated font lists
148
+ * Updates both font-family attributes and style properties
149
+ * Preserves font fallback chains when configured
150
+ * Case-insensitive font matching
151
+
152
+ === Element and attribute removal remediations
153
+
154
+ [[namespace-remediation]]
155
+ ==== NamespaceRemediation
156
+
157
+ Removes invalid namespace elements and attributes.
158
+
159
+ **Configuration Options**:
160
+
161
+ `default_namespace`:: Default namespace to apply to elements. Default: `"http://www.w3.org/2000/svg"`.
162
+ `preserve_content`:: Boolean flag to preserve element content when removing namespace elements. Default: `false`.
163
+ `cleanup_declarations`:: Boolean flag to remove unused namespace declarations. Default: `true`.
164
+
165
+ Configuration:
166
+ [source,yaml]
167
+ ----
168
+ - id: "fix_namespaces"
169
+ type: "NamespaceRemediation"
170
+ description: "Remove invalid namespace content"
171
+ targets: ["namespace_validation"]
172
+ config:
173
+ default_namespace: "http://www.w3.org/2000/svg"
174
+ preserve_content: false
175
+ cleanup_declarations: true
176
+ ----
177
+
178
+ **Targets**: link:requirements.adoc#namespace-requirement[NamespaceRequirement] violations
179
+ **Remediation Type**: Remove
180
+ **Confidence**: Safe Removal
181
+
182
+ Features:
183
+ * **Removes invalid namespace elements** (e.g., `<custom:element>`)
184
+ * **Removes invalid namespace attributes** (e.g., `custom:attr`)
185
+ * **Preserves valid namespaces** (SVG, XLink, XML)
186
+ * **Cleans up namespace declarations**
187
+ * Optional content preservation during element removal
188
+
189
+ [[namespace-attribute-remediation]]
190
+ ==== NamespaceAttributeRemediation
191
+
192
+ Removes attributes from disallowed namespaces.
193
+
194
+ **Configuration Options**:
195
+
196
+ `removal_strategy`:: Strategy for attribute removal: `"remove_all"` or `"selective"`. Default: `"selective"`.
197
+ `preserve_data`:: Boolean flag to preserve data contained in removed attributes. Default: `false`.
198
+
199
+ Configuration:
200
+ [source,yaml]
201
+ ----
202
+ - id: "fix_namespace_attrs"
203
+ type: "NamespaceAttributeRemediation"
204
+ description: "Remove disallowed namespace attributes"
205
+ targets: ["namespace_attributes"]
206
+ config:
207
+ removal_strategy: "selective"
208
+ preserve_data: false
209
+ ----
210
+
211
+ **Targets**: link:requirements.adoc#namespace-attributes-requirement[NamespaceAttributesRequirement] violations
212
+ **Remediation Type**: Remove
213
+ **Confidence**: Safe Removal
214
+
215
+ Features:
216
+ * Removes attributes from disallowed namespaces
217
+ * Selective removal based on namespace blacklist/whitelist
218
+ * Optional data preservation for removed attributes
219
+ * Maintains document structure integrity
220
+
221
+ [[no-external-css-remediation]]
222
+ ==== NoExternalCssRemediation
223
+
224
+ Removes external CSS references.
225
+
226
+ **Configuration Options**:
227
+
228
+ `strategy`:: Removal strategy: `"remove_external_references"`, `"inline_external"`, or `"convert_to_internal"`. Default: `"remove_external_references"`.
229
+ `preserve_internal_styles`:: Boolean flag to preserve internal `<style>` elements. Default: `true`.
230
+
231
+ Configuration:
232
+ [source,yaml]
233
+ ----
234
+ - id: "remove_external_css"
235
+ type: "NoExternalCssRemediation"
236
+ description: "Remove external CSS references"
237
+ targets: ["no_external_css"]
238
+ config:
239
+ strategy: "remove_external_references"
240
+ preserve_internal_styles: true
241
+ ----
242
+
243
+ **Targets**: link:requirements.adoc#no-external-css-requirement[NoExternalCssRequirement] violations
244
+ **Remediation Type**: Remove
245
+ **Confidence**: Safe Removal
246
+
247
+ Features:
248
+ * Removes external `<link>` elements
249
+ * Strips `@import` statements from `<style>` elements
250
+ * Removes external URLs from style attributes
251
+ * Optional preservation of internal styles
252
+ * Configurable removal strategies
253
+
254
+ === Addition remediations
255
+
256
+ [[viewbox-remediation]]
257
+ ==== ViewboxRemediation
258
+
259
+ Adds missing viewBox attributes to root SVG elements.
260
+
261
+ **Configuration Options**:
262
+
263
+ `generation_strategy`:: Strategy for viewBox generation: `"from_dimensions"`, `"from_content"`, or `"default"`. Default: `"from_dimensions"`.
264
+ `default_viewbox`:: Default viewBox value when automatic generation fails. Default: `"0 0 100 100"`.
265
+ `preserve_existing`:: Boolean flag to preserve existing viewBox attributes. Default: `true`.
266
+ `auto_calculate_bounds`:: Boolean flag to calculate bounds from SVG content. Default: `false`.
267
+
268
+ Configuration:
269
+ [source,yaml]
270
+ ----
271
+ - id: "add_viewbox"
272
+ type: "ViewboxRemediation"
273
+ description: "Add missing viewBox attributes"
274
+ targets: ["viewbox_required"]
275
+ config:
276
+ generation_strategy: "from_dimensions"
277
+ default_viewbox: "0 0 100 100"
278
+ preserve_existing: true
279
+ auto_calculate_bounds: false
280
+ ----
281
+
282
+ **Targets**: link:requirements.adoc#viewbox-required-requirement[ViewboxRequiredRequirement] violations
283
+ **Remediation Type**: Add
284
+ **Confidence**: Safe Structural
285
+
286
+ Features:
287
+ * Auto-generates viewBox from width/height attributes
288
+ * Handles malformed viewBox values
289
+ * Preserves existing valid viewBox attributes
290
+ * Optional content-based bounds calculation
291
+ * Configurable fallback values
292
+
293
+ === Style processing remediations
294
+
295
+ [[style-promotion-remediation]]
296
+ ==== StylePromotionRemediation
297
+
298
+ Promotes CSS style properties to SVG attributes.
299
+
300
+ **Configuration Options**:
301
+
302
+ `promotable_properties`:: List of CSS properties that can be promoted to SVG attributes.
303
+ `preserve_style_attribute`:: Boolean flag to preserve original style attribute after promotion. Default: `false`.
304
+ `selective_promotion`:: Boolean flag to promote only when beneficial. Default: `true`.
305
+
306
+ Configuration:
307
+ [source,yaml]
308
+ ----
309
+ - id: "promote_styles"
310
+ type: "StylePromotionRemediation"
311
+ description: "Promote style properties to attributes"
312
+ targets: ["style_promotion"]
313
+ config:
314
+ preserve_style_attribute: false
315
+ selective_promotion: true
316
+ promotable_properties:
317
+ - "fill"
318
+ - "stroke"
319
+ - "font-family"
320
+ - "font-size"
321
+ - "opacity"
322
+ ----
323
+
324
+ **Targets**: link:requirements.adoc#style-promotion-requirement[StylePromotionRequirement] violations
325
+ **Remediation Type**: Promote
326
+ **Confidence**: Automatic
327
+
328
+ Features:
329
+ * Converts style properties to equivalent SVG attributes
330
+ * Improves SVG compatibility and optimization
331
+ * Preserves visual appearance while changing structure
332
+ * Configurable property selection
333
+ * Optional selective promotion based on benefit analysis
334
+
335
+ === Reference fixing remediations
336
+
337
+ [[invalid-id-references-remediation]]
338
+ ==== InvalidIdReferencesRemediation
339
+
340
+ Fixes or removes broken ID references.
341
+
342
+ **Configuration Options**:
343
+
344
+ `strategy`:: Fixing strategy: `"remove_broken_elements"`, `"remove_references"`, or `"create_placeholders"`. Default: `"remove_broken_elements"`.
345
+ `preserve_structure`:: Boolean flag to maintain document structure when removing elements. Default: `true`.
346
+ `placeholder_content`:: Content to use for placeholder elements when using `"create_placeholders"` strategy.
347
+
348
+ Configuration:
349
+ [source,yaml]
350
+ ----
351
+ - id: "fix_broken_refs"
352
+ type: "InvalidIdReferencesRemediation"
353
+ description: "Fix broken ID references"
354
+ targets: ["id_references", "invalid_id_references"]
355
+ config:
356
+ strategy: "remove_broken_elements"
357
+ preserve_structure: true
358
+ placeholder_content: "<!-- Missing reference -->"
359
+ ----
360
+
361
+ **Targets**: link:requirements.adoc#id-reference-requirement[IdReferenceRequirement], InvalidIdReferencesRequirement violations
362
+ **Remediation Type**: Remove
363
+ **Confidence**: Safe Removal
364
+
365
+ Features:
366
+ * Removes `<use>` elements with broken href references
367
+ * Removes or fixes other broken ID references
368
+ * Can replace with placeholder content or remove entirely
369
+ * Configurable fixing strategies
370
+ * Maintains document structural integrity
371
+
372
+ == Structural Invalidity and Descendant Skipping
373
+
374
+ SvgConform implements **structural invalidity tracking** to match svgcheck's behavior of removing invalid elements with all their children.
375
+
376
+ === How It Works
377
+
378
+ When an element is determined to be structurally invalid (e.g., not an allowed element, or has an invalid parent-child relationship):
379
+
380
+ 1. **Element marked invalid**: The element is marked as structurally invalid in the validation context
381
+ 2. **Descendants recursively marked**: All child elements are recursively marked as invalid
382
+ 3. **Validation skipping**: All requirements skip validation of structurally invalid nodes
383
+ 4. **Single error reported**: Only the parent element error is reported, not separate errors for each child
384
+
385
+ === Benefits
386
+
387
+ **Prevents Cascade Errors**:
388
+ - Invalid `<font>` element → 48 `<glyph>` children automatically skipped
389
+ - Invalid `<clipPath>` parent → all children skipped
390
+ - Matches svgcheck: removes element WITH all children
391
+
392
+ **Example**:
393
+
394
+ Without structural invalidity tracking:
395
+ ```
396
+ ERROR: Element 'font' is not allowed as a child of 'defs'
397
+ ERROR: Element 'font-face' is not allowed in this profile
398
+ ERROR: Element 'missing-glyph' is not allowed in this profile
399
+ ERROR: Element 'glyph' is not allowed in this profile (x48 times)
400
+ Total: 51 errors
401
+ ```
402
+
403
+ With structural invalidity tracking:
404
+ ```
405
+ ERROR: Element 'font' is not allowed as a child of 'defs'
406
+ Total: 1 error
407
+ ```
408
+
409
+ === Implementation
410
+
411
+ **Marking Invalid Nodes** (in AllowedElementsRequirement):
412
+ ```ruby
413
+ unless allowed_elements.include?(element_name)
414
+ context.add_error(...)
415
+ context.mark_node_structurally_invalid(node) # Marks node and all descendants
416
+ return
417
+ end
418
+ ```
419
+
420
+ **Skipping Invalid Nodes** (in BaseRequirement):
421
+ ```ruby
422
+ def should_check_node?(node, context = nil)
423
+ return false unless node.respond_to?(:name) && node.respond_to?(:attributes)
424
+ return false if context && context.node_structurally_invalid?(node)
425
+ true
426
+ end
427
+ ```
428
+
429
+ **Recursive Descendant Marking** (in ValidationContext):
430
+ ```ruby
431
+ def mark_node_structurally_invalid(node)
432
+ @structurally_invalid_node_ids.add(generate_node_id(node))
433
+ mark_descendants_invalid(node) # Recursively mark all descendants
434
+ end
435
+ ```
436
+
437
+ === Impact on Remediations
438
+
439
+ Remediations automatically benefit from structural invalidity tracking:
440
+
441
+ * **Fewer errors to process**: Only parent errors, not descendant errors
442
+ * **Cleaner error reports**: More focused, actionable error messages
443
+ * **Better performance**: Less validation work on invalid subtrees
444
+ * **Matches svgcheck**: 100% compatibility with svgcheck behavior
445
+
446
+ == Violation Types and Remediability
447
+
448
+ SvgConform categorizes violations into two main types:
449
+
450
+ === Remediable Violations
451
+
452
+ These can be automatically fixed through remediation processing:
453
+
454
+ **ColorViolation** (`color_restrictions`):
455
+ * **Remediation**: Convert using CssColor equivalence system
456
+ * **Examples**: `red` → `black`, `#f00` → `#000000`
457
+ * **Confidence**: Automatic
458
+
459
+ **FontViolation** (`font_family`):
460
+ * **Remediation**: Map to generic font families
461
+ * **Examples**: `Arial` → `sans-serif`, `Times New Roman` → `serif`
462
+ * **Confidence**: Automatic
463
+
464
+ **ContentViolation** (`forbidden_content`):
465
+ * **Remediation**: Remove forbidden elements/attributes
466
+ * **Examples**: Remove `<script>`, `onclick` attributes
467
+ * **Confidence**: Safe removal
468
+
469
+ **ReferenceViolation** (`id_reference`, `link_validation`):
470
+ * **Remediation**: Remove broken references or elements
471
+ * **Examples**: Remove `<use>` with invalid href, broken links
472
+ * **Confidence**: Safe removal
473
+
474
+ **NamespaceViolation** (`namespace`, `namespace_attributes`):
475
+ * **Remediation**: Remove invalid namespace elements/attributes
476
+ * **Examples**: Remove `<inkscape:layer>`, `custom:attr`
477
+ * **Confidence**: Safe removal
478
+
479
+ **ViewboxViolation** (`viewbox_required`):
480
+ * **Remediation**: Add missing viewBox attributes
481
+ * **Examples**: Generate from width/height dimensions
482
+ * **Confidence**: Safe structural
483
+
484
+ **StyleViolation** (`style`, `style_promotion`):
485
+ * **Remediation**: Promote or convert style properties
486
+ * **Examples**: Move `style="fill:black"` to `fill="black"`
487
+ * **Confidence**: Automatic
488
+
489
+ === Non-Remediable Violations
490
+
491
+ These require manual intervention:
492
+
493
+ **StructuralViolation**:
494
+ * **Examples**: Malformed XML, root element not `<svg>`, invalid document hierarchy
495
+ * **Reason**: Automatic fixing could break document integrity or change meaning
496
+ * **Solution**: Manual document restructuring required
497
+
498
+ == Configuration Best Practices
499
+
500
+ === Remediation Configuration
501
+
502
+ **Target Mapping**:
503
+ [source,yaml]
504
+ ----
505
+ remediations:
506
+ - id: "comprehensive_color_fix"
507
+ type: "ColorRemediation"
508
+ description: "Handle all color violations"
509
+ targets: ["color_restrictions", "style_colors"] # Multiple targets
510
+ ----
511
+
512
+ **Strategy Selection**:
513
+ [source,yaml]
514
+ ----
515
+ - id: "safe_id_fix"
516
+ type: "InvalidIdReferencesRemediation"
517
+ targets: ["id_references"]
518
+ config:
519
+ strategy: "remove_references" # Conservative approach
520
+ preserve_structure: true
521
+
522
+ - id: "aggressive_id_fix"
523
+ type: "InvalidIdReferencesRemediation"
524
+ targets: ["id_references"]
525
+ config:
526
+ strategy: "remove_broken_elements" # More thorough cleanup
527
+ preserve_structure: false
528
+ ----
529
+
530
+ === Performance Optimization
531
+
532
+ **Efficient Remediation Order**:
533
+ 1. **Namespace cleanups** (removes invalid content early)
534
+ 2. **Content removal** (reduces document size for subsequent processing)
535
+ 3. **Content conversion** (processes remaining valid content)
536
+ 4. **Structure additions** (adds missing required elements)
537
+ 5. **Style promotion** (final optimization step)
538
+
539
+ **Remediation Grouping**:
540
+ [source,yaml]
541
+ ----
542
+ # Group related remediations for efficiency
543
+ remediations:
544
+ - id: "namespace_cleanup"
545
+ type: "NamespaceRemediation"
546
+ targets: ["namespace_validation"]
547
+ - id: "namespace_attrs_cleanup"
548
+ type: "NamespaceAttributeRemediation"
549
+ targets: ["namespace_attributes"]
550
+ - id: "color_conversion"
551
+ type: "ColorRemediation"
552
+ targets: ["color_restrictions"]
553
+ ----
554
+
555
+ === Safety Configuration
556
+
557
+ **Conservative Settings**:
558
+ [source,yaml]
559
+ ----
560
+ - id: "safe_remediation"
561
+ type: "NamespaceRemediation"
562
+ config:
563
+ preserve_content: true # Don't lose content
564
+ cleanup_declarations: false # Minimal cleanup
565
+ ----
566
+
567
+ **Aggressive Settings**:
568
+ [source,yaml]
569
+ ----
570
+ - id: "thorough_cleanup"
571
+ type: "NamespaceRemediation"
572
+ config:
573
+ preserve_content: false # Remove invalid content
574
+ cleanup_declarations: true # Full cleanup
575
+ ----
576
+
577
+ == Advanced Configuration
578
+
579
+ === Conditional Remediations
580
+
581
+ Remediations can be configured to apply conditionally based on document characteristics:
582
+
583
+ [source,yaml]
584
+ ----
585
+ - id: "conditional_color_fix"
586
+ type: "ColorRemediation"
587
+ description: "Apply color conversion only to specific elements"
588
+ targets: ["color_restrictions"]
589
+ config:
590
+ apply_to_elements: ["rect", "circle"] # Only fix colors on these elements
591
+ conversion_strategy: "threshold"
592
+ ----
593
+
594
+ === Custom Remediation Strategies
595
+
596
+ Define custom strategies for complex remediation scenarios:
597
+
598
+ [source,yaml]
599
+ ----
600
+ - id: "smart_font_mapping"
601
+ type: "FontRemediation"
602
+ targets: ["font_family"]
603
+ config:
604
+ font_mapping:
605
+ # Map common fonts to generic equivalents
606
+ "Arial": "sans-serif"
607
+ "Helvetica": "sans-serif"
608
+ "Georgia": "serif"
609
+ "Verdana": "sans-serif"
610
+ fallback_strategy: "closest_generic" # Find closest generic match
611
+ preserve_fallbacks: true
612
+ ----
613
+
614
+ === Remediation Chaining
615
+
616
+ Configure remediations to work together in sequence:
617
+
618
+ [source,yaml]
619
+ ----
620
+ remediations:
621
+ # Step 1: Clean up namespaces
622
+ - id: "namespace_cleanup"
623
+ type: "NamespaceRemediation"
624
+ targets: ["namespace_validation"]
625
+
626
+ # Step 2: Remove invalid attributes (depends on step 1)
627
+ - id: "attribute_cleanup"
628
+ type: "NamespaceAttributeRemediation"
629
+ targets: ["namespace_attributes"]
630
+ depends_on: ["namespace_cleanup"]
631
+
632
+ # Step 3: Fix remaining content (depends on steps 1-2)
633
+ - id: "content_fixes"
634
+ type: "ColorRemediation"
635
+ targets: ["color_restrictions"]
636
+ depends_on: ["namespace_cleanup", "attribute_cleanup"]
637
+ ----
638
+
639
+ == Enhanced Color System
640
+
641
+ SvgConform uses the `CssColor` class for advanced color equivalence recognition:
642
+
643
+ === Color Equivalence Examples
644
+
645
+ [source]
646
+ ----
647
+ # These are all equivalent and recognized as "white":
648
+ white
649
+ #ffffff
650
+ #FFFFFF
651
+ #fff
652
+ #FFF
653
+ rgb(255,255,255)
654
+ rgba(255,255,255,1.0)
655
+
656
+ # These are all equivalent and recognized as "black":
657
+ black
658
+ #000000
659
+ #000
660
+ rgb(0,0,0)
661
+ ----
662
+
663
+ === Color Conversion Features
664
+
665
+ * **Normalization**: All color formats converted to canonical hex
666
+ * **Named Color Support**: Full CSS named color palette
667
+ * **Case Insensitive**: Hex colors match regardless of case
668
+ * **Short Hex Expansion**: `#fff` automatically expands to `#ffffff`
669
+ * **RGB Function Parsing**: `rgb(255,0,0)` converts to `#ff0000`
670
+ * **Equivalence Checking**: Smart matching across all formats
671
+
672
+ Usage in color remediation:
673
+ [source,ruby]
674
+ ----
675
+ # These will all be recognized as equivalent to "white":
676
+ CssColor.equivalent?("#fff", "white") # => true
677
+ CssColor.equivalent?("#FFFFFF", "#fff") # => true
678
+ CssColor.normalize("rgb(255,255,255)") # => "#ffffff"
679
+ CssColor.to_canonical("#fff") # => "white"
680
+ ----
681
+
682
+ == Troubleshooting
683
+
684
+ === Common Remediation Issues
685
+
686
+ **Target Mismatch**:
687
+ - Ensure remediation `targets` match requirement IDs exactly
688
+ - Check that target requirements are included in the same profile
689
+ - Verify requirement IDs are spelled correctly
690
+
691
+ **Configuration Errors**:
692
+ - Validate YAML syntax for remediation configuration
693
+ - Ensure all referenced configuration parameters exist
694
+ - Check parameter types match expected values
695
+
696
+ **Remediation Conflicts**:
697
+ - Avoid multiple remediations targeting the same content
698
+ - Order remediations to prevent conflicts
699
+ - Use conditional application when needed
700
+
701
+ === Debugging Remediations
702
+
703
+ **Enable detailed logging**:
704
+ [source,yaml]
705
+ ----
706
+ - id: "debug_remediation"
707
+ type: "ColorRemediation"
708
+ targets: ["color_restrictions"]
709
+ config:
710
+ debug_logging: true # Enable detailed remediation logs
711
+ trace_changes: true # Track all changes made
712
+ ----
713
+
714
+ **Test remediation results**:
715
+ - Always validate remediated documents
716
+ - Check that visual appearance is preserved
717
+ - Verify no new validation errors are introduced
718
+ - Test with representative SVG files
719
+
720
+ === Performance Troubleshooting
721
+
722
+ **Slow remediations**:
723
+ - Profile remediation performance with timing
724
+ - Check for expensive operations in configuration
725
+ - Consider breaking complex remediations into simpler ones
726
+ - Optimize target requirement selection
727
+
728
+ **Memory usage**:
729
+ - Monitor memory consumption during large document processing
730
+ - Use streaming processing for very large SVG files
731
+ - Consider processing documents in batches
732
+ - Optimize configuration data structures