← 返回 Skills 市场
yangxiaoqiang1992

Docx

作者 yangxiaoqiang1992 · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ⚠ suspicious
29
总下载
0
收藏
0
当前安装
1
版本数
在 OpenClaw 中安装
/install docx1
功能描述
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...
使用说明 (SKILL.md)

\r \r

DOCX creation, editing, and analysis\r

\r

Overview\r

\r A .docx file is a ZIP archive containing XML files.\r \r

Quick Reference\r

\r | Task | Approach |\r |------|----------|\r | Read/analyze content | pandoc or unpack for raw XML |\r | Create new document | Use docx-js - see Creating New Documents below |\r | Edit existing document | Unpack → edit XML → repack - see Editing Existing Documents below |\r \r

Converting .doc to .docx\r

\r Legacy .doc files must be converted before editing:\r \r

python scripts/office/soffice.py --headless --convert-to docx document.doc\r
```\r
\r
### Reading Content\r
\r
```bash\r
# Text extraction with tracked changes\r
pandoc --track-changes=all document.docx -o output.md\r
\r
# Raw XML access\r
python scripts/office/unpack.py document.docx unpacked/\r
```\r
\r
### Converting to Images\r
\r
```bash\r
python scripts/office/soffice.py --headless --convert-to pdf document.docx\r
pdftoppm -jpeg -r 150 document.pdf page\r
```\r
\r
### Accepting Tracked Changes\r
\r
To produce a clean document with all tracked changes accepted (requires LibreOffice):\r
\r
```bash\r
python scripts/accept_changes.py input.docx output.docx\r
```\r
\r
---\r
\r
## Creating New Documents\r
\r
Generate .docx files with JavaScript, then validate. Install: `npm install -g docx`\r
\r
### Setup\r
```javascript\r
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun,\r
        Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink,\r
        InternalHyperlink, Bookmark, FootnoteReferenceRun, PositionalTab,\r
        PositionalTabAlignment, PositionalTabRelativeTo, PositionalTabLeader,\r
        TabStopType, TabStopPosition, Column, SectionType,\r
        TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType,\r
        VerticalAlign, PageNumber, PageBreak } = require('docx');\r
