html2pptx/SKILL.md
Convert HTML slides into native PowerPoint elements. Triggers: HTML to PPTX, convert HTML slides, html2pptx.
npx skillsauth add lidge-jun/cli-jaw-skills html2pptxInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Convert HTML slides into native PowerPoint elements with accurate positioning. Covers: HTML→native PPTX conversion (text, images, shapes, lists), screenshot fallback. For programmatic slide creation without HTML, see pptx skill.
| Task | Tool |
|------|------|
| Convert (native) | require("./scripts/html2pptx.cjs") — library, not CLI |
| Convert (screenshot) | node scripts/convert.mjs slide.html [output.pptx] [--layout 16x9\|4x3] |
| Batch convert | node scripts/batch.mjs slide-01.html slide-02.html [--output deck.pptx] [--layout 16x9\|4x3] |
HTML file → Playwright render → page.evaluate():
├── body background extraction (image/color)
├── DOM element traversal
│ ├── <div> + background/border → shape element
│ ├── <img> → image element
│ ├── <p>, <h1>-<h6> → text element + inline formatting
│ ├── <ul>, <ol> → bullet list element
│ └── .placeholder → { x, y, w, h } for addChart() etc.
└── validation (overflow, dimension mismatch)
→ PptxGenJS addText/addImage/addShape()
→ { slide, placeholders }
const pptxgen = require("pptxgenjs");
const html2pptx = require("./scripts/html2pptx.cjs");
(async () => {
const pres = new pptxgen();
pres.layout = "LAYOUT_16x9"; // must match HTML body dimensions
const { slide, placeholders } = await html2pptx("slide.html", pres);
if (placeholders.length > 0) {
slide.addChart(pres.charts.LINE, chartData, placeholders[0]);
}
await pres.writeFile({ fileName: "output.pptx" });
})();
const path = require("path");
const pptxgen = require("pptxgenjs");
const html2pptx = require("./scripts/html2pptx.cjs");
(async () => {
const pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
const slides = ["slide-01.html", "slide-02.html", "slide-03.html"];
for (const file of slides) {
await html2pptx(path.join(__dirname, file), pres);
}
await pres.writeFile({ fileName: "deck.pptx" });
})();
When CSS is too complex for native conversion:
node scripts/convert.mjs slide.html output.pptx
Renders HTML as a full-page screenshot embedded as a single image. Tradeoff: pixel-perfect visuals, but text is not selectable/editable.
<body> must have explicit width and height matching the presentation layout:
width: 960px; height: 540px (10" × 5.625" at 96 DPI)width: 960px; height: 720px (10" × 7.5" at 96 DPI)<p>, <h1>–<h6>, <ul>, or <ol> — bare text in <div> is silently dropped| CSS Property | PPTX Mapping | Notes |
|-------------|-------------|-------|
| background-color | shape fill | On <div> only |
| border (uniform) | shape line | Same width all 4 sides |
| border (partial) | line shapes | Individual lines per side |
| border-radius | rectRadius | px, pt, or % |
| box-shadow | shadow prop | Outer only |
| transform: rotate() | rotate prop | Degrees, matrix parsed |
| writing-mode | 90°/270° | vertical-rl = 90° |
| text-transform | applied directly | uppercase, lowercase, capitalize |
| <b>, <strong> | bold: true | |
| <i>, <em> | italic: true | |
| <u> | underline: true | |
| CSS Property | Workaround |
|-------------|-----------|
| CSS gradients | Rasterize to PNG with Sharp |
| Background images on <div> | Use <img> or slide-level background |
| box-shadow: inset | Not supported in PowerPoint |
| Margins on inline <span> | Use padding on parent |
| Bare text in <div> | Wrap in <p> or heading tags |
Add class="placeholder" to extract position without rendering:
<div class="placeholder" id="chart-area"
style="position: absolute; left: 100px; top: 200px; width: 400px; height: 300px;">
</div>
Returns: { id: "chart-area", x: 1.04, y: 2.08, w: 4.17, h: 3.12 }
Use coordinates to place charts, external images, or other programmatic content.
| Check | Error Pattern | |-------|--------------| | Content overflow | "HTML content overflows body by Xpt..." | | Dimension mismatch | "HTML dimensions don't match presentation layout..." | | Text too close to bottom | "Text box ends too close to bottom edge..." | | CSS gradients | "CSS gradients are not supported..." | | Background images on div | "Background images on DIV elements..." | | Bare text in div | "DIV element contains unwrapped text..." | | Styling on text elements | "Text element has background/border/shadow..." | | Manual bullet symbols | "Text element starts with bullet symbol..." | | Margins on inline spans | "Inline element has margin-left..." |
All errors are collected and thrown together.
| Instead of... | Do this | Why |
|--------------|---------|-----|
| Bare text in <div> | Wrap in <p>, <h1>–<h6>, <ul> | Bare text is silently dropped |
| Background/border on <p>, <h> | Move styling to parent <div> | Only <div> maps to PPTX shapes |
| CSS gradients | Rasterize to PNG first | No PPTX gradient equivalent |
| Manual bullet chars (• Item) | Use <ul><li>Item</li></ul> | Proper PPTX bullets with indentation |
| Margins on <span> | Use padding on parent | Inline margins ignored in PowerPoint |
| Omitting body width/height | Set explicit dimensions | Converter can't infer slide size |
npm install pptxgenjs playwright sharp
npx playwright install chromium
On macOS, convert.mjs/html2pptx.cjs use channel: "chrome" (system Chrome). If Chrome is unavailable, remove launchOptions.channel to use Playwright's bundled Chromium.
# 1. Convert
node scripts/batch.mjs slide-*.html --output deck.pptx
# 2. Visual check
soffice --headless --convert-to pdf deck.pptx
pdftoppm -jpeg -r 150 deck.pdf slide
# 3. Compare HTML vs PPTX output side-by-side
Checklist:
development
Goal execution guidelines with PABCD integration, verification tiers, documentation workflow, and AI-driven planning
tools
A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
development
Use this skill any time a spreadsheet file is the primary input or output (.xlsx, .xlsm, .csv, .tsv). This includes: creating, reading, editing, analyzing, or formatting spreadsheets; cleaning messy tabular data; converting between formats; and data visualization with charts. Also use for pandas-based data analysis when the deliverable is a spreadsheet. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration.
tools
Use this skill when the user wants to build a financial model, 3-statement model, DCF valuation, cap table, scenario analysis, or financial projections in Excel. Trigger on: 'financial model', '3-statement model', 'DCF', 'cap table', 'pro forma', 'projections', 'sensitivity analysis', 'waterfall', 'debt schedule', 'break-even', 'discounted cash flow', 'capitalization table', 'fundraising model', 'WACC calculation', 'scenario analysis model'. Input is a text prompt with assumptions. Output is a single .xlsx file with formula-driven, interconnected statement sheets.