Initial commit: Hermes Agent Skills collection

This commit is contained in:
Debian
2026-07-12 19:02:59 +00:00
commit e9cc106625
789 changed files with 233126 additions and 0 deletions
@@ -0,0 +1,175 @@
#!/usr/bin/env python3
"""
Validate a .pptx file for PowerPoint compatibility.
Checks for issues that LibreOffice tolerates but PowerPoint rejects:
- Negative shape dimensions (cx, cy ≤ 0) in <a:ext> elements
- Negative shape positions (x, y < 0) in <a:off> elements
- Missing required OOXML parts ([Content_Types].xml, presentation.xml, etc.)
- Malformed XML in any part
- Broken relationship references (rId in slide XML not found in .rels)
- Missing Content_Type overrides for slides
Usage:
python3 validate_pptx_compat.py <file.pptx>
Exit codes:
0 = all checks passed
1 = issues found (printed to stderr)
"""
import sys
import zipfile
import xml.etree.ElementTree as ET
NS_A = "http://schemas.openxmlformats.org/drawingml/2006/main"
NS_P = "http://schemas.openxmlformats.org/presentationml/2006/main"
NS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
NS_REL = "{http://schemas.openxmlformats.org/package/2006/relationships}"
def validate(pptx_path: str) -> list[str]:
"""Return a list of issue strings; empty list means clean."""
issues = []
with zipfile.ZipFile(pptx_path, "r") as z:
# 1. Zip integrity
bad = z.testzip()
if bad:
issues.append(f"BAD ZIP ENTRY: {bad}")
# 2. XML parse check on all XML/rels parts
for name in z.namelist():
if name.endswith(".xml") or name.endswith(".rels"):
try:
ET.parse(z.open(name))
except ET.ParseError as e:
issues.append(f"XML PARSE ERROR in {name}: {e}")
# 3. Required parts
required = [
"[Content_Types].xml",
"_rels/.rels",
"ppt/presentation.xml",
"ppt/_rels/presentation.xml.rels",
"ppt/theme/theme1.xml",
]
for req in required:
if req not in z.namelist():
issues.append(f"MISSING REQUIRED PART: {req}")
# 4. Slide rels existence
slides = [
f for f in z.namelist()
if f.startswith("ppt/slides/slide") and f.endswith(".xml")
]
for s in sorted(slides):
rels = s.replace("ppt/slides/", "ppt/slides/_rels/") + ".rels"
if rels not in z.namelist():
issues.append(f"MISSING RELS for {s}")
# 5. Content_Type overrides for slides
ct = ET.parse(z.open("[Content_Types].xml"))
ct_ns = {"ct": "http://schemas.openxmlformats.org/package/2006/content-types"}
overrides = [
o.get("PartName") for o in ct.findall(".//ct:Override", ct_ns)
]
for s in sorted(slides):
part_name = "/" + s
if part_name not in overrides:
issues.append(f"Missing Content_Type override for {s}")
# 6. Negative dimensions and positions (THE key check)
for i in range(1, len(slides) + 1):
slide_path = f"ppt/slides/slide{i}.xml"
if slide_path not in z.namelist():
continue
root = ET.parse(z.open(slide_path)).getroot()
for sp in root.iter(f"{{{NS_P}}}sp"):
spPr = sp.find(f".//{{{NS_P}}}spPr")
if spPr is None:
continue
# Get shape name for reporting
cNvPr = sp.find(f".//{{{NS_P}}}cNvPr")
name = cNvPr.get("name", "?") if cNvPr is not None else "?"
xfrm = spPr.find(f"{{{NS_A}}}xfrm")
if xfrm is None:
continue
off = xfrm.find(f"{{{NS_A}}}off")
ext = xfrm.find(f"{{{NS_A}}}ext")
if ext is not None:
cx = int(ext.get("cx", "0"))
cy = int(ext.get("cy", "0"))
if cx <= 0 or cy <= 0:
issues.append(
f"slide{i}: shape \"{name}\" has zero/negative extent: "
f"cx={cx} cy={cy}"
)
if off is not None:
x = int(off.get("x", "0"))
y = int(off.get("y", "0"))
if x < 0 or y < 0:
issues.append(
f"slide{i}: shape \"{name}\" has negative position: "
f"x={x} y={y}"
)
# 7. Broken image embed references
for i in range(1, len(slides) + 1):
slide_path = f"ppt/slides/slide{i}.xml"
if slide_path not in z.namelist():
continue
root = ET.parse(z.open(slide_path)).getroot()
rels_path = f"ppt/slides/_rels/slide{i}.xml.rels"
if rels_path not in z.namelist():
continue
rels_tree = ET.parse(z.open(rels_path))
rels_root = rels_tree.getroot()
valid_rids = {
rel.get("Id") for rel in rels_root.findall(f"{NS_REL}Relationship")
}
for blip in root.iter(f"{{{NS_A}}}blip"):
embed = blip.get(f"{{{NS_R}}}embed")
if embed is not None and embed not in valid_rids:
issues.append(
f"slide{i}: blipFill embed '{embed}' not found in rels"
)
return issues
def main():
if len(sys.argv) != 2:
print("Usage: validate_pptx_compat.py <file.pptx>", file=sys.stderr)
sys.exit(2)
pptx_path = sys.argv[1]
try:
issues = validate(pptx_path)
except FileNotFoundError:
print(f"File not found: {pptx_path}", file=sys.stderr)
sys.exit(2)
except zipfile.BadZipFile:
print(f"Not a valid ZIP/PPTX file: {pptx_path}", file=sys.stderr)
sys.exit(2)
if issues:
print(f"{len(issues)} issue(s) found:", file=sys.stderr)
for iss in issues:
print(f"{iss}", file=sys.stderr)
sys.exit(1)
else:
print(f"{pptx_path}: all checks passed")
sys.exit(0)
if __name__ == "__main__":
main()