Metadata-Version: 2.4
Name: excalidraw-convert
Version: 0.1.0
Summary: Convert Excalidraw diagrams to PowerPoint or Lucid Package Format
Author: Lyndon Liang
License-Expression: MIT
Project-URL: Repository, https://github.com/lliang17/excalidraw-convert
Project-URL: Issues, https://github.com/lliang17/excalidraw-convert/issues
Keywords: excalidraw,powerpoint,pptx,diagram,convert
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Graphics :: Presentation
Classifier: Topic :: Office/Business :: Office Suites
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: python-pptx>=0.6.21
Requires-Dist: requests>=2.28.0
Requires-Dist: cryptography>=41.0.0
Requires-Dist: click>=8.0.0
Requires-Dist: Pillow>=10.0.0
Provides-Extra: svg
Requires-Dist: cairosvg>=2.7.0; extra == "svg"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Dynamic: license-file

# excalidraw-convert

Convert Excalidraw diagrams to **editable PowerPoint vector objects** or **Lucid Package Format** (`.lucid`).

---

## Features

### PowerPoint output

Each shape, arrow, and text box becomes a native PowerPoint object you can move, resize, recolour, and animate individually — not a flat image.

| Excalidraw element | PowerPoint output |
|---|---|
| Rectangle (with/without roundness) | Auto-shape (Rectangle / Rounded Rectangle) |
| Ellipse | Auto-shape (Oval) |
| Diamond | Auto-shape (Diamond) |
| Arrow (2-point) | Straight Connector with arrowheads |
| Line / Arrow (multi-point) | Freeform path |
| Freedraw | Freeform path (approximate) |
| Text (standalone) | Text Box |
| Text (bound to shape) | Text inside the parent shape |
| Image (PNG/JPEG/WEBP) | Embedded picture |
| Image (SVG) | PNG fallback _(requires `cairosvg`)_ |
| Frame | Separate slide |
| No frames | Single slide (whole canvas) |

### Lucid output

Produces a `.lucid` file (ZIP archive in [Lucid Package Format](https://lucid.readme.io/docs/overview-si)) that can be opened directly in LucidChart or LucidSpark.

| Excalidraw element | Lucid output |
|---|---|
| Rectangle (with/without roundness) | `rectangle` shape |
| Ellipse | `circle` shape |
| Diamond | `diamond` shape |
| Arrow / Line (2-point) | `elbow` line connector |
| Arrow / Line (multi-point) | `straight` line with intermediate joints |
| Freedraw | `flexiblePolygon` (downsampled to ≤100 vertices) |
| Text (standalone) | `text` shape |
| Text (bound to shape) | Text property on the parent shape |
| Image | `image` shape with file embedded in the archive |
| Frame | Separate page |
| No frames | Single page (whole canvas) |

### Styling carried over (both formats)

Fill colour, stroke colour, stroke width, dashed/dotted strokes, rounded corners, arrowhead types, opacity, background colour, multi-line text, font family, font size, and text alignment.

---

## Installation

```bash
pip install excalidraw-convert
```

For SVG image support in PowerPoint output (optional):
```bash
pip install "excalidraw-convert[svg]"
```

To install from source:
```bash
pip install -e ".[dev]"
```

---

## Usage

### Command line

```bash
# Convert to PowerPoint
excalidraw-convert convert "https://excalidraw.com/#json=<id>,<key>" -o output.pptx

# Convert to Lucid Package Format
excalidraw-convert convert-lucid "https://excalidraw.com/#json=<id>,<key>" -o output.lucid

# From a direct JSON / .excalidraw file URL
excalidraw-convert convert "https://raw.githubusercontent.com/you/repo/main/diagram.excalidraw" -o output.pptx

# Append slides to an existing presentation
excalidraw-convert convert "https://..." -o existing.pptx --embed

# Inspect a scene before converting
excalidraw-convert inspect "https://..."
```

Also callable as a module:
```bash
python -m excalidraw_convert convert "https://..." -o output.pptx
python -m excalidraw_convert convert-lucid "https://..." -o output.lucid
```

### Python API

```python
from excalidraw_convert import fetch_scene, convert, convert_to_lucid

scene = fetch_scene("https://excalidraw.com/#json=<id>,<key>")

# PowerPoint
convert(scene, "output.pptx")

# Lucid Package Format
convert_to_lucid(scene, "output.lucid")

# Append to an existing PowerPoint file
convert(scene, "existing.pptx", embed_path="existing.pptx")

# Custom slide dimensions (inches, new files only)
convert(scene, "output.pptx", slide_width=10, slide_height=7.5)
```

---

## Supported URL formats

| Format | Example |
|---|---|
| Excalidraw share link | `https://excalidraw.com/#json=abc123,base64key` |
| Raw `.excalidraw` file URL | `https://raw.githubusercontent.com/.../diagram.excalidraw` |
| Any URL returning JSON | `https://your-server.com/scene.json` |

> **Note on Excalidraw share links:** the scene is end-to-end encrypted in the browser. This tool replicates the AES-GCM decryption that the Excalidraw web app performs client-side. If decryption fails for a link, try exporting the scene as a `.excalidraw` file and hosting it somewhere accessible.

---

## Limitations / known gaps

### Both formats
- **Roughness / hand-drawn style**: Excalidraw's sketchy aesthetic is not reproduced — shapes are rendered as clean geometric shapes.
- **Hachure fill**: approximated as a solid fill.
- **Curved / elbow arrows**: rendered as straight connectors or straight segments.
- **`freedraw` pressures**: variable stroke-width pressure data is ignored; a fixed width is used.
- **Grouped elements**: group membership is preserved in rendering order but not as native groups.
- **Embeddable / iframe elements**: skipped with a warning.
- **Fonts**: Excalidraw's *Virgil* hand-drawn font is mapped to *Caveat* (install it for best results; falls back to the system default).

### PowerPoint only
- `freedraw` elements are rendered as freeform polygon paths (not true brush strokes).

### Lucid only
- `freedraw` elements are approximated as `flexiblePolygon` shapes with up to 100 sampled vertices.
- Arrow connection points snap to the nearest edge of the target shape.

---

## Development

```bash
pip install -e ".[dev]"
pytest tests/ -v
```
