@nguyenphp/antigravity-marketing 1.0.16 → 1.0.19

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 (376) hide show
  1. package/README.md +187 -74
  2. package/bin/index.js +4 -4
  3. package/package.json +4 -3
  4. package/templates/.agent/agents/backend-specialist.md +263 -0
  5. package/templates/.agent/agents/database-architect.md +226 -0
  6. package/templates/.agent/agents/debugger.md +225 -0
  7. package/templates/.agent/agents/devops-engineer.md +242 -0
  8. package/templates/.agent/agents/documentation-writer.md +104 -0
  9. package/templates/.agent/agents/explorer-agent.md +73 -0
  10. package/templates/.agent/agents/frontend-specialist.md +527 -0
  11. package/templates/.agent/agents/game-developer.md +162 -0
  12. package/templates/.agent/agents/mobile-developer.md +377 -0
  13. package/templates/.agent/agents/orchestrator.md +400 -0
  14. package/templates/.agent/agents/penetration-tester.md +188 -0
  15. package/templates/.agent/agents/performance-optimizer.md +187 -0
  16. package/templates/.agent/agents/project-planner.md +403 -0
  17. package/templates/.agent/agents/security-auditor.md +170 -0
  18. package/templates/.agent/agents/seo-specialist.md +111 -0
  19. package/templates/.agent/agents/test-engineer.md +158 -0
  20. package/templates/.agent/rules/GEMINI.md +248 -0
  21. package/templates/.agent/skills/analytics-marketing/SKILL.md +172 -324
  22. package/templates/.agent/skills/api-patterns/SKILL.md +81 -0
  23. package/templates/.agent/skills/api-patterns/api-style.md +42 -0
  24. package/templates/.agent/skills/api-patterns/auth.md +24 -0
  25. package/templates/.agent/skills/api-patterns/documentation.md +26 -0
  26. package/templates/.agent/skills/api-patterns/graphql.md +41 -0
  27. package/templates/.agent/skills/api-patterns/rate-limiting.md +31 -0
  28. package/templates/.agent/skills/api-patterns/response.md +37 -0
  29. package/templates/.agent/skills/api-patterns/rest.md +40 -0
  30. package/templates/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  31. package/templates/.agent/skills/api-patterns/security-testing.md +122 -0
  32. package/templates/.agent/skills/api-patterns/trpc.md +41 -0
  33. package/templates/.agent/skills/api-patterns/versioning.md +22 -0
  34. package/templates/.agent/skills/app-builder/SKILL.md +75 -0
  35. package/templates/.agent/skills/app-builder/agent-coordination.md +71 -0
  36. package/templates/.agent/skills/app-builder/feature-building.md +53 -0
  37. package/templates/.agent/skills/app-builder/project-detection.md +34 -0
  38. package/templates/.agent/skills/app-builder/scaffolding.md +118 -0
  39. package/templates/.agent/skills/app-builder/tech-stack.md +40 -0
  40. package/templates/.agent/skills/app-builder/templates/SKILL.md +39 -0
  41. package/templates/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  42. package/templates/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  43. package/templates/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  44. package/templates/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  45. package/templates/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  46. package/templates/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  47. package/templates/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  48. package/templates/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +82 -0
  49. package/templates/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +100 -0
  50. package/templates/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +106 -0
  51. package/templates/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +101 -0
  52. package/templates/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  53. package/templates/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +93 -0
  54. package/templates/.agent/skills/architecture/SKILL.md +55 -0
  55. package/templates/.agent/skills/architecture/context-discovery.md +43 -0
  56. package/templates/.agent/skills/architecture/examples.md +94 -0
  57. package/templates/.agent/skills/architecture/pattern-selection.md +68 -0
  58. package/templates/.agent/skills/architecture/patterns-reference.md +50 -0
  59. package/templates/.agent/skills/architecture/trade-off-analysis.md +77 -0
  60. package/templates/.agent/skills/banner-design/SKILL.md +192 -0
  61. package/templates/.agent/skills/banner-design/references/banner-sizes-and-styles.md +118 -0
  62. package/templates/.agent/skills/bash-linux/SKILL.md +199 -0
  63. package/templates/.agent/skills/behavioral-modes/SKILL.md +242 -0
  64. package/templates/.agent/skills/brainstorming/SKILL.md +163 -0
  65. package/templates/.agent/skills/brainstorming/dynamic-questioning.md +350 -0
  66. package/templates/.agent/skills/brand/SKILL.md +97 -0
  67. package/templates/.agent/skills/brand/references/approval-checklist.md +169 -0
  68. package/templates/.agent/skills/brand/references/asset-organization.md +157 -0
  69. package/templates/.agent/skills/brand/references/brand-guideline-template.md +140 -0
  70. package/templates/.agent/skills/brand/references/color-palette-management.md +186 -0
  71. package/templates/.agent/skills/brand/references/consistency-checklist.md +94 -0
  72. package/templates/.agent/skills/brand/references/logo-usage-rules.md +185 -0
  73. package/templates/.agent/skills/brand/references/messaging-framework.md +85 -0
  74. package/templates/.agent/skills/brand/references/typography-specifications.md +214 -0
  75. package/templates/.agent/skills/brand/references/update.md +118 -0
  76. package/templates/.agent/skills/brand/references/visual-identity.md +96 -0
  77. package/templates/.agent/skills/brand/references/voice-framework.md +88 -0
  78. package/templates/.agent/skills/brand/scripts/extract-colors.cjs +341 -0
  79. package/templates/.agent/skills/brand/scripts/inject-brand-context.cjs +349 -0
  80. package/templates/.agent/skills/brand/scripts/sync-brand-to-tokens.cjs +266 -0
  81. package/templates/.agent/skills/brand/scripts/validate-asset.cjs +387 -0
  82. package/templates/.agent/skills/brand/templates/brand-guidelines-starter.md +275 -0
  83. package/templates/.agent/skills/clean-code/SKILL.md +201 -0
  84. package/templates/.agent/skills/code-review-checklist/SKILL.md +109 -0
  85. package/templates/.agent/skills/copywriting/SKILL.md +250 -0
  86. package/templates/.agent/skills/database-design/SKILL.md +52 -0
  87. package/templates/.agent/skills/database-design/database-selection.md +43 -0
  88. package/templates/.agent/skills/database-design/indexing.md +39 -0
  89. package/templates/.agent/skills/database-design/migrations.md +48 -0
  90. package/templates/.agent/skills/database-design/optimization.md +36 -0
  91. package/templates/.agent/skills/database-design/orm-selection.md +30 -0
  92. package/templates/.agent/skills/database-design/schema-design.md +56 -0
  93. package/templates/.agent/skills/database-design/scripts/schema_validator.py +172 -0
  94. package/templates/.agent/skills/deployment-procedures/SKILL.md +241 -0
  95. package/templates/.agent/skills/docker-expert/SKILL.md +409 -0
  96. package/templates/.agent/skills/frontend-design/animation-guide.md +331 -0
  97. package/templates/.agent/skills/frontend-design/color-system.md +311 -0
  98. package/templates/.agent/skills/frontend-design/decision-trees.md +418 -0
  99. package/templates/.agent/skills/frontend-design/motion-graphics.md +306 -0
  100. package/templates/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  101. package/templates/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  102. package/templates/.agent/skills/frontend-design/typography-system.md +345 -0
  103. package/templates/.agent/skills/frontend-design/ux-psychology.md +541 -0
  104. package/templates/.agent/skills/frontend-design/visual-effects.md +383 -0
  105. package/templates/.agent/skills/frontend-slides/SKILL.md +92 -0
  106. package/templates/.agent/skills/frontend-slides/STYLE_PRESETS.md +347 -0
  107. package/templates/.agent/skills/frontend-slides/animation-patterns.md +110 -0
  108. package/templates/.agent/skills/frontend-slides/examples/n8n-jupviec-automation.html +789 -0
  109. package/templates/.agent/skills/frontend-slides/examples/n8n-jupviec-automation.pptx +0 -0
  110. package/templates/.agent/skills/frontend-slides/html-template.md +347 -0
  111. package/templates/.agent/skills/frontend-slides/scripts/export-pptx.py +58 -0
  112. package/templates/.agent/skills/frontend-slides/scripts/extract-pptx.py +96 -0
  113. package/templates/.agent/skills/frontend-slides/viewport-base.css +153 -0
  114. package/templates/.agent/skills/game-development/2d-games/SKILL.md +119 -0
  115. package/templates/.agent/skills/game-development/3d-games/SKILL.md +135 -0
  116. package/templates/.agent/skills/game-development/SKILL.md +167 -0
  117. package/templates/.agent/skills/game-development/game-art/SKILL.md +185 -0
  118. package/templates/.agent/skills/game-development/game-audio/SKILL.md +190 -0
  119. package/templates/.agent/skills/game-development/game-design/SKILL.md +129 -0
  120. package/templates/.agent/skills/game-development/mobile-games/SKILL.md +108 -0
  121. package/templates/.agent/skills/game-development/multiplayer/SKILL.md +132 -0
  122. package/templates/.agent/skills/game-development/pc-games/SKILL.md +144 -0
  123. package/templates/.agent/skills/game-development/vr-ar/SKILL.md +123 -0
  124. package/templates/.agent/skills/game-development/web-games/SKILL.md +150 -0
  125. package/templates/.agent/skills/geo-fundamentals/SKILL.md +156 -0
  126. package/templates/.agent/skills/geo-fundamentals/scripts/geo_checker.py +289 -0
  127. package/templates/.agent/skills/growth-engine/SKILL.md +244 -0
  128. package/templates/.agent/skills/i18n-localization/SKILL.md +154 -0
  129. package/templates/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  130. package/templates/.agent/skills/lint-and-validate/SKILL.md +45 -0
  131. package/templates/.agent/skills/lint-and-validate/scripts/lint_runner.py +172 -0
  132. package/templates/.agent/skills/lint-and-validate/scripts/type_coverage.py +173 -0
  133. package/templates/.agent/skills/marketing-report-expert/SKILL.md +70 -0
  134. package/templates/.agent/skills/mcp-builder/SKILL.md +176 -0
  135. package/templates/.agent/skills/minimax-docx/LICENSE +21 -0
  136. package/templates/.agent/skills/minimax-docx/SKILL.md +274 -0
  137. package/templates/.agent/skills/minimax-docx/assets/styles/academic_styles.xml +250 -0
  138. package/templates/.agent/skills/minimax-docx/assets/styles/corporate_styles.xml +284 -0
  139. package/templates/.agent/skills/minimax-docx/assets/styles/default_styles.xml +449 -0
  140. package/templates/.agent/skills/minimax-docx/assets/xsd/aesthetic-rules.xsd +470 -0
  141. package/templates/.agent/skills/minimax-docx/assets/xsd/business-rules.xsd +130 -0
  142. package/templates/.agent/skills/minimax-docx/assets/xsd/common-types.xsd +159 -0
  143. package/templates/.agent/skills/minimax-docx/assets/xsd/wml-subset.xsd +589 -0
  144. package/templates/.agent/skills/minimax-docx/references/cjk_typography.md +357 -0
  145. package/templates/.agent/skills/minimax-docx/references/cjk_university_template_guide.md +184 -0
  146. package/templates/.agent/skills/minimax-docx/references/comments_guide.md +191 -0
  147. package/templates/.agent/skills/minimax-docx/references/design_good_bad_examples.md +829 -0
  148. package/templates/.agent/skills/minimax-docx/references/design_principles.md +819 -0
  149. package/templates/.agent/skills/minimax-docx/references/openxml_element_order.md +308 -0
  150. package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part1.md +4061 -0
  151. package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part2.md +2820 -0
  152. package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part3.md +3381 -0
  153. package/templates/.agent/skills/minimax-docx/references/openxml_namespaces.md +82 -0
  154. package/templates/.agent/skills/minimax-docx/references/openxml_units.md +72 -0
  155. package/templates/.agent/skills/minimax-docx/references/scenario_a_create.md +284 -0
  156. package/templates/.agent/skills/minimax-docx/references/scenario_b_edit_content.md +295 -0
  157. package/templates/.agent/skills/minimax-docx/references/scenario_c_apply_template.md +456 -0
  158. package/templates/.agent/skills/minimax-docx/references/track_changes_guide.md +200 -0
  159. package/templates/.agent/skills/minimax-docx/references/troubleshooting.md +506 -0
  160. package/templates/.agent/skills/minimax-docx/references/typography_guide.md +294 -0
  161. package/templates/.agent/skills/minimax-docx/references/xsd_validation_guide.md +158 -0
  162. package/templates/.agent/skills/minimax-docx/scripts/doc_to_docx.sh +40 -0
  163. package/templates/.agent/skills/minimax-docx/scripts/docx_preview.sh +37 -0
  164. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Cli/MiniMaxAIDocx.Cli.csproj +19 -0
  165. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Cli/Program.cs +18 -0
  166. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/AnalyzeCommand.cs +147 -0
  167. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/ApplyTemplateCommand.cs +322 -0
  168. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/CreateCommand.cs +324 -0
  169. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/DiffCommand.cs +155 -0
  170. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/EditContentCommand.cs +487 -0
  171. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/FixOrderCommand.cs +108 -0
  172. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/MergeRunsCommand.cs +122 -0
  173. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/ValidateCommand.cs +107 -0
  174. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/MiniMaxAIDocx.Core.csproj +15 -0
  175. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/CommentSynchronizer.cs +169 -0
  176. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/ElementOrder.cs +80 -0
  177. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/NamespaceConstants.cs +42 -0
  178. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/RunMerger.cs +81 -0
  179. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/StyleAnalyzer.cs +81 -0
  180. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/TrackChangesHelper.cs +99 -0
  181. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/UnitConverter.cs +23 -0
  182. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples.cs +1832 -0
  183. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch1.cs +910 -0
  184. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch2.cs +999 -0
  185. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch3.cs +1048 -0
  186. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch4.cs +1038 -0
  187. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/CharacterFormattingSamples.cs +1020 -0
  188. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/DocumentCreationSamples.cs +1121 -0
  189. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/FieldAndTocSamples.cs +624 -0
  190. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/FootnoteAndCommentSamples.cs +675 -0
  191. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/HeaderFooterSamples.cs +838 -0
  192. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ImageSamples.cs +917 -0
  193. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ListAndNumberingSamples.cs +826 -0
  194. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ParagraphFormattingSamples.cs +1199 -0
  195. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/StyleSystemSamples.cs +1487 -0
  196. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/TableSamples.cs +1163 -0
  197. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/TrackChangesSamples.cs +595 -0
  198. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/CjkHelper.cs +39 -0
  199. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/FontDefaults.cs +24 -0
  200. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/PageSizes.cs +20 -0
  201. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/BusinessRuleValidator.cs +224 -0
  202. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/GateCheckValidator.cs +148 -0
  203. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/ValidationResult.cs +23 -0
  204. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/XsdValidator.cs +69 -0
  205. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.slnx +4 -0
  206. package/templates/.agent/skills/minimax-docx/scripts/env_check.sh +196 -0
  207. package/templates/.agent/skills/minimax-docx/scripts/setup.ps1 +274 -0
  208. package/templates/.agent/skills/minimax-docx/scripts/setup.sh +504 -0
  209. package/templates/.agent/skills/minimax-multimodal-toolkit/SKILL.md +359 -0
  210. package/templates/.agent/skills/minimax-pdf/README.md +222 -0
  211. package/templates/.agent/skills/minimax-pdf/SKILL.md +201 -0
  212. package/templates/.agent/skills/minimax-pdf/design/design.md +381 -0
  213. package/templates/.agent/skills/minimax-pdf/scripts/cover.py +1579 -0
  214. package/templates/.agent/skills/minimax-pdf/scripts/fill_inspect.py +200 -0
  215. package/templates/.agent/skills/minimax-pdf/scripts/fill_write.py +242 -0
  216. package/templates/.agent/skills/minimax-pdf/scripts/make.sh +491 -0
  217. package/templates/.agent/skills/minimax-pdf/scripts/merge.py +112 -0
  218. package/templates/.agent/skills/minimax-pdf/scripts/palette.py +559 -0
  219. package/templates/.agent/skills/minimax-pdf/scripts/reformat_parse.py +374 -0
  220. package/templates/.agent/skills/minimax-pdf/scripts/render_body.py +1055 -0
  221. package/templates/.agent/skills/minimax-pdf/scripts/render_cover.cjs +111 -0
  222. package/templates/.agent/skills/minimax-xlsx/SKILL.md +138 -0
  223. package/templates/.agent/skills/minimax-xlsx/references/create.md +691 -0
  224. package/templates/.agent/skills/minimax-xlsx/references/edit.md +684 -0
  225. package/templates/.agent/skills/minimax-xlsx/references/fix.md +37 -0
  226. package/templates/.agent/skills/minimax-xlsx/references/format.md +768 -0
  227. package/templates/.agent/skills/minimax-xlsx/references/ooxml-cheatsheet.md +231 -0
  228. package/templates/.agent/skills/minimax-xlsx/references/read-analyze.md +97 -0
  229. package/templates/.agent/skills/minimax-xlsx/references/validate.md +772 -0
  230. package/templates/.agent/skills/minimax-xlsx/scripts/formula_check.py +422 -0
  231. package/templates/.agent/skills/minimax-xlsx/scripts/libreoffice_recalc.py +248 -0
  232. package/templates/.agent/skills/minimax-xlsx/scripts/shared_strings_builder.py +163 -0
  233. package/templates/.agent/skills/minimax-xlsx/scripts/style_audit.py +575 -0
  234. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_add_column.py +395 -0
  235. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_insert_row.py +274 -0
  236. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_pack.py +87 -0
  237. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_reader.py +362 -0
  238. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_shift_rows.py +396 -0
  239. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_unpack.py +130 -0
  240. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/[Content_Types].xml +9 -0
  241. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/_rels/.rels +6 -0
  242. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/_rels/workbook.xml.rels +19 -0
  243. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/sharedStrings.xml +33 -0
  244. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/styles.xml +160 -0
  245. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/workbook.xml +30 -0
  246. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/worksheets/sheet1.xml +70 -0
  247. package/templates/.agent/skills/mobile-design/SKILL.md +394 -0
  248. package/templates/.agent/skills/mobile-design/decision-trees.md +516 -0
  249. package/templates/.agent/skills/mobile-design/mobile-backend.md +491 -0
  250. package/templates/.agent/skills/mobile-design/mobile-color-system.md +420 -0
  251. package/templates/.agent/skills/mobile-design/mobile-debugging.md +122 -0
  252. package/templates/.agent/skills/mobile-design/mobile-design-thinking.md +357 -0
  253. package/templates/.agent/skills/mobile-design/mobile-navigation.md +458 -0
  254. package/templates/.agent/skills/mobile-design/mobile-performance.md +767 -0
  255. package/templates/.agent/skills/mobile-design/mobile-testing.md +356 -0
  256. package/templates/.agent/skills/mobile-design/mobile-typography.md +433 -0
  257. package/templates/.agent/skills/mobile-design/platform-android.md +666 -0
  258. package/templates/.agent/skills/mobile-design/platform-ios.md +561 -0
  259. package/templates/.agent/skills/mobile-design/scripts/mobile_audit.py +670 -0
  260. package/templates/.agent/skills/mobile-design/touch-psychology.md +537 -0
  261. package/templates/.agent/skills/nestjs-expert/SKILL.md +552 -0
  262. package/templates/.agent/skills/nextjs-best-practices/SKILL.md +203 -0
  263. package/templates/.agent/skills/nodejs-best-practices/SKILL.md +333 -0
  264. package/templates/.agent/skills/parallel-agents/SKILL.md +175 -0
  265. package/templates/.agent/skills/performance-profiling/SKILL.md +143 -0
  266. package/templates/.agent/skills/performance-profiling/scripts/lighthouse_audit.py +76 -0
  267. package/templates/.agent/skills/plan-writing/SKILL.md +152 -0
  268. package/templates/.agent/skills/powershell-windows/SKILL.md +167 -0
  269. package/templates/.agent/skills/ppc-advertising/SKILL.md +183 -475
  270. package/templates/.agent/skills/pptx-generator/SKILL.md +249 -0
  271. package/templates/.agent/skills/pptx-generator/references/design-system.md +392 -0
  272. package/templates/.agent/skills/pptx-generator/references/editing.md +162 -0
  273. package/templates/.agent/skills/pptx-generator/references/pitfalls.md +112 -0
  274. package/templates/.agent/skills/pptx-generator/references/pptxgenjs.md +420 -0
  275. package/templates/.agent/skills/pptx-generator/references/slide-types.md +413 -0
  276. package/templates/.agent/skills/prisma-expert/SKILL.md +355 -0
  277. package/templates/.agent/skills/python-patterns/SKILL.md +441 -0
  278. package/templates/.agent/skills/react-patterns/SKILL.md +198 -0
  279. package/templates/.agent/skills/red-team-tactics/SKILL.md +199 -0
  280. package/templates/.agent/skills/remotion-best-practices/SKILL.md +45 -111
  281. package/templates/.agent/skills/remotion-best-practices/rules/3d.md +4 -4
  282. package/templates/.agent/skills/remotion-best-practices/rules/animations.md +5 -7
  283. package/templates/.agent/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  284. package/templates/.agent/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  285. package/templates/.agent/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +103 -0
  286. package/templates/.agent/skills/remotion-best-practices/rules/assets.md +78 -0
  287. package/templates/.agent/skills/remotion-best-practices/rules/audio-visualization.md +198 -0
  288. package/templates/.agent/skills/remotion-best-practices/rules/audio.md +1 -4
  289. package/templates/.agent/skills/remotion-best-practices/rules/calculate-metadata.md +47 -17
  290. package/templates/.agent/skills/remotion-best-practices/rules/can-decode.md +75 -0
  291. package/templates/.agent/skills/remotion-best-practices/rules/charts.md +80 -48
  292. package/templates/.agent/skills/remotion-best-practices/rules/compositions.md +22 -14
  293. package/templates/.agent/skills/remotion-best-practices/rules/display-captions.md +79 -21
  294. package/templates/.agent/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  295. package/templates/.agent/skills/remotion-best-practices/rules/ffmpeg.md +38 -0
  296. package/templates/.agent/skills/remotion-best-practices/rules/fonts.md +96 -54
  297. package/templates/.agent/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  298. package/templates/.agent/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  299. package/templates/.agent/skills/remotion-best-practices/rules/get-video-duration.md +60 -0
  300. package/templates/.agent/skills/remotion-best-practices/rules/gifs.md +21 -18
  301. package/templates/.agent/skills/remotion-best-practices/rules/images.md +6 -2
  302. package/templates/.agent/skills/remotion-best-practices/rules/import-srt-captions.md +69 -0
  303. package/templates/.agent/skills/remotion-best-practices/rules/light-leaks.md +73 -0
  304. package/templates/.agent/skills/remotion-best-practices/rules/lottie.md +10 -7
  305. package/templates/.agent/skills/remotion-best-practices/rules/maps.md +412 -0
  306. package/templates/.agent/skills/remotion-best-practices/rules/measuring-dom-nodes.md +34 -0
  307. package/templates/.agent/skills/remotion-best-practices/rules/measuring-text.md +140 -0
  308. package/templates/.agent/skills/remotion-best-practices/rules/parameters.md +109 -0
  309. package/templates/.agent/skills/remotion-best-practices/rules/sequencing.md +13 -1
  310. package/templates/.agent/skills/remotion-best-practices/rules/sfx.md +26 -0
  311. package/templates/.agent/skills/remotion-best-practices/rules/subtitles.md +36 -0
  312. package/templates/.agent/skills/remotion-best-practices/rules/tailwind.md +11 -0
  313. package/templates/.agent/skills/remotion-best-practices/rules/text-animations.md +4 -115
  314. package/templates/.agent/skills/remotion-best-practices/rules/timing.md +19 -19
  315. package/templates/.agent/skills/remotion-best-practices/rules/transcribe-captions.md +70 -0
  316. package/templates/.agent/skills/remotion-best-practices/rules/transitions.md +117 -42
  317. package/templates/.agent/skills/remotion-best-practices/rules/transparent-videos.md +106 -0
  318. package/templates/.agent/skills/remotion-best-practices/rules/trimming.md +51 -0
  319. package/templates/.agent/skills/remotion-best-practices/rules/voiceover.md +99 -0
  320. package/templates/.agent/skills/seo-fundamentals/SKILL.md +83 -441
  321. package/templates/.agent/skills/seo-fundamentals/scripts/seo_checker.py +219 -0
  322. package/templates/.agent/skills/server-management/SKILL.md +161 -0
  323. package/templates/.agent/skills/systematic-debugging/SKILL.md +109 -0
  324. package/templates/.agent/skills/tdd-workflow/SKILL.md +149 -0
  325. package/templates/.agent/skills/testing-patterns/SKILL.md +178 -0
  326. package/templates/.agent/skills/testing-patterns/scripts/test_runner.py +219 -0
  327. package/templates/.agent/skills/tutorial-video-expert/SKILL.md +88 -0
  328. package/templates/.agent/skills/typescript-expert/SKILL.md +429 -0
  329. package/templates/.agent/skills/ui-ux-pro-max/SKILL.md +1 -1
  330. package/templates/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -0
  331. package/templates/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -0
  332. package/templates/.agent/skills/ui-ux-pro-max/data/icons.csv +101 -0
  333. package/templates/.agent/skills/ui-ux-pro-max/data/landing.csv +31 -0
  334. package/templates/.agent/skills/ui-ux-pro-max/data/products.csv +97 -0
  335. package/templates/.agent/skills/ui-ux-pro-max/data/prompts.csv +24 -0
  336. package/templates/.agent/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  337. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  338. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  339. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  340. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  341. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  342. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  343. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  344. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  345. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  346. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  347. package/templates/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  348. package/templates/.agent/skills/ui-ux-pro-max/data/styles.csv +59 -0
  349. package/templates/.agent/skills/ui-ux-pro-max/data/typography.csv +58 -0
  350. package/templates/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  351. package/templates/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  352. package/templates/.agent/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  353. package/templates/.agent/skills/ui-ux-pro-max/scripts/core.py +257 -0
  354. package/templates/.agent/skills/ui-ux-pro-max/scripts/design_system.py +487 -0
  355. package/templates/.agent/skills/ui-ux-pro-max/scripts/search.py +76 -0
  356. package/templates/.agent/skills/vision-analysis/SKILL.md +174 -0
  357. package/templates/.agent/skills/vue-expert/SKILL.md +374 -0
  358. package/templates/.agent/skills/vulnerability-scanner/SKILL.md +276 -0
  359. package/templates/.agent/skills/vulnerability-scanner/checklists.md +121 -0
  360. package/templates/.agent/skills/vulnerability-scanner/scripts/security_scan.py +458 -0
  361. package/templates/.agent/skills/webapp-testing/SKILL.md +187 -0
  362. package/templates/.agent/skills/webapp-testing/scripts/playwright_runner.py +173 -0
  363. package/templates/.agent/workflows/analyze.md +3 -0
  364. package/templates/.agent/workflows/brainstorm.md +113 -0
  365. package/templates/.agent/workflows/brand-report.md +44 -0
  366. package/templates/.agent/workflows/create.md +59 -0
  367. package/templates/.agent/workflows/debug.md +103 -0
  368. package/templates/.agent/workflows/deploy.md +176 -0
  369. package/templates/.agent/workflows/enhance.md +63 -0
  370. package/templates/.agent/workflows/orchestrate.md +237 -0
  371. package/templates/.agent/workflows/plan.md +89 -0
  372. package/templates/.agent/workflows/preview.md +80 -0
  373. package/templates/.agent/workflows/report.md +49 -0
  374. package/templates/.agent/workflows/status.md +86 -0
  375. package/templates/.agent/workflows/test.md +144 -0
  376. package/templates/.agent/workflows/ui-ux-pro-max.md +231 -0
