Sync third-party and MCP marketplace plugins

Constraint: Public skills are published only by explicit administrator action unless they are tracked third-party market sources.
Confidence: high
Scope-risk: narrow
Directive: Keep private/internal skills out of the public marketplace and preserve normal incremental market Git history.
Tested: Marketplace validation passed.
This commit is contained in:
KeyInfo Bot committed 2026-10-06 15:29:22 +08:00
1 parent be7ce9bda2
commit 36c089fee9
298 files changed
+32935 -11681

No files matched your search

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="360" height="360" viewBox="0 0 48 48"><title>docx</title><g fill="none"><path fill="url(#SVGEun4xcUP)" d="M11 43h26a3 3 0 0 0 3-3V18l-10-4l-4-10H11a3 3 0 0 0-3 3v33a3 3 0 0 0 3 3"/><path fill="url(#SVGcM4dxcaR)" fill-opacity=".5" d="M11 43h26a3 3 0 0 0 3-3V18l-10-4l-4-10H11a3 3 0 0 0-3 3v33a3 3 0 0 0 3 3"/><path fill="url(#SVGs75ELblf)" d="M26 15V4l14 14H29a3 3 0 0 1-3-3"/><path fill="url(#SVGdS9JudtG)" fill-opacity=".9" d="M16.25 23a1.25 1.25 0 1 0 0 2.5h15.5a1.25 1.25 0 1 0 0-2.5zM15 30.25c0-.69.56-1.25 1.25-1.25h15.5a1.25 1.25 0 1 1 0 2.5h-15.5c-.69 0-1.25-.56-1.25-1.25M16.25 35a1.25 1.25 0 1 0 0 2.5h15.5a1.25 1.25 0 1 0 0-2.5z"/><defs><linearGradient id="SVGEun4xcUP" x1="30.4" x2="33.484" y1="4" y2="36.911" gradientUnits="userSpaceOnUse"><stop stop-color="#6ce0ff"/><stop offset="1" stop-color="#4894fe"/></linearGradient><linearGradient id="SVGs75ELblf" x1="32.977" x2="29.477" y1="9.833" y2="15.667" gradientUnits="userSpaceOnUse"><stop stop-color="#9ff0f9"/><stop offset="1" stop-color="#b3e0ff"/></linearGradient><linearGradient id="SVGdS9JudtG" x1="33" x2="17.47" y1="43.3" y2="15.805" gradientUnits="userSpaceOnUse"><stop stop-color="#9deaff"/><stop offset="1" stop-color="#fff"/></linearGradient><radialGradient id="SVGcM4dxcaR" cx="0" cy="0" r="1" gradientTransform="rotate(134.348 19.568 11.308)scale(24.7968 14.6539)" gradientUnits="userSpaceOnUse"><stop offset=".362" stop-color="#4a43cb"/><stop offset="1" stop-color="#4a43cb" stop-opacity="0"/></radialGradient></defs></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="360" height="360" viewBox="0 0 24 24"><title>find-skills</title><g fill="none"><path fill="url(#SVG5b4mGcbO)" d="M21 19c0 2.5-4.03 4-9 4s-9-1.5-9-4c0-2.406 4.03-4 9-4s9 1.5 9 4"/><path fill="url(#SVGfOKLrdNQ)" d="M12 2a7.5 7.5 0 0 0-7.5 7.5c0 1.932 1.064 3.8 2.268 5.316c1.22 1.537 2.678 2.829 3.655 3.622c.926.75 2.228.75 3.154 0c.977-.793 2.435-2.085 3.655-3.622C18.436 13.301 19.5 11.432 19.5 9.5A7.5 7.5 0 0 0 12 2"/><path fill="url(#SVGOpCNSdas)" d="M14.5 9.5a2.5 2.5 0 1 1-5 0a2.5 2.5 0 0 1 5 0"/><defs><linearGradient id="SVGfOKLrdNQ" x1="1.219" x2="13.202" y1="-2.857" y2="16.549" gradientUnits="userSpaceOnUse"><stop stop-color="#f97dbd"/><stop offset="1" stop-color="#d7257d"/></linearGradient><linearGradient id="SVGOpCNSdas" x1="9.79" x2="12.394" y1="9.721" y2="12.428" gradientUnits="userSpaceOnUse"><stop stop-color="#fdfdfd"/><stop offset="1" stop-color="#fecbe6"/></linearGradient><radialGradient id="SVG5b4mGcbO" cx="0" cy="0" r="1" gradientTransform="rotate(-10.678 100.2 -51.93)scale(14.3921 6.38107)" gradientUnits="userSpaceOnUse"><stop stop-color="#7b7bff"/><stop offset=".502" stop-color="#a3a3ff"/><stop offset="1" stop-color="#ceb0ff"/></radialGradient></defs></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="360" height="360" viewBox="0 0 32 32"><title>pdf</title><g fill="none"><path fill="url(#SVGbYeP8enY)" d="M8.5 4A3.5 3.5 0 0 0 5 7.5v19A3.5 3.5 0 0 0 8.5 30h8.974c.146-.328.353-.634.621-.903l8.505-8.505a3 3 0 0 1 .4-.336V7.5A3.5 3.5 0 0 0 23.5 4z"/><path fill="url(#SVGjpE8fcaQ)" fill-opacity=".9" d="M10 13a1 1 0 0 1 1-1h10a1 1 0 1 1 0 2H11a1 1 0 0 1-1-1"/><path fill="url(#SVGjpE8fcaQ)" fill-opacity=".9" d="M10 18a1 1 0 0 1 1-1h5a1 1 0 1 1 0 2h-5a1 1 0 0 1-1-1"/><path fill="url(#SVGjpE8fcaQ)" fill-opacity=".9" d="M11 22a1 1 0 1 0 0 2h10a1 1 0 1 0 0-2z"/><path fill="url(#SVG8Zdw7rWn)" fill-opacity=".4" d="M8.5 4A3.5 3.5 0 0 0 5 7.5v19A3.5 3.5 0 0 0 8.5 30h8.974c.146-.328.353-.634.621-.903l8.505-8.505a3 3 0 0 1 .4-.336V7.5A3.5 3.5 0 0 0 23.5 4z"/><path fill="url(#SVGYPBejbdj)" fill-opacity=".4" d="M8.5 4A3.5 3.5 0 0 0 5 7.5v19A3.5 3.5 0 0 0 8.5 30h8.974c.146-.328.353-.634.621-.903l8.505-8.505a3 3 0 0 1 .4-.336V7.5A3.5 3.5 0 0 0 23.5 4z"/><path fill="url(#SVGTGP5Fd9u)" fill-opacity=".4" d="M8.5 4A3.5 3.5 0 0 0 5 7.5v19A3.5 3.5 0 0 0 8.5 30h8.974c.146-.328.353-.634.621-.903l8.505-8.505a3 3 0 0 1 .4-.336V7.5A3.5 3.5 0 0 0 23.5 4z"/><path fill="url(#SVGKHVETdmG)" d="M10 5a3 3 0 0 1 3-3h6a3 3 0 1 1 0 6h-6a3 3 0 0 1-3-3"/><path fill="url(#SVG2Rqg1dqL)" d="m20.539 29.469l7.61-7.543l-4.073-4.074l-7.567 7.64l.308 3.695z"/><path fill="url(#SVGTaD2n6OC)" d="m26.937 23.14l2.211-2.214a2.88 2.88 0 0 0 .072-4.017a2.88 2.88 0 0 0-4.144-.057l-2.238 2.241z"/><path fill="url(#SVGBGLG8drx)" d="M24.094 17.838a5.43 5.43 0 0 0 4.106 4.038l-1.55 1.551a5.43 5.43 0 0 1-4.106-4.04z"/><path fill="url(#SVGxKDc0jMv)" d="m20.539 29.47l.223-.223s-1.726-.661-2.535-1.47c-.809-.81-1.47-2.534-1.47-2.534l-.248.249a2.66 2.66 0 0 0-.686 1.206l-.79 3.051a1 1 0 0 0 1.217 1.22l3.02-.778a2.8 2.8 0 0 0 1.269-.722"/><defs><linearGradient id="SVGbYeP8enY" x1="5" x2="25.632" y1="6.6" y2="31.15" gradientUnits="userSpaceOnUse"><stop stop-color="#36dff1"/><stop offset="1" stop-color="#0094f0"/></linearGradient><linearGradient id="SVGjpE8fcaQ" x1="17.5" x2="8.622" y1="24" y2="13.125" gradientUnits="userSpaceOnUse"><stop stop-color="#9deaff"/><stop offset="1" stop-color="#fff"/></linearGradient><linearGradient id="SVGKHVETdmG" x1="16" x2="16" y1="2" y2="8" gradientUnits="userSpaceOnUse"><stop stop-color="#ffe06b"/><stop offset="1" stop-color="#fab500"/></linearGradient><linearGradient id="SVG2Rqg1dqL" x1="19.861" x2="26.044" y1="19.948" y2="26.149" gradientUnits="userSpaceOnUse"><stop stop-color="#ffa43d"/><stop offset="1" stop-color="#fb5937"/></linearGradient><linearGradient id="SVGTaD2n6OC" x1="28.502" x2="25.869" y1="17.485" y2="19.969" gradientUnits="userSpaceOnUse"><stop stop-color="#f97dbd"/><stop offset="1" stop-color="#dd3ce2"/></linearGradient><linearGradient id="SVGBGLG8drx" x1="25.469" x2="21.489" y1="21.664" y2="19.902" gradientUnits="userSpaceOnUse"><stop stop-color="#ff921f"/><stop offset="1" stop-color="#ffe994"/></linearGradient><linearGradient id="SVGxKDc0jMv" x1="14.174" x2="18.325" y1="26.847" y2="30.975" gradientUnits="userSpaceOnUse"><stop offset=".255" stop-color="#ffd394"/><stop offset="1" stop-color="#ff921f"/></linearGradient><radialGradient id="SVG8Zdw7rWn" cx="0" cy="0" r="1" gradientTransform="matrix(8.9375 0 0 7.86963 16 2.556)" gradientUnits="userSpaceOnUse"><stop stop-color="#0a1852"/><stop offset="1" stop-color="#0a1852" stop-opacity="0"/></radialGradient><radialGradient id="SVGYPBejbdj" cx="0" cy="0" r="1" gradientTransform="matrix(8.9375 0 0 8.87743 16 2.556)" gradientUnits="userSpaceOnUse"><stop stop-color="#0a1852"/><stop offset="1" stop-color="#0a1852" stop-opacity="0"/></radialGradient><radialGradient id="SVGTGP5Fd9u" cx="0" cy="0" r="1" gradientTransform="rotate(135.565 7.13 16.2)scale(14.4424 6.48727)" gradientUnits="userSpaceOnUse"><stop stop-color="#0a1852"/><stop offset="1" stop-color="#0a1852" stop-opacity="0"/></radialGradient></defs></g></svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="360" height="360" viewBox="0 0 24 24"><title>pptx</title><g fill="none"><path fill="url(#SVGdFie5cDw)" d="M8 6.25A2.25 2.25 0 0 1 10.25 4h7.5A2.25 2.25 0 0 1 20 6.25v8.5A2.25 2.25 0 0 1 17.75 17h-7.5A2.25 2.25 0 0 1 8 14.75z"/><path fill="url(#SVGXYfMve6h)" d="M8 6.25A2.25 2.25 0 0 1 10.25 4h7.5A2.25 2.25 0 0 1 20 6.25v8.5A2.25 2.25 0 0 1 17.75 17h-7.5A2.25 2.25 0 0 1 8 14.75z"/><path fill="url(#SVGCfFQgeqH)" d="M4 4.25A2.25 2.25 0 0 1 6.25 2h9a2.25 2.25 0 0 1 2.25 2.25v10.5A2.25 2.25 0 0 1 15.25 17h-9A2.25 2.25 0 0 1 4 14.75z"/><path fill="url(#SVGBFc5OckO)" d="M5.25 8A2.25 2.25 0 0 0 3 10.25v8.5A3.25 3.25 0 0 0 6.25 22h11.5A3.25 3.25 0 0 0 21 18.75v-1.5A2.25 2.25 0 0 0 18.75 15h-2.846a.75.75 0 0 1-.55-.24l-5.61-6.04A2.25 2.25 0 0 0 8.097 8z"/><defs><linearGradient id="SVGdFie5cDw" x1="21.8" x2="23.639" y1="19.5" y2="5.773" gradientUnits="userSpaceOnUse"><stop stop-color="#bb45ea"/><stop offset="1" stop-color="#9c6cfe"/></linearGradient><linearGradient id="SVGXYfMve6h" x1="20" x2="17" y1="8.5" y2="8.5" gradientUnits="userSpaceOnUse"><stop offset=".338" stop-color="#5750e2" stop-opacity="0"/><stop offset="1" stop-color="#5750e2"/></linearGradient><linearGradient id="SVGBFc5OckO" x1="6.857" x2="6.857" y1="8" y2="27.091" gradientUnits="userSpaceOnUse"><stop offset=".241" stop-color="#ffd638"/><stop offset=".637" stop-color="#fab500"/><stop offset=".985" stop-color="#ca6407"/></linearGradient><radialGradient id="SVGCfFQgeqH" cx="0" cy="0" r="1" gradientTransform="matrix(8.775 -11.5 18.53666 14.14428 8.05 14)" gradientUnits="userSpaceOnUse"><stop offset=".228" stop-color="#2764e7"/><stop offset=".685" stop-color="#5cd1ff"/><stop offset="1" stop-color="#6ce0ff"/></radialGradient></defs></g></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="360" height="360" viewBox="0 0 48 48"><title>xlsx</title><g fill="none"><rect width="36" height="36" x="6" y="6" fill="url(#SVG1iPhScTz)" rx="8.5"/><path fill="url(#SVGM1bApbhK)" d="M12.25 6A6.25 6.25 0 0 0 6 12.25v4.25h10.5V6zM19 6v10.5h10V6zm-2.5 13H6v10h10.5zM19 29V19h10v10zm-2.5 2.5H6v4.25A6.25 6.25 0 0 0 12.25 42h4.25zM19 42h10V31.5H19zm12.5 0V31.5H42v4.25A6.25 6.25 0 0 1 35.75 42zM42 19v10H31.5V19zm0-2.5v-4.25A6.25 6.25 0 0 0 35.75 6H31.5v10.5z"/><defs><linearGradient id="SVG1iPhScTz" x1="8.571" x2="39.429" y1="8.571" y2="39.429" gradientUnits="userSpaceOnUse"><stop stop-color="#b0f098"/><stop offset="1" stop-color="#98f0b0"/></linearGradient><linearGradient id="SVGM1bApbhK" x1="6" x2="42" y1="6" y2="42" gradientUnits="userSpaceOnUse"><stop stop-color="#42b870"/><stop offset="1" stop-color="#1a7f7c"/></linearGradient></defs></g></svg>

