Add infra-ops-toolkit plugin: topology diagram, html-to-pdf, teleport onboarding skills

Distills patterns from the Teleport access topology work: verified-data diagram
building, as-displayed HTML-to-PDF export via headless Chromium, and
container-scoped/host/database onboarding into an existing Teleport cluster.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R3ZTfgQrkR3q8DSEoZAmvs
This commit is contained in:
2026-09-08 16:11:36 +07:00
parent f2b97d4820
commit 98dca237f4
8 changed files with 327 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
---
name: html-to-pdf
description: Export a local HTML file to a PDF that looks exactly like the live browser rendering — no shrink-to-fit distortion, no forced page splits, no vanished sticky/grid elements. Use when the user says a browser's own Print-to-PDF/Print dialog produced a broken, tiny, or wrongly-paginated result and they want the PDF "as-is / seperti yang tampil di browser" instead of a print-reflowed version.
---
# HTML → PDF, exactly as displayed
## Why the browser's own Print dialog fails for this
A system print dialog always targets a **fixed paper size** (Letter/A4). For any page wider than ~800px of real content — a multi-column CSS Grid layout, a wide diagram — the browser either shrinks the *entire* page to fit one sheet (readable content becomes a postage stamp) or splits it across pages in ways that don't match what's on screen. Two extra failure modes compound this:
- `position: sticky` elements often just vanish or mis-render under the print media type.
- If the page has its own `@media print` rules (e.g. for a *deliberately* paginated print layout), those override the normal on-screen styling — which is the opposite of what "as-is" means here.
Neither "no print CSS at all" nor "add print CSS to force page-breaks" gives you the *live browser view* as a PDF. The actual fix is to render with a **page size equal to the content's own dimensions**, which no manual print dialog lets you set.
## The fix: headless Chromium in screen mode, content-sized page
```bash
mkdir -p /tmp/pdfgen && cd /tmp/pdfgen
npm init -y >/dev/null 2>&1
npm install puppeteer # bundles a compatible Chromium — no separate browser install needed
```
```js
// render.js
const puppeteer = require('puppeteer');
const path = require('path');
(async () => {
const srcPath = '/absolute/path/to/source.html';
const outPath = '/absolute/path/to/output.pdf';
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Match the viewport width the page's CSS was actually designed around
// (check its max-width / .page container, not an arbitrary guess).
await page.setViewport({ width: 1940, height: 1200, deviceScaleFactor: 2 });
await page.goto('file://' + srcPath, { waitUntil: 'networkidle0' });
// The critical line: force normal on-screen styles, ignoring any
// @media print rules the page might define for its own purposes.
await page.emulateMediaType('screen');
// Measure the real rendered size so the PDF page is exactly that size —
// one continuous page, nothing scaled, nothing split.
const { width, height } = await page.evaluate(() => {
const el = document.querySelector('.page') || document.body;
const rect = el.getBoundingClientRect();
return { width: Math.ceil(rect.width), height: Math.ceil(document.documentElement.scrollHeight) };
});
await page.pdf({
path: outPath,
width: `${width}px`,
height: `${height}px`,
printBackground: true, // otherwise CSS background colors silently disappear
margin: { top: 0, right: 0, bottom: 0, left: 0 },
});
await browser.close();
console.log('Saved:', outPath, width, 'x', height);
})().catch(err => { console.error(err); process.exit(1); });
```
```bash
node render.js
```
## Notes
- `printBackground: true` is easy to forget and its absence is easy to misdiagnose as "the PDF looks washed out" rather than "backgrounds are just missing."
- If the page measures its own scroll height *before* web fonts finish loading, dimensions can be slightly off — `waitUntil: 'networkidle0'` on `goto` covers most cases; add an explicit `page.evaluateHandle('document.fonts.ready')` await first if fonts still look unloaded in the output.
- This same technique works for any "I want the PDF to look like the page, not like a printout" request — it's not specific to any one diagram or document.
- Verify the result before calling it done: read the generated PDF back (most tools can render/preview a PDF's first page) and compare it against the live browser view side by side, don't just trust that `page.pdf()` succeeded without error.