@@ -0,0 +1,395 @@
1
+ #!/usr/bin/env python3
2
+ # SPDX-License-Identifier: MIT
3
+ """
4
+ xlsx_add_column.py — Add a new column to a worksheet in an unpacked xlsx.
5
+
6
+ Usage examples:
7
+ # Add a percentage column with formulas and number format
8
+ python3 xlsx_add_column.py /tmp/work/ --col G \\
9
+ --sheet "Budget FY2025" \\
10
+ --header "% of Total" \\
11
+ --formula '=F{row}/$F$10' --formula-rows 2:9 \\
12
+ --total-row 10 --total-formula '=SUM(G2:G9)' \\
13
+ --numfmt '0.0%'
14
+
15
+ What it does:
16
+ 1. Adds header cell (copies style from previous column's header)
17
+ 2. Adds formula cells for the specified row range
18
+ 3. Adds a total formula cell if specified
19
+ 4. Creates a new cell style with the given numfmt if needed
20
+ 5. Updates sharedStrings.xml for header text
21
+ 6. Updates dimension ref and column definitions
22
+
23
+ IMPORTANT: Run on an UNPACKED directory (from xlsx_unpack.py).
24
+ After running, repack with xlsx_pack.py.
25
+ """
26
+
27
+ import argparse
28
+ import copy
29
+ import os
30
+ import re
31
+ import sys
32
+ import xml.dom.minidom
33
+ import xml.etree.ElementTree as ET
34
+
35
+ NS_SS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
36
+ NS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
37
+
38
+ ET.register_namespace('', NS_SS)
39
+ ET.register_namespace('r', NS_REL)
40
+ ET.register_namespace('xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing')
41
+ ET.register_namespace('x14', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main')
42
+ ET.register_namespace('xr2', 'http://schemas.microsoft.com/office/spreadsheetml/2015/revision2')
43
+ ET.register_namespace('mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006')
44
+
45
+
46
+ def _tag(local: str) -> str:
47
+ return f"{{{NS_SS}}}{local}"
48
+
49
+
50
+ def _write_tree(tree: ET.ElementTree, path: str) -> None:
51
+ tree.write(path, encoding="unicode", xml_declaration=False)
52
+ with open(path, "r", encoding="utf-8") as fh:
53
+ raw = fh.read()
54
+ try:
55
+ dom = xml.dom.minidom.parseString(raw.encode("utf-8"))
56
+ pretty = dom.toprettyxml(indent=" ", encoding="utf-8").decode("utf-8")
57
+ lines = [line for line in pretty.splitlines() if line.strip()]
58
+ with open(path, "w", encoding="utf-8") as fh:
59
+ fh.write("\n".join(lines) + "\n")
60
+ except Exception:
61
+ pass
62
+
63
+
64
+ def col_number(s: str) -> int:
65
+ n = 0
66
+ for c in s.upper():
67
+ n = n * 26 + (ord(c) - 64)
68
+ return n
69
+
70
+
71
+ def col_letter(n: int) -> str:
72
+ r = ""
73
+ while n > 0:
74
+ n, rem = divmod(n - 1, 26)
75
+ r = chr(65 + rem) + r
76
+ return r
77
+
78
+
79
+ def find_ws_path(work_dir: str, sheet_name: str | None) -> str:
80
+ wb_tree = ET.parse(os.path.join(work_dir, "xl", "workbook.xml"))
81
+ rid = None
82
+ for sheet in wb_tree.getroot().iter(_tag("sheet")):
83
+ if sheet_name is None or sheet.get("name") == sheet_name:
84
+ rid = sheet.get(f"{{{NS_REL}}}id")
85
+ break
86
+
87
+ if rid is None:
88
+ print(f"ERROR: Sheet not found: {sheet_name}")
89
+ sys.exit(1)
90
+
91
+ rels_tree = ET.parse(os.path.join(work_dir, "xl", "_rels", "workbook.xml.rels"))
92
+ for rel in rels_tree.getroot():
93
+ if rel.get("Id") == rid:
94
+ return os.path.join(work_dir, "xl", rel.get("Target"))
95
+
96
+ print(f"ERROR: Relationship not found: {rid}")
97
+ sys.exit(1)
98
+
99
+
100
+ def add_shared_string(work_dir: str, text: str) -> int:
101
+ ss_path = os.path.join(work_dir, "xl", "sharedStrings.xml")
102
+ tree = ET.parse(ss_path)
103
+ root = tree.getroot()
104
+
105
+ idx = 0
106
+ for si in root.findall(_tag("si")):
107
+ t_el = si.find(_tag("t"))
108
+ if t_el is not None and t_el.text == text:
109
+ return idx
110
+ idx += 1
111
+
112
+ si = ET.SubElement(root, _tag("si"))
113
+ t = ET.SubElement(si, _tag("t"))
114
+ t.set("{http://www.w3.org/XML/1998/namespace}space", "preserve")
115
+ t.text = text
116
+
117
+ root.set("count", str(int(root.get("count", "0")) + 1))
118
+ root.set("uniqueCount", str(int(root.get("uniqueCount", "0")) + 1))
119
+
120
+ _write_tree(tree, ss_path)
121
+ return idx
122
+
123
+
124
+ def get_cell_style(ws_tree: ET.ElementTree, col: str, row: int) -> int:
125
+ ref = f"{col}{row}"
126
+ for row_el in ws_tree.getroot().iter(_tag("row")):
127
+ if row_el.get("r") == str(row):
128
+ for c in row_el:
129
+ if c.get("r") == ref:
130
+ return int(c.get("s", "0"))
131
+ return 0
132
+
133
+
134
+ def ensure_numfmt_style(work_dir: str, ref_style_idx: int, numfmt_code: str) -> int:
135
+ """Clone a cellXfs entry with the given numfmt. Returns new style index."""
136
+ styles_path = os.path.join(work_dir, "xl", "styles.xml")
137
+ tree = ET.parse(styles_path)
138
+ root = tree.getroot()
139
+
140
+ # Find or add numFmt
141
+ numfmts = root.find(_tag("numFmts"))
142
+ numfmt_id = None
143
+ if numfmts is not None:
144
+ for nf in numfmts:
145
+ if nf.get("formatCode") == numfmt_code:
146
+ numfmt_id = int(nf.get("numFmtId"))
147
+ break
148
+
149
+ if numfmt_id is None:
150
+ max_id = 163
151
+ if numfmts is not None:
152
+ for nf in numfmts:
153
+ max_id = max(max_id, int(nf.get("numFmtId", "0")))
154
+ else:
155
+ numfmts = ET.SubElement(root, _tag("numFmts"))
156
+ numfmts.set("count", "0")
157
+ root.remove(numfmts)
158
+ root.insert(0, numfmts)
159
+
160
+ numfmt_id = max_id + 1
161
+ nf = ET.SubElement(numfmts, _tag("numFmt"))
162
+ nf.set("numFmtId", str(numfmt_id))
163
+ nf.set("formatCode", numfmt_code)
164
+ numfmts.set("count", str(len(list(numfmts))))
165
+
166
+ # Find or create cellXfs entry
167
+ cellxfs = root.find(_tag("cellXfs"))
168
+ xf_list = list(cellxfs)
169
+ ref_xf = xf_list[min(ref_style_idx, len(xf_list) - 1)]
170
+
171
+ for i, xf in enumerate(xf_list):
172
+ if (xf.get("numFmtId") == str(numfmt_id) and
173
+ xf.get("fontId") == ref_xf.get("fontId") and
174
+ xf.get("fillId") == ref_xf.get("fillId") and
175
+ xf.get("borderId") == ref_xf.get("borderId")):
176
+ return i
177
+
178
+ new_xf = copy.deepcopy(ref_xf)
179
+ new_xf.set("numFmtId", str(numfmt_id))
180
+ new_xf.set("applyNumberFormat", "true")
181
+ cellxfs.append(new_xf)
182
+ cellxfs.set("count", str(len(list(cellxfs))))
183
+
184
+ _write_tree(tree, styles_path)
185
+ return len(list(cellxfs)) - 1
186
+
187
+
188
+ def _apply_border_to_row(work_dir: str, ws_path: str, ws_tree: ET.ElementTree,
189
+ ws_root: ET.Element, row_map: dict, border_row: int,
190
+ border_style: str, new_col: str) -> None:
191
+ """Apply a top border to ALL cells in the specified row (A through new_col)."""
192
+ styles_path = os.path.join(work_dir, "xl", "styles.xml")
193
+ st_tree = ET.parse(styles_path)
194
+ st_root = st_tree.getroot()
195
+
196
+ # 1. Create a new border entry with the specified top style
197
+ borders = st_root.find(_tag("borders"))
198
+ new_border = ET.SubElement(borders, _tag("border"))
199
+ for side in ("left", "right"):
200
+ ET.SubElement(new_border, _tag(side))
201
+ top_el = ET.SubElement(new_border, _tag("top"))
202
+ top_el.set("style", border_style)
203
+ ET.SubElement(new_border, _tag("bottom"))
204
+ ET.SubElement(new_border, _tag("diagonal"))
205
+ borders.set("count", str(len(list(borders))))
206
+ new_border_id = len(list(borders)) - 1
207
+
208
+ # 2. For each existing style used in the row, create a clone with the new borderId
209
+ cellxfs = st_root.find(_tag("cellXfs"))
210
+ style_remap = {} # old_style_idx -> new_style_idx
211
+
212
+ if border_row not in row_map:
213
+ return
214
+
215
+ row_el = row_map[border_row]
216
+ # Collect all cells in this row and their styles
217
+ for c in row_el:
218
+ old_s = int(c.get("s", "0"))
219
+ if old_s not in style_remap:
220
+ xf_list = list(cellxfs)
221
+ ref_xf = xf_list[min(old_s, len(xf_list) - 1)]
222
+ new_xf = copy.deepcopy(ref_xf)
223
+ new_xf.set("borderId", str(new_border_id))
224
+ new_xf.set("applyBorder", "true")
225
+ cellxfs.append(new_xf)
226
+ cellxfs.set("count", str(len(list(cellxfs))))
227
+ style_remap[old_s] = len(list(cellxfs)) - 1
228
+
229
+ # 3. Apply remapped styles to all cells in the row
230
+ for c in row_el:
231
+ old_s = int(c.get("s", "0"))
232
+ if old_s in style_remap:
233
+ c.set("s", str(style_remap[old_s]))
234
+
235
+ _write_tree(st_tree, styles_path)
236
+ last_col_num = col_number(new_col)
237
+ print(f" Applied {border_style} top border to all cells in row {border_row} "
238
+ f"(A-{new_col}, {len(style_remap)} style(s) cloned)")
239
+
240
+
241
+ def main() -> None:
242
+ parser = argparse.ArgumentParser(
243
+ description="Add a column to a worksheet in an unpacked xlsx")
244
+ parser.add_argument("work_dir", help="Unpacked xlsx working directory")
245
+ parser.add_argument("--col", required=True, help="Column letter (e.g., G)")
246
+ parser.add_argument("--sheet", default=None, help="Sheet name (default: first)")
247
+ parser.add_argument("--header", default=None, help="Header text for row 1")
248
+ parser.add_argument("--formula", default=None,
249
+ help="Formula template with {row} placeholder")
250
+ parser.add_argument("--formula-rows", default=None,
251
+ help="Row range for formulas (e.g., 2:9)")
252
+ parser.add_argument("--total-row", type=int, default=None,
253
+ help="Row number for total formula")
254
+ parser.add_argument("--total-formula", default=None,
255
+ help="Formula for total row")
256
+ parser.add_argument("--numfmt", default=None,
257
+ help="Number format for data/total cells (e.g., 0.0%%)")
258
+ parser.add_argument("--border-row", type=int, default=None,
259
+ help="Row to apply a top border to ALL cells (e.g., 10)")
260
+ parser.add_argument("--border-style", default="medium",
261
+ help="Border style: thin, medium, thick (default: medium)")
262
+ args = parser.parse_args()
263
+
264
+ col = args.col.upper()
265
+ prev_col = col_letter(col_number(col) - 1) if col_number(col) > 1 else "A"
266
+
267
+ ws_path = find_ws_path(args.work_dir, args.sheet)
268
+ ws_tree = ET.parse(ws_path)
269
+ changes = 0
270
+
271
+ print(f"Adding column {col} to {os.path.basename(ws_path)}")
272
+
273
+ # Resolve styles from previous column
274
+ header_style = get_cell_style(ws_tree, prev_col, 1) if args.header else 0
275
+
276
+ data_style = None
277
+ if args.formula_rows:
278
+ start_row = int(args.formula_rows.split(":")[0])
279
+ ref = get_cell_style(ws_tree, prev_col, start_row)
280
+ data_style = (ensure_numfmt_style(args.work_dir, ref, args.numfmt)
281
+ if args.numfmt else ref)
282
+
283
+ total_style = None
284
+ if args.total_row:
285
+ ref = get_cell_style(ws_tree, prev_col, args.total_row)
286
+ total_style = (ensure_numfmt_style(args.work_dir, ref, args.numfmt)
287
+ if args.numfmt else ref)
288
+
289
+ # Add header to sharedStrings
290
+ header_idx = add_shared_string(args.work_dir, args.header) if args.header else None
291
+
292
+ # Re-parse worksheet (sharedStrings write may have changed state)
293
+ ws_tree = ET.parse(ws_path)
294
+ root = ws_tree.getroot()
295
+ sheet_data = root.find(_tag("sheetData"))
296
+
297
+ row_map = {}
298
+ for row_el in sheet_data:
299
+ r = row_el.get("r")
300
+ if r:
301
+ row_map[int(r)] = row_el
302
+
303
+ # Add header cell
304
+ if args.header and 1 in row_map:
305
+ cell = ET.SubElement(row_map[1], _tag("c"))
306
+ cell.set("r", f"{col}1")
307
+ cell.set("s", str(header_style))
308
+ cell.set("t", "s")
309
+ v = ET.SubElement(cell, _tag("v"))
310
+ v.text = str(header_idx)
311
+ changes += 1
312
+ print(f" {col}1 = \"{args.header}\" (header, style={header_style})")
313
+
314
+ # Add formula cells
315
+ if args.formula and args.formula_rows:
316
+ start, end = map(int, args.formula_rows.split(":"))
317
+ for row_num in range(start, end + 1):
318
+ if row_num not in row_map:
319
+ row_el = ET.SubElement(sheet_data, _tag("row"))
320
+ row_el.set("r", str(row_num))
321
+ row_map[row_num] = row_el
322
+
323
+ formula_text = args.formula.replace("{row}", str(row_num))
324
+ formula_text = formula_text.lstrip("=")
325
+ cell = ET.SubElement(row_map[row_num], _tag("c"))
326
+ cell.set("r", f"{col}{row_num}")
327
+ if data_style is not None:
328
+ cell.set("s", str(data_style))
329
+ f_el = ET.SubElement(cell, _tag("f"))
330
+ f_el.text = formula_text
331
+ changes += 1
332
+
333
+ print(f" {col}{start}:{col}{end} = formulas (style={data_style})")
334
+
335
+ # Add total formula
336
+ if args.total_row and args.total_formula:
337
+ if args.total_row not in row_map:
338
+ row_el = ET.SubElement(sheet_data, _tag("row"))
339
+ row_el.set("r", str(args.total_row))
340
+ row_map[args.total_row] = row_el
341
+
342
+ total_f = args.total_formula.lstrip("=")
343
+ cell = ET.SubElement(row_map[args.total_row], _tag("c"))
344
+ cell.set("r", f"{col}{args.total_row}")
345
+ if total_style is not None:
346
+ cell.set("s", str(total_style))
347
+ f_el = ET.SubElement(cell, _tag("f"))
348
+ f_el.text = total_f
349
+ changes += 1
350
+ print(f" {col}{args.total_row} = ={total_f} (style={total_style})")
351
+
352
+ # Update dimension
353
+ for dim in root.iter(_tag("dimension")):
354
+ old_ref = dim.get("ref", "")
355
+ if ":" in old_ref:
356
+ start_ref, end_ref = old_ref.split(":")
357
+ end_col_str = re.match(r"([A-Z]+)", end_ref).group(1)
358
+ end_row_str = re.search(r"(\d+)", end_ref).group(1)
359
+ if col_number(col) > col_number(end_col_str):
360
+ new_ref = f"{start_ref}:{col}{end_row_str}"
361
+ dim.set("ref", new_ref)
362
+ print(f" Dimension: {old_ref} → {new_ref}")
363
+
364
+ # Extend <cols> to cover new column
365
+ cols_el = root.find(_tag("cols"))
366
+ if cols_el is not None:
367
+ new_col_num = col_number(col)
368
+ covered = any(
369
+ int(c.get("min", "0")) <= new_col_num <= int(c.get("max", "0"))
370
+ for c in cols_el
371
+ )
372
+ if not covered:
373
+ prev_num = col_number(prev_col)
374
+ for c in cols_el:
375
+ if int(c.get("min", "0")) <= prev_num <= int(c.get("max", "0")):
376
+ new_col_def = copy.deepcopy(c)
377
+ new_col_def.set("min", str(new_col_num))
378
+ new_col_def.set("max", str(new_col_num))
379
+ cols_el.append(new_col_def)
380
+ print(f" Added <col> definition for column {col}")
381
+ break
382
+
383
+ # Apply border to entire row if requested
384
+ if args.border_row:
385
+ _apply_border_to_row(args.work_dir, ws_path, ws_tree, root,
386
+ row_map, args.border_row, args.border_style,
387
+ col)
388
+
389
+ _write_tree(ws_tree, ws_path)
390
+ print(f"\nDone. {changes} cells added.")
391
+ print(f"\nNext: python3 xlsx_pack.py {args.work_dir} output.xlsx")
392
+
393
+
394
+ if __name__ == "__main__":
395
+ main()
@@ -0,0 +1,274 @@
1
+ #!/usr/bin/env python3
2
+ # SPDX-License-Identifier: MIT
3
+ """
4
+ xlsx_insert_row.py — Insert a new data row into a worksheet in an unpacked xlsx.
5
+
6
+ Usage examples:
7
+ # Insert "Utilities" row at position 6, copying styles from row 5
8
+ python3 xlsx_insert_row.py /tmp/work/ --at 6 \\
9
+ --sheet "Budget FY2025" \\
10
+ --text A=Utilities \\
11
+ --values B=3000 C=3000 D=3500 E=3500 \\
12
+ --formula 'F=SUM(B{row}:E{row})' \\
13
+ --copy-style-from 5
14
+
15
+ What it does:
16
+ 1. Shifts all rows >= at down by 1 (calls xlsx_shift_rows.py)
17
+ 2. Adds text values to sharedStrings.xml
18
+ 3. Inserts new row with specified cells (text, numbers, formulas)
19
+ 4. Copies cell styles from a reference row
20
+ 5. Updates dimension ref
21
+
22
+ The shift operation automatically expands SUM formulas that span the
23
+ insertion point, so total-row formulas are updated without extra work.
24
+
25
+ IMPORTANT: Run on an UNPACKED directory (from xlsx_unpack.py).
26
+ After running, repack with xlsx_pack.py.
27
+ """
28
+
29
+ import argparse
30
+ import os
31
+ import re
32
+ import subprocess
33
+ import sys
34
+ import xml.dom.minidom
35
+ import xml.etree.ElementTree as ET
36
+
37
+ NS_SS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
38
+ NS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
39
+
40
+ ET.register_namespace('', NS_SS)
41
+ ET.register_namespace('r', NS_REL)
42
+ ET.register_namespace('xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing')
43
+ ET.register_namespace('x14', 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/main')
44
+ ET.register_namespace('xr2', 'http://schemas.microsoft.com/office/spreadsheetml/2015/revision2')
45
+ ET.register_namespace('mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006')
46
+
47
+
48
+ def _tag(local: str) -> str:
49
+ return f"{{{NS_SS}}}{local}"
50
+
51
+
52
+ def _write_tree(tree: ET.ElementTree, path: str) -> None:
53
+ tree.write(path, encoding="unicode", xml_declaration=False)
54
+ with open(path, "r", encoding="utf-8") as fh:
55
+ raw = fh.read()
56
+ try:
57
+ dom = xml.dom.minidom.parseString(raw.encode("utf-8"))
58
+ pretty = dom.toprettyxml(indent=" ", encoding="utf-8").decode("utf-8")
59
+ lines = [line for line in pretty.splitlines() if line.strip()]
60
+ with open(path, "w", encoding="utf-8") as fh:
61
+ fh.write("\n".join(lines) + "\n")
62
+ except Exception:
63
+ pass
64
+
65
+
66
+ def col_number(s: str) -> int:
67
+ n = 0
68
+ for c in s.upper():
69
+ n = n * 26 + (ord(c) - 64)
70
+ return n
71
+
72
+
73
+ def find_ws_path(work_dir: str, sheet_name: str | None) -> str:
74
+ wb_tree = ET.parse(os.path.join(work_dir, "xl", "workbook.xml"))
75
+ rid = None
76
+ for sheet in wb_tree.getroot().iter(_tag("sheet")):
77
+ if sheet_name is None or sheet.get("name") == sheet_name:
78
+ rid = sheet.get(f"{{{NS_REL}}}id")
79
+ break
80
+
81
+ if rid is None:
82
+ print(f"ERROR: Sheet not found: {sheet_name}")
83
+ sys.exit(1)
84
+
85
+ rels_tree = ET.parse(os.path.join(work_dir, "xl", "_rels", "workbook.xml.rels"))
86
+ for rel in rels_tree.getroot():
87
+ if rel.get("Id") == rid:
88
+ return os.path.join(work_dir, "xl", rel.get("Target"))
89
+
90
+ print(f"ERROR: Relationship not found: {rid}")
91
+ sys.exit(1)
92
+
93
+
94
+ def add_shared_string(work_dir: str, text: str) -> int:
95
+ ss_path = os.path.join(work_dir, "xl", "sharedStrings.xml")
96
+ tree = ET.parse(ss_path)
97
+ root = tree.getroot()
98
+
99
+ idx = 0
100
+ for si in root.findall(_tag("si")):
101
+ t_el = si.find(_tag("t"))
102
+ if t_el is not None and t_el.text == text:
103
+ return idx
104
+ idx += 1
105
+
106
+ si = ET.SubElement(root, _tag("si"))
107
+ t = ET.SubElement(si, _tag("t"))
108
+ t.set("{http://www.w3.org/XML/1998/namespace}space", "preserve")
109
+ t.text = text
110
+
111
+ root.set("count", str(int(root.get("count", "0")) + 1))
112
+ root.set("uniqueCount", str(int(root.get("uniqueCount", "0")) + 1))
113
+
114
+ _write_tree(tree, ss_path)
115
+ return idx
116
+
117
+
118
+ def get_row_styles(ws_tree: ET.ElementTree, row_num: int) -> dict[str, int]:
119
+ """Get {col_letter: style_index} for all cells in a row."""
120
+ styles = {}
121
+ for row_el in ws_tree.getroot().iter(_tag("row")):
122
+ if row_el.get("r") == str(row_num):
123
+ for c in row_el:
124
+ ref = c.get("r", "")
125
+ col_str = re.match(r"([A-Z]+)", ref)
126
+ if col_str:
127
+ styles[col_str.group(1)] = int(c.get("s", "0"))
128
+ break
129
+ return styles
130
+
131
+
132
+ def parse_kv(specs: list[str] | None) -> dict[str, str]:
133
+ if not specs:
134
+ return {}
135
+ result = {}
136
+ for spec in specs:
137
+ col, _, val = spec.partition("=")
138
+ result[col.upper()] = val
139
+ return result
140
+
141
+
142
+ def main() -> None:
143
+ parser = argparse.ArgumentParser(
144
+ description="Insert a new row into a worksheet in an unpacked xlsx")
145
+ parser.add_argument("work_dir", help="Unpacked xlsx working directory")
146
+ parser.add_argument("--at", type=int, required=True,
147
+ help="Row number to insert at (existing rows shift down)")
148
+ parser.add_argument("--sheet", default=None, help="Sheet name (default: first)")
149
+ parser.add_argument("--text", nargs="+", default=None,
150
+ help="Text cells: COL=VALUE (e.g., A=Utilities)")
151
+ parser.add_argument("--values", nargs="+", default=None,
152
+ help="Numeric cells: COL=VALUE (e.g., B=3000 C=3000)")
153
+ parser.add_argument("--formula", nargs="+", default=None,
154
+ help="Formula cells: COL=FORMULA with {row} (e.g., F=SUM(B{row}:E{row}))")
155
+ parser.add_argument("--copy-style-from", type=int, default=None,
156
+ help="Copy cell styles from this row number")
157
+ args = parser.parse_args()
158
+
159
+ at = args.at
160
+ text_cells = parse_kv(args.text)
161
+ num_cells = parse_kv(args.values)
162
+ formula_cells = parse_kv(args.formula)
163
+
164
+ # Step 1: Shift rows down using xlsx_shift_rows.py
165
+ script_dir = os.path.dirname(os.path.abspath(__file__))
166
+ shift_script = os.path.join(script_dir, "xlsx_shift_rows.py")
167
+
168
+ print(f"Step 1: Shifting rows >= {at} down by 1...")
169
+ result = subprocess.run(
170
+ [sys.executable, shift_script, args.work_dir, "insert", str(at), "1"],
171
+ capture_output=True, text=True,
172
+ )
173
+ if result.returncode != 0:
174
+ print(f"ERROR: shift_rows failed:\n{result.stderr}")
175
+ sys.exit(1)
176
+ print(result.stdout)
177
+
178
+ # Step 2: Resolve worksheet path and get reference styles
179
+ ws_path = find_ws_path(args.work_dir, args.sheet)
180
+ ws_tree = ET.parse(ws_path)
181
+
182
+ ref_styles = {}
183
+ if args.copy_style_from is not None:
184
+ ref_styles = get_row_styles(ws_tree, args.copy_style_from)
185
+ print(f"Step 2: Copied styles from row {args.copy_style_from}: {ref_styles}")
186
+
187
+ # Step 3: Add text values to sharedStrings
188
+ text_indices = {}
189
+ for col, text in text_cells.items():
190
+ text_indices[col] = add_shared_string(args.work_dir, text)
191
+ print(f" Added shared string: \"{text}\" → index {text_indices[col]}")
192
+
193
+ # Step 4: Re-parse worksheet and build new row
194
+ ws_tree = ET.parse(ws_path)
195
+ root = ws_tree.getroot()
196
+ sheet_data = root.find(_tag("sheetData"))
197
+
198
+ new_row = ET.Element(_tag("row"))
199
+ new_row.set("r", str(at))
200
+
201
+ all_cols = sorted(
202
+ set(list(text_cells) + list(num_cells) + list(formula_cells)),
203
+ key=col_number,
204
+ )
205
+
206
+ for col in all_cols:
207
+ cell = ET.SubElement(new_row, _tag("c"))
208
+ cell.set("r", f"{col}{at}")
209
+
210
+ if col in ref_styles:
211
+ cell.set("s", str(ref_styles[col]))
212
+
213
+ if col in text_cells:
214
+ cell.set("t", "s")
215
+ v = ET.SubElement(cell, _tag("v"))
216
+ v.text = str(text_indices[col])
217
+ elif col in num_cells:
218
+ # Omit t attribute for numbers — "n" is the default per OOXML spec
219
+ v = ET.SubElement(cell, _tag("v"))
220
+ v.text = str(num_cells[col])
221
+ elif col in formula_cells:
222
+ formula_text = formula_cells[col].replace("{row}", str(at)).lstrip("=")
223
+ f_el = ET.SubElement(cell, _tag("f"))
224
+ f_el.text = formula_text
225
+ # Use formula style from reference if available; it may differ
226
+ # from the data style (e.g., black font vs blue font).
227
+ # Look for the formula column's style specifically.
228
+ if col in ref_styles:
229
+ cell.set("s", str(ref_styles[col]))
230
+
231
+ # Insert new row at the correct position in sheetData (sorted by row number)
232
+ insert_idx = 0
233
+ for i, row_el in enumerate(list(sheet_data)):
234
+ r = row_el.get("r")
235
+ if r and int(r) > at:
236
+ insert_idx = i
237
+ break
238
+ insert_idx = i + 1
239
+
240
+ sheet_data.insert(insert_idx, new_row)
241
+
242
+ print(f"\nStep 3: Inserted row {at} with {len(all_cols)} cells:")
243
+ for col in all_cols:
244
+ if col in text_cells:
245
+ print(f" {col}{at} = \"{text_cells[col]}\" (text)")
246
+ elif col in num_cells:
247
+ print(f" {col}{at} = {num_cells[col]} (number)")
248
+ elif col in formula_cells:
249
+ ftext = formula_cells[col].replace("{row}", str(at))
250
+ print(f" {col}{at} = {ftext} (formula)")
251
+
252
+ # Step 5: Update dimension
253
+ for dim in root.iter(_tag("dimension")):
254
+ old_ref = dim.get("ref", "")
255
+ if ":" in old_ref:
256
+ start_ref, end_ref = old_ref.split(":")
257
+ end_row = int(re.search(r"(\d+)", end_ref).group(1))
258
+ end_col = re.match(r"([A-Z]+)", end_ref).group(1)
259
+ # Dimension was already shifted by shift_rows, just verify
260
+ max_col = max(col_number(end_col), max(col_number(c) for c in all_cols))
261
+ max_col_letter = end_col if col_number(end_col) >= max_col else col
262
+ new_ref = f"{start_ref}:{max_col_letter}{end_row}"
263
+ if new_ref != old_ref:
264
+ dim.set("ref", new_ref)
265
+ print(f"\n Dimension: {old_ref} → {new_ref}")
266
+
267
+ _write_tree(ws_tree, ws_path)
268
+
269
+ print(f"\nDone. Row {at} inserted successfully.")
270
+ print(f"\nNext: python3 xlsx_pack.py {args.work_dir} output.xlsx")
271
+
272
+
273
+ if __name__ == "__main__":
274
+ main()