• Tech Dev NotesTech Dev Notes
Apps
  • App lookup
  • App compare
Market movement
  • App charts
  • App rankings
Visual proof
  • App screens
  • App listing screenshots
  • App icons
Build intelligence
  • App tech stacks
  • Tool releases
  • Developers
More
  • X feature flags
  • Grokipedia
  • Blog
  • Follow on X
Skip to content
All content/ filesChangelog

grok-build/latest/content · 0.2.69

skills/pptx/scripts/add_slide.py

Skill·6.7 KB·153 lines

content/

  • .

    • README.md
  • docs/user-guide

    • 01-getting-started.md
    • 02-authentication.md
    • 03-keyboard-shortcuts.md
    • 04-slash-commands.md
    • 05-configuration.md
    • 06-theming.md
    • 07-mcp-servers.md
    • 08-skills.md
    • 09-plugins.md
    • 10-hooks.md
    • 11-custom-models.md
    • 12-project-rules.md
    • 13-memory.md
    • 14-headless-mode.md
    • 15-agent-mode.md
    • 16-subagents.md
    • 17-sessions.md
    • 18-sandbox.md
    • 19-plan-mode.md
    • 20-background-tasks.md
    • 21-terminal-support.md
    • 22-permissions-and-safety.md
  • skills/check-work

    • SKILL.md
  • skills/code-review

    • SKILL.md
  • skills/create-skill

    • SKILL.md
  • skills/docx

    • SKILL.md
  • skills/docx/scripts

    • __init__.py
    • accept_changes.py
    • comment.py
  • skills/docx/scripts/office

    • pack.py
    • soffice.py
    • unpack.py
    • validate.py
  • skills/docx/scripts/office/helpers

    • __init__.py
    • merge_runs.py
    • simplify_redlines.py
  • skills/docx/scripts/office/schemas/ecma/fouth-edition

    • opc-contentTypes.xsd
    • opc-coreProperties.xsd
    • opc-digSig.xsd
    • opc-relationships.xsd
  • skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016

    • dml-chart.xsd
    • dml-chartDrawing.xsd
    • dml-diagram.xsd
    • dml-lockedCanvas.xsd
    • dml-main.xsd
    • dml-picture.xsd
    • dml-spreadsheetDrawing.xsd
    • dml-wordprocessingDrawing.xsd
    • pml.xsd
    • shared-additionalCharacteristics.xsd
    • shared-bibliography.xsd
    • shared-commonSimpleTypes.xsd
    • shared-customXmlDataProperties.xsd
    • shared-customXmlSchemaProperties.xsd
    • shared-documentPropertiesCustom.xsd
    • shared-documentPropertiesExtended.xsd
    • shared-documentPropertiesVariantTypes.xsd
    • shared-math.xsd
    • shared-relationshipReference.xsd
    • sml.xsd
    • vml-main.xsd
    • vml-officeDrawing.xsd
    • vml-presentationDrawing.xsd
    • vml-spreadsheetDrawing.xsd
    • vml-wordprocessingDrawing.xsd
    • wml.xsd
    • xml.xsd
  • skills/docx/scripts/office/schemas/mce

    • mc.xsd
  • skills/docx/scripts/office/schemas/microsoft

    • wml-2010.xsd
    • wml-2012.xsd
    • wml-2018.xsd
    • wml-cex-2018.xsd
    • wml-cid-2016.xsd
    • wml-sdtdatahash-2020.xsd
    • wml-symex-2015.xsd
  • skills/docx/scripts/office/validators

    • __init__.py
    • base.py
    • docx.py
    • pptx.py
    • redlining.py
  • skills/docx/scripts/templates

    • comments.xml
    • commentsExtended.xml
    • commentsExtensible.xml
    • commentsIds.xml
    • people.xml
  • skills/help

    • SKILL.md
  • skills/imagine

    • SKILL.md
  • skills/pptx

    • editing.md
    • pptxgenjs.md
    • SKILL.md
  • skills/pptx/scripts

    • __init__.py
    • add_slide.py
    • clean.py
    • thumbnail.py
  • skills/pptx/scripts/office

    • pack.py
    • soffice.py
    • unpack.py
    • validate.py
  • skills/pptx/scripts/office/helpers

    • __init__.py
    • merge_runs.py
    • simplify_redlines.py
  • skills/pptx/scripts/office/schemas/ecma/fouth-edition

    • opc-contentTypes.xsd
    • opc-coreProperties.xsd
    • opc-digSig.xsd
    • opc-relationships.xsd
  • skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016

    • dml-chart.xsd
    • dml-chartDrawing.xsd
    • dml-diagram.xsd
    • dml-lockedCanvas.xsd
    • dml-main.xsd
    • dml-picture.xsd
    • dml-spreadsheetDrawing.xsd
    • dml-wordprocessingDrawing.xsd
    • pml.xsd
    • shared-additionalCharacteristics.xsd
    • shared-bibliography.xsd
    • shared-commonSimpleTypes.xsd
    • shared-customXmlDataProperties.xsd
    • shared-customXmlSchemaProperties.xsd
    • shared-documentPropertiesCustom.xsd
    • shared-documentPropertiesExtended.xsd
    • shared-documentPropertiesVariantTypes.xsd
    • shared-math.xsd
    • shared-relationshipReference.xsd
    • sml.xsd
    • vml-main.xsd
    • vml-officeDrawing.xsd
    • vml-presentationDrawing.xsd
    • vml-spreadsheetDrawing.xsd
    • vml-wordprocessingDrawing.xsd
    • wml.xsd
    • xml.xsd
  • skills/pptx/scripts/office/schemas/mce

    • mc.xsd
  • skills/pptx/scripts/office/schemas/microsoft

    • wml-2010.xsd
    • wml-2012.xsd
    • wml-2018.xsd
    • wml-cex-2018.xsd
    • wml-cid-2016.xsd
    • wml-sdtdatahash-2020.xsd
    • wml-symex-2015.xsd
  • skills/pptx/scripts/office/validators

    • __init__.py
    • base.py
    • docx.py
    • pptx.py
    • redlining.py
  • skills/xlsx/scripts

    • recalc.py
  • skills/xlsx/scripts/office

    • pack.py
    • soffice.py
    • unpack.py
    • validate.py
  • skills/xlsx/scripts/office/helpers

    • __init__.py
    • merge_runs.py
    • simplify_redlines.py
  • skills/xlsx/scripts/office/schemas/ecma/fouth-edition

    • opc-contentTypes.xsd
  • skills/xlsx/scripts/office/validators

    • __init__.py
    • base.py
    • docx.py
    • pptx.py
    • redlining.py
