Files
iacore bc17471635 feat(skills): make skill scripts self-executing with uv hashbang
The Python scripts in mpi-pptx-translate, mpi-pdf-to-docx-conversion, and
mpi-chinese-text-normalize previously required users to type
manually. That is easy to forget and adds friction every time the skill runs.

Switch all four scripts to a  shebang,
so they can be invoked directly: . The
 PEP 723 metadata blocks remain, so uv still installs the
dependencies automatically. Also made the scripts executable and updated
their usage messages and SKILL.md instructions to match the direct-execution
style.
2026-07-15 13:05:34 +08:00

81 lines
2.5 KiB
Python
Executable File

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.9"
# dependencies = [
# "python-pptx",
# "pyyaml",
# ]
# ///
import sys, yaml
from pptx import Presentation
PLACEHOLDER_KINDS = {
1: "title", 2: "body", 3: "center_title",
4: "subtitle", 5: "body", 6: "body", 7: "body",
}
def shape_kind(shape):
if shape.has_table:
return "table"
try:
ph = shape.placeholder_format
if ph is not None and ph.type is not None:
return PLACEHOLDER_KINDS.get(ph.type, "body")
except ValueError:
pass
return "body"
def extract(pptx_path):
prs = Presentation(pptx_path)
entries = []
for slide_num, slide in enumerate(prs.slides, 1):
for shape_idx, shape in enumerate(slide.shapes):
kind = shape_kind(shape)
if shape.has_text_frame:
for para_idx, para in enumerate(shape.text_frame.paragraphs):
full = para.text.strip()
if not full:
continue
entries.append({
"slide": slide_num, "shape": shape_idx,
"run": para_idx, "kind": kind,
"zh": full, "en": "",
})
elif shape.has_table:
for row_idx, row in enumerate(shape.table.rows):
for col_idx, cell in enumerate(row.cells):
text = cell.text.strip()
if not text:
continue
entries.append({
"slide": slide_num, "shape": shape_idx,
"run": len(shape.table.rows) * col_idx + row_idx,
"kind": "table", "zh": text, "en": "",
})
if slide.has_notes_slide:
notes = slide.notes_slide.notes_text_frame.text.strip()
if notes:
entries.append({
"slide": slide_num, "shape": -1, "run": 0,
"kind": "notes", "zh": notes, "en": "",
})
return entries
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: ./extract.py <input.pptx> <output.yaml>", file=sys.stderr)
sys.exit(1)
entries = extract(sys.argv[1])
with open(sys.argv[2], "w") as f:
yaml.dump(entries, f, allow_unicode=True, default_flow_style=False, sort_keys=False)
print(f"Extracted {len(entries)} entries to {sys.argv[2]}")