\r
const doc = new Document({ sections: [{ children: [/* content */] }] });\r
Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer));\r
```\r
\r
### Validation\r
After creating the file, validate it. If validation fails, unpack, fix the XML, and repack.\r
```bash\r
python scripts/office/validate.py doc.docx\r
```\r
\r
### Page Size\r
\r
```javascript\r
// CRITICAL: docx-js defaults to A4, not US Letter\r
// Always set page size explicitly for consistent results\r
sections: [{\r
  properties: {\r
    page: {\r
      size: {\r
        width: 12240,   // 8.5 inches in DXA\r
        height: 15840   // 11 inches in DXA\r
      },\r
      margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } // 1 inch margins\r
    }\r
  },\r
  children: [/* content */]\r
}]\r
```\r
\r
**Common page sizes (DXA units, 1440 DXA = 1 inch):**\r
\r
| Paper | Width | Height | Content Width (1" margins) |\r
|-------|-------|--------|---------------------------|\r
| US Letter | 12,240 | 15,840 | 9,360 |\r
| A4 (default) | 11,906 | 16,838 | 9,026 |\r
\r
**Landscape orientation:** docx-js swaps width/height internally, so pass portrait dimensions and let it handle the swap:\r
```javascript\r
size: {\r
  width: 12240,   // Pass SHORT edge as width\r
  height: 15840,  // Pass LONG edge as height\r
  orientation: PageOrientation.LANDSCAPE  // docx-js swaps them in the XML\r
},\r
// Content width = 15840 - left margin - right margin (uses the long edge)\r
```\r
\r
### Styles (Override Built-in Headings)\r
\r
Use Arial as the default font (universally supported). Keep titles black for readability.\r
\r
```javascript\r
const doc = new Document({\r
  styles: {\r
    default: { document: { run: { font: "Arial", size: 24 } } }, // 12pt default\r
    paragraphStyles: [\r
      // IMPORTANT: Use exact IDs to override built-in styles\r
      { id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true,\r
        run: { size: 32, bold: true, font: "Arial" },\r
        paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } }, // outlineLevel required for TOC\r
      { id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true,\r
        run: { size: 28, bold: true, font: "Arial" },\r
        paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } },\r
    ]\r
  },\r
  sections: [{\r
    children: [\r
      new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("Title")] }),\r
    ]\r
  }]\r
});\r
```\r
\r
### Lists (NEVER use unicode bullets)\r
\r
```javascript\r
// ❌ WRONG - never manually insert bullet characters\r
new Paragraph({ children: [new TextRun("• Item")] })  // BAD\r
new Paragraph({ children: [new TextRun("\u2022 Item")] })  // BAD\r
\r
// ✅ CORRECT - use numbering config with LevelFormat.BULLET\r
const doc = new Document({\r
  numbering: {\r
    config: [\r
      { reference: "bullets",\r
        levels: [{ level: 0, format: LevelFormat.BULLET, text: "•", alignment: AlignmentType.LEFT,\r
          style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },\r
      { reference: "numbers",\r
        levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT,\r
          style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },\r
    ]\r
  },\r
  sections: [{\r
    children: [\r
      new Paragraph({ numbering: { reference: "bullets", level: 0 },\r
        children: [new TextRun("Bullet item")] }),\r
      new Paragraph({ numbering: { reference: "numbers", level: 0 },\r
        children: [new TextRun("Numbered item")] }),\r
    ]\r
  }]\r
});\r
\r
// ⚠️ Each reference creates INDEPENDENT numbering\r
// Same reference = continues (1,2,3 then 4,5,6)\r
// Different reference = restarts (1,2,3 then 1,2,3)\r
```\r
\r
### Tables\r
\r
**CRITICAL: Tables need dual widths** - set both `columnWidths` on the table AND `width` on each cell. Without both, tables render incorrectly on some platforms.\r
\r
```javascript\r
// CRITICAL: Always set table width for consistent rendering\r
// CRITICAL: Use ShadingType.CLEAR (not SOLID) to prevent black backgrounds\r
const border = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" };\r
const borders = { top: border, bottom: border, left: border, right: border };\r
\r
new Table({\r
  width: { size: 9360, type: WidthType.DXA }, // Always use DXA (percentages break in Google Docs)\r
  columnWidths: [4680, 4680], // Must sum to table width (DXA: 1440 = 1 inch)\r
  rows: [\r
    new TableRow({\r
      children: [\r
        new TableCell({\r
          borders,\r
          width: { size: 4680, type: WidthType.DXA }, // Also set on each cell\r
          shading: { fill: "D5E8F0", type: ShadingType.CLEAR }, // CLEAR not SOLID\r
          margins: { top: 80, bottom: 80, left: 120, right: 120 }, // Cell padding (internal, not added to width)\r
          children: [new Paragraph({ children: [new TextRun("Cell")] })]\r
        })\r
      ]\r
    })\r
  ]\r
})\r
```\r
\r
**Table width calculation:**\r
\r
Always use `WidthType.DXA` — `WidthType.PERCENTAGE` breaks in Google Docs.\r
\r
```javascript\r
// Table width = sum of columnWidths = content width\r
// US Letter with 1" margins: 12240 - 2880 = 9360 DXA\r
width: { size: 9360, type: WidthType.DXA },\r
columnWidths: [7000, 2360]  // Must sum to table width\r
```\r
\r
**Width rules:**\r
- **Always use `WidthType.DXA`** — never `WidthType.PERCENTAGE` (incompatible with Google Docs)\r
- Table width must equal the sum of `columnWidths`\r
- Cell `width` must match corresponding `columnWidth`\r
- Cell `margins` are internal padding - they reduce content area, not add to cell width\r
- For full-width tables: use content width (page width minus left and right margins)\r
\r
### Images\r
\r
```javascript\r
// CRITICAL: type parameter is REQUIRED\r
new Paragraph({\r
  children: [new ImageRun({\r
    type: "png", // Required: png, jpg, jpeg, gif, bmp, svg\r
    data: fs.readFileSync("image.png"),\r
    transformation: { width: 200, height: 150 },\r
    altText: { title: "Title", description: "Desc", name: "Name" } // All three required\r
  })]\r
})\r
```\r
\r
### Page Breaks\r
\r
```javascript\r
// CRITICAL: PageBreak must be inside a Paragraph\r
new Paragraph({ children: [new PageBreak()] })\r
\r
// Or use pageBreakBefore\r
new Paragraph({ pageBreakBefore: true, children: [new TextRun("New page")] })\r
```\r
\r
### Hyperlinks\r
\r
```javascript\r
// External link\r
new Paragraph({\r
  children: [new ExternalHyperlink({\r
    children: [new TextRun({ text: "Click here", style: "Hyperlink" })],\r
    link: "https://example.com",\r
  })]\r
})\r
\r
// Internal link (bookmark + reference)\r
// 1. Create bookmark at destination\r
new Paragraph({ heading: HeadingLevel.HEADING_1, children: [\r
  new Bookmark({ id: "chapter1", children: [new TextRun("Chapter 1")] }),\r
]})\r
// 2. Link to it\r
new Paragraph({ children: [new InternalHyperlink({\r
  children: [new TextRun({ text: "See Chapter 1", style: "Hyperlink" })],\r
  anchor: "chapter1",\r
})]})\r
```\r
\r
### Footnotes\r
\r
```javascript\r
const doc = new Document({\r
  footnotes: {\r
    1: { children: [new Paragraph("Source: Annual Report 2024")] },\r
    2: { children: [new Paragraph("See appendix for methodology")] },\r
  },\r
  sections: [{\r
    children: [new Paragraph({\r
      children: [\r
        new TextRun("Revenue grew 15%"),\r
        new FootnoteReferenceRun(1),\r
        new TextRun(" using adjusted metrics"),\r
        new FootnoteReferenceRun(2),\r
      ],\r
    })]\r
  }]\r
});\r
```\r
\r
### Tab Stops\r
\r
```javascript\r
// Right-align text on same line (e.g., date opposite a title)\r
new Paragraph({\r
  children: [\r
    new TextRun("Company Name"),\r
    new TextRun("	January 2025"),\r
  ],\r
  tabStops: [{ type: TabStopType.RIGHT, position: TabStopPosition.MAX }],\r
})\r
\r
// Dot leader (e.g., TOC-style)\r
new Paragraph({\r
  children: [\r
    new TextRun("Introduction"),\r
    new TextRun({ children: [\r
      new PositionalTab({\r
        alignment: PositionalTabAlignment.RIGHT,\r
        relativeTo: PositionalTabRelativeTo.MARGIN,\r
        leader: PositionalTabLeader.DOT,\r
      }),\r
      "3",\r
    ]}),\r
  ],\r
})\r
```\r
\r
### Multi-Column Layouts\r
\r
```javascript\r
// Equal-width columns\r
sections: [{\r
  properties: {\r
    column: {\r
      count: 2,          // number of columns\r
      space: 720,        // gap between columns in DXA (720 = 0.5 inch)\r
      equalWidth: true,\r
      separate: true,    // vertical line between columns\r
    },\r
  },\r
  children: [/* content flows naturally across columns */]\r
}]\r
\r
// Custom-width columns (equalWidth must be false)\r
sections: [{\r
  properties: {\r
    column: {\r
      equalWidth: false,\r
      children: [\r
        new Column({ width: 5400, space: 720 }),\r
        new Column({ width: 3240 }),\r
      ],\r
    },\r
  },\r
  children: [/* content */]\r
}]\r
```\r
\r
Force a column break with a new section using `type: SectionType.NEXT_COLUMN`.\r
\r
### Table of Contents\r
\r
```javascript\r
// CRITICAL: Headings must use HeadingLevel ONLY - no custom styles\r
new TableOfContents("Table of Contents", { hyperlink: true, headingStyleRange: "1-3" })\r
```\r
\r
### Headers/Footers\r
\r
```javascript\r
sections: [{\r
  properties: {\r
    page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } } // 1440 = 1 inch\r
  },\r
  headers: {\r
    default: new Header({ children: [new Paragraph({ children: [new TextRun("Header")] })] })\r
  },\r
  footers: {\r
    default: new Footer({ children: [new Paragraph({\r
      children: [new TextRun("Page "), new TextRun({ children: [PageNumber.CURRENT] })]\r
    })] })\r
  },\r
  children: [/* content */]\r
}]\r
```\r
\r
### Critical Rules for docx-js\r
\r
- **Set page size explicitly** - docx-js defaults to A4; use US Letter (12240 x 15840 DXA) for US documents\r
- **Landscape: pass portrait dimensions** - docx-js swaps width/height internally; pass short edge as `width`, long edge as `height`, and set `orientation: PageOrientation.LANDSCAPE`\r
- **Never use `\
`** - use separate Paragraph elements\r
- **Never use unicode bullets** - use `LevelFormat.BULLET` with numbering config\r
- **PageBreak must be in Paragraph** - standalone creates invalid XML\r
- **ImageRun requires `type`** - always specify png/jpg/etc\r
- **Always set table `width` with DXA** - never use `WidthType.PERCENTAGE` (breaks in Google Docs)\r
- **Tables need dual widths** - `columnWidths` array AND cell `width`, both must match\r
- **Table width = sum of columnWidths** - for DXA, ensure they add up exactly\r
- **Always add cell margins** - use `margins: { top: 80, bottom: 80, left: 120, right: 120 }` for readable padding\r
- **Use `ShadingType.CLEAR`** - never SOLID for table shading\r
- **Never use tables as dividers/rules** - cells have minimum height and render as empty boxes (including in headers/footers); use `border: { bottom: { style: BorderStyle.SINGLE, size: 6, color: "2E75B6", space: 1 } }` on a Paragraph instead. For two-column footers, use tab stops (see Tab Stops section), not tables\r
- **TOC requires HeadingLevel only** - no custom styles on heading paragraphs\r
- **Override built-in styles** - use exact IDs: "Heading1", "Heading2", etc.\r
- **Include `outlineLevel`** - required for TOC (0 for H1, 1 for H2, etc.)\r
\r
---\r
\r
## Editing Existing Documents\r
\r
**Follow all 3 steps in order.**\r
\r
### Step 1: Unpack\r
```bash\r
python scripts/office/unpack.py document.docx unpacked/\r
```\r
Extracts XML, pretty-prints, merges adjacent runs, and converts smart quotes to XML entities (`“` etc.) so they survive editing. Use `--merge-runs false` to skip run merging.\r
\r
### Step 2: Edit XML\r
\r
Edit files in `unpacked/word/`. See XML Reference below for patterns.\r
\r
**Use "Claude" as the author** for tracked changes and comments, unless the user explicitly requests use of a different name.\r
\r
**Use the Edit tool directly for string replacement. Do not write Python scripts.** Scripts introduce unnecessary complexity. The Edit tool shows exactly what is being replaced.\r
\r
**CRITICAL: Use smart quotes for new content.** When adding text with apostrophes or quotes, use XML entities to produce smart quotes:\r
```xml\r
\x3C!-- Use these entities for professional typography -->\r
\x3Cw:t>Here’s a quote: “Hello”\x3C/w:t>\r
```\r
| Entity | Character |\r
|--------|-----------|\r
| `‘` | ‘ (left single) |\r
| `’` | ’ (right single / apostrophe) |\r
| `“` | “ (left double) |\r
| `”` | ” (right double) |\r
\r
**Adding comments:** Use `comment.py` to handle boilerplate across multiple XML files (text must be pre-escaped XML):\r
```bash\r
python scripts/comment.py unpacked/ 0 "Comment text with & and ’"\r
python scripts/comment.py unpacked/ 1 "Reply text" --parent 0  # reply to comment 0\r
python scripts/comment.py unpacked/ 0 "Text" --author "Custom Author"  # custom author name\r
```\r
Then add markers to document.xml (see Comments in XML Reference).\r
\r
### Step 3: Pack\r
```bash\r
python scripts/office/pack.py unpacked/ output.docx --original document.docx\r
```\r
Validates with auto-repair, condenses XML, and creates DOCX. Use `--validate false` to skip.\r
\r
**Auto-repair will fix:**\r
- `durableId` >= 0x7FFFFFFF (regenerates valid ID)\r
- Missing `xml:space="preserve"` on `\x3Cw:t>` with whitespace\r
\r
**Auto-repair won't fix:**\r
- Malformed XML, invalid element nesting, missing relationships, schema violations\r
\r
### Common Pitfalls\r
\r
- **Replace entire `\x3Cw:r>` elements**: When adding tracked changes, replace the whole `\x3Cw:r>...\x3C/w:r>` block with `\x3Cw:del>...\x3Cw:ins>...` as siblings. Don't inject tracked change tags inside a run.\r
- **Preserve `\x3Cw:rPr>` formatting**: Copy the original run's `\x3Cw:rPr>` block into your tracked change runs to maintain bold, font size, etc.\r
\r
---\r
\r
## XML Reference\r
\r
### Schema Compliance\r
\r
- **Element order in `\x3Cw:pPr>`**: `\x3Cw:pStyle>`, `\x3Cw:numPr>`, `\x3Cw:spacing>`, `\x3Cw:ind>`, `\x3Cw:jc>`, `\x3Cw:rPr>` last\r
- **Whitespace**: Add `xml:space="preserve"` to `\x3Cw:t>` with leading/trailing spaces\r
- **RSIDs**: Must be 8-digit hex (e.g., `00AB1234`)\r
\r
### Tracked Changes\r
\r
**Insertion:**\r
```xml\r
\x3Cw:ins w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">\r
  \x3Cw:r>\x3Cw:t>inserted text\x3C/w:t>\x3C/w:r>\r