"""Add a new slide to an unpacked PPTX directory.

Usage: python add_slide.py <unpacked_dir> <source>

The source can be:
  - A slide file (e.g., slide2.xml) - duplicates the slide
  - A layout file (e.g., slideLayout2.xml) - creates from layout

Examples:
    python add_slide.py unpacked/ slide2.xml
    # Duplicates slide2, creates slide5.xml

    python add_slide.py unpacked/ slideLayout2.xml
    # Creates slide5.xml from slideLayout2.xml

To see available layouts: ls unpacked/ppt/slideLayouts/

Prints the <p:sldId> element to add to presentation.xml.
"""

import re
import shutil
import sys
from pathlib import Path


def get_next_slide_number(slides_dir: Path) -> int:
    existing = [
        int(m.group(1))
        for f in slides_dir.glob("slide*.xml")
        if (m := re.match(r"slide(\d+)\.xml", f.name))
    ]
    return max(existing) + 1 if existing else 1


def create_slide_from_layout(unpacked_dir: Path, layout_file: str) -> None:
    slides_dir = unpacked_dir / "ppt" / "slides"
    rels_dir = slides_dir / "_rels"
    layouts_dir = unpacked_dir / "ppt" / "slideLayouts"

    layout_path = layouts_dir / layout_file
    if not layout_path.exists():
        print(f"Error: {layout_path} not found", file=sys.stderr)
        sys.exit(1)

    next_num = get_next_slide_number(slides_dir)
    dest = f"slide{next_num}.xml"
    dest_slide = slides_dir / dest
    dest_rels = rels_dir / f"{dest}.rels"

    slide_xml = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
  <p:cSld>
    <p:spTree>
      <p:nvGrpSpPr>
        <p:cNvPr id="1" name=""/>
        <p:cNvGrpSpPr/>
        <p:nvPr/>
      </p:nvGrpSpPr>
      <p:grpSpPr>
        <a:xfrm>
          <a:off x="0" y="0"/>
          <a:ext cx="0" cy="0"/>
          <a:chOff x="0" y="0"/>
          <a:chExt cx="0" cy="0"/>
        </a:xfrm>
      </p:grpSpPr>
    </p:spTree>
  </p:cSld>
  <p:clrMapOvr>
    <a:masterClrMapping/>
  </p:clrMapOvr>
