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
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ # Load custom tasks
13
+ Dir.glob("lib/tasks/*.rake").each { |r| load r }
14
+
15
+ task default: %i[spec rubocop]
@@ -0,0 +1,34 @@
1
+ name: "base"
2
+ description: "Base SVG validation profile with common requirements"
3
+
4
+ requirements:
5
+ - id: "namespace"
6
+ type: "NamespaceRequirement"
7
+ description: "Validates SVG namespace declaration"
8
+
9
+ - id: "viewbox_required"
10
+ type: "ViewboxRequiredRequirement"
11
+ description: "Ensures SVG has viewBox attribute"
12
+ strict_mode: false
13
+
14
+ - id: "namespace_attributes"
15
+ type: "NamespaceAttributesRequirement"
16
+ description: "Only allows attributes from SVG, XLink, and XML namespaces per RFC 7996 Section 2.1"
17
+ allowed_namespaces:
18
+ - "http://www.w3.org/2000/svg"
19
+ - "http://www.w3.org/1999/xlink"
20
+ - "http://www.w3.org/XML/1998/namespace" # XML namespace (xml:space, xml:lang, etc.)
21
+ - "" # Default namespace (no prefix)
22
+
23
+ remediations:
24
+ - id: "fix_namespace"
25
+ type: "NamespaceRemediation"
26
+ description: "Add missing SVG namespace"
27
+ targets: ["namespace"]
28
+ default_namespace: "http://www.w3.org/2000/svg"
29
+
30
+ # RFC 7996 Section 2.1: ViewBox auto-generation
31
+ - id: "viewbox_generation"
32
+ type: "ViewboxRemediation"
33
+ description: "Auto-generate viewBox from width/height per RFC 7996 Section 2.1"
34
+ targets: ["viewbox_required"]
@@ -0,0 +1,37 @@
1
+ name: "lucid_fix"
2
+ description: "Lucid SVG Fix Profile - Removes invalid use element references and namespace attributes from Lucid-generated SVGs"
3
+
4
+ requirements:
5
+ - id: "invalid_id_references"
6
+ type: "InvalidIdReferencesRequirement"
7
+ description: "Validates that ID references point to existing elements"
8
+ check_use_elements: true
9
+ check_other_references: true
10
+ strict_mode: true
11
+ - id: "namespace_attributes_requirement"
12
+ type: "NamespaceAttributesRequirement"
13
+ description: "Disallow lucid namespace attributes"
14
+ disallowed_namespaces:
15
+ - "lucid"
16
+ - id: "viewbox_required"
17
+ type: "ViewboxRequiredRequirement"
18
+ description: "Require viewBox attribute on SVG root element"
19
+
20
+ remediations:
21
+ - id: "remove_invalid_use_elements"
22
+ type: "InvalidIdReferencesRemediation"
23
+ description: "Remove use elements with invalid ID references (Lucid fix)"
24
+ targets: ["invalid_id_references"]
25
+ strategy: "remove_invalid_use"
26
+ log_removed_elements: true
27
+ create_placeholder_comment: false
28
+ - id: "lucid_namespace_fix"
29
+ type: "NamespaceAttributeRemediation"
30
+ description: "Remove lucid namespace attributes and declarations"
31
+ targets: ["namespace_attributes_requirement"]
32
+ disallowed_namespaces:
33
+ - "lucid"
34
+ - id: "add_viewbox"
35
+ type: "ViewboxRemediation"
36
+ description: "Add viewBox attribute based on width/height"
37
+ targets: ["viewbox_required"]
@@ -0,0 +1,212 @@
1
+ name: "metanorma"
2
+ description: "Metanorma SVG Profile - SVG requirements for Metanorma technical documents with embedded resources"
3
+
4
+ requirements:
5
+ # Based on RFC 7996 Section 2.1: Elements, Properties, and Attributes
6
+ - id: "allowed_elements"
7
+ type: "AllowedElementsRequirement"
8
+ description: "Validates allowed SVG elements and attributes"
9
+ skip_foreign_namespaces: true
10
+ allow_rdf_metadata: false
11
+ allowed_namespaces:
12
+ - "http://www.w3.org/2000/svg"
13
+ - "" # Default namespace (no prefix)
14
+ element_configs:
15
+ # Direct encoding from svgcheck word_properties.py elements dictionary
16
+ - tag: "svg"
17
+ attributes: ["version", "baseProfile", "width", "viewBox", "preserveAspectRatio", "snapshotTime", "height", "id", "role", "break", "color-rendering", "fill-rule", "overflow", "data-name"]
18
+ required_attributes: ["version", "baseProfile"]
19
+ attribute_values:
20
+ version: ["1.2"]
21
+ baseProfile: ["tiny"]
22
+ allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc", "image", "style"]
23
+ - tag: "desc"
24
+ attributes: ["id", "role", "shape-rendering", "text-rendering", "buffered-rendering", "visibility", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "fill-rule"]
25
+ allowed_children: ["text"]
26
+ - tag: "title"
27
+ attributes: ["id", "role", "shape-rendering", "text-rendering", "buffered-rendering", "visibility", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "fill-rule"]
28
+ allowed_children: ["text"]
29
+ - tag: "path"
30
+ attributes: ["d", "pathLength", "stroke-miterlimit", "id", "role", "fill", "style", "transform", "font-size", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
31
+ allowed_children: ["title", "desc"]
32
+ - tag: "rect"
33
+ attributes: ["x", "y", "width", "height", "rx", "ry", "stroke-miterlimit", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
34
+ allowed_children: ["title", "desc"]
35
+ - tag: "circle"
36
+ attributes: ["cx", "cy", "r", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
37
+ allowed_children: ["title", "desc"]
38
+ - tag: "line"
39
+ attributes: ["x1", "y1", "x2", "y2", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
40
+ allowed_children: ["title", "desc"]
41
+ - tag: "ellipse"
42
+ attributes: ["cx", "cy", "rx", "ry", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
43
+ allowed_children: ["title", "desc"]
44
+ - tag: "polyline"
45
+ attributes: ["points", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
46
+ allowed_children: ["title", "desc"]
47
+ - tag: "polygon"
48
+ attributes: ["points", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
49
+ allowed_children: ["title", "desc"]
50
+ - tag: "solidColor"
51
+ attributes: ["id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
52
+ allowed_children: ["title", "desc"]
53
+ - tag: "textArea"
54
+ attributes: ["x", "y", "width", "height", "auto", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
55
+ allowed_children: ["desc", "title", "tspan", "text", "a"]
56
+ - tag: "text"
57
+ attributes: ["x", "y", "rotate", "id", "role", "fill", "style", "transform", "font-size", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "font-stretch", "writing-mode", "text-decoration"]
58
+ allowed_children: ["desc", "title", "tspan", "text", "a"]
59
+ - tag: "g"
60
+ attributes: ["label", "class", "id", "role", "fill", "style", "transform", "fill-rule", "visibility", "base", "lang", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "data-name"]
61
+ allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc", "image"]
62
+ - tag: "defs"
63
+ attributes: ["id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
64
+ allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc", "style", "clipPath", "linearGradient", "radialGradient", "pattern", "marker", "mask", "filter", "image"]
65
+ - tag: "clipPath"
66
+ attributes: ["id", "clipPathUnits", "class", "style"]
67
+ allowed_children: ["path", "rect", "circle", "ellipse", "line", "polyline", "polygon", "text", "use"]
68
+ - tag: "linearGradient"
69
+ attributes: ["id", "x1", "y1", "x2", "y2", "gradientUnits", "gradientTransform", "spreadMethod", "href", "xlink:href", "data-name"]
70
+ allowed_children: ["stop"]
71
+ - tag: "radialGradient"
72
+ attributes: ["id", "cx", "cy", "r", "fx", "fy", "fr", "gradientUnits", "gradientTransform", "spreadMethod", "href", "xlink:href", "data-name"]
73
+ allowed_children: ["stop"]
74
+ - tag: "stop"
75
+ attributes: ["offset", "stop-color", "stop-opacity", "style", "class", "id"]
76
+ allowed_children: []
77
+ - tag: "pattern"
78
+ attributes: ["id", "x", "y", "width", "height", "patternUnits", "patternContentUnits", "patternTransform", "viewBox", "preserveAspectRatio", "href", "xlink:href"]
79
+ allowed_children: ["path", "rect", "circle", "ellipse", "line", "polyline", "polygon", "text", "g", "use", "image"]
80
+ - tag: "marker"
81
+ attributes: ["id", "markerUnits", "refX", "refY", "markerWidth", "markerHeight", "orient", "preserveAspectRatio", "viewBox"]
82
+ allowed_children: ["path", "rect", "circle", "ellipse", "line", "polyline", "polygon", "text", "g"]
83
+ - tag: "mask"
84
+ attributes: ["id", "x", "y", "width", "height", "maskUnits", "maskContentUnits"]
85
+ allowed_children: ["path", "rect", "circle", "ellipse", "line", "polyline", "polygon", "text", "g", "use", "image"]
86
+ - tag: "filter"
87
+ attributes: ["id", "x", "y", "width", "height", "filterUnits", "primitiveUnits"]
88
+ allowed_children: []
89
+ - tag: "style"
90
+ attributes: ["type", "media", "title", "id", "class"]
91
+ allowed_children: []
92
+ - tag: "use"
93
+ attributes: ["x", "y", "href", "xlink:href", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
94
+ allowed_children: ["title", "desc"]
95
+ - tag: "a"
96
+ attributes: ["id", "role", "fill", "transform", "fill-rule", "target", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
97
+ allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc"]
98
+ - tag: "tspan"
99
+ attributes: ["x", "y", "id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "letter-spacing"]
100
+ allowed_children: ["desc", "title", "tspan", "text", "a", "tbreak"]
101
+ - tag: "tbreak"
102
+ attributes: ["id", "role", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
103
+ - tag: "image"
104
+ attributes: ["x", "y", "width", "height", "href", "xlink:href", "preserveAspectRatio", "id", "class", "style", "transform"]
105
+ allowed_children: ["title", "desc"]
106
+ check_attributes: true
107
+ check_invalid_attributes: true
108
+ check_parent_child: true
109
+
110
+ # Namespace restrictions - only SVG namespace allowed
111
+ - id: "namespace_validation"
112
+ type: "NamespaceRequirement"
113
+ description: "Only allows SVG namespace elements"
114
+ allow_rdf_metadata: false
115
+ allowed_namespaces:
116
+ - "http://www.w3.org/2000/svg"
117
+ - "" # Default namespace (no prefix)
118
+
119
+ # Namespace attribute restrictions - only SVG, XLink, and XML namespaces allowed
120
+ - id: "namespace_attributes"
121
+ type: "NamespaceAttributesRequirement"
122
+ description: "Only allows attributes from SVG, XLink, and XML namespaces"
123
+ allowed_namespaces:
124
+ - "http://www.w3.org/2000/svg"
125
+ - "http://www.w3.org/1999/xlink"
126
+ - "http://www.w3.org/XML/1998/namespace" # XML namespace (xml:space, xml:lang, etc.)
127
+ - "" # Default namespace (no prefix)
128
+ exempt_elements:
129
+ - "RDF"
130
+ - "Work"
131
+ - "format"
132
+ - "type"
133
+ - "title"
134
+ - "creator"
135
+ - "description"
136
+
137
+ # ViewBox required on root SVG element
138
+ - id: "viewbox_required"
139
+ type: "ViewboxRequiredRequirement"
140
+ description: "Requires viewBox attribute on root SVG element"
141
+
142
+ # Link validation - IRIs must be ASCII only
143
+ - id: "link_validation"
144
+ type: "LinkValidationRequirement"
145
+ description: "Validates links are ASCII-only"
146
+ error_context: "Metanorma requires ASCII-only IRIs"
147
+
148
+ # ID reference validation
149
+ - id: "id_references"
150
+ type: "IdReferenceRequirement"
151
+ description: "Validates ID references point to existing elements"
152
+
153
+ # Forbidden content - no multimedia, animation, scripting, etc.
154
+ - id: "forbidden_content"
155
+ type: "ForbiddenContentRequirement"
156
+ description: "Prohibits multimedia, animation, scripting content"
157
+ forbidden_elements: ["script", "audio", "video", "animation", "animateColor", "animateMotion", "animateTransform", "set"]
158
+ forbidden_attributes: ["onload", "onclick", "onmouseover", "onmouseout", "onfocus", "onblur", "onkeydown", "onkeyup", "onkeypress"]
159
+
160
+ # NEW: No external CSS - reject without remediation
161
+ - id: "no_external_css"
162
+ type: "NoExternalCssRequirement"
163
+ description: "Prohibits external CSS references - all styles must be embedded"
164
+ check_style_elements: true
165
+ check_style_attributes: true
166
+ check_link_elements: true
167
+
168
+ # NEW: No external fonts - detect and require embedding
169
+ - id: "no_external_fonts"
170
+ type: "NoExternalFontsRequirement"
171
+ description: "Prohibits external font references - all fonts must be embedded"
172
+ check_font_face: true
173
+ check_style_fonts: true
174
+
175
+ # NEW: No external images - detect and require embedding
176
+ - id: "no_external_images"
177
+ type: "NoExternalImagesRequirement"
178
+ description: "Prohibits external image references - all images must be embedded"
179
+ check_image_elements: true
180
+ check_style_images: true
181
+
182
+ remediations:
183
+ # ViewBox auto-generation
184
+ - id: "viewbox_generation"
185
+ type: "ViewboxRemediation"
186
+ description: "Auto-generate viewBox from width/height"
187
+ targets: ["viewbox_required"]
188
+
189
+ # Namespace cleanup - removes foreign elements, attributes, and declarations
190
+ - id: "namespace_cleanup"
191
+ type: "NamespaceRemediation"
192
+ description: "Remove foreign namespace elements (Inkscape, Sodipodi, etc.), attributes, and declarations"
193
+ targets: ["namespace_validation", "namespace_attributes"]
194
+ allowed_namespaces:
195
+ - "http://www.w3.org/2000/svg"
196
+ - "http://www.w3.org/1999/xlink"
197
+ - "http://www.w3.org/XML/1998/namespace"
198
+ remove_elements: true
199
+ remove_attributes: true
200
+ remove_declarations: true
201
+
202
+ # NEW: Font embedding remediation
203
+ - id: "font_embedding"
204
+ type: "FontEmbeddingRemediation"
205
+ description: "Convert external font references to embedded fonts"
206
+ targets: ["no_external_fonts"]
207
+
208
+ # NEW: Image embedding remediation
209
+ - id: "image_embedding"
210
+ type: "ImageEmbeddingRemediation"
211
+ description: "Convert external image references to embedded images"
212
+ targets: ["no_external_images"]
@@ -0,0 +1,20 @@
1
+ name: "no_external_css"
2
+ description: "Security-focused profile that disallows external CSS references"
3
+
4
+ requirements:
5
+ - id: "no_external_css"
6
+ type: "NoExternalCssRequirement"
7
+ description: "Validates that no external CSS references are present"
8
+ check_style_elements: true
9
+ check_style_attributes: true
10
+ check_link_elements: true
11
+ allowed_protocols: []
12
+
13
+ remediations:
14
+ - id: "remove_external_css"
15
+ type: "NoExternalCssRemediation"
16
+ description: "Remove external CSS references"
17
+ targets: ["no_external_css"]
18
+ strategy: "remove_external_references"
19
+ preserve_inline_styles: true
20
+ log_removed_elements: true
@@ -0,0 +1,284 @@
1
+ name: "svg_1_2_rfc"
2
+ description: "SVG 1.2 RFC Profile (RFC 7996) - Black and white diagrams for technical documents"
3
+
4
+ requirements:
5
+ # RFC 7996 Section 2.1: Elements, Properties, and Attributes Allowed in SVG 1.2 RFC
6
+ - id: "allowed_elements"
7
+ type: "AllowedElementsRequirement"
8
+ description: "Validates allowed SVG elements and attributes per RFC 7996 Section 2.1"
9
+ skip_foreign_namespaces: true
10
+ allow_rdf_metadata: false # RDF errors generated but filtered by compatibility engine for svgcheck
11
+ allowed_namespaces:
12
+ - "http://www.w3.org/2000/svg"
13
+ - "" # Default namespace (no prefix)
14
+ element_configs:
15
+ # Direct encoding from svgcheck word_properties.py elements dictionary
16
+ - tag: "svg"
17
+ attributes: ["version", "baseProfile", "width", "viewBox", "preserveAspectRatio", "snapshotTime", "height", "id", "role", "break", "color-rendering", "fill-rule"]
18
+ required_attributes: ["version", "baseProfile"]
19
+ attribute_values:
20
+ version: ["1.2"]
21
+ baseProfile: ["tiny"]
22
+ allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc"]
23
+ - tag: "desc"
24
+ attributes: ["id", "role", "shape-rendering", "text-rendering", "buffered-rendering", "visibility", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "fill-rule"]
25
+ allowed_children: ["text"]
26
+ - tag: "title"
27
+ attributes: ["id", "role", "shape-rendering", "text-rendering", "buffered-rendering", "visibility", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space", "fill-rule"]
28
+ allowed_children: ["text"]
29
+ - tag: "path"
30
+ attributes: ["d", "pathLength", "stroke-miterlimit", "id", "role", "fill", "style", "transform", "font-size", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
31
+ allowed_children: ["title", "desc"]
32
+ - tag: "rect"
33
+ attributes: ["x", "y", "width", "height", "rx", "ry", "stroke-miterlimit", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
34
+ allowed_children: ["title", "desc"]
35
+ - tag: "circle"
36
+ attributes: ["cx", "cy", "r", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
37
+ allowed_children: ["title", "desc"]
38
+ - tag: "line"
39
+ attributes: ["x1", "y1", "x2", "y2", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
40
+ allowed_children: ["title", "desc"]
41
+ - tag: "ellipse"
42
+ attributes: ["cx", "cy", "rx", "ry", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
43
+ allowed_children: ["title", "desc"]
44
+ - tag: "polyline"
45
+ attributes: ["points", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
46
+ allowed_children: ["title", "desc"]
47
+ - tag: "polygon"
48
+ attributes: ["points", "id", "role", "fill", "style", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
49
+ allowed_children: ["title", "desc"]
50
+ - tag: "solidColor"
51
+ attributes: ["id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
52
+ allowed_children: ["title", "desc"]
53
+ - tag: "textArea"
54
+ attributes: ["x", "y", "width", "height", "auto", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
55
+ allowed_children: ["desc", "title", "tspan", "text", "a"]
56
+ - tag: "text"
57
+ attributes: ["x", "y", "rotate", "id", "role", "fill", "style", "transform", "font-size", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
58
+ allowed_children: ["desc", "title", "tspan", "text", "a"]
59
+ - tag: "g"
60
+ attributes: ["label", "class", "id", "role", "fill", "style", "transform", "fill-rule", "visibility", "base", "lang", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
61
+ allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc"]
62
+ - tag: "defs"
63
+ attributes: ["id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
64
+ allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc"]
65
+ - tag: "use"
66
+ attributes: ["x", "y", "href", "xlink:href", "id", "role", "fill", "transform", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
67
+ allowed_children: ["title", "desc"]
68
+ - tag: "a"
69
+ attributes: ["id", "role", "fill", "transform", "fill-rule", "target", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
70
+ allowed_children: ["title", "path", "rect", "circle", "line", "ellipse", "polyline", "polygon", "solidColor", "textArea", "text", "g", "defs", "use", "a", "tspan", "desc"]
71
+ - tag: "tspan"
72
+ attributes: ["x", "y", "id", "role", "fill", "fill-rule", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
73
+ allowed_children: ["desc", "title", "tspan", "text", "a", "tbreak"]
74
+ - tag: "tbreak"
75
+ attributes: ["id", "role", "base", "lang", "class", "rel", "rev", "typeof", "content", "datatype", "resource", "about", "property", "space"]
76
+ check_attributes: true
77
+ check_invalid_attributes: true
78
+ check_parent_child: true
79
+
80
+ # RFC 7996 Section 2.1: Color restrictions - "Anything relating to 'color' is not allowed in SVG 1.2 RFC"
81
+ # RFC 6949: "Color and grayscale will not be accepted. RFCs must correctly display in monochromatic black-and-white"
82
+ - id: "color_restrictions"
83
+ type: "ColorRestrictionsRequirement"
84
+ description: "Restricts colors to black and white only per RFC 7996 Section 2.1 and RFC 6949"
85
+ mode: "black_white_only"
86
+ allowed_colors: ["black", "white", "#000000", "#ffffff", "#FFFFFF", "none", "inherit", "currentColor"]
87
+ black_and_white_threshold: 764 # RGB sum threshold for svgcheck compatibility (764 = 255+255+254)
88
+
89
+ # RFC 7996 Section 17: Font restrictions - "SVG 1.2 RFC only allows 'serif', 'sans-serif', and 'monospace' generic font families"
90
+ - id: "font_family"
91
+ type: "FontFamilyRequirement"
92
+ description: "Restricts font families to generic families per RFC 7996 Section 17"
93
+ allowed_families: ["serif", "sans-serif", "monospace", "inherit"]
94
+
95
+ # RFC 7996 Section 2.1: Unified style validation (syntax, properties, and values)
96
+ - id: "style"
97
+ type: "StyleRequirement"
98
+ description: "Validates style attributes per RFC 7996 Section 2.1 - syntax, allowed properties, and property values"
99
+ allowed_properties:
100
+ # All style properties that svgcheck recognizes (from word_properties.py properties dictionary)
101
+ # Font properties
102
+ - "font-family"
103
+ - "font-weight"
104
+ - "font-style"
105
+ - "font-variant"
106
+ - "font-size"
107
+ # Text properties
108
+ - "direction"
109
+ - "unicode-bidi"
110
+ - "text-anchor"
111
+ - "line-increment"
112
+ - "text-align"
113
+ - "display-align"
114
+ # Fill properties
115
+ - "fill"
116
+ - "fill-rule"
117
+ - "fill-opacity"
118
+ # Stroke properties
119
+ - "stroke"
120
+ - "stroke-width"
121
+ - "stroke-linecap"
122
+ - "stroke-linejoin"
123
+ - "stroke-miterlimit"
124
+ - "stroke-dasharray"
125
+ - "stroke-dashoffset"
126
+ - "stroke-opacity"
127
+ # Color properties
128
+ - "color"
129
+ - "solid-color"
130
+ - "solid-opacity"
131
+ - "stop-color"
132
+ - "stop-opacity"
133
+ # Display properties
134
+ - "display"
135
+ - "visibility"
136
+ # Rendering properties
137
+ - "image-rendering"
138
+ - "color-rendering"
139
+ - "shape-rendering"
140
+ - "text-rendering"
141
+ - "buffered-rendering"
142
+ # Vector and viewport properties
143
+ - "vector-effect"
144
+ - "viewport-fill"
145
+ - "viewport-fill-opacity"
146
+ property_values:
147
+ # Direct mapping from svgcheck word_properties.py properties dictionary
148
+ "font-family": ["serif", "sans-serif", "monospace", "inherit"]
149
+ "font-weight": ["normal", "bold", "bolder", "lighter", "inherit", "100", "200", "300", "400", "500", "600", "700", "800", "900"]
150
+ "font-style": ["normal", "italic", "oblique", "inherit"]
151
+ "font-variant": ["normal", "small-caps", "inherit"]
152
+ "direction": ["ltr", "rtl", "inherit"]
153
+ "unicode-bidi": ["normal", "embed", "bidi-override", "inherit"]
154
+ "text-anchor": ["start", "middle", "end", "inherit"]
155
+ "text-align": ["start", "end", "center", "inherit"]
156
+ "display-align": ["auto", "before", "center", "after", "inherit"]
157
+ "fill": ["none", "inherit", "<color>"] # Uses <color> type like Python
158
+ "fill-rule": ["nonzero", "evenodd", "inherit"]
159
+ "stroke": ["none", "<paint>"] # Match Python: ('none', '<paint>')
160
+ "stroke-linecap": ["butt", "round", "square", "inherit"]
161
+ "stroke-linejoin": ["miter", "round", "bevel", "inherit"]
162
+ "color": ["currentColor", "inherit", "<color>"]
163
+ "solid-color": ["currentColor", "inherit", "<color>"]
164
+ "stop-color": ["currentColor", "inherit", "<color>"]
165
+ "viewport-fill": ["none", "currentColor", "inherit", "<color>"]
166
+ "display": ["inline", "block", "list-item", "run-in", "compact", "table", "inline-table", "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group", "table-column", "table-cell", "table-caption", "none", "inherit"]
167
+ "visibility": ["visible", "hidden", "collapse", "inherit"]
168
+ "image-rendering": ["auto", "optimizeSpeed", "optimizeQuality", "inherit"]
169
+ "color-rendering": ["auto", "optimizeSpeed", "optimizeQuality", "inherit"]
170
+ "shape-rendering": ["auto", "optimizeSpeed", "crispEdges", "geometricPrecision", "inherit"]
171
+ "text-rendering": ["auto", "optimizeSpeed", "optimizeLegibility", "geometricPrecision", "inherit"]
172
+ "buffered-rendering": ["auto", "dynamic", "static", "inherit"]
173
+ "vector-effect": ["non-scaling-stroke", "none", "inherit"]
174
+ # Basic type definitions matching svgcheck word_properties.py basic_types
175
+ basic_types:
176
+ "<color>": ["black", "#ffffff", "#FFFFFF", "white", "#000000"]
177
+ "<paint>": ["none", "currentColor", "inherit", "<color>"]
178
+ "<number>": ["+"] # Indicates numeric validation with positive numbers
179
+ "<integer>": ["+"] # Indicates integer validation with positive numbers
180
+ # Color conversion settings matching svgcheck logic
181
+ color_conversion:
182
+ threshold: 764 # svgcheck color_threshold = 764
183
+ default_color: "black" # svgcheck color_default = 'black'
184
+ color_map:
185
+ "rgb(0,0,0)": "black"
186
+ property_types:
187
+ "fill": "<color>"
188
+ "stroke": "<paint>"
189
+ "color": "<color>"
190
+ "solid-color": "<color>"
191
+ "stop-color": "<color>"
192
+ "viewport-fill": "<color>"
193
+ "stroke-width": "<number>"
194
+ "stroke-miterlimit": "<number>"
195
+ "stroke-dashoffset": "<number>"
196
+ "fill-opacity": "<number>"
197
+ "stroke-opacity": "<number>"
198
+ "solid-opacity": "<number>"
199
+ "stop-opacity": "<number>"
200
+ "viewport-fill-opacity": "<number>"
201
+ "font-size": "<number>"
202
+
203
+ # RFC 7996 Section 2.1: Namespace restrictions - only SVG namespace allowed
204
+ - id: "namespace_validation"
205
+ type: "NamespaceRequirement"
206
+ description: "Only allows SVG namespace elements per RFC 7996 Section 2.1"
207
+ allow_rdf_metadata: false # RDF errors generated but filtered by compatibility engine for svgcheck
208
+ allowed_namespaces:
209
+ - "http://www.w3.org/2000/svg"
210
+ - "" # Default namespace (no prefix)
211
+
212
+ # RFC 7996 Section 2.1: Namespace attribute restrictions - only SVG, XLink, and XML namespaces allowed
213
+ - id: "namespace_attributes"
214
+ type: "NamespaceAttributesRequirement"
215
+ description: "Only allows attributes from SVG, XLink, and XML namespaces per RFC 7996 Section 2.1"
216
+ allowed_namespaces:
217
+ - "http://www.w3.org/2000/svg"
218
+ - "http://www.w3.org/1999/xlink"
219
+ - "http://www.w3.org/XML/1998/namespace" # XML namespace (xml:space, xml:lang, etc.)
220
+ - "" # Default namespace (no prefix)
221
+ exempt_elements:
222
+ # RDF metadata elements that svgcheck allows to have RDF namespace attributes
223
+ - "RDF"
224
+ - "Work"
225
+ - "format"
226
+ - "type"
227
+ - "title"
228
+ - "creator"
229
+ - "description"
230
+
231
+ # RFC 7996 Section 2.1: ViewBox required on root SVG element
232
+ - id: "viewbox_required"
233
+ type: "ViewboxRequiredRequirement"
234
+ description: "Requires viewBox attribute on root SVG element per RFC 7996 Section 2.1"
235
+
236
+ # RFC 7996 Section 14: Link validation - IRIs must be ASCII only
237
+ - id: "link_validation"
238
+ type: "LinkValidationRequirement"
239
+ description: "Validates links are ASCII-only per RFC 7996 Section 14"
240
+ error_context: "RFC 7996 Section 14 requires ASCII-only IRIs"
241
+
242
+ # RFC 7996 Section 2.1: ID reference validation
243
+ - id: "id_references"
244
+ type: "IdReferenceRequirement"
245
+ description: "Validates ID references point to existing elements per RFC 7996 Section 2.1"
246
+
247
+ # RFC 7996 Section 2: Forbidden content - no multimedia, animation, scripting, etc.
248
+ - id: "forbidden_content"
249
+ type: "ForbiddenContentRequirement"
250
+ description: "Prohibits multimedia, animation, scripting content per RFC 7996 Section 2"
251
+ forbidden_elements: ["script", "audio", "video", "animation", "animateColor", "animateMotion", "animateTransform", "set"]
252
+ forbidden_attributes: ["onload", "onclick", "onmouseover", "onmouseout", "onfocus", "onblur", "onkeydown", "onkeyup", "onkeypress"]
253
+
254
+ # RFC 7996 Section 2.1: Style promotion detection
255
+ - id: "style_promotion"
256
+ type: "StylePromotionRequirement"
257
+ description: "Detects CSS style properties that should be promoted to attributes per RFC 7996 Section 2.1"
258
+
259
+ remediations:
260
+ # RFC 7996 Section 2.1: Color restrictions remediation to black and white only
261
+ - id: "color_conversion"
262
+ type: "ColorRemediation"
263
+ description: "Convert colors to black and white only per RFC 7996 Section 2.1 and RFC 6949"
264
+ targets: ["color_restrictions"]
265
+
266
+ # RFC 7996 Section 17: Font family remediation to generic families only
267
+ - id: "font_family_conversion"
268
+ type: "FontRemediation"
269
+ description: "Convert font families to generic families per RFC 7996 Section 17"
270
+ targets: ["font_family"]
271
+ default_family: "sans-serif"
272
+ allowed_families: ["serif", "sans-serif", "monospace", "inherit"]
273
+
274
+ # RFC 7996 Section 2.1: Style processing remediations
275
+ - id: "style_promotion"
276
+ type: "StylePromotionRemediation"
277
+ description: "Promote valid style properties to attributes per RFC 7996 Section 2.1"
278
+ targets: ["style_promotion"]
279
+
280
+ # RFC 7996 Section 2.1: ViewBox auto-generation
281
+ - id: "viewbox_generation"
282
+ type: "ViewboxRemediation"
283
+ description: "Auto-generate viewBox from width/height per RFC 7996 Section 2.1"
284
+ targets: ["viewbox_required"]