\x3C/w:ins>\r
```\r
\r
**Deletion:**\r
```xml\r
\x3Cw:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">\r
  \x3Cw:r>\x3Cw:delText>deleted text\x3C/w:delText>\x3C/w:r>\r
\x3C/w:del>\r
```\r
\r
**Inside `\x3Cw:del>`**: Use `\x3Cw:delText>` instead of `\x3Cw:t>`, and `\x3Cw:delInstrText>` instead of `\x3Cw:instrText>`.\r
\r
**Minimal edits** - only mark what changes:\r
```xml\r
\x3C!-- Change "30 days" to "60 days" -->\r
\x3Cw:r>\x3Cw:t>The term is \x3C/w:t>\x3C/w:r>\r
\x3Cw:del w:id="1" w:author="Claude" w:date="...">\r
  \x3Cw:r>\x3Cw:delText>30\x3C/w:delText>\x3C/w:r>\r
\x3C/w:del>\r
\x3Cw:ins w:id="2" w:author="Claude" w:date="...">\r
  \x3Cw:r>\x3Cw:t>60\x3C/w:t>\x3C/w:r>\r
\x3C/w:ins>\r
\x3Cw:r>\x3Cw:t> days.\x3C/w:t>\x3C/w:r>\r
```\r
\r
**Deleting entire paragraphs/list items** - when removing ALL content from a paragraph, also mark the paragraph mark as deleted so it merges with the next paragraph. Add `\x3Cw:del/>` inside `\x3Cw:pPr>\x3Cw:rPr>`:\r
```xml\r
\x3Cw:p>\r
  \x3Cw:pPr>\r
    \x3Cw:numPr>...\x3C/w:numPr>  \x3C!-- list numbering if present -->\r
    \x3Cw:rPr>\r
      \x3Cw:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z"/>\r
    \x3C/w:rPr>\r
  \x3C/w:pPr>\r
  \x3Cw:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">\r
    \x3Cw:r>\x3Cw:delText>Entire paragraph content being deleted...\x3C/w:delText>\x3C/w:r>\r
  \x3C/w:del>\r
