html-to-pptx — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited html-to-pptx (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Convert any single-file HTML slide deck into a .pptx file that looks exactly like the browser render — fonts, glows, gradients, animations frozen at their initial state.
fullPage: true screenshot → one tall PNGThis avoids all scroll/clip coordinate bugs — each slide is a guaranteed unique pixel crop.
Before running, verify these are available:
node + puppeteer npm package (installed locally or globally)python with pillow and python-pptx packagesYou need:
.pptx)Auto-detect Chrome from these paths (check in order):
C:/Program Files/Google/Chrome/Application/chrome.exeC:/Program Files (x86)/Google/Chrome/Application/chrome.exeC:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe/usr/bin/google-chrome/usr/bin/chromium-browser# Check
node -e "require('puppeteer')" 2>&1
# Install locally in the HTML file's directory if missing
npm install puppeteer --save-devWrite _screenshot.mjs to the same folder as the HTML:
import puppeteer from 'puppeteer';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const HTML_PATH = path.join(__dirname, '<HTML_FILENAME>');
const W = 1920;
const H = 1080;
const browser = await puppeteer.launch({
executablePath: '<CHROME_PATH>',
headless: true,
args: ['--no-sandbox', `--window-size=${W},${H}`],
});
const page = await browser.newPage();
await page.setViewport({ width: W, height: H, deviceScaleFactor: 1 });
await page.goto(`file:///${HTML_PATH.replace(/\\/g, '/')}`, {
waitUntil: 'networkidle0',
timeout: 30000,
});
// Wait for fonts and transitions to settle
await new Promise(r => setTimeout(r, 2500));
// Freeze animations, hide fixed UI chrome
await page.addStyleTag({ content: `
* { animation: none !important; transition: none !important; }
body::after { display: none !important; }
#nav, #progress, nav, header[data-fixed] { display: none !important; }
` });
await page.screenshot({
path: path.join(__dirname, '_fullpage.png'),
fullPage: true,
});
console.log('Done.');
await browser.close();Write _pack_pptx.py to the same folder:
from PIL import Image
from pptx import Presentation
from pptx.util import Inches
import os
FOLDER = r'<FOLDER_PATH>'
FULLPAGE = os.path.join(FOLDER, '_fullpage.png')
OUT = os.path.join(FOLDER, '<OUTPUT_FILENAME>')
SLIDES = <SLIDE_COUNT>
img = Image.open(FULLPAGE)
W, H = img.size
slide_h = H // SLIDES
print(f"Full image: {W}x{H}, {SLIDES} slides, {slide_h}px each")
prs = Presentation()
prs.slide_width = Inches(20) # 1920px at 96dpi
prs.slide_height = Inches(11.25) # 1080px at 96dpi
blank = prs.slide_layouts[6]
for i in range(SLIDES):
top = i * slide_h
crop = img.crop((0, top, W, top + slide_h))
tmp = os.path.join(FOLDER, f'_slide_{i+1:02d}.png')
crop.save(tmp)
slide = prs.slides.add_slide(blank)
slide.shapes.add_picture(tmp, left=0, top=0,
width=prs.slide_width,
height=prs.slide_height)
print(f" Slide {i+1:02d} rows {top}-{top+slide_h}")
prs.save(OUT)
print(f"Saved: {OUT}")node _screenshot.mjs
python _pack_pptx.pyAfter confirming the PPTX looks correct, delete:
_fullpage.png_screenshot.mjs_pack_pptx.py_slide_01.png … _slide_NN.png| Problem | Cause | Fix |
|---|---|---|
| All slides identical | Using clip:{y:0} on scrolled viewport | Always use fullPage:true + slice — never scroll |
| PermissionError on save | PPTX open in PowerPoint | Close the file first, or save to a new filename |
| Fonts wrong in PPTX | Custom web fonts not installed locally | This approach embeds pixel images so fonts are always correct |
| Slide count wrong | H // SLIDES rounding | Check H % SLIDES == 0; if not, slides have min-height inconsistency in HTML |
| Chrome not found | Wrong exe path | Check Edge as fallback |
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.