@sarjallab09/figma-intelligence 1.1.0 → 1.2.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 (297) hide show
  1. package/README.md +67 -36
  2. package/dist/bin/cli.js +2 -0
  3. package/dist/design-bridge/bridge.js +2 -0
  4. package/dist/figma-bridge-plugin/bridge-relay.js +2 -0
  5. package/dist/figma-bridge-plugin/code.js +1 -0
  6. package/{figma-bridge-plugin → dist/figma-bridge-plugin}/package-lock.json +0 -3
  7. package/dist/figma-bridge-plugin/ui.html +4970 -0
  8. package/dist/figma-intelligence-layer/dist/index.js +2 -0
  9. package/dist/scripts/clean-existing-chunks.js +2 -0
  10. package/dist/scripts/connect-ai-tool.js +2 -0
  11. package/dist/scripts/convert-hub-pdfs.js +2 -0
  12. package/dist/scripts/figma-mcp-status.js +2 -0
  13. package/dist/scripts/register-codex-mcp.js +2 -0
  14. package/dist/scripts/test-copilot-chat.js +2 -0
  15. package/package.json +11 -8
  16. package/bin/cli.js +0 -859
  17. package/design-bridge/bridge.js +0 -196
  18. package/design-bridge/lib/assets.js +0 -367
  19. package/design-bridge/lib/prompt.js +0 -85
  20. package/design-bridge/lib/server.js +0 -66
  21. package/design-bridge/lib/stitch.js +0 -37
  22. package/design-bridge/lib/tokens.js +0 -82
  23. package/design-bridge/package-lock.json +0 -579
  24. package/figma-bridge-plugin/README.md +0 -97
  25. package/figma-bridge-plugin/anthropic-chat-runner.js +0 -192
  26. package/figma-bridge-plugin/bridge-relay.js +0 -2505
  27. package/figma-bridge-plugin/chat-runner.js +0 -485
  28. package/figma-bridge-plugin/code.js +0 -1534
  29. package/figma-bridge-plugin/codex-runner.js +0 -505
  30. package/figma-bridge-plugin/component-schemas.js +0 -110
  31. package/figma-bridge-plugin/content-context.js +0 -869
  32. package/figma-bridge-plugin/create-button.js +0 -216
  33. package/figma-bridge-plugin/gemini-cli-runner.js +0 -291
  34. package/figma-bridge-plugin/gemini-runner.js +0 -187
  35. package/figma-bridge-plugin/html-to-figma.js +0 -927
  36. package/figma-bridge-plugin/knowledge-hub/.gitkeep +0 -0
  37. package/figma-bridge-plugin/knowledge-hub/uspec-references/anatomy-spec.md +0 -159
  38. package/figma-bridge-plugin/knowledge-hub/uspec-references/api-spec.md +0 -162
  39. package/figma-bridge-plugin/knowledge-hub/uspec-references/color-spec.md +0 -148
  40. package/figma-bridge-plugin/knowledge-hub/uspec-references/full-spec-template.md +0 -314
  41. package/figma-bridge-plugin/knowledge-hub/uspec-references/property-spec.md +0 -175
  42. package/figma-bridge-plugin/knowledge-hub/uspec-references/screen-reader-spec.md +0 -180
  43. package/figma-bridge-plugin/knowledge-hub/uspec-references/structure-spec.md +0 -165
  44. package/figma-bridge-plugin/perplexity-runner.js +0 -188
  45. package/figma-bridge-plugin/references/SKILL.md +0 -178
  46. package/figma-bridge-plugin/references/anatomy-spec.md +0 -159
  47. package/figma-bridge-plugin/references/api-spec.md +0 -162
  48. package/figma-bridge-plugin/references/color-spec.md +0 -148
  49. package/figma-bridge-plugin/references/full-spec-template.md +0 -314
  50. package/figma-bridge-plugin/references/property-spec.md +0 -175
  51. package/figma-bridge-plugin/references/screen-reader-spec.md +0 -180
  52. package/figma-bridge-plugin/references/structure-spec.md +0 -165
  53. package/figma-bridge-plugin/shared-prompt-config.js +0 -645
  54. package/figma-bridge-plugin/spec-helpers/build-table.js +0 -269
  55. package/figma-bridge-plugin/spec-helpers/classify-elements.js +0 -189
  56. package/figma-bridge-plugin/spec-helpers/index.js +0 -35
  57. package/figma-bridge-plugin/spec-helpers/parse-figma-link.js +0 -49
  58. package/figma-bridge-plugin/spec-helpers/position-markers.js +0 -158
  59. package/figma-bridge-plugin/stitch-auth.js +0 -322
  60. package/figma-bridge-plugin/stitch-runner.js +0 -1427
  61. package/figma-bridge-plugin/token-resolver.js +0 -107
  62. package/figma-bridge-plugin/ui.html +0 -4542
  63. package/figma-intelligence-layer/.env.example +0 -39
  64. package/figma-intelligence-layer/docs/local-image-generation.md +0 -60
  65. package/figma-intelligence-layer/examples/comfyui-workflow-template.example.json +0 -101
  66. package/figma-intelligence-layer/jest.config.js +0 -14
  67. package/figma-intelligence-layer/mcp-config.json +0 -19
  68. package/figma-intelligence-layer/package-lock.json +0 -5892
  69. package/figma-intelligence-layer/scripts/setup-comfyui-local.sh +0 -67
  70. package/figma-intelligence-layer/scripts/start-comfyui.sh +0 -33
  71. package/figma-intelligence-layer/src/index.ts +0 -2233
  72. package/figma-intelligence-layer/src/shared/auto-layout-validator.ts +0 -404
  73. package/figma-intelligence-layer/src/shared/cache.ts +0 -187
  74. package/figma-intelligence-layer/src/shared/color-operations.ts +0 -533
  75. package/figma-intelligence-layer/src/shared/color-utils.ts +0 -138
  76. package/figma-intelligence-layer/src/shared/component-script-builder.ts +0 -413
  77. package/figma-intelligence-layer/src/shared/component-templates.ts +0 -2767
  78. package/figma-intelligence-layer/src/shared/concept-taxonomy.ts +0 -694
  79. package/figma-intelligence-layer/src/shared/decision-log.ts +0 -128
  80. package/figma-intelligence-layer/src/shared/design-system-context.ts +0 -568
  81. package/figma-intelligence-layer/src/shared/design-system-intelligence.ts +0 -131
  82. package/figma-intelligence-layer/src/shared/design-system-matcher.ts +0 -184
  83. package/figma-intelligence-layer/src/shared/design-system-normalizers.ts +0 -196
  84. package/figma-intelligence-layer/src/shared/design-system-tokens.ts +0 -295
  85. package/figma-intelligence-layer/src/shared/dtcg-validator.ts +0 -530
  86. package/figma-intelligence-layer/src/shared/enrichment-pipeline.ts +0 -671
  87. package/figma-intelligence-layer/src/shared/figma-bridge.ts +0 -1418
  88. package/figma-intelligence-layer/src/shared/font-config.ts +0 -126
  89. package/figma-intelligence-layer/src/shared/icon-catalog.ts +0 -360
  90. package/figma-intelligence-layer/src/shared/icon-fetch.ts +0 -80
  91. package/figma-intelligence-layer/src/shared/prototype-script-builder.ts +0 -162
  92. package/figma-intelligence-layer/src/shared/response-compression.ts +0 -440
  93. package/figma-intelligence-layer/src/shared/semantic-token-catalog.ts +0 -324
  94. package/figma-intelligence-layer/src/shared/token-binder.ts +0 -505
  95. package/figma-intelligence-layer/src/shared/token-math.ts +0 -427
  96. package/figma-intelligence-layer/src/shared/token-naming.ts +0 -468
  97. package/figma-intelligence-layer/src/shared/token-utils.ts +0 -420
  98. package/figma-intelligence-layer/src/shared/types.ts +0 -346
  99. package/figma-intelligence-layer/src/shared/typography-presets.ts +0 -94
  100. package/figma-intelligence-layer/src/shared/unsplash.ts +0 -165
  101. package/figma-intelligence-layer/src/shared/vision-client.ts +0 -607
  102. package/figma-intelligence-layer/src/shared/vision-provider-anthropic.ts +0 -334
  103. package/figma-intelligence-layer/src/shared/vision-provider-openai.ts +0 -446
  104. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotate-handler.ts +0 -782
  105. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotate-renderer.ts +0 -496
  106. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/a11y-annotation-kit.ts +0 -230
  107. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/colorblind-sim.ts +0 -66
  108. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/index.ts +0 -810
  109. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-analyzer.ts +0 -1191
  110. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-figma-page.ts +0 -1346
  111. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/keyboard-sr-order-handler.ts +0 -148
  112. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/vpat-figma-page.ts +0 -499
  113. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/vpat-report.ts +0 -910
  114. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/wcag-checker.ts +0 -989
  115. package/figma-intelligence-layer/src/tools/phase1-vision/a11y-audit/wcag-criteria.ts +0 -1160
  116. package/figma-intelligence-layer/src/tools/phase1-vision/design-from-ref/index.ts +0 -424
  117. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/component-recognizer.ts +0 -38
  118. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/ds-matcher.ts +0 -111
  119. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/font-matcher.ts +0 -114
  120. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/icon-resolver.ts +0 -103
  121. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/index.ts +0 -1060
  122. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/layout-segmenter.ts +0 -18
  123. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/token-inferencer.ts +0 -39
  124. package/figma-intelligence-layer/src/tools/phase1-vision/screen-cloner/vision-pipeline.ts +0 -58
  125. package/figma-intelligence-layer/src/tools/phase1-vision/sketch-to-design/index.ts +0 -298
  126. package/figma-intelligence-layer/src/tools/phase1-vision/visual-audit/index.ts +0 -197
  127. package/figma-intelligence-layer/src/tools/phase2-accuracy/component-audit/index.ts +0 -494
  128. package/figma-intelligence-layer/src/tools/phase2-accuracy/intent-translator/index.ts +0 -356
  129. package/figma-intelligence-layer/src/tools/phase2-accuracy/layout-intelligence/container-patterns.ts +0 -123
  130. package/figma-intelligence-layer/src/tools/phase2-accuracy/layout-intelligence/index.ts +0 -663
  131. package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/built-in-rules.yaml +0 -56
  132. package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/index.ts +0 -614
  133. package/figma-intelligence-layer/src/tools/phase2-accuracy/lint-rules/rule-engine.ts +0 -113
  134. package/figma-intelligence-layer/src/tools/phase2-accuracy/theme-generator/color-theory.ts +0 -178
  135. package/figma-intelligence-layer/src/tools/phase2-accuracy/theme-generator/index.ts +0 -470
  136. package/figma-intelligence-layer/src/tools/phase2-accuracy/variant-expander/index.ts +0 -429
  137. package/figma-intelligence-layer/src/tools/phase2-accuracy/variant-expander/token-override-maps.ts +0 -226
  138. package/figma-intelligence-layer/src/tools/phase3-generation/ai-image-insert/index.ts +0 -535
  139. package/figma-intelligence-layer/src/tools/phase3-generation/component-archaeologist/index.ts +0 -660
  140. package/figma-intelligence-layer/src/tools/phase3-generation/component-archaeologist/pattern-fingerprints.ts +0 -209
  141. package/figma-intelligence-layer/src/tools/phase3-generation/composition-builder/index.ts +0 -540
  142. package/figma-intelligence-layer/src/tools/phase3-generation/figma-animated-build.ts +0 -391
  143. package/figma-intelligence-layer/src/tools/phase3-generation/page-architect/index.ts +0 -2019
  144. package/figma-intelligence-layer/src/tools/phase3-generation/page-architect/screen-templates.ts +0 -131
  145. package/figma-intelligence-layer/src/tools/phase3-generation/prototype-map/index.ts +0 -381
  146. package/figma-intelligence-layer/src/tools/phase3-generation/prototype-wire/index.ts +0 -565
  147. package/figma-intelligence-layer/src/tools/phase3-generation/swarm-build/index.ts +0 -764
  148. package/figma-intelligence-layer/src/tools/phase3-generation/system-drift/index.ts +0 -535
  149. package/figma-intelligence-layer/src/tools/phase3-generation/unsplash-search/index.ts +0 -84
  150. package/figma-intelligence-layer/src/tools/phase3-generation/url-to-frame/index.ts +0 -401
  151. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/css-animations.ts +0 -68
  152. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/framer-motion.ts +0 -78
  153. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/code-generators/swift-animations.ts +0 -93
  154. package/figma-intelligence-layer/src/tools/phase4-sync/animation-specifier/index.ts +0 -596
  155. package/figma-intelligence-layer/src/tools/phase4-sync/ci-check/index.ts +0 -462
  156. package/figma-intelligence-layer/src/tools/phase4-sync/export-tokens/index.ts +0 -1470
  157. package/figma-intelligence-layer/src/tools/phase4-sync/generate-component-code/index.ts +0 -829
  158. package/figma-intelligence-layer/src/tools/phase4-sync/handoff-spec/index.ts +0 -702
  159. package/figma-intelligence-layer/src/tools/phase4-sync/icon-library-sync/index.ts +0 -483
  160. package/figma-intelligence-layer/src/tools/phase4-sync/sync-from-code/index.ts +0 -501
  161. package/figma-intelligence-layer/src/tools/phase4-sync/sync-from-code/storybook-parser.ts +0 -106
  162. package/figma-intelligence-layer/src/tools/phase4-sync/watch-docs/index.ts +0 -676
  163. package/figma-intelligence-layer/src/tools/phase4-sync/webhook-listener/index.ts +0 -560
  164. package/figma-intelligence-layer/src/tools/phase5-governance/apg-doc/index.ts +0 -1043
  165. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/component-detection.ts +0 -620
  166. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/anatomy.ts +0 -331
  167. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/color-tokens.ts +0 -77
  168. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/properties.ts +0 -54
  169. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/snapshot.ts +0 -287
  170. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/spacing.ts +0 -71
  171. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/states.ts +0 -43
  172. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/extractors/typography.ts +0 -71
  173. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/index.ts +0 -221
  174. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/_default.ts +0 -166
  175. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/accordion.ts +0 -232
  176. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/alert.ts +0 -234
  177. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/avatar-group.ts +0 -270
  178. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/avatar.ts +0 -249
  179. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/badge.ts +0 -231
  180. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/banner.ts +0 -293
  181. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/breadcrumb.ts +0 -240
  182. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/button.ts +0 -243
  183. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/calendar.ts +0 -307
  184. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/card.ts +0 -143
  185. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/checkbox.ts +0 -227
  186. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/chip.ts +0 -233
  187. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/combobox.ts +0 -282
  188. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/datepicker.ts +0 -276
  189. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/divider.ts +0 -223
  190. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/drawer.ts +0 -255
  191. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/dropdown-menu.ts +0 -289
  192. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/empty-state.ts +0 -261
  193. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/file-uploader.ts +0 -290
  194. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/form.ts +0 -265
  195. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/grid.ts +0 -238
  196. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/icon.ts +0 -255
  197. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/index.ts +0 -128
  198. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/inline-edit.ts +0 -286
  199. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/inline-message.ts +0 -255
  200. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/input.ts +0 -330
  201. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/link.ts +0 -247
  202. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/list.ts +0 -250
  203. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/menu.ts +0 -247
  204. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/modal.ts +0 -144
  205. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/navbar.ts +0 -264
  206. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/navigation.ts +0 -251
  207. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/number-input.ts +0 -261
  208. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/pagination.ts +0 -248
  209. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/popover.ts +0 -270
  210. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/progress.ts +0 -251
  211. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/radio.ts +0 -142
  212. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/range-slider.ts +0 -282
  213. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/rating.ts +0 -250
  214. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/search.ts +0 -258
  215. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/segmented-control.ts +0 -265
  216. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/select.ts +0 -319
  217. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/skeleton.ts +0 -256
  218. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/slider.ts +0 -232
  219. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/spinner.ts +0 -239
  220. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/status-dot.ts +0 -252
  221. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/stepper.ts +0 -270
  222. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/table.ts +0 -244
  223. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tabs.ts +0 -143
  224. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tag.ts +0 -243
  225. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/textarea.ts +0 -259
  226. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/time-picker.ts +0 -293
  227. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toast.ts +0 -144
  228. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toggle.ts +0 -289
  229. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/toolbar.ts +0 -267
  230. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/tooltip.ts +0 -232
  231. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/treeview.ts +0 -257
  232. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/knowledge/typography.ts +0 -319
  233. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/legacy-compat.ts +0 -121
  234. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/anatomy-diagram.ts +0 -430
  235. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/figma-page.ts +0 -312
  236. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/json.ts +0 -129
  237. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/markdown.ts +0 -78
  238. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/renderers/visual-doc.ts +0 -2333
  239. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/accessibility.ts +0 -100
  240. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/anatomy.ts +0 -32
  241. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/color-tokens.ts +0 -59
  242. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/content-guidance.ts +0 -18
  243. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/design-tokens.ts +0 -53
  244. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/interaction-rules.ts +0 -19
  245. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/overview.ts +0 -91
  246. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/properties-api.ts +0 -71
  247. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/qa-criteria.ts +0 -19
  248. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/related-components.ts +0 -110
  249. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/responsive.ts +0 -19
  250. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/size-specs.ts +0 -67
  251. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/spacing-structure.ts +0 -58
  252. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/state-specs.ts +0 -79
  253. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/states.ts +0 -50
  254. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/type-hierarchy.ts +0 -33
  255. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/typography.ts +0 -55
  256. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/usage-guidelines.ts +0 -73
  257. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/sections/variants.ts +0 -81
  258. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec/types.ts +0 -409
  259. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/index.ts +0 -198
  260. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/renderer.ts +0 -701
  261. package/figma-intelligence-layer/src/tools/phase5-governance/component-spec-sheet/types.ts +0 -88
  262. package/figma-intelligence-layer/src/tools/phase5-governance/decision-log/index.ts +0 -135
  263. package/figma-intelligence-layer/src/tools/phase5-governance/design-decision-log/index.ts +0 -491
  264. package/figma-intelligence-layer/src/tools/phase5-governance/ds-primitives/index.ts +0 -416
  265. package/figma-intelligence-layer/src/tools/phase5-governance/ds-scaffolder/index.ts +0 -722
  266. package/figma-intelligence-layer/src/tools/phase5-governance/ds-variables/index.ts +0 -449
  267. package/figma-intelligence-layer/src/tools/phase5-governance/health-report/index.ts +0 -393
  268. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/index.ts +0 -406
  269. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/figma-page.ts +0 -292
  270. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/json.ts +0 -24
  271. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/markdown.ts +0 -172
  272. package/figma-intelligence-layer/src/tools/phase5-governance/taxonomy-docs/renderers/naming-guide.ts +0 -409
  273. package/figma-intelligence-layer/src/tools/phase5-governance/token-analytics/index.ts +0 -594
  274. package/figma-intelligence-layer/src/tools/phase5-governance/token-docs/index.ts +0 -710
  275. package/figma-intelligence-layer/src/tools/phase5-governance/token-migrate/index.ts +0 -458
  276. package/figma-intelligence-layer/src/tools/phase5-governance/token-naming/index.ts +0 -134
  277. package/figma-intelligence-layer/tests/apg-doc.test.ts +0 -101
  278. package/figma-intelligence-layer/tests/design-system-context.test.ts +0 -152
  279. package/figma-intelligence-layer/tests/design-system-matcher.test.ts +0 -144
  280. package/figma-intelligence-layer/tests/figma-bridge.test.ts +0 -83
  281. package/figma-intelligence-layer/tests/generate-image-and-insert.test.ts +0 -56
  282. package/figma-intelligence-layer/tests/screen-cloner-regression.test.ts +0 -69
  283. package/figma-intelligence-layer/tests/smoke.test.ts +0 -174
  284. package/figma-intelligence-layer/tests/spec-generator.test.ts +0 -127
  285. package/figma-intelligence-layer/tests/token-migrate.test.ts +0 -21
  286. package/figma-intelligence-layer/tests/token-naming.test.ts +0 -30
  287. package/figma-intelligence-layer/tsconfig.json +0 -19
  288. package/scripts/clean-existing-chunks.js +0 -179
  289. package/scripts/connect-ai-tool.js +0 -490
  290. package/scripts/convert-hub-pdfs.js +0 -425
  291. package/scripts/figma-mcp-status.js +0 -349
  292. package/scripts/register-codex-mcp.js +0 -96
  293. /package/{design-bridge → dist/design-bridge}/.env.example +0 -0
  294. /package/{design-bridge → dist/design-bridge}/package.json +0 -0
  295. /package/{figma-bridge-plugin → dist/figma-bridge-plugin}/manifest.json +0 -0
  296. /package/{figma-bridge-plugin → dist/figma-bridge-plugin}/package.json +0 -0
  297. /package/{figma-intelligence-layer → dist/figma-intelligence-layer}/package.json +0 -0
