docx
npx skills add https://github.com/lingxling/awesome-skills-cn --skill docx
Agent 安装分布
Skill 文档
DOCX å建ãç¼è¾ååæ
æ¦è¿°
.docxæä»¶æ¯ä¸ä¸ªå å«XMLæä»¶çZIPåæ¡£ã
å¿«éåè
| ä»»å¡ | æ¹æ³ |
|---|---|
| 读å/åæå 容 | pandocæè§£å
以è·ååå§XML |
| åå»ºæ°ææ¡£ | 使ç¨docx-js – è§ä¸æåå»ºæ°ææ¡£ |
| ç¼è¾ç°æææ¡£ | è§£å â ç¼è¾XML â éæ°æå – è§ä¸æç¼è¾ç°æææ¡£ |
å°.doc转æ¢ä¸º.docx
ç¼è¾ä¹åå¿
é¡»è½¬æ¢æ§ç.docæä»¶ï¼
python scripts/office/soffice.py --headless --convert-to docx document.doc
读åå 容
# å¸¦ä¿®è®¢çææ¬æå
pandoc --track-changes=all document.docx -o output.md
# åå§XML访é®
python scripts/office/unpack.py document.docx unpacked/
转æ¢ä¸ºå¾å
python scripts/office/soffice.py --headless --convert-to pdf document.docx
pdftoppm -jpeg -r 150 document.pdf page
æ¥å修订
è¦çæä¸ä¸ªæ¥åææä¿®è®¢ç干忿¡£ï¼éè¦LibreOfficeï¼ï¼
python scripts/accept_changes.py input.docx output.docx
åå»ºæ°ææ¡£
使ç¨JavaScriptçæ.docxæä»¶ï¼ç¶åéªè¯ãå®è£
ï¼npm install -g docx
设置
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun,
Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink,
TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType,
VerticalAlign, PageNumber, PageBreak } = require('docx');
const doc = new Document({ sections: [{ children: [/* å
容 */] }] });
Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer));
éªè¯
å建æä»¶åï¼éªè¯å®ã妿éªè¯å¤±è´¥ï¼è§£å ï¼ä¿®å¤XMLï¼ç¶åéæ°æå ã
python scripts/office/validate.py doc.docx
页é¢å¤§å°
// å
³é®ï¼docx-jsé»è®¤ä¸ºA4ï¼ä¸æ¯US Letter
// å§ç»æ¾å¼è®¾ç½®é¡µé¢å¤§å°ä»¥è·å¾ä¸è´çç»æ
sections: [{
properties: {
page: {
size: {
width: 12240, // 8.5è±å¯¸ï¼DXAåä½
height: 15840 // 11è±å¯¸ï¼DXAåä½
},
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } // 1è±å¯¸è¾¹è·
}
},
children: [/* å
容 */]
}]
常è§é¡µé¢å¤§å°ï¼DXAåä½ï¼1440 DXA = 1è±å¯¸ï¼ï¼
| çº¸å¼ | 宽度 | é«åº¦ | å 容宽度ï¼1″è¾¹è·ï¼ |
|---|---|---|---|
| US Letter | 12,240 | 15,840 | 9,360 |
| A4ï¼é»è®¤ï¼ | 11,906 | 16,838 | 9,026 |
æ¨ªåæ¹åï¼docx-jså¨å é¨äº¤æ¢å®½åº¦/é«åº¦ï¼å æ¤ä¼ é纵å尺寸并让å®å¤ç交æ¢ï¼
size: {
width: 12240, // å°çè¾¹ä½ä¸ºå®½åº¦ä¼ é
height: 15840, // å°é¿è¾¹ä½ä¸ºé«åº¦ä¼ é
orientation: PageOrientation.LANDSCAPE // docx-jså¨XMLä¸äº¤æ¢å®ä»¬
},
// å
容宽度 = 15840 - å·¦è¾¹è· - å³è¾¹è·ï¼ä½¿ç¨é¿è¾¹ï¼
æ ·å¼ï¼è¦çå ç½®æ é¢ï¼
使ç¨Arialä½ä¸ºé»è®¤åä½ï¼éç¨æ¯æï¼ãä¿ææ é¢ä¸ºé»è²ä»¥æé«å¯è¯»æ§ã
const doc = new Document({
styles: {
default: { document: { run: { font: "Arial", size: 24 } } }, // 12pté»è®¤
paragraphStyles: [
// éè¦ï¼ä½¿ç¨ç²¾ç¡®IDè¦çå
ç½®æ ·å¼
{ id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true,
run: { size: 32, bold: true, font: "Arial" },
paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } }, // outlineLevelæ¯ç®å½æéç
{ id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true,
run: { size: 28, bold: true, font: "Arial" },
paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } },
]
},
sections: [{
children: [
new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("æ é¢")] }),
]
}]
});
å表ï¼ç»ä¸ä½¿ç¨unicode项ç®ç¬¦å·ï¼
// â é误 - æ°¸è¿ä¸è¦æå¨æå
¥é¡¹ç®ç¬¦å·å符
new Paragraph({ children: [new TextRun("⢠项ç®")] }) // å
new Paragraph({ children: [new TextRun("\u2022 项ç®")] }) // å
// â
æ£ç¡® - 使ç¨å¸¦æLevelFormat.BULLETçç¼å·é
ç½®
const doc = new Document({
numbering: {
config: [
{ reference: "bullets",
levels: [{ level: 0, format: LevelFormat.BULLET, text: "â¢", alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
{ reference: "numbers",
levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
]
},
sections: [{
children: [
new Paragraph({ numbering: { reference: "bullets", level: 0 },
children: [new TextRun("项ç®ç¬¦å·é¡¹")] }),
new Paragraph({ numbering: { reference: "numbers", level: 0 },
children: [new TextRun("ç¼å·é¡¹")] }),
]
}]
});
// â ï¸ æ¯ä¸ªreferenceå建ç¬ç«çç¼å·
// ç¸åreference = ç»§ç»ï¼1,2,3ç¶å4,5,6ï¼
// ä¸åreference = éæ°å¼å§ï¼1,2,3ç¶å1,2,3ï¼
è¡¨æ ¼
å
³é®ï¼è¡¨æ ¼éè¦åé宽度 – å¨è¡¨æ ¼ä¸è®¾ç½®columnWidthsï¼å¨æ¯ä¸ªåå
æ ¼ä¸è®¾ç½®widthãæ²¡æä¸¤è
ï¼è¡¨æ ¼å¨æäºå¹³å°ä¸æ¸²æä¸æ£ç¡®ã
// å
³é®ï¼å§ç»è®¾ç½®è¡¨æ ¼å®½åº¦ä»¥è·å¾ä¸è´ç渲æ
// å
³é®ï¼ä½¿ç¨ShadingType.CLEARï¼ä¸æ¯SOLIDï¼ä»¥é²æ¢é»è²èæ¯
const border = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" };
const borders = { top: border, bottom: border, left: border, right: border };
new Table({
width: { size: 9360, type: WidthType.DXA }, // å§ç»ä½¿ç¨DXAï¼ç¾åæ¯å¨Google Docsä¸ä¸æï¼
columnWidths: [4680, 4680], // å¿
é¡»æ»åä¸ºè¡¨æ ¼å®½åº¦ï¼DXAï¼1440 = 1è±å¯¸ï¼
rows: [
new TableRow({
children: [
new TableCell({
borders,
width: { size: 4680, type: WidthType.DXA }, // ä¹å¨æ¯ä¸ªåå
æ ¼ä¸è®¾ç½®
shading: { fill: "D5E8F0", type: ShadingType.CLEAR }, // CLEAR䏿¯SOLID
margins: { top: 80, bottom: 80, left: 120, right: 120 }, // åå
æ ¼å
è¾¹è·ï¼å
é¨ï¼ä¸æ·»å å°å®½åº¦ï¼
children: [new Paragraph({ children: [new TextRun("åå
æ ¼")] })]
})
]
})
]
})
è¡¨æ ¼å®½åº¦è®¡ç®ï¼
å§ç»ä½¿ç¨WidthType.DXA â WidthType.PERCENTAGEå¨Google Docsä¸ä¸æã
// è¡¨æ ¼å®½åº¦ = columnWidthsçæ»å = å
容宽度
// US Letter带æ1"è¾¹è·ï¼12240 - 2880 = 9360 DXA
width: { size: 9360, type: WidthType.DXA },
columnWidths: [7000, 2360] // å¿
é¡»æ»åä¸ºè¡¨æ ¼å®½åº¦
宽度è§åï¼
- å§ç»ä½¿ç¨
WidthType.DXAâ æ°¸è¿ä¸è¦WidthType.PERCENTAGEï¼ä¸Google Docsä¸å ¼å®¹ï¼ - è¡¨æ ¼å®½åº¦å¿
é¡»çäº
columnWidthsçæ»å - åå
æ ¼
widthå¿ é¡»å¹é ç¸åºçcolumnWidth - åå
æ ¼
marginsæ¯å é¨å è¾¹è· – å®ä»¬åå°å 容åºåï¼è䏿¯æ·»å å°åå æ ¼å®½åº¦ - 对äºå ¨å®½è¡¨æ ¼ï¼ä½¿ç¨å 容宽度ï¼é¡µé¢å®½åº¦åå»å·¦å³è¾¹è·ï¼
å¾å
// å
³é®ï¼typeåæ°æ¯å¿
éç
new Paragraph({
children: [new ImageRun({
type: "png", // å¿
éï¼png, jpg, jpeg, gif, bmp, svg
data: fs.readFileSync("image.png"),
transformation: { width: 200, height: 150 },
altText: { title: "æ é¢", description: "æè¿°", name: "åç§°" } // ææä¸ä¸ªé½æ¯å¿
éç
})]
})
å页符
// å
³é®ï¼PageBreakå¿
é¡»å¨Paragraphå
é¨
new Paragraph({ children: [new PageBreak()] })
// æä½¿ç¨pageBreakBefore
new Paragraph({ pageBreakBefore: true, children: [new TextRun("æ°é¡µé¢")] })
ç®å½
// å
³é®ï¼æ é¢å¿
é¡»ä»
使ç¨HeadingLevel - 没æèªå®ä¹æ ·å¼
new TableOfContents("ç®å½", { hyperlink: true, headingStyleRange: "1-3" })
页ç/页è
sections: [{
properties: {
page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } } // 1440 = 1è±å¯¸
},
headers: {
default: new Header({ children: [new Paragraph({ children: [new TextRun("页ç")] })] })
},
footers: {
default: new Footer({ children: [new Paragraph({
children: [new TextRun("页ç "), new TextRun({ children: [PageNumber.CURRENT] })]
})] })
},
children: [/* å
容 */]
}]
docx-jsçå ³é®è§å
- æ¾å¼è®¾ç½®é¡µé¢å¤§å° – docx-jsé»è®¤ä¸ºA4ï¼å¯¹äºUSææ¡£ä½¿ç¨US Letterï¼12240 x 15840 DXAï¼
- 横åï¼ä¼ é纵å尺寸 – docx-jså¨å
é¨äº¤æ¢å®½åº¦/é«åº¦ï¼å°çè¾¹ä½ä¸º
widthä¼ éï¼é¿è¾¹ä½ä¸ºheightä¼ éï¼å¹¶è®¾ç½®orientation: PageOrientation.LANDSCAPE - ç»ä¸ä½¿ç¨
\n– 使ç¨åç¬çParagraphå ç´ - ç»ä¸ä½¿ç¨unicode项ç®ç¬¦å· – 使ç¨å¸¦æç¼å·é
ç½®ç
LevelFormat.BULLET - PageBreakå¿ é¡»å¨Paragraphä¸ – ç¬ç«åå»ºæ æXML
- ImageRunéè¦
type– å§ç»æå®png/jpgç - å§ç»ä½¿ç¨DXAè®¾ç½®è¡¨æ ¼
width– æ°¸è¿ä¸è¦ä½¿ç¨WidthType.PERCENTAGEï¼å¨Google Docsä¸ä¸æï¼ - è¡¨æ ¼éè¦åé宽度 –
columnWidthsæ°ç»ååå æ ¼widthï¼ä¸¤è å¿ é¡»å¹é - è¡¨æ ¼å®½åº¦ = columnWidthsçæ»å – 对äºDXAï¼ç¡®ä¿å®ä»¬å®å ¨ç¸å
- å§ç»æ·»å åå
æ ¼è¾¹è· – 使ç¨
margins: { top: 80, bottom: 80, left: 120, right: 120 }以è·å¾å¯è¯»çå è¾¹è· - 使ç¨
ShadingType.CLEAR– æ°¸è¿ä¸è¦SOLIDç¨äºè¡¨æ ¼çè² - TOCä» éè¦HeadingLevel – æ 颿®µè½ä¸æ²¡æèªå®ä¹æ ·å¼
- è¦çå ç½®æ ·å¼ – 使ç¨ç²¾ç¡®IDï¼”Heading1″ã”Heading2″ç
- å
å«
outlineLevel– ç®å½æéï¼H1为0ï¼H2为1çï¼
ç¼è¾ç°æææ¡£
æé¡ºåºéµå¾ªææ3个æ¥éª¤ã
æ¥éª¤1ï¼è§£å
python scripts/office/unpack.py document.docx unpacked/
æåXMLï¼ç¾åæå°ï¼åå¹¶ç¸é»çè¿è¡ï¼å¹¶å°æºè½å¼å·è½¬æ¢ä¸ºXMLå®ä½ï¼“çï¼ï¼ä»¥ä¾¿å®ä»¬å¨ç¼è¾ä¸å¹¸åã使ç¨--merge-runs falseè·³è¿è¿è¡åå¹¶ã
æ¥éª¤2ï¼ç¼è¾XML
ç¼è¾unpacked/word/ä¸çæä»¶ãè§ä¸æXMLåè以è·å模å¼ã
使稔Claude”ä½ä¸ºä½è è¿è¡ä¿®è®¢åæ¹æ³¨ï¼é¤éç¨æ·æç¡®è¦æ±ä½¿ç¨ä¸åçåç§°ã
**ç´æ¥ä½¿ç¨Editå·¥å ·è¿è¡åç¬¦ä¸²æ¿æ¢ãä¸è¦ç¼åPythonèæ¬ã**èæ¬å¼å ¥ä¸å¿ è¦ç夿æ§ãEditå·¥å ·ç¡®åæ¾ç¤ºæ£å¨æ¿æ¢çå 容ã
**å ³é®ï¼å¯¹æ°å å®¹ä½¿ç¨æºè½å¼å·ã**彿·»å 带ææå·æå¼å·çææ¬æ¶ï¼ä½¿ç¨XMLå®ä½çææºè½å¼å·ï¼
<!-- 使ç¨è¿äºå®ä½ä»¥è·å¾ä¸ä¸çæç -->
<w:t>Here’s a quote: “Hello”</w:t>
| å®ä½ | å符 |
|---|---|
‘ |
‘ï¼å·¦åå¼å·ï¼ |
’ |
‘ï¼å³åå¼å·/æå·ï¼ |
“ |
“ï¼å·¦åå¼å·ï¼ |
” |
“ï¼å³åå¼å·ï¼ |
**æ·»å æ¹æ³¨ï¼**使ç¨comment.pyå¤çå¤ä¸ªXMLæä»¶çæ ·æ¿ï¼ææ¬å¿
é¡»æ¯é¢è½¬ä¹çXMLï¼ï¼
python scripts/comment.py unpacked/ 0 "带æ&å’çæ¹æ³¨ææ¬"
python scripts/comment.py unpacked/ 1 "å夿æ¬" --parent 0 # å夿¹æ³¨0
python scripts/comment.py unpacked/ 0 "ææ¬" --author "èªå®ä¹ä½è
" # èªå®ä¹ä½è
åç§°
ç¶åå°æ è®°æ·»å å°document.xmlï¼è§XMLåèä¸çæ¹æ³¨ï¼ã
æ¥éª¤3ï¼æå
python scripts/office/pack.py unpacked/ output.docx --original document.docx
使ç¨èªå¨ä¿®å¤è¿è¡éªè¯ï¼å缩XMLï¼å¹¶å建DOCXã使ç¨--validate falseè·³è¿ã
èªå¨ä¿®å¤å°ä¿®å¤ï¼
durableId>= 0x7FFFFFFFï¼éæ°çæææIDï¼<w:t>ä¸ç¼ºå°xml:space="preserve"ï¼å¸¦æç©ºç½
èªå¨ä¿®å¤ä¸ä¼ä¿®å¤ï¼
- æ ¼å¼é误çXMLãæ æçå ç´ åµå¥ã缺å°çå ³ç³»ãæ¨¡å¼è¿è§
常è§é·é±
- æ¿æ¢æ´ä¸ª
<w:r>å ç´ ï¼æ·»å 修订æ¶ï¼ç¨<w:del>...<w:ins>...ä½ä¸ºå 弿¿æ¢æ´ä¸ª<w:r>...</w:r>åãä¸è¦å¨è¿è¡ä¸æ³¨å ¥ä¿®è®¢æ è®°ã - ä¿ç
<w:rPr>æ ¼å¼åï¼å°åå§è¿è¡ç<w:rPr>åå¤å¶å°ä¿®è®¢è¿è¡ä¸ä»¥ä¿æç²ä½ãåä½å¤§å°çã
XMLåè
模å¼åè§æ§
<w:pPr>ä¸çå ç´ é¡ºåºï¼<w:pStyle>ã<w:numPr>ã<w:spacing>ã<w:ind>ã<w:jc>ã<w:rPr>æå- 空ç½ï¼å°
xml:space="preserve"æ·»å å°å¸¦æå导/å°¾é空ç½ç<w:t> - RSIDsï¼å¿
é¡»æ¯8ä½åå
è¿å¶ï¼ä¾å¦ï¼
00AB1234ï¼
修订
æå ¥ï¼
<w:ins w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
<w:r><w:t>æå
¥çææ¬</w:t></w:r>
</w:ins>
å é¤ï¼
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
<w:r><w:delText>å é¤çææ¬</w:delText></w:r>
</w:del>
å¨<w:del>å
é¨ï¼ä½¿ç¨<w:delText>è䏿¯<w:t>ï¼å¹¶ä½¿ç¨<w:delInstrText>è䏿¯<w:instrText>ã
æå°ç¼è¾ – ä» æ è®°æ´æ¹çå 容ï¼
<!-- å°"30天"æ´æ¹ä¸º"60天" -->
<w:r><w:t>æéæ¯ </w:t></w:r>
<w:del w:id="1" w:author="Claude" w:date="...">
<w:r><w:delText>30</w:delText></w:r>
</w:del>
<w:ins w:id="2" w:author="Claude" w:date="...">
<w:r><w:t>60</w:t></w:r>
</w:ins>
<w:r><w:t> 天ã</w:t></w:r>
å 餿´ä¸ªæ®µè½/å表项 – 仿®µè½ä¸å 餿æå
容æ¶ï¼ä¹å°æ®µè½æ è®°æ 记为已å é¤ï¼ä»¥ä¾¿å®ä¸ä¸ä¸æ®µè½åå¹¶ãå¨<w:pPr><w:rPr>å
æ·»å <w:del/>ï¼
<w:p>
<w:pPr>
<w:numPr>...</w:numPr> <!-- å表ç¼å·ï¼å¦æåå¨ï¼ -->
<w:rPr>
<w:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z"/>
</w:rPr>
</w:pPr>
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
<w:r><w:delText>æ£å¨å é¤çæ´ä¸ªæ®µè½å
容...</w:delText></w:r>
</w:del>
</w:p>
å¦ææ²¡æ<w:pPr><w:rPr>ä¸ç<w:del/>ï¼æ¥åæ´æ¹ä¼çä¸ä¸ä¸ªç©ºæ®µè½/å表项ã
æç»å¦ä¸ä¸ªä½è çæå ¥ – å¨ä»ä»¬çæå ¥å åµå¥å é¤ï¼
<w:ins w:author="Jane" w:id="5">
<w:del w:author="Claude" w:id="10">
<w:r><w:delText>ä»ä»¬æå
¥çææ¬</w:delText></w:r>
</w:del>
</w:ins>
æ¢å¤å¦ä¸ä¸ªä½è çå é¤ – å¨å é¤åæ·»å æå ¥ï¼ä¸è¦ä¿®æ¹ä»ä»¬çå é¤ï¼ï¼
<w:del w:author="Jane" w:id="5">
<w:r><w:delText>å é¤çææ¬</w:delText></w:r>
</w:del>
<w:ins w:author="Claude" w:id="10">
<w:r><w:t>å é¤çææ¬</w:t></w:r>
</w:ins>
æ¹æ³¨
è¿è¡comment.pyåï¼è§æ¥éª¤2ï¼ï¼å°æ è®°æ·»å å°document.xmlã对äºåå¤ï¼ä½¿ç¨--parentæ å¿å¹¶å°æ è®°åµå¥å¨ç¶æ è®°å
ã
å
³é®ï¼<w:commentRangeStart>å<w:commentRangeEnd>æ¯<w:r>çå
å¼ï¼æ°¸è¿ä¸å¨<w:r>å
é¨ã
<!-- æ¹æ³¨æ è®°æ¯w:pçç´æ¥åå
ç´ ï¼æ°¸è¿ä¸å¨w:rå
é¨ -->
<w:commentRangeStart w:id="0"/>
<w:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
<w:r><w:delText>å·²å é¤</w:delText></w:r>
</w:del>
<w:r><w:t> æ´å¤ææ¬</w:t></w:r>
<w:commentRangeEnd w:id="0"/>
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="0"/></w:r>
<!-- æ¹æ³¨0ï¼å
¶ä¸åµå¥äºåå¤1 -->
<w:commentRangeStart w:id="0"/>
<w:commentRangeStart w:id="1"/>
<w:r><w:t>ææ¬</w:t></w:r>
<w:commentRangeEnd w:id="1"/>
<w:commentRangeEnd w:id="0"/>
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="0"/></w:r>
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="1"/></w:r>
å¾å
- å°å¾åæä»¶æ·»å å°
word/media/ - å°å
³ç³»æ·»å å°
word/_rels/document.xml.relsï¼
<Relationship Id="rId5" Type=".../image" Target="media/image1.png"/>
- å°å
å®¹ç±»åæ·»å å°
[Content_Types].xmlï¼
<Default Extension="png" ContentType="image/png"/>
- å¨document.xmlä¸å¼ç¨ï¼
<w:drawing>
<wp:inline>
<wp:extent cx="914400" cy="914400"/> <!-- EMUï¼914400 = 1è±å¯¸ -->
<a:graphic>
<a:graphicData uri=".../picture">
<pic:pic>
<pic:blipFill><a:blip r:embed="rId5"/></pic:blipFill>
</pic:pic>
</a:graphicData>
</a:graphic>
</wp:inline>
</w:drawing>
ä¾èµé¡¹
- pandocï¼ææ¬æå
- docxï¼
npm install -g docxï¼æ°ææ¡£ï¼ - LibreOfficeï¼PDF转æ¢ï¼éè¿
scripts/office/soffice.py为æ²çç¯å¢èªå¨é ç½®ï¼ - Popplerï¼
pdftoppmç¨äºå¾å