@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.
- package/README.md +130 -78
- package/package.json +4 -3
- package/templates/.agent/skills/marketing-report-expert/SKILL.md +70 -0
- package/templates/.agent/skills/minimax-docx/LICENSE +21 -0
- package/templates/.agent/skills/minimax-docx/SKILL.md +274 -0
- package/templates/.agent/skills/minimax-docx/assets/styles/academic_styles.xml +250 -0
- package/templates/.agent/skills/minimax-docx/assets/styles/corporate_styles.xml +284 -0
- package/templates/.agent/skills/minimax-docx/assets/styles/default_styles.xml +449 -0
- package/templates/.agent/skills/minimax-docx/assets/xsd/aesthetic-rules.xsd +470 -0
- package/templates/.agent/skills/minimax-docx/assets/xsd/business-rules.xsd +130 -0
- package/templates/.agent/skills/minimax-docx/assets/xsd/common-types.xsd +159 -0
- package/templates/.agent/skills/minimax-docx/assets/xsd/wml-subset.xsd +589 -0
- package/templates/.agent/skills/minimax-docx/references/cjk_typography.md +357 -0
- package/templates/.agent/skills/minimax-docx/references/cjk_university_template_guide.md +184 -0
- package/templates/.agent/skills/minimax-docx/references/comments_guide.md +191 -0
- package/templates/.agent/skills/minimax-docx/references/design_good_bad_examples.md +829 -0
- package/templates/.agent/skills/minimax-docx/references/design_principles.md +819 -0
- package/templates/.agent/skills/minimax-docx/references/openxml_element_order.md +308 -0
- package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part1.md +4061 -0
- package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part2.md +2820 -0
- package/templates/.agent/skills/minimax-docx/references/openxml_encyclopedia_part3.md +3381 -0
- package/templates/.agent/skills/minimax-docx/references/openxml_namespaces.md +82 -0
- package/templates/.agent/skills/minimax-docx/references/openxml_units.md +72 -0
- package/templates/.agent/skills/minimax-docx/references/scenario_a_create.md +284 -0
- package/templates/.agent/skills/minimax-docx/references/scenario_b_edit_content.md +295 -0
- package/templates/.agent/skills/minimax-docx/references/scenario_c_apply_template.md +456 -0
- package/templates/.agent/skills/minimax-docx/references/track_changes_guide.md +200 -0
- package/templates/.agent/skills/minimax-docx/references/troubleshooting.md +506 -0
- package/templates/.agent/skills/minimax-docx/references/typography_guide.md +294 -0
- package/templates/.agent/skills/minimax-docx/references/xsd_validation_guide.md +158 -0
- package/templates/.agent/skills/minimax-docx/scripts/doc_to_docx.sh +40 -0
- package/templates/.agent/skills/minimax-docx/scripts/docx_preview.sh +37 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Cli/MiniMaxAIDocx.Cli.csproj +19 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Cli/Program.cs +18 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/AnalyzeCommand.cs +147 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/ApplyTemplateCommand.cs +322 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/CreateCommand.cs +324 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/DiffCommand.cs +155 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/EditContentCommand.cs +487 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/FixOrderCommand.cs +108 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/MergeRunsCommand.cs +122 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Commands/ValidateCommand.cs +107 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/MiniMaxAIDocx.Core.csproj +15 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/CommentSynchronizer.cs +169 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/ElementOrder.cs +80 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/NamespaceConstants.cs +42 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/RunMerger.cs +81 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/StyleAnalyzer.cs +81 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/TrackChangesHelper.cs +99 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/UnitConverter.cs +23 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples.cs +1832 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch1.cs +910 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch2.cs +999 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch3.cs +1048 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/AestheticRecipeSamples_Batch4.cs +1038 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/CharacterFormattingSamples.cs +1020 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/DocumentCreationSamples.cs +1121 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/FieldAndTocSamples.cs +624 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/FootnoteAndCommentSamples.cs +675 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/HeaderFooterSamples.cs +838 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ImageSamples.cs +917 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ListAndNumberingSamples.cs +826 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/ParagraphFormattingSamples.cs +1199 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/StyleSystemSamples.cs +1487 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/TableSamples.cs +1163 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Samples/TrackChangesSamples.cs +595 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/CjkHelper.cs +39 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/FontDefaults.cs +24 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Typography/PageSizes.cs +20 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/BusinessRuleValidator.cs +224 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/GateCheckValidator.cs +148 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/ValidationResult.cs +23 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/Validation/XsdValidator.cs +69 -0
- package/templates/.agent/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.slnx +4 -0
- package/templates/.agent/skills/minimax-docx/scripts/env_check.sh +196 -0
- package/templates/.agent/skills/minimax-docx/scripts/setup.ps1 +274 -0
- package/templates/.agent/skills/minimax-docx/scripts/setup.sh +504 -0
- package/templates/.agent/skills/minimax-multimodal-toolkit/SKILL.md +359 -0
- package/templates/.agent/skills/minimax-pdf/README.md +222 -0
- package/templates/.agent/skills/minimax-pdf/SKILL.md +201 -0
- package/templates/.agent/skills/minimax-pdf/design/design.md +381 -0
- package/templates/.agent/skills/minimax-pdf/scripts/cover.py +1579 -0
- package/templates/.agent/skills/minimax-pdf/scripts/fill_inspect.py +200 -0
- package/templates/.agent/skills/minimax-pdf/scripts/fill_write.py +242 -0
- package/templates/.agent/skills/minimax-pdf/scripts/make.sh +491 -0
- package/templates/.agent/skills/minimax-pdf/scripts/merge.py +112 -0
- package/templates/.agent/skills/minimax-pdf/scripts/palette.py +559 -0
- package/templates/.agent/skills/minimax-pdf/scripts/reformat_parse.py +374 -0
- package/templates/.agent/skills/minimax-pdf/scripts/render_body.py +1055 -0
- package/templates/.agent/skills/minimax-pdf/scripts/render_cover.cjs +111 -0
- package/templates/.agent/skills/minimax-xlsx/SKILL.md +138 -0
- package/templates/.agent/skills/minimax-xlsx/references/create.md +691 -0
- package/templates/.agent/skills/minimax-xlsx/references/edit.md +684 -0
- package/templates/.agent/skills/minimax-xlsx/references/fix.md +37 -0
- package/templates/.agent/skills/minimax-xlsx/references/format.md +768 -0
- package/templates/.agent/skills/minimax-xlsx/references/ooxml-cheatsheet.md +231 -0
- package/templates/.agent/skills/minimax-xlsx/references/read-analyze.md +97 -0
- package/templates/.agent/skills/minimax-xlsx/references/validate.md +772 -0
- package/templates/.agent/skills/minimax-xlsx/scripts/formula_check.py +422 -0
- package/templates/.agent/skills/minimax-xlsx/scripts/libreoffice_recalc.py +248 -0
- package/templates/.agent/skills/minimax-xlsx/scripts/shared_strings_builder.py +163 -0
- package/templates/.agent/skills/minimax-xlsx/scripts/style_audit.py +575 -0
- package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_add_column.py +395 -0
- package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_insert_row.py +274 -0
- package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_pack.py +87 -0
- package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_reader.py +362 -0
- package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_shift_rows.py +396 -0
- package/templates/.agent/skills/minimax-xlsx/scripts/xlsx_unpack.py +130 -0
- package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/[Content_Types].xml +9 -0
- package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/_rels/.rels +6 -0
- package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/_rels/workbook.xml.rels +19 -0
- package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/sharedStrings.xml +33 -0
- package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/styles.xml +160 -0
- package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/workbook.xml +30 -0
- package/templates/.agent/skills/minimax-xlsx/templates/minimal_xlsx/xl/worksheets/sheet1.xml +70 -0
- package/templates/.agent/skills/pptx-generator/SKILL.md +249 -0
- package/templates/.agent/skills/pptx-generator/references/design-system.md +392 -0
- package/templates/.agent/skills/pptx-generator/references/editing.md +162 -0
- package/templates/.agent/skills/pptx-generator/references/pitfalls.md +112 -0
- package/templates/.agent/skills/pptx-generator/references/pptxgenjs.md +420 -0
- package/templates/.agent/skills/pptx-generator/references/slide-types.md +413 -0
- package/templates/.agent/skills/tutorial-video-expert/SKILL.md +88 -0
- package/templates/.agent/skills/ui-ux-pro-max/SKILL.md +170 -585
- package/templates/.agent/skills/vision-analysis/SKILL.md +174 -0
- package/templates/.agent/workflows/analyze.md +3 -0
- package/templates/.agent/workflows/brand-report.md +44 -0
- package/templates/.agent/workflows/report.md +49 -0
- package/templates/.agent/agents/backend-specialist.md +0 -263
- package/templates/.agent/agents/database-architect.md +0 -226
- package/templates/.agent/agents/debugger.md +0 -225
- package/templates/.agent/agents/devops-engineer.md +0 -242
- package/templates/.agent/agents/frontend-specialist.md +0 -527
- package/templates/.agent/agents/game-developer.md +0 -162
- package/templates/.agent/agents/mobile-developer.md +0 -377
- package/templates/.agent/agents/penetration-tester.md +0 -188
- package/templates/.agent/agents/security-auditor.md +0 -170
- package/templates/.agent/agents/test-engineer.md +0 -158
- package/templates/.agent/skills/api-patterns/SKILL.md +0 -81
- package/templates/.agent/skills/api-patterns/api-style.md +0 -42
- package/templates/.agent/skills/api-patterns/auth.md +0 -24
- package/templates/.agent/skills/api-patterns/documentation.md +0 -26
- package/templates/.agent/skills/api-patterns/graphql.md +0 -41
- package/templates/.agent/skills/api-patterns/rate-limiting.md +0 -31
- package/templates/.agent/skills/api-patterns/response.md +0 -37
- package/templates/.agent/skills/api-patterns/rest.md +0 -40
- package/templates/.agent/skills/api-patterns/scripts/api_validator.py +0 -211
- package/templates/.agent/skills/api-patterns/security-testing.md +0 -122
- package/templates/.agent/skills/api-patterns/trpc.md +0 -41
- package/templates/.agent/skills/api-patterns/versioning.md +0 -22
- package/templates/.agent/skills/app-builder/SKILL.md +0 -75
- package/templates/.agent/skills/app-builder/agent-coordination.md +0 -71
- package/templates/.agent/skills/app-builder/feature-building.md +0 -53
- package/templates/.agent/skills/app-builder/project-detection.md +0 -34
- package/templates/.agent/skills/app-builder/scaffolding.md +0 -118
- package/templates/.agent/skills/app-builder/tech-stack.md +0 -40
- package/templates/.agent/skills/app-builder/templates/SKILL.md +0 -39
- package/templates/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +0 -76
- package/templates/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +0 -92
- package/templates/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +0 -88
- package/templates/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +0 -88
- package/templates/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +0 -83
- package/templates/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +0 -90
- package/templates/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +0 -90
- package/templates/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +0 -82
- package/templates/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +0 -100
- package/templates/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +0 -106
- package/templates/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +0 -101
- package/templates/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +0 -83
- package/templates/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +0 -93
- package/templates/.agent/skills/architecture/SKILL.md +0 -55
- package/templates/.agent/skills/architecture/context-discovery.md +0 -43
- package/templates/.agent/skills/architecture/examples.md +0 -94
- package/templates/.agent/skills/architecture/pattern-selection.md +0 -68
- package/templates/.agent/skills/architecture/patterns-reference.md +0 -50
- package/templates/.agent/skills/architecture/trade-off-analysis.md +0 -77
- package/templates/.agent/skills/bash-linux/SKILL.md +0 -199
- package/templates/.agent/skills/behavioral-modes/SKILL.md +0 -242
- package/templates/.agent/skills/clean-code/SKILL.md +0 -201
- package/templates/.agent/skills/code-review-checklist/SKILL.md +0 -109
- package/templates/.agent/skills/database-design/SKILL.md +0 -52
- package/templates/.agent/skills/database-design/database-selection.md +0 -43
- package/templates/.agent/skills/database-design/indexing.md +0 -39
- package/templates/.agent/skills/database-design/migrations.md +0 -48
- package/templates/.agent/skills/database-design/optimization.md +0 -36
- package/templates/.agent/skills/database-design/orm-selection.md +0 -30
- package/templates/.agent/skills/database-design/schema-design.md +0 -56
- package/templates/.agent/skills/database-design/scripts/schema_validator.py +0 -172
- package/templates/.agent/skills/deployment-procedures/SKILL.md +0 -241
- package/templates/.agent/skills/docker-expert/SKILL.md +0 -409
- package/templates/.agent/skills/game-development/2d-games/SKILL.md +0 -119
- package/templates/.agent/skills/game-development/3d-games/SKILL.md +0 -135
- package/templates/.agent/skills/game-development/SKILL.md +0 -167
- package/templates/.agent/skills/game-development/game-art/SKILL.md +0 -185
- package/templates/.agent/skills/game-development/game-audio/SKILL.md +0 -190
- package/templates/.agent/skills/game-development/game-design/SKILL.md +0 -129
- package/templates/.agent/skills/game-development/mobile-games/SKILL.md +0 -108
- package/templates/.agent/skills/game-development/multiplayer/SKILL.md +0 -132
- package/templates/.agent/skills/game-development/pc-games/SKILL.md +0 -144
- package/templates/.agent/skills/game-development/vr-ar/SKILL.md +0 -123
- package/templates/.agent/skills/game-development/web-games/SKILL.md +0 -150
- package/templates/.agent/skills/lint-and-validate/SKILL.md +0 -45
- package/templates/.agent/skills/lint-and-validate/scripts/lint_runner.py +0 -172
- package/templates/.agent/skills/lint-and-validate/scripts/type_coverage.py +0 -173
- package/templates/.agent/skills/mcp-builder/SKILL.md +0 -176
- package/templates/.agent/skills/nestjs-expert/SKILL.md +0 -552
- package/templates/.agent/skills/nextjs-best-practices/SKILL.md +0 -203
- package/templates/.agent/skills/nodejs-best-practices/SKILL.md +0 -333
- package/templates/.agent/skills/parallel-agents/SKILL.md +0 -175
- package/templates/.agent/skills/performance-profiling/SKILL.md +0 -143
- package/templates/.agent/skills/performance-profiling/scripts/lighthouse_audit.py +0 -76
- package/templates/.agent/skills/powershell-windows/SKILL.md +0 -167
- package/templates/.agent/skills/prisma-expert/SKILL.md +0 -355
- package/templates/.agent/skills/python-patterns/SKILL.md +0 -441
- package/templates/.agent/skills/react-patterns/SKILL.md +0 -198
- package/templates/.agent/skills/red-team-tactics/SKILL.md +0 -199
- package/templates/.agent/skills/server-management/SKILL.md +0 -161
- package/templates/.agent/skills/systematic-debugging/SKILL.md +0 -109
- package/templates/.agent/skills/tdd-workflow/SKILL.md +0 -149
- package/templates/.agent/skills/testing-patterns/SKILL.md +0 -178
- package/templates/.agent/skills/testing-patterns/scripts/test_runner.py +0 -219
- package/templates/.agent/skills/typescript-expert/SKILL.md +0 -429
- package/templates/.agent/skills/vue-expert/SKILL.md +0 -374
- package/templates/.agent/skills/vulnerability-scanner/SKILL.md +0 -276
- package/templates/.agent/skills/vulnerability-scanner/checklists.md +0 -121
- package/templates/.agent/skills/vulnerability-scanner/scripts/security_scan.py +0 -458
- package/templates/.agent/skills/webapp-testing/SKILL.md +0 -187
- package/templates/.agent/skills/webapp-testing/scripts/playwright_runner.py +0 -173
- package/templates/.agent/workflows/debug.md +0 -103
- package/templates/.agent/workflows/deploy.md +0 -176
- package/templates/.agent/workflows/enhance.md +0 -63
- package/templates/.agent/workflows/test.md +0 -144
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# make.sh — minimax-pdf unified CLI
|
|
3
|
+
# Usage: bash make.sh <command> [options]
|
|
4
|
+
#
|
|
5
|
+
# Commands:
|
|
6
|
+
# check Verify all dependencies
|
|
7
|
+
# fix Auto-install missing dependencies
|
|
8
|
+
# run --title T --type TYPE Full pipeline → output.pdf
|
|
9
|
+
# --out FILE Output path (default: output.pdf)
|
|
10
|
+
# --author A --date D
|
|
11
|
+
# --subtitle S
|
|
12
|
+
# --abstract A Optional abstract text for cover
|
|
13
|
+
# --cover-image URL Optional cover image URL/path
|
|
14
|
+
# --content FILE Path to content.json (optional)
|
|
15
|
+
# demo Build a full-featured demo to demo.pdf
|
|
16
|
+
#
|
|
17
|
+
# Document types:
|
|
18
|
+
# report proposal resume portfolio academic general
|
|
19
|
+
# minimal stripe diagonal frame editorial
|
|
20
|
+
# magazine darkroom terminal poster
|
|
21
|
+
#
|
|
22
|
+
# Content block types:
|
|
23
|
+
# h1 h2 h3 body bullet numbered callout table
|
|
24
|
+
# image figure code math chart flowchart bibliography
|
|
25
|
+
# divider caption pagebreak spacer
|
|
26
|
+
#
|
|
27
|
+
# Exit codes: 0 success, 1 usage error, 2 dep missing, 3 runtime error
|
|
28
|
+
|
|
29
|
+
set -euo pipefail
|
|
30
|
+
SCRIPTS="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
31
|
+
PY="python3"
|
|
32
|
+
NODE="node"
|
|
33
|
+
|
|
34
|
+
# ── Colour helpers ─────────────────────────────────────────────────────────────
|
|
35
|
+
red() { printf '\033[0;31m%s\033[0m\n' "$*"; }
|
|
36
|
+
green() { printf '\033[0;32m%s\033[0m\n' "$*"; }
|
|
37
|
+
yellow() { printf '\033[0;33m%s\033[0m\n' "$*"; }
|
|
38
|
+
bold() { printf '\033[1m%s\033[0m\n' "$*"; }
|
|
39
|
+
|
|
40
|
+
# ── check ──────────────────────────────────────────────────────────────────────
|
|
41
|
+
cmd_check() {
|
|
42
|
+
local ok=true
|
|
43
|
+
bold "Checking dependencies..."
|
|
44
|
+
|
|
45
|
+
# Python
|
|
46
|
+
if command -v python3 &>/dev/null; then
|
|
47
|
+
green " ✓ python3 $(python3 --version 2>&1 | awk '{print $2}')"
|
|
48
|
+
else
|
|
49
|
+
red " ✗ python3 not found"
|
|
50
|
+
ok=false
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# reportlab
|
|
54
|
+
if python3 -c "import reportlab" 2>/dev/null; then
|
|
55
|
+
green " ✓ reportlab"
|
|
56
|
+
else
|
|
57
|
+
yellow " ⚠ reportlab not installed (run: make.sh fix)"
|
|
58
|
+
ok=false
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# pypdf
|
|
62
|
+
if python3 -c "import pypdf" 2>/dev/null; then
|
|
63
|
+
green " ✓ pypdf"
|
|
64
|
+
else
|
|
65
|
+
yellow " ⚠ pypdf not installed (run: make.sh fix)"
|
|
66
|
+
ok=false
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# Node.js
|
|
70
|
+
if command -v node &>/dev/null; then
|
|
71
|
+
green " ✓ node $(node --version)"
|
|
72
|
+
else
|
|
73
|
+
red " ✗ node not found — cover rendering unavailable"
|
|
74
|
+
ok=false
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Playwright
|
|
78
|
+
if node -e "require('playwright')" 2>/dev/null || \
|
|
79
|
+
node -e "require(require('child_process').execSync('npm root -g').toString().trim()+'/playwright')" 2>/dev/null; then
|
|
80
|
+
green " ✓ playwright"
|
|
81
|
+
else
|
|
82
|
+
yellow " ⚠ playwright not found (run: make.sh fix)"
|
|
83
|
+
ok=false
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# matplotlib (optional — required for math/chart/flowchart; degrades gracefully)
|
|
87
|
+
if python3 -c "import matplotlib" 2>/dev/null; then
|
|
88
|
+
green " ✓ matplotlib (math, chart, flowchart blocks enabled)"
|
|
89
|
+
else
|
|
90
|
+
yellow " ⚠ matplotlib not installed — math/chart/flowchart blocks degrade to text (run: make.sh fix)"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
if $ok; then
|
|
94
|
+
green "\nAll dependencies satisfied."
|
|
95
|
+
exit 0
|
|
96
|
+
else
|
|
97
|
+
yellow "\nSome dependencies missing. Run: bash make.sh fix"
|
|
98
|
+
exit 2
|
|
99
|
+
fi
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# ── fix ────────────────────────────────────────────────────────────────────────
|
|
103
|
+
cmd_fix() {
|
|
104
|
+
bold "Installing missing dependencies..."
|
|
105
|
+
local rc=0
|
|
106
|
+
|
|
107
|
+
# Python packages
|
|
108
|
+
if command -v python3 &>/dev/null; then
|
|
109
|
+
python3 -m pip install --break-system-packages -q reportlab pypdf matplotlib 2>/dev/null \
|
|
110
|
+
|| python3 -m pip install -q reportlab pypdf matplotlib 2>/dev/null \
|
|
111
|
+
|| { yellow " pip install failed — try: pip install reportlab pypdf matplotlib"; rc=3; }
|
|
112
|
+
green " ✓ Python packages installed (reportlab, pypdf, matplotlib)"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Playwright
|
|
116
|
+
if command -v npm &>/dev/null; then
|
|
117
|
+
npm install -g playwright --silent 2>/dev/null && \
|
|
118
|
+
npx playwright install chromium --silent 2>/dev/null && \
|
|
119
|
+
green " ✓ Playwright + Chromium installed" || \
|
|
120
|
+
{ yellow " playwright install failed — try manually"; rc=3; }
|
|
121
|
+
else
|
|
122
|
+
yellow " npm not found — cannot install Playwright automatically"
|
|
123
|
+
rc=2
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
if [[ $rc -eq 0 ]]; then
|
|
127
|
+
green "\nAll dependencies installed. Run: bash make.sh check"
|
|
128
|
+
fi
|
|
129
|
+
exit $rc
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# ── run ────────────────────────────────────────────────────────────────────────
|
|
133
|
+
cmd_run() {
|
|
134
|
+
local title="Untitled Document"
|
|
135
|
+
local type="general"
|
|
136
|
+
local author=""
|
|
137
|
+
local date=""
|
|
138
|
+
local subtitle=""
|
|
139
|
+
local abstract=""
|
|
140
|
+
local cover_image=""
|
|
141
|
+
local accent=""
|
|
142
|
+
local cover_bg=""
|
|
143
|
+
local content_file=""
|
|
144
|
+
local out="output.pdf"
|
|
145
|
+
local workdir
|
|
146
|
+
workdir="$(mktemp -d)"
|
|
147
|
+
|
|
148
|
+
# Parse options
|
|
149
|
+
while [[ $# -gt 0 ]]; do
|
|
150
|
+
case "$1" in
|
|
151
|
+
--title) title="$2"; shift 2 ;;
|
|
152
|
+
--type) type="$2"; shift 2 ;;
|
|
153
|
+
--author) author="$2"; shift 2 ;;
|
|
154
|
+
--date) date="$2"; shift 2 ;;
|
|
155
|
+
--subtitle) subtitle="$2"; shift 2 ;;
|
|
156
|
+
--abstract) abstract="$2"; shift 2 ;;
|
|
157
|
+
--cover-image) cover_image="$2"; shift 2 ;;
|
|
158
|
+
--accent) accent="$2"; shift 2 ;;
|
|
159
|
+
--cover-bg) cover_bg="$2"; shift 2 ;;
|
|
160
|
+
--content) content_file="$2"; shift 2 ;;
|
|
161
|
+
--out) out="$2"; shift 2 ;;
|
|
162
|
+
*) echo "Unknown option: $1"; exit 1 ;;
|
|
163
|
+
esac
|
|
164
|
+
done
|
|
165
|
+
|
|
166
|
+
bold "Building: $title"
|
|
167
|
+
echo " Type : $type"
|
|
168
|
+
echo " Output : $out"
|
|
169
|
+
|
|
170
|
+
# Step 1: tokens
|
|
171
|
+
echo ""
|
|
172
|
+
bold "Step 1/4 Generating design tokens..."
|
|
173
|
+
local accent_args=()
|
|
174
|
+
[[ -n "$accent" ]] && accent_args+=(--accent "$accent")
|
|
175
|
+
[[ -n "$cover_bg" ]] && accent_args+=(--cover-bg "$cover_bg")
|
|
176
|
+
$PY "$SCRIPTS/palette.py" \
|
|
177
|
+
--title "$title" --type "$type" \
|
|
178
|
+
--author "$author" --date "$date" \
|
|
179
|
+
--out "$workdir/tokens.json" \
|
|
180
|
+
"${accent_args[@]+"${accent_args[@]}"}"
|
|
181
|
+
|
|
182
|
+
# Inject optional cover fields into tokens.json
|
|
183
|
+
if [[ -n "$abstract" || -n "$cover_image" ]]; then
|
|
184
|
+
PDF_ABSTRACT="$abstract" PDF_COVER_IMAGE="$cover_image" PDF_TOKENS="$workdir/tokens.json" \
|
|
185
|
+
$PY - <<'PYEOF'
|
|
186
|
+
import json, os
|
|
187
|
+
with open(os.environ["PDF_TOKENS"]) as f:
|
|
188
|
+
t = json.load(f)
|
|
189
|
+
abstract = os.environ.get("PDF_ABSTRACT", "")
|
|
190
|
+
cover_image = os.environ.get("PDF_COVER_IMAGE", "")
|
|
191
|
+
if abstract:
|
|
192
|
+
t["abstract"] = abstract
|
|
193
|
+
if cover_image:
|
|
194
|
+
t["cover_image"] = cover_image
|
|
195
|
+
with open(os.environ["PDF_TOKENS"], "w") as f:
|
|
196
|
+
json.dump(t, f, indent=2)
|
|
197
|
+
PYEOF
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
cat "$workdir/tokens.json" | $PY -c "
|
|
201
|
+
import json,sys
|
|
202
|
+
t=json.load(sys.stdin)
|
|
203
|
+
print(f' Mood : {t[\"mood\"]}')
|
|
204
|
+
print(f' Pattern : {t[\"cover_pattern\"]}')
|
|
205
|
+
print(f' Fonts : {t[\"font_display\"]} / {t[\"font_body\"]}')"
|
|
206
|
+
|
|
207
|
+
# Step 2: cover HTML + render
|
|
208
|
+
echo ""
|
|
209
|
+
bold "Step 2/4 Rendering cover..."
|
|
210
|
+
local subtitle_args=()
|
|
211
|
+
[[ -n "$subtitle" ]] && subtitle_args=(--subtitle "$subtitle")
|
|
212
|
+
$PY "$SCRIPTS/cover.py" \
|
|
213
|
+
--tokens "$workdir/tokens.json" \
|
|
214
|
+
--out "$workdir/cover.html" \
|
|
215
|
+
"${subtitle_args[@]+"${subtitle_args[@]}"}"
|
|
216
|
+
|
|
217
|
+
$NODE "$SCRIPTS/render_cover.cjs" \
|
|
218
|
+
--input "$workdir/cover.html" \
|
|
219
|
+
--out "$workdir/cover.pdf"
|
|
220
|
+
green " ✓ Cover rendered"
|
|
221
|
+
|
|
222
|
+
# Step 3: body
|
|
223
|
+
echo ""
|
|
224
|
+
bold "Step 3/4 Rendering body pages..."
|
|
225
|
+
if [[ -z "$content_file" ]]; then
|
|
226
|
+
# Generate a minimal placeholder body
|
|
227
|
+
cat > "$workdir/content.json" <<'JSON'
|
|
228
|
+
[
|
|
229
|
+
{"type":"h1", "text":"Document Body"},
|
|
230
|
+
{"type":"body", "text":"Replace this with your content.json file using --content path/to/content.json"},
|
|
231
|
+
{"type":"body", "text":"See the content.json schema in the skill README for the full list of supported block types: h1, h2, h3, body, bullet, callout, table, pagebreak, spacer."}
|
|
232
|
+
]
|
|
233
|
+
JSON
|
|
234
|
+
content_file="$workdir/content.json"
|
|
235
|
+
yellow " No content file provided — using placeholder body."
|
|
236
|
+
fi
|
|
237
|
+
|
|
238
|
+
$PY "$SCRIPTS/render_body.py" \
|
|
239
|
+
--tokens "$workdir/tokens.json" \
|
|
240
|
+
--content "$content_file" \
|
|
241
|
+
--out "$workdir/body.pdf"
|
|
242
|
+
green " ✓ Body rendered"
|
|
243
|
+
|
|
244
|
+
# Step 4: merge
|
|
245
|
+
echo ""
|
|
246
|
+
bold "Step 4/4 Merging and QA..."
|
|
247
|
+
$PY "$SCRIPTS/merge.py" \
|
|
248
|
+
--cover "$workdir/cover.pdf" \
|
|
249
|
+
--body "$workdir/body.pdf" \
|
|
250
|
+
--out "$out" \
|
|
251
|
+
--title "$title"
|
|
252
|
+
|
|
253
|
+
# Cleanup
|
|
254
|
+
rm -rf "$workdir"
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
# ── fill ──────────────────────────────────────────────────────────────────────
|
|
258
|
+
cmd_fill() {
|
|
259
|
+
local input="" out="" values="" data_file="" inspect_only=false
|
|
260
|
+
|
|
261
|
+
while [[ $# -gt 0 ]]; do
|
|
262
|
+
case "$1" in
|
|
263
|
+
--input) input="$2"; shift 2 ;;
|
|
264
|
+
--out) out="$2"; shift 2 ;;
|
|
265
|
+
--values) values="$2"; shift 2 ;;
|
|
266
|
+
--data) data_file="$2"; shift 2 ;;
|
|
267
|
+
--inspect) inspect_only=true; shift ;;
|
|
268
|
+
*) echo "Unknown option: $1"; exit 1 ;;
|
|
269
|
+
esac
|
|
270
|
+
done
|
|
271
|
+
|
|
272
|
+
if [[ -z "$input" ]]; then
|
|
273
|
+
echo "Usage: make.sh fill --input form.pdf [--out filled.pdf] [--values '{...}'] [--data values.json] [--inspect]"
|
|
274
|
+
exit 1
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
if $inspect_only || [[ -z "$out" && -z "$values" && -z "$data_file" ]]; then
|
|
278
|
+
bold "Inspecting form fields in: $input"
|
|
279
|
+
$PY "$SCRIPTS/fill_inspect.py" --input "$input"
|
|
280
|
+
return
|
|
281
|
+
fi
|
|
282
|
+
|
|
283
|
+
bold "Filling form: $input → $out"
|
|
284
|
+
|
|
285
|
+
local val_args=""
|
|
286
|
+
if [[ -n "$values" ]]; then val_args="--values $values"; fi
|
|
287
|
+
if [[ -n "$data_file" ]]; then val_args="--data $data_file"; fi
|
|
288
|
+
|
|
289
|
+
$PY "$SCRIPTS/fill_write.py" --input "$input" --out "$out" $val_args
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
# ── reformat ───────────────────────────────────────────────────────────────────
|
|
293
|
+
cmd_reformat() {
|
|
294
|
+
local input="" title="Reformatted Document" type="general"
|
|
295
|
+
local author="" date="" out="output.pdf" subtitle=""
|
|
296
|
+
local tmpdir
|
|
297
|
+
tmpdir="$(mktemp -d)"
|
|
298
|
+
|
|
299
|
+
while [[ $# -gt 0 ]]; do
|
|
300
|
+
case "$1" in
|
|
301
|
+
--input) input="$2"; shift 2 ;;
|
|
302
|
+
--title) title="$2"; shift 2 ;;
|
|
303
|
+
--type) type="$2"; shift 2 ;;
|
|
304
|
+
--author) author="$2"; shift 2 ;;
|
|
305
|
+
--date) date="$2"; shift 2 ;;
|
|
306
|
+
--subtitle) subtitle="$2"; shift 2 ;;
|
|
307
|
+
--out) out="$2"; shift 2 ;;
|
|
308
|
+
*) echo "Unknown option: $1"; exit 1 ;;
|
|
309
|
+
esac
|
|
310
|
+
done
|
|
311
|
+
|
|
312
|
+
if [[ -z "$input" ]]; then
|
|
313
|
+
echo "Usage: make.sh reformat --input source.md --title T --type TYPE --out output.pdf"
|
|
314
|
+
exit 1
|
|
315
|
+
fi
|
|
316
|
+
|
|
317
|
+
bold "Parsing: $input"
|
|
318
|
+
$PY "$SCRIPTS/reformat_parse.py" --input "$input" --out "$tmpdir/content.json"
|
|
319
|
+
green " ✓ Parsed to content.json"
|
|
320
|
+
|
|
321
|
+
bold "Applying design and building PDF..."
|
|
322
|
+
local sub_args=()
|
|
323
|
+
[[ -n "$subtitle" ]] && sub_args=(--subtitle "$subtitle")
|
|
324
|
+
|
|
325
|
+
cmd_run \
|
|
326
|
+
--title "$title" --type "$type" \
|
|
327
|
+
--author "$author" --date "$date" \
|
|
328
|
+
--content "$tmpdir/content.json" \
|
|
329
|
+
--out "$out" \
|
|
330
|
+
"${sub_args[@]+"${sub_args[@]}"}"
|
|
331
|
+
|
|
332
|
+
rm -rf "$tmpdir"
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
# ── demo ──────────────────────────────────────────────────────────────────────
|
|
336
|
+
cmd_demo() {
|
|
337
|
+
local tmpdir
|
|
338
|
+
tmpdir="$(mktemp -d)"
|
|
339
|
+
|
|
340
|
+
cat > "$tmpdir/content.json" <<'JSON'
|
|
341
|
+
[
|
|
342
|
+
{"type":"h1", "text":"Executive Summary"},
|
|
343
|
+
{"type":"body", "text":"This document was generated by minimax-pdf — a skill for creating visually polished PDFs. Every design decision is rooted in the document type and content, not a generic template."},
|
|
344
|
+
{"type":"callout", "text":"Key insight: design tokens flow from palette.py through every renderer, keeping cover and body visually consistent."},
|
|
345
|
+
|
|
346
|
+
{"type":"h1", "text":"How It Works"},
|
|
347
|
+
{"type":"h2", "text":"The Token Pipeline"},
|
|
348
|
+
{"type":"body", "text":"The palette.py script infers a color palette and typography pair from the document type. These tokens are written to tokens.json and consumed by every downstream script."},
|
|
349
|
+
{"type":"numbered","text":"palette.py generates color tokens, font selection, and the cover pattern"},
|
|
350
|
+
{"type":"numbered","text":"cover.py renders the cover HTML using the selected pattern"},
|
|
351
|
+
{"type":"numbered","text":"render_cover.js uses Playwright to convert the HTML cover to PDF"},
|
|
352
|
+
{"type":"numbered","text":"render_body.py builds inner pages from content.json using ReportLab"},
|
|
353
|
+
{"type":"numbered","text":"merge.py combines cover + body and runs final QA checks"},
|
|
354
|
+
|
|
355
|
+
{"type":"h2", "text":"Cover Patterns"},
|
|
356
|
+
{"type":"table",
|
|
357
|
+
"headers": ["Pattern", "Document type", "Visual character"],
|
|
358
|
+
"rows": [
|
|
359
|
+
["fullbleed", "report, general", "Deep background · dot-grid texture"],
|
|
360
|
+
["split", "proposal", "Left dark panel · right dot-grid"],
|
|
361
|
+
["typographic", "resume, academic", "Oversized display type · first-word accent"],
|
|
362
|
+
["atmospheric", "portfolio", "Dark bg · radial glow · dot-grid"],
|
|
363
|
+
["magazine", "magazine", "Cream bg · centered · hero image"],
|
|
364
|
+
["darkroom", "darkroom", "Navy bg · centered · grayscale image"],
|
|
365
|
+
["terminal", "terminal", "Near-black · grid lines · monospace"],
|
|
366
|
+
["poster", "poster", "White · thick sidebar · oversized title"]
|
|
367
|
+
]
|
|
368
|
+
},
|
|
369
|
+
|
|
370
|
+
{"type":"h1", "text":"Data Visualisation"},
|
|
371
|
+
{"type":"h2", "text":"Performance Metrics (Chart)"},
|
|
372
|
+
{"type":"body", "text":"Charts are rendered natively using matplotlib with a color palette derived from the document accent. No external chart services or image files required."},
|
|
373
|
+
{"type":"chart",
|
|
374
|
+
"chart_type": "bar",
|
|
375
|
+
"title": "Quarterly Performance",
|
|
376
|
+
"labels": ["Q1", "Q2", "Q3", "Q4"],
|
|
377
|
+
"datasets": [
|
|
378
|
+
{"label": "Revenue", "values": [120, 145, 132, 178]},
|
|
379
|
+
{"label": "Expenses", "values": [95, 108, 99, 122]}
|
|
380
|
+
],
|
|
381
|
+
"y_label": "USD (thousands)",
|
|
382
|
+
"caption": "Quarterly revenue vs. expenses"
|
|
383
|
+
},
|
|
384
|
+
|
|
385
|
+
{"type":"h2", "text":"Market Share (Pie Chart)"},
|
|
386
|
+
{"type":"chart",
|
|
387
|
+
"chart_type": "pie",
|
|
388
|
+
"labels": ["Product A", "Product B", "Product C", "Other"],
|
|
389
|
+
"datasets": [{"values": [42, 28, 18, 12]}],
|
|
390
|
+
"caption": "Annual market share by product line"
|
|
391
|
+
},
|
|
392
|
+
|
|
393
|
+
{"type":"pagebreak"},
|
|
394
|
+
|
|
395
|
+
{"type":"h1", "text":"Mathematics"},
|
|
396
|
+
{"type":"body", "text":"Display math is rendered via matplotlib mathtext — no LaTeX binary installation required. Inline references use standard [N] notation in body text."},
|
|
397
|
+
{"type":"math", "text":"E = mc^2", "label":"(1)"},
|
|
398
|
+
{"type":"math", "text":"\\int_0^\\infty e^{-x^2}\\,dx = \\frac{\\sqrt{\\pi}}{2}", "label":"(2)"},
|
|
399
|
+
{"type":"math", "text":"\\sum_{n=1}^{\\infty} \\frac{1}{n^2} = \\frac{\\pi^2}{6}", "caption":"Basel problem (Euler, 1734)"},
|
|
400
|
+
|
|
401
|
+
{"type":"h1", "text":"Process Flow"},
|
|
402
|
+
{"type":"body", "text":"Flowcharts are drawn directly using matplotlib patches — no Graphviz or external tools needed. Supported node shapes: rect, diamond, oval, parallelogram."},
|
|
403
|
+
{"type":"flowchart",
|
|
404
|
+
"nodes": [
|
|
405
|
+
{"id":"start", "label":"Start", "shape":"oval"},
|
|
406
|
+
{"id":"input", "label":"Receive Input", "shape":"parallelogram"},
|
|
407
|
+
{"id":"valid", "label":"Valid?", "shape":"diamond"},
|
|
408
|
+
{"id":"proc", "label":"Process Data", "shape":"rect"},
|
|
409
|
+
{"id":"err", "label":"Return Error", "shape":"rect"},
|
|
410
|
+
{"id":"out", "label":"Return Result", "shape":"parallelogram"},
|
|
411
|
+
{"id":"end", "label":"End", "shape":"oval"}
|
|
412
|
+
],
|
|
413
|
+
"edges": [
|
|
414
|
+
{"from":"start", "to":"input"},
|
|
415
|
+
{"from":"input", "to":"valid"},
|
|
416
|
+
{"from":"valid", "to":"proc", "label":"Yes"},
|
|
417
|
+
{"from":"valid", "to":"err", "label":"No"},
|
|
418
|
+
{"from":"proc", "to":"out"},
|
|
419
|
+
{"from":"err", "to":"end"},
|
|
420
|
+
{"from":"out", "to":"end"}
|
|
421
|
+
],
|
|
422
|
+
"caption": "Data validation and processing flow"
|
|
423
|
+
},
|
|
424
|
+
|
|
425
|
+
{"type":"h1", "text":"Code Example"},
|
|
426
|
+
{"type":"code", "language":"python",
|
|
427
|
+
"text":"# Design token pipeline\ntokens = palette.build_tokens(\n title=\"Annual Report\",\n doc_type=\"report\",\n author=\"J. Smith\",\n date=\"March 2026\",\n)\nhtml = cover.render(tokens)\npdf = render_cover(html)"},
|
|
428
|
+
|
|
429
|
+
{"type":"h1", "text":"Design Principles"},
|
|
430
|
+
{"type":"body", "text":"The aesthetic system is documented in design/design.md. The core rule: every design decision must be rooted in the document content and purpose. A color chosen because it fits the content will always outperform a color chosen because it seems safe."},
|
|
431
|
+
{"type":"h2", "text":"Restraint over decoration"},
|
|
432
|
+
{"type":"body", "text":"The page is done when there is nothing left to remove. Accent color appears on section rules only — not on headings, not on bullets. No card components, no drop shadows."},
|
|
433
|
+
{"type":"callout", "text":"A PDF passes the quality bar when a designer would not be embarrassed to hand it to a client."},
|
|
434
|
+
|
|
435
|
+
{"type":"pagebreak"},
|
|
436
|
+
{"type":"bibliography",
|
|
437
|
+
"title": "References",
|
|
438
|
+
"items": [
|
|
439
|
+
{"id":"1","text":"Bringhurst, R. (2004). The Elements of Typographic Style (3rd ed.). Hartley & Marks."},
|
|
440
|
+
{"id":"2","text":"Cairo, A. (2016). The Truthful Art: Data, Charts, and Maps for Communication. New Riders."},
|
|
441
|
+
{"id":"3","text":"Hochuli, J. & Kinross, R. (1996). Designing Books: Practice and Theory. Hyphen Press."}
|
|
442
|
+
]
|
|
443
|
+
}
|
|
444
|
+
]
|
|
445
|
+
JSON
|
|
446
|
+
|
|
447
|
+
cmd_run \
|
|
448
|
+
--title "minimax-pdf demo" \
|
|
449
|
+
--type "report" \
|
|
450
|
+
--author "minimax-pdf skill" \
|
|
451
|
+
--date "$(date '+%B %Y')" \
|
|
452
|
+
--subtitle "A demonstration of the token-based design pipeline" \
|
|
453
|
+
--content "$tmpdir/content.json" \
|
|
454
|
+
--out "demo.pdf"
|
|
455
|
+
|
|
456
|
+
rm -rf "$tmpdir"
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
# ── dispatch ───────────────────────────────────────────────────────────────────
|
|
460
|
+
main() {
|
|
461
|
+
if [[ $# -lt 1 ]]; then
|
|
462
|
+
bold "minimax-pdf — make.sh"
|
|
463
|
+
echo ""
|
|
464
|
+
echo "Usage: bash make.sh <command> [options]"
|
|
465
|
+
echo ""
|
|
466
|
+
echo "Commands:"
|
|
467
|
+
echo " check Verify all dependencies"
|
|
468
|
+
echo " fix Auto-install missing deps"
|
|
469
|
+
echo " run --title T --type TYPE CREATE: full pipeline → PDF"
|
|
470
|
+
echo " [--author A] [--date D] [--subtitle S]"
|
|
471
|
+
echo " [--abstract A] [--cover-image URL]"
|
|
472
|
+
echo " [--accent #HEX] [--cover-bg #HEX]"
|
|
473
|
+
echo " [--content content.json] [--out output.pdf]"
|
|
474
|
+
echo " fill --input f.pdf FILL: inspect or fill form fields"
|
|
475
|
+
echo " reformat --input doc.md REFORMAT: parse doc → apply design → PDF"
|
|
476
|
+
echo " demo Build a full-featured demo PDF"
|
|
477
|
+
exit 0
|
|
478
|
+
fi
|
|
479
|
+
|
|
480
|
+
case "$1" in
|
|
481
|
+
check) cmd_check ;;
|
|
482
|
+
fix) cmd_fix ;;
|
|
483
|
+
run) shift; cmd_run "$@" ;;
|
|
484
|
+
fill) shift; cmd_fill "$@" ;;
|
|
485
|
+
reformat) shift; cmd_reformat "$@" ;;
|
|
486
|
+
demo) cmd_demo ;;
|
|
487
|
+
*) echo "Unknown command: $1"; exit 1 ;;
|
|
488
|
+
esac
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
main "$@"
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
merge.py — Merge cover.pdf + body.pdf → final.pdf and print a QA report.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python3 merge.py --cover cover.pdf --body body.pdf --out final.pdf
|
|
7
|
+
python3 merge.py --cover cover.pdf --body body.pdf --out final.pdf --title "My Report"
|
|
8
|
+
|
|
9
|
+
Exit codes: 0 success, 1 bad args/missing file, 2 missing dep, 3 merge error
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import argparse
|
|
13
|
+
import importlib.util
|
|
14
|
+
import json
|
|
15
|
+
import os
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
def ensure_deps():
|
|
19
|
+
if importlib.util.find_spec("pypdf") is None:
|
|
20
|
+
import subprocess
|
|
21
|
+
subprocess.check_call(
|
|
22
|
+
[sys.executable, "-m", "pip", "install", "--break-system-packages", "-q", "pypdf"]
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
ensure_deps()
|
|
27
|
+
|
|
28
|
+
from pypdf import PdfWriter, PdfReader
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def merge(cover_path: str, body_path: str, out_path: str, title: str = "") -> dict:
|
|
32
|
+
writer = PdfWriter()
|
|
33
|
+
|
|
34
|
+
for fpath, label in [(cover_path, "cover"), (body_path, "body")]:
|
|
35
|
+
if not os.path.exists(fpath):
|
|
36
|
+
return {"status": "error", "error": f"{label} file not found: {fpath}"}
|
|
37
|
+
reader = PdfReader(fpath)
|
|
38
|
+
for page in reader.pages:
|
|
39
|
+
writer.add_page(page)
|
|
40
|
+
|
|
41
|
+
# Set PDF metadata
|
|
42
|
+
if title:
|
|
43
|
+
writer.add_metadata({"/Title": title})
|
|
44
|
+
|
|
45
|
+
os.makedirs(os.path.dirname(os.path.abspath(out_path)), exist_ok=True)
|
|
46
|
+
with open(out_path, "wb") as f:
|
|
47
|
+
writer.write(f)
|
|
48
|
+
|
|
49
|
+
size_kb = os.path.getsize(out_path) // 1024
|
|
50
|
+
total_pages = len(writer.pages)
|
|
51
|
+
|
|
52
|
+
# ── QA checks ─────────────────────────────────────────────────────────────
|
|
53
|
+
warnings = []
|
|
54
|
+
|
|
55
|
+
# Page count sanity
|
|
56
|
+
cover_pages = len(PdfReader(cover_path).pages)
|
|
57
|
+
body_pages = len(PdfReader(body_path).pages)
|
|
58
|
+
if cover_pages != 1:
|
|
59
|
+
warnings.append(f"Cover PDF has {cover_pages} pages (expected 1)")
|
|
60
|
+
|
|
61
|
+
# File size sanity
|
|
62
|
+
if size_kb < 20:
|
|
63
|
+
warnings.append(f"Output is very small ({size_kb} KB) — may have blank pages")
|
|
64
|
+
if size_kb > 50_000:
|
|
65
|
+
warnings.append(f"Output is very large ({size_kb} KB) — consider compressing images")
|
|
66
|
+
|
|
67
|
+
report = {
|
|
68
|
+
"status": "ok",
|
|
69
|
+
"out": out_path,
|
|
70
|
+
"total_pages": total_pages,
|
|
71
|
+
"cover_pages": cover_pages,
|
|
72
|
+
"body_pages": body_pages,
|
|
73
|
+
"size_kb": size_kb,
|
|
74
|
+
}
|
|
75
|
+
if warnings:
|
|
76
|
+
report["warnings"] = warnings
|
|
77
|
+
|
|
78
|
+
return report
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def main():
|
|
82
|
+
parser = argparse.ArgumentParser(description="Merge cover + body PDFs")
|
|
83
|
+
parser.add_argument("--cover", required=True)
|
|
84
|
+
parser.add_argument("--body", required=True)
|
|
85
|
+
parser.add_argument("--out", required=True)
|
|
86
|
+
parser.add_argument("--title", default="")
|
|
87
|
+
args = parser.parse_args()
|
|
88
|
+
|
|
89
|
+
result = merge(args.cover, args.body, args.out, args.title)
|
|
90
|
+
|
|
91
|
+
if result["status"] == "error":
|
|
92
|
+
print(json.dumps(result), file=sys.stderr)
|
|
93
|
+
sys.exit(3)
|
|
94
|
+
|
|
95
|
+
print(json.dumps(result))
|
|
96
|
+
|
|
97
|
+
# Human-readable QA summary
|
|
98
|
+
print(f"\n── Build complete ──────────────────────────────────────")
|
|
99
|
+
print(f" Output : {result['out']}")
|
|
100
|
+
print(f" Pages : {result['total_pages']} total (1 cover + {result['body_pages']} body)")
|
|
101
|
+
print(f" Size : {result['size_kb']} KB")
|
|
102
|
+
if result.get("warnings"):
|
|
103
|
+
print(f" ⚠ Warnings:")
|
|
104
|
+
for w in result["warnings"]:
|
|
105
|
+
print(f" • {w}")
|
|
106
|
+
else:
|
|
107
|
+
print(f" ✓ No issues detected")
|
|
108
|
+
print(f"────────────────────────────────────────────────────────\n")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
if __name__ == "__main__":
|
|
112
|
+
main()
|