</p:sld>"""
    dest_slide.write_text(slide_xml, encoding="utf-8")

    rels_dir.mkdir(exist_ok=True)
    rels_xml = f"""<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/{layout_file}"/>
</Relationships>"""
    dest_rels.write_text(rels_xml, encoding="utf-8")

    _add_to_content_types(unpacked_dir, dest)

    rid = _add_to_presentation_rels(unpacked_dir, dest)

    next_slide_id = _get_next_slide_id(unpacked_dir)

    print(f"Created {dest} from {layout_file}")
    print(f'Add to presentation.xml <p:sldIdLst>: <p:sldId id="{next_slide_id}" r:id="{rid}"/>')


def duplicate_slide(unpacked_dir: Path, source: str) -> None:
    slides_dir = unpacked_dir / "ppt" / "slides"
    rels_dir = slides_dir / "_rels"

    source_slide = slides_dir / source

    if not source_slide.exists():
        print(f"Error: {source_slide} not found", file=sys.stderr)
        sys.exit(1)

    next_num = get_next_slide_number(slides_dir)
    dest = f"slide{next_num}.xml"
    dest_slide = slides_dir / dest

    source_rels = rels_dir / f"{source}.rels"
    dest_rels = rels_dir / f"{dest}.rels"

    shutil.copy2(source_slide, dest_slide)

    if source_rels.exists():
        shutil.copy2(source_rels, dest_rels)

        rels_content = dest_rels.read_text(encoding="utf-8")
        rels_content = re.sub(
            r'\s*<Relationship[^>]*Type="[^"]*notesSlide"[^>]*/>\s*',
            "\n",
            rels_content,
        )
        dest_rels.write_text(rels_content, encoding="utf-8")

    _add_to_content_types(unpacked_dir, dest)

    rid = _add_to_presentation_rels(unpacked_dir, dest)

    next_slide_id = _get_next_slide_id(unpacked_dir)

    print(f"Created {dest} from {source}")
    print(f'Add to presentation.xml <p:sldIdLst>: <p:sldId id="{next_slide_id}" r:id="{rid}"/>')


def _add_to_content_types(unpacked_dir: Path, dest: str) -> None:
    content_types_path = unpacked_dir / "[Content_Types].xml"
    content_types = content_types_path.read_text(encoding="utf-8")

    new_override = f'<Override PartName="/ppt/slides/{dest}" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/>'

    if f"/ppt/slides/{dest}" not in content_types:
        content_types = content_types.replace("</Types>", f"  {new_override}\n</Types>")
        content_types_path.write_text(content_types, encoding="utf-8")


def _add_to_presentation_rels(unpacked_dir: Path, dest: str) -> str:
    pres_rels_path = unpacked_dir / "ppt" / "_rels" / "presentation.xml.rels"
    pres_rels = pres_rels_path.read_text(encoding="utf-8")

    rids = [int(m) for m in re.findall(r'Id="rId(\d+)"', pres_rels)]
    next_rid = max(rids) + 1 if rids else 1
    rid = f"rId{next_rid}"

    new_rel = f'<Relationship Id="{rid}" Type="http://schemas.openxmlformats.org/off
…
Previousskills/pptx/scripts/__init__.pyNextskills/pptx/scripts/clean.py

© 2026 Tech Dev Notes

RSSAboutAPIPrivacyTermsSitemap@techdevnotes