\x3C/w:p>\r
```\r
Without the `\x3Cw:del/>` in `\x3Cw:pPr>\x3Cw:rPr>`, accepting changes leaves an empty paragraph/list item.\r
\r
**Rejecting another author's insertion** - nest deletion inside their insertion:\r
```xml\r
\x3Cw:ins w:author="Jane" w:id="5">\r
  \x3Cw:del w:author="Claude" w:id="10">\r
    \x3Cw:r>\x3Cw:delText>their inserted text\x3C/w:delText>\x3C/w:r>\r
  \x3C/w:del>\r
\x3C/w:ins>\r
```\r
\r
**Restoring another author's deletion** - add insertion after (don't modify their deletion):\r
```xml\r
\x3Cw:del w:author="Jane" w:id="5">\r
  \x3Cw:r>\x3Cw:delText>deleted text\x3C/w:delText>\x3C/w:r>\r
\x3C/w:del>\r
\x3Cw:ins w:author="Claude" w:id="10">\r
  \x3Cw:r>\x3Cw:t>deleted text\x3C/w:t>\x3C/w:r>\r
\x3C/w:ins>\r
```\r
\r
### Comments\r
\r
After running `comment.py` (see Step 2), add markers to document.xml. For replies, use `--parent` flag and nest markers inside the parent's.\r
\r
**CRITICAL: `\x3Cw:commentRangeStart>` and `\x3Cw:commentRangeEnd>` are siblings of `\x3Cw:r>`, never inside `\x3Cw:r>`.**\r
\r
```xml\r
\x3C!-- Comment markers are direct children of w:p, never inside w:r -->\r
\x3Cw:commentRangeStart w:id="0"/>\r
\x3Cw:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">\r
  \x3Cw:r>\x3Cw:delText>deleted\x3C/w:delText>\x3C/w:r>\r
