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,709 @@
1
+ = SVG Requirements
2
+ :toc: left
3
+ :toclevels: 3
4
+ :sectlinks:
5
+ :sectanchors:
6
+ :source-highlighter: rouge
7
+
8
+ == Overview
9
+
10
+ **Requirements** are the core validation logic that check SVG documents for conformance issues. There are two types of requirements:
11
+
12
+ === Structural Requirements
13
+
14
+ Structural requirements validate the basic structure and syntax of SVG documents.
15
+
16
+ === Logical Requirements
17
+
18
+ Logical requirements validate the content and semantics of SVG documents.
19
+
20
+ Requirements can be configured with specific parameters to customize their behavior for different use cases. Each requirement type provides configuration options that affect how validation is performed.
21
+
22
+ == Available requirements
23
+
24
+ SvgConform provides 15 different requirement types that can be configured in profiles to validate specific aspects of SVG documents.
25
+
26
+ === Structural requirements
27
+
28
+ These validate the fundamental structure and syntax of SVG documents:
29
+
30
+ [[namespace-requirement]]
31
+ ==== NamespaceRequirement
32
+
33
+ Ensures proper SVG namespace declarations on elements.
34
+
35
+ **Configuration Options**:
36
+
37
+ `allowed_namespaces`:: List of permitted namespace URIs. Default includes SVG and XLink namespaces.
38
+ `required_namespace`:: The namespace URI that must be present on the root element. Default: `"http://www.w3.org/2000/svg"`.
39
+ `allow_rdf_metadata`:: Boolean flag to permit RDF/Dublin Core metadata namespaces. When `true`, RDF namespaces are silently allowed. When `false` (default), RDF namespace errors are generated. Default: `false`.
40
+
41
+ Configuration:
42
+ [source,yaml]
43
+ ----
44
+ - id: "svg_namespace"
45
+ type: "NamespaceRequirement"
46
+ description: "Validate SVG namespace usage"
47
+ allowed_namespaces:
48
+ - "http://www.w3.org/2000/svg"
49
+ - ""
50
+ required_namespace: "http://www.w3.org/2000/svg"
51
+ allow_rdf_metadata: false # or true for permissive RDF handling
52
+ ----
53
+
54
+ .Strict RDF validation (default)
55
+ [example]
56
+ [source,yaml]
57
+ ----
58
+ - id: "namespace_validation"
59
+ type: "NamespaceRequirement"
60
+ allow_rdf_metadata: false # Strict: RDF errors generated
61
+ allowed_namespaces:
62
+ - "http://www.w3.org/2000/svg"
63
+ - ""
64
+ ----
65
+
66
+ RDF namespace elements will trigger validation errors that can be filtered for svgcheck compatibility or reported to users.
67
+
68
+ .Permissive RDF handling
69
+ [example]
70
+ [source,yaml]
71
+ ----
72
+ - id: "namespace_validation"
73
+ type: "NamespaceRequirement"
74
+ allow_rdf_metadata: true # Permissive: RDF silently allowed
75
+ allowed_namespaces:
76
+ - "http://www.w3.org/2000/svg"
77
+ - ""
78
+ ----
79
+
80
+ RDF/Dublin Core metadata elements are silently accepted without generating errors.
81
+
82
+ Features:
83
+ * Validates root SVG element has correct namespace
84
+ * Removes elements with disallowed namespaces
85
+ * Supports whitelist and blacklist modes
86
+ * **Configurable RDF metadata support**: Control whether RDF namespaces are allowed
87
+ * **Generic namespace detection**: No hardcoded element names
88
+
89
+ **Supported RDF Namespaces** (when `allow_rdf_metadata: true`):
90
+ - `http://www.w3.org/1999/02/22-rdf-syntax-ns#`
91
+ - `http://creativecommons.org/ns#`
92
+ - `http://purl.org/dc/elements/1.1/`
93
+ - `http://purl.org/dc/dcmitype/`
94
+ - `http://www.w3.org/2000/01/rdf-schema#`
95
+
96
+ For complete RDF metadata configuration details, see link:rdf_metadata_support.adoc[RDF Metadata Support Documentation].
97
+
98
+ **Target Remediations**: link:remediation.adoc#namespace-remediation[NamespaceRemediation]
99
+
100
+ [[allowed-elements-requirement]]
101
+ ==== AllowedElementsRequirement
102
+
103
+ Restricts which SVG elements and attributes are permitted.
104
+
105
+ **Configuration Options**:
106
+
107
+ `element_configs`:: List of element configuration objects defining allowed elements and their attributes.
108
+ `check_attributes`:: Boolean flag to enable attribute validation. Default: `false`.
109
+ `check_parent_child`:: Boolean flag to enable parent-child relationship validation. Default: `false`.
110
+ `skip_foreign_namespaces`:: Boolean flag to skip validation of foreign namespace elements. When `true`, elements in non-SVG namespaces are skipped and handled by NamespaceRequirement instead. Default: `false`.
111
+ `allowed_namespaces`:: List of namespace URIs that are considered valid (not foreign). Used with `skip_foreign_namespaces`. Default: `[]`.
112
+ `allow_rdf_metadata`:: Boolean flag to permit RDF/Dublin Core metadata namespaces. When `true`, RDF namespace elements are considered valid and skipped. Default: `false`.
113
+
114
+ Each element configuration object supports:
115
+ - `tag`: Element name (required)
116
+ - `attributes`: List of allowed attribute names
117
+ - `required_attributes`: List of mandatory attribute names
118
+ - `allowed_children`: List of allowed child element names
119
+
120
+ Configuration:
121
+ [source,yaml]
122
+ ----
123
+ - id: "svg_elements"
124
+ type: "AllowedElementsRequirement"
125
+ description: "Restrict to allowed SVG elements"
126
+ skip_foreign_namespaces: true
127
+ allow_rdf_metadata: false
128
+ allowed_namespaces:
129
+ - "http://www.w3.org/2000/svg"
130
+ - ""
131
+ element_configs:
132
+ - tag: "svg"
133
+ attributes: ["width", "height", "viewBox", "xmlns"]
134
+ required_attributes: ["viewBox"]
135
+ allowed_children: ["g", "rect", "circle", "path", "text"]
136
+ - tag: "rect"
137
+ attributes: ["x", "y", "width", "height", "fill", "stroke"]
138
+ - tag: "circle"
139
+ attributes: ["cx", "cy", "r", "fill", "stroke"]
140
+ check_attributes: true
141
+ check_parent_child: true
142
+ ----
143
+
144
+ .Generic namespace skipping
145
+ [example]
146
+ [source,yaml]
147
+ ----
148
+ - id: "allowed_elements"
149
+ type: "AllowedElementsRequirement"
150
+ skip_foreign_namespaces: true
151
+ allowed_namespaces:
152
+ - "http://www.w3.org/2000/svg"
153
+ - ""
154
+ element_configs:
155
+ # ... element definitions
156
+ ----
157
+
158
+ With `skip_foreign_namespaces: true`, elements in foreign namespaces (not in `allowed_namespaces`) are skipped during validation. This allows NamespaceRequirement to handle foreign namespace validation, preventing duplicate errors.
159
+
160
+ Features:
161
+ * Configurable whitelist of allowed elements and attributes
162
+ * Parent-child relationship validation
163
+ * Required attribute enforcement
164
+ * **Generic namespace skipping**: Skip foreign namespace elements without hardcoding
165
+ * **RDF metadata support**: Configurable via `allow_rdf_metadata` flag
166
+ * **Structural invalidity tracking**: Invalid elements marked to skip descendant validation
167
+ * **Zero hardcoding**: All element and namespace handling configuration-driven
168
+
169
+ **Structural Invalidity Behavior**:
170
+
171
+ When an element is marked as structurally invalid (not allowed, or invalid parent-child relationship):
172
+ 1. The element is marked as structurally invalid
173
+ 2. All descendants are recursively marked invalid
174
+ 3. All requirements skip invalid nodes and their descendants
175
+ 4. Matches svgcheck behavior: removes element WITH all children
176
+
177
+ This prevents cascade errors where children of invalid elements are separately reported.
178
+
179
+ **Target Remediations**: Content removal remediations (elements removed by validation logic)
180
+
181
+ [[viewbox-required-requirement]]
182
+ ==== ViewboxRequiredRequirement
183
+
184
+ Requires viewBox attribute on root SVG element.
185
+
186
+ **Configuration Options**:
187
+
188
+ `auto_generate`:: Boolean flag to enable automatic viewBox generation from width/height. Default: `false`.
189
+ `preserve_aspect_ratio`:: Boolean flag to maintain aspect ratio during generation. Default: `true`.
190
+
191
+ Configuration:
192
+ [source,yaml]
193
+ ----
194
+ - id: "viewbox_required"
195
+ type: "ViewboxRequiredRequirement"
196
+ description: "Require viewBox on root element"
197
+ config:
198
+ auto_generate: true
199
+ preserve_aspect_ratio: true
200
+ ----
201
+
202
+ Features:
203
+ * Validates presence of viewBox attribute
204
+ * Validates viewBox format (four space-separated numbers)
205
+ * Critical for scalable SVG rendering
206
+ * Optional auto-generation from width/height attributes
207
+
208
+ **Target Remediations**: link:remediation.adoc#viewbox-remediation[ViewboxRemediation]
209
+
210
+ [[namespace-attributes-requirement]]
211
+ ==== NamespaceAttributesRequirement
212
+
213
+ Validates attributes don't use disallowed namespaces.
214
+
215
+ **Configuration Options**:
216
+
217
+ `disallowed_namespaces`:: List of namespace URIs that are not permitted on attributes.
218
+ `allowed_namespaces`:: List of namespace URIs that are explicitly allowed (whitelist mode).
219
+ `mode`:: Validation mode: `"blacklist"` (default) or `"whitelist"`.
220
+
221
+ Configuration:
222
+ [source,yaml]
223
+ ----
224
+ - id: "namespace_attrs"
225
+ type: "NamespaceAttributesRequirement"
226
+ description: "Control namespace attribute usage"
227
+ config:
228
+ mode: "blacklist"
229
+ disallowed_namespaces:
230
+ - "http://custom.namespace.com"
231
+ - "http://www.inkscape.org/namespaces/inkscape"
232
+ - "http://www.lucidchart.com/chart"
233
+ ----
234
+
235
+ Features:
236
+ * Removes attributes from disallowed namespaces
237
+ * Supports both whitelist and blacklist modes
238
+ * Preserves valid namespace attributes (xlink, xml)
239
+ * Configurable namespace filtering
240
+
241
+ **Target Remediations**: link:remediation.adoc#namespace-attribute-remediation[NamespaceAttributeRemediation]
242
+
243
+ === Content requirements
244
+
245
+ These validate the content and semantics of SVG documents:
246
+
247
+ [[color-restrictions-requirement]]
248
+ ==== ColorRestrictionsRequirement
249
+
250
+ Enforces color usage restrictions with enhanced equivalence detection and threshold-based validation.
251
+
252
+ **Configuration Options**:
253
+
254
+ `mode`:: Color restriction mode. Currently supports `"black_white_only"`.
255
+ `allowed_colors`:: List of exact color strings that are permitted.
256
+ `black_and_white_threshold`:: Optional RGB sum threshold for strict validation. When specified, only exact string matches from `allowed_colors` are permitted.
257
+ `case_sensitive`:: Boolean flag for case-sensitive color matching. Default: `false`.
258
+
259
+ Configuration:
260
+ [source,yaml]
261
+ ----
262
+ - id: "colors"
263
+ type: "ColorRestrictionsRequirement"
264
+ description: "Restrict colors to black and white"
265
+ config:
266
+ mode: "black_white_only"
267
+ allowed_colors: ["black", "white", "#000000", "#ffffff", "none", "inherit", "currentColor"]
268
+ black_and_white_threshold: 764 # Optional: RGB sum threshold for strict validation
269
+ case_sensitive: false
270
+ ----
271
+
272
+ Where,
273
+
274
+ `mode`:: The color restriction mode. Currently supports `black_white_only`.
275
+ `allowed_colors`:: List of exact color strings that are permitted.
276
+ `black_and_white_threshold`:: Optional RGB sum threshold for strict validation. When specified, only exact string matches from `allowed_colors` are permitted, and threshold logic is applied during remediation.
277
+
278
+ .Using strict black and white validation with RGB threshold
279
+ [example]
280
+ ====
281
+ [source,yaml]
282
+ ----
283
+ - id: "strict_colors"
284
+ type: "ColorRestrictionsRequirement"
285
+ description: "Strict black and white validation for technical documents"
286
+ config:
287
+ mode: "black_white_only"
288
+ black_and_white_threshold: 764
289
+ allowed_colors: ["black", "white", "#000000", "#ffffff", "#FFFFFF", "none", "inherit", "currentColor"]
290
+ ----
291
+ ====
292
+
293
+ This configuration enables strict validation where only exact color strings are accepted during validation, while threshold-based conversion (RGB sum ≤ 764 → black, RGB sum > 764 → white) is applied during remediation.
294
+
295
+ Features:
296
+ * **Enhanced color equivalence**: `#fff` ↔ `#ffffff` ↔ `white` (when threshold not specified)
297
+ * **Strict format validation**: When `black_and_white_threshold` is specified, only exact strings from `allowed_colors` are permitted
298
+ * **Percentage RGB support**: `rgb(100%,100%,100%)` and mixed formats handled
299
+ * **Case-insensitive processing**: `BLACK` → `black` normalization
300
+ * **RGB function support**: `rgb(255,255,255)` → `white` equivalence
301
+ * **Short hex expansion**: `#000` → `#000000` normalization
302
+ * Validates fill, stroke, and style attributes
303
+
304
+ **Target Remediations**: link:remediation.adoc#color-remediation[ColorRemediation]
305
+
306
+ [[font-family-requirement]]
307
+ ==== FontFamilyRequirement
308
+
309
+ Controls font family usage and validates font specifications.
310
+
311
+ **Configuration Options**:
312
+
313
+ `allowed_families`:: List of permitted font family names (case-insensitive).
314
+ `default_family`:: Default font family to suggest in error messages. Default: `"sans-serif"`.
315
+ `strict_mode`:: Boolean flag to enable strict font validation. Default: `false`.
316
+ `allow_generic`:: Boolean flag to allow CSS generic font families. Default: `true`.
317
+
318
+ Configuration:
319
+ [source,yaml]
320
+ ----
321
+ - id: "fonts"
322
+ type: "FontFamilyRequirement"
323
+ description: "Restrict to generic font families"
324
+ config:
325
+ allowed_families: ["serif", "sans-serif", "monospace"]
326
+ default_family: "sans-serif"
327
+ strict_mode: true
328
+ allow_generic: true
329
+ ----
330
+
331
+ Features:
332
+ * Restricts to specific font families
333
+ * Validates both font-family attributes and style properties
334
+ * Handles comma-separated font family lists
335
+ * Support for CSS generic font families
336
+ * Case-insensitive font name matching
337
+
338
+ **Target Remediations**: link:remediation.adoc#font-remediation[FontRemediation]
339
+
340
+ [[forbidden-content-requirement]]
341
+ ==== ForbiddenContentRequirement
342
+
343
+ Prevents inclusion of forbidden elements and attributes.
344
+
345
+ **Configuration Options**:
346
+
347
+ `forbidden_elements`:: List of element names that are not permitted.
348
+ `forbidden_attributes`:: List of attribute names that are not permitted.
349
+ `case_sensitive`:: Boolean flag for case-sensitive matching. Default: `false`.
350
+ `remove_content`:: Boolean flag to remove forbidden content during validation. Default: `false`.
351
+
352
+ Configuration:
353
+ [source,yaml]
354
+ ----
355
+ - id: "no_scripts"
356
+ type: "ForbiddenContentRequirement"
357
+ description: "Prevent scripting and multimedia"
358
+ config:
359
+ forbidden_elements: ["script", "audio", "video", "object", "embed"]
360
+ forbidden_attributes: ["onclick", "onload", "onmouseover", "onchange"]
361
+ case_sensitive: false
362
+ remove_content: true
363
+ ----
364
+
365
+ Features:
366
+ * Configurable lists of forbidden elements and attributes
367
+ * Useful for security-focused profiles
368
+ * Supports multimedia and scripting restrictions
369
+ * Optional content removal during validation
370
+
371
+ **Target Remediations**: Content removal occurs during validation when `remove_content` is enabled
372
+
373
+ [[no-external-css-requirement]]
374
+ ==== NoExternalCssRequirement
375
+
376
+ Prevents external CSS references to ensure self-contained documents.
377
+
378
+ **Configuration Options**:
379
+
380
+ `allowed_protocols`:: List of permitted URL protocols. Empty list blocks all external references.
381
+ `allow_data_urls`:: Boolean flag to allow data: URLs. Default: `true`.
382
+ `strict_mode`:: Boolean flag for strict URL validation. Default: `false`.
383
+
384
+ Configuration:
385
+ [source,yaml]
386
+ ----
387
+ - id: "no_external_css"
388
+ type: "NoExternalCssRequirement"
389
+ description: "Block external CSS references"
390
+ config:
391
+ allowed_protocols: [] # No external protocols allowed
392
+ allow_data_urls: true
393
+ strict_mode: true
394
+ ----
395
+
396
+ Features:
397
+ * Blocks `@import` statements in `<style>` elements
398
+ * Prevents external stylesheet `<link>` elements
399
+ * Validates URL references in style attributes
400
+ * Configurable protocol restrictions
401
+
402
+ **Target Remediations**: link:remediation.adoc#no-external-css-remediation[NoExternalCssRemediation]
403
+
404
+ === Reference requirements
405
+
406
+ These validate links and references within SVG documents:
407
+
408
+ [[id-reference-requirement]]
409
+ ==== IdReferenceRequirement
410
+
411
+ Validates that ID references point to existing elements.
412
+
413
+ **Configuration Options**:
414
+
415
+ `strict_validation`:: Boolean flag for strict ID reference checking. Default: `true`.
416
+ `allow_external_refs`:: Boolean flag to allow references to external documents. Default: `false`.
417
+ `case_sensitive`:: Boolean flag for case-sensitive ID matching. Default: `true`.
418
+
419
+ Configuration:
420
+ [source,yaml]
421
+ ----
422
+ - id: "valid_ids"
423
+ type: "IdReferenceRequirement"
424
+ description: "Ensure ID references are valid"
425
+ config:
426
+ strict_validation: true
427
+ allow_external_refs: false
428
+ case_sensitive: true
429
+ ----
430
+
431
+ Features:
432
+ * Validates `<use>` element href references
433
+ * Checks URL fragments in various attributes
434
+ * Prevents broken internal links
435
+ * Configurable strictness levels
436
+
437
+ **Target Remediations**: link:remediation.adoc#invalid-id-references-remediation[InvalidIdReferencesRemediation]
438
+
439
+ [[link-validation-requirement]]
440
+ ==== LinkValidationRequirement
441
+
442
+ Validates that links use only ASCII characters (IETF requirement).
443
+
444
+ **Configuration Options**:
445
+
446
+ `ascii_only`:: Boolean flag to restrict links to ASCII characters. Default: `true`.
447
+ `allow_unicode`:: Boolean flag to allow Unicode characters in links. Default: `false`.
448
+ `encoding_check`:: Boolean flag to validate proper URL encoding. Default: `true`.
449
+
450
+ Configuration:
451
+ [source,yaml]
452
+ ----
453
+ - id: "ascii_links"
454
+ type: "LinkValidationRequirement"
455
+ description: "Links must be ASCII-only"
456
+ config:
457
+ ascii_only: true
458
+ allow_unicode: false
459
+ encoding_check: true
460
+ ----
461
+
462
+ Features:
463
+ * Validates href attributes contain only ASCII
464
+ * Required for RFC 7996 compliance
465
+ * Prevents internationalization issues
466
+ * Configurable character set restrictions
467
+
468
+ **Target Remediations**: Manual link correction required (no automatic remediation available)
469
+
470
+ === Style requirements
471
+
472
+ These validate CSS styling within SVG documents:
473
+
474
+ [[style-requirement]]
475
+ ==== StyleRequirement
476
+
477
+ Comprehensive CSS style validation including syntax, properties, and values.
478
+
479
+ **Configuration Options**:
480
+
481
+ `allowed_properties`:: List of permitted CSS property names.
482
+ `property_values`:: Hash mapping CSS properties to allowed values.
483
+ `strict_syntax`:: Boolean flag for strict CSS syntax validation. Default: `false`.
484
+ `validate_values`:: Boolean flag to validate property values. Default: `true`.
485
+
486
+ Configuration:
487
+ [source,yaml]
488
+ ----
489
+ - id: "valid_styles"
490
+ type: "StyleRequirement"
491
+ description: "Validate CSS style syntax and properties"
492
+ config:
493
+ strict_syntax: true
494
+ validate_values: true
495
+ allowed_properties: ["fill", "stroke", "font-family", "font-size"]
496
+ property_values:
497
+ "fill": ["black", "white", "none"]
498
+ "stroke": ["black", "white", "none"]
499
+ "font-family": ["serif", "sans-serif", "monospace"]
500
+ ----
501
+
502
+ Features:
503
+ * CSS syntax validation
504
+ * Property whitelist enforcement
505
+ * Property value validation with type checking
506
+ * Supports complex property configurations
507
+ * Flexible validation rules
508
+
509
+ **Target Remediations**: Manual style correction required (validation-focused requirement)
510
+
511
+ [[style-promotion-requirement]]
512
+ ==== StylePromotionRequirement
513
+
514
+ Detects style properties that should be promoted to SVG attributes.
515
+
516
+ **Configuration Options**:
517
+
518
+ `promotable_properties`:: List of CSS properties that can become SVG attributes.
519
+ `auto_promote`:: Boolean flag to automatically promote during validation. Default: `false`.
520
+ `preserve_style`:: Boolean flag to preserve original style attribute. Default: `false`.
521
+
522
+ Configuration:
523
+ [source,yaml]
524
+ ----
525
+ - id: "promote_styles"
526
+ type: "StylePromotionRequirement"
527
+ description: "Detect styles that should be attributes"
528
+ config:
529
+ auto_promote: false
530
+ preserve_style: false
531
+ promotable_properties: ["fill", "stroke", "font-family", "font-size", "opacity"]
532
+ ----
533
+
534
+ Features:
535
+ * Identifies style properties that can be SVG attributes
536
+ * Helps with SVG optimization and compatibility
537
+ * Configurable property promotion rules
538
+ * Optional automatic promotion during validation
539
+
540
+ **Target Remediations**: link:remediation.adoc#style-promotion-remediation[StylePromotionRemediation]
541
+
542
+ == Configuration Best Practices
543
+
544
+ === Parameter Types
545
+
546
+ Requirements support several parameter types:
547
+
548
+ **String parameters**:
549
+ [source,yaml]
550
+ ----
551
+ config:
552
+ required_namespace: "http://www.w3.org/2000/svg"
553
+ default_family: "sans-serif"
554
+ ----
555
+
556
+ **Boolean parameters**:
557
+ [source,yaml]
558
+ ----
559
+ config:
560
+ strict_mode: true
561
+ case_sensitive: false
562
+ auto_generate: true
563
+ ----
564
+
565
+ **Array parameters**:
566
+ [source,yaml]
567
+ ----
568
+ config:
569
+ allowed_colors: ["black", "white", "#000000"]
570
+ forbidden_elements: ["script", "audio", "video"]
571
+ ----
572
+
573
+ **Hash parameters**:
574
+ [source,yaml]
575
+ ----
576
+ config:
577
+ property_values:
578
+ "fill": ["black", "white", "none"]
579
+ "font-family": ["serif", "sans-serif"]
580
+ ----
581
+
582
+ **Nested object parameters**:
583
+ [source,yaml]
584
+ ----
585
+ config:
586
+ element_configs:
587
+ - tag: "rect"
588
+ attributes: ["x", "y", "width", "height"]
589
+ required_attributes: ["width", "height"]
590
+ ----
591
+
592
+ === Validation Modes
593
+
594
+ Many requirements support different validation modes:
595
+
596
+ **Strict vs Permissive**:
597
+ - `strict_mode: true` - Fails validation for any non-compliant content
598
+ - `strict_mode: false` - Issues warnings but allows content
599
+
600
+ **Whitelist vs Blacklist**:
601
+ - `mode: "whitelist"` - Only explicitly allowed items pass validation
602
+ - `mode: "blacklist"` - Only explicitly forbidden items fail validation
603
+
604
+ **Case Sensitivity**:
605
+ - `case_sensitive: true` - Exact case matching required
606
+ - `case_sensitive: false` - Case-insensitive matching
607
+
608
+ === Performance Considerations
609
+
610
+ **Efficient Configuration**:
611
+ - Use specific allowed lists rather than broad restrictions
612
+ - Avoid overly complex regular expressions in validation
613
+ - Consider validation frequency vs. thoroughness tradeoffs
614
+
615
+ **Memory Usage**:
616
+ - Large allowed/forbidden lists consume more memory
617
+ - Complex nested configurations increase processing time
618
+ - Balance configuration detail with performance needs
619
+
620
+ == Advanced Configuration
621
+
622
+ === Conditional Requirements
623
+
624
+ Requirements can be configured to apply conditionally:
625
+
626
+ [source,yaml]
627
+ ----
628
+ - id: "conditional_colors"
629
+ type: "ColorRestrictionsRequirement"
630
+ description: "Apply color restrictions only to specific elements"
631
+ config:
632
+ mode: "black_white_only"
633
+ allowed_colors: ["black", "white"]
634
+ apply_to_elements: ["rect", "circle", "path"] # Only validate these elements
635
+ ----
636
+
637
+ === Custom Validation Rules
638
+
639
+ Requirements support custom validation logic through configuration:
640
+
641
+ [source,yaml]
642
+ ----
643
+ - id: "custom_element_validation"
644
+ type: "AllowedElementsRequirement"
645
+ description: "Custom element validation with business logic"
646
+ config:
647
+ element_configs:
648
+ - tag: "text"
649
+ attributes: ["x", "y", "font-family"]
650
+ custom_rules:
651
+ - rule: "max_length"
652
+ value: 100
653
+ - rule: "required_parent"
654
+ value: ["g", "svg"]
655
+ ----
656
+
657
+ === Profile-Specific Configuration
658
+
659
+ Requirements can have different configurations per profile:
660
+
661
+ [source,yaml]
662
+ ----
663
+ # In profile A - strict colors
664
+ - id: "colors"
665
+ type: "ColorRestrictionsRequirement"
666
+ config:
667
+ mode: "black_white_only"
668
+ black_and_white_threshold: 764
669
+
670
+ # In profile B - relaxed colors
671
+ - id: "colors"
672
+ type: "ColorRestrictionsRequirement"
673
+ config:
674
+ mode: "black_white_only"
675
+ allowed_colors: ["black", "white", "gray", "#808080"]
676
+ ----
677
+
678
+ == Troubleshooting
679
+
680
+ === Common Configuration Issues
681
+
682
+ **Invalid parameter names**:
683
+ - Check requirement class documentation for correct parameter names
684
+ - Use `config` hash for all requirement-specific parameters
685
+
686
+ **Type mismatches**:
687
+ - Ensure arrays are provided as YAML lists `[item1, item2]`
688
+ - Ensure booleans are `true`/`false`, not `"true"`/`"false"`
689
+
690
+ **Missing required parameters**:
691
+ - Some requirements have mandatory configuration parameters
692
+ - Check requirement documentation for required vs. optional parameters
693
+
694
+ === Validation Debugging
695
+
696
+ **Enable verbose logging**:
697
+ [source,yaml]
698
+ ----
699
+ - id: "debug_requirement"
700
+ type: "ColorRestrictionsRequirement"
701
+ config:
702
+ verbose_logging: true # Enable detailed validation messages
703
+ debug_mode: true # Include debug information in results
704
+ ----
705
+
706
+ **Test with minimal configuration**:
707
+ - Start with simple configurations and add complexity gradually
708
+ - Use built-in profiles as configuration examples
709
+ - Validate configuration syntax before deployment