@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,1487 @@
1
+ using DocumentFormat.OpenXml;
2
+ using DocumentFormat.OpenXml.Packaging;
3
+ using DocumentFormat.OpenXml.Wordprocessing;
4
+ using MiniMaxAIDocx.Core.OpenXml;
5
+
6
+ namespace MiniMaxAIDocx.Core.Samples;
7
+
8
+ /// <summary>
9
+ /// Compilable reference examples for the OpenXML style system.
10
+ /// Demonstrates style creation, inheritance, CJK styles, academic formatting,
11
+ /// style import, and effective formatting resolution.
12
+ ///
13
+ /// KEY CONCEPT — Style Inheritance Chain:
14
+ /// docDefaults → basedOn chain → style rPr/pPr → direct formatting (in paragraph/run)
15
+ /// Each level overrides only the properties it explicitly sets.
16
+ /// "StyleRunProperties" (rPr inside a style) vs "RunProperties" (rPr inside a run) are
17
+ /// different classes that produce the same XML element name but at different tree positions.
18
+ /// </summary>
19
+ public static class StyleSystemSamples
20
+ {
21
+ // ────────────────────────────────────────────────────────────────────
22
+ // 1. BASIC STYLES (Normal + Headings + Title + Subtitle)
23
+ // ────────────────────────────────────────────────────────────────────
24
+
25
+ /// <summary>
26
+ /// Creates the core set of paragraph styles: Normal (default), Heading1–6, Title, Subtitle.
27
+ /// Demonstrates the basedOn inheritance chain and outlineLevel for TOC integration.
28
+ /// </summary>
29
+ /// <remarks>
30
+ /// Style inheritance for headings:
31
+ /// Normal (default paragraph style)
32
+ /// └─ Heading1 (basedOn: Normal, outlineLevel: 0)
33
+ /// └─ Heading2 (basedOn: Heading1? NO — basedOn: Normal, outlineLevel: 1)
34
+ ///
35
+ /// WARNING: Word's built-in headings all use basedOn="Normal", NOT a chain like
36
+ /// Heading2→Heading1. This is because each heading level has completely different
37
+ /// formatting. Using a chain would cause unwanted inheritance.
38
+ ///
39
+ /// XML produced for Heading1:
40
+ /// <code>
41
+ /// &lt;w:style w:type="paragraph" w:styleId="Heading1"&gt;
42
+ /// &lt;w:name w:val="heading 1"/&gt;
43
+ /// &lt;w:basedOn w:val="Normal"/&gt;
44
+ /// &lt;w:next w:val="Normal"/&gt;
45
+ /// &lt;w:link w:val="Heading1Char"/&gt;
46
+ /// &lt;w:uiPriority w:val="9"/&gt;
47
+ /// &lt;w:qFormat/&gt;
48
+ /// &lt;w:pPr&gt;
49
+ /// &lt;w:keepNext/&gt;
50
+ /// &lt;w:keepLines/&gt;
51
+ /// &lt;w:spacing w:before="240"/&gt;
52
+ /// &lt;w:outlineLvl w:val="0"/&gt;
53
+ /// &lt;/w:pPr&gt;
54
+ /// &lt;w:rPr&gt;
55
+ /// &lt;w:rFonts w:asciiTheme="majorHAnsi" w:hAnsiTheme="majorHAnsi"/&gt;
56
+ /// &lt;w:color w:val="2F5496" w:themeColor="accent1" w:themeShade="BF"/&gt;
57
+ /// &lt;w:sz w:val="32"/&gt;
58
+ /// &lt;/w:rPr&gt;
59
+ /// &lt;/w:style&gt;
60
+ /// </code>
61
+ /// </remarks>
62
+ public static void CreateBasicStyles(StyleDefinitionsPart stylesPart)
63
+ {
64
+ stylesPart.Styles ??= new Styles();
65
+ var styles = stylesPart.Styles;
66
+
67
+ // ── "Normal" — the default paragraph style ──
68
+ // IMPORTANT: Exactly one paragraph style should have Default="1".
69
+ // All other paragraph styles inherit from Normal unless they specify a different basedOn.
70
+ styles.Append(new Style(
71
+ new StyleName { Val = "Normal" },
72
+ // UiPriority controls the sort order in Word's Styles pane
73
+ new UIPriority { Val = 0 },
74
+ // qFormat makes the style appear in the Quick Styles gallery
75
+ new PrimaryStyle(),
76
+ new StyleParagraphProperties(
77
+ new SpacingBetweenLines
78
+ {
79
+ After = "160", // 8pt after paragraph (in DXA twentieths-of-a-point)
80
+ Line = "259", // ~1.08 line spacing (in 240ths for auto rule)
81
+ LineRule = LineSpacingRuleValues.Auto
82
+ }
83
+ ),
84
+ new StyleRunProperties(
85
+ // IMPORTANT: StyleRunProperties (w:rPr inside w:style) is different from
86
+ // RunProperties (w:rPr inside w:r). They produce the same XML tag name
87
+ // but are different C# classes. Using the wrong one will compile but
88
+ // may place elements in the wrong location.
89
+ new RunFonts
90
+ {
91
+ Ascii = "Calibri",
92
+ HighAnsi = "Calibri",
93
+ EastAsia = "SimSun",
94
+ ComplexScript = "Arial"
95
+ },
96
+ new FontSize { Val = "22" }, // 11pt (in half-points)
97
+ new FontSizeComplexScript { Val = "22" },
98
+ new Languages { Val = "en-US", EastAsia = "zh-CN" }
99
+ )
100
+ )
101
+ {
102
+ Type = StyleValues.Paragraph,
103
+ StyleId = "Normal",
104
+ Default = true // This is THE default paragraph style
105
+ });
106
+
107
+ // ── Heading styles 1–6 ──
108
+ // Each heading has:
109
+ // - basedOn: Normal (inherit base formatting)
110
+ // - next: Normal (pressing Enter after heading returns to Normal)
111
+ // - outlineLvl: 0–5 (determines TOC level; outlineLvl 0 = TOC level 1)
112
+ // - keepNext + keepLines (prevent orphaned headings)
113
+ // - link to a character style for inline use
114
+
115
+ var headingConfigs = new[]
116
+ {
117
+ // (StyleId, Name, SizePt, outlineLevel, Color, Bold, SpaceBefore)
118
+ ("Heading1", "heading 1", 16.0, 0, "2F5496", true, 240),
119
+ ("Heading2", "heading 2", 13.0, 1, "2F5496", true, 40),
120
+ ("Heading3", "heading 3", 12.0, 2, "1F3864", true, 40),
121
+ ("Heading4", "heading 4", 11.0, 3, "2F5496", true, 40),
122
+ ("Heading5", "heading 5", 11.0, 4, "2F5496", false, 40),
123
+ ("Heading6", "heading 6", 11.0, 5, "1F3864", false, 40),
124
+ };
125
+
126
+ foreach (var (id, name, sizePt, level, color, bold, spaceBefore) in headingConfigs)
127
+ {
128
+ var style = new Style
129
+ {
130
+ Type = StyleValues.Paragraph,
131
+ StyleId = id
132
+ };
133
+
134
+ style.Append(new StyleName { Val = name });
135
+ // basedOn: all headings inherit from Normal
136
+ style.Append(new BasedOn { Val = "Normal" });
137
+ // next: pressing Enter after this style creates a Normal paragraph
138
+ style.Append(new NextParagraphStyle { Val = "Normal" });
139
+ // link: connects this paragraph style to its character style counterpart
140
+ style.Append(new LinkedStyle { Val = id + "Char" });
141
+ // uiPriority 9 = high visibility in Styles pane
142
+ style.Append(new UIPriority { Val = 9 });
143
+ // qFormat = show in Quick Styles gallery on the Home ribbon
144
+ style.Append(new PrimaryStyle());
145
+
146
+ // Paragraph properties for headings
147
+ var pPr = new StyleParagraphProperties(
148
+ // keepNext: don't allow a page break between this heading and the next paragraph
149
+ new KeepNext(),
150
+ // keepLines: don't split this paragraph across pages
151
+ new KeepLines(),
152
+ new SpacingBetweenLines
153
+ {
154
+ Before = spaceBefore.ToString(), // space before in DXA
155
+ After = "0" // no space after heading
156
+ },
157
+ // outlineLvl: 0-based; determines the heading's level in:
158
+ // - Table of Contents (TOC)
159
+ // - Navigation Pane
160
+ // - Document outline
161
+ // IMPORTANT: outlineLvl 0 = "Level 1" in Word's UI
162
+ new OutlineLevel { Val = level }
163
+ );
164
+ style.Append(pPr);
165
+
166
+ // Run properties for the heading text appearance
167
+ var rPr = new StyleRunProperties(
168
+ new RunFonts
169
+ {
170
+ // "majorHAnsi" theme font slot = the theme's heading font (e.g. Calibri Light)
171
+ AsciiTheme = ThemeFontValues.MajorHighAnsi,
172
+ HighAnsiTheme = ThemeFontValues.MajorHighAnsi,
173
+ EastAsiaTheme = ThemeFontValues.MajorEastAsia,
174
+ ComplexScriptTheme = ThemeFontValues.MajorBidi
175
+ },
176
+ new Color
177
+ {
178
+ Val = color,
179
+ // themeColor + themeShade: if a theme is applied, Word uses these
180
+ // instead of the literal Val. The Val acts as a fallback.
181
+ ThemeColor = ThemeColorValues.Accent1,
182
+ ThemeShade = "BF"
183
+ },
184
+ // Font size in half-points
185
+ new FontSize { Val = ((int)(sizePt * 2)).ToString() },
186
+ new FontSizeComplexScript { Val = ((int)(sizePt * 2)).ToString() }
187
+ );
188
+
189
+ if (bold)
190
+ {
191
+ // IMPORTANT: For Bold in a style, just include the element with no Val.
192
+ // <w:b/> means true. <w:b w:val="false"/> means explicitly NOT bold.
193
+ rPr.Append(new Bold());
194
+ rPr.Append(new BoldComplexScript());
195
+ }
196
+
197
+ style.Append(rPr);
198
+ styles.Append(style);
199
+
200
+ // ── Linked character style ──
201
+ // A "linked" character style lets users apply heading formatting to
202
+ // inline text without changing the paragraph style.
203
+ // It must have the same rPr as the paragraph style.
204
+ var charStyle = new Style
205
+ {
206
+ Type = StyleValues.Character,
207
+ StyleId = id + "Char",
208
+ CustomStyle = true
209
+ };
210
+ charStyle.Append(new StyleName { Val = name + " Char" });
211
+ charStyle.Append(new BasedOn { Val = "DefaultParagraphFont" });
212
+ charStyle.Append(new LinkedStyle { Val = id });
213
+ charStyle.Append(new UIPriority { Val = 9 });
214
+ charStyle.Append((StyleRunProperties)rPr.CloneNode(true));
215
+ styles.Append(charStyle);
216
+ }
217
+
218
+ // ── "Title" style ──
219
+ styles.Append(new Style(
220
+ new StyleName { Val = "Title" },
221
+ new BasedOn { Val = "Normal" },
222
+ new NextParagraphStyle { Val = "Normal" },
223
+ new UIPriority { Val = 10 },
224
+ new PrimaryStyle(),
225
+ new StyleParagraphProperties(
226
+ new SpacingBetweenLines { After = "0", Line = "240", LineRule = LineSpacingRuleValues.Auto },
227
+ new Justification { Val = JustificationValues.Center }
228
+ ),
229
+ new StyleRunProperties(
230
+ new RunFonts
231
+ {
232
+ AsciiTheme = ThemeFontValues.MajorHighAnsi,
233
+ HighAnsiTheme = ThemeFontValues.MajorHighAnsi,
234
+ EastAsiaTheme = ThemeFontValues.MajorEastAsia,
235
+ ComplexScriptTheme = ThemeFontValues.MajorBidi
236
+ },
237
+ new FontSize { Val = "56" }, // 28pt
238
+ new FontSizeComplexScript { Val = "56" },
239
+ // Spacing = character spacing expansion in DXA twentieths-of-a-point
240
+ // Negative = condensed, Positive = expanded
241
+ new Spacing { Val = -10 }, // slight condensing
242
+ new Kern { Val = (UInt32Value)28U } // kern at 28 half-pt (14pt) and above
243
+ )
244
+ )
245
+ {
246
+ Type = StyleValues.Paragraph,
247
+ StyleId = "Title"
248
+ });
249
+
250
+ // ── "Subtitle" style ──
251
+ styles.Append(new Style(
252
+ new StyleName { Val = "Subtitle" },
253
+ new BasedOn { Val = "Normal" },
254
+ new NextParagraphStyle { Val = "Normal" },
255
+ new UIPriority { Val = 11 },
256
+ new PrimaryStyle(),
257
+ new StyleParagraphProperties(
258
+ new SpacingBetweenLines { After = "160" },
259
+ new Justification { Val = JustificationValues.Center }
260
+ ),
261
+ new StyleRunProperties(
262
+ new RunFonts
263
+ {
264
+ EastAsiaTheme = ThemeFontValues.MinorEastAsia
265
+ },
266
+ new Color
267
+ {
268
+ Val = "5A5A5A",
269
+ ThemeColor = ThemeColorValues.Text1,
270
+ ThemeTint = "A6"
271
+ },
272
+ new FontSize { Val = "24" }, // 12pt
273
+ new FontSizeComplexScript { Val = "24" },
274
+ new Spacing { Val = 15 } // slight expansion
275
+ )
276
+ )
277
+ {
278
+ Type = StyleValues.Paragraph,
279
+ StyleId = "Subtitle"
280
+ });
281
+
282
+ styles.Save();
283
+ }
284
+
285
+ // ────────────────────────────────────────────────────────────────────
286
+ // 2. CHARACTER STYLE (bold + red, linked to paragraph style)
287
+ // ────────────────────────────────────────────────────────────────────
288
+
289
+ /// <summary>
290
+ /// Creates a character style "StrongAccent" that applies bold + red formatting.
291
+ /// Also creates a linked paragraph style to show the link mechanism.
292
+ /// </summary>
293
+ /// <remarks>
294
+ /// Character styles:
295
+ /// - Type = StyleValues.Character
296
+ /// - Only contain rPr (run properties), never pPr
297
+ /// - Applied via &lt;w:rPr&gt;&lt;w:rStyle w:val="StrongAccent"/&gt;&lt;/w:rPr&gt; on a Run
298
+ /// - Can be "linked" to a paragraph style: when the entire paragraph uses the para
299
+ /// style, Word shows the char style name; when only a run uses it, same formatting
300
+ ///
301
+ /// XML produced:
302
+ /// <code>
303
+ /// &lt;w:style w:type="character" w:styleId="StrongAccent"&gt;
304
+ /// &lt;w:name w:val="Strong Accent"/&gt;
305
+ /// &lt;w:basedOn w:val="DefaultParagraphFont"/&gt;
306
+ /// &lt;w:uiPriority w:val="22"/&gt;
307
+ /// &lt;w:qFormat/&gt;
308
+ /// &lt;w:rPr&gt;
309
+ /// &lt;w:b/&gt;
310
+ /// &lt;w:bCs/&gt;
311
+ /// &lt;w:color w:val="FF0000"/&gt;
312
+ /// &lt;/w:rPr&gt;
313
+ /// &lt;/w:style&gt;
314
+ /// </code>
315
+ /// </remarks>
316
+ public static void CreateCharacterStyle(StyleDefinitionsPart stylesPart)
317
+ {
318
+ stylesPart.Styles ??= new Styles();
319
+
320
+ // ── Character style ──
321
+ var charStyle = new Style
322
+ {
323
+ Type = StyleValues.Character,
324
+ StyleId = "StrongAccent",
325
+ // CustomStyle = true means this is not a built-in Word style.
326
+ // Built-in styles (like "Strong") have this as false/omitted.
327
+ CustomStyle = true
328
+ };
329
+
330
+ charStyle.Append(new StyleName { Val = "Strong Accent" });
331
+ // IMPORTANT: Character styles should be basedOn "DefaultParagraphFont"
332
+ // (the implicit base for all character styles), NOT on another named style,
333
+ // unless you specifically want to inherit from it.
334
+ charStyle.Append(new BasedOn { Val = "DefaultParagraphFont" });
335
+ charStyle.Append(new UIPriority { Val = 22 });
336
+ charStyle.Append(new PrimaryStyle()); // show in Quick Styles gallery
337
+ // Link to the paragraph style counterpart
338
+ charStyle.Append(new LinkedStyle { Val = "StrongAccentPara" });
339
+
340
+ charStyle.Append(new StyleRunProperties(
341
+ new Bold(),
342
+ new BoldComplexScript(),
343
+ new Color { Val = "FF0000" }, // pure red; no # prefix in OpenXML
344
+ new Underline { Val = UnderlineValues.None } // explicitly no underline
345
+ ));
346
+
347
+ stylesPart.Styles.Append(charStyle);
348
+
349
+ // ── Linked paragraph style ──
350
+ // When a paragraph style and character style are "linked", Word treats them
351
+ // as two views of the same formatting. If a whole paragraph uses the para
352
+ // style, Word displays it as the char style in the UI.
353
+ var paraStyle = new Style
354
+ {
355
+ Type = StyleValues.Paragraph,
356
+ StyleId = "StrongAccentPara",
357
+ CustomStyle = true
358
+ };
359
+
360
+ paraStyle.Append(new StyleName { Val = "Strong Accent Paragraph" });
361
+ paraStyle.Append(new BasedOn { Val = "Normal" });
362
+ paraStyle.Append(new LinkedStyle { Val = "StrongAccent" });
363
+ paraStyle.Append(new UIPriority { Val = 22 });
364
+
365
+ // The paragraph style carries the same rPr as the character style
366
+ paraStyle.Append(new StyleRunProperties(
367
+ new Bold(),
368
+ new BoldComplexScript(),
369
+ new Color { Val = "FF0000" }
370
+ ));
371
+
372
+ stylesPart.Styles.Append(paraStyle);
373
+ stylesPart.Styles.Save();
374
+ }
375
+
376
+ // ────────────────────────────────────────────────────────────────────
377
+ // 3. TABLE STYLE (header row, banded rows)
378
+ // ────────────────────────────────────────────────────────────────────
379
+
380
+ /// <summary>
381
+ /// Creates a table style with conditional formatting for header row,
382
+ /// banded (alternating) rows, and first column highlighting.
383
+ /// </summary>
384
+ /// <remarks>
385
+ /// Table styles use "conditional formatting" (tblStylePr) to vary appearance
386
+ /// by region. Each region type is identified by a TableStyleOverrideValues enum:
387
+ /// FirstRow, LastRow, FirstColumn, LastColumn,
388
+ /// Band1Vertical, Band2Vertical, Band1Horizontal, Band2Horizontal,
389
+ /// NorthEastCell, NorthWestCell, SouthEastCell, SouthWestCell
390
+ ///
391
+ /// The table must opt-in to conditional formatting via w:tblLook:
392
+ /// <code>
393
+ /// &lt;w:tblLook w:val="04A0" w:firstRow="1" w:lastRow="0"
394
+ /// w:firstColumn="1" w:lastColumn="0" w:noHBand="0" w:noVBand="1"/&gt;
395
+ /// </code>
396
+ /// </remarks>
397
+ public static void CreateTableStyle(StyleDefinitionsPart stylesPart)
398
+ {
399
+ stylesPart.Styles ??= new Styles();
400
+
401
+ var tableStyle = new Style
402
+ {
403
+ Type = StyleValues.Table,
404
+ StyleId = "CustomGrid",
405
+ CustomStyle = true
406
+ };
407
+
408
+ tableStyle.Append(new StyleName { Val = "Custom Grid" });
409
+ tableStyle.Append(new UIPriority { Val = 59 });
410
+ // BasedOn "TableNormal" — the implicit base for all table styles
411
+ tableStyle.Append(new BasedOn { Val = "TableNormal" });
412
+
413
+ // ── Base table properties (apply to all cells by default) ──
414
+ var baseTblPr = new StyleTableProperties(
415
+ new TableBorders(
416
+ new TopBorder { Val = BorderValues.Single, Size = 4, Color = "BFBFBF" },
417
+ new BottomBorder { Val = BorderValues.Single, Size = 4, Color = "BFBFBF" },
418
+ new LeftBorder { Val = BorderValues.Single, Size = 4, Color = "BFBFBF" },
419
+ new RightBorder { Val = BorderValues.Single, Size = 4, Color = "BFBFBF" },
420
+ new InsideHorizontalBorder { Val = BorderValues.Single, Size = 4, Color = "BFBFBF" },
421
+ new InsideVerticalBorder { Val = BorderValues.Single, Size = 4, Color = "BFBFBF" }
422
+ ),
423
+ // Default cell margins (in DXA)
424
+ new TableCellMarginDefault(
425
+ new TopMargin { Width = "0", Type = TableWidthUnitValues.Dxa },
426
+ new StartMargin { Width = "108", Type = TableWidthUnitValues.Dxa }, // ~0.075 inch
427
+ new BottomMargin { Width = "0", Type = TableWidthUnitValues.Dxa },
428
+ new EndMargin { Width = "108", Type = TableWidthUnitValues.Dxa }
429
+ )
430
+ );
431
+ tableStyle.Append(baseTblPr);
432
+
433
+ // ── Header row override (firstRow) ──
434
+ // Dark background, white bold text
435
+ var firstRowStyle = new TableStyleProperties { Type = TableStyleOverrideValues.FirstRow };
436
+ firstRowStyle.Append(new StyleParagraphProperties(
437
+ new Justification { Val = JustificationValues.Center }
438
+ ));
439
+ firstRowStyle.Append(new RunPropertiesBaseStyle(
440
+ new Bold(),
441
+ new BoldComplexScript(),
442
+ new Color { Val = "FFFFFF" }, // white text
443
+ new FontSize { Val = "22" },
444
+ new FontSizeComplexScript { Val = "22" }
445
+ ));
446
+ firstRowStyle.Append(new TableStyleConditionalFormattingTableCellProperties(
447
+ new Shading
448
+ {
449
+ Val = ShadingPatternValues.Clear,
450
+ Color = "auto",
451
+ Fill = "4472C4" // accent blue background
452
+ }
453
+ ));
454
+ tableStyle.Append(firstRowStyle);
455
+
456
+ // ── Banded rows (Band1Horizontal = odd data rows) ──
457
+ // Light gray background for visual distinction
458
+ var band1Style = new TableStyleProperties { Type = TableStyleOverrideValues.Band1Horizontal };
459
+ band1Style.Append(new TableStyleConditionalFormattingTableCellProperties(
460
+ new Shading
461
+ {
462
+ Val = ShadingPatternValues.Clear,
463
+ Color = "auto",
464
+ Fill = "D9E2F3" // light blue-gray
465
+ }
466
+ ));
467
+ tableStyle.Append(band1Style);
468
+ // Band2Horizontal (even data rows) inherits the base style (no shading)
469
+
470
+ // ── First column override ──
471
+ var firstColStyle = new TableStyleProperties { Type = TableStyleOverrideValues.FirstColumn };
472
+ firstColStyle.Append(new RunPropertiesBaseStyle(
473
+ new Bold(),
474
+ new BoldComplexScript()
475
+ ));
476
+ tableStyle.Append(firstColStyle);
477
+
478
+ stylesPart.Styles.Append(tableStyle);
479
+ stylesPart.Styles.Save();
480
+ }
481
+
482
+ // ────────────────────────────────────────────────────────────────────
483
+ // 4. LIST STYLE (paragraph style linked to numbering)
484
+ // ────────────────────────────────────────────────────────────────────
485
+
486
+ /// <summary>
487
+ /// Creates a paragraph style "ListBullet1" that is linked to a numbering definition.
488
+ /// When this style is applied to a paragraph, the numbering automatically appears.
489
+ /// </summary>
490
+ /// <remarks>
491
+ /// The link between a paragraph style and numbering works as follows:
492
+ /// 1. An AbstractNum defines the list format (bullet/number, indent, etc.)
493
+ /// 2. The AbstractNum can reference a styleLink to connect to a list style
494
+ /// 3. The paragraph style's pPr contains numPr with numId + ilvl
495
+ ///
496
+ /// WARNING: The NumberingDefinitionsPart must exist and contain the referenced
497
+ /// AbstractNum/NumberingInstance, or Word will strip the numPr on open.
498
+ /// </remarks>
499
+ public static void CreateListStyle(StyleDefinitionsPart stylesPart)
500
+ {
501
+ stylesPart.Styles ??= new Styles();
502
+
503
+ var listStyle = new Style
504
+ {
505
+ Type = StyleValues.Paragraph,
506
+ StyleId = "ListBullet1",
507
+ CustomStyle = true
508
+ };
509
+
510
+ listStyle.Append(new StyleName { Val = "List Bullet 1" });
511
+ listStyle.Append(new BasedOn { Val = "Normal" });
512
+ listStyle.Append(new UIPriority { Val = 34 });
513
+ listStyle.Append(new PrimaryStyle());
514
+
515
+ // The numPr in the style's pPr links this style to a numbering definition
516
+ listStyle.Append(new StyleParagraphProperties(
517
+ new NumberingProperties(
518
+ // numId = the NumberingInstance ID (not the AbstractNum ID)
519
+ // IMPORTANT: This must match a <w:num w:numId="1"> in the numbering part
520
+ new NumberingId { Val = 1 },
521
+ // ilvl = indent level (0-based); level 0 = first level bullet
522
+ new NumberingLevelReference { Val = 0 }
523
+ ),
524
+ // Contextual spacing: suppress space between consecutive list items
525
+ // that use the same style (Word collapses the after-spacing)
526
+ new ContextualSpacing()
527
+ ));
528
+
529
+ stylesPart.Styles.Append(listStyle);
530
+ stylesPart.Styles.Save();
531
+ }
532
+
533
+ // ────────────────────────────────────────────────────────────────────
534
+ // 5. DOC DEFAULTS (comprehensive)
535
+ // ────────────────────────────────────────────────────────────────────
536
+
537
+ /// <summary>
538
+ /// Sets up DocDefaults with all 4 font slots, complex-script sizes,
539
+ /// language tags, and paragraph-level default spacing.
540
+ /// DocDefaults is the absolute base of the style inheritance chain —
541
+ /// everything inherits from it unless explicitly overridden.
542
+ /// </summary>
543
+ /// <remarks>
544
+ /// Inheritance resolution order (highest priority last):
545
+ /// 1. DocDefaults (w:docDefaults) — base for everything
546
+ /// 2. Table style (w:tblStyle) — if inside a table
547
+ /// 3. Paragraph style (w:pStyle basedOn chain)
548
+ /// 4. Character style (w:rStyle basedOn chain)
549
+ /// 5. Direct formatting (rPr/pPr directly on the paragraph/run)
550
+ ///
551
+ /// IMPORTANT: DocDefaults must be the FIRST child of w:styles.
552
+ /// </remarks>
553
+ public static void SetupDocDefaults(StyleDefinitionsPart stylesPart)
554
+ {
555
+ stylesPart.Styles ??= new Styles();
556
+
557
+ var docDefaults = new DocDefaults(
558
+ new RunPropertiesDefault(
559
+ new RunPropertiesBaseStyle(
560
+ // ── The 4 font slots ──
561
+ // These cover all Unicode ranges a document might encounter:
562
+ new RunFonts
563
+ {
564
+ // Ascii: Basic Latin (U+0000–U+007F)
565
+ Ascii = "Calibri",
566
+ // HighAnsi: Latin Extended + other non-EastAsian scripts
567
+ HighAnsi = "Calibri",
568
+ // EastAsia: CJK Unified Ideographs, Hiragana, Katakana, Hangul
569
+ EastAsia = "SimSun", // 宋体
570
+ // ComplexScript: Arabic, Hebrew, Thai, Devanagari, etc.
571
+ ComplexScript = "Arial"
572
+ },
573
+ // ── Font sizes ──
574
+ // IMPORTANT: Font sizes are in HALF-POINTS throughout OpenXML
575
+ // 22 half-pt = 11pt (Word's default body size)
576
+ // 24 half-pt = 12pt (common for academic papers)
577
+ new FontSize { Val = "22" },
578
+ new FontSizeComplexScript { Val = "22" },
579
+ // ── Language tags ──
580
+ // Control spell-check dictionary, hyphenation rules, and
581
+ // font fallback behavior for each script
582
+ new Languages
583
+ {
584
+ Val = "en-US", // Latin script language
585
+ EastAsia = "zh-CN", // CJK language (Simplified Chinese)
586
+ Bidi = "ar-SA" // BiDi language (Arabic, Saudi Arabia)
587
+ },
588
+ // ── Kerning ──
589
+ // Kern font pairs at this size (in half-points) and above
590
+ // 0 = no kerning; 2 = kern at 1pt+ (aggressive); 28 = kern at 14pt+ (typical)
591
+ new Kern { Val = (UInt32Value)2U }
592
+ )
593
+ ),
594
+ new ParagraphPropertiesDefault(
595
+ new ParagraphPropertiesBaseStyle(
596
+ new SpacingBetweenLines
597
+ {
598
+ // Before = space before paragraph (DXA twentieths-of-a-point)
599
+ Before = "0",
600
+ // After = space after paragraph
601
+ After = "160", // 8pt = Word 2016+ default
602
+ // Line spacing:
603
+ // For Auto rule: units are 240ths of a line
604
+ // 240 = exactly single spacing
605
+ // 259 = ~1.08 (Word's default "single")
606
+ // 360 = 1.5 spacing
607
+ // 480 = double spacing
608
+ // For Exact/AtLeast rules: units are DXA (twentieths-of-a-point)
609
+ Line = "259",
610
+ LineRule = LineSpacingRuleValues.Auto
611
+ },
612
+ // WidowControl: prevent single lines at top/bottom of page
613
+ new WidowControl()
614
+ )
615
+ )
616
+ );
617
+
618
+ // Remove any existing DocDefaults and prepend the new one
619
+ stylesPart.Styles.DocDefaults?.Remove();
620
+ stylesPart.Styles.PrependChild(docDefaults);
621
+ stylesPart.Styles.Save();
622
+ }
623
+
624
+ // ────────────────────────────────────────────────────────────────────
625
+ // 6. LATENT STYLES
626
+ // ────────────────────────────────────────────────────────────────────
627
+
628
+ /// <summary>
629
+ /// Configures latent styles — the built-in styles that Word knows about
630
+ /// but doesn't include in styles.xml until they're used.
631
+ /// Controls visibility, priority, and quick-format status of all 375+ built-in styles.
632
+ /// </summary>
633
+ /// <remarks>
634
+ /// Latent styles serve two purposes:
635
+ /// 1. Performance: Word doesn't serialize all 375+ built-in styles into styles.xml
636
+ /// 2. UI: Controls which styles appear in the Styles pane and Quick Styles gallery
637
+ ///
638
+ /// The LatentStyles element sets defaults, then LatentStyleExceptionInfo overrides
639
+ /// specific styles. If a built-in style is used in the document but not in styles.xml,
640
+ /// Word uses the latent style definition to determine its formatting.
641
+ /// </remarks>
642
+ public static void SetupLatentStyles(StyleDefinitionsPart stylesPart)
643
+ {
644
+ stylesPart.Styles ??= new Styles();
645
+
646
+ var latentStyles = new LatentStyles
647
+ {
648
+ // Default values for ALL built-in styles not explicitly listed
649
+ DefaultLockedState = false,
650
+ DefaultUiPriority = 99, // 99 = low priority (sorted last in Styles pane)
651
+ DefaultSemiHidden = true, // hidden from Styles pane by default
652
+ DefaultUnhideWhenUsed = true, // auto-show when used in the document
653
+ DefaultPrimaryStyle = false, // don't show in Quick Styles gallery by default
654
+ Count = 376 // total number of built-in styles in Word 2019+
655
+ };
656
+
657
+ // Override specific styles to make them visible and high-priority
658
+ // These are the styles users commonly need in the Styles pane
659
+
660
+ // Core paragraph styles — always visible
661
+ latentStyles.Append(new LatentStyleExceptionInfo
662
+ {
663
+ Name = "Normal",
664
+ UiPriority = 0,
665
+ SemiHidden = false,
666
+ UnhideWhenUsed = false,
667
+ PrimaryStyle = true
668
+ });
669
+
670
+ // Heading styles
671
+ for (int i = 1; i <= 6; i++)
672
+ {
673
+ latentStyles.Append(new LatentStyleExceptionInfo
674
+ {
675
+ Name = $"heading {i}",
676
+ UiPriority = 9,
677
+ SemiHidden = i > 2, // only H1-H2 visible by default
678
+ UnhideWhenUsed = true,
679
+ PrimaryStyle = i <= 3 // H1-H3 in Quick Styles
680
+ });
681
+ }
682
+
683
+ // Title and Subtitle
684
+ latentStyles.Append(new LatentStyleExceptionInfo
685
+ {
686
+ Name = "Title",
687
+ UiPriority = 10,
688
+ SemiHidden = false,
689
+ UnhideWhenUsed = false,
690
+ PrimaryStyle = true
691
+ });
692
+ latentStyles.Append(new LatentStyleExceptionInfo
693
+ {
694
+ Name = "Subtitle",
695
+ UiPriority = 11,
696
+ SemiHidden = false,
697
+ UnhideWhenUsed = false,
698
+ PrimaryStyle = true
699
+ });
700
+
701
+ // Inline styles
702
+ latentStyles.Append(new LatentStyleExceptionInfo
703
+ {
704
+ Name = "Strong",
705
+ UiPriority = 22,
706
+ SemiHidden = false,
707
+ UnhideWhenUsed = false,
708
+ PrimaryStyle = true
709
+ });
710
+ latentStyles.Append(new LatentStyleExceptionInfo
711
+ {
712
+ Name = "Emphasis",
713
+ UiPriority = 20,
714
+ SemiHidden = false,
715
+ UnhideWhenUsed = false,
716
+ PrimaryStyle = true
717
+ });
718
+
719
+ // Table styles
720
+ latentStyles.Append(new LatentStyleExceptionInfo
721
+ {
722
+ Name = "Table Grid",
723
+ UiPriority = 39,
724
+ SemiHidden = false,
725
+ UnhideWhenUsed = false
726
+ });
727
+
728
+ // List styles
729
+ latentStyles.Append(new LatentStyleExceptionInfo
730
+ {
731
+ Name = "List Paragraph",
732
+ UiPriority = 34,
733
+ SemiHidden = false,
734
+ UnhideWhenUsed = false,
735
+ PrimaryStyle = true
736
+ });
737
+
738
+ // No Spacing (popular alternative to Normal)
739
+ latentStyles.Append(new LatentStyleExceptionInfo
740
+ {
741
+ Name = "No Spacing",
742
+ UiPriority = 1,
743
+ SemiHidden = false,
744
+ UnhideWhenUsed = false,
745
+ PrimaryStyle = true
746
+ });
747
+
748
+ // Remove existing LatentStyles and add new one
749
+ // IMPORTANT: LatentStyles should come after DocDefaults but before Style elements
750
+ stylesPart.Styles.Elements<LatentStyles>().ToList().ForEach(ls => ls.Remove());
751
+ var docDefaults = stylesPart.Styles.DocDefaults;
752
+ if (docDefaults is not null)
753
+ docDefaults.InsertAfterSelf(latentStyles);
754
+ else
755
+ stylesPart.Styles.PrependChild(latentStyles);
756
+
757
+ stylesPart.Styles.Save();
758
+ }
759
+
760
+ // ────────────────────────────────────────────────────────────────────
761
+ // 7. CJK STYLES (Chinese 公文)
762
+ // ────────────────────────────────────────────────────────────────────
763
+
764
+ /// <summary>
765
+ /// Creates Chinese government document (公文) styles per GB/T 9704-2012:
766
+ /// - GongWenTitle: 方正小标宋简体 (FZXiaoBiaoSong) 二号 (22pt) — document title
767
+ /// - GongWenBody: 仿宋 (FangSong) 三号 (16pt) — body text
768
+ /// - L1Heading: 黑体 (SimHei) 三号 (16pt) — first-level heading
769
+ /// - L2Heading: 楷体 (KaiTi) 三号 (16pt) — second-level heading
770
+ /// </summary>
771
+ /// <remarks>
772
+ /// Chinese font size names to point sizes:
773
+ /// 初号 = 42pt 小初 = 36pt
774
+ /// 一号 = 26pt 小一 = 24pt
775
+ /// 二号 = 22pt 小二 = 18pt
776
+ /// 三号 = 16pt 小三 = 15pt
777
+ /// 四号 = 14pt 小四 = 12pt
778
+ /// 五号 = 10.5pt 小五 = 9pt
779
+ /// 六号 = 7.5pt 小六 = 6.5pt
780
+ /// 七号 = 5.5pt 八号 = 5pt
781
+ ///
782
+ /// CJK font usage in 公文:
783
+ /// 方正小标宋简体 (FZXiaoBiaoSong-B13S) — titles, rarely available; fallback: 华文中宋 or SimSun
784
+ /// 仿宋 (FangSong / FangSong_GB2312) — body text
785
+ /// 黑体 (SimHei) — first-level headings (bold-like appearance)
786
+ /// 楷体 (KaiTi / KaiTi_GB2312) — second-level headings (calligraphic)
787
+ /// 宋体 (SimSun) — fallback for everything
788
+ ///
789
+ /// IMPORTANT: The EastAsia font slot controls which font is used for CJK characters.
790
+ /// The Ascii/HighAnsi slots only affect Latin characters within CJK paragraphs.
791
+ /// </remarks>
792
+ public static void CreateCjkStyles(StyleDefinitionsPart stylesPart)
793
+ {
794
+ stylesPart.Styles ??= new Styles();
795
+
796
+ // ── 公文标题 (Document Title) ──
797
+ // 方正小标宋简体 二号 (22pt), centered, 行距固定值 (exact line spacing)
798
+ var titleStyle = new Style
799
+ {
800
+ Type = StyleValues.Paragraph,
801
+ StyleId = "GongWenTitle",
802
+ CustomStyle = true
803
+ };
804
+ titleStyle.Append(new StyleName { Val = "公文标题" });
805
+ titleStyle.Append(new BasedOn { Val = "Normal" });
806
+ titleStyle.Append(new NextParagraphStyle { Val = "GongWenBody" });
807
+ titleStyle.Append(new UIPriority { Val = 1 });
808
+ titleStyle.Append(new PrimaryStyle());
809
+ titleStyle.Append(new StyleParagraphProperties(
810
+ new Justification { Val = JustificationValues.Center },
811
+ new SpacingBetweenLines
812
+ {
813
+ // 公文 title uses exact line spacing, typically ~32pt = 640 DXA
814
+ Line = "640",
815
+ LineRule = LineSpacingRuleValues.Exact,
816
+ Before = "0",
817
+ After = "0"
818
+ },
819
+ new KeepNext(),
820
+ new KeepLines(),
821
+ // outlineLvl 0 makes this appear as "Level 1" in navigation / TOC
822
+ new OutlineLevel { Val = 0 }
823
+ ));
824
+ titleStyle.Append(new StyleRunProperties(
825
+ new RunFonts
826
+ {
827
+ // EastAsia = the CJK font that renders Chinese characters
828
+ // 方正小标宋简体 is the standard 公文 title font
829
+ // Fallback: 华文中宋 (STZhongsong) → SimSun
830
+ EastAsia = "方正小标宋简体",
831
+ Ascii = "Times New Roman",
832
+ HighAnsi = "Times New Roman",
833
+ ComplexScript = "Times New Roman"
834
+ },
835
+ // 二号 = 22pt = 44 half-points
836
+ new FontSize { Val = "44" },
837
+ new FontSizeComplexScript { Val = "44" }
838
+ ));
839
+ stylesPart.Styles.Append(titleStyle);
840
+
841
+ // ── 公文正文 (Body Text) ──
842
+ // 仿宋 三号 (16pt), justified, 28pt exact line spacing
843
+ var bodyStyle = new Style
844
+ {
845
+ Type = StyleValues.Paragraph,
846
+ StyleId = "GongWenBody",
847
+ CustomStyle = true
848
+ };
849
+ bodyStyle.Append(new StyleName { Val = "公文正文" });
850
+ bodyStyle.Append(new BasedOn { Val = "Normal" });
851
+ bodyStyle.Append(new UIPriority { Val = 2 });
852
+ bodyStyle.Append(new PrimaryStyle());
853
+ bodyStyle.Append(new StyleParagraphProperties(
854
+ new Justification { Val = JustificationValues.Both },
855
+ new SpacingBetweenLines
856
+ {
857
+ // 28pt line spacing (exact) = 560 DXA, standard for 公文 body
858
+ Line = "560",
859
+ LineRule = LineSpacingRuleValues.Exact,
860
+ Before = "0",
861
+ After = "0"
862
+ },
863
+ // First-line indent of 2 characters for Chinese body text
864
+ // For 三号 (16pt) font: 2 chars ≈ 640 DXA (16pt * 20 DXA/pt * 2)
865
+ new Indentation { FirstLine = "640" },
866
+ // CJK paragraph settings
867
+ new WordWrap { Val = true },
868
+ new AutoSpaceDE { Val = true },
869
+ new AutoSpaceDN { Val = true }
870
+ ));
871
+ bodyStyle.Append(new StyleRunProperties(
872
+ new RunFonts
873
+ {
874
+ EastAsia = "仿宋",
875
+ Ascii = "Times New Roman",
876
+ HighAnsi = "Times New Roman",
877
+ ComplexScript = "Times New Roman"
878
+ },
879
+ // 三号 = 16pt = 32 half-points
880
+ new FontSize { Val = "32" },
881
+ new FontSizeComplexScript { Val = "32" }
882
+ ));
883
+ stylesPart.Styles.Append(bodyStyle);
884
+
885
+ // ── 一级标题 (Level 1 Heading) ──
886
+ // 黑体 三号 (16pt), bold by nature of the font
887
+ var l1Style = new Style
888
+ {
889
+ Type = StyleValues.Paragraph,
890
+ StyleId = "L1Heading",
891
+ CustomStyle = true
892
+ };
893
+ l1Style.Append(new StyleName { Val = "一级标题" });
894
+ l1Style.Append(new BasedOn { Val = "GongWenBody" });
895
+ l1Style.Append(new NextParagraphStyle { Val = "GongWenBody" });
896
+ l1Style.Append(new UIPriority { Val = 3 });
897
+ l1Style.Append(new PrimaryStyle());
898
+ l1Style.Append(new StyleParagraphProperties(
899
+ new KeepNext(),
900
+ new KeepLines(),
901
+ // Remove the first-line indent from headings
902
+ new Indentation { FirstLine = "0" },
903
+ new Justification { Val = JustificationValues.Center },
904
+ new OutlineLevel { Val = 1 }
905
+ ));
906
+ l1Style.Append(new StyleRunProperties(
907
+ new RunFonts
908
+ {
909
+ // 黑体 (SimHei) — a sans-serif CJK font that looks inherently bold
910
+ // IMPORTANT: Do NOT add w:b (Bold) — SimHei is already visually bold,
911
+ // and adding Bold makes it too thick
912
+ EastAsia = "黑体",
913
+ Ascii = "Arial",
914
+ HighAnsi = "Arial"
915
+ },
916
+ // Same size as body: 三号 = 16pt
917
+ new FontSize { Val = "32" },
918
+ new FontSizeComplexScript { Val = "32" }
919
+ ));
920
+ stylesPart.Styles.Append(l1Style);
921
+
922
+ // ── 二级标题 (Level 2 Heading) ──
923
+ // 楷体 三号 (16pt), also not bold by convention
924
+ var l2Style = new Style
925
+ {
926
+ Type = StyleValues.Paragraph,
927
+ StyleId = "L2Heading",
928
+ CustomStyle = true
929
+ };
930
+ l2Style.Append(new StyleName { Val = "二级标题" });
931
+ l2Style.Append(new BasedOn { Val = "GongWenBody" });
932
+ l2Style.Append(new NextParagraphStyle { Val = "GongWenBody" });
933
+ l2Style.Append(new UIPriority { Val = 4 });
934
+ l2Style.Append(new PrimaryStyle());
935
+ l2Style.Append(new StyleParagraphProperties(
936
+ new KeepNext(),
937
+ new KeepLines(),
938
+ new Indentation { FirstLine = "0" },
939
+ new Justification { Val = JustificationValues.Left },
940
+ new OutlineLevel { Val = 2 }
941
+ ));
942
+ l2Style.Append(new StyleRunProperties(
943
+ new RunFonts
944
+ {
945
+ // 楷体 (KaiTi) — calligraphic script font
946
+ EastAsia = "楷体",
947
+ Ascii = "Times New Roman",
948
+ HighAnsi = "Times New Roman"
949
+ },
950
+ new FontSize { Val = "32" },
951
+ new FontSizeComplexScript { Val = "32" }
952
+ ));
953
+ stylesPart.Styles.Append(l2Style);
954
+
955
+ stylesPart.Styles.Save();
956
+ }
957
+
958
+ // ────────────────────────────────────────────────────────────────────
959
+ // 8. ACADEMIC STYLES (APA 7th Edition)
960
+ // ────────────────────────────────────────────────────────────────────
961
+
962
+ /// <summary>
963
+ /// Creates styles conforming to APA 7th edition formatting guidelines:
964
+ /// - APATitle: centered, bold, 12pt Times New Roman
965
+ /// - APAHeading1–5: the five APA heading levels
966
+ /// - APABody: double-spaced, first-line indent 0.5", 12pt TNR
967
+ /// - APAAbstract: single paragraph, no indent, 12pt
968
+ /// - APABlockQuote: 0.5" left indent, no first-line indent, double-spaced
969
+ /// </summary>
970
+ /// <remarks>
971
+ /// APA 7th edition heading levels:
972
+ /// Level 1: Centered, Bold, Title Case (like a chapter title)
973
+ /// Level 2: Flush Left, Bold, Title Case
974
+ /// Level 3: Flush Left, Bold Italic, Title Case
975
+ /// Level 4: Indented 0.5", Bold, Title Case, Period. (run-in heading)
976
+ /// Level 5: Indented 0.5", Bold Italic, Title Case, Period.
977
+ ///
978
+ /// All text: Times New Roman 12pt, double-spaced (480 in 240ths units).
979
+ /// </remarks>
980
+ public static void CreateAcademicStyles(StyleDefinitionsPart stylesPart)
981
+ {
982
+ stylesPart.Styles ??= new Styles();
983
+
984
+ const string font = "Times New Roman";
985
+ const string sizeVal = "24"; // 12pt in half-points
986
+ // Double spacing: 480 = 2.0 * 240 (240ths of a line)
987
+ const string doubleSpace = "480";
988
+
989
+ // ── APA Body (base for all APA styles) ──
990
+ var apaBody = new Style
991
+ {
992
+ Type = StyleValues.Paragraph,
993
+ StyleId = "APABody",
994
+ CustomStyle = true
995
+ };
996
+ apaBody.Append(new StyleName { Val = "APA Body" });
997
+ apaBody.Append(new BasedOn { Val = "Normal" });
998
+ apaBody.Append(new UIPriority { Val = 1 });
999
+ apaBody.Append(new PrimaryStyle());
1000
+ apaBody.Append(new StyleParagraphProperties(
1001
+ new SpacingBetweenLines
1002
+ {
1003
+ Line = doubleSpace,
1004
+ LineRule = LineSpacingRuleValues.Auto,
1005
+ Before = "0",
1006
+ After = "0" // APA: no extra space between paragraphs
1007
+ },
1008
+ // APA 7: 0.5-inch first-line indent = 720 DXA
1009
+ new Indentation { FirstLine = "720" },
1010
+ new Justification { Val = JustificationValues.Left },
1011
+ // WARNING: APA explicitly says do NOT use justified alignment.
1012
+ // Always use left (ragged right).
1013
+ new WidowControl()
1014
+ ));
1015
+ apaBody.Append(new StyleRunProperties(
1016
+ new RunFonts
1017
+ {
1018
+ Ascii = font,
1019
+ HighAnsi = font,
1020
+ EastAsia = font,
1021
+ ComplexScript = font
1022
+ },
1023
+ new FontSize { Val = sizeVal },
1024
+ new FontSizeComplexScript { Val = sizeVal }
1025
+ ));
1026
+ stylesPart.Styles.Append(apaBody);
1027
+
1028
+ // ── APA Title (paper title on title page) ──
1029
+ var apaTitle = new Style
1030
+ {
1031
+ Type = StyleValues.Paragraph,
1032
+ StyleId = "APATitle",
1033
+ CustomStyle = true
1034
+ };
1035
+ apaTitle.Append(new StyleName { Val = "APA Title" });
1036
+ apaTitle.Append(new BasedOn { Val = "APABody" });
1037
+ apaTitle.Append(new NextParagraphStyle { Val = "APABody" });
1038
+ apaTitle.Append(new UIPriority { Val = 2 });
1039
+ apaTitle.Append(new PrimaryStyle());
1040
+ apaTitle.Append(new StyleParagraphProperties(
1041
+ new Justification { Val = JustificationValues.Center },
1042
+ new Indentation { FirstLine = "0" },
1043
+ // Extra space before the title block
1044
+ new SpacingBetweenLines
1045
+ {
1046
+ Line = doubleSpace,
1047
+ LineRule = LineSpacingRuleValues.Auto,
1048
+ Before = "0",
1049
+ After = "0"
1050
+ },
1051
+ new OutlineLevel { Val = 0 }
1052
+ ));
1053
+ apaTitle.Append(new StyleRunProperties(
1054
+ new Bold(),
1055
+ new BoldComplexScript()
1056
+ ));
1057
+ stylesPart.Styles.Append(apaTitle);
1058
+
1059
+ // ── APA Heading Levels 1–5 ──
1060
+ var apaHeadings = new (string Id, string Name, int Level, bool Bold, bool Italic, JustificationValues Jc, string Indent, bool RunIn)[]
1061
+ {
1062
+ ("APAHeading1", "APA Heading 1", 1, true, false, JustificationValues.Center, "0", false),
1063
+ ("APAHeading2", "APA Heading 2", 2, true, false, JustificationValues.Left, "0", false),
1064
+ ("APAHeading3", "APA Heading 3", 3, true, true, JustificationValues.Left, "0", false),
1065
+ ("APAHeading4", "APA Heading 4", 4, true, false, JustificationValues.Left, "720", true),
1066
+ ("APAHeading5", "APA Heading 5", 5, true, true, JustificationValues.Left, "720", true),
1067
+ };
1068
+
1069
+ foreach (var (id, name, level, bold, italic, jc, indent, runIn) in apaHeadings)
1070
+ {
1071
+ var style = new Style
1072
+ {
1073
+ Type = StyleValues.Paragraph,
1074
+ StyleId = id,
1075
+ CustomStyle = true
1076
+ };
1077
+ style.Append(new StyleName { Val = name });
1078
+ style.Append(new BasedOn { Val = "APABody" });
1079
+ style.Append(new NextParagraphStyle { Val = runIn ? id : "APABody" });
1080
+ style.Append(new UIPriority { Val = 9 });
1081
+ style.Append(new PrimaryStyle());
1082
+
1083
+ var pPr = new StyleParagraphProperties(
1084
+ new KeepNext(),
1085
+ new KeepLines(),
1086
+ new SpacingBetweenLines
1087
+ {
1088
+ Line = doubleSpace,
1089
+ LineRule = LineSpacingRuleValues.Auto,
1090
+ Before = "0",
1091
+ After = "0"
1092
+ },
1093
+ new Justification { Val = jc },
1094
+ // Remove or set first-line indent based on APA level
1095
+ new Indentation
1096
+ {
1097
+ Left = indent,
1098
+ FirstLine = "0"
1099
+ },
1100
+ // outlineLvl is 0-based, APA level 1 = outlineLvl 0
1101
+ new OutlineLevel { Val = level - 1 }
1102
+ );
1103
+ style.Append(pPr);
1104
+
1105
+ var rPr = new StyleRunProperties();
1106
+ if (bold)
1107
+ {
1108
+ rPr.Append(new Bold());
1109
+ rPr.Append(new BoldComplexScript());
1110
+ }
1111
+ if (italic)
1112
+ {
1113
+ rPr.Append(new Italic());
1114
+ rPr.Append(new ItalicComplexScript());
1115
+ }
1116
+ style.Append(rPr);
1117
+
1118
+ stylesPart.Styles.Append(style);
1119
+ }
1120
+
1121
+ // ── APA Abstract ──
1122
+ var apaAbstract = new Style
1123
+ {
1124
+ Type = StyleValues.Paragraph,
1125
+ StyleId = "APAAbstract",
1126
+ CustomStyle = true
1127
+ };
1128
+ apaAbstract.Append(new StyleName { Val = "APA Abstract" });
1129
+ apaAbstract.Append(new BasedOn { Val = "APABody" });
1130
+ apaAbstract.Append(new UIPriority { Val = 5 });
1131
+ apaAbstract.Append(new StyleParagraphProperties(
1132
+ // APA Abstract: single paragraph, NO first-line indent
1133
+ new Indentation { FirstLine = "0" }
1134
+ ));
1135
+ stylesPart.Styles.Append(apaAbstract);
1136
+
1137
+ // ── APA Block Quote ──
1138
+ // For quotes of 40+ words: 0.5" left indent, no first-line indent, double-spaced
1139
+ var apaBlock = new Style
1140
+ {
1141
+ Type = StyleValues.Paragraph,
1142
+ StyleId = "APABlockQuote",
1143
+ CustomStyle = true
1144
+ };
1145
+ apaBlock.Append(new StyleName { Val = "APA Block Quote" });
1146
+ apaBlock.Append(new BasedOn { Val = "APABody" });
1147
+ apaBlock.Append(new UIPriority { Val = 6 });
1148
+ apaBlock.Append(new StyleParagraphProperties(
1149
+ // 0.5-inch left indent = 720 DXA
1150
+ new Indentation { Left = "720", FirstLine = "0" }
1151
+ ));
1152
+ stylesPart.Styles.Append(apaBlock);
1153
+
1154
+ stylesPart.Styles.Save();
1155
+ }
1156
+
1157
+ // ────────────────────────────────────────────────────────────────────
1158
+ // 9. IMPORT STYLES FROM ANOTHER DOCUMENT
1159
+ // ────────────────────────────────────────────────────────────────────
1160
+
1161
+ /// <summary>
1162
+ /// Imports styles, numbering definitions, and theme from a source DOCX
1163
+ /// into the target document's MainDocumentPart by stream-copying the parts.
1164
+ /// This is the standard "apply template" pattern.
1165
+ /// </summary>
1166
+ /// <remarks>
1167
+ /// WARNING: This replaces the ENTIRE styles/numbering/theme parts.
1168
+ /// Any existing styles in the target that aren't in the source will be lost.
1169
+ /// For a merge approach (keeping both), you would need to deserialize both
1170
+ /// Styles objects and merge individual Style elements, resolving ID conflicts.
1171
+ ///
1172
+ /// Parts copied:
1173
+ /// - StyleDefinitionsPart (word/styles.xml)
1174
+ /// - NumberingDefinitionsPart (word/numbering.xml)
1175
+ /// - ThemePart (word/theme/theme1.xml)
1176
+ /// </remarks>
1177
+ public static void ImportStylesFromDocument(string sourcePath, MainDocumentPart target)
1178
+ {
1179
+ // Open source as read-only
1180
+ using var sourceDoc = WordprocessingDocument.Open(sourcePath, isEditable: false);
1181
+ var sourceMain = sourceDoc.MainDocumentPart;
1182
+ if (sourceMain is null) return;
1183
+
1184
+ // ── Copy StyleDefinitionsPart ──
1185
+ if (sourceMain.StyleDefinitionsPart is not null)
1186
+ {
1187
+ // Delete existing styles part if present
1188
+ if (target.StyleDefinitionsPart is not null)
1189
+ target.DeletePart(target.StyleDefinitionsPart);
1190
+
1191
+ // Add a fresh part and stream-copy the content
1192
+ var newStylesPart = target.AddNewPart<StyleDefinitionsPart>();
1193
+ using (var sourceStream = sourceMain.StyleDefinitionsPart.GetStream())
1194
+ using (var targetStream = newStylesPart.GetStream(FileMode.Create))
1195
+ {
1196
+ sourceStream.CopyTo(targetStream);
1197
+ }
1198
+ }
1199
+
1200
+ // ── Copy NumberingDefinitionsPart ──
1201
+ if (sourceMain.NumberingDefinitionsPart is not null)
1202
+ {
1203
+ if (target.NumberingDefinitionsPart is not null)
1204
+ target.DeletePart(target.NumberingDefinitionsPart);
1205
+
1206
+ var newNumPart = target.AddNewPart<NumberingDefinitionsPart>();
1207
+ using (var sourceStream = sourceMain.NumberingDefinitionsPart.GetStream())
1208
+ using (var targetStream = newNumPart.GetStream(FileMode.Create))
1209
+ {
1210
+ sourceStream.CopyTo(targetStream);
1211
+ }
1212
+ }
1213
+
1214
+ // ── Copy ThemePart ──
1215
+ if (sourceMain.ThemePart is not null)
1216
+ {
1217
+ if (target.ThemePart is not null)
1218
+ target.DeletePart(target.ThemePart);
1219
+
1220
+ var newThemePart = target.AddNewPart<ThemePart>();
1221
+ using (var sourceStream = sourceMain.ThemePart.GetStream())
1222
+ using (var targetStream = newThemePart.GetStream(FileMode.Create))
1223
+ {
1224
+ sourceStream.CopyTo(targetStream);
1225
+ }
1226
+ }
1227
+
1228
+ // IMPORTANT: After importing, you may need to update style references
1229
+ // in the document body if the source uses different style IDs.
1230
+ // Also check that numbering numId references in paragraphs match the
1231
+ // imported NumberingInstance IDs.
1232
+ }
1233
+
1234
+ // ────────────────────────────────────────────────────────────────────
1235
+ // 10. APPLY STYLE TO EXISTING PARAGRAPHS
1236
+ // ────────────────────────────────────────────────────────────────────
1237
+
1238
+ /// <summary>
1239
+ /// Finds all paragraphs in the body and applies (or changes) their paragraph style.
1240
+ /// Demonstrates how to set/replace the pStyle element on existing paragraphs.
1241
+ /// </summary>
1242
+ /// <remarks>
1243
+ /// To apply a style to a paragraph:
1244
+ /// <code>
1245
+ /// &lt;w:p&gt;
1246
+ /// &lt;w:pPr&gt;
1247
+ /// &lt;w:pStyle w:val="Heading1"/&gt;
1248
+ /// &lt;/w:pPr&gt;
1249
+ /// ...
1250
+ /// &lt;/w:p&gt;
1251
+ /// </code>
1252
+ ///
1253
+ /// IMPORTANT: pStyle must be the FIRST child of pPr.
1254
+ /// If you Append it, it may end up after other elements, which technically
1255
+ /// violates the schema (though Word tolerates it).
1256
+ /// </remarks>
1257
+ public static void ApplyStyleToExistingParagraphs(Body body, string styleId)
1258
+ {
1259
+ foreach (var para in body.Elements<Paragraph>())
1260
+ {
1261
+ // Get or create ParagraphProperties
1262
+ var pPr = para.ParagraphProperties;
1263
+ if (pPr is null)
1264
+ {
1265
+ pPr = new ParagraphProperties();
1266
+ // IMPORTANT: pPr must be the FIRST child of the paragraph
1267
+ para.PrependChild(pPr);
1268
+ }
1269
+
1270
+ // Get or create ParagraphStyleId
1271
+ var pStyle = pPr.ParagraphStyleId;
1272
+ if (pStyle is not null)
1273
+ {
1274
+ // Update existing style reference
1275
+ pStyle.Val = styleId;
1276
+ }
1277
+ else
1278
+ {
1279
+ // Create new style reference
1280
+ // IMPORTANT: pStyle must be the FIRST child of pPr
1281
+ pPr.PrependChild(new ParagraphStyleId { Val = styleId });
1282
+ }
1283
+ }
1284
+ }
1285
+
1286
+ // ────────────────────────────────────────────────────────────────────
1287
+ // 11. RESOLVE EFFECTIVE FORMATTING
1288
+ // ────────────────────────────────────────────────────────────────────
1289
+
1290
+ /// <summary>
1291
+ /// Walks the style inheritance chain to resolve the effective (computed)
1292
+ /// formatting for a paragraph's first run. Returns a summary of the resolved
1293
+ /// font, size, bold, and italic properties.
1294
+ /// </summary>
1295
+ /// <remarks>
1296
+ /// Resolution order (later overrides earlier):
1297
+ /// 1. DocDefaults → rPrDefault
1298
+ /// 2. basedOn chain (walk from the root ancestor down to the paragraph's style)
1299
+ /// 3. Paragraph style's rPr (StyleRunProperties)
1300
+ /// 4. Character style's rPr (if w:rStyle is set on the run)
1301
+ /// 5. Direct formatting (RunProperties on the run itself)
1302
+ ///
1303
+ /// Each level only overrides properties it explicitly sets; unset properties
1304
+ /// are inherited from the previous level.
1305
+ ///
1306
+ /// IMPORTANT: This is a simplified resolution. Full resolution must also handle:
1307
+ /// - Table style conditional formatting
1308
+ /// - Numbering level rPr
1309
+ /// - Toggle properties (bold, italic) which XOR rather than override
1310
+ /// - Theme font resolution (majorHAnsi → actual font name from theme)
1311
+ /// </remarks>
1312
+ public static ResolvedFormatting ResolveEffectiveFormatting(
1313
+ Paragraph para,
1314
+ StyleDefinitionsPart stylesPart)
1315
+ {
1316
+ var result = new ResolvedFormatting();
1317
+ var styles = stylesPart.Styles;
1318
+ if (styles is null) return result;
1319
+
1320
+ // ── Step 1: DocDefaults ──
1321
+ var docDefaults = styles.DocDefaults;
1322
+ if (docDefaults?.RunPropertiesDefault?.RunPropertiesBaseStyle is RunPropertiesBaseStyle defaultRPr)
1323
+ {
1324
+ ApplyRunProps(result, defaultRPr);
1325
+ }
1326
+
1327
+ // ── Step 2–3: Walk basedOn chain for the paragraph style ──
1328
+ var pStyleId = para.ParagraphProperties?.ParagraphStyleId?.Val?.Value;
1329
+ // If no explicit style, use the default paragraph style
1330
+ pStyleId ??= styles.Elements<Style>()
1331
+ .FirstOrDefault(s => s.Type?.Value == StyleValues.Paragraph && s.Default?.Value == true)
1332
+ ?.StyleId?.Value;
1333
+
1334
+ if (pStyleId is not null)
1335
+ {
1336
+ // Build the chain: [root ancestor, ..., grandparent, parent, style]
1337
+ var chain = BuildBasedOnChain(pStyleId, styles);
1338
+
1339
+ // Apply each style's rPr in order (root first, most specific last)
1340
+ foreach (var styleInChain in chain)
1341
+ {
1342
+ var styleRPr = styleInChain.StyleRunProperties;
1343
+ if (styleRPr is not null)
1344
+ {
1345
+ ApplyRunProps(result, styleRPr);
1346
+ }
1347
+ }
1348
+ }
1349
+
1350
+ // ── Step 4: Character style (rStyle on the run) ──
1351
+ var firstRun = para.Elements<Run>().FirstOrDefault();
1352
+ var rStyleId = firstRun?.RunProperties?.RunStyle?.Val?.Value;
1353
+ if (rStyleId is not null)
1354
+ {
1355
+ var charChain = BuildBasedOnChain(rStyleId, styles);
1356
+ foreach (var styleInChain in charChain)
1357
+ {
1358
+ var styleRPr = styleInChain.StyleRunProperties;
1359
+ if (styleRPr is not null)
1360
+ {
1361
+ ApplyRunProps(result, styleRPr);
1362
+ }
1363
+ }
1364
+ }
1365
+
1366
+ // ── Step 5: Direct formatting on the run ──
1367
+ if (firstRun?.RunProperties is RunProperties directRPr)
1368
+ {
1369
+ ApplyRunProps(result, directRPr);
1370
+ }
1371
+
1372
+ return result;
1373
+ }
1374
+
1375
+ /// <summary>
1376
+ /// Builds the basedOn chain for a style, from root ancestor to the style itself.
1377
+ /// Returns a list ordered [root, ..., parent, style].
1378
+ /// </summary>
1379
+ private static List<Style> BuildBasedOnChain(string styleId, Styles styles)
1380
+ {
1381
+ var chain = new List<Style>();
1382
+ var visited = new HashSet<string>(); // guard against circular references
1383
+
1384
+ var currentId = styleId;
1385
+ while (currentId is not null && visited.Add(currentId))
1386
+ {
1387
+ var style = styles.Elements<Style>()
1388
+ .FirstOrDefault(s => s.StyleId?.Value == currentId);
1389
+
1390
+ if (style is null) break;
1391
+
1392
+ chain.Add(style);
1393
+ currentId = style.BasedOn?.Val?.Value;
1394
+ }
1395
+
1396
+ // Reverse so root ancestor is first
1397
+ chain.Reverse();
1398
+ return chain;
1399
+ }
1400
+
1401
+ /// <summary>
1402
+ /// Applies run properties from any source (DocDefaults, StyleRunProperties, or RunProperties)
1403
+ /// to the resolved formatting result. Only overrides properties that are explicitly set.
1404
+ /// </summary>
1405
+ private static void ApplyRunProps(ResolvedFormatting result, OpenXmlCompositeElement rPr)
1406
+ {
1407
+ // Font name — check all slots
1408
+ var fonts = rPr.GetFirstChild<RunFonts>();
1409
+ if (fonts is not null)
1410
+ {
1411
+ if (fonts.Ascii?.Value is not null) result.FontAscii = fonts.Ascii.Value;
1412
+ if (fonts.HighAnsi?.Value is not null) result.FontHighAnsi = fonts.HighAnsi.Value;
1413
+ if (fonts.EastAsia?.Value is not null) result.FontEastAsia = fonts.EastAsia.Value;
1414
+ if (fonts.ComplexScript?.Value is not null) result.FontComplexScript = fonts.ComplexScript.Value;
1415
+
1416
+ // Theme font references (these override explicit names when a theme is active)
1417
+ if (fonts.AsciiTheme?.Value is not null) result.ThemeFontAscii = fonts.AsciiTheme.Value.ToString();
1418
+ if (fonts.EastAsiaTheme?.Value is not null) result.ThemeFontEastAsia = fonts.EastAsiaTheme.Value.ToString();
1419
+ }
1420
+
1421
+ // Font size
1422
+ var sz = rPr.GetFirstChild<FontSize>();
1423
+ if (sz?.Val?.Value is not null)
1424
+ {
1425
+ if (int.TryParse(sz.Val.Value, out var halfPts))
1426
+ result.SizePoints = halfPts / 2.0;
1427
+ }
1428
+
1429
+ // Bold — toggle property
1430
+ var bold = rPr.GetFirstChild<Bold>();
1431
+ if (bold is not null)
1432
+ {
1433
+ // <w:b/> means true; <w:b w:val="false"/> means false
1434
+ // WARNING: Bold is a "toggle" property in OpenXML.
1435
+ // In theory, if a parent style sets bold=true and a child style sets bold=true,
1436
+ // they XOR to false. In practice, most implementations treat it as a simple override.
1437
+ result.IsBold = bold.Val is null || bold.Val.Value;
1438
+ }
1439
+
1440
+ // Italic — also a toggle property
1441
+ var italic = rPr.GetFirstChild<Italic>();
1442
+ if (italic is not null)
1443
+ {
1444
+ result.IsItalic = italic.Val is null || italic.Val.Value;
1445
+ }
1446
+
1447
+ // Color
1448
+ var color = rPr.GetFirstChild<Color>();
1449
+ if (color?.Val?.Value is not null)
1450
+ {
1451
+ result.ColorHex = color.Val.Value;
1452
+ }
1453
+
1454
+ // Underline
1455
+ var underline = rPr.GetFirstChild<Underline>();
1456
+ if (underline?.Val is not null)
1457
+ {
1458
+ result.UnderlineStyle = underline.Val.Value.ToString();
1459
+ }
1460
+ }
1461
+
1462
+ /// <summary>
1463
+ /// Represents the fully resolved formatting after walking the inheritance chain.
1464
+ /// </summary>
1465
+ public class ResolvedFormatting
1466
+ {
1467
+ public string? FontAscii { get; set; }
1468
+ public string? FontHighAnsi { get; set; }
1469
+ public string? FontEastAsia { get; set; }
1470
+ public string? FontComplexScript { get; set; }
1471
+ public string? ThemeFontAscii { get; set; }
1472
+ public string? ThemeFontEastAsia { get; set; }
1473
+ public double SizePoints { get; set; }
1474
+ public bool IsBold { get; set; }
1475
+ public bool IsItalic { get; set; }
1476
+ public string? ColorHex { get; set; }
1477
+ public string? UnderlineStyle { get; set; }
1478
+
1479
+ public override string ToString() =>
1480
+ $"Font: {FontAscii ?? ThemeFontAscii ?? "?"}, " +
1481
+ $"EastAsia: {FontEastAsia ?? ThemeFontEastAsia ?? "?"}, " +
1482
+ $"Size: {SizePoints}pt, " +
1483
+ $"Bold: {IsBold}, Italic: {IsItalic}, " +
1484
+ $"Color: {ColorHex ?? "auto"}, " +
1485
+ $"Underline: {UnderlineStyle ?? "none"}";
1486
+ }
1487
+ }