#!/usr/bin/env python3 """Compile current-page SVG sources with a separate released template, locally.""" from __future__ import annotations import argparse import base64 import importlib.util import json import os from pathlib import Path import re import sys import tempfile from urllib.parse import unquote, urlsplit import xml.etree.ElementTree as ET import template_ref as ref SVG = "http://www.w3.org/2000/svg" ET.register_namespace("", SVG) DEPENDENCIES = {"python-pptx": "pptx", "lxml": "lxml", "Pillow": "PIL", "XlsxWriter": "xlsxwriter", "typing_extensions": "typing_extensions", "defusedxml": "defusedxml", "numpy": "numpy", "openpyxl": "openpyxl", "et_xmlfile": "et_xmlfile"} def regular(path: Path, label: str, *, directory=False) -> Path: path = Path(os.path.abspath(path)) ref.require(not any(item.is_symlink() for item in (path, *path.parents)), f"{label}: symlinks forbidden") ref.require(path.is_dir() if directory else path.is_file(), f"{label}: missing {'directory' if directory else 'file'}: {path}") return path def boundary_file(root: Path, value: str, label: str) -> Path: ref.local_path(root, value, label) return regular(root / value, label) def runtime_root() -> Path: # The installed Skill and a prepared portable project both keep scripts/ # adjacent to runtime/. No machine path or other installed Skill is read. root = Path(__file__).resolve().parent.parent / "runtime/ppt-master" regular(root / "scripts/attribution_guard.py", "bundled attribution guard") return root def load_compiler(): if sys.version_info < (3, 12): raise ValueError("Native compiler requires Python 3.12+; metadata-only project commands require Python 3.10+") missing = [name for name, module in DEPENDENCIES.items() if importlib.util.find_spec(module) is None] if missing: raise ValueError("Native compiler dependencies missing: " + ", ".join(missing) + "; provision runtime/requirements.txt using the installation environment") sys.path.insert(0, str(runtime_root() / "scripts")) from attribution_guard import require_skill_integrity require_skill_integrity() from svg_to_pptx.pptx_package.builder import create_pptx_with_native_svg from svg_to_pptx.drawingml.theme_fonts import MasterTextStyleSpec from finalize_theme import finalize, typography, verify, preserve_declared_font_families return create_pptx_with_native_svg, MasterTextStyleSpec, finalize, typography, verify, preserve_declared_font_families def prepare_svg(source: Path, target: Path, allowed: Path): regular(source, "SVG source") ref.require(source.is_relative_to(allowed), "SVG source is outside its declared resource boundary") text = source.read_text(encoding="utf-8") ref.require(not re.search(r"