\x3C/w:del>\r
\x3Cw:r>\x3Cw:t> more text\x3C/w:t>\x3C/w:r>\r
\x3Cw:commentRangeEnd w:id="0"/>\r
\x3Cw:r>\x3Cw:rPr>\x3Cw:rStyle w:val="CommentReference"/>\x3C/w:rPr>\x3Cw:commentReference w:id="0"/>\x3C/w:r>\r
\r
\x3C!-- Comment 0 with reply 1 nested inside -->\r
\x3Cw:commentRangeStart w:id="0"/>\r
  \x3Cw:commentRangeStart w:id="1"/>\r
  \x3Cw:r>\x3Cw:t>text\x3C/w:t>\x3C/w:r>\r
  \x3Cw:commentRangeEnd w:id="1"/>\r
\x3Cw:commentRangeEnd w:id="0"/>\r
\x3Cw:r>\x3Cw:rPr>\x3Cw:rStyle w:val="CommentReference"/>\x3C/w:rPr>\x3Cw:commentReference w:id="0"/>\x3C/w:r>\r
\x3Cw:r>\x3Cw:rPr>\x3Cw:rStyle w:val="CommentReference"/>\x3C/w:rPr>\x3Cw:commentReference w:id="1"/>\x3C/w:r>\r
```\r
\r
### Images\r
\r
1. Add image file to `word/media/`\r
2. Add relationship to `word/_rels/document.xml.rels`:\r
```xml\r
\x3CRelationship Id="rId5" Type=".../image" Target="media/image1.png"/>\r
```\r
3. Add content type to `[Content_Types].xml`:\r
```xml\r
\x3CDefault Extension="png" ContentType="image/png"/>\r
```\r
4. Reference in document.xml:\r
```xml\r
\x3Cw:drawing>\r
  \x3Cwp:inline>\r
    \x3Cwp:extent cx="914400" cy="914400"/>  \x3C!-- EMUs: 914400 = 1 inch -->\r
    \x3Ca:graphic>\r
      \x3Ca:graphicData uri=".../picture">\r
        \x3Cpic:pic>\r
          \x3Cpic:blipFill>\x3Ca:blip r:embed="rId5"/>\x3C/pic:blipFill>\r
        \x3C/pic:pic>\r
      \x3C/a:graphicData>\r
    \x3C/a:graphic>\r
  \x3C/wp:inline>\r
