Metadata-Version: 2.4
Name: pptxizza
Version: 0.1.2
Summary: A streamlined, LLM-friendly pip package for creating and editing pptx files from templates.
Author: Kameron
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: lxml>=4.9.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"

# pptxizza

A streamlined, LLM-friendly pip package for creating and editing `.pptx` files dynamically. `pptxizza` uses direct XML manipulation under the hood (via `lxml`) to fill text, replace images, and update charts and tables within existing PowerPoint templates quickly and efficiently, featuring a highly-granular Object-Oriented API for direct shape manipulation!

## Why pptxizza? (vs `python-pptx`)

This project is heavily inspired by [`python-pptx`](https://github.com/scanny/python-pptx), which is a fantastic and comprehensive library for working with PowerPoint files. However, `pptxizza` was created primarily for one very important reason: **to add native SVG support haha!**

Native PowerPoint doesn't typically embed pure SVGs comfortably via older XML specifications, and `python-pptx` lacks native support for them. `pptxizza` solves this by utilizing modern Microsoft Open XML extension nodes to automatically parse, embed, and inject SVGs cleanly into your slides.

## Features

- **Object-Oriented Integrity**: Native interaction with shapes (`Shape`, `Rect`, `Circle`) and charts (`BarChart`, `PieChart`, etc.).
- **Programmatic Shape Insertion**: Generate and structure exact geometry auto-shapes or vector pictures dynamically from code.
- **Text Replacement**: Replace `{{mustache}}` template variables anywhere on a slide, or target specific named shapes.
- **Image Replacement**: Easily swap out placeholder images with `.png`, `.jpg`, or `.svg` files while preserving position and styling.
- **Chart & Table Data Binding**: Update the underlying data of native PowerPoint charts (`BarChart`, `PieChart`, `LineChart`) directly via their class objects.

## Installation

As this package is under development, you can use it locally by ensuring the package is in your `sys.path` or installing it in editable mode:

```bash
pip install -e .
```

Dependencies:
- `lxml`

## Quick Start (Templating)

The most robust way to use `pptxizza` is to create a template (`template.pptx`) with some named placeholders or `{{mustache_keys}}`, then parse it:

```python
from pptxizza import Presentation

def main():
    pres = Presentation("template.pptx")
    slide = pres.slides[0]

    # Fill the slide with dynamic content mapped to shape names
    slide.fill({
        "{{title}}": "Quarterly Business Review",  # Global mustache text replacement
        "SubtitleShape": "Q3 2026 Results",         # Named shape text replacement
        "LogoPlaceholder": "company_logo.svg"       # Named picture shape replacement (injects SVG!)
    })

    pres.save("output.pptx")

if __name__ == "__main__":
    main()
```

## Creating a Presentation from Scratch

If you just need a blank presentation without an existing template, you can initialize `Presentation` with no arguments.

```python
from pptxizza import Presentation

def main():
    # Calling Presentation() without an argument loads a default blank template
    pres = Presentation()
    
    # You can now add slides or insert shapes programmatically
    # ...
    
    pres.save("new_presentation.pptx")

if __name__ == "__main__":
    main()
```

## The Object-Oriented API (`pptxizza.shapes`)

`pptxizza` maps OpenXML structures directly into typed Python objects, allowing for programmatic instantiation and highly specific template discovery.

### 1. Generating & Inserting Shapes Programmatically

Instead of relying solely on existing templates, you can import granular geometric components from `pptxizza.shapes` to build slides from scratch!

```python
from pptxizza.shapes import Shape, Rect, Circle, Picture, Table
from pptxizza import Inches

slide = pres.slides[0]

# Create a primitive Rect shape with text
my_rect = Rect(text="Action Item", x=Inches(1), y=Inches(1), cx=Inches(3), cy=Inches(1))

# Create an Oval/Circle
my_circle = Circle(text="1", x=Inches(5), y=Inches(1), cx=Inches(1), cy=Inches(1))

# Create a Table (3 rows, 3 columns)
my_table = Table(rows=3, cols=3, x=Inches(1), y=Inches(3), cx=Inches(6), cy=Inches(1.5))

# Create an SVG Vector graphic dynamically
my_ufo = Picture(image_path="ufo.svg", x=Inches(3), y=Inches(5), cx=Inches(2), cy=Inches(2))

# Insert the objects natively. Background relation mapping is handled automatically!
slide.insert_shape(my_rect)
slide.insert_shape(my_circle)
slide.insert_shape(my_table)
slide.insert_shape(my_ufo)
```

_Note_: `x`, `y`, `cx`, and `cy` are tracked in English Metric Units (EMUs). All shapes also expose `x_inches`, `y_inches`, `width_inches`, and `height_inches` for easier visual math.

### 2. Inspecting and Manipulating Dynamic Shapes

`pptxizza` intelligently probes into the ZIP packages under the hood to detect exactly what's sitting on a template slide. When examining `slide.shapes`, generic graphic frames are dynamically resolved into explicit subclasses like `BarChart`, `PieChart`, or `LineChart`.

```python
for shape in slide.shapes:
    print(f"Discovered: {type(shape).__name__} named '{shape.shape_name}'")
    
    # You can access common underlying properties easily!
    shape.x_inches += 1.5  # shift everything right by 1.5 inches
```

### 3. Updating Chart Data via Shape Objects

When `slide.shapes` returns a chart class (e.g. `BarChart`, `PieChart`), you can call `.replace_data()` directly onto the object to overwrite its internal points caches.

```python
from pptxizza.shapes import BarChart

for shape in slide.shapes:
    if isinstance(shape, BarChart) and shape.shape_name == "SalesChart":
        categories = ["Jan", "Feb", "Mar"]
        data = {
            0: [150, 200, 250],        # Update series 0 by its index
            "Europe": [120, 180, 210]  # Update series by string name matching
        }
        
        # Inject seamlessly into the cache!
        shape.replace_data(data, categories)
```

### 4. Manipulating Tables

`Table` objects allow for granular cell access and styling using presets.

```python
from pptxizza.shapes import Table

for shape in slide.shapes:
    if isinstance(shape, Table):
        # Access cells by (row, col)
        shape.cell(0, 0).text = "Header 1"
        
        # Helper to set first row names
        shape.set_column_names(["ID", "Name", "Status"])
        
        # Add new rows or columns
        new_row = shape.add_row()
        new_row.cells[0].text = "001"
        
        # Apply visual presets
        shape.apply_preset("Medium Style 2 - Accent 1")
```

### 5. Styling and Rich Text

Most shapes support direct styling of fill and font properties. You can also use the `Text` and `Run` objects for rich text formatting.

```python
from pptxizza import RGBColor, HexColor, ThemeColor, Pt, Text

# Solid Fill
shape.fill.solid(HexColor("#4287f5"))

# Font Styling
shape.font.size = Pt(24)
shape.font.bold = True
shape.font.color = RGBColor(255, 255, 255)

# Rich Text with Runs
t = Text()
t.add_run("Normal text, ")
t.add_run("BOLD AND RED", bold=True, color=HexColor("FF0000"))
t.add_run(" and ", italic=True)
t.add_run("LARGE BLUE", size=Pt(40), color=ThemeColor("accent1"))

shape.text = t
```

## Advanced Native Image Support (SVG)

Native PowerPoint doesn't typically embed pure SVGs comfortably via older XML specifications. `pptxizza` utilizes modern Microsoft Open XML extension nodes natively mapping `a:svgBlip` relations to automatically parse, embed, and inject SVGs interchangeably with PNGs and JPGs!
