@nguyenphp/antigravity-marketing 1.0.18 → 1.0.20

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 (231) hide show
  1. package/README.md +130 -78
  2. package/package.json +4 -3
  3. package/templates/.agent/skills/marketing-report-expert/SKILL.md +70 -0
  4. package/templates/.agent/skills/minimax-docx/LICENSE +21 -0
  5. package/templates/.agent/skills/minimax-docx/SKILL.md +274 -0
  6. package/templates/.agent/skills/minimax-docx/assets/styles/academic_styles.xml +250 -0
  7. package/templates/.agent/skills/minimax-docx/assets/styles/corporate_styles.xml +284 -0
  8. package/templates/.agent/skills/minimax-docx/assets/styles/default_styles.xml +449 -0
  9. package/templates/.agent/skills/minimax-docx/assets/xsd/aesthetic-rules.xsd +470 -0
  10. package/templates/.agent/skills/minimax-docx/assets/xsd/business-rules.xsd +130 -0
  11. package/templates/.agent/skills/minimax-docx/assets/xsd/common-types.xsd +159 -0
  12. package/templates/.agent/skills/minimax-docx/assets/xsd/wml-subset.xsd +589 -0
  13. package/templates/.agent/skills/minimax-docx/references/cjk_typography.md +357 -0
  14. package/templates/.agent/skills/minimax-docx/references/cjk_university_template_guide.md +184 -0
  15. package/templates/.agent/skills/minimax-docx/references/comments_guide.md +191 -0
  16. package/templates/.agent/skills/minimax-docx/references/design_good_bad_examples.md +829 -0
  17. package/templates/.agent/skills/minimax-docx/references/design_principles.md +819 -0
  18. package/templates/.agent/skills/minimax-docx/references/openxml_element_order.md +308 -0
  19. package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part1.md +4061 -0
  20. package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part2.md +2820 -0
  21. package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part3.md +3381 -0
  22. package/templates/.agent/skills/minimax-docx/references/openxml_namespaces.md +82 -0
  23. package/templates/.agent/skills/minimax-docx/references/openxml_units.md +72 -0
  24. package/templates/.agent/skills/minimax-docx/references/scenario_a_create.md +284 -0
  25. package/templates/.agent/skills/minimax-docx/references/scenario_b_edit_content.md +295 -0
  26. package/templates/.agent/skills/minimax-docx/references/scenario_c_apply_template.md +456 -0
  27. package/templates/.agent/skills/minimax-docx/references/track_changes_guide.md +200 -0
  28. package/templates/.agent/skills/minimax-docx/references/troubleshooting.md +506 -0
  29. package/templates/.agent/skills/minimax-docx/references/typography_guide.md +294 -0
  30. package/templates/.agent/skills/minimax-docx/references/xsd_validation_guide.md +158 -0
  31. package/templates/.agent/skills/minimax-docx/scripts/doc_to_docx.sh +40 -0
  32. package/templates/.agent/skills/minimax-docx/scripts/docx_preview.sh +37 -0
  33. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Cli/MiniMaxAIDocx.Cli.csproj +19 -0
  34. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Cli/Program.cs +18 -0
  35. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/AnalyzeCommand.cs +147 -0
  36. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/ApplyTemplateCommand.cs +322 -0
  37. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/CreateCommand.cs +324 -0
  38. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/DiffCommand.cs +155 -0
  39. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/EditContentCommand.cs +487 -0
  40. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/FixOrderCommand.cs +108 -0
  41. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/MergeRunsCommand.cs +122 -0
  42. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/ValidateCommand.cs +107 -0
  43. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/MiniMaxAIDocx.Core.csproj +15 -0
  44. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/CommentSynchronizer.cs +169 -0
  45. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/ElementOrder.cs +80 -0
  46. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/NamespaceConstants.cs +42 -0
  47. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/RunMerger.cs +81 -0
  48. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/StyleAnalyzer.cs +81 -0
  49. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/TrackChangesHelper.cs +99 -0
  50. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/UnitConverter.cs +23 -0
  51. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples.cs +1832 -0
  52. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch1.cs +910 -0
  53. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch2.cs +999 -0
  54. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch3.cs +1048 -0
  55. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch4.cs +1038 -0
  56. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/CharacterFormattingSamples.cs +1020 -0
  57. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/DocumentCreationSamples.cs +1121 -0
  58. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/FieldAndTocSamples.cs +624 -0
  59. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/FootnoteAndCommentSamples.cs +675 -0
  60. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/HeaderFooterSamples.cs +838 -0
  61. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ImageSamples.cs +917 -0
  62. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ListAndNumberingSamples.cs +826 -0
  63. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ParagraphFormattingSamples.cs +1199 -0
  64. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/StyleSystemSamples.cs +1487 -0
  65. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/TableSamples.cs +1163 -0
  66. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/TrackChangesSamples.cs +595 -0
  67. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/CjkHelper.cs +39 -0
  68. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/FontDefaults.cs +24 -0
  69. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/PageSizes.cs +20 -0
  70. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/BusinessRuleValidator.cs +224 -0
  71. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/GateCheckValidator.cs +148 -0
  72. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/ValidationResult.cs +23 -0
  73. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/XsdValidator.cs +69 -0
  74. package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.slnx +4 -0
  75. package/templates/.agent/skills/minimax-docx/scripts/env_check.sh +196 -0
  76. package/templates/.agent/skills/minimax-docx/scripts/setup.ps1 +274 -0
  77. package/templates/.agent/skills/minimax-docx/scripts/setup.sh +504 -0
  78. package/templates/.agent/skills/minimax-multimodal-toolkit/SKILL.md +359 -0
  79. package/templates/.agent/skills/minimax-pdf/README.md +222 -0
  80. package/templates/.agent/skills/minimax-pdf/SKILL.md +201 -0
  81. package/templates/.agent/skills/minimax-pdf/design/design.md +381 -0
  82. package/templates/.agent/skills/minimax-pdf/scripts/cover.py +1579 -0
  83. package/templates/.agent/skills/minimax-pdf/scripts/fill_inspect.py +200 -0
  84. package/templates/.agent/skills/minimax-pdf/scripts/fill_write.py +242 -0
  85. package/templates/.agent/skills/minimax-pdf/scripts/make.sh +491 -0
  86. package/templates/.agent/skills/minimax-pdf/scripts/merge.py +112 -0
  87. package/templates/.agent/skills/minimax-pdf/scripts/palette.py +559 -0
  88. package/templates/.agent/skills/minimax-pdf/scripts/reformat_parse.py +374 -0
  89. package/templates/.agent/skills/minimax-pdf/scripts/render_body.py +1055 -0
  90. package/templates/.agent/skills/minimax-pdf/scripts/render_cover.cjs +111 -0
  91. package/templates/.agent/skills/minimax-xlsx/SKILL.md +138 -0
  92. package/templates/.agent/skills/minimax-xlsx/references/create.md +691 -0
  93. package/templates/.agent/skills/minimax-xlsx/references/edit.md +684 -0
  94. package/templates/.agent/skills/minimax-xlsx/references/fix.md +37 -0
  95. package/templates/.agent/skills/minimax-xlsx/references/format.md +768 -0
  96. package/templates/.agent/skills/minimax-xlsx/references/ooxml-cheatsheet.md +231 -0
  97. package/templates/.agent/skills/minimax-xlsx/references/read-analyze.md +97 -0
  98. package/templates/.agent/skills/minimax-xlsx/references/validate.md +772 -0
  99. package/templates/.agent/skills/minimax-xlsx/scripts/formula_check.py +422 -0
  100. package/templates/.agent/skills/minimax-xlsx/scripts/libreoffice_recalc.py +248 -0
  101. package/templates/.agent/skills/minimax-xlsx/scripts/shared_strings_builder.py +163 -0
  102. package/templates/.agent/skills/minimax-xlsx/scripts/style_audit.py +575 -0
  103. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_add_column.py +395 -0
  104. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_insert_row.py +274 -0
  105. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_pack.py +87 -0
  106. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_reader.py +362 -0
  107. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_shift_rows.py +396 -0
  108. package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_unpack.py +130 -0
  109. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/[Content_Types].xml +9 -0
  110. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/_rels/.rels +6 -0
  111. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/_rels/workbook.xml.rels +19 -0
  112. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/sharedStrings.xml +33 -0
  113. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/styles.xml +160 -0
  114. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/workbook.xml +30 -0
  115. package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/worksheets/sheet1.xml +70 -0
  116. package/templates/.agent/skills/pptx-generator/SKILL.md +249 -0
  117. package/templates/.agent/skills/pptx-generator/references/design-system.md +392 -0
  118. package/templates/.agent/skills/pptx-generator/references/editing.md +162 -0
  119. package/templates/.agent/skills/pptx-generator/references/pitfalls.md +112 -0
  120. package/templates/.agent/skills/pptx-generator/references/pptxgenjs.md +420 -0
  121. package/templates/.agent/skills/pptx-generator/references/slide-types.md +413 -0
  122. package/templates/.agent/skills/tutorial-video-expert/SKILL.md +88 -0
  123. package/templates/.agent/skills/ui-ux-pro-max/SKILL.md +170 -585
  124. package/templates/.agent/skills/vision-analysis/SKILL.md +174 -0
  125. package/templates/.agent/workflows/analyze.md +3 -0
  126. package/templates/.agent/workflows/brand-report.md +44 -0
  127. package/templates/.agent/workflows/report.md +49 -0
  128. package/templates/.agent/agents/backend-specialist.md +0 -263
  129. package/templates/.agent/agents/database-architect.md +0 -226
  130. package/templates/.agent/agents/debugger.md +0 -225
  131. package/templates/.agent/agents/devops-engineer.md +0 -242
  132. package/templates/.agent/agents/frontend-specialist.md +0 -527
  133. package/templates/.agent/agents/game-developer.md +0 -162
  134. package/templates/.agent/agents/mobile-developer.md +0 -377
  135. package/templates/.agent/agents/penetration-tester.md +0 -188
  136. package/templates/.agent/agents/security-auditor.md +0 -170
  137. package/templates/.agent/agents/test-engineer.md +0 -158
  138. package/templates/.agent/skills/api-patterns/SKILL.md +0 -81
  139. package/templates/.agent/skills/api-patterns/api-style.md +0 -42
  140. package/templates/.agent/skills/api-patterns/auth.md +0 -24
  141. package/templates/.agent/skills/api-patterns/documentation.md +0 -26
  142. package/templates/.agent/skills/api-patterns/graphql.md +0 -41
  143. package/templates/.agent/skills/api-patterns/rate-limiting.md +0 -31
  144. package/templates/.agent/skills/api-patterns/response.md +0 -37
  145. package/templates/.agent/skills/api-patterns/rest.md +0 -40
  146. package/templates/.agent/skills/api-patterns/scripts/api_validator.py +0 -211
  147. package/templates/.agent/skills/api-patterns/security-testing.md +0 -122
  148. package/templates/.agent/skills/api-patterns/trpc.md +0 -41
  149. package/templates/.agent/skills/api-patterns/versioning.md +0 -22
  150. package/templates/.agent/skills/app-builder/SKILL.md +0 -75
  151. package/templates/.agent/skills/app-builder/agent-coordination.md +0 -71
  152. package/templates/.agent/skills/app-builder/feature-building.md +0 -53
  153. package/templates/.agent/skills/app-builder/project-detection.md +0 -34
  154. package/templates/.agent/skills/app-builder/scaffolding.md +0 -118
  155. package/templates/.agent/skills/app-builder/tech-stack.md +0 -40
  156. package/templates/.agent/skills/app-builder/templates/SKILL.md +0 -39
  157. package/templates/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +0 -76
  158. package/templates/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +0 -92
  159. package/templates/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +0 -88
  160. package/templates/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +0 -88
  161. package/templates/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +0 -83
  162. package/templates/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +0 -90
  163. package/templates/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +0 -90
  164. package/templates/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +0 -82
  165. package/templates/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +0 -100
  166. package/templates/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +0 -106
  167. package/templates/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +0 -101
  168. package/templates/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +0 -83
  169. package/templates/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +0 -93
  170. package/templates/.agent/skills/architecture/SKILL.md +0 -55
  171. package/templates/.agent/skills/architecture/context-discovery.md +0 -43
  172. package/templates/.agent/skills/architecture/examples.md +0 -94
  173. package/templates/.agent/skills/architecture/pattern-selection.md +0 -68
  174. package/templates/.agent/skills/architecture/patterns-reference.md +0 -50
  175. package/templates/.agent/skills/architecture/trade-off-analysis.md +0 -77
  176. package/templates/.agent/skills/bash-linux/SKILL.md +0 -199
  177. package/templates/.agent/skills/behavioral-modes/SKILL.md +0 -242
  178. package/templates/.agent/skills/clean-code/SKILL.md +0 -201
  179. package/templates/.agent/skills/code-review-checklist/SKILL.md +0 -109
  180. package/templates/.agent/skills/database-design/SKILL.md +0 -52
  181. package/templates/.agent/skills/database-design/database-selection.md +0 -43
  182. package/templates/.agent/skills/database-design/indexing.md +0 -39
  183. package/templates/.agent/skills/database-design/migrations.md +0 -48
  184. package/templates/.agent/skills/database-design/optimization.md +0 -36
  185. package/templates/.agent/skills/database-design/orm-selection.md +0 -30
  186. package/templates/.agent/skills/database-design/schema-design.md +0 -56
  187. package/templates/.agent/skills/database-design/scripts/schema_validator.py +0 -172
  188. package/templates/.agent/skills/deployment-procedures/SKILL.md +0 -241
  189. package/templates/.agent/skills/docker-expert/SKILL.md +0 -409
  190. package/templates/.agent/skills/game-development/2d-games/SKILL.md +0 -119
  191. package/templates/.agent/skills/game-development/3d-games/SKILL.md +0 -135
  192. package/templates/.agent/skills/game-development/SKILL.md +0 -167
  193. package/templates/.agent/skills/game-development/game-art/SKILL.md +0 -185
  194. package/templates/.agent/skills/game-development/game-audio/SKILL.md +0 -190
  195. package/templates/.agent/skills/game-development/game-design/SKILL.md +0 -129
  196. package/templates/.agent/skills/game-development/mobile-games/SKILL.md +0 -108
  197. package/templates/.agent/skills/game-development/multiplayer/SKILL.md +0 -132
  198. package/templates/.agent/skills/game-development/pc-games/SKILL.md +0 -144
  199. package/templates/.agent/skills/game-development/vr-ar/SKILL.md +0 -123
  200. package/templates/.agent/skills/game-development/web-games/SKILL.md +0 -150
  201. package/templates/.agent/skills/lint-and-validate/SKILL.md +0 -45
  202. package/templates/.agent/skills/lint-and-validate/scripts/lint_runner.py +0 -172
  203. package/templates/.agent/skills/lint-and-validate/scripts/type_coverage.py +0 -173
  204. package/templates/.agent/skills/mcp-builder/SKILL.md +0 -176
  205. package/templates/.agent/skills/nestjs-expert/SKILL.md +0 -552
  206. package/templates/.agent/skills/nextjs-best-practices/SKILL.md +0 -203
  207. package/templates/.agent/skills/nodejs-best-practices/SKILL.md +0 -333
  208. package/templates/.agent/skills/parallel-agents/SKILL.md +0 -175
  209. package/templates/.agent/skills/performance-profiling/SKILL.md +0 -143
  210. package/templates/.agent/skills/performance-profiling/scripts/lighthouse_audit.py +0 -76
  211. package/templates/.agent/skills/powershell-windows/SKILL.md +0 -167
  212. package/templates/.agent/skills/prisma-expert/SKILL.md +0 -355
  213. package/templates/.agent/skills/python-patterns/SKILL.md +0 -441
  214. package/templates/.agent/skills/react-patterns/SKILL.md +0 -198
  215. package/templates/.agent/skills/red-team-tactics/SKILL.md +0 -199
  216. package/templates/.agent/skills/server-management/SKILL.md +0 -161
  217. package/templates/.agent/skills/systematic-debugging/SKILL.md +0 -109
  218. package/templates/.agent/skills/tdd-workflow/SKILL.md +0 -149
  219. package/templates/.agent/skills/testing-patterns/SKILL.md +0 -178
  220. package/templates/.agent/skills/testing-patterns/scripts/test_runner.py +0 -219
  221. package/templates/.agent/skills/typescript-expert/SKILL.md +0 -429
  222. package/templates/.agent/skills/vue-expert/SKILL.md +0 -374
  223. package/templates/.agent/skills/vulnerability-scanner/SKILL.md +0 -276
  224. package/templates/.agent/skills/vulnerability-scanner/checklists.md +0 -121
  225. package/templates/.agent/skills/vulnerability-scanner/scripts/security_scan.py +0 -458
  226. package/templates/.agent/skills/webapp-testing/SKILL.md +0 -187
  227. package/templates/.agent/skills/webapp-testing/scripts/playwright_runner.py +0 -173
  228. package/templates/.agent/workflows/debug.md +0 -103
  229. package/templates/.agent/workflows/deploy.md +0 -176
  230. package/templates/.agent/workflows/enhance.md +0 -63
  231. package/templates/.agent/workflows/test.md +0 -144