\x3C/w:drawing>\r
```\r
\r
---\r
\r
## Dependencies\r
\r
- **pandoc**: Text extraction\r
- **docx**: `npm install -g docx` (new documents)\r
- **LibreOffice**: PDF conversion (auto-configured for sandboxed environments via `scripts/office/soffice.py`)\r
- **Poppler**: `pdftoppm` for images\r
安全使用建议
Install only if you are comfortable with a document skill that runs external office tools and can invoke gcc plus LD_PRELOAD for LibreOffice in some environments. Use it on copies of documents in a controlled workspace, avoid untrusted Office files, and review the LibreOffice shim behavior before using conversion or tracked-change acceptance features.
能力评估
Purpose & Capability
The core DOCX creation, XML editing, comments, tracked-changes, validation, packing, and conversion helpers are purpose-aligned, but the package also supports PPTX/XLSX helpers despite being presented as DOCX-focused, and it includes an LD_PRELOAD LibreOffice shim that goes beyond ordinary document editing.
Instruction Scope
The SKILL.md trigger guidance is mostly scoped to Word/.docx work and explicitly excludes spreadsheets and PDFs, but bundled script help and validators expose broader Office archive operations.
Install Mechanism
No installer or self-updating behavior was found; the documentation does ask users to rely on external tools such as LibreOffice, pandoc, poppler, npm docx, git, gcc, and the skill scripts.
Credentials
The LibreOffice helper can compile C code at runtime, place artifacts in the shared temp directory, and inject the resulting shared object with LD_PRELOAD when AF_UNIX sockets are unavailable; that is high-impact behavior for a DOCX skill and lacks clear opt-in controls.
Persistence & Privilege
The skill does not access credentials or create account-level persistence, but it can leave a shared /tmp LibreOffice shim and creates a persistent LibreOffice macro profile under /tmp for accepting tracked changes.
如何使用
  1. 确保已安装 OpenClaw(本地或 Docker 部署)
  2. 在对话框中输入安装命令:/install docx1
  3. 安装完成后,直接呼叫该 Skill 的名称或使用 /docx1 触发
  4. 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v1.0.0
Initial release of the docx skill for creating, reading, editing, and analyzing Word documents. - Enables creation, editing, and content extraction for .docx files, with clear triggers for when to use the skill. - Provides detailed guidance for generating documents using JavaScript (`docx-js`), including page size, styles, lists, and table best practices. - Includes instructions for converting legacy .doc files and handling tracked changes. - Emphasizes validation and platform compatibility for reliable output. - Specifies key limitations (not for PDFs, spreadsheets, or general coding tasks).
元数据
Slug docx1
版本 1.0.0
许可证 MIT-0
累计安装 0
当前安装数 0
历史版本数 1
常见问题

Docx 是什么?

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... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 29 次。

如何安装 Docx?

在 OpenClaw 或 Claude Code 对话框中运行命令「/install docx1」即可一键安装,无需额外配置。

Docx 是免费的吗?

是的,Docx 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。

Docx 支持哪些平台?

Docx 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。

谁开发了 Docx?

由 yangxiaoqiang1992(@yangxiaoqiang1992)开发并维护,当前版本 v1.0.0。

💬 留言讨论