After

Width:  |  Height:  |  Size: 900 B

+439
View File
@@ -1,5 +1,444 @@
{
"sources": [
{
"id": "docx",
"repo": "https://github.com/anthropics/skills.git",
"ref": "main",
"adapter": "claude-skill",
"pluginName": "docx",
"category": "Productivity",
"skillPath": "skills/docx",
"sparseCheckout": [
"skills/docx"
],
"materializePaths": [
{
"source": "skills/docx/SKILL.md",
"destination": "upstream-guide.md"
}
],
"marketAssets": [
{
"source": "config/skill-overrides/docx/SKILL.md",
"destination": "skills/docx/SKILL.md"
},
{
"source": "config/skill-overrides/common/platform.md",
"destination": "skills/docx/references/platform.md"
},
{
"source": "config/assets/docx.svg",
"destination": "assets/market-icon.svg"
},
{
"source": "config/skill-overrides/common/soffice.py",
"destination": "skills/docx/scripts/office/soffice.py"
},
{
"source": "config/skill-overrides/common/render_pdf.py",
"destination": "skills/docx/scripts/render_pdf.py"
},
{
"source": "config/skill-overrides/common/office_package.py",
"destination": "skills/docx/scripts/office_package.py"
},
{
"source": "config/skill-overrides/docx/accept_changes.py",
"destination": "skills/docx/scripts/accept_changes.py"
}
],
"manifestOverrides": {
"version": "2.0.0",
"description": "创建、读取和编辑 Word 文档,适配简体中文排版与 Windows。",
"author": {
"name": "Anthropic; EAPIL localization",
"url": "https://github.com/anthropics"
},
"license": "Proprietary",
"keywords": [
"docx",
"documents",
"zh-CN",
"windows"
],
"interface": {
"displayName": "docx",
"shortDescription": "创建、读取和编辑 Word 文档,适配简体中文排版与 Windows。",
"longDescription": "创建、读取和编辑 Word 文档,适配简体中文排版与 Windows。 包含最新上游工具及简体中文入口、PowerShell 指引和跨平台辅助脚本。依赖需按任务检查并安装。",
"developerName": "Anthropic; EAPIL",
"category": "Productivity",
"defaultPrompt": [
"使用 docx 处理这份中文文档,并检查最终输出。"
],
"logo": "./assets/market-icon.svg",
"composerIcon": "./assets/market-icon.svg"
}
}
},
{
"id": "pdf",
"repo": "https://github.com/anthropics/skills.git",
"ref": "main",
"adapter": "claude-skill",
"pluginName": "pdf",
"category": "Productivity",
"skillPath": "skills/pdf",
"sparseCheckout": [
"skills/pdf"
],
"materializePaths": [
{
"source": "skills/pdf/SKILL.md",
"destination": "upstream-guide.md"
}
],
"marketAssets": [
{
"source": "config/skill-overrides/pdf/SKILL.md",
"destination": "skills/pdf/SKILL.md"
},
{
"source": "config/skill-overrides/common/platform.md",
"destination": "skills/pdf/references/platform.md"
},
{
"source": "config/assets/pdf.svg",
"destination": "assets/market-icon.svg"
},
{
"source": "config/skill-overrides/common/render_pdf.py",
"destination": "skills/pdf/scripts/convert_pdf_to_images.py"
}
],
"manifestOverrides": {
"version": "2.0.0",
"description": "读取、创建和填写 PDF,支持中文字体与免 Poppler 预览。",
"author": {
"name": "Anthropic; EAPIL localization",
"url": "https://github.com/anthropics"
},
"license": "Proprietary",
"keywords": [
"pdf",
"documents",
"zh-CN",
"windows"
],
"interface": {
"displayName": "pdf",
"shortDescription": "读取、创建和填写 PDF,支持中文字体与免 Poppler 预览。",
"longDescription": "读取、创建和填写 PDF,支持中文字体与免 Poppler 预览。 包含最新上游工具及简体中文入口、PowerShell 指引和跨平台辅助脚本。依赖需按任务检查并安装。",
"developerName": "Anthropic; EAPIL",
"category": "Productivity",
"defaultPrompt": [
"使用 pdf 处理这份中文文档,并检查最终输出。"
],
"logo": "./assets/market-icon.svg",
"composerIcon": "./assets/market-icon.svg"
}
}
},
{
"id": "pptx",
"repo": "https://github.com/anthropics/skills.git",
"ref": "main",
"adapter": "claude-skill",
"pluginName": "pptx",
"category": "Productivity",
"skillPath": "skills/pptx",
"sparseCheckout": [
"skills/pptx"
],
"materializePaths": [
{
"source": "skills/pptx/SKILL.md",
"destination": "upstream-guide.md"
}
],
"marketAssets": [
{
"source": "config/skill-overrides/pptx/SKILL.md",
"destination": "skills/pptx/SKILL.md"
},
{
"source": "config/skill-overrides/common/platform.md",
"destination": "skills/pptx/references/platform.md"
},
{
"source": "config/assets/pptx.svg",
"destination": "assets/market-icon.svg"
},
{
"source": "config/skill-overrides/common/soffice.py",
"destination": "skills/pptx/scripts/office/soffice.py"
},
{
"source": "config/skill-overrides/common/render_pdf.py",
"destination": "skills/pptx/scripts/render_pdf.py"
},
{
"source": "config/skill-overrides/common/office_package.py",
"destination": "skills/pptx/scripts/office_package.py"
}
],
"manifestOverrides": {
"version": "2.0.0",
"description": "创建和编辑 PowerPoint,保留模板与图表,适配中文和 Windows。",
"author": {
"name": "Anthropic; EAPIL localization",
"url": "https://github.com/anthropics"
},
"license": "Proprietary",
"keywords": [
"pptx",
"documents",
"zh-CN",
"windows"
],
"interface": {
"displayName": "pptx",
"shortDescription": "创建和编辑 PowerPoint,保留模板与图表,适配中文和 Windows。",
"longDescription": "创建和编辑 PowerPoint,保留模板与图表,适配中文和 Windows。 包含最新上游工具及简体中文入口、PowerShell 指引和跨平台辅助脚本。依赖需按任务检查并安装。",
"developerName": "Anthropic; EAPIL",
"category": "Productivity",
"defaultPrompt": [
"使用 pptx 处理这份中文文档,并检查最终输出。"
],
"logo": "./assets/market-icon.svg",
"composerIcon": "./assets/market-icon.svg"
}
}
},
{
"id": "xlsx",
"repo": "https://github.com/anthropics/skills.git",
"ref": "main",
"adapter": "claude-skill",
"pluginName": "xlsx",
"category": "Productivity",
"skillPath": "skills/xlsx",
"sparseCheckout": [
"skills/xlsx"
],
"materializePaths": [
{
"source": "skills/xlsx/SKILL.md",
"destination": "upstream-guide.md"
}
],
"marketAssets": [
{
"source": "config/skill-overrides/xlsx/SKILL.md",
"destination": "skills/xlsx/SKILL.md"
},
{
"source": "config/skill-overrides/common/platform.md",
"destination": "skills/xlsx/references/platform.md"
},
{
"source": "config/assets/xlsx.svg",
"destination": "assets/market-icon.svg"
},
{
"source": "config/skill-overrides/common/soffice.py",
"destination": "skills/xlsx/scripts/office/soffice.py"
},
{
"source": "config/skill-overrides/common/render_pdf.py",
"destination": "skills/xlsx/scripts/render_pdf.py"
},
{
"source": "config/skill-overrides/common/office_package.py",
"destination": "skills/xlsx/scripts/office_package.py"
},
{
"source": "config/skill-overrides/xlsx/recalc.py",
"destination": "skills/xlsx/scripts/recalc.py"
}
],
"manifestOverrides": {
"version": "2.0.0",
"description": "创建和编辑 Excel,验证公式,适配中文数据与 Windows Excel。",
"author": {
"name": "Anthropic; EAPIL localization",
"url": "https://github.com/anthropics"
},
"license": "Proprietary",
"keywords": [
"xlsx",
"documents",
"zh-CN",
"windows"
],
"interface": {
"displayName": "xlsx",
"shortDescription": "创建和编辑 Excel,验证公式,适配中文数据与 Windows Excel。",
"longDescription": "创建和编辑 Excel,验证公式,适配中文数据与 Windows Excel。 包含最新上游工具及简体中文入口、PowerShell 指引和跨平台辅助脚本。依赖需按任务检查并安装。",
"developerName": "Anthropic; EAPIL",
"category": "Productivity",
"defaultPrompt": [
"使用 xlsx 处理这份中文文档,并检查最终输出。"
],
"logo": "./assets/market-icon.svg",
"composerIcon": "./assets/market-icon.svg"
}
}
},
{
"id": "find-skills",
"repo": "https://github.com/vercel-labs/skills.git",
"ref": "main",
"adapter": "claude-skill",
"pluginName": "find-skills",
"category": "Productivity",
"skillPath": "skills/find-skills",
"sparseCheckout": [
"skills/find-skills",
"LICENSE"
],
"includeRootFiles": [
"LICENSE"
],
"marketAssets": [
{
"source": "config/assets/find-skills.svg",
"destination": "assets/market-icon.svg"
}
],
"skillDescriptions": {
"find-skills": "当用户想查找、选择或安装现成 Agent Skill 时,搜索技能生态并核对来源与适用性。"
},
"manifestOverrides": {
"description": "从 Vercel Skills 生态发现和安装适合任务的 Agent Skills。",
"author": {
"name": "Vercel",
"url": "https://github.com/vercel-labs"
},
"license": "MIT",
"interface": {
"displayName": "find-skills",
"shortDescription": "查找并选择适合任务的 Agent Skills。",
"longDescription": "跟随 vercel-labs/skills 的 find-skills 原始技能,使用 Skills CLI 搜索并核对来源。需要 Node.js 和 npx。",
"developerName": "Vercel",
"category": "Productivity",
"defaultPrompt": [
"使用 find-skills 查找适合当前任务的技能。"
],
"logo": "./assets/market-icon.svg",
"composerIcon": "./assets/market-icon.svg"
}
}
},
{
"id": "generate-agents-md",
"repo": "https://git.playones.com/chenmingxuan/ManySkills.git",
"releaseChannel": "latest-stable",
"releaseProvider": "gitea",
"adapter": "codex-plugin",
"pluginName": "generate-agents-md",
"category": "Developer Tools",
"sourcePath": "plugins/generate-agents-md",
"sparseCheckout": [
"plugins/generate-agents-md"
],
"include": [
".codex-plugin",
"skills",
"assets"
],
"manifestOverrides": {
"repository": "https://git.playones.com/chenmingxuan/ManySkills",
"homepage": "https://git.playones.com/chenmingxuan/ManySkills/src/branch/main/plugins/generate-agents-md"
}
},
{
"id": "design-md",
"repo": "https://git.playones.com/chenmingxuan/ManySkills.git",
"releaseChannel": "latest-stable",
"releaseProvider": "gitea",
"adapter": "codex-plugin",
"pluginName": "design-md",
"category": "Creativity",
"sourcePath": "plugins/design-md",
"sparseCheckout": [
"plugins/design-md"
],
"include": [
".codex-plugin",
"skills",
"assets"
],
"manifestOverrides": {
"repository": "https://git.playones.com/chenmingxuan/ManySkills",
"homepage": "https://git.playones.com/chenmingxuan/ManySkills/src/branch/main/plugins/design-md"
}
},
{
"id": "eapil-llmapi-structured",
"repo": "https://git.playones.com/chenmingxuan/ManySkills.git",
"releaseChannel": "latest-stable",
"releaseProvider": "gitea",
"adapter": "codex-plugin",
"pluginName": "eapil-llmapi-structured",
"category": "Developer Tools",
"sourcePath": "plugins/eapil-llmapi-structured",
"sparseCheckout": [
"plugins/eapil-llmapi-structured"
],
"include": [
".codex-plugin",
"skills",
"assets"
],
"manifestOverrides": {
"repository": "https://git.playones.com/chenmingxuan/ManySkills",
"homepage": "https://git.playones.com/chenmingxuan/ManySkills/src/branch/main/plugins/eapil-llmapi-structured"
}
},
{
"id": "eapil-gpt2-image",
"repo": "https://git.playones.com/chenmingxuan/ManySkills.git",
"releaseChannel": "latest-stable",
"releaseProvider": "gitea",
"adapter": "codex-plugin",
"pluginName": "eapil-gpt2-image",
"category": "Creativity",
"sourcePath": "plugins/eapil-gpt2-image",
"sparseCheckout": [
"plugins/eapil-gpt2-image"
],
"include": [
".codex-plugin",
"skills",
"assets"
],
"manifestOverrides": {
"repository": "https://git.playones.com/chenmingxuan/ManySkills",
"homepage": "https://git.playones.com/chenmingxuan/ManySkills/src/branch/main/plugins/eapil-gpt2-image"
}
},
{
"id": "eapil-voice",
"repo": "https://git.playones.com/chenmingxuan/ManySkills.git",
"releaseChannel": "latest-stable",
"releaseProvider": "gitea",
"adapter": "codex-plugin",
"pluginName": "eapil-voice",
"category": "Creativity",
"sourcePath": "plugins/eapil-voice",
"sparseCheckout": [
"plugins/eapil-voice"
],
"include": [
".codex-plugin",
"skills",
"assets"
],
"manifestOverrides": {
"repository": "https://git.playones.com/chenmingxuan/ManySkills",
"homepage": "https://git.playones.com/chenmingxuan/ManySkills/src/branch/main/plugins/eapil-voice"
}
},
{
"id": "dingtalk-workspace",
"repo": "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli.git",
+96 -6
View File
@@ -1,5 +1,95 @@
{
"sources": [
{
"id": "docx",
"pluginName": "docx",
"repo": "https://github.com/anthropics/skills.git",
"ref": "main",
"adapter": "claude-skill",
"commit": "683bc88e56f3e09ba94f7055977f3d3aa499f202",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "pdf",
"pluginName": "pdf",
"repo": "https://github.com/anthropics/skills.git",
"ref": "main",
"adapter": "claude-skill",
"commit": "683bc88e56f3e09ba94f7055977f3d3aa499f202",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "pptx",
"pluginName": "pptx",
"repo": "https://github.com/anthropics/skills.git",
"ref": "main",
"adapter": "claude-skill",
"commit": "683bc88e56f3e09ba94f7055977f3d3aa499f202",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "xlsx",
"pluginName": "xlsx",
"repo": "https://github.com/anthropics/skills.git",
"ref": "main",
"adapter": "claude-skill",
"commit": "683bc88e56f3e09ba94f7055977f3d3aa499f202",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "find-skills",
"pluginName": "find-skills",
"repo": "https://github.com/vercel-labs/skills.git",
"ref": "main",
"adapter": "claude-skill",
"commit": "14cf84aa922cccc7e5b11fee5af9a01b3750fddf",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "generate-agents-md",
"pluginName": "generate-agents-md",
"repo": "https://git.playones.com/chenmingxuan/ManySkills.git",
"ref": "v1.0.0",
"adapter": "codex-plugin",
"commit": "e869eb169eeb5a7cd9e58c0e514fa2dbbf50987d",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "design-md",
"pluginName": "design-md",
"repo": "https://git.playones.com/chenmingxuan/ManySkills.git",
"ref": "v1.0.0",
"adapter": "codex-plugin",
"commit": "e869eb169eeb5a7cd9e58c0e514fa2dbbf50987d",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "eapil-llmapi-structured",
"pluginName": "eapil-llmapi-structured",
"repo": "https://git.playones.com/chenmingxuan/ManySkills.git",
"ref": "v1.0.0",
"adapter": "codex-plugin",
"commit": "e869eb169eeb5a7cd9e58c0e514fa2dbbf50987d",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "eapil-gpt2-image",
"pluginName": "eapil-gpt2-image",
"repo": "https://git.playones.com/chenmingxuan/ManySkills.git",
"ref": "v1.0.0",
"adapter": "codex-plugin",
"commit": "e869eb169eeb5a7cd9e58c0e514fa2dbbf50987d",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "eapil-voice",
"pluginName": "eapil-voice",
"repo": "https://git.playones.com/chenmingxuan/ManySkills.git",
"ref": "v1.0.0",
"adapter": "codex-plugin",
"commit": "e869eb169eeb5a7cd9e58c0e514fa2dbbf50987d",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "dingtalk-workspace",
"pluginName": "dingtalk-workspace",
@@ -24,8 +114,8 @@
"repo": "https://github.com/JuliusBrussee/caveman.git",
"ref": "main",
"adapter": "codex-plugin",
"commit": "6571943370f7c9d4de1946481177ee7b306cd8e8",
"syncedAt": "2026-10-04T16:00:00Z"
"commit": "99aafe151a1be72be783e662858e8a0955add59f",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "taste-skill",
@@ -42,8 +132,8 @@
"repo": "https://github.com/shadcn-ui/ui.git",
"ref": "main",
"adapter": "claude-skill",
"commit": "dba27166ad7b146b2bd840dcfb0a7d0fd95f5c8c",
"syncedAt": "2026-10-05T16:00:00Z"
"commit": "7ff7dbf8669fa3392c294ee745dc8d8c3cee842c",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "frontend-slides",
@@ -168,8 +258,8 @@
"repo": "https://github.com/vercel/next.js.git",
"ref": "canary",
"adapter": "skill-collection",
"commit": "41215d77762375b4b5154b12cfbb4372a835f8a0",
"syncedAt": "2026-10-05T16:00:00Z"
"commit": "8619c015f8cc9b26fbe10c5e97b0f8cb9ed5cb92",
"syncedAt": "2026-10-06T07:26:41Z"
},
{
"id": "shuorenhua",
@@ -0,0 +1,52 @@
"""Unpack or repack an OOXML document without shell-specific ZIP commands."""
import argparse
import os
import tempfile
import zipfile
from pathlib import Path, PurePosixPath
def unpack(source, destination):
root = Path(destination).resolve()
if root.exists() and any(root.iterdir()):
raise ValueError("Unpack destination must be empty")
with zipfile.ZipFile(source) as archive:
for info in archive.infolist():
name = PurePosixPath(info.filename.replace("\\", "/"))
if name.is_absolute() or ".." in name.parts or any(":" in part for part in name.parts):
raise ValueError(f"Unsafe ZIP entry: {info.filename}")
if (info.external_attr >> 16) & 0o170000 == 0o120000:
raise ValueError(f"ZIP symlink is not supported: {info.filename}")
archive.extractall(root)
def pack(source, destination):
root = Path(source).resolve()
output = Path(destination).resolve()
if output.is_relative_to(root):
raise ValueError("Output must be outside the unpacked directory")
if not (root / "[Content_Types].xml").is_file():
raise ValueError("Source must be the package root containing [Content_Types].xml")
output.parent.mkdir(parents=True, exist_ok=True)
fd, temporary = tempfile.mkstemp(suffix=output.suffix, dir=output.parent)
os.close(fd)
try:
with zipfile.ZipFile(temporary, "w", zipfile.ZIP_DEFLATED) as archive:
for file in sorted(root.rglob("*")):
if file.is_symlink():
raise ValueError(f"Package symlink is not supported: {file}")
if file.is_file():
archive.write(file, file.relative_to(root).as_posix())
os.replace(temporary, output)
finally:
Path(temporary).unlink(missing_ok=True)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("action", choices=("unpack", "pack"))
parser.add_argument("input")
parser.add_argument("output")
args = parser.parse_args()
{"unpack": unpack, "pack": pack}[args.action](args.input, args.output)
+41
View File
@@ -0,0 +1,41 @@
# 简体中文与 Windows 环境
以下命令中的 `$skill` 是当前已安装 Skill 的真实目录;不要硬编码开发者机器路径。脚本使用 Python 3.10+。先检查现有 Python/Node 环境,缺少哪个依赖再安装哪个。
```powershell
$env:PYTHONUTF8 = "1"
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
python --version
node --version
```
若只有 `py`,把命令中的 `python` 替换为 `py -3`。PowerShell 调用带空格的可执行文件路径使用 `& "路径"`;Python 脚本路径作为独立参数传入,不拼接 shell 命令。中文路径、空格路径均需引号。
需要独立依赖环境时,在任务工作目录创建 `.venv`,使用 `& ".\.venv\Scripts\python.exe" -m pip install <缺失包>`。无需改变系统执行策略或激活脚本。Node 库安装到任务目录,不默认全局安装。不要假设 Codex、Claude 或容器已预装所有依赖。
## 字体与文本
- 用户未指定语言时,中文用户的说明、标题、图例和交付文案使用简体中文;引文、产品名、代码和原文专有名词保持原样。
- 新文件优先使用本机可用的微软雅黑、等线、宋体或思源黑体。先查字体;声明字体名不等于字体已安装。Word 配置 `w:rFonts/@w:eastAsia` 与 `zh-CN`,PPT 配置主题字体和文本框字体,Excel 使用 `Microsoft YaHei` 等实际存在的字体。
- PDF 优先嵌入有再分发许可的中文字体;ReportLab 简单中文文档可用 `UnicodeCIDFont('STSong-Light')`,交付前仍检查目标阅读器效果。不要用 Helvetica 绘制中文,也不要把方块字当正常输出。
- CSV 面向 Windows Excel 时可用 `utf-8-sig`;先保留已有文件编码,不要自动改写所有输入。XML、JSON 和新建脚本使用 UTF-8。
- 标点、单位、日期、人民币格式、身份证号和前导零按用户语义保留;不要默认套用美式日期或把长编号转为数字。
## 转换与预览
Office 文档转 PDF 使用随附的跨平台 `scripts/office/soffice.py`。它按 `SOFFICE_PATH`、PATH、Windows Program Files、macOS 应用目录寻找 LibreOffice,并为转换创建独立临时 profile。
```powershell
# 仅在自动检测不到时设置;不要求添加系统 PATH
$env:SOFFICE_PATH = "C:\Program Files\LibreOffice\program\soffice.com"
python "$skill\scripts\office\soffice.py" --headless --convert-to pdf --outdir ".\preview" ".\中文 文档.docx"
python "$skill\scripts\render_pdf.py" ".\preview\中文 文档.pdf" ".\preview\pages"
```
按实际需要安装 LibreOffice、`pymupdf`、`defusedxml`、`lxml` 等缺失依赖。PDF 的 `scripts/convert_pdf_to_images.py` 与其他 Skill 的 `scripts/render_pdf.py` 均使用 PyMuPDF,不需要 Poppler。`pptx` 上游缩略图脚本仍需 Poppler;无 Poppler 时走 PDF 渲染流程。
使用 Python `scripts/office_package.py unpack <输入> <空目录>` 和 `pack <包根目录> <输出>` 处理 Office ZIP,无需 `unzip`、`zip`、`rm` 或 Bash。输出必须在解包目录之外。
## 验证与交付
生成或编辑后保存到新文件;先检查内容、公式或 OOXML 结构,再渲染并查看页面,检查中文缺字、表格越界、文本遮挡和分页。转换失败或字体缺失时说明具体原因,不把“文件保存成功”当成渲染通过。保留输入,除非用户明确要求覆盖。
@@ -0,0 +1,29 @@
"""Render PDF pages without Poppler; requires PyMuPDF."""
import argparse
from pathlib import Path
import pymupdf
def convert(pdf_path, output_dir, max_dim=1600):
if max_dim <= 0:
raise ValueError("max_dim must be positive")
output = Path(output_dir)
output.mkdir(parents=True, exist_ok=True)
with pymupdf.open(pdf_path) as document:
for index, page in enumerate(document):
scale = min(max_dim / page.rect.width, max_dim / page.rect.height)
pixmap = page.get_pixmap(matrix=pymupdf.Matrix(scale, scale), alpha=False)
target = output / f"page_{index + 1}.png"
pixmap.save(str(target))
print(target)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("input")
parser.add_argument("output")
parser.add_argument("--max-dim", type=int, default=1600)
args = parser.parse_args()
convert(args.input, args.output, args.max_dim)
+61
View File
@@ -0,0 +1,61 @@
"""Portable LibreOffice runner for Windows, macOS and Linux."""
import os
import platform
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path
def resolve_soffice_binary():
explicit = os.environ.get("SOFFICE_PATH")
if explicit:
candidate = Path(explicit).expanduser()
if candidate.is_file():
return str(candidate)
raise FileNotFoundError(f"SOFFICE_PATH does not exist: {candidate}")
names = ("soffice.com", "soffice.exe", "soffice") if platform.system() == "Windows" else ("soffice",)
for name in names:
binary = shutil.which(name)
if binary:
return binary
candidates = [Path("/Applications/LibreOffice.app/Contents/MacOS/soffice")]
if platform.system() == "Windows":
candidates = [
Path(root) / "LibreOffice/program" / name
for root in (os.environ.get("ProgramFiles"), os.environ.get("ProgramFiles(x86)")) if root
for name in ("soffice.com", "soffice.exe")
]
for candidate in candidates:
if candidate.is_file():
return str(candidate)
raise FileNotFoundError("LibreOffice not found. Install it or set SOFFICE_PATH to its executable.")
def get_soffice_env():
env = os.environ.copy()
env["PYTHONUTF8"] = "1"
if platform.system() == "Linux":
env.setdefault("SAL_USE_VCLPLUGIN", "svp")
return env
def run_soffice(args, **kwargs):
binary = resolve_soffice_binary()
kwargs.setdefault("env", get_soffice_env())
kwargs.setdefault("timeout", 120)
if any(str(arg).startswith("-env:UserInstallation=") for arg in args):
return subprocess.run([binary, *args], **kwargs)
with tempfile.TemporaryDirectory(prefix="skill-lo-", ignore_cleanup_errors=True) as profile:
profile_arg = f"-env:UserInstallation={Path(profile).resolve().as_uri()}"
return subprocess.run([binary, profile_arg, *args], **kwargs)
if __name__ == "__main__":
try:
raise SystemExit(run_soffice(sys.argv[1:]).returncode)
except (FileNotFoundError, subprocess.TimeoutExpired) as exc:
print(str(exc), file=sys.stderr)
raise SystemExit(1)
+38
View File
@@ -0,0 +1,38 @@
---
name: docx
description: 创建、读取、编辑和检查 Word 文档或模板(.docx/.dotx),包括中文排版、表格、批注和修订;适用于简体中文与 Windows PowerShell 环境。
license: Proprietary. LICENSE.txt has complete terms
---
# Word 文档
开始操作前读取 [references/platform.md](references/platform.md),确认 Python、Node、中文字体及需要的转换工具。命令中的脚本路径均相对本 Skill。
| 任务 | 选择 |
| --- | --- |
| 新建文档 | `docx`(Node)或 `python-docx`,按所需版式选择 |
| 提取正文或表格 | `python-docx`;需要查看修订时用 Pandoc 或检查 OOXML |
| 编辑复杂模板、批注或修订 | 保留 OOXML 结构,使用随附脚本 |
| .doc 旧文件 | LibreOffice 先转换为 .docx |
## 中文版式
未指定页面时,新文档采用 A4;已有文档沿用其页面和样式。正文中文字体设置 East Asian 字体,语言为 `zh-CN`,标题使用真正的标题样式。保持全角标点、编号、金额和原文引文;中文表格不要依赖空格对齐。
`docx` 创建时注意:表格同时指定列宽和单元格宽度;`ShadingType.CLEAR` 避免黑底;列表用 numbering 配置;`ImageRun` 指定类型;分页符放进 Paragraph。每个逻辑段落独立创建,不用换行模拟段落。需要 API 细节时按需读取 [upstream-guide.md](upstream-guide.md)。
## 编辑与审阅
先确认要清稿、批注还是保留修订;不要因文档类型自动强制红线。原有修订与批注保持不变,除非用户要求接受、拒绝或删除。
```powershell
python "$skill\scripts\office_package.py" unpack ".\输入.docx" ".\unpacked"
python "$skill\scripts\merge_runs.py" ".\unpacked"
# 按需编辑 word/document.xml,保持命名空间与节点顺序
python "$skill\scripts\office_package.py" pack ".\unpacked" ".\输出.docx"
python "$skill\scripts\office\validate.py" ".\输出.docx" --original ".\输入.docx"
```
`scripts/comment.py` 支持为文档添加批注;输出的定位节点需放到对应正文位置才能显示。`scripts/accept_changes.py` 仅在用户要求接受全部修订时使用,输出新文件;超时、文件未保存或仍有修订均算失败。
最终转换为 PDF,用 `scripts/render_pdf.py` 生成预览并查看中文字体、表格、页眉页脚、分页和页码。保留可编辑 Word 文件与用户需要的最终副本。
@@ -0,0 +1,75 @@
"""Accept tracked changes into a new DOCX using an isolated LibreOffice profile."""
import argparse
import shutil
import subprocess
import tempfile
import zipfile
from pathlib import Path
from defusedxml import ElementTree
from office.soffice import run_soffice
MACRO = '''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="Module1" script:language="StarBasic">
Sub AcceptAllTrackedChanges()
Dim dispatcher As Object
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dispatcher.executeDispatch(ThisComponent.CurrentController.Frame, ".uno:AcceptAllTrackedChanges", "", 0, Array())
ThisComponent.store()
ThisComponent.close(True)
End Sub
</script:module>'''
WORD_NS = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
def accept_changes(input_file, output_file, timeout=120):
source = Path(input_file).resolve()
output = Path(output_file).resolve()
if source == output or not source.is_file() or source.suffix.lower() != ".docx":
return None, "Input must be an existing DOCX and output must be a different file"
output.parent.mkdir(parents=True, exist_ok=True)
try:
with tempfile.TemporaryDirectory(prefix="docx-accept-", ignore_cleanup_errors=True) as temporary:
root = Path(temporary).resolve()
profile = root / "profile"
profile_arg = f"-env:UserInstallation={profile.as_uri()}"
run_soffice([profile_arg, "--headless", "--terminate_after_init"], check=True, capture_output=True, timeout=timeout)
macro_dir = profile / "user/basic/Standard"
macro_dir.mkdir(parents=True, exist_ok=True)
(macro_dir / "Module1.xba").write_text(MACRO, encoding="utf-8")
candidate = root / "accepted.docx"
shutil.copy2(source, candidate)
before = candidate.stat().st_mtime_ns
run_soffice([
profile_arg, "--headless", "--norestore",
"vnd.sun.star.script:Standard.Module1.AcceptAllTrackedChanges?language=Basic&location=application",
str(candidate),
], check=True, capture_output=True, timeout=timeout)
if candidate.stat().st_mtime_ns == before:
return None, "LibreOffice did not save the document"
with zipfile.ZipFile(candidate) as archive:
for name in archive.namelist():
if not name.startswith("word/") or not name.endswith(".xml"):
continue
document = ElementTree.fromstring(archive.read(name))
if any(element.tag in {WORD_NS + "ins", WORD_NS + "del", WORD_NS + "moveFrom", WORD_NS + "moveTo"}
or (element.tag.startswith(WORD_NS) and element.tag.endswith("Change"))
for element in document.iter()):
return None, f"Tracked changes remain in {name}"
shutil.copy2(candidate, output)
return None, f"Accepted tracked changes: {output}"
except (OSError, subprocess.SubprocessError, zipfile.BadZipFile) as exc:
return None, f"Failed to accept tracked changes: {exc}"
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("input")
parser.add_argument("output")
parser.add_argument("--timeout", type=int, default=120)
args = parser.parse_args()
_, message = accept_changes(args.input, args.output, args.timeout)
print(message)
raise SystemExit(0 if message.startswith("Accepted tracked changes:") else 1)
+35
View File
@@ -0,0 +1,35 @@
---
name: pdf
description: 读取、创建、合并、拆分、旋转、OCR 或填写 PDF 表单,处理简体中文字体与页面预览;适用于 Windows PowerShell 和跨平台终端。
license: Proprietary. LICENSE.txt has complete terms
---
# PDF 文档
先读取 [references/platform.md](references/platform.md),确认中文字体、Python 与实际需要的依赖。PDF 不等于扫描图片,先判断页面是否有可提取文字。
| 任务 | 工具 |
| --- | --- |
| 文本、页面预览、坐标检查 | PyMuPDF |
| 合并、拆分、旋转、元数据、加密 | pypdf |
| 表格提取 | pdfplumber,提取后核对表头、合并单元格与换行 |
| 新建中文 PDF | ReportLab 或可用的 Office/HTML 转 PDF 工具 |
| 扫描页 OCR | 本机可用的 OCR;Tesseract 中文需 `chi_sim` 数据 |
## 中文与排版
新文档默认简体中文、A4;已有版式或用户指定版式优先。中文必须使用实际可用的中文字体。优先嵌入授权允许的字体;ReportLab 简单文档可注册 `UnicodeCIDFont('STSong-Light')`。复制文本不乱码、渲染无缺字都需检查。
OCR 只针对扫描页或提取失败的页面;中文可用 `chi_sim+eng`,未装语言包时报告缺失。OCR 结果需核对数字、单位、姓名与表格关系,不凭猜测补全。
## 表单
涉及填写时按需读取 [forms.md](forms.md),先判断是否有 AcroForm 字段。可填表单使用随附 `extract_form_field_info.py`、`fill_fillable_fields.py`;非可填表单按页面坐标叠加,并检查原内容与填写区域。不要把签名图片视作数字签名。
## 预览与检查
```powershell
python "$skill\scripts\convert_pdf_to_images.py" ".\输入 中文.pdf" ".\preview"
```
此脚本使用 PyMuPDF,无需 Poppler,逐页渲染以避免一次加载整个大文档。合并或拆分后核对页面数量和顺序;填写后检查可见内容、字段值与页面边界。更多提取与转换方案见 [reference.md](reference.md),旧平台专用命令以本地环境指导为准。
+34
View File
@@ -0,0 +1,34 @@
---
name: pptx
description: 创建、读取、编辑和检查 PowerPoint 演示文稿或模板(.pptx/.potx),保留模板与可编辑图表,适配简体中文字体和 Windows PowerShell。
license: Proprietary. LICENSE.txt has complete terms
---
# PowerPoint 演示文稿
先读取 [references/platform.md](references/platform.md),确认字体、Node/Python 与需要的转换工具。先看用户模板或参考稿,再决定布局、配色与内容密度。
| 任务 | 选择 |
| --- | --- |
| 新建幻灯片 | `pptxgenjs`;简单任务也可使用 `python-pptx` |
| 提取文本 | `python-pptx` 或 markitdown;检查备注与隐藏页 |
| 复杂模板、母版或原生图表编辑 | OOXML 加随附脚本 |
| .ppt 旧格式 | LibreOffice 先转 .pptx |
## 中文与画布
新建稿未指定比例时用 16:9,设置画布后再添加元素。用户模板比例和主题优先。使用本机可用的微软雅黑、等线或思源黑体,同时设置主题字体与正文文本字体;简体中文语言标记使用 `zh-CN`。长中文标题主动换行,表格与数据标签保留足够空间,不能只缩小字号隐藏溢出。
`pptxgenjs` 颜色使用六位 HEX,不带 `#`;每次添加元素使用独立选项对象。文本框 margin 与字体测量要一致;原生图表、表格和文本保持可编辑。坐标单位为英寸,必须落在实际画布内。库限制、组合图表和模板 OOXML 细节按需读取 [upstream-guide.md](upstream-guide.md)。
## 模板编辑
先完成复制、删除或重排幻灯片,再改正文。使用 `scripts/add_slide.py` 注册复制页,最终页序确定后运行 `scripts/clean.py` 清理失去引用的部分。不要只复制 slide XML;关系、媒体、母版和内容类型必须一起处理。用 `scripts/office_package.py` 解包和重打包,避免依赖 Bash ZIP 命令。
```powershell
python "$skill\scripts\office\validate.py" ".\输出.pptx" --original ".\模板.pptx"
python "$skill\scripts\office\soffice.py" --headless --convert-to pdf --outdir ".\preview" ".\输出.pptx"
python "$skill\scripts\render_pdf.py" ".\preview\输出.pdf" ".\preview\pages"
```
没有模板时省略 `--original`。每页检查文字溢出、缺字、对齐、遮挡、图表标签、图片分辨率和页序。需要模板缩略图且 Poppler 可用时运行 `scripts/thumbnail.py` 并指定独立输出前缀;否则用上面的免 Poppler 逐页预览。
+35
View File
@@ -0,0 +1,35 @@
---
name: xlsx
description: 创建、读取、清理、编辑和检查 Excel 工作簿或 CSV/TSV,处理公式、图表、中文表头及 Windows Excel 编码,保留现有格式与宏。
license: Proprietary. LICENSE.txt has complete terms
---
# Excel 工作簿
先读取 [references/platform.md](references/platform.md),确认 Python、中文字体及是否需要公式计算引擎。复杂工作簿先检查公式、外部链接、宏、图表和现有样式,再选择处理方法。
- `openpyxl` 用于普通 .xlsx 单元格、公式和样式;`.xlsm` 读取时用 `keep_vba=True`,保留扩展名。不保证复杂 Excel 功能无损,必须检查实际需要保留的部分。
- `pandas` 适合表格数据清理;不要用整表重写处理需要保留样式、公式或图表的原文件。
- `.xls` 旧格式先使用兼容工具读取或转换;不要直接交给 openpyxl。
## 简体中文与数据类型
用户未指定语言时用简体中文表头、图例与说明。新文件使用可用的中文字体,表头、行高与列宽按中文实际长度设置;已有工作簿沿用其约定。身份证号、订单号、手机号和前导零存为文本,日期存真实日期值并设置明确格式,金额单位按用户要求标注。
Windows Excel 打开的新 CSV 可写 `utf-8-sig`;读取旧 CSV 先判断编码和分隔符。CSV 导出不保留多表、公式和样式,转换前明确所需交付格式。
## 公式与缓存
按用户语义写公式,验证引用范围与预期结果;不要用硬编码数值代替可重算公式。跨表引用含空格或中文标点时正确引用工作表名。合并区域只写左上角。
openpyxl 不计算公式。检查时分别用 `data_only=False` 读取公式、`data_only=True` 读取缓存;不能保存 `data_only=True` 的工作簿,否则公式会被数值覆盖。
```powershell
python "$skill\scripts\recalc.py" ".\输出 中文.xlsx" 120
```
重算会改写指定工作簿,先保留输入。脚本使用独立 LibreOffice profile,自动识别 Windows 的安装路径。检查 JSON 的 `status`、`total_errors` 和具体单元格;`errors_found` 即使进程退出码为零也未通过。含 `error` 的结果表示没有完成重算。
有外部链接、宏、动态数组或 Excel 专用函数时,优先使用目标 Excel 环境验证,不能盲目用 LibreOffice 往返保存。兼容公式、缓存丢失和链接风险按需读取 [upstream-guide.md](upstream-guide.md)。无法运行计算引擎时说明“尚未重算”,不要声称公式已验证。
交付前核对数值、公式、中文显示、筛选、冻结窗格、打印区域和图表。用新输出文件保留输入;抽查代表行、合计和异常情况,避免只检查文件能够打开。
+89
View File
@@ -0,0 +1,89 @@
"""Recalculate an XLSX through a temporary LibreOffice import/export, without macros."""
import argparse
import json
import os
import shutil
import subprocess
import tempfile
import zipfile
from pathlib import Path
from openpyxl import load_workbook
from office.soffice import run_soffice
def inspect_workbook(path):
formulas = load_workbook(path, data_only=False)
values = load_workbook(path, data_only=True)
try:
formula_cells = set()
errors = {}
for sheet in formulas:
if not hasattr(sheet, "iter_rows"):
continue
for row in sheet.iter_rows():
for cell in row:
location = f"{sheet.title}!{cell.coordinate}"
if cell.data_type == "f":
formula_cells.add(location)
cached = values[sheet.title][cell.coordinate]
if cached.data_type == "e":
errors.setdefault(str(cached.value), []).append(location)
return formula_cells, errors
finally:
formulas.close()
values.close()
def recalc(filename, timeout=120):
source = Path(filename).expanduser().resolve()
if not source.is_file() or source.suffix.lower() != ".xlsx":
return {"error": "Input must be an existing .xlsx file; use Excel for macro-enabled workbooks"}
try:
with zipfile.ZipFile(source) as archive:
if any(name.startswith("xl/externalLinks/") for name in archive.namelist()):
return {"error": "External workbook links require validation in Excel; original file was not modified"}
original_formulas, _ = inspect_workbook(source)
with tempfile.TemporaryDirectory(prefix="xlsx-recalc-", dir=source.parent, ignore_cleanup_errors=True) as temporary:
root = Path(temporary)
input_dir, output_dir = root / "input", root / "output"
input_dir.mkdir()
output_dir.mkdir()
candidate = input_dir / source.name
shutil.copy2(source, candidate)
result = run_soffice([
"--headless", "--norestore", "--convert-to", "xlsx:Calc MS Excel 2007 XML",
"--outdir", str(output_dir), str(candidate),
], capture_output=True, text=True, encoding="utf-8", errors="replace", timeout=timeout)
recalculated = output_dir / source.name
if result.returncode or not recalculated.is_file():
return {"error": "LibreOffice did not export a recalculated workbook", "details": result.stderr or result.stdout}
formula_cells, errors = inspect_workbook(recalculated)
if original_formulas != formula_cells:
return {"error": "Formula locations changed during conversion; original file was not modified"}
error_count = sum(len(locations) for locations in errors.values())
report = {
"status": "errors_found" if error_count else "success",
"total_formulas": len(formula_cells),
"total_errors": error_count,
"error_summary": {
error: {"count": len(locations), "locations": locations[:100]}
for error, locations in errors.items()
},
}
if not errors:
os.replace(recalculated, source)
return report
except (OSError, subprocess.SubprocessError, zipfile.BadZipFile, ValueError) as exc:
return {"error": str(exc)}
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("input")
parser.add_argument("timeout", nargs="?", type=int, default=120)
args = parser.parse_args()
report = recalc(args.input, args.timeout)
print(json.dumps(report, ensure_ascii=False, indent=2))
raise SystemExit(1 if "error" in report else 0)