@@ -0,0 +1,374 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ reformat_parse.py — Convert an existing document into content.json,
4
+ then hand off to the CREATE pipeline (render_body.py).
5
+
6
+ Supported input formats:
7
+ .md / .txt — Markdown / plain text
8
+ .pdf — Extract text from existing PDF (layout preserved as best-effort)
9
+ .json — Pass-through if already content.json format
10
+
11
+ Usage:
12
+ python3 reformat_parse.py --input doc.md --out content.json
13
+ python3 reformat_parse.py --input old.pdf --out content.json
14
+ python3 reformat_parse.py --input data.json --out content.json
15
+
16
+ Then pipe into the CREATE pipeline:
17
+ python3 render_body.py --tokens tokens.json --content content.json --out body.pdf
18
+
19
+ Or use make.sh reformat which does both steps:
20
+ bash make.sh reformat --input doc.md --type report --title "My Report" --out output.pdf
21
+
22
+ Exit codes: 0 success, 1 bad args / unsupported format, 2 dep missing, 3 parse error
23
+ """
24
+
25
+ import argparse
26
+ import json
27
+ import os
28
+ import re
29
+ import sys
30
+ import importlib.util
31
+ from pathlib import Path
32
+
33
+
34
+
35
+
36
+ def ensure_deps():
37
+ missing = []
38
+ if importlib.util.find_spec("pypdf") is None:
39
+ missing.append("pypdf")
40
+ if missing:
41
+ import subprocess
42
+ subprocess.check_call(
43
+ [sys.executable, "-m", "pip", "install", "--break-system-packages", "-q"] + missing
44
+ )
45
+
46
+
47
+ ensure_deps()
48
+
49
+
50
+ # ── Markdown / plain text parser ───────────────────────────────────────────────
51
+ def parse_markdown(text: str) -> list:
52
+ """
53
+ Convert Markdown to content.json blocks.
54
+ Supports: # headings, **bold**, bullet lists, > blockquotes (→ callout),
55
+ | tables |, plain paragraphs.
56
+ """
57
+ blocks = []
58
+ lines = text.splitlines()
59
+ i = 0
60
+
61
+ def flush_para(buf: list):
62
+ t = " ".join(buf).strip()
63
+ if t:
64
+ blocks.append({"type": "body", "text": _md_inline(t)})
65
+
66
+ para_buf = []
67
+
68
+ while i < len(lines):
69
+ line = lines[i]
70
+ stripped = line.strip()
71
+
72
+ # Blank line — flush paragraph buffer
73
+ if not stripped:
74
+ flush_para(para_buf)
75
+ para_buf = []
76
+ i += 1
77
+ continue
78
+
79
+ # ATX Headings: # ## ###
80
+ m = re.match(r'^(#{1,3})\s+(.*)', stripped)
81
+ if m:
82
+ flush_para(para_buf)
83
+ para_buf = []
84
+ level = len(m.group(1))
85
+ htype = {1: "h1", 2: "h2", 3: "h3"}.get(level, "h3")
86
+ blocks.append({"type": htype, "text": _md_inline(m.group(2))})
87
+ i += 1
88
+ continue
89
+
90
+ # Display math block: $$expr$$ on one line, or opening $$ ... closing $$
91
+ if stripped.startswith("$$"):
92
+ flush_para(para_buf)
93
+ para_buf = []
94
+ inline_expr = stripped[2:].rstrip("$").strip()
95
+ if inline_expr:
96
+ # Single-line: $$E = mc^2$$
97
+ blocks.append({"type": "math", "text": inline_expr})
98
+ i += 1
99
+ else:
100
+ # Multi-line: opening $$ alone, then expression lines, then closing $$
101
+ math_lines = []
102
+ i += 1
103
+ while i < len(lines) and lines[i].strip() != "$$":
104
+ math_lines.append(lines[i])
105
+ i += 1
106
+ if i < len(lines):
107
+ i += 1 # skip closing $$
108
+ blocks.append({"type": "math", "text": "\n".join(math_lines).strip()})
109
+ continue
110
+
111
+ # Fenced code block: ``` or ~~~
112
+ if stripped.startswith("```") or stripped.startswith("~~~"):
113
+ flush_para(para_buf)
114
+ para_buf = []
115
+ fence = stripped[:3]
116
+ code_lines = []
117
+ i += 1
118
+ while i < len(lines) and not lines[i].strip().startswith(fence):
119
+ code_lines.append(lines[i])
120
+ i += 1
121
+ if i < len(lines):
122
+ i += 1 # skip closing fence
123
+ blocks.append({"type": "code", "text": "\n".join(code_lines)})
124
+ continue
125
+
126
+ # Blockquote → callout
127
+ if stripped.startswith(">"):
128
+ flush_para(para_buf)
129
+ para_buf = []
130
+ qt = re.sub(r'^>\s*', '', stripped)
131
+ blocks.append({"type": "callout", "text": _md_inline(qt)})
132
+ i += 1
133
+ continue
134
+
135
+ # Unordered bullet: -, *, +
136
+ if re.match(r'^[-*+]\s+', stripped):
137
+ flush_para(para_buf)
138
+ para_buf = []
139
+ text_part = re.sub(r'^[-*+]\s+', '', stripped)
140
+ blocks.append({"type": "bullet", "text": _md_inline(text_part)})
141
+ i += 1
142
+ continue
143
+
144
+ # Ordered list: 1. 2. etc. → numbered (preserves counter in render_body)
145
+ if re.match(r'^\d+\.\s+', stripped):
146
+ flush_para(para_buf)
147
+ para_buf = []
148
+ text_part = re.sub(r'^\d+\.\s+', '', stripped)
149
+ blocks.append({"type": "numbered", "text": _md_inline(text_part)})
150
+ i += 1
151
+ continue
152
+
153
+ # Table: | col | col |
154
+ if stripped.startswith("|"):
155
+ flush_para(para_buf)
156
+ para_buf = []
157
+ table_lines = []
158
+ while i < len(lines) and lines[i].strip().startswith("|"):
159
+ table_lines.append(lines[i].strip())
160
+ i += 1
161
+ # Remove separator rows (|---|---|)
162
+ data_rows = [r for r in table_lines if not re.match(r'^\|[-:| ]+\|$', r)]
163
+ parsed = []
164
+ for row in data_rows:
165
+ cells = [c.strip() for c in row.strip("|").split("|")]
166
+ parsed.append(cells)
167
+ if len(parsed) >= 2:
168
+ blocks.append({
169
+ "type": "table",
170
+ "headers": parsed[0],
171
+ "rows": parsed[1:],
172
+ })
173
+ elif len(parsed) == 1:
174
+ # Single row — treat as paragraph
175
+ blocks.append({"type": "body", "text": " | ".join(parsed[0])})
176
+ continue
177
+
178
+ # Horizontal rule → spacer
179
+ if re.match(r'^[-*_]{3,}$', stripped):
180
+ flush_para(para_buf)
181
+ para_buf = []
182
+ blocks.append({"type": "spacer", "pt": 16})
183
+ i += 1
184
+ continue
185
+
186
+ # Plain text → accumulate into paragraph
187
+ para_buf.append(stripped)
188
+ i += 1
189
+
190
+ flush_para(para_buf)
191
+ return blocks
192
+
193
+
194
+ def _md_inline(text: str) -> str:
195
+ """Convert inline Markdown to ReportLab XML markup."""
196
+ # Bold: **text** or __text__
197
+ text = re.sub(r'\*\*(.+?)\*\*', r'<b>\1</b>', text)
198
+ text = re.sub(r'__(.+?)__', r'<b>\1</b>', text)
199
+ # Italic: *text* or _text_
200
+ text = re.sub(r'\*(.+?)\*', r'<i>\1</i>', text)
201
+ text = re.sub(r'_(.+?)_', r'<i>\1</i>', text)
202
+ # Inline code: `code`
203
+ text = re.sub(r'`(.+?)`', r'<font name="Courier">\1</font>', text)
204
+ # Strip markdown links, keep text
205
+ text = re.sub(r'\[(.+?)\]\(.+?\)', r'\1', text)
206
+ return text
207
+
208
+
209
+ # ── PDF text extractor ─────────────────────────────────────────────────────────
210
+ def parse_pdf(pdf_path: str) -> list:
211
+ """
212
+ Extract text from an existing PDF and convert to content.json blocks.
213
+ Best-effort: detects headings by font size heuristics if available,
214
+ otherwise falls back to paragraph splitting.
215
+ """
216
+ from pypdf import PdfReader
217
+
218
+ reader = PdfReader(pdf_path)
219
+ all_text = []
220
+
221
+ for page in reader.pages:
222
+ text = page.extract_text()
223
+ if text:
224
+ all_text.append(text.strip())
225
+
226
+ full_text = "\n\n".join(all_text)
227
+
228
+ # Treat extracted PDF text as plain text / light markdown
229
+ # (most PDFs lose formatting — we do our best)
230
+ return parse_plain(full_text)
231
+
232
+
233
+ def parse_plain(text: str) -> list:
234
+ """
235
+ Heuristic plain-text parser.
236
+ Short ALL-CAPS or title-case lines → headings.
237
+ Everything else → paragraphs.
238
+ """
239
+ blocks = []
240
+ paragraphs = re.split(r'\n{2,}', text.strip())
241
+
242
+ for para in paragraphs:
243
+ para = para.strip()
244
+ if not para:
245
+ continue
246
+
247
+ lines = para.splitlines()
248
+
249
+ # Single short line that looks like a heading
250
+ if len(lines) == 1 and len(para) < 80:
251
+ if para.isupper() or re.match(r'^[A-Z][^.!?]*$', para):
252
+ blocks.append({"type": "h1", "text": para.title()})
253
+ continue
254
+
255
+ # Bullet lists
256
+ if lines[0].startswith(("- ", "• ", "* ")):
257
+ for line in lines:
258
+ text_part = re.sub(r'^[-•*]\s+', '', line.strip())
259
+ if text_part:
260
+ blocks.append({"type": "bullet", "text": text_part})
261
+ continue
262
+
263
+ # Regular paragraph
264
+ blocks.append({"type": "body", "text": " ".join(lines)})
265
+
266
+ return blocks
267
+
268
+
269
+ # ── Pass-through validator ─────────────────────────────────────────────────────
270
+ VALID_TYPES = {"h1","h2","h3","body","bullet","numbered","callout","table",
271
+ "image","code","math","divider","caption","pagebreak","spacer"}
272
+
273
+ def validate_content_json(data: list) -> tuple[list, list]:
274
+ """Return (valid_blocks, warnings)."""
275
+ valid, warnings = [], []
276
+ for i, block in enumerate(data):
277
+ if not isinstance(block, dict):
278
+ warnings.append(f"Block {i}: not a dict, skipped")
279
+ continue
280
+ btype = block.get("type")
281
+ if btype not in VALID_TYPES:
282
+ warnings.append(f"Block {i}: unknown type '{btype}', kept as-is")
283
+ valid.append(block)
284
+ return valid, warnings
285
+
286
+
287
+ # ── Dispatcher ─────────────────────────────────────────────────────────────────
288
+ def parse_file(input_path: str) -> tuple[list, list]:
289
+ """Return (blocks, warnings)."""
290
+ ext = Path(input_path).suffix.lower()
291
+
292
+ if ext in (".md", ".txt", ".markdown"):
293
+ with open(input_path, encoding="utf-8", errors="replace") as f:
294
+ text = f.read()
295
+ blocks = parse_markdown(text)
296
+ return blocks, []
297
+
298
+ if ext == ".pdf":
299
+ blocks = parse_pdf(input_path)
300
+ return blocks, ["PDF text extraction is best-effort — review content.json before rendering"]
301
+
302
+ if ext == ".json":
303
+ with open(input_path) as f:
304
+ data = json.load(f)
305
+ if isinstance(data, list):
306
+ return validate_content_json(data)
307
+ # Maybe it's a meta-wrapper {"content": [...]}
308
+ if isinstance(data, dict) and "content" in data:
309
+ return validate_content_json(data["content"])
310
+ return [], [f"JSON file does not contain a list of content blocks"]
311
+
312
+ return [], [f"Unsupported file type: {ext}. Supported: .md .txt .pdf .json"]
313
+
314
+
315
+ # ── CLI ────────────────────────────────────────────────────────────────────────
316
+ def main():
317
+ parser = argparse.ArgumentParser(description="Parse a document into content.json")
318
+ parser.add_argument("--input", required=True, help="Input file (.md, .txt, .pdf, .json)")
319
+ parser.add_argument("--out", default="content.json", help="Output content.json path")
320
+ args = parser.parse_args()
321
+
322
+ if not os.path.exists(args.input):
323
+ print(json.dumps({"status": "error", "error": f"File not found: {args.input}"}),
324
+ file=sys.stderr)
325
+ sys.exit(1)
326
+
327
+ try:
328
+ blocks, warnings = parse_file(args.input)
329
+ except Exception as e:
330
+ import traceback
331
+ print(json.dumps({"status": "error", "error": str(e),
332
+ "trace": traceback.format_exc()}), file=sys.stderr)
333
+ sys.exit(3)
334
+
335
+ if not blocks:
336
+ print(json.dumps({
337
+ "status": "error",
338
+ "error": "No content blocks extracted",
339
+ "warnings": warnings,
340
+ }), file=sys.stderr)
341
+ sys.exit(3)
342
+
343
+ with open(args.out, "w", encoding="utf-8") as f:
344
+ json.dump(blocks, f, indent=2, ensure_ascii=False)
345
+
346
+ result = {
347
+ "status": "ok",
348
+ "out": args.out,
349
+ "block_count": len(blocks),
350
+ "warnings": warnings,
351
+ }
352
+ print(json.dumps(result, indent=2))
353
+
354
+ print(f"\n── Parsed {args.input} ─────────────────────────────────────",
355
+ file=sys.stderr)
356
+ print(f" Blocks : {len(blocks)}", file=sys.stderr)
357
+
358
+ type_counts: dict = {}
359
+ for b in blocks:
360
+ type_counts[b.get("type","?")] = type_counts.get(b.get("type","?"), 0) + 1
361
+ for t, n in sorted(type_counts.items()):
362
+ print(f" {t:12} × {n}", file=sys.stderr)
363
+
364
+ if warnings:
365
+ print(f" Warnings:", file=sys.stderr)
366
+ for w in warnings:
367
+ print(f" ⚠ {w}", file=sys.stderr)
368
+ print(f"\n Next: bash make.sh run --content {args.out} --title '...' --type ...",
369
+ file=sys.stderr)
370
+ print("", file=sys.stderr)
371
+
372
+
373
+ if __name__ == "__main__":
374
+ main()