提供专业PDF处理方案,涵盖生成、表单填写与创建、合并拆分、水印加密及矢量排版。支持四种路径:快速内容生成、现有文档编辑、基于pdf-lib脚本的高级定制(含CJK字体)及HTML转换,确保满足从简单报告到复杂表单的专业需求。
Trigger Scenarios
Install
npx skills add spinabot/brigade --skill pdf -g -y
SKILL.md
Frontmatter
{
"name": "pdf",
"metadata": {
"brigade": {
"emoji": "📄"
}
},
"description": "Create and edit PDFs to a professional standard — generate from content, draw vector\/precise layouts, embed custom (incl. CJK\/Unicode) fonts, CREATE and fill AcroForm fields (text\/checkbox\/radio\/dropdown), flatten, merge\/split\/rotate, stamp\/watermark, encrypt, and extract text. Use when the user asks Brigade to make a PDF, fill or build a PDF form, or combine\/split\/stamp\/secure PDFs."
}
pdf — professional PDFs
| Need | Path |
|---|---|
| Simple content PDF (title, headings, paragraphs, image) | Path 1 — make_document tool |
| Fill an existing form, merge/split/stamp/watermark | Path 2 — edit_document tool |
| Form-field CREATION, vector drawing, embedded fonts (bold/CJK), precise layout, encryption, page surgery | Path 3 — script @cantoo/pdf-lib via brigade exec-node |
| Pixel-perfect, brand-styled layout from HTML/CSS | Path 4 — HTML→PDF (optional binary) |
Note: PDF is a final format with no reflow engine. If the recipient must edit, deliver the editable source (
.docx/.xlsx) and the PDF.
Path 1 — quick content PDF (make_document tool)
make_document(format="pdf", content={ title, pages:[{ heading, paragraphs, image:{path} }] })
Flow layout, US-Letter, single column, word-wrapped. Good for reports/summaries/letters. For forms, precise layout, or custom fonts → Path 3.
Path 2 — edit an existing PDF (edit_document tool)
fill_form {fields}— fill existing AcroForm fields by name (text/checkbox/dropdown).merge {pdfs}/add_pages {pdfs}·split {pages}·remove_pages {pages}.stamp {text}·watermark {text}(45° translucent).
Form decision: first detect whether the PDF has real fillable fields. If it does → fill them (clean, type-validated). If it's a flat/scanned form (no fields) → you must draw text at coordinates instead (Path 3, annotations) — never assume fields exist.
Path 3 — full power: script @cantoo/pdf-lib
Brigade bundles @cantoo/pdf-lib (a maintained pdf-lib fork — note the scoped name) plus @pdf-lib/fontkit (custom-font embedding) and unpdf (text extraction). write a gen.cjs, run brigade exec-node gen.cjs:
// gen.cjs — illustrative
const fs = require("node:fs");
const { PDFDocument, StandardFonts, rgb } = require("@cantoo/pdf-lib");
(async () => {
const pdf = await PDFDocument.create();
// embed a custom font (real bold / CJK / Unicode) — requires fontkit
// const fontkit = require("@pdf-lib/fontkit"); pdf.registerFontkit(fontkit);
// const font = await pdf.embedFont(fs.readFileSync("Brand-Bold.ttf"));
const font = await pdf.embedFont(StandardFonts.HelveticaBold);
const page = pdf.addPage([612, 792]); // US Letter; origin is BOTTOM-LEFT, y-up
page.drawText("Invoice", { x: 54, y: 720, size: 22, font, color: rgb(0.1, 0.1, 0.1) });
page.drawRectangle({ x: 54, y: 700, width: 504, height: 1, color: rgb(0.8, 0.8, 0.8) }); // vector rule
// CREATE fillable form fields
const form = pdf.getForm();
const name = form.createTextField("client.name");
name.addToPage(page, { x: 120, y: 640, width: 300, height: 18 });
const agree = form.createCheckBox("agree");
agree.addToPage(page, { x: 54, y: 600, width: 14, height: 14 });
// form.flatten(); // bake fields into static content if no further filling
fs.writeFileSync(process.argv[2] || "out.pdf", await pdf.save());
console.log("wrote");
})();
@cantoo/pdf-lib covers: draw text/lines/rects/ellipses/SVG paths/images; embed custom TTF/OTF fonts (subset, full Unicode); create AND fill AcroForm text/checkbox/radio/dropdown/option-list fields; flatten; copy/merge/split/rotate pages; metadata; password encryption (the reason this fork is bundled). Extract text/structure with unpdf.
Coordinate gotcha: pdf-lib origin is bottom-left, y-up. If you author field positions from a top-left image/spec, convert: y_pdf = pageHeight - y_top - height. One coordinate convention per script.
Path 4 — pixel-perfect / branded PDF from HTML+CSS (optional)
pdf-lib has no HTML/CSS layout engine — for a designed, brand-styled document, render HTML→PDF. Use whatever is present (detect first):
command -v soffice >/dev/null 2>&1 && soffice --headless --convert-to pdf brand.html # LibreOffice route
A headless browser (Puppeteer/Playwright page.pdf()) is the higher-fidelity alternative if installed. Prefer Path 1/3 unless the brand design genuinely requires CSS.
Conventions
- Use real AcroForm fields when filling a fillable PDF; only fall back to drawn-text annotations for flat/scanned forms.
- Embed a font for anything beyond basic Latin — standard PDF fonts lack bold-as-a-face and all CJK/emoji (missing glyphs render as boxes).
- Keep ≥0.5" margins; align to a grid; don't rely on text reflowing (there's no engine — you place it).
Verify (required)
Confirm the output exists and opens. For filled/created forms, re-open and read back the field values (or render to an image with soffice/a viewer and look at placement) before declaring done — never fill or place blind.
Version History
- db99206 Current 2026-07-05 10:59


