CtrlK
BlogDocsLog inGet started
Tessl Logo

jbaruch/speaker-toolkit

Six-skill presentation system: ingest talks into a rhetoric vault, run interactive clarification, generate a speaker profile, create presentations that match your documented patterns, produce the deck illustrations + thumbnail visual layer, and publish talk pages to a Jekyll shownotes site. Includes a 111-entry Presentation Patterns taxonomy (81 observable: 62 patterns + 19 antipatterns; 30 unobservable: 21 patterns + 9 antipatterns) for scoring, brainstorming, and go-live preparation.

Quality

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

export-pdf.pyskills/presentation-creator/scripts/

#!/usr/bin/env python3
"""Export a PowerPoint deck to PDF via AppleScript (macOS + Microsoft PowerPoint).

Falls back to LibreOffice CLI if PowerPoint is not available.

Usage:
    export-pdf.py <deck.pptx> [<output.pdf>]

    If output.pdf is omitted, uses the same name with .pdf extension.

Examples:
    export-pdf.py presentation.pptx
    export-pdf.py presentation.pptx ~/exports/presentation.pdf
"""

import os
import shutil
import subprocess
import sys


def try_powerpoint_applescript(pptx_path, pdf_path):
    """Export via Microsoft PowerPoint AppleScript (macOS only)."""
    script = f'''
tell application "Microsoft PowerPoint"
    open POSIX file "{pptx_path}"
    delay 2
    save active presentation in POSIX file "{pdf_path}" as save as PDF
    close active presentation saving no
end tell
'''
    result = subprocess.run(
        ["osascript", "-e", script], capture_output=True, text=True, timeout=30
    )
    return result.returncode == 0


def try_libreoffice(pptx_path, pdf_path):
    """Export via LibreOffice CLI."""
    output_dir = os.path.dirname(pdf_path) or "."
    result = subprocess.run(
        [
            "libreoffice",
            "--headless",
            "--convert-to",
            "pdf",
            "--outdir",
            output_dir,
            pptx_path,
        ],
        capture_output=True,
        text=True,
        timeout=60,
    )
    if result.returncode == 0:
        # LibreOffice names output after the input file
        lo_output = os.path.join(
            output_dir, os.path.splitext(os.path.basename(pptx_path))[0] + ".pdf"
        )
        if lo_output != pdf_path and os.path.exists(lo_output):
            shutil.move(lo_output, pdf_path)
    return result.returncode == 0


def main():
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <deck.pptx> [<output.pdf>]", file=sys.stderr)
        sys.exit(1)

    pptx_path = os.path.abspath(sys.argv[1])
    if len(sys.argv) >= 3:
        pdf_path = os.path.abspath(sys.argv[2])
    else:
        pdf_path = os.path.splitext(pptx_path)[0] + ".pdf"

    # Try PowerPoint first (macOS), then LibreOffice
    if sys.platform == "darwin" and shutil.which("osascript"):
        if try_powerpoint_applescript(pptx_path, pdf_path):
            print(f"Exported via PowerPoint: {pdf_path}")
            sys.exit(0)
        print("PowerPoint export failed, trying LibreOffice...", file=sys.stderr)

    if shutil.which("libreoffice"):
        if try_libreoffice(pptx_path, pdf_path):
            print(f"Exported via LibreOffice: {pdf_path}")
            sys.exit(0)

    print(
        "ERROR: Neither PowerPoint nor LibreOffice available for PDF export",
        file=sys.stderr,
    )
    sys.exit(1)


if __name__ == "__main__":
    main()

skills

presentation-creator

SKILL.md

README.md

tile.json