@panda-agent/panda-cli 0.1.28 → 0.1.30
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/dist/panda-cli-ink.bundle.mjs +267 -258
- package/package.json +6 -4
- package/skills/.gitkeep +0 -0
- package/skills/README.md +13 -0
- package/skills/docx/.skill-metadata.yaml +173 -0
- package/skills/docx/LICENSE.txt +30 -0
- package/skills/docx/SKILL.md +589 -0
- package/skills/docx/scripts/__init__.py +1 -0
- package/skills/docx/scripts/accept_changes.py +206 -0
- package/skills/docx/scripts/comment.py +442 -0
- package/skills/docx/scripts/office/helpers/__init__.py +1 -0
- package/skills/docx/scripts/office/helpers/merge_runs.py +190 -0
- package/skills/docx/scripts/office/helpers/simplify_redlines.py +185 -0
- package/skills/docx/scripts/office/pack.py +167 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/docx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/docx/scripts/office/soffice.py +194 -0
- package/skills/docx/scripts/office/unpack.py +145 -0
- package/skills/docx/scripts/office/validate.py +114 -0
- package/skills/docx/scripts/office/validators/__init__.py +16 -0
- package/skills/docx/scripts/office/validators/base.py +733 -0
- package/skills/docx/scripts/office/validators/docx.py +354 -0
- package/skills/docx/scripts/office/validators/pptx.py +230 -0
- package/skills/docx/scripts/office/validators/redlining.py +212 -0
- package/skills/docx/scripts/templates/comments.xml +3 -0
- package/skills/docx/scripts/templates/commentsExtended.xml +3 -0
- package/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/skills/docx/scripts/templates/commentsIds.xml +3 -0
- package/skills/docx/scripts/templates/people.xml +3 -0
- package/skills/frontend-design/LICENSE.txt +177 -0
- package/skills/frontend-design/SKILL.md +42 -0
- package/skills/pdf/.skill-metadata.yaml +273 -0
- package/skills/pdf/LICENSE.txt +30 -0
- package/skills/pdf/SKILL.md +324 -0
- package/skills/pdf/advanced-reference.md +609 -0
- package/skills/pdf/form-filling-guide.md +318 -0
- package/skills/pdf/forms.md +294 -0
- package/skills/pdf/reference.md +612 -0
- package/skills/pdf/scripts/check_bounding_boxes.py +198 -0
- package/skills/pdf/scripts/check_fillable_fields.py +64 -0
- package/skills/pdf/scripts/convert_pdf_to_images.py +102 -0
- package/skills/pdf/scripts/create_validation_image.py +125 -0
- package/skills/pdf/scripts/extract_form_field_info.py +220 -0
- package/skills/pdf/scripts/extract_form_structure.py +202 -0
- package/skills/pdf/scripts/fill_fillable_fields.py +205 -0
- package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +193 -0
- package/skills/pptx-generator/SKILL.md +204 -0
- package/skills/pptx-generator/assets/styles/business.json +8 -0
- package/skills/pptx-generator/assets/styles/minimal.json +8 -0
- package/skills/pptx-generator/assets/styles/modern.json +8 -0
- package/skills/pptx-generator/assets/templates/ppt_data_template.json +40 -0
- package/skills/pptx-generator/references/collaboration_guide.md +381 -0
- package/skills/pptx-generator/references/json_format_spec.md +215 -0
- package/skills/pptx-generator/references/layout_guide.md +290 -0
- package/skills/pptx-generator/scripts/json_validator.py +194 -0
- package/skills/pptx-generator/scripts/pptx_builder.py +340 -0
- package/skills/pptx-generator/scripts/pptx_validator.py +162 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/SKILL.md +479 -0
- package/skills/skill-creator/agents/analyzer.md +274 -0
- package/skills/skill-creator/agents/comparator.md +202 -0
- package/skills/skill-creator/agents/grader.md +223 -0
- package/skills/skill-creator/assets/eval_review.html +146 -0
- package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/skill-creator/references/schemas.md +430 -0
- package/skills/skill-creator/scripts/__init__.py +0 -0
- package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/skill-creator/scripts/generate_report.py +326 -0
- package/skills/skill-creator/scripts/improve_description.py +248 -0
- package/skills/skill-creator/scripts/package_skill.py +136 -0
- package/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/skills/skill-creator/scripts/run_eval.py +310 -0
- package/skills/skill-creator/scripts/run_loop.py +332 -0
- package/skills/skill-creator/scripts/utils.py +47 -0
- package/skills/xlsx/.skill-metadata.yaml +185 -0
- package/skills/xlsx/LICENSE.txt +30 -0
- package/skills/xlsx/SKILL.md +233 -0
- package/skills/xlsx/scripts/office/helpers/__init__.py +1 -0
- package/skills/xlsx/scripts/office/helpers/merge_runs.py +226 -0
- package/skills/xlsx/scripts/office/helpers/simplify_redlines.py +198 -0
- package/skills/xlsx/scripts/office/pack.py +162 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/xlsx/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/xlsx/scripts/office/soffice.py +185 -0
- package/skills/xlsx/scripts/office/unpack.py +146 -0
- package/skills/xlsx/scripts/office/validate.py +108 -0
- package/skills/xlsx/scripts/office/validators/__init__.py +13 -0
- package/skills/xlsx/scripts/office/validators/base.py +800 -0
- package/skills/xlsx/scripts/office/validators/docx.py +383 -0
- package/skills/xlsx/scripts/office/validators/pptx.py +250 -0
- package/skills/xlsx/scripts/office/validators/redlining.py +229 -0
- package/skills/xlsx/scripts/recalc.py +296 -0
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docx
|
|
3
|
+
version: 1.0.1
|
|
4
|
+
description: "Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). Triggers include: any mention of 'Word doc', 'word document', '.docx', or requests to produce professional documents with formatting like tables of contents, headings, page numbers, or letterheads. Also use when extracting or reorganizing content from .docx files, inserting or replacing images in documents, performing find-and-replace in Word files, working with tracked changes or comments, or converting content into a polished Word document. If the user asks for a 'report', 'memo', 'letter', 'template', or similar deliverable as a Word or .docx file, use this skill. Do NOT use for PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document generation."
|
|
5
|
+
description_zh: "当用户需要创建、读取、编辑或操作 Word 文档(.docx 文件)时使用此技能。触发条件包括:任何提及 'Word 文档'、'.docx' 的情况,或要求生成带有目录、标题、页码或信头等格式的专业文档。也适用于:从 .docx 文件中提取或重组内容、在文档中插入或替换图片、在 Word 文件中执行查找替换、处理修订标记或批注,或将内容转换为精美的 Word 文档。当用户要求以 Word 或 .docx 文件形式交付'报告'、'备忘录'、'信函'、'模板'或类似文档时使用此技能。不适用于 PDF、电子表格、Google Docs 或与文档生成无关的编程任务。"
|
|
6
|
+
license: Proprietary. LICENSE.txt has complete terms
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Working with DOCX: Creation, Modification, and Inspection
|
|
10
|
+
|
|
11
|
+
A `.docx` file is a ZIP container holding a tree of XML files conforming to the OOXML standard.
|
|
12
|
+
|
|
13
|
+
## Task Decision Matrix
|
|
14
|
+
|
|
15
|
+
| Goal | Approach |
|
|
16
|
+
|------|----------|
|
|
17
|
+
| Inspect / extract text | `pandoc` or unpack to browse raw XML |
|
|
18
|
+
| Build a new document | `docx-js` (see §Generating Documents) |
|
|
19
|
+
| Modify an existing file | Unpack → edit XML → repack (see §Patching Existing Documents) |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Common Operations
|
|
24
|
+
|
|
25
|
+
### Converting legacy .doc to .docx
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python scripts/office/soffice.py --headless --convert-to docx document.doc
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Extracting text
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Markdown output preserving tracked-change information
|
|
35
|
+
pandoc --track-changes=all document.docx -o output.md
|
|
36
|
+
|
|
37
|
+
# Direct XML access for fine-grained inspection
|
|
38
|
+
python scripts/office/unpack.py document.docx unpacked/
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Rendering pages as images
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python scripts/office/soffice.py --headless --convert-to pdf document.docx
|
|
45
|
+
pdftoppm -jpeg -r 150 document.pdf page
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Accepting all tracked changes
|
|
49
|
+
|
|
50
|
+
Produces a pristine copy with all revisions resolved (LibreOffice required):
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
python scripts/accept_changes.py input.docx output.docx
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Generating Documents from Scratch
|
|
59
|
+
|
|
60
|
+
Produce `.docx` files via JavaScript. Install: `npm install -g docx`
|
|
61
|
+
|
|
62
|
+
### Bootstrap
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun,
|
|
66
|
+
Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink,
|
|
67
|
+
InternalHyperlink, Bookmark, FootnoteReferenceRun, PositionalTab,
|
|
68
|
+
PositionalTabAlignment, PositionalTabRelativeTo, PositionalTabLeader,
|
|
69
|
+
TabStopType, TabStopPosition, Column, SectionType,
|
|
70
|
+
TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType,
|
|
71
|
+
VerticalAlign, PageNumber, PageBreak } = require('docx');
|
|
72
|
+
|
|
73
|
+
const doc = new Document({ sections: [{ children: [/* content */] }] });
|
|
74
|
+
Packer.toBuffer(doc).then(buf => fs.writeFileSync("doc.docx", buf));
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Validation
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
python scripts/office/validate.py doc.docx
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
If the validator reports issues, unpack, repair the XML, and repackage.
|
|
84
|
+
|
|
85
|
+
### Page Dimensions
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
// docx-js defaults to A4; US Letter must be set explicitly.
|
|
89
|
+
sections: [{
|
|
90
|
+
properties: {
|
|
91
|
+
page: {
|
|
92
|
+
size: { width: 12240, height: 15840 }, // 8.5 × 11 in (DXA)
|
|
93
|
+
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } // 1-inch
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
children: [/* body content */]
|
|
97
|
+
}]
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Paper sizes (DXA; 1440 DXA = 1 inch):**
|
|
101
|
+
|
|
102
|
+
| Format | Width | Height | Usable width (1 in margins) |
|
|
103
|
+
|--------|-------|--------|-----------------------------|
|
|
104
|
+
| US Letter | 12 240 | 15 840 | 9 360 |
|
|
105
|
+
| A4 (default) | 11 906 | 16 838 | 9 026 |
|
|
106
|
+
|
|
107
|
+
**Landscape:** Always supply portrait dimensions — docx-js internally transposes them:
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
size: {
|
|
111
|
+
width: 12240, // short edge
|
|
112
|
+
height: 15840, // long edge
|
|
113
|
+
orientation: PageOrientation.LANDSCAPE
|
|
114
|
+
},
|
|
115
|
+
// Effective content width = 15840 − left − right (long edge becomes horizontal)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Heading Styles
|
|
119
|
+
|
|
120
|
+
Default to Arial for broad compatibility. Keep heading text black.
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
const doc = new Document({
|
|
124
|
+
styles: {
|
|
125
|
+
default: { document: { run: { font: "Arial", size: 24 } } }, // 12 pt base
|
|
126
|
+
paragraphStyles: [
|
|
127
|
+
{ id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true,
|
|
128
|
+
run: { size: 32, bold: true, font: "Arial" },
|
|
129
|
+
paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } },
|
|
130
|
+
{ id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true,
|
|
131
|
+
run: { size: 28, bold: true, font: "Arial" },
|
|
132
|
+
paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } },
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
sections: [{
|
|
136
|
+
children: [
|
|
137
|
+
new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("Title")] }),
|
|
138
|
+
]
|
|
139
|
+
}]
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Lists (NEVER use Unicode bullet characters)
|
|
144
|
+
|
|
145
|
+
```javascript
|
|
146
|
+
// ❌ WRONG — literal bullet glyphs produce broken output
|
|
147
|
+
new Paragraph({ children: [new TextRun("• Item")] }) // BAD
|
|
148
|
+
new Paragraph({ children: [new TextRun("\u2022 Item")] }) // BAD
|
|
149
|
+
|
|
150
|
+
// ✅ CORRECT — use LevelFormat.BULLET via numbering configuration
|
|
151
|
+
const doc = new Document({
|
|
152
|
+
numbering: {
|
|
153
|
+
config: [
|
|
154
|
+
{ reference: "bullets",
|
|
155
|
+
levels: [{ level: 0, format: LevelFormat.BULLET, text: "•", alignment: AlignmentType.LEFT,
|
|
156
|
+
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
|
|
157
|
+
{ reference: "numbers",
|
|
158
|
+
levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT,
|
|
159
|
+
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
sections: [{
|
|
163
|
+
children: [
|
|
164
|
+
new Paragraph({ numbering: { reference: "bullets", level: 0 },
|
|
165
|
+
children: [new TextRun("Bullet item")] }),
|
|
166
|
+
new Paragraph({ numbering: { reference: "numbers", level: 0 },
|
|
167
|
+
children: [new TextRun("Numbered item")] }),
|
|
168
|
+
]
|
|
169
|
+
}]
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// ⚠️ Same reference → continuous (1,2,3…4,5,6); different references → restart (1,2,3…1,2,3)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Tables
|
|
176
|
+
|
|
177
|
+
**Both `columnWidths` on Table AND `width` on every TableCell are required.**
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
const borderDef = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" };
|
|
181
|
+
const allBorders = { top: borderDef, bottom: borderDef, left: borderDef, right: borderDef };
|
|
182
|
+
|
|
183
|
+
new Table({
|
|
184
|
+
width: { size: 9360, type: WidthType.DXA }, // always DXA, never PERCENTAGE
|
|
185
|
+
columnWidths: [4680, 4680], // must sum to table width
|
|
186
|
+
rows: [
|
|
187
|
+
new TableRow({
|
|
188
|
+
children: [
|
|
189
|
+
new TableCell({
|
|
190
|
+
borders: allBorders,
|
|
191
|
+
width: { size: 4680, type: WidthType.DXA }, // must match columnWidths entry
|
|
192
|
+
shading: { fill: "D5E8F0", type: ShadingType.CLEAR }, // CLEAR, never SOLID
|
|
193
|
+
margins: { top: 80, bottom: 80, left: 120, right: 120 },
|
|
194
|
+
children: [new Paragraph({ children: [new TextRun("Cell")] })]
|
|
195
|
+
})
|
|
196
|
+
]
|
|
197
|
+
})
|
|
198
|
+
]
|
|
199
|
+
})
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Width computation:**
|
|
203
|
+
|
|
204
|
+
```javascript
|
|
205
|
+
// table width = Σ columnWidths = page width − both margins
|
|
206
|
+
// US Letter + 1 in margins: 12240 − 2880 = 9360 DXA
|
|
207
|
+
width: { size: 9360, type: WidthType.DXA },
|
|
208
|
+
columnWidths: [7000, 2360] // must sum to 9360
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Table rules:**
|
|
212
|
+
- Always `WidthType.DXA` — `PERCENTAGE` breaks in Google Docs
|
|
213
|
+
- Cell `width` must equal its corresponding `columnWidths` entry
|
|
214
|
+
- Cell `margins` are inward padding (shrink content area, don't add to cell width)
|
|
215
|
+
- Full-width: set width to page width minus both lateral margins
|
|
216
|
+
|
|
217
|
+
### Images
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
new Paragraph({
|
|
221
|
+
children: [new ImageRun({
|
|
222
|
+
type: "png", // required; accepted: png, jpg, jpeg, gif, bmp, svg
|
|
223
|
+
data: fs.readFileSync("image.png"),
|
|
224
|
+
transformation: { width: 200, height: 150 },
|
|
225
|
+
altText: { title: "Title", description: "Desc", name: "Name" } // all three required
|
|
226
|
+
})]
|
|
227
|
+
})
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Page Breaks
|
|
231
|
+
|
|
232
|
+
```javascript
|
|
233
|
+
// PageBreak MUST live inside a Paragraph
|
|
234
|
+
new Paragraph({ children: [new PageBreak()] })
|
|
235
|
+
|
|
236
|
+
// Alternative: pageBreakBefore
|
|
237
|
+
new Paragraph({ pageBreakBefore: true, children: [new TextRun("New page")] })
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Hyperlinks
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
// External URL
|
|
244
|
+
new Paragraph({
|
|
245
|
+
children: [new ExternalHyperlink({
|
|
246
|
+
children: [new TextRun({ text: "Click here", style: "Hyperlink" })],
|
|
247
|
+
link: "https://example.com",
|
|
248
|
+
})]
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
// In-document cross-reference
|
|
252
|
+
// 1. Place bookmark at destination
|
|
253
|
+
new Paragraph({ heading: HeadingLevel.HEADING_1, children: [
|
|
254
|
+
new Bookmark({ id: "chapter1", children: [new TextRun("Chapter 1")] }),
|
|
255
|
+
]})
|
|
256
|
+
// 2. Link to it
|
|
257
|
+
new Paragraph({ children: [new InternalHyperlink({
|
|
258
|
+
children: [new TextRun({ text: "See Chapter 1", style: "Hyperlink" })],
|
|
259
|
+
anchor: "chapter1",
|
|
260
|
+
})]})
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Footnotes
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
const doc = new Document({
|
|
267
|
+
footnotes: {
|
|
268
|
+
1: { children: [new Paragraph("Source: Annual Report 2024")] },
|
|
269
|
+
2: { children: [new Paragraph("See appendix for methodology")] },
|
|
270
|
+
},
|
|
271
|
+
sections: [{
|
|
272
|
+
children: [new Paragraph({
|
|
273
|
+
children: [
|
|
274
|
+
new TextRun("Revenue grew 15%"),
|
|
275
|
+
new FootnoteReferenceRun(1),
|
|
276
|
+
new TextRun(" using adjusted metrics"),
|
|
277
|
+
new FootnoteReferenceRun(2),
|
|
278
|
+
],
|
|
279
|
+
})]
|
|
280
|
+
}]
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Tab Stops
|
|
285
|
+
|
|
286
|
+
```javascript
|
|
287
|
+
// Right-aligned text on the same line
|
|
288
|
+
new Paragraph({
|
|
289
|
+
children: [new TextRun("Company Name"), new TextRun("\tJanuary 2025")],
|
|
290
|
+
tabStops: [{ type: TabStopType.RIGHT, position: TabStopPosition.MAX }],
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
// Dot-leader (TOC-style)
|
|
294
|
+
new Paragraph({
|
|
295
|
+
children: [
|
|
296
|
+
new TextRun("Introduction"),
|
|
297
|
+
new TextRun({ children: [
|
|
298
|
+
new PositionalTab({
|
|
299
|
+
alignment: PositionalTabAlignment.RIGHT,
|
|
300
|
+
relativeTo: PositionalTabRelativeTo.MARGIN,
|
|
301
|
+
leader: PositionalTabLeader.DOT,
|
|
302
|
+
}),
|
|
303
|
+
"3",
|
|
304
|
+
]}),
|
|
305
|
+
],
|
|
306
|
+
})
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Multi-column Layouts
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
// Evenly spaced columns
|
|
313
|
+
sections: [{
|
|
314
|
+
properties: {
|
|
315
|
+
column: { count: 2, space: 720, equalWidth: true, separate: true },
|
|
316
|
+
},
|
|
317
|
+
children: [/* text flows across columns automatically */]
|
|
318
|
+
}]
|
|
319
|
+
|
|
320
|
+
// Custom widths
|
|
321
|
+
sections: [{
|
|
322
|
+
properties: {
|
|
323
|
+
column: {
|
|
324
|
+
equalWidth: false,
|
|
325
|
+
children: [new Column({ width: 5400, space: 720 }), new Column({ width: 3240 })],
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
children: [/* content */]
|
|
329
|
+
}]
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Explicit column break: add a new section with `type: SectionType.NEXT_COLUMN`.
|
|
333
|
+
|
|
334
|
+
### Table of Contents
|
|
335
|
+
|
|
336
|
+
```javascript
|
|
337
|
+
// Headings MUST use HeadingLevel — custom paragraph styles are invisible to the TOC.
|
|
338
|
+
new TableOfContents("Table of Contents", { hyperlink: true, headingStyleRange: "1-3" })
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Headers and Footers
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
sections: [{
|
|
345
|
+
properties: {
|
|
346
|
+
page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } }
|
|
347
|
+
},
|
|
348
|
+
headers: {
|
|
349
|
+
default: new Header({ children: [new Paragraph({ children: [new TextRun("Header")] })] })
|
|
350
|
+
},
|
|
351
|
+
footers: {
|
|
352
|
+
default: new Footer({ children: [new Paragraph({
|
|
353
|
+
children: [new TextRun("Page "), new TextRun({ children: [PageNumber.CURRENT] })]
|
|
354
|
+
})] })
|
|
355
|
+
},
|
|
356
|
+
children: [/* body */]
|
|
357
|
+
}]
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Essential docx-js Rules
|
|
361
|
+
|
|
362
|
+
- **Page size:** defaults to A4; US Letter = 12 240 × 15 840 DXA
|
|
363
|
+
- **Landscape:** supply portrait dimensions + `PageOrientation.LANDSCAPE`
|
|
364
|
+
- **No `\n`:** create separate Paragraph objects
|
|
365
|
+
- **No Unicode bullets:** use `LevelFormat.BULLET` via numbering API
|
|
366
|
+
- **PageBreak inside Paragraph only**
|
|
367
|
+
- **ImageRun requires `type`**
|
|
368
|
+
- **Table `width` must use DXA** — `PERCENTAGE` breaks in Google Docs
|
|
369
|
+
- **Dual-width rule:** set `columnWidths` on table AND `width` on every cell
|
|
370
|
+
- **Table width = Σ columnWidths**
|
|
371
|
+
- **Cell margins:** `{ top: 80, bottom: 80, left: 120, right: 120 }` for readable padding
|
|
372
|
+
- **Use `ShadingType.CLEAR`** — never SOLID for cell fills
|
|
373
|
+
- **Avoid tables as dividers:** use border on Paragraph instead; for side-by-side footer content use tab stops
|
|
374
|
+
- **TOC only with HeadingLevel**
|
|
375
|
+
- **Override styles by ID:** "Heading1", "Heading2", etc.
|
|
376
|
+
- **Provide `outlineLevel`** for TOC (0 = H1, 1 = H2 …)
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Patching Existing Documents
|
|
381
|
+
|
|
382
|
+
Execute all three stages in order.
|
|
383
|
+
|
|
384
|
+
### Stage 1 — Unpack
|
|
385
|
+
|
|
386
|
+
```bash
|
|
387
|
+
python scripts/office/unpack.py document.docx unpacked/
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Inflates the archive, pretty-prints XML, coalesces adjacent runs, and encodes typographic quotes as XML entities (`“` etc.). Pass `--merge-runs false` to skip run coalescing.
|
|
391
|
+
|
|
392
|
+
### Stage 2 — Edit the XML
|
|
393
|
+
|
|
394
|
+
Work inside `unpacked/word/`. Refer to §XML Patterns below.
|
|
395
|
+
|
|
396
|
+
**Use "Claude" as the author** for tracked changes and comments, unless the user specifies otherwise.
|
|
397
|
+
|
|
398
|
+
**Use the Edit tool for string replacements — do not write Python scripts.** The Edit tool makes every replacement visible and auditable.
|
|
399
|
+
|
|
400
|
+
**Use typographic (smart) quotes for new text:**
|
|
401
|
+
|
|
402
|
+
```xml
|
|
403
|
+
<w:t>Here’s a quote: “Hello”</w:t>
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
| Entity | Character |
|
|
407
|
+
|--------|-----------|
|
|
408
|
+
| `‘` | ' (left single) |
|
|
409
|
+
| `’` | ' (right single / apostrophe) |
|
|
410
|
+
| `“` | " (left double) |
|
|
411
|
+
| `”` | " (right double) |
|
|
412
|
+
|
|
413
|
+
**Inserting comments** — `comment.py` handles the multi-file boilerplate (text must be XML-escaped):
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
python scripts/comment.py unpacked/ 0 "Comment text with & and ’"
|
|
417
|
+
python scripts/comment.py unpacked/ 1 "Reply text" --parent 0
|
|
418
|
+
python scripts/comment.py unpacked/ 0 "Text" --author "Custom Author"
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Then wire markers into document.xml (see §Comments below).
|
|
422
|
+
|
|
423
|
+
### Stage 3 — Repack
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
python scripts/office/pack.py unpacked/ output.docx --original document.docx
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Validates with automatic repair, condenses XML, produces the final DOCX. Pass `--validate false` to bypass.
|
|
430
|
+
|
|
431
|
+
**Auto-repair corrects:**
|
|
432
|
+
- `durableId` values ≥ 0x7FFFFFFF (replaced with fresh IDs)
|
|
433
|
+
- Missing `xml:space="preserve"` on `<w:t>` with leading/trailing whitespace
|
|
434
|
+
|
|
435
|
+
**Does NOT fix:** malformed XML, illegal nesting, broken relationships, schema violations.
|
|
436
|
+
|
|
437
|
+
### Gotchas
|
|
438
|
+
|
|
439
|
+
- **Swap whole `<w:r>` blocks:** when introducing tracked changes, replace the entire run — never splice change-tracking tags inside an existing run.
|
|
440
|
+
- **Carry forward `<w:rPr>`:** copy original formatting properties into new tracked-change runs.
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
## XML Patterns
|
|
445
|
+
|
|
446
|
+
### Schema Ordering
|
|
447
|
+
|
|
448
|
+
- **`<w:pPr>` child order:** `<w:pStyle>` → `<w:numPr>` → `<w:spacing>` → `<w:ind>` → `<w:jc>` → `<w:rPr>` last
|
|
449
|
+
- **Whitespace:** attach `xml:space="preserve"` to any `<w:t>` with leading/trailing spaces
|
|
450
|
+
- **RSIDs:** 8-character hexadecimal (e.g. `00AB1234`)
|
|
451
|
+
|
|
452
|
+
### Tracked Changes
|
|
453
|
+
|
|
454
|
+
**Insertion:**
|
|
455
|
+
|
|
456
|
+
```xml
|
|
457
|
+
<w:ins w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
|
458
|
+
<w:r><w:t>inserted text</w:t></w:r>
|
|
459
|
+
</w:ins>
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
**Deletion:**
|
|
463
|
+
|
|
464
|
+
```xml
|
|
465
|
+
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
|
466
|
+
<w:r><w:delText>deleted text</w:delText></w:r>
|
|
467
|
+
</w:del>
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Inside `<w:del>`: use `<w:delText>` instead of `<w:t>`, `<w:delInstrText>` instead of `<w:instrText>`.
|
|
471
|
+
|
|
472
|
+
**Minimal-footprint edit (change "30 days" to "60 days"):**
|
|
473
|
+
|
|
474
|
+
```xml
|
|
475
|
+
<w:r><w:t>The term is </w:t></w:r>
|
|
476
|
+
<w:del w:id="1" w:author="Claude" w:date="...">
|
|
477
|
+
<w:r><w:delText>30</w:delText></w:r>
|
|
478
|
+
</w:del>
|
|
479
|
+
<w:ins w:id="2" w:author="Claude" w:date="...">
|
|
480
|
+
<w:r><w:t>60</w:t></w:r>
|
|
481
|
+
</w:ins>
|
|
482
|
+
<w:r><w:t> days.</w:t></w:r>
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
**Deleting a complete paragraph** — flag the paragraph mark so the empty shell merges with the next paragraph:
|
|
486
|
+
|
|
487
|
+
```xml
|
|
488
|
+
<w:p>
|
|
489
|
+
<w:pPr>
|
|
490
|
+
<w:numPr>...</w:numPr>
|
|
491
|
+
<w:rPr>
|
|
492
|
+
<w:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z"/>
|
|
493
|
+
</w:rPr>
|
|
494
|
+
</w:pPr>
|
|
495
|
+
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
|
496
|
+
<w:r><w:delText>Entire paragraph content being deleted...</w:delText></w:r>
|
|
497
|
+
</w:del>
|
|
498
|
+
</w:p>
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Without the `<w:del/>` in `<w:pPr><w:rPr>`, accepting leaves a blank paragraph.
|
|
502
|
+
|
|
503
|
+
**Rejecting another author's insertion:**
|
|
504
|
+
|
|
505
|
+
```xml
|
|
506
|
+
<w:ins w:author="Jane" w:id="5">
|
|
507
|
+
<w:del w:author="Claude" w:id="10">
|
|
508
|
+
<w:r><w:delText>their inserted text</w:delText></w:r>
|
|
509
|
+
</w:del>
|
|
510
|
+
</w:ins>
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
**Restoring another author's deletion:**
|
|
514
|
+
|
|
515
|
+
```xml
|
|
516
|
+
<w:del w:author="Jane" w:id="5">
|
|
517
|
+
<w:r><w:delText>deleted text</w:delText></w:r>
|
|
518
|
+
</w:del>
|
|
519
|
+
<w:ins w:author="Claude" w:id="10">
|
|
520
|
+
<w:r><w:t>deleted text</w:t></w:r>
|
|
521
|
+
</w:ins>
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
### Comments
|
|
525
|
+
|
|
526
|
+
After calling `comment.py`, add range markers in document.xml. For replies, use `--parent` and nest child markers inside the parent's range.
|
|
527
|
+
|
|
528
|
+
**Rule: `<w:commentRangeStart>` and `<w:commentRangeEnd>` are siblings of `<w:r>` — never inside a run.**
|
|
529
|
+
|
|
530
|
+
```xml
|
|
531
|
+
<!-- Standalone comment -->
|
|
532
|
+
<w:commentRangeStart w:id="0"/>
|
|
533
|
+
<w:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
|
534
|
+
<w:r><w:delText>deleted</w:delText></w:r>
|
|
535
|
+
</w:del>
|
|
536
|
+
<w:r><w:t> more text</w:t></w:r>
|
|
537
|
+
<w:commentRangeEnd w:id="0"/>
|
|
538
|
+
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="0"/></w:r>
|
|
539
|
+
|
|
540
|
+
<!-- Comment 0 with nested reply 1 -->
|
|
541
|
+
<w:commentRangeStart w:id="0"/>
|
|
542
|
+
<w:commentRangeStart w:id="1"/>
|
|
543
|
+
<w:r><w:t>text</w:t></w:r>
|
|
544
|
+
<w:commentRangeEnd w:id="1"/>
|
|
545
|
+
<w:commentRangeEnd w:id="0"/>
|
|
546
|
+
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="0"/></w:r>
|
|
547
|
+
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="1"/></w:r>
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
### Images
|
|
551
|
+
|
|
552
|
+
1. Drop file into `word/media/`
|
|
553
|
+
2. Register relationship in `word/_rels/document.xml.rels`:
|
|
554
|
+
|
|
555
|
+
```xml
|
|
556
|
+
<Relationship Id="rId5" Type=".../image" Target="media/image1.png"/>
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
3. Declare content type in `[Content_Types].xml`:
|
|
560
|
+
|
|
561
|
+
```xml
|
|
562
|
+
<Default Extension="png" ContentType="image/png"/>
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
4. Reference from document.xml:
|
|
566
|
+
|
|
567
|
+
```xml
|
|
568
|
+
<w:drawing>
|
|
569
|
+
<wp:inline>
|
|
570
|
+
<wp:extent cx="914400" cy="914400"/> <!-- EMUs: 914 400 = 1 inch -->
|
|
571
|
+
<a:graphic>
|
|
572
|
+
<a:graphicData uri=".../picture">
|
|
573
|
+
<pic:pic>
|
|
574
|
+
<pic:blipFill><a:blip r:embed="rId5"/></pic:blipFill>
|
|
575
|
+
</pic:pic>
|
|
576
|
+
</a:graphicData>
|
|
577
|
+
</a:graphic>
|
|
578
|
+
</wp:inline>
|
|
579
|
+
</w:drawing>
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
---
|
|
583
|
+
|
|
584
|
+
## External Dependencies
|
|
585
|
+
|
|
586
|
+
- **pandoc** — text extraction and format conversion
|
|
587
|
+
- **docx** — `npm install -g docx` (new-document generation)
|
|
588
|
+
- **LibreOffice** — PDF conversion (auto-configured via `scripts/office/soffice.py`)
|
|
589
|
+
- **Poppler** — `pdftoppm` for rasterising PDF pages
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Package marker — no public API exposed at this level.
|