@@ -1,910 +0,0 @@
1
- // ─────────────────────────────────────────────────────────────────────────────
2
- // VPAT Report Builder
3
- // Takes raw audit issues + the criteria registry and produces a structured
4
- // VPAT-style accessibility conformance report with rich, design-aware remarks.
5
- // ─────────────────────────────────────────────────────────────────────────────
6
-
7
- import {
8
- WCAGLevel,
9
- WCAGPrinciple,
10
- ConformanceStatus,
11
- WCAGCriterionDef,
12
- getCriteriaForLevel,
13
- } from "./wcag-criteria.js";
14
- import { WCAGIssue } from "../../../shared/types.js";
15
-
16
- // ─────────────────────────────────────────────────────────────────────────────
17
- // Types
18
- // ─────────────────────────────────────────────────────────────────────────────
19
-
20
- /** Summary of what the design contains — drives contextual VPAT remarks. */
21
- export interface DesignContext {
22
- /** Human-readable name of the audited frame/page */
23
- frameName: string;
24
- /** Total node count in the tree */
25
- totalNodes: number;
26
- /** Count of TEXT nodes */
27
- textNodeCount: number;
28
- /** Count of interactive elements (buttons, links, inputs, etc.) */
29
- interactiveCount: number;
30
- /** Count of IMAGE / VECTOR nodes (non-text visuals) */
31
- imageCount: number;
32
- /** Count of COMPONENT_SET nodes */
33
- componentSetCount: number;
34
- /** Count of FRAME / GROUP containers */
35
- frameCount: number;
36
- /** Names of detected landmarks (nav, header, footer, sidebar, etc.) */
37
- landmarkNames: string[];
38
- /** Names/labels of detected interactive elements (first N) */
39
- interactiveLabels: string[];
40
- /** Whether the design appears to contain form inputs */
41
- hasFormInputs: boolean;
42
- /** Whether the design contains navigation-like structures */
43
- hasNavigation: boolean;
44
- /** Whether the design contains images or icons */
45
- hasImages: boolean;
46
- /** Whether the design contains headings (large/bold text) */
47
- hasHeadings: boolean;
48
- /** Sample heading texts found */
49
- headingTexts: string[];
50
- /** Whether auto-layout is used on frames */
51
- hasAutoLayout: boolean;
52
- /** Sample text content (first few text strings for context) */
53
- sampleTexts: string[];
54
- /** Interactive element type breakdown */
55
- interactiveBreakdown: Record<string, number>;
56
- }
57
-
58
- export interface VPATRow {
59
- criterionId: string;
60
- criterionName: string;
61
- level: WCAGLevel;
62
- principle: WCAGPrinciple;
63
- guideline: string;
64
- conformanceStatus: ConformanceStatus;
65
- checkType: "automated" | "heuristic" | "manual";
66
- remarks: string;
67
- issues: WCAGIssue[];
68
- }
69
-
70
- export interface VPATSummary {
71
- totalCriteria: number;
72
- supports: number;
73
- partiallySupports: number;
74
- doesNotSupport: number;
75
- notApplicable: number;
76
- notEvaluated: number;
77
- automatedChecks: number;
78
- heuristicChecks: number;
79
- manualReviewRequired: number;
80
- }
81
-
82
- export interface VPATReport {
83
- title: string;
84
- wcagVersion: "2.2";
85
- evaluatedLevel: WCAGLevel;
86
- evaluationDate: string;
87
- nodeId: string;
88
- nodeName: string;
89
- summary: VPATSummary;
90
- principles: Record<WCAGPrinciple, VPATRow[]>;
91
- rows: VPATRow[];
92
- formattedReport: string;
93
- }
94
-
95
- // ─────────────────────────────────────────────────────────────────────────────
96
- // Conformance determination
97
- // ─────────────────────────────────────────────────────────────────────────────
98
-
99
- function determineConformance(
100
- criterion: WCAGCriterionDef,
101
- issues: WCAGIssue[],
102
- override?: ConformanceStatus
103
- ): ConformanceStatus {
104
- if (override) return override;
105
-
106
- const { checkCapability } = criterion;
107
-
108
- // Manual criteria cannot be evaluated by the tool
109
- if (checkCapability === "manual") {
110
- return "Not Evaluated";
111
- }
112
-
113
- const hasErrors = issues.some((i) => i.severity === "error");
114
- const hasWarnings = issues.some(
115
- (i) => i.severity === "warning" || i.severity === "suggestion"
116
- );
117
-
118
- if (checkCapability === "automated") {
119
- if (hasErrors) return "Does Not Support";
120
- if (hasWarnings) return "Partially Supports";
121
- return "Supports";
122
- }
123
-
124
- // Heuristic: even with zero issues, we can only claim partial support
125
- if (checkCapability === "heuristic") {
126
- if (hasErrors) return "Does Not Support";
127
- if (hasWarnings) return "Partially Supports";
128
- // No issues found, but check was not exhaustive
129
- return "Partially Supports";
130
- }
131
-
132
- return "Not Evaluated";
133
- }
134
-
135
- // ─────────────────────────────────────────────────────────────────────────────
136
- // Context-aware remarks builder
137
- // ─────────────────────────────────────────────────────────────────────────────
138
-
139
- function buildRemarks(
140
- criterion: WCAGCriterionDef,
141
- issues: WCAGIssue[],
142
- conformance: ConformanceStatus,
143
- ctx: DesignContext
144
- ): string {
145
- const parts: string[] = [];
146
-
147
- if (conformance === "Not Applicable") {
148
- parts.push(getNotApplicableReason(criterion, ctx));
149
- return parts.join(" ");
150
- }
151
-
152
- if (conformance === "Not Evaluated") {
153
- parts.push(getDesignAwareManualGuidance(criterion, ctx));
154
- return parts.join(" ");
155
- }
156
-
157
- // ── Issues found ──────────────────────────────────────────────────────────
158
- if (issues.length > 0) {
159
- const errorCount = issues.filter((i) => i.severity === "error").length;
160
- const warningCount = issues.filter((i) => i.severity === "warning").length;
161
- const suggestionCount = issues.filter(
162
- (i) => i.severity === "suggestion"
163
- ).length;
164
-
165
- // Severity summary
166
- const counts: string[] = [];
167
- if (errorCount > 0) counts.push(`${errorCount} error(s)`);
168
- if (warningCount > 0) counts.push(`${warningCount} warning(s)`);
169
- if (suggestionCount > 0) counts.push(`${suggestionCount} suggestion(s)`);
170
- parts.push(`Found ${counts.join(", ")} across ${ctx.totalNodes} nodes scanned.`);
171
-
172
- // Group issues by type for a richer summary
173
- const issuesByType = new Map<string, WCAGIssue[]>();
174
- for (const issue of issues) {
175
- const key = issue.issue.split(".")[0].split(":")[0].trim();
176
- const existing = issuesByType.get(key) || [];
177
- existing.push(issue);
178
- issuesByType.set(key, existing);
179
- }
180
-
181
- // Show grouped issue summaries (up to 5 groups)
182
- const groups = Array.from(issuesByType.entries()).slice(0, 5);
183
- for (const [type, groupIssues] of groups) {
184
- if (groupIssues.length === 1) {
185
- const i = groupIssues[0];
186
- parts.push(`- ${i.nodeName}: ${i.issue}`);
187
- } else {
188
- const nodeNames = groupIssues
189
- .slice(0, 3)
190
- .map((i) => i.nodeName)
191
- .join(", ");
192
- const suffix =
193
- groupIssues.length > 3
194
- ? ` (+${groupIssues.length - 3} more)`
195
- : "";
196
- parts.push(`- ${type} — affects: ${nodeNames}${suffix}`);
197
- }
198
- }
199
-
200
- if (issuesByType.size > 5) {
201
- parts.push(
202
- `... and ${issuesByType.size - 5} more issue categories.`
203
- );
204
- }
205
-
206
- // Actionable fix guidance
207
- const fixes = new Set<string>();
208
- for (const issue of issues) {
209
- if (issue.suggestedFix && fixes.size < 3) {
210
- fixes.add(issue.suggestedFix);
211
- }
212
- }
213
- if (fixes.size > 0) {
214
- parts.push("Recommended fixes:");
215
- for (const fix of fixes) {
216
- parts.push(` → ${fix}`);
217
- }
218
- }
219
- } else {
220
- // ── No issues — heuristic or automated pass ───────────────────────────
221
- parts.push(getPassRemarks(criterion, ctx));
222
- }
223
-
224
- return parts.join("\n");
225
- }
226
-
227
- // ─────────────────────────────────────────────────────────────────────────────
228
- // Criterion-specific remark generators
229
- // ─────────────────────────────────────────────────────────────────────────────
230
-
231
- function getNotApplicableReason(
232
- criterion: WCAGCriterionDef,
233
- ctx: DesignContext
234
- ): string {
235
- const id = criterion.id;
236
-
237
- // Time-based media criteria
238
- if (id.startsWith("1.2")) {
239
- return `Not applicable — "${ctx.frameName}" is a static UI design with no audio or video content. If the final product introduces media players or video embeds, re-evaluate this criterion.`;
240
- }
241
- if (id === "1.4.2") {
242
- return `Not applicable — no auto-playing audio content detected in this static design. If the implementation adds background audio, sound effects, or media players, ensure a pause/stop/mute control is provided.`;
243
- }
244
- return `Not applicable to this design context. Re-evaluate if the implementation introduces related functionality.`;
245
- }
246
-
247
- function getDesignAwareManualGuidance(
248
- criterion: WCAGCriterionDef,
249
- ctx: DesignContext
250
- ): string {
251
- const id = criterion.id;
252
- const parts: string[] = [];
253
- parts.push("[Manual Review Required]");
254
-
255
- switch (id) {
256
- // ── 1.2.x Time-based Media ──────────────────────────────────────────
257
- case "1.2.1":
258
- parts.push(
259
- `This static design does not contain audio/video, but the final implementation for "${ctx.frameName}" may include media content.`,
260
- "DEV ACTION: If any audio-only or video-only prerecorded content is added, provide a transcript (audio) or text/audio alternative (video).",
261
- "QA CHECK: Verify transcripts are accurate and complete."
262
- );
263
- break;
264
- case "1.2.2":
265
- parts.push(
266
- `No video content present in this Figma design.`,
267
- "DEV ACTION: All prerecorded video with audio must include synchronised captions. Use WebVTT format. Ensure captions are accurate, synchronised, and include speaker identification.",
268
- "QA CHECK: Review captions for accuracy and timing across all video content."
269
- );
270
- break;
271
- case "1.2.3":
272
- parts.push(
273
- `No video content in this static design.`,
274
- "DEV ACTION: Provide audio description or a full text alternative for prerecorded video. Audio descriptions should narrate visual-only information not conveyed through dialogue.",
275
- "QA CHECK: Verify audio descriptions cover all visual information essential to understanding the content."
276
- );
277
- break;
278
- case "1.2.4":
279
- parts.push(
280
- "DEV ACTION: If live video with audio is implemented, real-time captions must be provided. Consider integrating a live captioning service.",
281
- "QA CHECK: Test live captioning accuracy and latency."
282
- );
283
- break;
284
- case "1.2.5":
285
- parts.push(
286
- "DEV ACTION: Provide audio descriptions for all prerecorded video content where the soundtrack alone does not convey all visual information.",
287
- "QA CHECK: Audio descriptions should cover actions, scene changes, and on-screen text not spoken in dialogue."
288
- );
289
- break;
290
-
291
- // ── 1.3.3 Sensory Characteristics ───────────────────────────────────
292
- case "1.3.3": {
293
- parts.push(
294
- `Design "${ctx.frameName}" contains ${ctx.textNodeCount} text elements.`
295
- );
296
- if (ctx.hasFormInputs) {
297
- parts.push(
298
- "RISK: Form instructions may rely on visual position (\"the field on the left\") or color (\"fields in red are required\"). Ensure all instructions also use text labels."
299
- );
300
- }
301
- if (ctx.hasNavigation) {
302
- parts.push(
303
- "RISK: Navigation cues must not rely solely on shape or position. Ensure active/current state is conveyed through text (e.g., aria-current) not just color."
304
- );
305
- }
306
- parts.push(
307
- "DEV ACTION: Review all instructional text. Replace references like \"click the green button\" or \"see the sidebar\" with explicit labels. Use aria-describedby for supplementary instructions.",
308
- "QA CHECK: Disable CSS and verify instructions still make sense without visual cues."
309
- );
310
- break;
311
- }
312
-
313
- // ── 2.1.x Keyboard Accessible ──────────────────────────────────────
314
- case "2.1.1": {
315
- parts.push(
316
- `Design contains ${ctx.interactiveCount} interactive elements: ${summarizeInteractiveBreakdown(ctx)}.`
317
- );
318
- if (ctx.interactiveLabels.length > 0) {
319
- const sample = ctx.interactiveLabels.slice(0, 6).join(", ");
320
- parts.push(`Key elements to verify: ${sample}.`);
321
- }
322
- parts.push(
323
- "DEV ACTION: All interactive elements must be operable via keyboard (Tab to focus, Enter/Space to activate). Custom widgets must implement WAI-ARIA APG keyboard patterns.",
324
- "QA CHECK: Tab through every interactive element. Verify all actions are reachable and operable without a mouse. Test with screen reader in forms mode."
325
- );
326
- break;
327
- }
328
- case "2.1.2": {
329
- const trapRisks: string[] = [];
330
- if (ctx.interactiveBreakdown["modal"] || ctx.interactiveBreakdown["dialog"])
331
- trapRisks.push("modal dialogs (must trap focus but allow Esc to dismiss)");
332
- if (ctx.hasFormInputs)
333
- trapRisks.push("form fields with autocomplete dropdowns");
334
- if (ctx.interactiveBreakdown["menu"])
335
- trapRisks.push("menus/dropdowns");
336
-
337
- parts.push(
338
- `Design has ${ctx.interactiveCount} interactive elements.`
339
- );
340
- if (trapRisks.length > 0) {
341
- parts.push(`Keyboard trap risk areas: ${trapRisks.join("; ")}.`);
342
- }
343
- parts.push(
344
- "DEV ACTION: Ensure focus can always be moved away using standard keys (Tab, Shift+Tab, Escape). For modals, trap focus within the dialog but allow Escape to close.",
345
- "QA CHECK: Navigate with keyboard only through all interactive paths. Verify you can always Tab away or Escape out."
346
- );
347
- break;
348
- }
349
- case "2.1.4":
350
- parts.push(
351
- "DEV ACTION: If single character key shortcuts (e.g., 'S' for search, 'N' for next) are implemented, provide settings to remap or disable them. Modifier-key shortcuts (Ctrl+S) are exempt.",
352
- "QA CHECK: Test that all single-key shortcuts can be turned off or remapped."
353
- );
354
- break;
355
-
356
- // ── 2.2.x Enough Time ──────────────────────────────────────────────
357
- case "2.2.1":
358
- parts.push(
359
- `Review "${ctx.frameName}" implementation for any time-limited interactions (session timeouts, auto-advancing carousels, countdown timers).`,
360
- "DEV ACTION: For each time limit, provide controls to extend (10x default), turn off, or adjust the limit. Warn users at least 20 seconds before expiry.",
361
- "QA CHECK: Identify all time-limited interactions and verify extension mechanisms work."
362
- );
363
- break;
364
- case "2.2.2":
365
- parts.push(
366
- "DEV ACTION: Any auto-moving, blinking, or auto-updating content must have a pause/stop/hide mechanism. This includes carousels, news tickers, and real-time updates.",
367
- "QA CHECK: Verify the pause mechanism persists across page interactions."
368
- );
369
- break;
370
-
371
- // ── 2.3.x Seizures ────────────────────────────────────────────────
372
- case "2.3.1":
373
- parts.push(
374
- "DEV ACTION: No content should flash more than 3 times per second. This applies to animations, video, GIFs, and CSS transitions. Use the Photosensitive Epilepsy Analysis Tool (PEAT) to test.",
375
- "QA CHECK: Review all animations and transitions for flash frequency."
376
- );
377
- break;
378
-
379
- // ── 2.4.x Navigable ───────────────────────────────────────────────
380
- case "2.4.1": {
381
- parts.push(
382
- `Design "${ctx.frameName}" has ${ctx.landmarkNames.length > 0 ? "landmarks: " + ctx.landmarkNames.join(", ") : "no detected landmark regions"}.`
383
- );
384
- if (ctx.hasNavigation) {
385
- parts.push(
386
- "IMPORTANT: Navigation block detected — a skip link must be provided to bypass repeated navigation and jump to main content."
387
- );
388
- }
389
- parts.push(
390
- "DEV ACTION: Add a visually hidden \"Skip to main content\" link as the first focusable element. Implement ARIA landmarks: <nav>, <main>, <header>, <footer>. These provide screen reader skip navigation.",
391
- "QA CHECK: Tab to the first element — verify a skip link appears. Test with screen reader landmark navigation (NVDA: D key, VoiceOver: rotor)."
392
- );
393
- break;
394
- }
395
- case "2.4.2":
396
- parts.push(
397
- `This page is named "${ctx.frameName}" in Figma. The HTML <title> must describe the page's topic and purpose.`,
398
- "DEV ACTION: Set a descriptive <title> like \"Checkout - Address Selection | Store Name\". For SPAs, update document.title on route change.",
399
- "QA CHECK: Check browser tab for a meaningful, unique title on every page/view."
400
- );
401
- break;
402
- case "2.4.5":
403
- parts.push(
404
- `Design contains navigation elements.`,
405
- "DEV ACTION: Provide at least two ways to find any page: navigation menu, site search, sitemap, table of contents, or A-Z index.",
406
- "QA CHECK: Verify users can reach every page through at least two distinct mechanisms."
407
- );
408
- break;
409
-
410
- // ── 2.5.x Input Modalities ────────────────────────────────────────
411
- case "2.5.1":
412
- parts.push(
413
- "DEV ACTION: All multipoint gestures (pinch-zoom, two-finger scroll, multi-finger swipe) must have single-pointer alternatives (e.g., +/- buttons for zoom).",
414
- "QA CHECK: Disable multi-touch and verify all features remain accessible via single tap/click."
415
- );
416
- break;
417
- case "2.5.2":
418
- parts.push(
419
- "DEV ACTION: Actions must activate on pointer-up (not pointer-down), and the user must be able to abort by moving the pointer away before releasing. This applies to all buttons and interactive elements.",
420
- "QA CHECK: Press and hold an interactive element, move pointer away, and release — verify no activation occurs."
421
- );
422
- break;
423
- case "2.5.4":
424
- parts.push(
425
- "DEV ACTION: Any functionality triggered by device motion (shake to undo, tilt to scroll) must also have a UI button alternative, and motion triggering must be disableable to prevent accidental activation.",
426
- "QA CHECK: Verify all motion-triggered features have equivalent button controls."
427
- );
428
- break;
429
- case "2.5.7":
430
- parts.push(
431
- "DEV ACTION: Drag-and-drop functionality (e.g., reordering lists) must have a single-pointer alternative (e.g., move up/down buttons or a sort dialog).",
432
- "QA CHECK: Test all drag interactions without dragging — verify alternative controls exist."
433
- );
434
- break;
435
-
436
- // ── 3.1.x Readable ────────────────────────────────────────────────
437
- case "3.1.1":
438
- parts.push(
439
- "DEV ACTION: Set lang attribute on <html> element matching the primary language of the content (e.g., <html lang=\"en\">). This enables correct screen reader pronunciation.",
440
- "QA CHECK: Inspect <html> element and verify lang attribute is present and correct."
441
- );
442
- break;
443
- case "3.1.2": {
444
- parts.push(
445
- "DEV ACTION: Wrap any content in a different language with the appropriate lang attribute (e.g., <span lang=\"fr\">Bonjour</span>). This allows screen readers to switch pronunciation.",
446
- "QA CHECK: Review text content for foreign-language phrases and verify lang attributes."
447
- );
448
- break;
449
- }
450
-
451
- // ── 3.2.x Predictable ─────────────────────────────────────────────
452
- case "3.2.1":
453
- parts.push(
454
- `Design has ${ctx.interactiveCount} focusable elements.`,
455
- "DEV ACTION: No element should trigger a context change (page navigation, new window, form submission) simply by receiving focus. Activations must require explicit user action (click/Enter).",
456
- "QA CHECK: Tab through all elements and verify no unexpected navigation or popups occur on focus alone."
457
- );
458
- break;
459
- case "3.2.2": {
460
- parts.push(
461
- `Design contains ${ctx.hasFormInputs ? "form inputs that" : "interactive elements that"} must not auto-submit or navigate on value change.`
462
- );
463
- if (ctx.hasFormInputs) {
464
- parts.push(
465
- "RISK: Dropdowns and radio buttons that immediately navigate or submit without a dedicated \"Apply\" or \"Submit\" button violate this criterion."
466
- );
467
- }
468
- parts.push(
469
- "DEV ACTION: Do not auto-submit forms or navigate on select/radio change unless users are warned in advance. Provide explicit submit buttons.",
470
- "QA CHECK: Change every form control value and verify no unexpected page changes occur."
471
- );
472
- break;
473
- }
474
- case "3.2.3":
475
- parts.push(
476
- `Navigation structure in "${ctx.frameName}" must remain consistent across all pages.`,
477
- "DEV ACTION: Navigation menus must appear in the same position and order on every page. New items may be added but existing item order must be preserved.",
478
- "QA CHECK: Compare navigation across multiple pages — verify order and position are consistent."
479
- );
480
- break;
481
- case "3.2.4":
482
- parts.push(
483
- "DEV ACTION: Components with the same function must use the same labels and icons across all pages (e.g., don't use \"Search\" on one page and \"Find\" on another for the same feature).",
484
- "QA CHECK: Cross-reference common actions (search, save, delete) across pages for consistency."
485
- );
486
- break;
487
- case "3.2.6":
488
- parts.push(
489
- "DEV ACTION: If help mechanisms exist (contact info, chat widget, FAQ link), place them in the same relative position on every page.",
490
- "QA CHECK: Verify help mechanism position is consistent across all pages."
491
- );
492
- break;
493
-
494
- // ── 3.3.x Input Assistance ────────────────────────────────────────
495
- case "3.3.4": {
496
- parts.push(
497
- `"${ctx.frameName}" ${ctx.hasFormInputs ? "contains form inputs" : "may involve data submission"}.`
498
- );
499
- parts.push(
500
- "IMPORTANT: If this page involves financial transactions, legal commitments, or user-controlled data: (1) submissions must be reversible, (2) data must be checked for errors and the user given an opportunity to correct, or (3) a confirmation/review step must be provided before final submission.",
501
- "DEV ACTION: Add a review step before checkout/payment. Show a summary of all entered data with an \"Edit\" option. Provide \"Undo\" for irreversible actions.",
502
- "QA CHECK: Complete a full transaction flow and verify there is a review/confirmation step before final submission."
503
- );
504
- break;
505
- }
506
- case "3.3.7": {
507
- parts.push(
508
- `"${ctx.frameName}" ${ctx.hasFormInputs ? "contains form fields" : "may be part of a multi-step flow"}.`
509
- );
510
- parts.push(
511
- "DEV ACTION: If the user has already provided information in a previous step (name, address, email), auto-populate it or offer a selection rather than requiring re-entry.",
512
- "QA CHECK: Walk through multi-step flows and verify previously entered data is not requested again."
513
- );
514
- break;
515
- }
516
- case "3.3.8":
517
- parts.push(
518
- "DEV ACTION: Authentication must not require cognitive function tests (CAPTCHAs, puzzles). Allow password managers, passkeys, and WebAuthn. If CAPTCHAs are used, provide an audio alternative.",
519
- "QA CHECK: Test login/auth flows with a password manager and verify it works without cognitive tests."
520
- );
521
- break;
522
-
523
- // ── 4.1.x Robust ──────────────────────────────────────────────────
524
- case "4.1.3": {
525
- parts.push(
526
- `Design "${ctx.frameName}" has ${ctx.interactiveCount} interactive elements that may produce status messages.`
527
- );
528
- parts.push(
529
- "DEV ACTION: Status messages (success confirmations, error counts, search result counts, cart updates) must use aria-live regions or appropriate ARIA roles (role=\"status\", role=\"alert\") so screen readers announce them without focus moving.",
530
- "IMPLEMENTATION: Use role=\"status\" + aria-live=\"polite\" for non-urgent updates (cart count, search results). Use role=\"alert\" + aria-live=\"assertive\" for errors or urgent messages.",
531
- "QA CHECK: Trigger status messages (add to cart, form submission, search) and verify screen reader announces them without focus change."
532
- );
533
- break;
534
- }
535
-
536
- default:
537
- // Fallback: use the criterion's manual guidance with design context
538
- parts.push(criterion.manualGuidance);
539
- if (ctx.interactiveCount > 0) {
540
- parts.push(
541
- `This design contains ${ctx.interactiveCount} interactive elements and ${ctx.textNodeCount} text nodes that should be reviewed against this criterion.`
542
- );
543
- }
544
- parts.push(`DEV ACTION: Review the implementation of "${ctx.frameName}" against this WCAG criterion during development and QA testing.`);
545
- break;
546
- }
547
-
548
- return parts.join("\n");
549
- }
550
-
551
- /** Provide rich pass remarks for heuristic/automated checks with no issues */
552
- function getPassRemarks(
553
- criterion: WCAGCriterionDef,
554
- ctx: DesignContext
555
- ): string {
556
- const id = criterion.id;
557
- const isHeuristic = criterion.checkCapability === "heuristic";
558
- const prefix = isHeuristic
559
- ? "No issues detected via heuristic analysis."
560
- : "All automated checks passed.";
561
-
562
- switch (id) {
563
- case "1.1.1":
564
- return `${prefix} Scanned ${ctx.imageCount} image/vector nodes — all have adjacent text labels or descriptive naming.\nDEV ACTION: Verify each image has appropriate alt text in HTML. Decorative images should use alt="" and role="presentation". Icons should use aria-label or sr-only text.\nMANUAL VERIFY: Check that alt text accurately describes the image purpose, not just the file name.`;
565
-
566
- case "1.3.1":
567
- return `${prefix} Detected ${ctx.hasHeadings ? "heading hierarchy from font size/weight" : "no clear heading hierarchy"}. Found ${ctx.textNodeCount} text nodes with ${ctx.headingTexts.length > 0 ? "headings: " + ctx.headingTexts.slice(0, 4).join(", ") : "no headings detected"}.\nDEV ACTION: Map visual heading hierarchy to semantic HTML (h1-h6). Use <ul>/<ol> for lists, <table> for tabular data. Group related form fields in <fieldset> with <legend>.\nMANUAL VERIFY: Ensure heading levels don't skip (e.g., h1 → h3) and all sections have headings.`;
568
-
569
- case "1.3.2":
570
- return `${prefix} Compared Figma layer order against visual layout positions for ${ctx.frameCount} frames.\nDEV ACTION: Ensure DOM order matches visual reading order (top-to-bottom, left-to-right in LTR layouts). Use CSS for visual positioning, not DOM re-ordering. Test with CSS disabled.\nMANUAL VERIFY: Read the page with styles disabled — content should still make logical sense.`;
571
-
572
- case "1.3.4":
573
- return `${prefix} Design layout appears to be single-orientation.\nDEV ACTION: Do not lock viewport orientation with CSS (orientation: portrait). Content must work in both portrait and landscape unless a specific orientation is essential (e.g., piano app).\nMANUAL VERIFY: Test on mobile in both orientations.`;
574
-
575
- case "1.3.5":
576
- return `${prefix} Scanned ${ctx.interactiveCount} interactive elements for autocomplete purpose hints.\nDEV ACTION: Add autocomplete attributes to inputs collecting personal data: autocomplete="name", "email", "tel", "address-line1", etc. This enables browser auto-fill and helps users with cognitive disabilities.\nMANUAL VERIFY: Test that browser auto-fill populates form fields correctly.`;
577
-
578
- case "1.4.1":
579
- return `${prefix} Checked ${ctx.componentSetCount} component sets for color-only state differentiation.\nDEV ACTION: Ensure states (error, success, active, disabled) use icons, text, or borders in addition to color. Error states should have error icons + text, not just red coloring.\nMANUAL VERIFY: View the interface in grayscale (browser devtools) — all states should still be distinguishable.`;
580
-
581
- case "1.4.3":
582
- return `All ${ctx.textNodeCount} text nodes meet WCAG AA minimum contrast ratio (4.5:1 for normal text, 3:1 for large text 18px+/14px bold+).\nPASS DETAILS: All foreground/background pairs analysed from Figma fill properties.\nMANUAL VERIFY: Check contrast for text rendered over images, gradients, or dynamic backgrounds that may not be captured in static design.`;
583
-
584
- case "1.4.4":
585
- return `${prefix} No fixed-height containers with text children that would clip on resize were detected.\nDEV ACTION: Use relative units (rem, em, %) for typography and containers. Text must be resizable up to 200% without content loss.\nMANUAL VERIFY: Zoom browser to 200% and verify no text is clipped, overlaps, or becomes unreadable.`;
586
-
587
- case "1.4.5":
588
- return `${prefix} No rasterised text (images of text) detected.\nDEV ACTION: Always use real HTML text, not images of text. Exceptions: logos and cases where a particular visual presentation is essential.\nMANUAL VERIFY: Verify no text is embedded in images — select all text on the page to confirm.`;
589
-
590
- case "1.4.10":
591
- return `${prefix} Checked ${ctx.frameCount} frames for auto-layout usage and responsive constraints. ${ctx.hasAutoLayout ? "Auto-layout detected — good foundation for reflow." : "Warning: Limited auto-layout usage may indicate reflow issues."}\nDEV ACTION: Content must reflow to single-column at 320px viewport width without horizontal scrolling. Use CSS flexbox/grid with relative units.\nMANUAL VERIFY: Test at 320px wide viewport and 256px tall viewport.`;
592
-
593
- case "1.4.11":
594
- return `All ${ctx.interactiveCount} interactive element borders and icons meet 3:1 minimum contrast ratio against their backgrounds.\nDEV ACTION: UI components (buttons, form inputs, focus indicators) and meaningful graphics must maintain 3:1 contrast. This includes borders, icons, and graphical objects.\nMANUAL VERIFY: Check custom UI elements and state changes (hover, focus) maintain contrast.`;
595
-
596
- case "1.4.12":
597
- return `All ${ctx.textNodeCount} text nodes pass text spacing requirements.\nPASS DETAILS: Line height ≥ 1.5× font size, paragraph spacing ≥ 2× font size, letter spacing ≥ 0.12× font size, word spacing ≥ 0.16× font size.\nDEV ACTION: No content loss when users override text spacing. Avoid fixed-height containers for text. Use CSS that allows spacing overrides.\nMANUAL VERIFY: Apply the WCAG text spacing bookmarklet and verify no text is clipped.`;
598
-
599
- case "1.4.13":
600
- return `${prefix} Checked ${ctx.componentSetCount} component sets for hover/tooltip patterns.\nDEV ACTION: Content appearing on hover/focus must be: (1) dismissable with Escape key without moving focus, (2) hoverable — pointer can move over the new content without it disappearing, (3) persistent — remains visible until dismissed or focus moves.\nMANUAL VERIFY: Test all tooltips and hover content for these three requirements.`;
601
-
602
- case "2.4.3":
603
- return `${prefix} Compared interactive element positions against node tree order for ${ctx.interactiveCount} elements.\nDEV ACTION: Tab order should follow the visual reading order (generally top-to-bottom, left-to-right). Use tabindex="0" for custom interactive elements. Avoid tabindex > 0. Use CSS for layout, not DOM order changes.\nMANUAL VERIFY: Tab through the entire page and verify focus moves logically.`;
604
-
605
- case "2.4.4":
606
- return `${prefix} All link-like elements have descriptive text labels.\nDEV ACTION: Avoid generic link text ("Click here", "Read more", "Learn more"). If visual design requires short text, use aria-label or visually hidden text for full context (e.g., "Read more about Product Name").\nMANUAL VERIFY: List all links (NVDA: Insert+F7) — each should be understandable out of context.`;
607
-
608
- case "2.4.6":
609
- return `${prefix} Checked ${ctx.frameCount} sections for heading and label presence. ${ctx.headingTexts.length > 0 ? "Headings found: " + ctx.headingTexts.slice(0, 5).join(", ") + "." : "No headings detected."}\nDEV ACTION: Every section must have a descriptive heading. Form fields must have visible labels (not just placeholder text). Labels must describe the purpose of the input.\nMANUAL VERIFY: Confirm every section has a heading and every input has a persistent visible label.`;
610
-
611
- case "2.4.7":
612
- return `${prefix} Checked component sets for visible focus-state variants.\nDEV ACTION: All focusable elements must show a visible focus indicator. Default browser focus ring is acceptable. Custom focus styles must meet 3:1 contrast and at least 2px outline.\nMANUAL VERIFY: Tab through all elements and verify a clearly visible focus ring appears on each.`;
613
-
614
- case "2.4.11":
615
- return `${prefix} Checked component sets for focus indicator obscuration.\nDEV ACTION: When an element receives focus, it must not be completely hidden by other content (sticky headers, modals, toasts). Use scroll-margin to ensure focused elements are visible.\nMANUAL VERIFY: Tab through elements near sticky headers/footers and verify focus is never hidden.`;
616
-
617
- case "2.5.3":
618
- return `${prefix} Checked interactive components for label-in-name match.\nDEV ACTION: The accessible name (aria-label, alt text) must include the visible text label. e.g., if a button shows "Search", the accessible name should contain "Search" (not just "Magnifying glass icon").\nMANUAL VERIFY: For each labeled interactive element, verify that speaking the visible text activates it in voice control (Dragon NaturallySpeaking, Voice Control).`;
619
-
620
- case "2.5.5":
621
- return `All ${ctx.interactiveCount} interactive elements meet the enhanced 44×44px target size.\nDEV ACTION: Maintain minimum 44×44 CSS pixel click/tap targets. Smaller targets are allowed if an equivalent larger target exists, or spacing ensures no overlap.\nMANUAL VERIFY: Test on actual touch devices — verify all targets are easy to tap accurately.`;
622
-
623
- case "2.5.8":
624
- return `All ${ctx.interactiveCount} interactive elements meet the minimum 24×24px target size.\nDEV ACTION: Maintain at least 24×24 CSS pixel targets for pointer inputs. Inline links within text are exempt. Ensure spacing between adjacent targets prevents accidental activation.\nMANUAL VERIFY: Test on mobile — verify no adjacent targets cause mis-taps.`;
625
-
626
- case "3.3.1":
627
- return `${prefix} Checked ${ctx.componentSetCount} component sets for error-state variants with descriptive text.\nDEV ACTION: Error messages must: (1) identify the field in error, (2) describe the error in text, (3) not rely solely on color. Use aria-invalid="true" and aria-describedby pointing to the error message.\nMANUAL VERIFY: Trigger validation errors and verify screen reader announces which field has the error and what the error is.`;
628
-
629
- case "3.3.2":
630
- return `${prefix} Checked ${ctx.interactiveCount} interactive elements for visible label siblings.\nDEV ACTION: Every input must have a visible label (not just placeholder). Use <label for="id"> associations. Group related inputs in <fieldset> with <legend>. Provide format hints (e.g., "MM/DD/YYYY").\nMANUAL VERIFY: Clear all inputs and verify each has a persistent visible label that describes its purpose.`;
631
-
632
- case "3.3.3":
633
- return `${prefix} Error-state variants checked for suggestion text.\nDEV ACTION: When input errors are detected and corrections are known, suggest the fix (e.g., "Email must contain @" not just "Invalid email"). For constrained values, show valid options.\nMANUAL VERIFY: Trigger validation errors and verify helpful correction suggestions appear.`;
634
-
635
- case "4.1.2":
636
- return `${prefix} Checked ${ctx.interactiveCount} interactive elements for name/description properties and visible labels.\nDEV ACTION: Every interactive element must expose: (1) name — accessible label (aria-label, <label>, alt text), (2) role — element type (button, link, textbox) via semantic HTML or ARIA, (3) value — current state (checked, expanded, selected) via ARIA properties.\nMANUAL VERIFY: Test with screen reader — each element should announce its name, role, and state.`;
637
-
638
- default:
639
- return `${prefix} ${criterion.figmaRelevance}\nMANUAL VERIFY: ${criterion.manualGuidance}`;
640
- }
641
- }
642
-
643
- function summarizeInteractiveBreakdown(ctx: DesignContext): string {
644
- const entries = Object.entries(ctx.interactiveBreakdown);
645
- if (entries.length === 0) return "no categorized elements";
646
- return entries
647
- .filter(([, count]) => count > 0)
648
- .map(([type, count]) => `${count} ${type}${count > 1 ? "s" : ""}`)
649
- .join(", ");
650
- }
651
-
652
- // ─────────────────────────────────────────────────────────────────────────────
653
- // Markdown formatter
654
- // ─────────────────────────────────────────────────────────────────────────────
655
-
656
- function formatMarkdownReport(
657
- report: Omit<VPATReport, "formattedReport">
658
- ): string {
659
- const lines: string[] = [];
660
-
661
- lines.push(`# WCAG 2.2 Level ${report.evaluatedLevel} — Accessibility Conformance Report`);
662
- lines.push("");
663
- lines.push(`**Product:** ${report.nodeName} (Node ${report.nodeId})`);
664
- lines.push(`**Date:** ${report.evaluationDate}`);
665
- lines.push(`**WCAG Version:** ${report.wcagVersion}`);
666
- lines.push(`**Evaluation Level:** ${report.evaluatedLevel}`);
667
- lines.push("");
668
-
669
- // Summary
670
- lines.push("## Summary");
671
- lines.push("");
672
- lines.push(`| Metric | Count |`);
673
- lines.push(`|--------|-------|`);
674
- lines.push(`| Total Criteria | ${report.summary.totalCriteria} |`);
675
- lines.push(`| Supports | ${report.summary.supports} |`);
676
- lines.push(`| Partially Supports | ${report.summary.partiallySupports} |`);
677
- lines.push(`| Does Not Support | ${report.summary.doesNotSupport} |`);
678
- lines.push(`| Not Applicable | ${report.summary.notApplicable} |`);
679
- lines.push(`| Not Evaluated (Manual Review) | ${report.summary.notEvaluated} |`);
680
- lines.push("");
681
- lines.push(
682
- `> **Automated checks:** ${report.summary.automatedChecks} | **Heuristic checks:** ${report.summary.heuristicChecks} | **Manual review required:** ${report.summary.manualReviewRequired}`
683
- );
684
- lines.push("");
685
-
686
- // Per-principle tables
687
- const principleOrder: WCAGPrinciple[] = [
688
- "Perceivable",
689
- "Operable",
690
- "Understandable",
691
- "Robust",
692
- ];
693
-
694
- for (const principle of principleOrder) {
695
- const rows = report.principles[principle];
696
- if (rows.length === 0) continue;
697
-
698
- lines.push(`## ${principle}`);
699
- lines.push("");
700
- lines.push(
701
- `| SC | Name | Level | Conformance | Check | Remarks |`
702
- );
703
- lines.push(
704
- `|----|------|-------|-------------|-------|---------|`
705
- );
706
-
707
- for (const row of rows) {
708
- const statusIcon = getStatusIcon(row.conformanceStatus);
709
- // Truncate remarks for table readability
710
- const shortRemarks = truncateRemarks(row.remarks, 200);
711
- lines.push(
712
- `| ${row.criterionId} | ${row.criterionName} | ${row.level} | ${statusIcon} ${row.conformanceStatus} | ${row.checkType} | ${shortRemarks} |`
713
- );
714
- }
715
- lines.push("");
716
- }
717
-
718
- // Detailed remarks section — full content for every criterion
719
- lines.push("## Detailed Assessment");
720
- lines.push("");
721
-
722
- for (const principle of principleOrder) {
723
- const rows = report.principles[principle];
724
- if (rows.length === 0) continue;
725
-
726
- lines.push(`### ${principle}`);
727
- lines.push("");
728
-
729
- for (const row of rows) {
730
- const statusIcon = getStatusIcon(row.conformanceStatus);
731
- lines.push(`#### ${row.criterionId} ${row.criterionName} — ${statusIcon} ${row.conformanceStatus}`);
732
- lines.push("");
733
- lines.push(row.remarks);
734
- lines.push("");
735
-
736
- // Include specific issues if any
737
- if (row.issues.length > 0) {
738
- lines.push("**Issues:**");
739
- for (const issue of row.issues) {
740
- const severity = issue.severity.toUpperCase();
741
- lines.push(
742
- `- **[${severity}]** \`${issue.nodeName}\` (${issue.nodeId}): ${issue.issue}`
743
- );
744
- if (issue.currentValue) {
745
- lines.push(` - Current: ${issue.currentValue}`);
746
- }
747
- if (issue.suggestedFix) {
748
- lines.push(` - Fix: ${issue.suggestedFix}`);
749
- }
750
- }
751
- lines.push("");
752
- }
753
- }
754
- }
755
-
756
- return lines.join("\n");
757
- }
758
-
759
- function getStatusIcon(status: ConformanceStatus): string {
760
- switch (status) {
761
- case "Supports":
762
- return "[PASS]";
763
- case "Partially Supports":
764
- return "[PARTIAL]";
765
- case "Does Not Support":
766
- return "[FAIL]";
767
- case "Not Applicable":
768
- return "[N/A]";
769
- case "Not Evaluated":
770
- return "[REVIEW]";
771
- }
772
- }
773
-
774
- function truncateRemarks(text: string, maxLen: number): string {
775
- // For table display, take only the first line/sentence
776
- const firstLine = text.split("\n")[0];
777
- if (firstLine.length <= maxLen) return firstLine;
778
- return firstLine.slice(0, maxLen - 3) + "...";
779
- }
780
-
781
- // ─────────────────────────────────────────────────────────────────────────────
782
- // Main builder
783
- // ─────────────────────────────────────────────────────────────────────────────
784
-
785
- /**
786
- * Build a VPAT-style accessibility conformance report.
787
- *
788
- * @param evaluatedLevel - WCAG conformance level to evaluate
789
- * @param nodeId - Figma node ID that was audited
790
- * @param nodeName - Human-readable name of the audited node
791
- * @param issues - All issues found by the checker functions
792
- * @param designContext - Summary of design contents for contextual remarks
793
- * @param applicabilityOverrides - Optional overrides for specific SC (e.g. mark media criteria as N/A)
794
- */
795
- export function buildVPATReport(
796
- evaluatedLevel: WCAGLevel,
797
- nodeId: string,
798
- nodeName: string,
799
- issues: WCAGIssue[],
800
- designContext?: DesignContext,
801
- applicabilityOverrides?: Record<string, ConformanceStatus>
802
- ): VPATReport {
803
- const criteria = getCriteriaForLevel(evaluatedLevel);
804
- const today = new Date().toISOString().split("T")[0];
805
-
806
- // Default context if not provided (backwards compatibility)
807
- const ctx: DesignContext = designContext || {
808
- frameName: nodeName,
809
- totalNodes: 0,
810
- textNodeCount: 0,
811
- interactiveCount: 0,
812
- imageCount: 0,
813
- componentSetCount: 0,
814
- frameCount: 0,
815
- landmarkNames: [],
816
- interactiveLabels: [],
817
- hasFormInputs: false,
818
- hasNavigation: false,
819
- hasImages: false,
820
- hasHeadings: false,
821
- headingTexts: [],
822
- hasAutoLayout: false,
823
- sampleTexts: [],
824
- interactiveBreakdown: {},
825
- };
826
-
827
- // Group issues by criterion ID (match the leading SC number)
828
- const issuesByCriterion = new Map<string, WCAGIssue[]>();
829
- for (const issue of issues) {
830
- // The criterion field may be "1.4.3" or "1.4.3 Contrast (Minimum)"
831
- const scId = issue.criterion.split(" ")[0];
832
- const existing = issuesByCriterion.get(scId) || [];
833
- existing.push(issue);
834
- issuesByCriterion.set(scId, existing);
835
- }
836
-
837
- const rows: VPATRow[] = [];
838
- const principles: Record<WCAGPrinciple, VPATRow[]> = {
839
- Perceivable: [],
840
- Operable: [],
841
- Understandable: [],
842
- Robust: [],
843
- };
844
-
845
- for (const criterion of criteria) {
846
- const scIssues = issuesByCriterion.get(criterion.id) || [];
847
- const override = applicabilityOverrides?.[criterion.id];
848
- const conformance = determineConformance(criterion, scIssues, override);
849
- const remarks = buildRemarks(criterion, scIssues, conformance, ctx);
850
-
851
- const row: VPATRow = {
852
- criterionId: criterion.id,
853
- criterionName: criterion.name,
854
- level: criterion.level,
855
- principle: criterion.principle,
856
- guideline: criterion.guideline,
857
- conformanceStatus: conformance,
858
- checkType: criterion.checkCapability,
859
- remarks,
860
- issues: scIssues,
861
- };
862
-
863
- rows.push(row);
864
- principles[criterion.principle].push(row);
865
- }
866
-
867
- // Compute summary
868
- const summary: VPATSummary = {
869
- totalCriteria: rows.length,
870
- supports: rows.filter((r) => r.conformanceStatus === "Supports").length,
871
- partiallySupports: rows.filter(
872
- (r) => r.conformanceStatus === "Partially Supports"
873
- ).length,
874
- doesNotSupport: rows.filter(
875
- (r) => r.conformanceStatus === "Does Not Support"
876
- ).length,
877
- notApplicable: rows.filter(
878
- (r) => r.conformanceStatus === "Not Applicable"
879
- ).length,
880
- notEvaluated: rows.filter(
881
- (r) => r.conformanceStatus === "Not Evaluated"
882
- ).length,
883
- automatedChecks: criteria.filter(
884
- (c) => c.checkCapability === "automated"
885
- ).length,
886
- heuristicChecks: criteria.filter(
887
- (c) => c.checkCapability === "heuristic"
888
- ).length,
889
- manualReviewRequired: criteria.filter(
890
- (c) => c.checkCapability === "manual"
891
- ).length,
892
- };
893
-
894
- const partial: Omit<VPATReport, "formattedReport"> = {
895
- title: `WCAG 2.2 Level ${evaluatedLevel} Conformance Report`,
896
- wcagVersion: "2.2",
897
- evaluatedLevel,
898
- evaluationDate: today,
899
- nodeId,
900
- nodeName,
901
- summary,
902
- principles,
903
- rows,
904
- };
905
-
906
- return {
907
- ...partial,
908
- formattedReport: formatMarkdownReport(partial),
909
- };
910
- }