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.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: mpi-chinese-text-normalize
|
name: mpi-chinese-text-normalize
|
||||||
description: Normalize Chinese markdown files by removing extraneous mid-sentence line breaks from fixed-width exports while preserving TOC structures, section headers, and intentional paragraph breaks. Do not use for English prose, wiki-link index files, or mixed CJK/English documents without manual review.
|
description: Normalize Chinese markdown files by removing extraneous mid-sentence line breaks from fixed-width exports while preserving TOC structures, section headers, and intentional paragraph breaks. Do not use for English prose, wiki-link index files, or mixed CJK/English documents without manual review.
|
||||||
compatibility: Requires Python 3.9+ and uv. The script uses only the standard library.
|
compatibility: Requires Python 3.9+ and uv. The script's shebang invokes `uv run --script`; it uses only the standard library.
|
||||||
---
|
---
|
||||||
|
|
||||||
When Chinese text has hard line breaks at a fixed width (~20-25 chars) — common in PDF exports, OCR output, or poorly-converted documents — use this skill to join them into flowing paragraphs.
|
When Chinese text has hard line breaks at a fixed width (~20-25 chars) — common in PDF exports, OCR output, or poorly-converted documents — use this skill to join them into flowing paragraphs.
|
||||||
@@ -14,13 +14,13 @@ When Chinese text has hard line breaks at a fixed width (~20-25 chars) — commo
|
|||||||
|
|
||||||
## Approach
|
## Approach
|
||||||
|
|
||||||
Run with `uv`:
|
Run the script directly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv run skills/mpi-chinese-text-normalize/scripts/normalize_breaks.py <directory>
|
skills/mpi-chinese-text-normalize/scripts/normalize_breaks.py <directory>
|
||||||
```
|
```
|
||||||
|
|
||||||
It processes all `.md` files in the directory.
|
The shebang invokes `uv run --script`. It processes all `.md` files in the directory.
|
||||||
|
|
||||||
The script handles three file patterns:
|
The script handles three file patterns:
|
||||||
|
|
||||||
|
|||||||
Regular → Executable
+3
-2
@@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env -S uv run --script
|
||||||
# /// script
|
# /// script
|
||||||
# requires-python = ">=3.9"
|
# requires-python = ">=3.9"
|
||||||
# dependencies = []
|
# dependencies = []
|
||||||
@@ -11,7 +12,7 @@ Three file patterns:
|
|||||||
2. Mostly-paragraph with stray breaks + outline TOC -> join broken lines, preserve list items
|
2. Mostly-paragraph with stray breaks + outline TOC -> join broken lines, preserve list items
|
||||||
3. Already fine -> skip (idempotent)
|
3. Already fine -> skip (idempotent)
|
||||||
|
|
||||||
Usage: uv run normalize_breaks.py <directory>
|
Usage: ./normalize_breaks.py <directory>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
@@ -162,7 +163,7 @@ def process_file(filepath):
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print("Usage: uv run normalize_breaks.py <directory>", file=sys.stderr)
|
print("Usage: ./normalize_breaks.py <directory>", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
workdir = Path(sys.argv[1])
|
workdir = Path(sys.argv[1])
|
||||||
files = sorted(workdir.glob('*.md'))
|
files = sorted(workdir.glob('*.md'))
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name: mpi-pdf-to-docx-conversion
|
name: mpi-pdf-to-docx-conversion
|
||||||
description: Convert flowing text PDFs (Chinese or multi-language) to DOCX with proper fonts, styles, native bullets, lists, and embedded images. Use for text-based PDFs. Do not use for scanned/image PDFs, form-heavy PDFs, or documents where exact page layout must be preserved.
|
description: Convert flowing text PDFs (Chinese or multi-language) to DOCX with proper fonts, styles, native bullets, lists, and embedded images. Use for text-based PDFs. Do not use for scanned/image PDFs, form-heavy PDFs, or documents where exact page layout must be preserved.
|
||||||
license: MIT
|
license: MIT
|
||||||
compatibility: Requires Python 3.9+ and uv. Dependencies (pymupdf, python-docx) are declared in the script's /// script metadata.
|
compatibility: Requires Python 3.9+ and uv. The script's shebang invokes `uv run --script`; dependencies (pymupdf, python-docx) are declared in the `/// script` metadata.
|
||||||
---
|
---
|
||||||
|
|
||||||
# PDF-to-DOCX Conversion
|
# PDF-to-DOCX Conversion
|
||||||
@@ -11,13 +11,13 @@ Convert text-based PDF documents (including CJK) into structured DOCX files that
|
|||||||
|
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
For most PDFs, run the bundled converter with `uv`:
|
For most PDFs, run the bundled converter directly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv run skills/mpi-pdf-to-docx-conversion/scripts/convert_pdf_to_docx.py input.pdf output.docx
|
skills/mpi-pdf-to-docx-conversion/scripts/convert_pdf_to_docx.py input.pdf output.docx
|
||||||
```
|
```
|
||||||
|
|
||||||
`uv` reads the `/// script` metadata block in the script and installs `pymupdf` and `python-docx` automatically.
|
The shebang invokes `uv run --script`, which reads the `/// script` metadata block and installs `pymupdf` and `python-docx` automatically.
|
||||||
|
|
||||||
For documents with unusual fonts or structure, inspect first and pass a config dict. See `references/config-patterns.md` for the config schema and common patterns.
|
For documents with unusual fonts or structure, inspect first and pass a config dict. See `references/config-patterns.md` for the config schema and common patterns.
|
||||||
|
|
||||||
|
|||||||
Regular → Executable
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env -S uv run --script
|
||||||
# /// script
|
# /// script
|
||||||
# requires-python = ">=3.9"
|
# requires-python = ">=3.9"
|
||||||
# dependencies = [
|
# dependencies = [
|
||||||
@@ -13,7 +13,7 @@ Handles multi-language text, mixed fonts, bullets, numbered lists, verses,
|
|||||||
attributions, images, and flowing text across pages.
|
attributions, images, and flowing text across pages.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
uv run convert_pdf_to_docx.py input.pdf output.docx
|
./convert_pdf_to_docx.py input.pdf output.docx
|
||||||
|
|
||||||
Requires: uv (dependencies are declared in the /// script block above)
|
Requires: uv (dependencies are declared in the /// script block above)
|
||||||
"""
|
"""
|
||||||
@@ -552,6 +552,6 @@ def convert_pdf_to_docx(pdf_path: str, docx_path: str, config: dict = None):
|
|||||||
# CLI
|
# CLI
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 3:
|
if len(sys.argv) != 3:
|
||||||
print("Usage: uv run convert_pdf_to_docx.py <input.pdf> <output.docx>")
|
print("Usage: ./convert_pdf_to_docx.py <input.pdf> <output.docx>")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
convert_pdf_to_docx(sys.argv[1], sys.argv[2])
|
convert_pdf_to_docx(sys.argv[1], sys.argv[2])
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
name: mpi-pptx-translate
|
name: mpi-pptx-translate
|
||||||
description: Translate PowerPoint files between Chinese and English — extract strings to YAML, translate, quality review, and write back with font-shrink + auto-fit for layout. Use only for .pptx files. Do not use for .ppt, Google Slides exports, or PDFs.
|
description: Translate PowerPoint files between Chinese and English — extract strings to YAML, translate, quality review, and write back with font-shrink + auto-fit for layout. Use only for .pptx files. Do not use for .ppt, Google Slides exports, or PDFs.
|
||||||
category: productivity
|
category: productivity
|
||||||
compatibility: Requires Python 3.9+ and uv. Dependencies (python-pptx, pyyaml) are declared in the scripts' /// script metadata.
|
compatibility: Requires Python 3.9+ and uv. The scripts' shebang invokes `uv run --script`; dependencies (python-pptx, pyyaml) are declared in the `/// script` metadata.
|
||||||
---
|
---
|
||||||
|
|
||||||
# PPTX Translation
|
# PPTX Translation
|
||||||
@@ -13,13 +13,13 @@ Translate `.pptx` files between Chinese and English. Covers the full pipeline: e
|
|||||||
|
|
||||||
### 1. Extract strings to YAML
|
### 1. Extract strings to YAML
|
||||||
|
|
||||||
Run with `uv`:
|
Run the script directly:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv run skills/mpi-pptx-translate/scripts/extract.py original.pptx strings.yaml
|
skills/mpi-pptx-translate/scripts/extract.py original.pptx strings.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
`uv` reads the `/// script` metadata block and installs `python-pptx` and `pyyaml` automatically. Produces YAML with entries:
|
The shebang invokes `uv run --script`, which reads the `/// script` metadata block and installs `python-pptx` and `pyyaml` automatically. Produces YAML with entries:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- slide: 1
|
- slide: 1
|
||||||
@@ -65,7 +65,7 @@ Scan for:
|
|||||||
### 4. Write back with layout fixes
|
### 4. Write back with layout fixes
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv run skills/mpi-pptx-translate/scripts/build.py strings.yaml original.pptx translated.pptx
|
skills/mpi-pptx-translate/scripts/build.py strings.yaml original.pptx translated.pptx
|
||||||
```
|
```
|
||||||
|
|
||||||
The script:
|
The script:
|
||||||
@@ -89,5 +89,5 @@ The absorbed `pptx-translation` skill had alternate script names: `extract_pptx.
|
|||||||
|
|
||||||
## Scripts
|
## Scripts
|
||||||
|
|
||||||
- `uv run skills/mpi-pptx-translate/scripts/extract.py` — extract strings from PPTX to YAML
|
- `skills/mpi-pptx-translate/scripts/extract.py` — extract strings from PPTX to YAML
|
||||||
- `uv run skills/mpi-pptx-translate/scripts/build.py` — write translations back with font shrink + auto-fit
|
- `skills/mpi-pptx-translate/scripts/build.py` — write translations back with font shrink + auto-fit
|
||||||
|
|||||||
Regular → Executable
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env -S uv run --script
|
||||||
# /// script
|
# /// script
|
||||||
# requires-python = ">=3.9"
|
# requires-python = ">=3.9"
|
||||||
# dependencies = [
|
# dependencies = [
|
||||||
@@ -77,6 +78,6 @@ def build(yaml_path, src_path, out_path):
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 4:
|
if len(sys.argv) != 4:
|
||||||
print("Usage: uv run build.py <strings.yaml> <input.pptx> <output.pptx>", file=sys.stderr)
|
print("Usage: ./build.py <strings.yaml> <input.pptx> <output.pptx>", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
build(sys.argv[1], sys.argv[2], sys.argv[3])
|
build(sys.argv[1], sys.argv[2], sys.argv[3])
|
||||||
|
|||||||
Regular → Executable
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env -S uv run --script
|
||||||
# /// script
|
# /// script
|
||||||
# requires-python = ">=3.9"
|
# requires-python = ">=3.9"
|
||||||
# dependencies = [
|
# dependencies = [
|
||||||
@@ -71,7 +72,7 @@ def extract(pptx_path):
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 3:
|
if len(sys.argv) != 3:
|
||||||
print("Usage: uv run extract.py <input.pptx> <output.yaml>", file=sys.stderr)
|
print("Usage: ./extract.py <input.pptx> <output.yaml>", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
entries = extract(sys.argv[1])
|
entries = extract(sys.argv[1])
|
||||||
with open(sys.argv[2], "w") as f:
|
with open(sys.argv[2], "w") as f:
|
||||||
|
|||||||
Reference in New Issue
Block a user