appiq-solution 1.4.8 → 1.5.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 (738) hide show
  1. package/README.md +172 -48
  2. package/bmad-core/agent-teams/team-fullstack.yaml +1 -11
  3. package/bmad-core/agents/analyst.md +3 -7
  4. package/bmad-core/agents/architect.md +0 -6
  5. package/bmad-core/agents/dev.md +5 -24
  6. package/bmad-core/agents/pm.md +3 -7
  7. package/bmad-core/agents/qa.md +0 -17
  8. package/bmad-core/agents/sm.md +3 -8
  9. package/bmad-core/agents/ux-expert.md +3 -8
  10. package/bmad-core/data/technical-preferences.md +1 -147
  11. package/bmad-core/templates/fullstack-architecture-tmpl.yaml +5 -12
  12. package/bmad-core/workflows/brownfield-fullstack.yaml +1 -15
  13. package/bmad-core/workflows/greenfield-fullstack.yaml +5 -49
  14. package/bmad-core/working-in-the-brownfield.md +10 -19
  15. package/dist/agents/bmad-orchestrator.txt +0 -111
  16. package/dist/agents/pm.txt +2 -0
  17. package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +0 -111
  18. package/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +0 -111
  19. package/dist/teams/team-all.txt +2 -111
  20. package/dist/teams/team-fullstack.txt +2 -111
  21. package/dist/teams/team-ide-minimal.txt +0 -111
  22. package/dist/teams/team-no-ui.txt +2 -111
  23. package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/config.yaml +1 -0
  24. package/package.json +60 -18
  25. package/tools/cli.js +3 -3
  26. package/tools/installer/lib/ide-setup.js +11 -0
  27. package/tools/installer/package-lock.json +2 -2
  28. package/#NEW APP PROMPT/ARCHITECTURE.md +0 -279
  29. package/#NEW APP PROMPT/ARCHITECTURE_UNIFIED.md +0 -414
  30. package/#NEW APP PROMPT/accesibility_prompt.md +0 -103
  31. package/#NEW APP PROMPT/clean-code.mdc +0 -55
  32. package/#NEW APP PROMPT/codequality.mdc +0 -47
  33. package/#NEW APP PROMPT/flutter-ai-rules/LICENSE +0 -21
  34. package/#NEW APP PROMPT/flutter-ai-rules/README.md +0 -104
  35. package/#NEW APP PROMPT/flutter-ai-rules/combined/README.md +0 -25
  36. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_dart.md +0 -192
  37. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_dart__under_6K.md +0 -99
  38. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_dart_bloc_mocktail.md +0 -308
  39. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_dart_bloc_mocktail__under_6K.md +0 -87
  40. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_dart_change_notifier.md +0 -254
  41. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_dart_change_notifier__under_6K.md +0 -98
  42. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_dart_provider.md +0 -261
  43. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_dart_provider__under_6K.md +0 -105
  44. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_dart_riverpod_mockito.md +0 -371
  45. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_dart_riverpod_mockito__under_6K.md +0 -92
  46. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_with_bloc.md +0 -287
  47. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_with_bloc__under_6K.md +0 -68
  48. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_with_riverpod.md +0 -375
  49. package/#NEW APP PROMPT/flutter-ai-rules/combined/flutter_with_riverpod__under_6K.md +0 -106
  50. package/#NEW APP PROMPT/flutter-ai-rules/media/flutter_ai_rules.png +0 -0
  51. package/#NEW APP PROMPT/flutter-ai-rules/media/mocktail_md_01.png +0 -0
  52. package/#NEW APP PROMPT/flutter-ai-rules/media/mocktail_md_02.png +0 -0
  53. package/#NEW APP PROMPT/flutter-ai-rules/rules/bloc.md +0 -94
  54. package/#NEW APP PROMPT/flutter-ai-rules/rules/dart_3_updates.md +0 -93
  55. package/#NEW APP PROMPT/flutter-ai-rules/rules/effective_dart.md +0 -105
  56. package/#NEW APP PROMPT/flutter-ai-rules/rules/flutter_app_architecture.md +0 -57
  57. package/#NEW APP PROMPT/flutter-ai-rules/rules/flutter_change_notifier.md +0 -62
  58. package/#NEW APP PROMPT/flutter-ai-rules/rules/flutter_errors.md +0 -11
  59. package/#NEW APP PROMPT/flutter-ai-rules/rules/mockito.md +0 -31
  60. package/#NEW APP PROMPT/flutter-ai-rules/rules/mocktail.md +0 -24
  61. package/#NEW APP PROMPT/flutter-ai-rules/rules/provider.md +0 -69
  62. package/#NEW APP PROMPT/flutter-ai-rules/rules/riverpod.md +0 -188
  63. package/#NEW APP PROMPT/generate ssh.md +0 -4
  64. package/#NEW APP PROMPT/project_ai_prompt.md +0 -544
  65. package/#Tools/APPIQ-METHOD/.bmad-config.json +0 -13
  66. package/#Tools/APPIQ-METHOD/.cursor/commands/analyze.md +0 -27
  67. package/#Tools/APPIQ-METHOD/.cursor/commands/appiq.md +0 -27
  68. package/#Tools/APPIQ-METHOD/.cursor/commands/help.md +0 -27
  69. package/#Tools/APPIQ-METHOD/.cursor/commands/story.md +0 -27
  70. package/#Tools/APPIQ-METHOD/DEVELOPMENT_GUIDE.md +0 -855
  71. package/#Tools/APPIQ-METHOD/NPM-README.md +0 -138
  72. package/#Tools/APPIQ-METHOD/README.md +0 -107
  73. package/#Tools/APPIQ-METHOD/SMART_WORKFLOW_GUIDE.md +0 -401
  74. package/#Tools/APPIQ-METHOD/activate-appiq.js +0 -81
  75. package/#Tools/APPIQ-METHOD/appiq-solution/README.md +0 -226
  76. package/#Tools/APPIQ-METHOD/bmad-core/agent-teams/team-all.yaml +0 -14
  77. package/#Tools/APPIQ-METHOD/bmad-core/agent-teams/team-flutter-mobile.yaml +0 -114
  78. package/#Tools/APPIQ-METHOD/bmad-core/agent-teams/team-fullstack.yaml +0 -28
  79. package/#Tools/APPIQ-METHOD/bmad-core/agent-teams/team-ide-minimal.yaml +0 -10
  80. package/#Tools/APPIQ-METHOD/bmad-core/agent-teams/team-no-ui.yaml +0 -13
  81. package/#Tools/APPIQ-METHOD/bmad-core/agents/analyst.md +0 -85
  82. package/#Tools/APPIQ-METHOD/bmad-core/agents/architect.md +0 -90
  83. package/#Tools/APPIQ-METHOD/bmad-core/agents/bmad-master.md +0 -108
  84. package/#Tools/APPIQ-METHOD/bmad-core/agents/bmad-orchestrator.md +0 -150
  85. package/#Tools/APPIQ-METHOD/bmad-core/agents/bmad-smart-launcher.md +0 -170
  86. package/#Tools/APPIQ-METHOD/bmad-core/agents/dev.md +0 -95
  87. package/#Tools/APPIQ-METHOD/bmad-core/agents/init-flow-po.md +0 -143
  88. package/#Tools/APPIQ-METHOD/bmad-core/agents/pm.md +0 -85
  89. package/#Tools/APPIQ-METHOD/bmad-core/agents/po.md +0 -76
  90. package/#Tools/APPIQ-METHOD/bmad-core/agents/qa.md +0 -86
  91. package/#Tools/APPIQ-METHOD/bmad-core/agents/sm.md +0 -67
  92. package/#Tools/APPIQ-METHOD/bmad-core/agents/ux-expert.md +0 -71
  93. package/#Tools/APPIQ-METHOD/bmad-core/bmad-core/user-guide.md +0 -0
  94. package/#Tools/APPIQ-METHOD/bmad-core/checklists/architect-checklist.md +0 -443
  95. package/#Tools/APPIQ-METHOD/bmad-core/checklists/change-checklist.md +0 -182
  96. package/#Tools/APPIQ-METHOD/bmad-core/checklists/pm-checklist.md +0 -375
  97. package/#Tools/APPIQ-METHOD/bmad-core/checklists/po-master-checklist.md +0 -441
  98. package/#Tools/APPIQ-METHOD/bmad-core/checklists/security-validation-checklist.md +0 -332
  99. package/#Tools/APPIQ-METHOD/bmad-core/checklists/story-dod-checklist.md +0 -101
  100. package/#Tools/APPIQ-METHOD/bmad-core/checklists/story-draft-checklist.md +0 -156
  101. package/#Tools/APPIQ-METHOD/bmad-core/core-config.yaml +0 -20
  102. package/#Tools/APPIQ-METHOD/bmad-core/core-config.yaml.bak +0 -20
  103. package/#Tools/APPIQ-METHOD/bmad-core/data/backend-services-integration.md +0 -686
  104. package/#Tools/APPIQ-METHOD/bmad-core/data/bmad-kb.md +0 -803
  105. package/#Tools/APPIQ-METHOD/bmad-core/data/brainstorming-techniques.md +0 -36
  106. package/#Tools/APPIQ-METHOD/bmad-core/data/elicitation-methods.md +0 -134
  107. package/#Tools/APPIQ-METHOD/bmad-core/data/shadcn-ui-integration.md +0 -388
  108. package/#Tools/APPIQ-METHOD/bmad-core/data/technical-preferences.md +0 -149
  109. package/#Tools/APPIQ-METHOD/bmad-core/enhanced-ide-development-workflow.md +0 -43
  110. package/#Tools/APPIQ-METHOD/bmad-core/tasks/advanced-elicitation.md +0 -117
  111. package/#Tools/APPIQ-METHOD/bmad-core/tasks/brownfield-create-epic.md +0 -160
  112. package/#Tools/APPIQ-METHOD/bmad-core/tasks/brownfield-create-story.md +0 -147
  113. package/#Tools/APPIQ-METHOD/bmad-core/tasks/correct-course.md +0 -70
  114. package/#Tools/APPIQ-METHOD/bmad-core/tasks/create-brownfield-story.md +0 -304
  115. package/#Tools/APPIQ-METHOD/bmad-core/tasks/create-deep-research-prompt.md +0 -289
  116. package/#Tools/APPIQ-METHOD/bmad-core/tasks/create-flutter-story.md +0 -197
  117. package/#Tools/APPIQ-METHOD/bmad-core/tasks/create-next-story.md +0 -112
  118. package/#Tools/APPIQ-METHOD/bmad-core/tasks/document-project.md +0 -341
  119. package/#Tools/APPIQ-METHOD/bmad-core/tasks/facilitate-brainstorming-session.md +0 -136
  120. package/#Tools/APPIQ-METHOD/bmad-core/tasks/generate-ai-frontend-prompt.md +0 -51
  121. package/#Tools/APPIQ-METHOD/bmad-core/tasks/index-docs.md +0 -179
  122. package/#Tools/APPIQ-METHOD/bmad-core/tasks/intelligent-epic-creation.md +0 -234
  123. package/#Tools/APPIQ-METHOD/bmad-core/tasks/kb-mode-interaction.md +0 -75
  124. package/#Tools/APPIQ-METHOD/bmad-core/tasks/review-story.md +0 -145
  125. package/#Tools/APPIQ-METHOD/bmad-core/tasks/shard-doc.md +0 -187
  126. package/#Tools/APPIQ-METHOD/bmad-core/tasks/smart-project-analysis.md +0 -289
  127. package/#Tools/APPIQ-METHOD/bmad-core/tasks/validate-next-story.md +0 -134
  128. package/#Tools/APPIQ-METHOD/bmad-core/templates/architecture-tmpl.yaml +0 -650
  129. package/#Tools/APPIQ-METHOD/bmad-core/templates/brainstorming-output-tmpl.yaml +0 -156
  130. package/#Tools/APPIQ-METHOD/bmad-core/templates/brownfield-architecture-tmpl.yaml +0 -476
  131. package/#Tools/APPIQ-METHOD/bmad-core/templates/brownfield-prd-tmpl.yaml +0 -280
  132. package/#Tools/APPIQ-METHOD/bmad-core/templates/competitor-analysis-tmpl.yaml +0 -293
  133. package/#Tools/APPIQ-METHOD/bmad-core/templates/flutter-mobile-prd-tmpl.yaml +0 -330
  134. package/#Tools/APPIQ-METHOD/bmad-core/templates/flutter-story-tmpl.yaml +0 -376
  135. package/#Tools/APPIQ-METHOD/bmad-core/templates/flutter-ui-spec-tmpl.yaml +0 -415
  136. package/#Tools/APPIQ-METHOD/bmad-core/templates/front-end-architecture-tmpl.yaml +0 -206
  137. package/#Tools/APPIQ-METHOD/bmad-core/templates/front-end-spec-tmpl.yaml +0 -349
  138. package/#Tools/APPIQ-METHOD/bmad-core/templates/fullstack-architecture-tmpl.yaml +0 -812
  139. package/#Tools/APPIQ-METHOD/bmad-core/templates/market-research-tmpl.yaml +0 -252
  140. package/#Tools/APPIQ-METHOD/bmad-core/templates/prd-tmpl.yaml +0 -202
  141. package/#Tools/APPIQ-METHOD/bmad-core/templates/project-brief-tmpl.yaml +0 -221
  142. package/#Tools/APPIQ-METHOD/bmad-core/templates/story-tmpl.yaml +0 -137
  143. package/#Tools/APPIQ-METHOD/bmad-core/user-guide.md +0 -251
  144. package/#Tools/APPIQ-METHOD/bmad-core/workflows/brownfield-fullstack.yaml +0 -311
  145. package/#Tools/APPIQ-METHOD/bmad-core/workflows/brownfield-service.yaml +0 -187
  146. package/#Tools/APPIQ-METHOD/bmad-core/workflows/brownfield-ui.yaml +0 -197
  147. package/#Tools/APPIQ-METHOD/bmad-core/workflows/greenfield-fullstack.yaml +0 -284
  148. package/#Tools/APPIQ-METHOD/bmad-core/workflows/greenfield-service.yaml +0 -206
  149. package/#Tools/APPIQ-METHOD/bmad-core/workflows/greenfield-ui.yaml +0 -235
  150. package/#Tools/APPIQ-METHOD/bmad-core/working-in-the-brownfield.md +0 -373
  151. package/#Tools/APPIQ-METHOD/commands/README.md +0 -28
  152. package/#Tools/APPIQ-METHOD/commands/analyze.md +0 -27
  153. package/#Tools/APPIQ-METHOD/commands/appiq.md +0 -27
  154. package/#Tools/APPIQ-METHOD/commands/help.md +0 -27
  155. package/#Tools/APPIQ-METHOD/commands/story.md +0 -27
  156. package/#Tools/APPIQ-METHOD/dist/agents/analyst.txt +0 -2882
  157. package/#Tools/APPIQ-METHOD/dist/agents/architect.txt +0 -3543
  158. package/#Tools/APPIQ-METHOD/dist/agents/bmad-master.txt +0 -8756
  159. package/#Tools/APPIQ-METHOD/dist/agents/bmad-orchestrator.txt +0 -1490
  160. package/#Tools/APPIQ-METHOD/dist/agents/dev.txt +0 -428
  161. package/#Tools/APPIQ-METHOD/dist/agents/pm.txt +0 -2229
  162. package/#Tools/APPIQ-METHOD/dist/agents/po.txt +0 -1364
  163. package/#Tools/APPIQ-METHOD/dist/agents/qa.txt +0 -386
  164. package/#Tools/APPIQ-METHOD/dist/agents/sm.txt +0 -668
  165. package/#Tools/APPIQ-METHOD/dist/agents/ux-expert.txt +0 -701
  166. package/#Tools/APPIQ-METHOD/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +0 -2408
  167. package/#Tools/APPIQ-METHOD/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +0 -1631
  168. package/#Tools/APPIQ-METHOD/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +0 -822
  169. package/#Tools/APPIQ-METHOD/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +0 -10989
  170. package/#Tools/APPIQ-METHOD/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.txt +0 -4047
  171. package/#Tools/APPIQ-METHOD/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.txt +0 -3744
  172. package/#Tools/APPIQ-METHOD/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.txt +0 -465
  173. package/#Tools/APPIQ-METHOD/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.txt +0 -990
  174. package/#Tools/APPIQ-METHOD/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +0 -15467
  175. package/#Tools/APPIQ-METHOD/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +0 -2077
  176. package/#Tools/APPIQ-METHOD/dist/teams/team-all.txt +0 -11062
  177. package/#Tools/APPIQ-METHOD/dist/teams/team-fullstack.txt +0 -10392
  178. package/#Tools/APPIQ-METHOD/dist/teams/team-ide-minimal.txt +0 -3507
  179. package/#Tools/APPIQ-METHOD/dist/teams/team-no-ui.txt +0 -8951
  180. package/#Tools/APPIQ-METHOD/install-appiq.sh +0 -41
  181. package/#Tools/APPIQ-METHOD/package-lock.json +0 -631
  182. package/#Tools/APPIQ-METHOD/package.json +0 -44
  183. package/#Tools/APPIQ-METHOD/tasks/todo.md +0 -275
  184. package/#Tools/APPIQ-METHOD/tools/appiq-installer.js +0 -2711
  185. package/#Tools/APPIQ-METHOD/tools/bmad-npx-wrapper.js +0 -39
  186. package/#Tools/APPIQ-METHOD/tools/builders/web-builder.js +0 -681
  187. package/#Tools/APPIQ-METHOD/tools/bump-all-versions.js +0 -106
  188. package/#Tools/APPIQ-METHOD/tools/bump-expansion-version.js +0 -83
  189. package/#Tools/APPIQ-METHOD/tools/cli.js +0 -152
  190. package/#Tools/APPIQ-METHOD/tools/epic-solution-installer.js +0 -536
  191. package/#Tools/APPIQ-METHOD/tools/flattener/main.js +0 -570
  192. package/#Tools/APPIQ-METHOD/tools/installer/README.md +0 -8
  193. package/#Tools/APPIQ-METHOD/tools/installer/bin/bmad.js +0 -483
  194. package/#Tools/APPIQ-METHOD/tools/installer/config/ide-agent-config.yaml +0 -58
  195. package/#Tools/APPIQ-METHOD/tools/installer/config/install.config.yaml +0 -92
  196. package/#Tools/APPIQ-METHOD/tools/installer/lib/config-loader.js +0 -253
  197. package/#Tools/APPIQ-METHOD/tools/installer/lib/file-manager.js +0 -411
  198. package/#Tools/APPIQ-METHOD/tools/installer/lib/ide-base-setup.js +0 -227
  199. package/#Tools/APPIQ-METHOD/tools/installer/lib/ide-setup.js +0 -1096
  200. package/#Tools/APPIQ-METHOD/tools/installer/lib/installer.js +0 -1772
  201. package/#Tools/APPIQ-METHOD/tools/installer/lib/memory-profiler.js +0 -224
  202. package/#Tools/APPIQ-METHOD/tools/installer/lib/module-manager.js +0 -110
  203. package/#Tools/APPIQ-METHOD/tools/installer/lib/resource-locator.js +0 -310
  204. package/#Tools/APPIQ-METHOD/tools/installer/package-lock.json +0 -906
  205. package/#Tools/APPIQ-METHOD/tools/installer/package.json +0 -43
  206. package/#Tools/APPIQ-METHOD/tools/lib/dependency-resolver.js +0 -179
  207. package/#Tools/APPIQ-METHOD/tools/lib/yaml-utils.js +0 -29
  208. package/#Tools/APPIQ-METHOD/tools/md-assets/web-agent-startup-instructions.md +0 -39
  209. package/#Tools/APPIQ-METHOD/tools/semantic-release-sync-installer.js +0 -30
  210. package/#Tools/APPIQ-METHOD/tools/setup-ide-commands.js +0 -348
  211. package/#Tools/APPIQ-METHOD/tools/smart-installer.js +0 -592
  212. package/#Tools/APPIQ-METHOD/tools/sync-installer-version.js +0 -34
  213. package/#Tools/APPIQ-METHOD/tools/update-expansion-version.js +0 -54
  214. package/#Tools/APPIQ-METHOD/tools/upgraders/v3-to-v4-upgrader.js +0 -763
  215. package/#Tools/APPIQ-METHOD/tools/version-bump.js +0 -79
  216. package/#Tools/APPIQ-METHOD/tools/yaml-format.js +0 -240
  217. package/#Tools/SkyReels-V2/.pre-commit-config.yaml +0 -25
  218. package/#Tools/SkyReels-V2/LICENSE.txt +0 -38
  219. package/#Tools/SkyReels-V2/README.md +0 -766
  220. package/#Tools/SkyReels-V2/generate_video.py +0 -161
  221. package/#Tools/SkyReels-V2/generate_video_df.py +0 -220
  222. package/#Tools/SkyReels-V2/requirements.txt +0 -16
  223. package/#Tools/SkyReels-V2/skycaptioner_v1/README.md +0 -278
  224. package/#Tools/SkyReels-V2/skycaptioner_v1/examples/test.csv +0 -5
  225. package/#Tools/SkyReels-V2/skycaptioner_v1/examples/test_result.csv +0 -5
  226. package/#Tools/SkyReels-V2/skycaptioner_v1/infer_fusion_caption.sh +0 -9
  227. package/#Tools/SkyReels-V2/skycaptioner_v1/infer_struct_caption.sh +0 -8
  228. package/#Tools/SkyReels-V2/skycaptioner_v1/requirements.txt +0 -3
  229. package/#Tools/SkyReels-V2/skycaptioner_v1/scripts/gradio_fusion_caption.py +0 -146
  230. package/#Tools/SkyReels-V2/skycaptioner_v1/scripts/gradio_struct_caption.py +0 -92
  231. package/#Tools/SkyReels-V2/skycaptioner_v1/scripts/utils.py +0 -19
  232. package/#Tools/SkyReels-V2/skycaptioner_v1/scripts/vllm_fusion_caption.py +0 -256
  233. package/#Tools/SkyReels-V2/skycaptioner_v1/scripts/vllm_struct_caption.py +0 -156
  234. package/#Tools/SkyReels-V2/skyreels_v2_infer/__init__.py +0 -1
  235. package/#Tools/SkyReels-V2/skyreels_v2_infer/distributed/__init__.py +0 -0
  236. package/#Tools/SkyReels-V2/skyreels_v2_infer/distributed/xdit_context_parallel.py +0 -286
  237. package/#Tools/SkyReels-V2/skyreels_v2_infer/modules/__init__.py +0 -69
  238. package/#Tools/SkyReels-V2/skyreels_v2_infer/modules/attention.py +0 -179
  239. package/#Tools/SkyReels-V2/skyreels_v2_infer/modules/clip.py +0 -525
  240. package/#Tools/SkyReels-V2/skyreels_v2_infer/modules/t5.py +0 -454
  241. package/#Tools/SkyReels-V2/skyreels_v2_infer/modules/tokenizers.py +0 -78
  242. package/#Tools/SkyReels-V2/skyreels_v2_infer/modules/transformer.py +0 -839
  243. package/#Tools/SkyReels-V2/skyreels_v2_infer/modules/vae.py +0 -639
  244. package/#Tools/SkyReels-V2/skyreels_v2_infer/modules/xlm_roberta.py +0 -165
  245. package/#Tools/SkyReels-V2/skyreels_v2_infer/pipelines/__init__.py +0 -5
  246. package/#Tools/SkyReels-V2/skyreels_v2_infer/pipelines/diffusion_forcing_pipeline.py +0 -659
  247. package/#Tools/SkyReels-V2/skyreels_v2_infer/pipelines/image2video_pipeline.py +0 -156
  248. package/#Tools/SkyReels-V2/skyreels_v2_infer/pipelines/prompt_enhancer.py +0 -65
  249. package/#Tools/SkyReels-V2/skyreels_v2_infer/pipelines/text2video_pipeline.py +0 -110
  250. package/#Tools/SkyReels-V2/skyreels_v2_infer/scheduler/__init__.py +0 -0
  251. package/#Tools/SkyReels-V2/skyreels_v2_infer/scheduler/fm_solvers_unipc.py +0 -759
  252. package/#Tools/SuperClaude/.claude/commands/analyze.md +0 -36
  253. package/#Tools/SuperClaude/.claude/commands/build.md +0 -35
  254. package/#Tools/SuperClaude/.claude/commands/cleanup.md +0 -46
  255. package/#Tools/SuperClaude/.claude/commands/deploy.md +0 -55
  256. package/#Tools/SuperClaude/.claude/commands/design.md +0 -91
  257. package/#Tools/SuperClaude/.claude/commands/dev-setup.md +0 -37
  258. package/#Tools/SuperClaude/.claude/commands/document.md +0 -99
  259. package/#Tools/SuperClaude/.claude/commands/estimate.md +0 -69
  260. package/#Tools/SuperClaude/.claude/commands/explain.md +0 -85
  261. package/#Tools/SuperClaude/.claude/commands/git.md +0 -47
  262. package/#Tools/SuperClaude/.claude/commands/improve.md +0 -162
  263. package/#Tools/SuperClaude/.claude/commands/index.md +0 -159
  264. package/#Tools/SuperClaude/.claude/commands/load.md +0 -65
  265. package/#Tools/SuperClaude/.claude/commands/migrate.md +0 -76
  266. package/#Tools/SuperClaude/.claude/commands/scan.md +0 -163
  267. package/#Tools/SuperClaude/.claude/commands/shared/ambiguity-check.yml +0 -40
  268. package/#Tools/SuperClaude/.claude/commands/shared/audit.yml +0 -21
  269. package/#Tools/SuperClaude/.claude/commands/shared/checkpoint.yml +0 -28
  270. package/#Tools/SuperClaude/.claude/commands/shared/cleanup-patterns.yml +0 -107
  271. package/#Tools/SuperClaude/.claude/commands/shared/command-memory.yml +0 -52
  272. package/#Tools/SuperClaude/.claude/commands/shared/command-templates.yml +0 -167
  273. package/#Tools/SuperClaude/.claude/commands/shared/config-validator.yml +0 -206
  274. package/#Tools/SuperClaude/.claude/commands/shared/constants.yml +0 -311
  275. package/#Tools/SuperClaude/.claude/commands/shared/documentation-dirs.yml +0 -134
  276. package/#Tools/SuperClaude/.claude/commands/shared/error-handling.yml +0 -341
  277. package/#Tools/SuperClaude/.claude/commands/shared/evidence.yml +0 -75
  278. package/#Tools/SuperClaude/.claude/commands/shared/execution-lifecycle.yml +0 -277
  279. package/#Tools/SuperClaude/.claude/commands/shared/git-operations.yml +0 -217
  280. package/#Tools/SuperClaude/.claude/commands/shared/git-workflow.yml +0 -37
  281. package/#Tools/SuperClaude/.claude/commands/shared/implementation.yml +0 -199
  282. package/#Tools/SuperClaude/.claude/commands/shared/loading-config.yml +0 -73
  283. package/#Tools/SuperClaude/.claude/commands/shared/mcp-flags.yml +0 -109
  284. package/#Tools/SuperClaude/.claude/commands/shared/migration-report.md +0 -165
  285. package/#Tools/SuperClaude/.claude/commands/shared/patterns.yml +0 -155
  286. package/#Tools/SuperClaude/.claude/commands/shared/performance.yml +0 -317
  287. package/#Tools/SuperClaude/.claude/commands/shared/planning-mode.yml +0 -51
  288. package/#Tools/SuperClaude/.claude/commands/shared/research-first.yml +0 -278
  289. package/#Tools/SuperClaude/.claude/commands/shared/session-recovery.yml +0 -144
  290. package/#Tools/SuperClaude/.claude/commands/shared/severity-levels.yml +0 -252
  291. package/#Tools/SuperClaude/.claude/commands/shared/task-system.yml +0 -380
  292. package/#Tools/SuperClaude/.claude/commands/shared/task-ultracompressed.yml +0 -88
  293. package/#Tools/SuperClaude/.claude/commands/shared/templates/feature-template.md +0 -59
  294. package/#Tools/SuperClaude/.claude/commands/shared/templates/task-ultracompressed.md +0 -26
  295. package/#Tools/SuperClaude/.claude/commands/shared/thinking-modes.yml +0 -61
  296. package/#Tools/SuperClaude/.claude/commands/shared/ultracompressed.yml +0 -97
  297. package/#Tools/SuperClaude/.claude/commands/shared/user-experience.yml +0 -208
  298. package/#Tools/SuperClaude/.claude/commands/shared/validation.yml +0 -54
  299. package/#Tools/SuperClaude/.claude/commands/shared/workflow-chains.yml +0 -138
  300. package/#Tools/SuperClaude/.claude/commands/spawn.md +0 -106
  301. package/#Tools/SuperClaude/.claude/commands/task.md +0 -110
  302. package/#Tools/SuperClaude/.claude/commands/test.md +0 -67
  303. package/#Tools/SuperClaude/.claude/commands/troubleshoot.md +0 -93
  304. package/#Tools/SuperClaude/.github/ISSUE_TEMPLATE/bug_report.yml +0 -114
  305. package/#Tools/SuperClaude/.github/ISSUE_TEMPLATE/feature_request.yml +0 -119
  306. package/#Tools/SuperClaude/.github/ISSUE_TEMPLATE/question.yml +0 -87
  307. package/#Tools/SuperClaude/.github/pull_request_template.md +0 -62
  308. package/#Tools/SuperClaude/CHANGELOG.md +0 -109
  309. package/#Tools/SuperClaude/CLAUDE.md +0 -95
  310. package/#Tools/SuperClaude/CODE_OF_CONDUCT.md +0 -45
  311. package/#Tools/SuperClaude/CONTRIBUTING.md +0 -225
  312. package/#Tools/SuperClaude/Commands_Cheat_Sheet.md +0 -160
  313. package/#Tools/SuperClaude/LICENSE +0 -21
  314. package/#Tools/SuperClaude/MCP.md +0 -117
  315. package/#Tools/SuperClaude/PERSONAS.md +0 -115
  316. package/#Tools/SuperClaude/README.md +0 -249
  317. package/#Tools/SuperClaude/RULES.md +0 -220
  318. package/#Tools/SuperClaude/SECURITY.md +0 -91
  319. package/#Tools/SuperClaude/install.sh +0 -296
  320. package/#Tools/claude-talk-to-figma-mcp/.github/workflows/test.yml +0 -36
  321. package/#Tools/claude-talk-to-figma-mcp/CHANGELOG.md +0 -88
  322. package/#Tools/claude-talk-to-figma-mcp/Dockerfile +0 -16
  323. package/#Tools/claude-talk-to-figma-mcp/LICENSE +0 -22
  324. package/#Tools/claude-talk-to-figma-mcp/TESTING.md +0 -216
  325. package/#Tools/claude-talk-to-figma-mcp/bun.lock +0 -964
  326. package/#Tools/claude-talk-to-figma-mcp/context/01/00-analisis.md +0 -151
  327. package/#Tools/claude-talk-to-figma-mcp/context/01/01-tools-refactor.md +0 -370
  328. package/#Tools/claude-talk-to-figma-mcp/context/01/02-tools-refactor-backlog.md +0 -253
  329. package/#Tools/claude-talk-to-figma-mcp/context/01/03-tools-refactor-test.md +0 -138
  330. package/#Tools/claude-talk-to-figma-mcp/context/01/04-tools-refactor-channel-error.md +0 -133
  331. package/#Tools/claude-talk-to-figma-mcp/context/01/04-tools-refactor-test-backlog.md +0 -0
  332. package/#Tools/claude-talk-to-figma-mcp/context/01/05-tools-refactor-four-tools-error.md +0 -356
  333. package/#Tools/claude-talk-to-figma-mcp/context/01/06-tools-refactor-four-tools-error-backlog.md +0 -425
  334. package/#Tools/claude-talk-to-figma-mcp/context/01/prompt-dev-nodejs-bun.md +0 -105
  335. package/#Tools/claude-talk-to-figma-mcp/context/01-prompt.md +0 -135
  336. package/#Tools/claude-talk-to-figma-mcp/context/02/00-analisis.md +0 -131
  337. package/#Tools/claude-talk-to-figma-mcp/context/02/01-plan.md +0 -162
  338. package/#Tools/claude-talk-to-figma-mcp/context/02/02-backlog.md +0 -241
  339. package/#Tools/claude-talk-to-figma-mcp/context/02-analisis.md +0 -202
  340. package/#Tools/claude-talk-to-figma-mcp/context/99-notas.md +0 -139
  341. package/#Tools/claude-talk-to-figma-mcp/context/pr-14/pr-14-analisis.md +0 -221
  342. package/#Tools/claude-talk-to-figma-mcp/context/pr-14/pr-14-claude-tests.md +0 -152
  343. package/#Tools/claude-talk-to-figma-mcp/context/pr-14/pr-14-npm-publishing.md +0 -272
  344. package/#Tools/claude-talk-to-figma-mcp/images/claude-talk-to-figma.png +0 -0
  345. package/#Tools/claude-talk-to-figma-mcp/images/mcp-figma-plugin-configuration.png +0 -0
  346. package/#Tools/claude-talk-to-figma-mcp/jest.config.cjs +0 -25
  347. package/#Tools/claude-talk-to-figma-mcp/package.json +0 -67
  348. package/#Tools/claude-talk-to-figma-mcp/prompts/prompt-ux-ui-especialista-es.md +0 -82
  349. package/#Tools/claude-talk-to-figma-mcp/prompts/prompt-ux-ui-especialista-gal.md +0 -80
  350. package/#Tools/claude-talk-to-figma-mcp/prompts/prompt-ux-ui-especialista-pt.md +0 -80
  351. package/#Tools/claude-talk-to-figma-mcp/prompts/prompt-ux-ui-specialist.md +0 -80
  352. package/#Tools/claude-talk-to-figma-mcp/readme.md +0 -307
  353. package/#Tools/claude-talk-to-figma-mcp/scripts/configure-claude.js +0 -90
  354. package/#Tools/claude-talk-to-figma-mcp/scripts/setup.sh +0 -30
  355. package/#Tools/claude-talk-to-figma-mcp/scripts/test-integration.js +0 -339
  356. package/#Tools/claude-talk-to-figma-mcp/smithery.yaml +0 -26
  357. package/#Tools/claude-talk-to-figma-mcp/src/claude_mcp_plugin/code.js +0 -3295
  358. package/#Tools/claude-talk-to-figma-mcp/src/claude_mcp_plugin/manifest.json +0 -24
  359. package/#Tools/claude-talk-to-figma-mcp/src/claude_mcp_plugin/setcharacters.js +0 -215
  360. package/#Tools/claude-talk-to-figma-mcp/src/claude_mcp_plugin/ui.html +0 -656
  361. package/#Tools/claude-talk-to-figma-mcp/src/socket.ts +0 -349
  362. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/bun.lock +0 -246
  363. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/config/config.ts +0 -22
  364. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/package.json +0 -31
  365. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/prompts/index.ts +0 -297
  366. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/server.ts +0 -62
  367. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/tools/component-tools.ts +0 -48
  368. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/tools/creation-tools.ts +0 -620
  369. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/tools/document-tools.ts +0 -390
  370. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/tools/index.ts +0 -28
  371. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/tools/modification-tools.ts +0 -408
  372. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/tools/text-tools.ts +0 -531
  373. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/tsconfig.json +0 -18
  374. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/types/color.ts +0 -13
  375. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/types/index.ts +0 -87
  376. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/utils/defaults.ts +0 -23
  377. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/utils/figma-helpers.ts +0 -142
  378. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/utils/logger.ts +0 -8
  379. package/#Tools/claude-talk-to-figma-mcp/src/talk_to_figma_mcp/utils/websocket.ts +0 -258
  380. package/#Tools/claude-talk-to-figma-mcp/tests/fixtures/test-data.ts +0 -32
  381. package/#Tools/claude-talk-to-figma-mcp/tests/integration/set-fill-color.test.ts +0 -309
  382. package/#Tools/claude-talk-to-figma-mcp/tests/integration/set-stroke-color.test.ts +0 -387
  383. package/#Tools/claude-talk-to-figma-mcp/tests/setup.ts +0 -7
  384. package/#Tools/claude-talk-to-figma-mcp/tests/unit/utils/defaults.test.ts +0 -131
  385. package/#Tools/claude-talk-to-figma-mcp/tsconfig.json +0 -17
  386. package/#Tools/claude-talk-to-figma-mcp/tsup.config.ts +0 -14
  387. package/#Tools/jwt creator/AuthKey_MZ7UQGFV2Q.p8 +0 -6
  388. package/#Tools/jwt creator/generate_apple_jwt.js +0 -18
  389. package/#Tools/jwt creator/node_modules/.package-lock.json +0 -145
  390. package/#Tools/jwt creator/node_modules/buffer-equal-constant-time/.travis.yml +0 -4
  391. package/#Tools/jwt creator/node_modules/buffer-equal-constant-time/LICENSE.txt +0 -12
  392. package/#Tools/jwt creator/node_modules/buffer-equal-constant-time/README.md +0 -50
  393. package/#Tools/jwt creator/node_modules/buffer-equal-constant-time/index.js +0 -41
  394. package/#Tools/jwt creator/node_modules/buffer-equal-constant-time/package.json +0 -21
  395. package/#Tools/jwt creator/node_modules/buffer-equal-constant-time/test.js +0 -42
  396. package/#Tools/jwt creator/node_modules/ecdsa-sig-formatter/CODEOWNERS +0 -1
  397. package/#Tools/jwt creator/node_modules/ecdsa-sig-formatter/LICENSE +0 -201
  398. package/#Tools/jwt creator/node_modules/ecdsa-sig-formatter/README.md +0 -65
  399. package/#Tools/jwt creator/node_modules/ecdsa-sig-formatter/package.json +0 -46
  400. package/#Tools/jwt creator/node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.d.ts +0 -17
  401. package/#Tools/jwt creator/node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.js +0 -187
  402. package/#Tools/jwt creator/node_modules/ecdsa-sig-formatter/src/param-bytes-for-alg.js +0 -23
  403. package/#Tools/jwt creator/node_modules/jsonwebtoken/LICENSE +0 -21
  404. package/#Tools/jwt creator/node_modules/jsonwebtoken/README.md +0 -396
  405. package/#Tools/jwt creator/node_modules/jsonwebtoken/decode.js +0 -30
  406. package/#Tools/jwt creator/node_modules/jsonwebtoken/index.js +0 -8
  407. package/#Tools/jwt creator/node_modules/jsonwebtoken/lib/JsonWebTokenError.js +0 -14
  408. package/#Tools/jwt creator/node_modules/jsonwebtoken/lib/NotBeforeError.js +0 -13
  409. package/#Tools/jwt creator/node_modules/jsonwebtoken/lib/TokenExpiredError.js +0 -13
  410. package/#Tools/jwt creator/node_modules/jsonwebtoken/lib/asymmetricKeyDetailsSupported.js +0 -3
  411. package/#Tools/jwt creator/node_modules/jsonwebtoken/lib/psSupported.js +0 -3
  412. package/#Tools/jwt creator/node_modules/jsonwebtoken/lib/rsaPssKeyDetailsSupported.js +0 -3
  413. package/#Tools/jwt creator/node_modules/jsonwebtoken/lib/timespan.js +0 -18
  414. package/#Tools/jwt creator/node_modules/jsonwebtoken/lib/validateAsymmetricKey.js +0 -66
  415. package/#Tools/jwt creator/node_modules/jsonwebtoken/package.json +0 -71
  416. package/#Tools/jwt creator/node_modules/jsonwebtoken/sign.js +0 -253
  417. package/#Tools/jwt creator/node_modules/jsonwebtoken/verify.js +0 -263
  418. package/#Tools/jwt creator/node_modules/jwa/LICENSE +0 -17
  419. package/#Tools/jwt creator/node_modules/jwa/README.md +0 -150
  420. package/#Tools/jwt creator/node_modules/jwa/index.js +0 -266
  421. package/#Tools/jwt creator/node_modules/jwa/package.json +0 -37
  422. package/#Tools/jwt creator/node_modules/jws/CHANGELOG.md +0 -34
  423. package/#Tools/jwt creator/node_modules/jws/LICENSE +0 -17
  424. package/#Tools/jwt creator/node_modules/jws/index.js +0 -22
  425. package/#Tools/jwt creator/node_modules/jws/lib/data-stream.js +0 -55
  426. package/#Tools/jwt creator/node_modules/jws/lib/sign-stream.js +0 -78
  427. package/#Tools/jwt creator/node_modules/jws/lib/tostring.js +0 -10
  428. package/#Tools/jwt creator/node_modules/jws/lib/verify-stream.js +0 -120
  429. package/#Tools/jwt creator/node_modules/jws/package.json +0 -34
  430. package/#Tools/jwt creator/node_modules/jws/readme.md +0 -255
  431. package/#Tools/jwt creator/node_modules/lodash.includes/LICENSE +0 -47
  432. package/#Tools/jwt creator/node_modules/lodash.includes/README.md +0 -18
  433. package/#Tools/jwt creator/node_modules/lodash.includes/index.js +0 -745
  434. package/#Tools/jwt creator/node_modules/lodash.includes/package.json +0 -17
  435. package/#Tools/jwt creator/node_modules/lodash.isboolean/LICENSE +0 -22
  436. package/#Tools/jwt creator/node_modules/lodash.isboolean/README.md +0 -18
  437. package/#Tools/jwt creator/node_modules/lodash.isboolean/index.js +0 -70
  438. package/#Tools/jwt creator/node_modules/lodash.isboolean/package.json +0 -17
  439. package/#Tools/jwt creator/node_modules/lodash.isinteger/LICENSE +0 -47
  440. package/#Tools/jwt creator/node_modules/lodash.isinteger/README.md +0 -18
  441. package/#Tools/jwt creator/node_modules/lodash.isinteger/index.js +0 -265
  442. package/#Tools/jwt creator/node_modules/lodash.isinteger/package.json +0 -17
  443. package/#Tools/jwt creator/node_modules/lodash.isnumber/LICENSE +0 -22
  444. package/#Tools/jwt creator/node_modules/lodash.isnumber/README.md +0 -18
  445. package/#Tools/jwt creator/node_modules/lodash.isnumber/index.js +0 -79
  446. package/#Tools/jwt creator/node_modules/lodash.isnumber/package.json +0 -17
  447. package/#Tools/jwt creator/node_modules/lodash.isplainobject/LICENSE +0 -47
  448. package/#Tools/jwt creator/node_modules/lodash.isplainobject/README.md +0 -18
  449. package/#Tools/jwt creator/node_modules/lodash.isplainobject/index.js +0 -139
  450. package/#Tools/jwt creator/node_modules/lodash.isplainobject/package.json +0 -17
  451. package/#Tools/jwt creator/node_modules/lodash.isstring/LICENSE +0 -22
  452. package/#Tools/jwt creator/node_modules/lodash.isstring/README.md +0 -18
  453. package/#Tools/jwt creator/node_modules/lodash.isstring/index.js +0 -95
  454. package/#Tools/jwt creator/node_modules/lodash.isstring/package.json +0 -17
  455. package/#Tools/jwt creator/node_modules/lodash.once/LICENSE +0 -47
  456. package/#Tools/jwt creator/node_modules/lodash.once/README.md +0 -18
  457. package/#Tools/jwt creator/node_modules/lodash.once/index.js +0 -294
  458. package/#Tools/jwt creator/node_modules/lodash.once/package.json +0 -17
  459. package/#Tools/jwt creator/node_modules/ms/index.js +0 -162
  460. package/#Tools/jwt creator/node_modules/ms/license.md +0 -21
  461. package/#Tools/jwt creator/node_modules/ms/package.json +0 -38
  462. package/#Tools/jwt creator/node_modules/ms/readme.md +0 -59
  463. package/#Tools/jwt creator/node_modules/safe-buffer/LICENSE +0 -21
  464. package/#Tools/jwt creator/node_modules/safe-buffer/README.md +0 -584
  465. package/#Tools/jwt creator/node_modules/safe-buffer/index.d.ts +0 -187
  466. package/#Tools/jwt creator/node_modules/safe-buffer/index.js +0 -65
  467. package/#Tools/jwt creator/node_modules/safe-buffer/package.json +0 -51
  468. package/#Tools/jwt creator/node_modules/semver/LICENSE +0 -15
  469. package/#Tools/jwt creator/node_modules/semver/README.md +0 -664
  470. package/#Tools/jwt creator/node_modules/semver/bin/semver.js +0 -191
  471. package/#Tools/jwt creator/node_modules/semver/classes/comparator.js +0 -143
  472. package/#Tools/jwt creator/node_modules/semver/classes/index.js +0 -7
  473. package/#Tools/jwt creator/node_modules/semver/classes/range.js +0 -556
  474. package/#Tools/jwt creator/node_modules/semver/classes/semver.js +0 -319
  475. package/#Tools/jwt creator/node_modules/semver/functions/clean.js +0 -8
  476. package/#Tools/jwt creator/node_modules/semver/functions/cmp.js +0 -54
  477. package/#Tools/jwt creator/node_modules/semver/functions/coerce.js +0 -62
  478. package/#Tools/jwt creator/node_modules/semver/functions/compare-build.js +0 -9
  479. package/#Tools/jwt creator/node_modules/semver/functions/compare-loose.js +0 -5
  480. package/#Tools/jwt creator/node_modules/semver/functions/compare.js +0 -7
  481. package/#Tools/jwt creator/node_modules/semver/functions/diff.js +0 -60
  482. package/#Tools/jwt creator/node_modules/semver/functions/eq.js +0 -5
  483. package/#Tools/jwt creator/node_modules/semver/functions/gt.js +0 -5
  484. package/#Tools/jwt creator/node_modules/semver/functions/gte.js +0 -5
  485. package/#Tools/jwt creator/node_modules/semver/functions/inc.js +0 -21
  486. package/#Tools/jwt creator/node_modules/semver/functions/lt.js +0 -5
  487. package/#Tools/jwt creator/node_modules/semver/functions/lte.js +0 -5
  488. package/#Tools/jwt creator/node_modules/semver/functions/major.js +0 -5
  489. package/#Tools/jwt creator/node_modules/semver/functions/minor.js +0 -5
  490. package/#Tools/jwt creator/node_modules/semver/functions/neq.js +0 -5
  491. package/#Tools/jwt creator/node_modules/semver/functions/parse.js +0 -18
  492. package/#Tools/jwt creator/node_modules/semver/functions/patch.js +0 -5
  493. package/#Tools/jwt creator/node_modules/semver/functions/prerelease.js +0 -8
  494. package/#Tools/jwt creator/node_modules/semver/functions/rcompare.js +0 -5
  495. package/#Tools/jwt creator/node_modules/semver/functions/rsort.js +0 -5
  496. package/#Tools/jwt creator/node_modules/semver/functions/satisfies.js +0 -12
  497. package/#Tools/jwt creator/node_modules/semver/functions/sort.js +0 -5
  498. package/#Tools/jwt creator/node_modules/semver/functions/valid.js +0 -8
  499. package/#Tools/jwt creator/node_modules/semver/index.js +0 -91
  500. package/#Tools/jwt creator/node_modules/semver/internal/constants.js +0 -37
  501. package/#Tools/jwt creator/node_modules/semver/internal/debug.js +0 -11
  502. package/#Tools/jwt creator/node_modules/semver/internal/identifiers.js +0 -25
  503. package/#Tools/jwt creator/node_modules/semver/internal/lrucache.js +0 -42
  504. package/#Tools/jwt creator/node_modules/semver/internal/parse-options.js +0 -17
  505. package/#Tools/jwt creator/node_modules/semver/internal/re.js +0 -223
  506. package/#Tools/jwt creator/node_modules/semver/package.json +0 -78
  507. package/#Tools/jwt creator/node_modules/semver/preload.js +0 -4
  508. package/#Tools/jwt creator/node_modules/semver/range.bnf +0 -16
  509. package/#Tools/jwt creator/node_modules/semver/ranges/gtr.js +0 -6
  510. package/#Tools/jwt creator/node_modules/semver/ranges/intersects.js +0 -9
  511. package/#Tools/jwt creator/node_modules/semver/ranges/ltr.js +0 -6
  512. package/#Tools/jwt creator/node_modules/semver/ranges/max-satisfying.js +0 -27
  513. package/#Tools/jwt creator/node_modules/semver/ranges/min-satisfying.js +0 -26
  514. package/#Tools/jwt creator/node_modules/semver/ranges/min-version.js +0 -63
  515. package/#Tools/jwt creator/node_modules/semver/ranges/outside.js +0 -82
  516. package/#Tools/jwt creator/node_modules/semver/ranges/simplify.js +0 -49
  517. package/#Tools/jwt creator/node_modules/semver/ranges/subset.js +0 -249
  518. package/#Tools/jwt creator/node_modules/semver/ranges/to-comparators.js +0 -10
  519. package/#Tools/jwt creator/node_modules/semver/ranges/valid.js +0 -13
  520. package/#Tools/jwt creator/package-lock.json +0 -150
  521. package/#Tools/jwt creator/package.json +0 -5
  522. package/#Tools/package.json +0 -94
  523. package/SuperClaude/.claude/commands/analyze.md +0 -36
  524. package/SuperClaude/.claude/commands/build.md +0 -35
  525. package/SuperClaude/.claude/commands/cleanup.md +0 -46
  526. package/SuperClaude/.claude/commands/deploy.md +0 -55
  527. package/SuperClaude/.claude/commands/design.md +0 -91
  528. package/SuperClaude/.claude/commands/dev-setup.md +0 -37
  529. package/SuperClaude/.claude/commands/document.md +0 -99
  530. package/SuperClaude/.claude/commands/estimate.md +0 -69
  531. package/SuperClaude/.claude/commands/explain.md +0 -85
  532. package/SuperClaude/.claude/commands/git.md +0 -47
  533. package/SuperClaude/.claude/commands/improve.md +0 -162
  534. package/SuperClaude/.claude/commands/index.md +0 -159
  535. package/SuperClaude/.claude/commands/load.md +0 -65
  536. package/SuperClaude/.claude/commands/migrate.md +0 -76
  537. package/SuperClaude/.claude/commands/scan.md +0 -163
  538. package/SuperClaude/.claude/commands/shared/ambiguity-check.yml +0 -40
  539. package/SuperClaude/.claude/commands/shared/audit.yml +0 -21
  540. package/SuperClaude/.claude/commands/shared/checkpoint.yml +0 -28
  541. package/SuperClaude/.claude/commands/shared/cleanup-patterns.yml +0 -107
  542. package/SuperClaude/.claude/commands/shared/command-memory.yml +0 -52
  543. package/SuperClaude/.claude/commands/shared/command-templates.yml +0 -167
  544. package/SuperClaude/.claude/commands/shared/config-validator.yml +0 -206
  545. package/SuperClaude/.claude/commands/shared/constants.yml +0 -311
  546. package/SuperClaude/.claude/commands/shared/documentation-dirs.yml +0 -134
  547. package/SuperClaude/.claude/commands/shared/error-handling.yml +0 -341
  548. package/SuperClaude/.claude/commands/shared/evidence.yml +0 -75
  549. package/SuperClaude/.claude/commands/shared/execution-lifecycle.yml +0 -277
  550. package/SuperClaude/.claude/commands/shared/git-operations.yml +0 -217
  551. package/SuperClaude/.claude/commands/shared/git-workflow.yml +0 -37
  552. package/SuperClaude/.claude/commands/shared/implementation.yml +0 -199
  553. package/SuperClaude/.claude/commands/shared/loading-config.yml +0 -73
  554. package/SuperClaude/.claude/commands/shared/mcp-flags.yml +0 -109
  555. package/SuperClaude/.claude/commands/shared/migration-report.md +0 -165
  556. package/SuperClaude/.claude/commands/shared/patterns.yml +0 -155
  557. package/SuperClaude/.claude/commands/shared/performance.yml +0 -317
  558. package/SuperClaude/.claude/commands/shared/planning-mode.yml +0 -51
  559. package/SuperClaude/.claude/commands/shared/research-first.yml +0 -278
  560. package/SuperClaude/.claude/commands/shared/session-recovery.yml +0 -144
  561. package/SuperClaude/.claude/commands/shared/severity-levels.yml +0 -252
  562. package/SuperClaude/.claude/commands/shared/task-system.yml +0 -380
  563. package/SuperClaude/.claude/commands/shared/task-ultracompressed.yml +0 -88
  564. package/SuperClaude/.claude/commands/shared/templates/feature-template.md +0 -59
  565. package/SuperClaude/.claude/commands/shared/templates/task-ultracompressed.md +0 -26
  566. package/SuperClaude/.claude/commands/shared/thinking-modes.yml +0 -61
  567. package/SuperClaude/.claude/commands/shared/ultracompressed.yml +0 -97
  568. package/SuperClaude/.claude/commands/shared/user-experience.yml +0 -208
  569. package/SuperClaude/.claude/commands/shared/validation.yml +0 -54
  570. package/SuperClaude/.claude/commands/shared/workflow-chains.yml +0 -138
  571. package/SuperClaude/.claude/commands/spawn.md +0 -106
  572. package/SuperClaude/.claude/commands/task.md +0 -110
  573. package/SuperClaude/.claude/commands/test.md +0 -67
  574. package/SuperClaude/.claude/commands/troubleshoot.md +0 -93
  575. package/SuperClaude/.github/ISSUE_TEMPLATE/bug_report.yml +0 -114
  576. package/SuperClaude/.github/ISSUE_TEMPLATE/feature_request.yml +0 -119
  577. package/SuperClaude/.github/ISSUE_TEMPLATE/question.yml +0 -87
  578. package/SuperClaude/.github/pull_request_template.md +0 -62
  579. package/SuperClaude/CHANGELOG.md +0 -109
  580. package/SuperClaude/CLAUDE.md +0 -95
  581. package/SuperClaude/CODE_OF_CONDUCT.md +0 -45
  582. package/SuperClaude/CONTRIBUTING.md +0 -225
  583. package/SuperClaude/Commands_Cheat_Sheet.md +0 -160
  584. package/SuperClaude/LICENSE +0 -21
  585. package/SuperClaude/MCP.md +0 -117
  586. package/SuperClaude/PERSONAS.md +0 -115
  587. package/SuperClaude/README.md +0 -249
  588. package/SuperClaude/RULES.md +0 -220
  589. package/SuperClaude/SECURITY.md +0 -91
  590. package/SuperClaude/install.sh +0 -296
  591. package/appiq-mcp installer/How-to.md +0 -250
  592. package/appiq-mcp installer/LICENSE +0 -21
  593. package/appiq-mcp installer/README.md +0 -235
  594. package/appiq-mcp installer/index.js +0 -672
  595. package/appiq-mcp installer/my_mcps.md +0 -105
  596. package/appiq-mcp installer/package-lock.json +0 -708
  597. package/appiq-mcp installer/package.json +0 -46
  598. package/appiq-mcp installer/test-install.bat +0 -60
  599. package/appiq-mcp installer/test-install.sh +0 -55
  600. package/appiq-mcp installer/test-load.js +0 -40
  601. package/bmad-core/agent-teams/team-flutter-mobile.yaml +0 -114
  602. package/bmad-core/agents/bmad-smart-launcher.md +0 -170
  603. package/bmad-core/agents/init-flow-po.md +0 -143
  604. package/bmad-core/checklists/security-validation-checklist.md +0 -332
  605. package/bmad-core/core-config.yaml.bak +0 -20
  606. package/bmad-core/data/backend-services-integration.md +0 -686
  607. package/bmad-core/data/shadcn-ui-integration.md +0 -388
  608. package/bmad-core/tasks/create-flutter-story.md +0 -197
  609. package/bmad-core/tasks/intelligent-epic-creation.md +0 -234
  610. package/bmad-core/tasks/smart-project-analysis.md +0 -289
  611. package/bmad-core/templates/flutter-mobile-prd-tmpl.yaml +0 -330
  612. package/bmad-core/templates/flutter-story-tmpl.yaml +0 -376
  613. package/bmad-core/templates/flutter-ui-spec-tmpl.yaml +0 -415
  614. package/dist/expansion-packs/bmad-mobile-app-dev/agents/mobile-analytics.txt +0 -1530
  615. package/dist/expansion-packs/bmad-mobile-app-dev/agents/mobile-architect.txt +0 -322
  616. package/dist/expansion-packs/bmad-mobile-app-dev/agents/mobile-developer.txt +0 -692
  617. package/dist/expansion-packs/bmad-mobile-app-dev/agents/mobile-pm.txt +0 -382
  618. package/dist/expansion-packs/bmad-mobile-app-dev/agents/mobile-qa.txt +0 -665
  619. package/dist/expansion-packs/bmad-mobile-app-dev/agents/mobile-security.txt +0 -1070
  620. package/dist/expansion-packs/bmad-mobile-app-dev/agents/mobile-ux-expert.txt +0 -1494
  621. package/dist/expansion-packs/bmad-mobile-app-dev/teams/mobile-team-cross-platform.txt +0 -15613
  622. package/flutter/CLAUDE.md +0 -58
  623. package/flutter/punkt.claude/New Folder With Items/channel.md +0 -221
  624. package/flutter/punkt.claude/New Folder With Items/commands/add-translations.md +0 -12
  625. package/flutter/punkt.claude/New Folder With Items/commands/create-feature.md +0 -168
  626. package/flutter/punkt.claude/New Folder With Items/commands/explain-codebase.md +0 -1
  627. package/flutter/punkt.claude/New Folder With Items/commands/feature-business-logic.md +0 -551
  628. package/flutter/punkt.claude/New Folder With Items/commands/feature-data-layer.md +0 -924
  629. package/flutter/punkt.claude/New Folder With Items/commands/feature-domain-layer.md +0 -540
  630. package/flutter/punkt.claude/New Folder With Items/commands/feature-integration.md +0 -493
  631. package/flutter/punkt.claude/New Folder With Items/commands/feature-localization.md +0 -427
  632. package/flutter/punkt.claude/New Folder With Items/commands/feature-ui-layer.md +0 -300
  633. package/flutter/punkt.claude/New Folder With Items/commands/git-commit.md +0 -3
  634. package/flutter/punkt.claude/New Folder With Items/commands/search-web.md +0 -1
  635. package/flutter/punkt.claude/punkt.claude/channel.md +0 -225
  636. package/flutter/punkt.claude/punkt.claude/commands/add-translations.md +0 -60
  637. package/flutter/punkt.claude/punkt.claude/commands/bug-fix.md +0 -32
  638. package/flutter/punkt.claude/punkt.claude/commands/checkdev.md +0 -122
  639. package/flutter/punkt.claude/punkt.claude/commands/create-feature.md +0 -174
  640. package/flutter/punkt.claude/punkt.claude/commands/dev.md +0 -79
  641. package/flutter/punkt.claude/punkt.claude/commands/explain-codebase.md +0 -1
  642. package/flutter/punkt.claude/punkt.claude/commands/feature-business-logic.md +0 -430
  643. package/flutter/punkt.claude/punkt.claude/commands/feature-data-layer.md +0 -572
  644. package/flutter/punkt.claude/punkt.claude/commands/feature-domain-layer.md +0 -537
  645. package/flutter/punkt.claude/punkt.claude/commands/feature-integration.md +0 -493
  646. package/flutter/punkt.claude/punkt.claude/commands/feature-localization.md +0 -427
  647. package/flutter/punkt.claude/punkt.claude/commands/feature-ui-layer.md +0 -831
  648. package/flutter/punkt.claude/punkt.claude/commands/git-commit.md +0 -3
  649. package/flutter/punkt.claude/punkt.claude/commands/manage-translations.md +0 -433
  650. package/flutter/punkt.claude/punkt.claude/commands/search-web.md +0 -1
  651. package/flutter/punkt.claude/punkt.claude/developer_check.md +0 -121
  652. package/tools/appiq-installer.js +0 -2711
  653. package/tools/epic-solution-installer.js +0 -536
  654. package/tools/setup-ide-commands.js +0 -348
  655. package/tools/smart-installer.js +0 -592
  656. package/web/CLAUDE.md +0 -58
  657. /package/{#Tools/APPIQ-METHOD/.github → .github}/FUNDING.yaml +0 -0
  658. /package/{#Tools/APPIQ-METHOD/.github → .github}/ISSUE_TEMPLATE/bug_report.md +0 -0
  659. /package/{#Tools/APPIQ-METHOD/.github → .github}/ISSUE_TEMPLATE/feature_request.md +0 -0
  660. /package/{#Tools/APPIQ-METHOD/.github → .github}/workflows/release.yaml +0 -0
  661. /package/{#Tools/APPIQ-METHOD/.releaserc.json → .releaserc.json} +0 -0
  662. /package/{#Tools/APPIQ-METHOD/.vscode → .vscode}/settings.json +0 -0
  663. /package/{#Tools/APPIQ-METHOD/CHANGELOG.md → CHANGELOG.md} +0 -0
  664. /package/{#Tools/APPIQ-METHOD/CONTRIBUTING.md → CONTRIBUTING.md} +0 -0
  665. /package/{#Tools/APPIQ-METHOD/LICENSE → LICENSE} +0 -0
  666. /package/{#Tools/APPIQ-METHOD/common → common}/tasks/create-doc.md +0 -0
  667. /package/{#Tools/APPIQ-METHOD/common → common}/tasks/execute-checklist.md +0 -0
  668. /package/{#Tools/APPIQ-METHOD/common → common}/utils/bmad-doc-template.md +0 -0
  669. /package/{#Tools/APPIQ-METHOD/common → common}/utils/workflow-management.md +0 -0
  670. /package/{#Tools/APPIQ-METHOD/docs → docs}/GUIDING-PRINCIPLES.md +0 -0
  671. /package/{#Tools/APPIQ-METHOD/docs → docs}/core-architecture.md +0 -0
  672. /package/{#Tools/APPIQ-METHOD/docs → docs}/expansion-packs.md +0 -0
  673. /package/{#Tools/APPIQ-METHOD/docs → docs}/how-to-contribute-with-pull-requests.md +0 -0
  674. /package/{#Tools/APPIQ-METHOD/docs → docs}/versioning-and-releases.md +0 -0
  675. /package/{#Tools/APPIQ-METHOD/docs → docs}/versions.md +0 -0
  676. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/README.md +0 -0
  677. /package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/agent-teams/flutter-mobile-team.yaml +0 -0
  678. /package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/agents/flutter-cubit-agent.md +0 -0
  679. /package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/agents/flutter-data-agent.md +0 -0
  680. /package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/agents/flutter-domain-agent.md +0 -0
  681. /package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/agents/flutter-ui-agent.md +0 -0
  682. /package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/agents/shared-components-agent.md +0 -0
  683. /package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/checklists/flutter-story-dod-checklist.md +0 -0
  684. /package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/data/flutter-development-guidelines.md +0 -0
  685. /package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/templates/flutter-mobile-architecture-tmpl.yaml +0 -0
  686. /package/{#Tools/APPIQ-METHOD/expansion-packs/bmad-flutter-mobile-dev → expansion-packs/appiq-flutter-mobile-dev}/workflows/flutter-ui-first-development.yaml +0 -0
  687. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/agent-teams/phaser-2d-nodejs-game-team.yaml +0 -0
  688. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/agents/game-designer.md +0 -0
  689. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/agents/game-developer.md +0 -0
  690. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/agents/game-sm.md +0 -0
  691. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/checklists/game-design-checklist.md +0 -0
  692. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/checklists/game-story-dod-checklist.md +0 -0
  693. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/config.yaml +0 -0
  694. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/data/bmad-kb.md +0 -0
  695. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/data/development-guidelines.md +0 -0
  696. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/tasks/advanced-elicitation.md +0 -0
  697. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/tasks/create-game-story.md +0 -0
  698. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/tasks/game-design-brainstorming.md +0 -0
  699. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +0 -0
  700. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +0 -0
  701. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +0 -0
  702. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +0 -0
  703. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +0 -0
  704. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +0 -0
  705. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +0 -0
  706. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/agent-teams/unity-2d-game-team.yaml +0 -0
  707. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/agents/game-architect.md +0 -0
  708. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/agents/game-designer.md +0 -0
  709. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/agents/game-developer.md +0 -0
  710. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/agents/game-sm.md +0 -0
  711. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/checklists/game-architect-checklist.md +0 -0
  712. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/checklists/game-change-checklist.md +0 -0
  713. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/checklists/game-design-checklist.md +0 -0
  714. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/checklists/game-story-dod-checklist.md +0 -0
  715. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/config.yaml +0 -0
  716. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/data/bmad-kb.md +0 -0
  717. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/data/development-guidelines.md +0 -0
  718. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/tasks/advanced-elicitation.md +0 -0
  719. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/tasks/correct-course-game.md +0 -0
  720. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/tasks/create-game-story.md +0 -0
  721. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/tasks/game-design-brainstorming.md +0 -0
  722. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/tasks/validate-game-story.md +0 -0
  723. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/templates/game-architecture-tmpl.yaml +0 -0
  724. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/templates/game-brief-tmpl.yaml +0 -0
  725. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/templates/game-design-doc-tmpl.yaml +0 -0
  726. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/templates/game-story-tmpl.yaml +0 -0
  727. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/templates/level-design-doc-tmpl.yaml +0 -0
  728. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/workflows/game-dev-greenfield.yaml +0 -0
  729. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-2d-unity-game-dev/workflows/game-prototype.yaml +0 -0
  730. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-infrastructure-devops/README.md +0 -0
  731. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-infrastructure-devops/agents/infra-devops-platform.md +0 -0
  732. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-infrastructure-devops/checklists/infrastructure-checklist.md +0 -0
  733. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-infrastructure-devops/config.yaml +0 -0
  734. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-infrastructure-devops/data/bmad-kb.md +0 -0
  735. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-infrastructure-devops/tasks/review-infrastructure.md +0 -0
  736. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-infrastructure-devops/tasks/validate-infrastructure.md +0 -0
  737. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +0 -0
  738. /package/{#Tools/APPIQ-METHOD/expansion-packs → expansion-packs}/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +0 -0
@@ -1,3295 +0,0 @@
1
- // This is the main code file for the Claude MCP Figma plugin
2
- // It handles Figma API commands
3
-
4
- // Plugin state
5
- const state = {
6
- serverPort: 3055, // Default port
7
- };
8
-
9
- // Helper function for progress updates
10
- function sendProgressUpdate(commandId, commandType, status, progress, totalItems, processedItems, message, payload = null) {
11
- const update = {
12
- type: 'command_progress',
13
- commandId,
14
- commandType,
15
- status,
16
- progress,
17
- totalItems,
18
- processedItems,
19
- message,
20
- timestamp: Date.now()
21
- };
22
-
23
- // Add optional chunk information if present
24
- if (payload) {
25
- if (payload.currentChunk !== undefined && payload.totalChunks !== undefined) {
26
- update.currentChunk = payload.currentChunk;
27
- update.totalChunks = payload.totalChunks;
28
- update.chunkSize = payload.chunkSize;
29
- }
30
- update.payload = payload;
31
- }
32
-
33
- // Send to UI
34
- figma.ui.postMessage(update);
35
- console.log(`Progress update: ${status} - ${progress}% - ${message}`);
36
-
37
- return update;
38
- }
39
-
40
- // Show UI
41
- figma.showUI(__html__, { width: 350, height: 450 });
42
-
43
- // Plugin commands from UI
44
- figma.ui.onmessage = async (msg) => {
45
- switch (msg.type) {
46
- case "update-settings":
47
- updateSettings(msg);
48
- break;
49
- case "notify":
50
- figma.notify(msg.message);
51
- break;
52
- case "close-plugin":
53
- figma.closePlugin();
54
- break;
55
- case "execute-command":
56
- // Execute commands received from UI (which gets them from WebSocket)
57
- try {
58
- const result = await handleCommand(msg.command, msg.params);
59
- // Send result back to UI
60
- figma.ui.postMessage({
61
- type: "command-result",
62
- id: msg.id,
63
- result,
64
- });
65
- } catch (error) {
66
- figma.ui.postMessage({
67
- type: "command-error",
68
- id: msg.id,
69
- error: error.message || "Error executing command",
70
- });
71
- }
72
- break;
73
- }
74
- };
75
-
76
- // Listen for plugin commands from menu
77
- figma.on("run", ({ command }) => {
78
- figma.ui.postMessage({ type: "auto-connect" });
79
- });
80
-
81
- // Update plugin settings
82
- function updateSettings(settings) {
83
- if (settings.serverPort) {
84
- state.serverPort = settings.serverPort;
85
- }
86
-
87
- figma.clientStorage.setAsync("settings", {
88
- serverPort: state.serverPort,
89
- });
90
- }
91
-
92
- // Handle commands from UI
93
- async function handleCommand(command, params) {
94
- switch (command) {
95
- case "get_document_info":
96
- return await getDocumentInfo();
97
- case "get_selection":
98
- return await getSelection();
99
- case "get_node_info":
100
- if (!params || !params.nodeId) {
101
- throw new Error("Missing nodeId parameter");
102
- }
103
- return await getNodeInfo(params.nodeId);
104
- case "get_nodes_info":
105
- if (!params || !params.nodeIds || !Array.isArray(params.nodeIds)) {
106
- throw new Error("Missing or invalid nodeIds parameter");
107
- }
108
- return await getNodesInfo(params.nodeIds);
109
- case "create_rectangle":
110
- return await createRectangle(params);
111
- case "create_frame":
112
- return await createFrame(params);
113
- case "create_text":
114
- return await createText(params);
115
- case "set_fill_color":
116
- return await setFillColor(params);
117
- case "set_stroke_color":
118
- return await setStrokeColor(params);
119
- case "move_node":
120
- return await moveNode(params);
121
- case "resize_node":
122
- return await resizeNode(params);
123
- case "delete_node":
124
- return await deleteNode(params);
125
- case "get_styles":
126
- return await getStyles();
127
- case "get_local_components":
128
- return await getLocalComponents();
129
- // case "get_team_components":
130
- // return await getTeamComponents();
131
- case "create_component_instance":
132
- return await createComponentInstance(params);
133
- case "export_node_as_image":
134
- return await exportNodeAsImage(params);
135
- case "set_corner_radius":
136
- return await setCornerRadius(params);
137
- case "set_text_content":
138
- return await setTextContent(params);
139
- case "clone_node":
140
- return await cloneNode(params);
141
- case "scan_text_nodes":
142
- return await scanTextNodes(params);
143
- case "set_multiple_text_contents":
144
- return await setMultipleTextContents(params);
145
- case "set_auto_layout":
146
- return await setAutoLayout(params);
147
- // Nuevos comandos para propiedades de texto
148
- case "set_font_name":
149
- return await setFontName(params);
150
- case "set_font_size":
151
- return await setFontSize(params);
152
- case "set_font_weight":
153
- return await setFontWeight(params);
154
- case "set_letter_spacing":
155
- return await setLetterSpacing(params);
156
- case "set_line_height":
157
- return await setLineHeight(params);
158
- case "set_paragraph_spacing":
159
- return await setParagraphSpacing(params);
160
- case "set_text_case":
161
- return await setTextCase(params);
162
- case "set_text_decoration":
163
- return await setTextDecoration(params);
164
- case "get_styled_text_segments":
165
- return await getStyledTextSegments(params);
166
- case "load_font_async":
167
- return await loadFontAsyncWrapper(params);
168
- case "get_remote_components":
169
- return await getRemoteComponents(params);
170
- case "set_effects":
171
- return await setEffects(params);
172
- case "set_effect_style_id":
173
- return await setEffectStyleId(params);
174
- case "group_nodes":
175
- return await groupNodes(params);
176
- case "ungroup_nodes":
177
- return await ungroupNodes(params);
178
- case "flatten_node":
179
- return await flattenNode(params);
180
- case "insert_child":
181
- return await insertChild(params);
182
- case "create_ellipse":
183
- return await createEllipse(params);
184
- case "create_polygon":
185
- return await createPolygon(params);
186
- case "create_star":
187
- return await createStar(params);
188
- case "create_vector":
189
- return await createVector(params);
190
- case "create_line":
191
- return await createLine(params);
192
- default:
193
- throw new Error(`Unknown command: ${command}`);
194
- }
195
- }
196
-
197
- // Command implementations
198
-
199
- async function getDocumentInfo() {
200
- await figma.currentPage.loadAsync();
201
- const page = figma.currentPage;
202
- return {
203
- name: page.name,
204
- id: page.id,
205
- type: page.type,
206
- children: page.children.map((node) => ({
207
- id: node.id,
208
- name: node.name,
209
- type: node.type,
210
- })),
211
- currentPage: {
212
- id: page.id,
213
- name: page.name,
214
- childCount: page.children.length,
215
- },
216
- pages: [
217
- {
218
- id: page.id,
219
- name: page.name,
220
- childCount: page.children.length,
221
- },
222
- ],
223
- };
224
- }
225
-
226
- async function getSelection() {
227
- return {
228
- selectionCount: figma.currentPage.selection.length,
229
- selection: figma.currentPage.selection.map((node) => ({
230
- id: node.id,
231
- name: node.name,
232
- type: node.type,
233
- visible: node.visible,
234
- })),
235
- };
236
- }
237
-
238
- async function getNodeInfo(nodeId) {
239
- const node = await figma.getNodeByIdAsync(nodeId);
240
-
241
- if (!node) {
242
- throw new Error(`Node not found with ID: ${nodeId}`);
243
- }
244
-
245
- const response = await node.exportAsync({
246
- format: "JSON_REST_V1",
247
- });
248
-
249
- return response.document;
250
- }
251
-
252
- async function getNodesInfo(nodeIds) {
253
- try {
254
- // Load all nodes in parallel
255
- const nodes = await Promise.all(
256
- nodeIds.map((id) => figma.getNodeByIdAsync(id))
257
- );
258
-
259
- // Filter out any null values (nodes that weren't found)
260
- const validNodes = nodes.filter((node) => node !== null);
261
-
262
- // Export all valid nodes in parallel
263
- const responses = await Promise.all(
264
- validNodes.map(async (node) => {
265
- const response = await node.exportAsync({
266
- format: "JSON_REST_V1",
267
- });
268
- return {
269
- nodeId: node.id,
270
- document: response.document,
271
- };
272
- })
273
- );
274
-
275
- return responses;
276
- } catch (error) {
277
- throw new Error(`Error getting nodes info: ${error.message}`);
278
- }
279
- }
280
-
281
- async function createRectangle(params) {
282
- const {
283
- x = 0,
284
- y = 0,
285
- width = 100,
286
- height = 100,
287
- name = "Rectangle",
288
- parentId,
289
- } = params || {};
290
-
291
- const rect = figma.createRectangle();
292
- rect.x = x;
293
- rect.y = y;
294
- rect.resize(width, height);
295
- rect.name = name;
296
-
297
- // If parentId is provided, append to that node, otherwise append to current page
298
- if (parentId) {
299
- const parentNode = await figma.getNodeByIdAsync(parentId);
300
- if (!parentNode) {
301
- throw new Error(`Parent node not found with ID: ${parentId}`);
302
- }
303
- if (!("appendChild" in parentNode)) {
304
- throw new Error(`Parent node does not support children: ${parentId}`);
305
- }
306
- parentNode.appendChild(rect);
307
- } else {
308
- figma.currentPage.appendChild(rect);
309
- }
310
-
311
- return {
312
- id: rect.id,
313
- name: rect.name,
314
- x: rect.x,
315
- y: rect.y,
316
- width: rect.width,
317
- height: rect.height,
318
- parentId: rect.parent ? rect.parent.id : undefined,
319
- };
320
- }
321
-
322
- async function createFrame(params) {
323
- const {
324
- x = 0,
325
- y = 0,
326
- width = 100,
327
- height = 100,
328
- name = "Frame",
329
- parentId,
330
- fillColor,
331
- strokeColor,
332
- strokeWeight,
333
- } = params || {};
334
-
335
- const frame = figma.createFrame();
336
- frame.x = x;
337
- frame.y = y;
338
- frame.resize(width, height);
339
- frame.name = name;
340
-
341
- // Set fill color if provided
342
- if (fillColor) {
343
- const paintStyle = {
344
- type: "SOLID",
345
- color: {
346
- r: parseFloat(fillColor.r) || 0,
347
- g: parseFloat(fillColor.g) || 0,
348
- b: parseFloat(fillColor.b) || 0,
349
- },
350
- opacity: parseFloat(fillColor.a) || 1,
351
- };
352
- frame.fills = [paintStyle];
353
- }
354
-
355
- // Set stroke color and weight if provided
356
- if (strokeColor) {
357
- const strokeStyle = {
358
- type: "SOLID",
359
- color: {
360
- r: parseFloat(strokeColor.r) || 0,
361
- g: parseFloat(strokeColor.g) || 0,
362
- b: parseFloat(strokeColor.b) || 0,
363
- },
364
- opacity: parseFloat(strokeColor.a) || 1,
365
- };
366
- frame.strokes = [strokeStyle];
367
- }
368
-
369
- // Set stroke weight if provided
370
- if (strokeWeight !== undefined) {
371
- frame.strokeWeight = strokeWeight;
372
- }
373
-
374
- // If parentId is provided, append to that node, otherwise append to current page
375
- if (parentId) {
376
- const parentNode = await figma.getNodeByIdAsync(parentId);
377
- if (!parentNode) {
378
- throw new Error(`Parent node not found with ID: ${parentId}`);
379
- }
380
- if (!("appendChild" in parentNode)) {
381
- throw new Error(`Parent node does not support children: ${parentId}`);
382
- }
383
- parentNode.appendChild(frame);
384
- } else {
385
- figma.currentPage.appendChild(frame);
386
- }
387
-
388
- return {
389
- id: frame.id,
390
- name: frame.name,
391
- x: frame.x,
392
- y: frame.y,
393
- width: frame.width,
394
- height: frame.height,
395
- fills: frame.fills,
396
- strokes: frame.strokes,
397
- strokeWeight: frame.strokeWeight,
398
- parentId: frame.parent ? frame.parent.id : undefined,
399
- };
400
- }
401
-
402
- async function createText(params) {
403
- const {
404
- x = 0,
405
- y = 0,
406
- text = "Text",
407
- fontSize = 14,
408
- fontWeight = 400,
409
- fontColor = { r: 0, g: 0, b: 0, a: 1 }, // Default to black
410
- name = "Text",
411
- parentId,
412
- } = params || {};
413
-
414
- // Map common font weights to Figma font styles
415
- const getFontStyle = (weight) => {
416
- switch (weight) {
417
- case 100:
418
- return "Thin";
419
- case 200:
420
- return "Extra Light";
421
- case 300:
422
- return "Light";
423
- case 400:
424
- return "Regular";
425
- case 500:
426
- return "Medium";
427
- case 600:
428
- return "Semi Bold";
429
- case 700:
430
- return "Bold";
431
- case 800:
432
- return "Extra Bold";
433
- case 900:
434
- return "Black";
435
- default:
436
- return "Regular";
437
- }
438
- };
439
-
440
- const textNode = figma.createText();
441
- textNode.x = x;
442
- textNode.y = y;
443
- textNode.name = name;
444
- try {
445
- await figma.loadFontAsync({
446
- family: "Inter",
447
- style: getFontStyle(fontWeight),
448
- });
449
- textNode.fontName = { family: "Inter", style: getFontStyle(fontWeight) };
450
- textNode.fontSize = parseInt(fontSize);
451
- } catch (error) {
452
- console.error("Error setting font size", error);
453
- }
454
- setCharacters(textNode, text);
455
-
456
- // Set text color
457
- const paintStyle = {
458
- type: "SOLID",
459
- color: {
460
- r: parseFloat(fontColor.r) || 0,
461
- g: parseFloat(fontColor.g) || 0,
462
- b: parseFloat(fontColor.b) || 0,
463
- },
464
- opacity: parseFloat(fontColor.a) || 1,
465
- };
466
- textNode.fills = [paintStyle];
467
-
468
- // If parentId is provided, append to that node, otherwise append to current page
469
- if (parentId) {
470
- const parentNode = await figma.getNodeByIdAsync(parentId);
471
- if (!parentNode) {
472
- throw new Error(`Parent node not found with ID: ${parentId}`);
473
- }
474
- if (!("appendChild" in parentNode)) {
475
- throw new Error(`Parent node does not support children: ${parentId}`);
476
- }
477
- parentNode.appendChild(textNode);
478
- } else {
479
- figma.currentPage.appendChild(textNode);
480
- }
481
-
482
- return {
483
- id: textNode.id,
484
- name: textNode.name,
485
- x: textNode.x,
486
- y: textNode.y,
487
- width: textNode.width,
488
- height: textNode.height,
489
- characters: textNode.characters,
490
- fontSize: textNode.fontSize,
491
- fontWeight: fontWeight,
492
- fontColor: fontColor,
493
- fontName: textNode.fontName,
494
- fills: textNode.fills,
495
- parentId: textNode.parent ? textNode.parent.id : undefined,
496
- };
497
- }
498
-
499
- async function setFillColor(params) {
500
- console.log("setFillColor", params);
501
- const {
502
- nodeId,
503
- color: { r, g, b, a },
504
- } = params || {};
505
-
506
- if (!nodeId) {
507
- throw new Error("Missing nodeId parameter");
508
- }
509
-
510
- const node = await figma.getNodeByIdAsync(nodeId);
511
- if (!node) {
512
- throw new Error(`Node not found with ID: ${nodeId}`);
513
- }
514
-
515
- if (!("fills" in node)) {
516
- throw new Error(`Node does not support fills: ${nodeId}`);
517
- }
518
-
519
- // Validate that MCP layer provided complete data
520
- if (r === undefined || g === undefined || b === undefined || a === undefined) {
521
- throw new Error("Incomplete color data received from MCP layer. All RGBA components must be provided.");
522
- }
523
-
524
- // Parse values - no defaults, just format conversion
525
- const rgbColor = {
526
- r: parseFloat(r),
527
- g: parseFloat(g),
528
- b: parseFloat(b),
529
- a: parseFloat(a)
530
- };
531
-
532
- // Validate parsing succeeded
533
- if (isNaN(rgbColor.r) || isNaN(rgbColor.g) || isNaN(rgbColor.b) || isNaN(rgbColor.a)) {
534
- throw new Error("Invalid color values received - all components must be valid numbers");
535
- }
536
-
537
- // Set fill - pure translation to Figma API format
538
- const paintStyle = {
539
- type: "SOLID",
540
- color: {
541
- r: rgbColor.r,
542
- g: rgbColor.g,
543
- b: rgbColor.b,
544
- },
545
- opacity: rgbColor.a,
546
- };
547
-
548
- console.log("paintStyle", paintStyle);
549
-
550
- node.fills = [paintStyle];
551
-
552
- return {
553
- id: node.id,
554
- name: node.name,
555
- fills: [paintStyle],
556
- };
557
- }
558
-
559
- async function setStrokeColor(params) {
560
- const {
561
- nodeId,
562
- color: { r, g, b, a },
563
- strokeWeight,
564
- } = params || {};
565
-
566
- if (!nodeId) {
567
- throw new Error("Missing nodeId parameter");
568
- }
569
-
570
- const node = await figma.getNodeByIdAsync(nodeId);
571
- if (!node) {
572
- throw new Error(`Node not found with ID: ${nodeId}`);
573
- }
574
-
575
- if (!("strokes" in node)) {
576
- throw new Error(`Node does not support strokes: ${nodeId}`);
577
- }
578
-
579
- if (r === undefined || g === undefined || b === undefined || a === undefined) {
580
- throw new Error("Incomplete color data received from MCP layer. All RGBA components must be provided.");
581
- }
582
-
583
- if (strokeWeight === undefined) {
584
- throw new Error("Stroke weight must be provided by MCP layer.");
585
- }
586
-
587
- const rgbColor = {
588
- r: parseFloat(r),
589
- g: parseFloat(g),
590
- b: parseFloat(b),
591
- a: parseFloat(a)
592
- };
593
- const strokeWeightParsed = parseFloat(strokeWeight);
594
-
595
- if (isNaN(rgbColor.r) || isNaN(rgbColor.g) || isNaN(rgbColor.b) || isNaN(rgbColor.a)) {
596
- throw new Error("Invalid color values received - all components must be valid numbers");
597
- }
598
-
599
- if (isNaN(strokeWeightParsed)) {
600
- throw new Error("Invalid stroke weight - must be a valid number");
601
- }
602
-
603
- const paintStyle = {
604
- type: "SOLID",
605
- color: {
606
- r: rgbColor.r,
607
- g: rgbColor.g,
608
- b: rgbColor.b,
609
- },
610
- opacity: rgbColor.a,
611
- };
612
-
613
- node.strokes = [paintStyle];
614
-
615
- // Set stroke weight if available
616
- if ("strokeWeight" in node) {
617
- node.strokeWeight = strokeWeightParsed;
618
- }
619
-
620
- return {
621
- id: node.id,
622
- name: node.name,
623
- strokes: node.strokes,
624
- strokeWeight: "strokeWeight" in node ? node.strokeWeight : undefined,
625
- };
626
- }
627
-
628
- async function moveNode(params) {
629
- const { nodeId, x, y } = params || {};
630
-
631
- if (!nodeId) {
632
- throw new Error("Missing nodeId parameter");
633
- }
634
-
635
- if (x === undefined || y === undefined) {
636
- throw new Error("Missing x or y parameters");
637
- }
638
-
639
- const node = await figma.getNodeByIdAsync(nodeId);
640
- if (!node) {
641
- throw new Error(`Node not found with ID: ${nodeId}`);
642
- }
643
-
644
- if (!("x" in node) || !("y" in node)) {
645
- throw new Error(`Node does not support position: ${nodeId}`);
646
- }
647
-
648
- node.x = x;
649
- node.y = y;
650
-
651
- return {
652
- id: node.id,
653
- name: node.name,
654
- x: node.x,
655
- y: node.y,
656
- };
657
- }
658
-
659
- async function resizeNode(params) {
660
- const { nodeId, width, height } = params || {};
661
-
662
- if (!nodeId) {
663
- throw new Error("Missing nodeId parameter");
664
- }
665
-
666
- if (width === undefined || height === undefined) {
667
- throw new Error("Missing width or height parameters");
668
- }
669
-
670
- const node = await figma.getNodeByIdAsync(nodeId);
671
- if (!node) {
672
- throw new Error(`Node not found with ID: ${nodeId}`);
673
- }
674
-
675
- if (!("resize" in node)) {
676
- throw new Error(`Node does not support resizing: ${nodeId}`);
677
- }
678
-
679
- node.resize(width, height);
680
-
681
- return {
682
- id: node.id,
683
- name: node.name,
684
- width: node.width,
685
- height: node.height,
686
- };
687
- }
688
-
689
- async function deleteNode(params) {
690
- const { nodeId } = params || {};
691
-
692
- if (!nodeId) {
693
- throw new Error("Missing nodeId parameter");
694
- }
695
-
696
- const node = await figma.getNodeByIdAsync(nodeId);
697
- if (!node) {
698
- throw new Error(`Node not found with ID: ${nodeId}`);
699
- }
700
-
701
- // Save node info before deleting
702
- const nodeInfo = {
703
- id: node.id,
704
- name: node.name,
705
- type: node.type,
706
- };
707
-
708
- node.remove();
709
-
710
- return nodeInfo;
711
- }
712
-
713
- async function getStyles() {
714
- const styles = {
715
- colors: await figma.getLocalPaintStylesAsync(),
716
- texts: await figma.getLocalTextStylesAsync(),
717
- effects: await figma.getLocalEffectStylesAsync(),
718
- grids: await figma.getLocalGridStylesAsync(),
719
- };
720
-
721
- return {
722
- colors: styles.colors.map((style) => ({
723
- id: style.id,
724
- name: style.name,
725
- key: style.key,
726
- paint: style.paints[0],
727
- })),
728
- texts: styles.texts.map((style) => ({
729
- id: style.id,
730
- name: style.name,
731
- key: style.key,
732
- fontSize: style.fontSize,
733
- fontName: style.fontName,
734
- })),
735
- effects: styles.effects.map((style) => ({
736
- id: style.id,
737
- name: style.name,
738
- key: style.key,
739
- })),
740
- grids: styles.grids.map((style) => ({
741
- id: style.id,
742
- name: style.name,
743
- key: style.key,
744
- })),
745
- };
746
- }
747
-
748
- async function getLocalComponents() {
749
- await figma.loadAllPagesAsync();
750
-
751
- const components = figma.root.findAllWithCriteria({
752
- types: ["COMPONENT"],
753
- });
754
-
755
- return {
756
- count: components.length,
757
- components: components.map((component) => ({
758
- id: component.id,
759
- name: component.name,
760
- key: "key" in component ? component.key : null,
761
- })),
762
- };
763
- }
764
-
765
- // async function getTeamComponents() {
766
- // try {
767
- // const teamComponents =
768
- // await figma.teamLibrary.getAvailableComponentsAsync();
769
-
770
- // return {
771
- // count: teamComponents.length,
772
- // components: teamComponents.map((component) => ({
773
- // key: component.key,
774
- // name: component.name,
775
- // description: component.description,
776
- // libraryName: component.libraryName,
777
- // })),
778
- // };
779
- // } catch (error) {
780
- // throw new Error(`Error getting team components: ${error.message}`);
781
- // }
782
- // }
783
-
784
- async function createComponentInstance(params) {
785
- const { componentKey, x = 0, y = 0 } = params || {};
786
-
787
- if (!componentKey) {
788
- throw new Error("Missing componentKey parameter");
789
- }
790
-
791
- try {
792
- // Set up a manual timeout to detect long operations
793
- let timeoutId;
794
- const timeoutPromise = new Promise((_, reject) => {
795
- timeoutId = setTimeout(() => {
796
- reject(new Error("Timeout while creating component instance (10s). The component may be too complex or unavailable."));
797
- }, 10000); // 10 seconds timeout
798
- });
799
-
800
- console.log(`Starting component import for key: ${componentKey}...`);
801
-
802
- // Execute the import with a timeout
803
- const importPromise = figma.importComponentByKeyAsync(componentKey);
804
-
805
- // Use Promise.race to implement the timeout
806
- const component = await Promise.race([importPromise, timeoutPromise])
807
- .finally(() => {
808
- clearTimeout(timeoutId); // Clear the timeout to prevent memory leaks
809
- });
810
-
811
- // Add progress logging
812
- console.log(`Component imported successfully, creating instance...`);
813
-
814
- // Create instance and set properties in a separate try block to handle errors specifically from this step
815
- try {
816
- const instance = component.createInstance();
817
- instance.x = x;
818
- instance.y = y;
819
-
820
- figma.currentPage.appendChild(instance);
821
-
822
- console.log(`Component instance created and added to page successfully`);
823
-
824
- return {
825
- id: instance.id,
826
- name: instance.name,
827
- x: instance.x,
828
- y: instance.y,
829
- width: instance.width,
830
- height: instance.height,
831
- componentId: instance.componentId,
832
- };
833
- } catch (instanceError) {
834
- console.error(`Error creating component instance: ${instanceError.message}`);
835
- throw new Error(`Error creating component instance: ${instanceError.message}`);
836
- }
837
- } catch (error) {
838
- console.error(`Detailed error creating component instance: ${error.message || "Unknown error"}`);
839
- console.error(`Stack trace: ${error.stack || "Not available"}`);
840
-
841
- // Provide more helpful error messages for common failure scenarios
842
- if (error.message.includes("timeout") || error.message.includes("Timeout")) {
843
- throw new Error(`The component import timed out after 10 seconds. This usually happens with complex remote components or network issues. Try again later or use a simpler component.`);
844
- } else if (error.message.includes("not found") || error.message.includes("Not found")) {
845
- throw new Error(`Component with key "${componentKey}" not found. Make sure the component exists and is accessible in your document or team libraries.`);
846
- } else if (error.message.includes("permission") || error.message.includes("Permission")) {
847
- throw new Error(`You don't have permission to use this component. Make sure you have access to the team library containing this component.`);
848
- } else {
849
- throw new Error(`Error creating component instance: ${error.message}`);
850
- }
851
- }
852
- }
853
-
854
- async function exportNodeAsImage(params) {
855
- const { nodeId, scale = 1 } = params || {};
856
-
857
- const format = "PNG";
858
-
859
- if (!nodeId) {
860
- throw new Error("Missing nodeId parameter");
861
- }
862
-
863
- const node = await figma.getNodeByIdAsync(nodeId);
864
- if (!node) {
865
- throw new Error(`Node not found with ID: ${nodeId}`);
866
- }
867
-
868
- if (!("exportAsync" in node)) {
869
- throw new Error(`Node does not support exporting: ${nodeId}`);
870
- }
871
-
872
- try {
873
- const settings = {
874
- format: format,
875
- constraint: { type: "SCALE", value: scale },
876
- };
877
-
878
- const bytes = await node.exportAsync(settings);
879
-
880
- let mimeType;
881
- switch (format) {
882
- case "PNG":
883
- mimeType = "image/png";
884
- break;
885
- case "JPG":
886
- mimeType = "image/jpeg";
887
- break;
888
- case "SVG":
889
- mimeType = "image/svg+xml";
890
- break;
891
- case "PDF":
892
- mimeType = "application/pdf";
893
- break;
894
- default:
895
- mimeType = "application/octet-stream";
896
- }
897
-
898
- // Proper way to convert Uint8Array to base64
899
- const base64 = customBase64Encode(bytes);
900
- // const imageData = `data:${mimeType};base64,${base64}`;
901
-
902
- return {
903
- nodeId,
904
- format,
905
- scale,
906
- mimeType,
907
- imageData: base64,
908
- };
909
- } catch (error) {
910
- throw new Error(`Error exporting node as image: ${error.message}`);
911
- }
912
- }
913
- function customBase64Encode(bytes) {
914
- const chars =
915
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
916
- let base64 = "";
917
-
918
- const byteLength = bytes.byteLength;
919
- const byteRemainder = byteLength % 3;
920
- const mainLength = byteLength - byteRemainder;
921
-
922
- let a, b, c, d;
923
- let chunk;
924
-
925
- // Main loop deals with bytes in chunks of 3
926
- for (let i = 0; i < mainLength; i = i + 3) {
927
- // Combine the three bytes into a single integer
928
- chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
929
-
930
- // Use bitmasks to extract 6-bit segments from the triplet
931
- a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
932
- b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12
933
- c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6
934
- d = chunk & 63; // 63 = 2^6 - 1
935
-
936
- // Convert the raw binary segments to the appropriate ASCII encoding
937
- base64 += chars[a] + chars[b] + chars[c] + chars[d];
938
- }
939
-
940
- // Deal with the remaining bytes and padding
941
- if (byteRemainder === 1) {
942
- chunk = bytes[mainLength];
943
-
944
- a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
945
-
946
- // Set the 4 least significant bits to zero
947
- b = (chunk & 3) << 4; // 3 = 2^2 - 1
948
-
949
- base64 += chars[a] + chars[b] + "==";
950
- } else if (byteRemainder === 2) {
951
- chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];
952
-
953
- a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
954
- b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4
955
-
956
- // Set the 2 least significant bits to zero
957
- c = (chunk & 15) << 2; // 15 = 2^4 - 1
958
-
959
- base64 += chars[a] + chars[b] + chars[c] + "=";
960
- }
961
-
962
- return base64;
963
- }
964
-
965
- async function setCornerRadius(params) {
966
- const { nodeId, radius, corners } = params || {};
967
-
968
- if (!nodeId) {
969
- throw new Error("Missing nodeId parameter");
970
- }
971
-
972
- if (radius === undefined) {
973
- throw new Error("Missing radius parameter");
974
- }
975
-
976
- const node = await figma.getNodeByIdAsync(nodeId);
977
- if (!node) {
978
- throw new Error(`Node not found with ID: ${nodeId}`);
979
- }
980
-
981
- // Check if node supports corner radius
982
- if (!("cornerRadius" in node)) {
983
- throw new Error(`Node does not support corner radius: ${nodeId}`);
984
- }
985
-
986
- // If corners array is provided, set individual corner radii
987
- if (corners && Array.isArray(corners) && corners.length === 4) {
988
- if ("topLeftRadius" in node) {
989
- // Node supports individual corner radii
990
- if (corners[0]) node.topLeftRadius = radius;
991
- if (corners[1]) node.topRightRadius = radius;
992
- if (corners[2]) node.bottomRightRadius = radius;
993
- if (corners[3]) node.bottomLeftRadius = radius;
994
- } else {
995
- // Node only supports uniform corner radius
996
- node.cornerRadius = radius;
997
- }
998
- } else {
999
- // Set uniform corner radius
1000
- node.cornerRadius = radius;
1001
- }
1002
-
1003
- return {
1004
- id: node.id,
1005
- name: node.name,
1006
- cornerRadius: "cornerRadius" in node ? node.cornerRadius : undefined,
1007
- topLeftRadius: "topLeftRadius" in node ? node.topLeftRadius : undefined,
1008
- topRightRadius: "topRightRadius" in node ? node.topRightRadius : undefined,
1009
- bottomRightRadius:
1010
- "bottomRightRadius" in node ? node.bottomRightRadius : undefined,
1011
- bottomLeftRadius:
1012
- "bottomLeftRadius" in node ? node.bottomLeftRadius : undefined,
1013
- };
1014
- }
1015
-
1016
- async function setTextContent(params) {
1017
- const { nodeId, text } = params || {};
1018
-
1019
- if (!nodeId) {
1020
- throw new Error("Missing nodeId parameter");
1021
- }
1022
-
1023
- if (text === undefined) {
1024
- throw new Error("Missing text parameter");
1025
- }
1026
-
1027
- const node = await figma.getNodeByIdAsync(nodeId);
1028
- if (!node) {
1029
- throw new Error(`Node not found with ID: ${nodeId}`);
1030
- }
1031
-
1032
- if (node.type !== "TEXT") {
1033
- throw new Error(`Node is not a text node: ${nodeId}`);
1034
- }
1035
-
1036
- try {
1037
- await figma.loadFontAsync(node.fontName);
1038
-
1039
- await setCharacters(node, text);
1040
-
1041
- return {
1042
- id: node.id,
1043
- name: node.name,
1044
- characters: node.characters,
1045
- fontName: node.fontName,
1046
- };
1047
- } catch (error) {
1048
- throw new Error(`Error setting text content: ${error.message}`);
1049
- }
1050
- }
1051
-
1052
- // Initialize settings on load
1053
- (async function initializePlugin() {
1054
- try {
1055
- const savedSettings = await figma.clientStorage.getAsync("settings");
1056
- if (savedSettings) {
1057
- if (savedSettings.serverPort) {
1058
- state.serverPort = savedSettings.serverPort;
1059
- }
1060
- }
1061
-
1062
- // Send initial settings to UI
1063
- figma.ui.postMessage({
1064
- type: "init-settings",
1065
- settings: {
1066
- serverPort: state.serverPort,
1067
- },
1068
- });
1069
- } catch (error) {
1070
- console.error("Error loading settings:", error);
1071
- }
1072
- })();
1073
-
1074
- function uniqBy(arr, predicate) {
1075
- const cb = typeof predicate === "function" ? predicate : (o) => o[predicate];
1076
- return [
1077
- ...arr
1078
- .reduce((map, item) => {
1079
- const key = item === null || item === undefined ? item : cb(item);
1080
-
1081
- map.has(key) || map.set(key, item);
1082
-
1083
- return map;
1084
- }, new Map())
1085
- .values(),
1086
- ];
1087
- }
1088
- const setCharacters = async (node, characters, options) => {
1089
- const fallbackFont = (options && options.fallbackFont) || {
1090
- family: "Inter",
1091
- style: "Regular",
1092
- };
1093
- try {
1094
- if (node.fontName === figma.mixed) {
1095
- if (options && options.smartStrategy === "prevail") {
1096
- const fontHashTree = {};
1097
- for (let i = 1; i < node.characters.length; i++) {
1098
- const charFont = node.getRangeFontName(i - 1, i);
1099
- const key = `${charFont.family}::${charFont.style}`;
1100
- fontHashTree[key] = fontHashTree[key] ? fontHashTree[key] + 1 : 1;
1101
- }
1102
- const prevailedTreeItem = Object.entries(fontHashTree).sort(
1103
- (a, b) => b[1] - a[1]
1104
- )[0];
1105
- const [family, style] = prevailedTreeItem[0].split("::");
1106
- const prevailedFont = {
1107
- family,
1108
- style,
1109
- };
1110
- await figma.loadFontAsync(prevailedFont);
1111
- node.fontName = prevailedFont;
1112
- } else if (options && options.smartStrategy === "strict") {
1113
- return setCharactersWithStrictMatchFont(node, characters, fallbackFont);
1114
- } else if (options && options.smartStrategy === "experimental") {
1115
- return setCharactersWithSmartMatchFont(node, characters, fallbackFont);
1116
- } else {
1117
- const firstCharFont = node.getRangeFontName(0, 1);
1118
- await figma.loadFontAsync(firstCharFont);
1119
- node.fontName = firstCharFont;
1120
- }
1121
- } else {
1122
- await figma.loadFontAsync({
1123
- family: node.fontName.family,
1124
- style: node.fontName.style,
1125
- });
1126
- }
1127
- } catch (err) {
1128
- console.warn(
1129
- `Failed to load "${node.fontName["family"]} ${node.fontName["style"]}" font and replaced with fallback "${fallbackFont.family} ${fallbackFont.style}"`,
1130
- err
1131
- );
1132
- await figma.loadFontAsync(fallbackFont);
1133
- node.fontName = fallbackFont;
1134
- }
1135
- try {
1136
- node.characters = characters;
1137
- return true;
1138
- } catch (err) {
1139
- console.warn(`Failed to set characters. Skipped.`, err);
1140
- return false;
1141
- }
1142
- };
1143
-
1144
- const setCharactersWithStrictMatchFont = async (
1145
- node,
1146
- characters,
1147
- fallbackFont
1148
- ) => {
1149
- const fontHashTree = {};
1150
- for (let i = 1; i < node.characters.length; i++) {
1151
- const startIdx = i - 1;
1152
- const startCharFont = node.getRangeFontName(startIdx, i);
1153
- const startCharFontVal = `${startCharFont.family}::${startCharFont.style}`;
1154
- while (i < node.characters.length) {
1155
- i++;
1156
- const charFont = node.getRangeFontName(i - 1, i);
1157
- if (startCharFontVal !== `${charFont.family}::${charFont.style}`) {
1158
- break;
1159
- }
1160
- }
1161
- fontHashTree[`${startIdx}_${i}`] = startCharFontVal;
1162
- }
1163
- await figma.loadFontAsync(fallbackFont);
1164
- node.fontName = fallbackFont;
1165
- node.characters = characters;
1166
- console.log(fontHashTree);
1167
- await Promise.all(
1168
- Object.keys(fontHashTree).map(async (range) => {
1169
- console.log(range, fontHashTree[range]);
1170
- const [start, end] = range.split("_");
1171
- const [family, style] = fontHashTree[range].split("::");
1172
- const matchedFont = {
1173
- family,
1174
- style,
1175
- };
1176
- await figma.loadFontAsync(matchedFont);
1177
- return node.setRangeFontName(Number(start), Number(end), matchedFont);
1178
- })
1179
- );
1180
- return true;
1181
- };
1182
-
1183
- const getDelimiterPos = (str, delimiter, startIdx = 0, endIdx = str.length) => {
1184
- const indices = [];
1185
- let temp = startIdx;
1186
- for (let i = startIdx; i < endIdx; i++) {
1187
- if (
1188
- str[i] === delimiter &&
1189
- i + startIdx !== endIdx &&
1190
- temp !== i + startIdx
1191
- ) {
1192
- indices.push([temp, i + startIdx]);
1193
- temp = i + startIdx + 1;
1194
- }
1195
- }
1196
- temp !== endIdx && indices.push([temp, endIdx]);
1197
- return indices.filter(Boolean);
1198
- };
1199
-
1200
- const buildLinearOrder = (node) => {
1201
- const fontTree = [];
1202
- const newLinesPos = getDelimiterPos(node.characters, "\n");
1203
- newLinesPos.forEach(([newLinesRangeStart, newLinesRangeEnd], n) => {
1204
- const newLinesRangeFont = node.getRangeFontName(
1205
- newLinesRangeStart,
1206
- newLinesRangeEnd
1207
- );
1208
- if (newLinesRangeFont === figma.mixed) {
1209
- const spacesPos = getDelimiterPos(
1210
- node.characters,
1211
- " ",
1212
- newLinesRangeStart,
1213
- newLinesRangeEnd
1214
- );
1215
- spacesPos.forEach(([spacesRangeStart, spacesRangeEnd], s) => {
1216
- const spacesRangeFont = node.getRangeFontName(
1217
- spacesRangeStart,
1218
- spacesRangeEnd
1219
- );
1220
- if (spacesRangeFont === figma.mixed) {
1221
- const spacesRangeFont = node.getRangeFontName(
1222
- spacesRangeStart,
1223
- spacesRangeStart[0]
1224
- );
1225
- fontTree.push({
1226
- start: spacesRangeStart,
1227
- delimiter: " ",
1228
- family: spacesRangeFont.family,
1229
- style: spacesRangeFont.style,
1230
- });
1231
- } else {
1232
- fontTree.push({
1233
- start: spacesRangeStart,
1234
- delimiter: " ",
1235
- family: spacesRangeFont.family,
1236
- style: spacesRangeFont.style,
1237
- });
1238
- }
1239
- });
1240
- } else {
1241
- fontTree.push({
1242
- start: newLinesRangeStart,
1243
- delimiter: "\n",
1244
- family: newLinesRangeFont.family,
1245
- style: newLinesRangeFont.style,
1246
- });
1247
- }
1248
- });
1249
- return fontTree
1250
- .sort((a, b) => +a.start - +b.start)
1251
- .map(({ family, style, delimiter }) => ({ family, style, delimiter }));
1252
- };
1253
-
1254
- const setCharactersWithSmartMatchFont = async (
1255
- node,
1256
- characters,
1257
- fallbackFont
1258
- ) => {
1259
- const rangeTree = buildLinearOrder(node);
1260
- const fontsToLoad = uniqBy(
1261
- rangeTree,
1262
- ({ family, style }) => `${family}::${style}`
1263
- ).map(({ family, style }) => ({
1264
- family,
1265
- style,
1266
- }));
1267
-
1268
- await Promise.all([...fontsToLoad, fallbackFont].map(figma.loadFontAsync));
1269
-
1270
- node.fontName = fallbackFont;
1271
- node.characters = characters;
1272
-
1273
- let prevPos = 0;
1274
- rangeTree.forEach(({ family, style, delimiter }) => {
1275
- if (prevPos < node.characters.length) {
1276
- const delimeterPos = node.characters.indexOf(delimiter, prevPos);
1277
- const endPos =
1278
- delimeterPos > prevPos ? delimeterPos : node.characters.length;
1279
- const matchedFont = {
1280
- family,
1281
- style,
1282
- };
1283
- node.setRangeFontName(prevPos, endPos, matchedFont);
1284
- prevPos = endPos + 1;
1285
- }
1286
- });
1287
- return true;
1288
- };
1289
-
1290
- // Add the cloneNode function implementation
1291
- async function cloneNode(params) {
1292
- const { nodeId, x, y } = params || {};
1293
-
1294
- if (!nodeId) {
1295
- throw new Error("Missing nodeId parameter");
1296
- }
1297
-
1298
- const node = await figma.getNodeByIdAsync(nodeId);
1299
- if (!node) {
1300
- throw new Error(`Node not found with ID: ${nodeId}`);
1301
- }
1302
-
1303
- // Clone the node
1304
- const clone = node.clone();
1305
-
1306
- // If x and y are provided, move the clone to that position
1307
- if (x !== undefined && y !== undefined) {
1308
- if (!("x" in clone) || !("y" in clone)) {
1309
- throw new Error(`Cloned node does not support position: ${nodeId}`);
1310
- }
1311
- clone.x = x;
1312
- clone.y = y;
1313
- }
1314
-
1315
- // Add the clone to the same parent as the original node
1316
- if (node.parent) {
1317
- node.parent.appendChild(clone);
1318
- } else {
1319
- figma.currentPage.appendChild(clone);
1320
- }
1321
-
1322
- return {
1323
- id: clone.id,
1324
- name: clone.name,
1325
- x: "x" in clone ? clone.x : undefined,
1326
- y: "y" in clone ? clone.y : undefined,
1327
- width: "width" in clone ? clone.width : undefined,
1328
- height: "height" in clone ? clone.height : undefined,
1329
- };
1330
- }
1331
-
1332
- async function scanTextNodes(params) {
1333
- console.log(`Starting to scan text nodes from node ID: ${params.nodeId}`);
1334
- const { nodeId, useChunking = true, chunkSize = 10, commandId = generateCommandId() } = params || {};
1335
-
1336
- const node = await figma.getNodeByIdAsync(nodeId);
1337
-
1338
- if (!node) {
1339
- console.error(`Node with ID ${nodeId} not found`);
1340
- // Send error progress update
1341
- sendProgressUpdate(
1342
- commandId,
1343
- 'scan_text_nodes',
1344
- 'error',
1345
- 0,
1346
- 0,
1347
- 0,
1348
- `Node with ID ${nodeId} not found`,
1349
- { error: `Node not found: ${nodeId}` }
1350
- );
1351
- throw new Error(`Node with ID ${nodeId} not found`);
1352
- }
1353
-
1354
- // If chunking is not enabled, use the original implementation
1355
- if (!useChunking) {
1356
- const textNodes = [];
1357
- try {
1358
- // Send started progress update
1359
- sendProgressUpdate(
1360
- commandId,
1361
- 'scan_text_nodes',
1362
- 'started',
1363
- 0,
1364
- 1, // Not known yet how many nodes there are
1365
- 0,
1366
- `Starting scan of node "${node.name || nodeId}" without chunking`,
1367
- null
1368
- );
1369
-
1370
- await findTextNodes(node, [], 0, textNodes);
1371
-
1372
- // Send completed progress update
1373
- sendProgressUpdate(
1374
- commandId,
1375
- 'scan_text_nodes',
1376
- 'completed',
1377
- 100,
1378
- textNodes.length,
1379
- textNodes.length,
1380
- `Scan complete. Found ${textNodes.length} text nodes.`,
1381
- { textNodes }
1382
- );
1383
-
1384
- return {
1385
- success: true,
1386
- message: `Scanned ${textNodes.length} text nodes.`,
1387
- count: textNodes.length,
1388
- textNodes: textNodes,
1389
- commandId
1390
- };
1391
- } catch (error) {
1392
- console.error("Error scanning text nodes:", error);
1393
-
1394
- // Send error progress update
1395
- sendProgressUpdate(
1396
- commandId,
1397
- 'scan_text_nodes',
1398
- 'error',
1399
- 0,
1400
- 0,
1401
- 0,
1402
- `Error scanning text nodes: ${error.message}`,
1403
- { error: error.message }
1404
- );
1405
-
1406
- throw new Error(`Error scanning text nodes: ${error.message}`);
1407
- }
1408
- }
1409
-
1410
- // Chunked implementation
1411
- console.log(`Using chunked scanning with chunk size: ${chunkSize}`);
1412
-
1413
- // First, collect all nodes to process (without processing them yet)
1414
- const nodesToProcess = [];
1415
-
1416
- // Send started progress update
1417
- sendProgressUpdate(
1418
- commandId,
1419
- 'scan_text_nodes',
1420
- 'started',
1421
- 0,
1422
- 0, // Not known yet how many nodes there are
1423
- 0,
1424
- `Starting chunked scan of node "${node.name || nodeId}"`,
1425
- { chunkSize }
1426
- );
1427
-
1428
- await collectNodesToProcess(node, [], 0, nodesToProcess);
1429
-
1430
- const totalNodes = nodesToProcess.length;
1431
- console.log(`Found ${totalNodes} total nodes to process`);
1432
-
1433
- // Calculate number of chunks needed
1434
- const totalChunks = Math.ceil(totalNodes / chunkSize);
1435
- console.log(`Will process in ${totalChunks} chunks`);
1436
-
1437
- // Send update after node collection
1438
- sendProgressUpdate(
1439
- commandId,
1440
- 'scan_text_nodes',
1441
- 'in_progress',
1442
- 5, // 5% progress for collection phase
1443
- totalNodes,
1444
- 0,
1445
- `Found ${totalNodes} nodes to scan. Will process in ${totalChunks} chunks.`,
1446
- {
1447
- totalNodes,
1448
- totalChunks,
1449
- chunkSize
1450
- }
1451
- );
1452
-
1453
- // Process nodes in chunks
1454
- const allTextNodes = [];
1455
- let processedNodes = 0;
1456
- let chunksProcessed = 0;
1457
-
1458
- for (let i = 0; i < totalNodes; i += chunkSize) {
1459
- const chunkEnd = Math.min(i + chunkSize, totalNodes);
1460
- console.log(`Processing chunk ${chunksProcessed + 1}/${totalChunks} (nodes ${i} to ${chunkEnd - 1})`);
1461
-
1462
- // Send update before processing chunk
1463
- sendProgressUpdate(
1464
- commandId,
1465
- 'scan_text_nodes',
1466
- 'in_progress',
1467
- Math.round(5 + ((chunksProcessed / totalChunks) * 90)), // 5-95% for processing
1468
- totalNodes,
1469
- processedNodes,
1470
- `Processing chunk ${chunksProcessed + 1}/${totalChunks}`,
1471
- {
1472
- currentChunk: chunksProcessed + 1,
1473
- totalChunks,
1474
- textNodesFound: allTextNodes.length
1475
- }
1476
- );
1477
-
1478
- const chunkNodes = nodesToProcess.slice(i, chunkEnd);
1479
- const chunkTextNodes = [];
1480
-
1481
- // Process each node in this chunk
1482
- for (const nodeInfo of chunkNodes) {
1483
- if (nodeInfo.node.type === "TEXT") {
1484
- try {
1485
- const textNodeInfo = await processTextNode(nodeInfo.node, nodeInfo.parentPath, nodeInfo.depth);
1486
- if (textNodeInfo) {
1487
- chunkTextNodes.push(textNodeInfo);
1488
- }
1489
- } catch (error) {
1490
- console.error(`Error processing text node: ${error.message}`);
1491
- // Continue with other nodes
1492
- }
1493
- }
1494
-
1495
- // Brief delay to allow UI updates and prevent freezing
1496
- await delay(5);
1497
- }
1498
-
1499
- // Add results from this chunk
1500
- allTextNodes.push(...chunkTextNodes);
1501
- processedNodes += chunkNodes.length;
1502
- chunksProcessed++;
1503
-
1504
- // Send update after processing chunk
1505
- sendProgressUpdate(
1506
- commandId,
1507
- 'scan_text_nodes',
1508
- 'in_progress',
1509
- Math.round(5 + ((chunksProcessed / totalChunks) * 90)), // 5-95% for processing
1510
- totalNodes,
1511
- processedNodes,
1512
- `Processed chunk ${chunksProcessed}/${totalChunks}. Found ${allTextNodes.length} text nodes so far.`,
1513
- {
1514
- currentChunk: chunksProcessed,
1515
- totalChunks,
1516
- processedNodes,
1517
- textNodesFound: allTextNodes.length,
1518
- chunkResult: chunkTextNodes
1519
- }
1520
- );
1521
-
1522
- // Small delay between chunks to prevent UI freezing
1523
- if (i + chunkSize < totalNodes) {
1524
- await delay(50);
1525
- }
1526
- }
1527
-
1528
- // Send completed progress update
1529
- sendProgressUpdate(
1530
- commandId,
1531
- 'scan_text_nodes',
1532
- 'completed',
1533
- 100,
1534
- totalNodes,
1535
- processedNodes,
1536
- `Scan complete. Found ${allTextNodes.length} text nodes.`,
1537
- {
1538
- textNodes: allTextNodes,
1539
- processedNodes,
1540
- chunks: chunksProcessed
1541
- }
1542
- );
1543
-
1544
- return {
1545
- success: true,
1546
- message: `Chunked scan complete. Found ${allTextNodes.length} text nodes.`,
1547
- totalNodes: allTextNodes.length,
1548
- processedNodes: processedNodes,
1549
- chunks: chunksProcessed,
1550
- textNodes: allTextNodes,
1551
- commandId
1552
- };
1553
- }
1554
-
1555
- // Helper function to collect all nodes that need to be processed
1556
- async function collectNodesToProcess(node, parentPath = [], depth = 0, nodesToProcess = []) {
1557
- // Skip invisible nodes
1558
- if (node.visible === false) return;
1559
-
1560
- // Get the path to this node
1561
- const nodePath = [...parentPath, node.name || `Unnamed ${node.type}`];
1562
-
1563
- // Add this node to the processing list
1564
- nodesToProcess.push({
1565
- node: node,
1566
- parentPath: nodePath,
1567
- depth: depth
1568
- });
1569
-
1570
- // Recursively add children
1571
- if ("children" in node) {
1572
- for (const child of node.children) {
1573
- await collectNodesToProcess(child, nodePath, depth + 1, nodesToProcess);
1574
- }
1575
- }
1576
- }
1577
-
1578
- // Process a single text node
1579
- async function processTextNode(node, parentPath, depth) {
1580
- if (node.type !== "TEXT") return null;
1581
-
1582
- try {
1583
- // Safely extract font information
1584
- let fontFamily = "";
1585
- let fontStyle = "";
1586
-
1587
- if (node.fontName) {
1588
- if (typeof node.fontName === "object") {
1589
- if ("family" in node.fontName) fontFamily = node.fontName.family;
1590
- if ("style" in node.fontName) fontStyle = node.fontName.style;
1591
- }
1592
- }
1593
-
1594
- // Create a safe representation of the text node
1595
- const safeTextNode = {
1596
- id: node.id,
1597
- name: node.name || "Text",
1598
- type: node.type,
1599
- characters: node.characters,
1600
- fontSize: typeof node.fontSize === "number" ? node.fontSize : 0,
1601
- fontFamily: fontFamily,
1602
- fontStyle: fontStyle,
1603
- x: typeof node.x === "number" ? node.x : 0,
1604
- y: typeof node.y === "number" ? node.y : 0,
1605
- width: typeof node.width === "number" ? node.width : 0,
1606
- height: typeof node.height === "number" ? node.height : 0,
1607
- path: parentPath.join(" > "),
1608
- depth: depth,
1609
- };
1610
-
1611
- // Highlight the node briefly (optional visual feedback)
1612
- try {
1613
- const originalFills = JSON.parse(JSON.stringify(node.fills));
1614
- node.fills = [
1615
- {
1616
- type: "SOLID",
1617
- color: { r: 1, g: 0.5, b: 0 },
1618
- opacity: 0.3,
1619
- },
1620
- ];
1621
-
1622
- // Brief delay for the highlight to be visible
1623
- await delay(100);
1624
-
1625
- try {
1626
- node.fills = originalFills;
1627
- } catch (err) {
1628
- console.error("Error resetting fills:", err);
1629
- }
1630
- } catch (highlightErr) {
1631
- console.error("Error highlighting text node:", highlightErr);
1632
- // Continue anyway, highlighting is just visual feedback
1633
- }
1634
-
1635
- return safeTextNode;
1636
- } catch (nodeErr) {
1637
- console.error("Error processing text node:", nodeErr);
1638
- return null;
1639
- }
1640
- }
1641
-
1642
- // A delay function that returns a promise
1643
- function delay(ms) {
1644
- return new Promise(resolve => setTimeout(resolve, ms));
1645
- }
1646
-
1647
- // Keep the original findTextNodes for backward compatibility
1648
- async function findTextNodes(node, parentPath = [], depth = 0, textNodes = []) {
1649
- // Skip invisible nodes
1650
- if (node.visible === false) return;
1651
-
1652
- // Get the path to this node including its name
1653
- const nodePath = [...parentPath, node.name || `Unnamed ${node.type}`];
1654
-
1655
- if (node.type === "TEXT") {
1656
- try {
1657
- // Safely extract font information to avoid Symbol serialization issues
1658
- let fontFamily = "";
1659
- let fontStyle = "";
1660
-
1661
- if (node.fontName) {
1662
- if (typeof node.fontName === "object") {
1663
- if ("family" in node.fontName) fontFamily = node.fontName.family;
1664
- if ("style" in node.fontName) fontStyle = node.fontName.style;
1665
- }
1666
- }
1667
-
1668
- // Create a safe representation of the text node with only serializable properties
1669
- const safeTextNode = {
1670
- id: node.id,
1671
- name: node.name || "Text",
1672
- type: node.type,
1673
- characters: node.characters,
1674
- fontSize: typeof node.fontSize === "number" ? node.fontSize : 0,
1675
- fontFamily: fontFamily,
1676
- fontStyle: fontStyle,
1677
- x: typeof node.x === "number" ? node.x : 0,
1678
- y: typeof node.y === "number" ? node.y : 0,
1679
- width: typeof node.width === "number" ? node.width : 0,
1680
- height: typeof node.height === "number" ? node.height : 0,
1681
- path: nodePath.join(" > "),
1682
- depth: depth,
1683
- };
1684
-
1685
- // Only highlight the node if it's not being done via API
1686
- try {
1687
- // Safe way to create a temporary highlight without causing serialization issues
1688
- const originalFills = JSON.parse(JSON.stringify(node.fills));
1689
- node.fills = [
1690
- {
1691
- type: "SOLID",
1692
- color: { r: 1, g: 0.5, b: 0 },
1693
- opacity: 0.3,
1694
- },
1695
- ];
1696
-
1697
- // Promise-based delay instead of setTimeout
1698
- await delay(500);
1699
-
1700
- try {
1701
- node.fills = originalFills;
1702
- } catch (err) {
1703
- console.error("Error resetting fills:", err);
1704
- }
1705
- } catch (highlightErr) {
1706
- console.error("Error highlighting text node:", highlightErr);
1707
- // Continue anyway, highlighting is just visual feedback
1708
- }
1709
-
1710
- textNodes.push(safeTextNode);
1711
- } catch (nodeErr) {
1712
- console.error("Error processing text node:", nodeErr);
1713
- // Skip this node but continue with others
1714
- }
1715
- }
1716
-
1717
- // Recursively process children of container nodes
1718
- if ("children" in node) {
1719
- for (const child of node.children) {
1720
- await findTextNodes(child, nodePath, depth + 1, textNodes);
1721
- }
1722
- }
1723
- }
1724
-
1725
- // Replace text in a specific node
1726
- async function setMultipleTextContents(params) {
1727
- const { nodeId, text } = params || {};
1728
- const commandId = params.commandId || generateCommandId();
1729
-
1730
- if (!nodeId || !text || !Array.isArray(text)) {
1731
- const errorMsg = "Missing required parameters: nodeId and text array";
1732
-
1733
- // Send error progress update
1734
- sendProgressUpdate(
1735
- commandId,
1736
- 'set_multiple_text_contents',
1737
- 'error',
1738
- 0,
1739
- 0,
1740
- 0,
1741
- errorMsg,
1742
- { error: errorMsg }
1743
- );
1744
-
1745
- throw new Error(errorMsg);
1746
- }
1747
-
1748
- console.log(
1749
- `Starting text replacement for node: ${nodeId} with ${text.length} text replacements`
1750
- );
1751
-
1752
- // Send started progress update
1753
- sendProgressUpdate(
1754
- commandId,
1755
- 'set_multiple_text_contents',
1756
- 'started',
1757
- 0,
1758
- text.length,
1759
- 0,
1760
- `Starting text replacement for ${text.length} nodes`,
1761
- { totalReplacements: text.length }
1762
- );
1763
-
1764
- // Define the results array and counters
1765
- const results = [];
1766
- let successCount = 0;
1767
- let failureCount = 0;
1768
-
1769
- // Split text replacements into chunks of 5
1770
- const CHUNK_SIZE = 5;
1771
- const chunks = [];
1772
-
1773
- for (let i = 0; i < text.length; i += CHUNK_SIZE) {
1774
- chunks.push(text.slice(i, i + CHUNK_SIZE));
1775
- }
1776
-
1777
- console.log(`Split ${text.length} replacements into ${chunks.length} chunks`);
1778
-
1779
- // Send chunking info update
1780
- sendProgressUpdate(
1781
- commandId,
1782
- 'set_multiple_text_contents',
1783
- 'in_progress',
1784
- 5, // 5% progress for planning phase
1785
- text.length,
1786
- 0,
1787
- `Preparing to replace text in ${text.length} nodes using ${chunks.length} chunks`,
1788
- {
1789
- totalReplacements: text.length,
1790
- chunks: chunks.length,
1791
- chunkSize: CHUNK_SIZE
1792
- }
1793
- );
1794
-
1795
- // Process each chunk sequentially
1796
- for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
1797
- const chunk = chunks[chunkIndex];
1798
- console.log(`Processing chunk ${chunkIndex + 1}/${chunks.length} with ${chunk.length} replacements`);
1799
-
1800
- // Send chunk processing start update
1801
- sendProgressUpdate(
1802
- commandId,
1803
- 'set_multiple_text_contents',
1804
- 'in_progress',
1805
- Math.round(5 + ((chunkIndex / chunks.length) * 90)), // 5-95% for processing
1806
- text.length,
1807
- successCount + failureCount,
1808
- `Processing text replacements chunk ${chunkIndex + 1}/${chunks.length}`,
1809
- {
1810
- currentChunk: chunkIndex + 1,
1811
- totalChunks: chunks.length,
1812
- successCount,
1813
- failureCount
1814
- }
1815
- );
1816
-
1817
- // Process replacements within a chunk in parallel
1818
- const chunkPromises = chunk.map(async (replacement) => {
1819
- if (!replacement.nodeId || replacement.text === undefined) {
1820
- console.error(`Missing nodeId or text for replacement`);
1821
- return {
1822
- success: false,
1823
- nodeId: replacement.nodeId || "unknown",
1824
- error: "Missing nodeId or text in replacement entry"
1825
- };
1826
- }
1827
-
1828
- try {
1829
- console.log(`Attempting to replace text in node: ${replacement.nodeId}`);
1830
-
1831
- // Get the text node to update (just to check it exists and get original text)
1832
- const textNode = await figma.getNodeByIdAsync(replacement.nodeId);
1833
-
1834
- if (!textNode) {
1835
- console.error(`Text node not found: ${replacement.nodeId}`);
1836
- return {
1837
- success: false,
1838
- nodeId: replacement.nodeId,
1839
- error: `Node not found: ${replacement.nodeId}`
1840
- };
1841
- }
1842
-
1843
- if (textNode.type !== "TEXT") {
1844
- console.error(`Node is not a text node: ${replacement.nodeId} (type: ${textNode.type})`);
1845
- return {
1846
- success: false,
1847
- nodeId: replacement.nodeId,
1848
- error: `Node is not a text node: ${replacement.nodeId} (type: ${textNode.type})`
1849
- };
1850
- }
1851
-
1852
- // Save original text for the result
1853
- const originalText = textNode.characters;
1854
- console.log(`Original text: "${originalText}"`);
1855
- console.log(`Will translate to: "${replacement.text}"`);
1856
-
1857
- // Highlight the node before changing text
1858
- let originalFills;
1859
- try {
1860
- // Save original fills for restoration later
1861
- originalFills = JSON.parse(JSON.stringify(textNode.fills));
1862
- // Apply highlight color (orange with 30% opacity)
1863
- textNode.fills = [
1864
- {
1865
- type: "SOLID",
1866
- color: { r: 1, g: 0.5, b: 0 },
1867
- opacity: 0.3,
1868
- },
1869
- ];
1870
- } catch (highlightErr) {
1871
- console.error(`Error highlighting text node: ${highlightErr.message}`);
1872
- // Continue anyway, highlighting is just visual feedback
1873
- }
1874
-
1875
- // Use the existing setTextContent function to handle font loading and text setting
1876
- await setTextContent({
1877
- nodeId: replacement.nodeId,
1878
- text: replacement.text
1879
- });
1880
-
1881
- // Keep highlight for a moment after text change, then restore original fills
1882
- if (originalFills) {
1883
- try {
1884
- // Use delay function for consistent timing
1885
- await delay(500);
1886
- textNode.fills = originalFills;
1887
- } catch (restoreErr) {
1888
- console.error(`Error restoring fills: ${restoreErr.message}`);
1889
- }
1890
- }
1891
-
1892
- console.log(`Successfully replaced text in node: ${replacement.nodeId}`);
1893
- return {
1894
- success: true,
1895
- nodeId: replacement.nodeId,
1896
- originalText: originalText,
1897
- translatedText: replacement.text
1898
- };
1899
- } catch (error) {
1900
- console.error(`Error replacing text in node ${replacement.nodeId}: ${error.message}`);
1901
- return {
1902
- success: false,
1903
- nodeId: replacement.nodeId,
1904
- error: `Error applying replacement: ${error.message}`
1905
- };
1906
- }
1907
- });
1908
-
1909
- // Wait for all replacements in this chunk to complete
1910
- const chunkResults = await Promise.all(chunkPromises);
1911
-
1912
- // Process results for this chunk
1913
- chunkResults.forEach(result => {
1914
- if (result.success) {
1915
- successCount++;
1916
- } else {
1917
- failureCount++;
1918
- }
1919
- results.push(result);
1920
- });
1921
-
1922
- // Send chunk processing complete update with partial results
1923
- sendProgressUpdate(
1924
- commandId,
1925
- 'set_multiple_text_contents',
1926
- 'in_progress',
1927
- Math.round(5 + (((chunkIndex + 1) / chunks.length) * 90)), // 5-95% for processing
1928
- text.length,
1929
- successCount + failureCount,
1930
- `Completed chunk ${chunkIndex + 1}/${chunks.length}. ${successCount} successful, ${failureCount} failed so far.`,
1931
- {
1932
- currentChunk: chunkIndex + 1,
1933
- totalChunks: chunks.length,
1934
- successCount,
1935
- failureCount,
1936
- chunkResults: chunkResults
1937
- }
1938
- );
1939
-
1940
- // Add a small delay between chunks to avoid overloading Figma
1941
- if (chunkIndex < chunks.length - 1) {
1942
- console.log('Pausing between chunks to avoid overloading Figma...');
1943
- await delay(1000); // 1 second delay between chunks
1944
- }
1945
- }
1946
-
1947
- console.log(
1948
- `Replacement complete: ${successCount} successful, ${failureCount} failed`
1949
- );
1950
-
1951
- // Send completed progress update
1952
- sendProgressUpdate(
1953
- commandId,
1954
- 'set_multiple_text_contents',
1955
- 'completed',
1956
- 100,
1957
- text.length,
1958
- successCount + failureCount,
1959
- `Text replacement complete: ${successCount} successful, ${failureCount} failed`,
1960
- {
1961
- totalReplacements: text.length,
1962
- replacementsApplied: successCount,
1963
- replacementsFailed: failureCount,
1964
- completedInChunks: chunks.length,
1965
- results: results
1966
- }
1967
- );
1968
-
1969
- return {
1970
- success: successCount > 0,
1971
- nodeId: nodeId,
1972
- replacementsApplied: successCount,
1973
- replacementsFailed: failureCount,
1974
- totalReplacements: text.length,
1975
- results: results,
1976
- completedInChunks: chunks.length,
1977
- commandId
1978
- };
1979
- }
1980
-
1981
- // Function to generate simple UUIDs for command IDs
1982
- function generateCommandId() {
1983
- return 'cmd_' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
1984
- }
1985
-
1986
- async function setAutoLayout(params) {
1987
- const {
1988
- nodeId,
1989
- layoutMode,
1990
- paddingTop,
1991
- paddingBottom,
1992
- paddingLeft,
1993
- paddingRight,
1994
- itemSpacing,
1995
- primaryAxisAlignItems,
1996
- counterAxisAlignItems,
1997
- layoutWrap,
1998
- strokesIncludedInLayout
1999
- } = params || {};
2000
-
2001
- if (!nodeId) {
2002
- throw new Error("Missing nodeId parameter");
2003
- }
2004
-
2005
- if (!layoutMode) {
2006
- throw new Error("Missing layoutMode parameter");
2007
- }
2008
-
2009
- const node = await figma.getNodeByIdAsync(nodeId);
2010
- if (!node) {
2011
- throw new Error(`Node not found with ID: ${nodeId}`);
2012
- }
2013
-
2014
- // Check if the node is a frame or group
2015
- if (!("layoutMode" in node)) {
2016
- throw new Error(`Node does not support auto layout: ${nodeId}`);
2017
- }
2018
-
2019
- // Configure layout mode
2020
- if (layoutMode === "NONE") {
2021
- node.layoutMode = "NONE";
2022
- } else {
2023
- // Set auto layout properties
2024
- node.layoutMode = layoutMode;
2025
-
2026
- // Configure padding if provided
2027
- if (paddingTop !== undefined) node.paddingTop = paddingTop;
2028
- if (paddingBottom !== undefined) node.paddingBottom = paddingBottom;
2029
- if (paddingLeft !== undefined) node.paddingLeft = paddingLeft;
2030
- if (paddingRight !== undefined) node.paddingRight = paddingRight;
2031
-
2032
- // Configure item spacing
2033
- if (itemSpacing !== undefined) node.itemSpacing = itemSpacing;
2034
-
2035
- // Configure alignment
2036
- if (primaryAxisAlignItems !== undefined) {
2037
- node.primaryAxisAlignItems = primaryAxisAlignItems;
2038
- }
2039
-
2040
- if (counterAxisAlignItems !== undefined) {
2041
- node.counterAxisAlignItems = counterAxisAlignItems;
2042
- }
2043
-
2044
- // Configure wrap
2045
- if (layoutWrap !== undefined) {
2046
- node.layoutWrap = layoutWrap;
2047
- }
2048
-
2049
- // Configure stroke inclusion
2050
- if (strokesIncludedInLayout !== undefined) {
2051
- node.strokesIncludedInLayout = strokesIncludedInLayout;
2052
- }
2053
- }
2054
-
2055
- return {
2056
- id: node.id,
2057
- name: node.name,
2058
- layoutMode: node.layoutMode,
2059
- paddingTop: node.paddingTop,
2060
- paddingBottom: node.paddingBottom,
2061
- paddingLeft: node.paddingLeft,
2062
- paddingRight: node.paddingRight,
2063
- itemSpacing: node.itemSpacing,
2064
- primaryAxisAlignItems: node.primaryAxisAlignItems,
2065
- counterAxisAlignItems: node.counterAxisAlignItems,
2066
- layoutWrap: node.layoutWrap,
2067
- strokesIncludedInLayout: node.strokesIncludedInLayout
2068
- };
2069
- }
2070
-
2071
- // Nuevas funciones para propiedades de texto
2072
-
2073
- async function setFontName(params) {
2074
- const { nodeId, family, style } = params || {};
2075
- if (!nodeId || !family) {
2076
- throw new Error("Missing nodeId or font family");
2077
- }
2078
-
2079
- const node = await figma.getNodeByIdAsync(nodeId);
2080
- if (!node) {
2081
- throw new Error(`Node not found with ID: ${nodeId}`);
2082
- }
2083
-
2084
- if (node.type !== "TEXT") {
2085
- throw new Error(`Node is not a text node: ${nodeId}`);
2086
- }
2087
-
2088
- try {
2089
- await figma.loadFontAsync({ family, style: style || "Regular" });
2090
- node.fontName = { family, style: style || "Regular" };
2091
- return {
2092
- id: node.id,
2093
- name: node.name,
2094
- fontName: node.fontName
2095
- };
2096
- } catch (error) {
2097
- throw new Error(`Error setting font name: ${error.message}`);
2098
- }
2099
- }
2100
-
2101
- async function setFontSize(params) {
2102
- const { nodeId, fontSize } = params || {};
2103
- if (!nodeId || fontSize === undefined) {
2104
- throw new Error("Missing nodeId or fontSize");
2105
- }
2106
-
2107
- const node = await figma.getNodeByIdAsync(nodeId);
2108
- if (!node) {
2109
- throw new Error(`Node not found with ID: ${nodeId}`);
2110
- }
2111
-
2112
- if (node.type !== "TEXT") {
2113
- throw new Error(`Node is not a text node: ${nodeId}`);
2114
- }
2115
-
2116
- try {
2117
- await figma.loadFontAsync(node.fontName);
2118
- node.fontSize = fontSize;
2119
- return {
2120
- id: node.id,
2121
- name: node.name,
2122
- fontSize: node.fontSize
2123
- };
2124
- } catch (error) {
2125
- throw new Error(`Error setting font size: ${error.message}`);
2126
- }
2127
- }
2128
-
2129
- async function setFontWeight(params) {
2130
- const { nodeId, weight } = params || {};
2131
- if (!nodeId || weight === undefined) {
2132
- throw new Error("Missing nodeId or weight");
2133
- }
2134
-
2135
- // Map weight to font style
2136
- const getFontStyle = (weight) => {
2137
- switch (weight) {
2138
- case 100: return "Thin";
2139
- case 200: return "Extra Light";
2140
- case 300: return "Light";
2141
- case 400: return "Regular";
2142
- case 500: return "Medium";
2143
- case 600: return "Semi Bold";
2144
- case 700: return "Bold";
2145
- case 800: return "Extra Bold";
2146
- case 900: return "Black";
2147
- default: return "Regular";
2148
- }
2149
- };
2150
-
2151
- const node = await figma.getNodeByIdAsync(nodeId);
2152
- if (!node) {
2153
- throw new Error(`Node not found with ID: ${nodeId}`);
2154
- }
2155
-
2156
- if (node.type !== "TEXT") {
2157
- throw new Error(`Node is not a text node: ${nodeId}`);
2158
- }
2159
-
2160
- try {
2161
- const family = node.fontName.family;
2162
- const style = getFontStyle(weight);
2163
- await figma.loadFontAsync({ family, style });
2164
- node.fontName = { family, style };
2165
- return {
2166
- id: node.id,
2167
- name: node.name,
2168
- fontName: node.fontName,
2169
- weight: weight
2170
- };
2171
- } catch (error) {
2172
- throw new Error(`Error setting font weight: ${error.message}`);
2173
- }
2174
- }
2175
-
2176
- async function setLetterSpacing(params) {
2177
- const { nodeId, letterSpacing, unit = "PIXELS" } = params || {};
2178
- if (!nodeId || letterSpacing === undefined) {
2179
- throw new Error("Missing nodeId or letterSpacing");
2180
- }
2181
-
2182
- const node = await figma.getNodeByIdAsync(nodeId);
2183
- if (!node) {
2184
- throw new Error(`Node not found with ID: ${nodeId}`);
2185
- }
2186
-
2187
- if (node.type !== "TEXT") {
2188
- throw new Error(`Node is not a text node: ${nodeId}`);
2189
- }
2190
-
2191
- try {
2192
- await figma.loadFontAsync(node.fontName);
2193
- node.letterSpacing = { value: letterSpacing, unit };
2194
- return {
2195
- id: node.id,
2196
- name: node.name,
2197
- letterSpacing: node.letterSpacing
2198
- };
2199
- } catch (error) {
2200
- throw new Error(`Error setting letter spacing: ${error.message}`);
2201
- }
2202
- }
2203
-
2204
- async function setLineHeight(params) {
2205
- const { nodeId, lineHeight, unit = "PIXELS" } = params || {};
2206
- if (!nodeId || lineHeight === undefined) {
2207
- throw new Error("Missing nodeId or lineHeight");
2208
- }
2209
-
2210
- const node = await figma.getNodeByIdAsync(nodeId);
2211
- if (!node) {
2212
- throw new Error(`Node not found with ID: ${nodeId}`);
2213
- }
2214
-
2215
- if (node.type !== "TEXT") {
2216
- throw new Error(`Node is not a text node: ${nodeId}`);
2217
- }
2218
-
2219
- try {
2220
- await figma.loadFontAsync(node.fontName);
2221
- node.lineHeight = { value: lineHeight, unit };
2222
- return {
2223
- id: node.id,
2224
- name: node.name,
2225
- lineHeight: node.lineHeight
2226
- };
2227
- } catch (error) {
2228
- throw new Error(`Error setting line height: ${error.message}`);
2229
- }
2230
- }
2231
-
2232
- async function setParagraphSpacing(params) {
2233
- const { nodeId, paragraphSpacing } = params || {};
2234
- if (!nodeId || paragraphSpacing === undefined) {
2235
- throw new Error("Missing nodeId or paragraphSpacing");
2236
- }
2237
-
2238
- const node = await figma.getNodeByIdAsync(nodeId);
2239
- if (!node) {
2240
- throw new Error(`Node not found with ID: ${nodeId}`);
2241
- }
2242
-
2243
- if (node.type !== "TEXT") {
2244
- throw new Error(`Node is not a text node: ${nodeId}`);
2245
- }
2246
-
2247
- try {
2248
- await figma.loadFontAsync(node.fontName);
2249
- node.paragraphSpacing = paragraphSpacing;
2250
- return {
2251
- id: node.id,
2252
- name: node.name,
2253
- paragraphSpacing: node.paragraphSpacing
2254
- };
2255
- } catch (error) {
2256
- throw new Error(`Error setting paragraph spacing: ${error.message}`);
2257
- }
2258
- }
2259
-
2260
- async function setTextCase(params) {
2261
- const { nodeId, textCase } = params || {};
2262
- if (!nodeId || textCase === undefined) {
2263
- throw new Error("Missing nodeId or textCase");
2264
- }
2265
-
2266
- // Valid textCase values: "ORIGINAL", "UPPER", "LOWER", "TITLE"
2267
- if (!["ORIGINAL", "UPPER", "LOWER", "TITLE"].includes(textCase)) {
2268
- throw new Error("Invalid textCase value. Must be one of: ORIGINAL, UPPER, LOWER, TITLE");
2269
- }
2270
-
2271
- const node = await figma.getNodeByIdAsync(nodeId);
2272
- if (!node) {
2273
- throw new Error(`Node not found with ID: ${nodeId}`);
2274
- }
2275
-
2276
- if (node.type !== "TEXT") {
2277
- throw new Error(`Node is not a text node: ${nodeId}`);
2278
- }
2279
-
2280
- try {
2281
- await figma.loadFontAsync(node.fontName);
2282
- node.textCase = textCase;
2283
- return {
2284
- id: node.id,
2285
- name: node.name,
2286
- textCase: node.textCase
2287
- };
2288
- } catch (error) {
2289
- throw new Error(`Error setting text case: ${error.message}`);
2290
- }
2291
- }
2292
-
2293
- async function setTextDecoration(params) {
2294
- const { nodeId, textDecoration } = params || {};
2295
- if (!nodeId || textDecoration === undefined) {
2296
- throw new Error("Missing nodeId or textDecoration");
2297
- }
2298
-
2299
- // Valid textDecoration values: "NONE", "UNDERLINE", "STRIKETHROUGH"
2300
- if (!["NONE", "UNDERLINE", "STRIKETHROUGH"].includes(textDecoration)) {
2301
- throw new Error("Invalid textDecoration value. Must be one of: NONE, UNDERLINE, STRIKETHROUGH");
2302
- }
2303
-
2304
- const node = await figma.getNodeByIdAsync(nodeId);
2305
- if (!node) {
2306
- throw new Error(`Node not found with ID: ${nodeId}`);
2307
- }
2308
-
2309
- if (node.type !== "TEXT") {
2310
- throw new Error(`Node is not a text node: ${nodeId}`);
2311
- }
2312
-
2313
- try {
2314
- await figma.loadFontAsync(node.fontName);
2315
- node.textDecoration = textDecoration;
2316
- return {
2317
- id: node.id,
2318
- name: node.name,
2319
- textDecoration: node.textDecoration
2320
- };
2321
- } catch (error) {
2322
- throw new Error(`Error setting text decoration: ${error.message}`);
2323
- }
2324
- }
2325
-
2326
- async function getStyledTextSegments(params) {
2327
- const { nodeId, property } = params || {};
2328
- if (!nodeId || !property) {
2329
- throw new Error("Missing nodeId or property");
2330
- }
2331
-
2332
- // Valid properties: "fillStyleId", "fontName", "fontSize", "textCase",
2333
- // "textDecoration", "textStyleId", "fills", "letterSpacing", "lineHeight", "fontWeight"
2334
- const validProperties = [
2335
- "fillStyleId", "fontName", "fontSize", "textCase",
2336
- "textDecoration", "textStyleId", "fills", "letterSpacing",
2337
- "lineHeight", "fontWeight"
2338
- ];
2339
-
2340
- if (!validProperties.includes(property)) {
2341
- throw new Error(`Invalid property. Must be one of: ${validProperties.join(", ")}`);
2342
- }
2343
-
2344
- const node = await figma.getNodeByIdAsync(nodeId);
2345
- if (!node) {
2346
- throw new Error(`Node not found with ID: ${nodeId}`);
2347
- }
2348
-
2349
- if (node.type !== "TEXT") {
2350
- throw new Error(`Node is not a text node: ${nodeId}`);
2351
- }
2352
-
2353
- try {
2354
- const segments = node.getStyledTextSegments([property]);
2355
-
2356
- // Prepare segments data in a format safe for serialization
2357
- const safeSegments = segments.map(segment => {
2358
- const safeSegment = {
2359
- characters: segment.characters,
2360
- start: segment.start,
2361
- end: segment.end
2362
- };
2363
-
2364
- // Handle different property types for safe serialization
2365
- if (property === "fontName") {
2366
- if (segment[property] && typeof segment[property] === "object") {
2367
- safeSegment[property] = {
2368
- family: segment[property].family || "",
2369
- style: segment[property].style || ""
2370
- };
2371
- } else {
2372
- safeSegment[property] = { family: "", style: "" };
2373
- }
2374
- } else if (property === "letterSpacing" || property === "lineHeight") {
2375
- // Handle spacing properties which have a value and unit
2376
- if (segment[property] && typeof segment[property] === "object") {
2377
- safeSegment[property] = {
2378
- value: segment[property].value || 0,
2379
- unit: segment[property].unit || "PIXELS"
2380
- };
2381
- } else {
2382
- safeSegment[property] = { value: 0, unit: "PIXELS" };
2383
- }
2384
- } else if (property === "fills") {
2385
- // Handle fills which can be complex
2386
- safeSegment[property] = segment[property] ? JSON.parse(JSON.stringify(segment[property])) : [];
2387
- } else {
2388
- // Handle simple properties
2389
- safeSegment[property] = segment[property];
2390
- }
2391
-
2392
- return safeSegment;
2393
- });
2394
-
2395
- return {
2396
- id: node.id,
2397
- name: node.name,
2398
- property: property,
2399
- segments: safeSegments
2400
- };
2401
- } catch (error) {
2402
- throw new Error(`Error getting styled text segments: ${error.message}`);
2403
- }
2404
- }
2405
-
2406
- async function loadFontAsyncWrapper(params) {
2407
- const { family, style = "Regular" } = params || {};
2408
- if (!family) {
2409
- throw new Error("Missing font family");
2410
- }
2411
-
2412
- try {
2413
- await figma.loadFontAsync({ family, style });
2414
- return {
2415
- success: true,
2416
- family: family,
2417
- style: style,
2418
- message: `Successfully loaded ${family} ${style}`
2419
- };
2420
- } catch (error) {
2421
- throw new Error(`Error loading font: ${error.message}`);
2422
- }
2423
- }
2424
-
2425
- async function getRemoteComponents() {
2426
- try {
2427
- // Check if figma.teamLibrary is available
2428
- if (!figma.teamLibrary) {
2429
- console.error("Error: figma.teamLibrary API is not available");
2430
- throw new Error("The figma.teamLibrary API is not available in this context");
2431
- }
2432
-
2433
- // Check if figma.teamLibrary.getAvailableComponentsAsync exists
2434
- if (!figma.teamLibrary.getAvailableComponentsAsync) {
2435
- console.error("Error: figma.teamLibrary.getAvailableComponentsAsync is not available");
2436
- throw new Error("The getAvailableComponentsAsync method is not available");
2437
- }
2438
-
2439
- console.log("Starting remote components retrieval...");
2440
-
2441
- // Set up a manual timeout to detect deadlocks
2442
- let timeoutId;
2443
- const timeoutPromise = new Promise((_, reject) => {
2444
- timeoutId = setTimeout(() => {
2445
- reject(new Error("Internal timeout while retrieving remote components (15s)"));
2446
- }, 15000); // 15 seconds internal timeout
2447
- });
2448
-
2449
- // Execute the request with a manual timeout
2450
- const fetchPromise = figma.teamLibrary.getAvailableComponentsAsync();
2451
-
2452
- // Use Promise.race to implement the timeout
2453
- const teamComponents = await Promise.race([fetchPromise, timeoutPromise])
2454
- .finally(() => {
2455
- clearTimeout(timeoutId); // Clear the timeout
2456
- });
2457
-
2458
- console.log(`Retrieved ${teamComponents.length} remote components`);
2459
-
2460
- return {
2461
- success: true,
2462
- count: teamComponents.length,
2463
- components: teamComponents.map(component => ({
2464
- key: component.key,
2465
- name: component.name,
2466
- description: component.description || "",
2467
- libraryName: component.libraryName
2468
- }))
2469
- };
2470
- } catch (error) {
2471
- console.error(`Detailed error retrieving remote components: ${error.message || "Unknown error"}`);
2472
- console.error(`Stack trace: ${error.stack || "Not available"}`);
2473
-
2474
- // Instead of returning an error object, throw an exception with the error message
2475
- throw new Error(`Error retrieving remote components: ${error.message}`);
2476
- }
2477
- }
2478
-
2479
- // Set Effects Tool
2480
- async function setEffects(params) {
2481
- const { nodeId, effects } = params || {};
2482
-
2483
- if (!nodeId) {
2484
- throw new Error("Missing nodeId parameter");
2485
- }
2486
-
2487
- if (!effects || !Array.isArray(effects)) {
2488
- throw new Error("Missing or invalid effects parameter. Must be an array.");
2489
- }
2490
-
2491
- const node = await figma.getNodeByIdAsync(nodeId);
2492
- if (!node) {
2493
- throw new Error(`Node not found with ID: ${nodeId}`);
2494
- }
2495
-
2496
- if (!("effects" in node)) {
2497
- throw new Error(`Node does not support effects: ${nodeId}`);
2498
- }
2499
-
2500
- try {
2501
- // Convert incoming effects to valid Figma effects
2502
- const validEffects = effects.map(effect => {
2503
- // Ensure all effects have the required properties
2504
- if (!effect.type) {
2505
- throw new Error("Each effect must have a type property");
2506
- }
2507
-
2508
- // Create a clean effect object based on type
2509
- switch (effect.type) {
2510
- case "DROP_SHADOW":
2511
- case "INNER_SHADOW":
2512
- return {
2513
- type: effect.type,
2514
- color: effect.color || { r: 0, g: 0, b: 0, a: 0.5 },
2515
- offset: effect.offset || { x: 0, y: 0 },
2516
- radius: effect.radius || 5,
2517
- spread: effect.spread || 0,
2518
- visible: effect.visible !== undefined ? effect.visible : true,
2519
- blendMode: effect.blendMode || "NORMAL"
2520
- };
2521
- case "LAYER_BLUR":
2522
- case "BACKGROUND_BLUR":
2523
- return {
2524
- type: effect.type,
2525
- radius: effect.radius || 5,
2526
- visible: effect.visible !== undefined ? effect.visible : true
2527
- };
2528
- default:
2529
- throw new Error(`Unsupported effect type: ${effect.type}`);
2530
- }
2531
- });
2532
-
2533
- // Apply the effects to the node
2534
- node.effects = validEffects;
2535
-
2536
- return {
2537
- id: node.id,
2538
- name: node.name,
2539
- effects: node.effects
2540
- };
2541
- } catch (error) {
2542
- throw new Error(`Error setting effects: ${error.message}`);
2543
- }
2544
- }
2545
-
2546
- // Set Effect Style ID Tool
2547
- async function setEffectStyleId(params) {
2548
- const { nodeId, effectStyleId } = params || {};
2549
-
2550
- if (!nodeId) {
2551
- throw new Error("Missing nodeId parameter");
2552
- }
2553
-
2554
- if (!effectStyleId) {
2555
- throw new Error("Missing effectStyleId parameter");
2556
- }
2557
-
2558
- try {
2559
- // Set up a manual timeout to detect long operations
2560
- let timeoutId;
2561
- const timeoutPromise = new Promise((_, reject) => {
2562
- timeoutId = setTimeout(() => {
2563
- reject(new Error("Timeout while setting effect style ID (8s). The operation took too long to complete."));
2564
- }, 8000); // 8 seconds timeout
2565
- });
2566
-
2567
- console.log(`Starting to set effect style ID ${effectStyleId} on node ${nodeId}...`);
2568
-
2569
- // Get node and validate in a promise
2570
- const nodePromise = (async () => {
2571
- const node = await figma.getNodeByIdAsync(nodeId);
2572
- if (!node) {
2573
- throw new Error(`Node not found with ID: ${nodeId}`);
2574
- }
2575
-
2576
- if (!("effectStyleId" in node)) {
2577
- throw new Error(`Node with ID ${nodeId} does not support effect styles`);
2578
- }
2579
-
2580
- // Try to validate the effect style exists before applying
2581
- console.log(`Fetching effect styles to validate style ID: ${effectStyleId}`);
2582
- const effectStyles = await figma.getLocalEffectStylesAsync();
2583
- const foundStyle = effectStyles.find(style => style.id === effectStyleId);
2584
-
2585
- if (!foundStyle) {
2586
- throw new Error(`Effect style not found with ID: ${effectStyleId}. Available styles: ${effectStyles.length}`);
2587
- }
2588
-
2589
- console.log(`Effect style found, applying to node...`);
2590
-
2591
- // Apply the effect style to the node
2592
- node.effectStyleId = effectStyleId;
2593
-
2594
- return {
2595
- id: node.id,
2596
- name: node.name,
2597
- effectStyleId: node.effectStyleId,
2598
- appliedEffects: node.effects
2599
- };
2600
- })();
2601
-
2602
- // Race between the node operation and the timeout
2603
- const result = await Promise.race([nodePromise, timeoutPromise])
2604
- .finally(() => {
2605
- // Clear the timeout to prevent memory leaks
2606
- clearTimeout(timeoutId);
2607
- });
2608
-
2609
- console.log(`Successfully set effect style ID on node ${nodeId}`);
2610
- return result;
2611
- } catch (error) {
2612
- console.error(`Error setting effect style ID: ${error.message || "Unknown error"}`);
2613
- console.error(`Stack trace: ${error.stack || "Not available"}`);
2614
-
2615
- // Proporcionar mensajes de error específicos para diferentes casos
2616
- if (error.message.includes("timeout") || error.message.includes("Timeout")) {
2617
- throw new Error(`The operation timed out after 8 seconds. This could happen with complex nodes or effects. Try with a simpler node or effect style.`);
2618
- } else if (error.message.includes("not found") && error.message.includes("Node")) {
2619
- throw new Error(`Node with ID "${nodeId}" not found. Make sure the node exists in the current document.`);
2620
- } else if (error.message.includes("not found") && error.message.includes("style")) {
2621
- throw new Error(`Effect style with ID "${effectStyleId}" not found. Make sure the style exists in your local styles.`);
2622
- } else if (error.message.includes("does not support")) {
2623
- throw new Error(`The selected node type does not support effect styles. Only certain node types like frames, components, and instances can have effect styles.`);
2624
- } else {
2625
- throw new Error(`Error setting effect style ID: ${error.message}`);
2626
- }
2627
- }
2628
- }
2629
-
2630
- // Function to group nodes
2631
- async function groupNodes(params) {
2632
- const { nodeIds, name } = params || {};
2633
-
2634
- if (!nodeIds || !Array.isArray(nodeIds) || nodeIds.length < 2) {
2635
- throw new Error("Must provide at least two nodeIds to group");
2636
- }
2637
-
2638
- try {
2639
- // Get all nodes to be grouped
2640
- const nodesToGroup = [];
2641
- for (const nodeId of nodeIds) {
2642
- const node = await figma.getNodeByIdAsync(nodeId);
2643
- if (!node) {
2644
- throw new Error(`Node not found with ID: ${nodeId}`);
2645
- }
2646
- nodesToGroup.push(node);
2647
- }
2648
-
2649
- // Verify that all nodes have the same parent
2650
- const parent = nodesToGroup[0].parent;
2651
- for (const node of nodesToGroup) {
2652
- if (node.parent !== parent) {
2653
- throw new Error("All nodes must have the same parent to be grouped");
2654
- }
2655
- }
2656
-
2657
- // Create a group and add the nodes to it
2658
- const group = figma.group(nodesToGroup, parent);
2659
-
2660
- // Optionally set a name for the group
2661
- if (name) {
2662
- group.name = name;
2663
- }
2664
-
2665
- return {
2666
- id: group.id,
2667
- name: group.name,
2668
- type: group.type,
2669
- children: group.children.map(child => ({ id: child.id, name: child.name, type: child.type }))
2670
- };
2671
- } catch (error) {
2672
- throw new Error(`Error grouping nodes: ${error.message}`);
2673
- }
2674
- }
2675
-
2676
- // Function to ungroup nodes
2677
- async function ungroupNodes(params) {
2678
- const { nodeId } = params || {};
2679
-
2680
- if (!nodeId) {
2681
- throw new Error("Missing nodeId parameter");
2682
- }
2683
-
2684
- try {
2685
- const node = await figma.getNodeByIdAsync(nodeId);
2686
- if (!node) {
2687
- throw new Error(`Node not found with ID: ${nodeId}`);
2688
- }
2689
-
2690
- // Verify that the node is a group or a frame
2691
- if (node.type !== "GROUP" && node.type !== "FRAME") {
2692
- throw new Error(`Node with ID ${nodeId} is not a GROUP or FRAME`);
2693
- }
2694
-
2695
- // Get the parent and children before ungrouping
2696
- const parent = node.parent;
2697
- const children = [...node.children];
2698
-
2699
- // Ungroup the node
2700
- const ungroupedItems = figma.ungroup(node);
2701
-
2702
- return {
2703
- success: true,
2704
- ungroupedCount: ungroupedItems.length,
2705
- items: ungroupedItems.map(item => ({ id: item.id, name: item.name, type: item.type }))
2706
- };
2707
- } catch (error) {
2708
- throw new Error(`Error ungrouping node: ${error.message}`);
2709
- }
2710
- }
2711
-
2712
- // Function to flatten nodes (e.g., boolean operations, convert to path)
2713
- async function flattenNode(params) {
2714
- const { nodeId } = params || {};
2715
-
2716
- if (!nodeId) {
2717
- throw new Error("Missing nodeId parameter");
2718
- }
2719
-
2720
- try {
2721
- const node = await figma.getNodeByIdAsync(nodeId);
2722
- if (!node) {
2723
- throw new Error(`Node not found with ID: ${nodeId}`);
2724
- }
2725
-
2726
- // Check for specific node types that can be flattened
2727
- const flattenableTypes = ["VECTOR", "BOOLEAN_OPERATION", "STAR", "POLYGON", "ELLIPSE", "RECTANGLE"];
2728
-
2729
- if (!flattenableTypes.includes(node.type)) {
2730
- throw new Error(`Node with ID ${nodeId} and type ${node.type} cannot be flattened. Only vector-based nodes can be flattened.`);
2731
- }
2732
-
2733
- // Verify the node has the flatten method before calling it
2734
- if (typeof node.flatten !== 'function') {
2735
- throw new Error(`Node with ID ${nodeId} does not support the flatten operation.`);
2736
- }
2737
-
2738
- // Implement a timeout mechanism
2739
- let timeoutId;
2740
- const timeoutPromise = new Promise((_, reject) => {
2741
- timeoutId = setTimeout(() => {
2742
- reject(new Error("Flatten operation timed out after 8 seconds. The node may be too complex."));
2743
- }, 8000); // 8 seconds timeout
2744
- });
2745
-
2746
- // Execute the flatten operation in a promise
2747
- const flattenPromise = new Promise((resolve, reject) => {
2748
- // Execute in the next tick to allow UI updates
2749
- setTimeout(() => {
2750
- try {
2751
- console.log(`Starting flatten operation for node ID ${nodeId}...`);
2752
- const flattened = node.flatten();
2753
- console.log(`Flatten operation completed successfully for node ID ${nodeId}`);
2754
- resolve(flattened);
2755
- } catch (err) {
2756
- console.error(`Error during flatten operation: ${err.message}`);
2757
- reject(err);
2758
- }
2759
- }, 0);
2760
- });
2761
-
2762
- // Race between the timeout and the operation
2763
- const flattened = await Promise.race([flattenPromise, timeoutPromise])
2764
- .finally(() => {
2765
- // Clear the timeout to prevent memory leaks
2766
- clearTimeout(timeoutId);
2767
- });
2768
-
2769
- return {
2770
- id: flattened.id,
2771
- name: flattened.name,
2772
- type: flattened.type
2773
- };
2774
- } catch (error) {
2775
- console.error(`Error in flattenNode: ${error.message}`);
2776
- if (error.message.includes("timed out")) {
2777
- // Provide a more helpful message for timeout errors
2778
- throw new Error(`The flatten operation timed out. This usually happens with complex nodes. Try simplifying the node first or breaking it into smaller parts.`);
2779
- } else {
2780
- throw new Error(`Error flattening node: ${error.message}`);
2781
- }
2782
- }
2783
- }
2784
-
2785
- // Function to insert a child into a parent node
2786
- async function insertChild(params) {
2787
- const { parentId, childId, index } = params || {};
2788
-
2789
- if (!parentId) {
2790
- throw new Error("Missing parentId parameter");
2791
- }
2792
-
2793
- if (!childId) {
2794
- throw new Error("Missing childId parameter");
2795
- }
2796
-
2797
- try {
2798
- // Get the parent and child nodes
2799
- const parent = await figma.getNodeByIdAsync(parentId);
2800
- if (!parent) {
2801
- throw new Error(`Parent node not found with ID: ${parentId}`);
2802
- }
2803
-
2804
- const child = await figma.getNodeByIdAsync(childId);
2805
- if (!child) {
2806
- throw new Error(`Child node not found with ID: ${childId}`);
2807
- }
2808
-
2809
- // Check if the parent can have children
2810
- if (!("appendChild" in parent)) {
2811
- throw new Error(`Parent node with ID ${parentId} cannot have children`);
2812
- }
2813
-
2814
- // Save child's current parent for proper handling
2815
- const originalParent = child.parent;
2816
-
2817
- // Insert the child at the specified index or append it
2818
- if (index !== undefined && index >= 0 && index <= parent.children.length) {
2819
- parent.insertChild(index, child);
2820
- } else {
2821
- parent.appendChild(child);
2822
- }
2823
-
2824
- // Verify that the insertion worked
2825
- const newIndex = parent.children.indexOf(child);
2826
-
2827
- return {
2828
- parentId: parent.id,
2829
- childId: child.id,
2830
- index: newIndex,
2831
- success: newIndex !== -1,
2832
- previousParentId: originalParent ? originalParent.id : null
2833
- };
2834
- } catch (error) {
2835
- console.error(`Error inserting child: ${error.message}`, error);
2836
- throw new Error(`Error inserting child: ${error.message}`);
2837
- }
2838
- }
2839
-
2840
- async function createEllipse(params) {
2841
- const {
2842
- x = 0,
2843
- y = 0,
2844
- width = 100,
2845
- height = 100,
2846
- name = "Ellipse",
2847
- parentId,
2848
- fillColor = { r: 0.8, g: 0.8, b: 0.8, a: 1 },
2849
- strokeColor,
2850
- strokeWeight
2851
- } = params || {};
2852
-
2853
- // Create a new ellipse node
2854
- const ellipse = figma.createEllipse();
2855
- ellipse.name = name;
2856
-
2857
- // Position and size the ellipse
2858
- ellipse.x = x;
2859
- ellipse.y = y;
2860
- ellipse.resize(width, height);
2861
-
2862
- // Set fill color if provided
2863
- if (fillColor) {
2864
- const fillStyle = {
2865
- type: "SOLID",
2866
- color: {
2867
- r: parseFloat(fillColor.r) || 0,
2868
- g: parseFloat(fillColor.g) || 0,
2869
- b: parseFloat(fillColor.b) || 0,
2870
- },
2871
- opacity: parseFloat(fillColor.a) || 1
2872
- };
2873
- ellipse.fills = [fillStyle];
2874
- }
2875
-
2876
- // Set stroke color and weight if provided
2877
- if (strokeColor) {
2878
- const strokeStyle = {
2879
- type: "SOLID",
2880
- color: {
2881
- r: parseFloat(strokeColor.r) || 0,
2882
- g: parseFloat(strokeColor.g) || 0,
2883
- b: parseFloat(strokeColor.b) || 0,
2884
- },
2885
- opacity: parseFloat(strokeColor.a) || 1
2886
- };
2887
- ellipse.strokes = [strokeStyle];
2888
-
2889
- if (strokeWeight) {
2890
- ellipse.strokeWeight = strokeWeight;
2891
- }
2892
- }
2893
-
2894
- // If parentId is provided, append to that node, otherwise append to current page
2895
- if (parentId) {
2896
- const parentNode = await figma.getNodeByIdAsync(parentId);
2897
- if (!parentNode) {
2898
- throw new Error(`Parent node not found with ID: ${parentId}`);
2899
- }
2900
- if (!("appendChild" in parentNode)) {
2901
- throw new Error(`Parent node does not support children: ${parentId}`);
2902
- }
2903
- parentNode.appendChild(ellipse);
2904
- } else {
2905
- figma.currentPage.appendChild(ellipse);
2906
- }
2907
-
2908
- return {
2909
- id: ellipse.id,
2910
- name: ellipse.name,
2911
- type: ellipse.type,
2912
- x: ellipse.x,
2913
- y: ellipse.y,
2914
- width: ellipse.width,
2915
- height: ellipse.height
2916
- };
2917
- }
2918
-
2919
- async function createPolygon(params) {
2920
- const {
2921
- x = 0,
2922
- y = 0,
2923
- width = 100,
2924
- height = 100,
2925
- sides = 6,
2926
- name = "Polygon",
2927
- parentId,
2928
- fillColor,
2929
- strokeColor,
2930
- strokeWeight
2931
- } = params || {};
2932
-
2933
- // Create the polygon
2934
- const polygon = figma.createPolygon();
2935
- polygon.x = x;
2936
- polygon.y = y;
2937
- polygon.resize(width, height);
2938
- polygon.name = name;
2939
-
2940
- // Set the number of sides
2941
- if (sides >= 3) {
2942
- polygon.pointCount = sides;
2943
- }
2944
-
2945
- // Set fill color if provided
2946
- if (fillColor) {
2947
- const paintStyle = {
2948
- type: "SOLID",
2949
- color: {
2950
- r: parseFloat(fillColor.r) || 0,
2951
- g: parseFloat(fillColor.g) || 0,
2952
- b: parseFloat(fillColor.b) || 0,
2953
- },
2954
- opacity: parseFloat(fillColor.a) || 1,
2955
- };
2956
- polygon.fills = [paintStyle];
2957
- }
2958
-
2959
- // Set stroke color and weight if provided
2960
- if (strokeColor) {
2961
- const strokeStyle = {
2962
- type: "SOLID",
2963
- color: {
2964
- r: parseFloat(strokeColor.r) || 0,
2965
- g: parseFloat(strokeColor.g) || 0,
2966
- b: parseFloat(strokeColor.b) || 0,
2967
- },
2968
- opacity: parseFloat(strokeColor.a) || 1,
2969
- };
2970
- polygon.strokes = [strokeStyle];
2971
- }
2972
-
2973
- // Set stroke weight if provided
2974
- if (strokeWeight !== undefined) {
2975
- polygon.strokeWeight = strokeWeight;
2976
- }
2977
-
2978
- // If parentId is provided, append to that node, otherwise append to current page
2979
- if (parentId) {
2980
- const parentNode = await figma.getNodeByIdAsync(parentId);
2981
- if (!parentNode) {
2982
- throw new Error(`Parent node not found with ID: ${parentId}`);
2983
- }
2984
- if (!("appendChild" in parentNode)) {
2985
- throw new Error(`Parent node does not support children: ${parentId}`);
2986
- }
2987
- parentNode.appendChild(polygon);
2988
- } else {
2989
- figma.currentPage.appendChild(polygon);
2990
- }
2991
-
2992
- return {
2993
- id: polygon.id,
2994
- name: polygon.name,
2995
- type: polygon.type,
2996
- x: polygon.x,
2997
- y: polygon.y,
2998
- width: polygon.width,
2999
- height: polygon.height,
3000
- pointCount: polygon.pointCount,
3001
- fills: polygon.fills,
3002
- strokes: polygon.strokes,
3003
- strokeWeight: polygon.strokeWeight,
3004
- parentId: polygon.parent ? polygon.parent.id : undefined,
3005
- };
3006
- }
3007
-
3008
- async function createStar(params) {
3009
- const {
3010
- x = 0,
3011
- y = 0,
3012
- width = 100,
3013
- height = 100,
3014
- points = 5,
3015
- innerRadius = 0.5, // As a proportion of the outer radius
3016
- name = "Star",
3017
- parentId,
3018
- fillColor,
3019
- strokeColor,
3020
- strokeWeight
3021
- } = params || {};
3022
-
3023
- // Create the star
3024
- const star = figma.createStar();
3025
- star.x = x;
3026
- star.y = y;
3027
- star.resize(width, height);
3028
- star.name = name;
3029
-
3030
- // Set the number of points
3031
- if (points >= 3) {
3032
- star.pointCount = points;
3033
- }
3034
-
3035
- // Set the inner radius ratio
3036
- if (innerRadius > 0 && innerRadius < 1) {
3037
- star.innerRadius = innerRadius;
3038
- }
3039
-
3040
- // Set fill color if provided
3041
- if (fillColor) {
3042
- const paintStyle = {
3043
- type: "SOLID",
3044
- color: {
3045
- r: parseFloat(fillColor.r) || 0,
3046
- g: parseFloat(fillColor.g) || 0,
3047
- b: parseFloat(fillColor.b) || 0,
3048
- },
3049
- opacity: parseFloat(fillColor.a) || 1,
3050
- };
3051
- star.fills = [paintStyle];
3052
- }
3053
-
3054
- // Set stroke color and weight if provided
3055
- if (strokeColor) {
3056
- const strokeStyle = {
3057
- type: "SOLID",
3058
- color: {
3059
- r: parseFloat(strokeColor.r) || 0,
3060
- g: parseFloat(strokeColor.g) || 0,
3061
- b: parseFloat(strokeColor.b) || 0,
3062
- },
3063
- opacity: parseFloat(strokeColor.a) || 1,
3064
- };
3065
- star.strokes = [strokeStyle];
3066
- }
3067
-
3068
- // Set stroke weight if provided
3069
- if (strokeWeight !== undefined) {
3070
- star.strokeWeight = strokeWeight;
3071
- }
3072
-
3073
- // If parentId is provided, append to that node, otherwise append to current page
3074
- if (parentId) {
3075
- const parentNode = await figma.getNodeByIdAsync(parentId);
3076
- if (!parentNode) {
3077
- throw new Error(`Parent node not found with ID: ${parentId}`);
3078
- }
3079
- if (!("appendChild" in parentNode)) {
3080
- throw new Error(`Parent node does not support children: ${parentId}`);
3081
- }
3082
- parentNode.appendChild(star);
3083
- } else {
3084
- figma.currentPage.appendChild(star);
3085
- }
3086
-
3087
- return {
3088
- id: star.id,
3089
- name: star.name,
3090
- type: star.type,
3091
- x: star.x,
3092
- y: star.y,
3093
- width: star.width,
3094
- height: star.height,
3095
- pointCount: star.pointCount,
3096
- innerRadius: star.innerRadius,
3097
- fills: star.fills,
3098
- strokes: star.strokes,
3099
- strokeWeight: star.strokeWeight,
3100
- parentId: star.parent ? star.parent.id : undefined,
3101
- };
3102
- }
3103
-
3104
- async function createVector(params) {
3105
- const {
3106
- x = 0,
3107
- y = 0,
3108
- width = 100,
3109
- height = 100,
3110
- name = "Vector",
3111
- parentId,
3112
- vectorPaths = [],
3113
- fillColor,
3114
- strokeColor,
3115
- strokeWeight
3116
- } = params || {};
3117
-
3118
- // Create the vector
3119
- const vector = figma.createVector();
3120
- vector.x = x;
3121
- vector.y = y;
3122
- vector.resize(width, height);
3123
- vector.name = name;
3124
-
3125
- // Set vector paths if provided
3126
- if (vectorPaths && vectorPaths.length > 0) {
3127
- vector.vectorPaths = vectorPaths.map(path => {
3128
- return {
3129
- windingRule: path.windingRule || "EVENODD",
3130
- data: path.data || ""
3131
- };
3132
- });
3133
- }
3134
-
3135
- // Set fill color if provided
3136
- if (fillColor) {
3137
- const paintStyle = {
3138
- type: "SOLID",
3139
- color: {
3140
- r: parseFloat(fillColor.r) || 0,
3141
- g: parseFloat(fillColor.g) || 0,
3142
- b: parseFloat(fillColor.b) || 0,
3143
- },
3144
- opacity: parseFloat(fillColor.a) || 1,
3145
- };
3146
- vector.fills = [paintStyle];
3147
- }
3148
-
3149
- // Set stroke color and weight if provided
3150
- if (strokeColor) {
3151
- const strokeStyle = {
3152
- type: "SOLID",
3153
- color: {
3154
- r: parseFloat(strokeColor.r) || 0,
3155
- g: parseFloat(strokeColor.g) || 0,
3156
- b: parseFloat(strokeColor.b) || 0,
3157
- },
3158
- opacity: parseFloat(strokeColor.a) || 1,
3159
- };
3160
- vector.strokes = [strokeStyle];
3161
- }
3162
-
3163
- // Set stroke weight if provided
3164
- if (strokeWeight !== undefined) {
3165
- vector.strokeWeight = strokeWeight;
3166
- }
3167
-
3168
- // If parentId is provided, append to that node, otherwise append to current page
3169
- if (parentId) {
3170
- const parentNode = await figma.getNodeByIdAsync(parentId);
3171
- if (!parentNode) {
3172
- throw new Error(`Parent node not found with ID: ${parentId}`);
3173
- }
3174
- if (!("appendChild" in parentNode)) {
3175
- throw new Error(`Parent node does not support children: ${parentId}`);
3176
- }
3177
- parentNode.appendChild(vector);
3178
- } else {
3179
- figma.currentPage.appendChild(vector);
3180
- }
3181
-
3182
- return {
3183
- id: vector.id,
3184
- name: vector.name,
3185
- type: vector.type,
3186
- x: vector.x,
3187
- y: vector.y,
3188
- width: vector.width,
3189
- height: vector.height,
3190
- vectorNetwork: vector.vectorNetwork,
3191
- fills: vector.fills,
3192
- strokes: vector.strokes,
3193
- strokeWeight: vector.strokeWeight,
3194
- parentId: vector.parent ? vector.parent.id : undefined,
3195
- };
3196
- }
3197
-
3198
- async function createLine(params) {
3199
- const {
3200
- x1 = 0,
3201
- y1 = 0,
3202
- x2 = 100,
3203
- y2 = 0,
3204
- name = "Line",
3205
- parentId,
3206
- strokeColor = { r: 0, g: 0, b: 0, a: 1 },
3207
- strokeWeight = 1,
3208
- strokeCap = "NONE" // Can be "NONE", "ROUND", "SQUARE", "ARROW_LINES", or "ARROW_EQUILATERAL"
3209
- } = params || {};
3210
-
3211
- // Create a vector node to represent the line
3212
- const line = figma.createVector();
3213
- line.name = name;
3214
-
3215
- // Position the line at the starting point
3216
- line.x = x1;
3217
- line.y = y1;
3218
-
3219
- // Calculate the vector size
3220
- const width = Math.abs(x2 - x1);
3221
- const height = Math.abs(y2 - y1);
3222
- line.resize(width > 0 ? width : 1, height > 0 ? height : 1);
3223
-
3224
- // Create vector path data for a straight line
3225
- // SVG path data format: M (move to) starting point, L (line to) ending point
3226
- const dx = x2 - x1;
3227
- const dy = y2 - y1;
3228
-
3229
- // Calculate relative endpoint coordinates in the vector's local coordinate system
3230
- const endX = dx > 0 ? width : 0;
3231
- const endY = dy > 0 ? height : 0;
3232
- const startX = dx > 0 ? 0 : width;
3233
- const startY = dy > 0 ? 0 : height;
3234
-
3235
- // Generate SVG path data for the line
3236
- const pathData = `M ${startX} ${startY} L ${endX} ${endY}`;
3237
-
3238
- // Set vector paths
3239
- line.vectorPaths = [{
3240
- windingRule: "NONZERO",
3241
- data: pathData
3242
- }];
3243
-
3244
- // Set stroke color
3245
- const strokeStyle = {
3246
- type: "SOLID",
3247
- color: {
3248
- r: parseFloat(strokeColor.r) || 0,
3249
- g: parseFloat(strokeColor.g) || 0,
3250
- b: parseFloat(strokeColor.b) || 0,
3251
- },
3252
- opacity: parseFloat(strokeColor.a) || 1
3253
- };
3254
- line.strokes = [strokeStyle];
3255
-
3256
- // Set stroke weight
3257
- line.strokeWeight = strokeWeight;
3258
-
3259
- // Set stroke cap style if supported
3260
- if (["NONE", "ROUND", "SQUARE", "ARROW_LINES", "ARROW_EQUILATERAL"].includes(strokeCap)) {
3261
- line.strokeCap = strokeCap;
3262
- }
3263
-
3264
- // Set fill to none (transparent) as lines typically don't have fills
3265
- line.fills = [];
3266
-
3267
- // If parentId is provided, append to that node, otherwise append to current page
3268
- if (parentId) {
3269
- const parentNode = await figma.getNodeByIdAsync(parentId);
3270
- if (!parentNode) {
3271
- throw new Error(`Parent node not found with ID: ${parentId}`);
3272
- }
3273
- if (!("appendChild" in parentNode)) {
3274
- throw new Error(`Parent node does not support children: ${parentId}`);
3275
- }
3276
- parentNode.appendChild(line);
3277
- } else {
3278
- figma.currentPage.appendChild(line);
3279
- }
3280
-
3281
- return {
3282
- id: line.id,
3283
- name: line.name,
3284
- type: line.type,
3285
- x: line.x,
3286
- y: line.y,
3287
- width: line.width,
3288
- height: line.height,
3289
- strokeWeight: line.strokeWeight,
3290
- strokeCap: line.strokeCap,
3291
- strokes: line.strokes,
3292
- vectorPaths: line.vectorPaths,
3293
- parentId: line.parent ? line.parent.id : undefined
3294
- };
3295
- }