Token导航 LogoToken导航TokenDH.com
前端设计操作浏览器github未标认证来源可访问许可证需确认审计提醒

document-generation-pdfdocument generation PDF 命令行

Agent Skill

document-generation-pdf 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

372

周安装

16

GitHub Stars

98

下载量

131
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:document-generation-pdf(document generation PDF 命令行)
来源仓库:https://github.com/curiositech/some_claude_skills
仓库路径:skills/document-generation-pdf
安装命令:
npx skills add https://github.com/curiositech/some_claude_skills --skill document-generation-pdf
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/curiositech/some_claude_skills --skill document-generation-pdf

简介

document-generation-pdf 专用于法律表单、发票证书等业务流程的程序化生成与组装。

  • 支持法律表格自动化(消案/移民/合同)、政府文件填写(IRS/法院)等多场景。
  • 提供模板填充、多文档打包和批量生成能力,适用于 HR 与商务工作流程。
  • 使用时需确保模板合法合规,避免生成误导性或违法的文件内容。
  • 不处理 PDF 查看、基础转换或 OCR 文字提取等简单操作需求。

SKILL.md

Document Generation & PDF Automation

Expert in generating, filling, and assembling PDF documents programmatically for legal, HR, and business workflows.

When to Use

Use for:

  • Legal form automation (expungement, immigration, contracts)
  • Invoice/receipt generation at scale
  • Certificate creation (completion, participation, awards)
  • Contract assembly from templates
  • Government form filling (IRS, court filings)
  • Multi-document packet creation

NOT for:

  • Simple PDF viewing (use browser or pdf.js)
  • Basic file conversion (use online tools)
  • OCR text extraction (use Tesseract.js or AWS Textract)
  • PDF editing by hand (use Adobe Acrobat)

Technology Selection

pdf-lib vs Puppeteer vs LaTeX

Featurepdf-libPuppeteerLaTeX
Form filling✅ Native❌ Complex❌ No
Template rendering❌ No✅ HTML/CSS✅ Templates
Performance (1000 PDFs)5s60s30s
File sizeSmallMediumSmall
Signature fields✅ Yes❌ No❌ No
Best forGovernment formsInvoices, reportsAcademic papers

Timeline:

  • 2000s: LaTeX for academic documents
  • 2010: PDFKit (Node.js) for generation
  • 2017: Puppeteer for HTML → PDF
  • 2019: pdf-lib for pure JS form filling
  • 2024: pdf-lib is gold standard for forms

Decision tree:

Need to fill existing form? → pdf-lib
Need complex layouts? → Puppeteer (HTML/CSS)
Need academic formatting? → LaTeX
Need to merge PDFs? → pdf-lib
Need digital signatures? → pdf-lib + DocuSign API

Common Anti-Patterns

Anti-Pattern 1: Using Puppeteer for Simple Form Filling

Novice thinking: "I'll use Puppeteer for everything, it's versatile"

Problem: 12x slower, 10x more memory, can't preserve form fields.

Wrong approach:

// ❌ Puppeteer for simple form filling (SLOW!)
import puppeteer from 'puppeteer';

async function fillForm(data: FormData): Promise<Buffer> {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  // Load PDF in browser
  await page.goto(`file://${pdfPath}`);

  // Somehow fill form fields? (hacky)
  await page.evaluate((data) => {
    // Can't easily access PDF form fields from DOM
    // Would need to convert PDF → HTML first
  }, data);

  const pdf = await page.pdf();
  await browser.close();

  return pdf;
}

Why wrong:

  • Browser overhead (200MB+ RAM per instance)
  • Can't access native PDF form fields
  • Loses interactive form capabilities
  • 12x slower than pdf-lib

Correct approach:

// ✅ pdf-lib for form filling (FAST!)
import { PDFDocument } from 'pdf-lib';

async function fillForm(templatePath: string, data: FormData): Promise<Uint8Array> {
  // Load existing PDF form
  const existingPdfBytes = await fs.readFile(templatePath);
  const pdfDoc = await PDFDocument.load(existingPdfBytes);

  // Get form
  const form = pdfDoc.getForm();

  // Fill text fields
  form.getTextField('applicant_name').setText(data.name);
  form.getTextField('case_number').setText(data.caseNumber);
  form.getTextField('date_of_birth').setText(data.dob);

  // Fill checkboxes
  if (data.hasPriorConvictions) {
    form.getCheckBox('prior_convictions').check();
  }

  // Fill dropdowns
  form.getDropdown('state').select(data.state);

  // Flatten form (make non-editable)
  form.flatten();

  // Save
  return await pdfDoc.save();
}

Performance comparison (1000 PDFs):

  • Puppeteer: 60 seconds, 4GB RAM
  • pdf-lib: 5 seconds, 200MB RAM

Timeline context:

  • 2017: Puppeteer released, everyone used it for PDFs
  • 2019: pdf-lib released, proper form handling
  • 2024: pdf-lib is standard for government forms

Anti-Pattern 2: Not Flattening Forms

Problem: Users can edit filled forms, causing data inconsistencies.

Wrong approach:

// ❌ Don't flatten - form stays editable
const pdfDoc = await PDFDocument.load(existingPdfBytes);
const form = pdfDoc.getForm();

form.getTextField('name').setText('John Doe');

const pdfBytes = await pdfDoc.save();
// User can open PDF and change "John Doe" to anything!

Why wrong:

  • User can modify official documents
  • Data doesn't match database
  • Violates document integrity

Correct approach:

// ✅ Flatten form after filling
const pdfDoc = await PDFDocument.load(existingPdfBytes);
const form = pdfDoc.getForm();

form.getTextField('name').setText('John Doe');

// Flatten (convert fields to static text)
form.flatten();

const pdfBytes = await pdfDoc.save();
// User can't edit filled values ✅

When NOT to flatten:

  • Draft documents (user needs to review/edit)
  • Multi-step workflows (partial completion)
  • Templates for users to fill manually

Anti-Pattern 3: Generating PDFs from HTML Without Page Breaks

Novice thinking: "HTML → PDF is easy with Puppeteer"

Problem: Content splits mid-sentence across pages.

Wrong approach:

// ❌ No page break control
const html = `
  <div class="contract">
    <h1>Mutual Agreement</h1>
    <p>Long paragraph that might split across pages...</p>
    <section>
      <h2>Terms and Conditions</h2>
      <ol>
        <li>Term 1 that could get cut off...</li>
        <li>Term 2...</li>
      </ol>
    </section>
  </div>
`;

const pdf = await page.pdf({ format: 'A4' });
// Result: Ugly page breaks in middle of sections

Correct approach:

// ✅ Explicit page break control with CSS
const html = `
  <style>
    @media print {
      .page-break { page-break-after: always; }
      .avoid-break { page-break-inside: avoid; }

      h1, h2, h3 {
        page-break-after: avoid;
        page-break-inside: avoid;
      }

      section {
        page-break-inside: avoid;
      }
    }
  </style>

  <div class="contract">
    <section class="avoid-break">
      <h1>Mutual Agreement</h1>
      <p>This entire section stays together...</p>
    </section>

    <div class="page-break"></div>

    <section class="avoid-break">
      <h2>Terms and Conditions</h2>
      <ol>
        <li>Term 1</li>
        <li>Term 2</li>
      </ol>
    </section>
  </div>
`;

const pdf = await page.pdf({
  format: 'A4',
  printBackground: true,
  margin: {
    top: '1in',
    right: '1in',
    bottom: '1in',
    left: '1in'
  }
});

CSS print properties:

  • page-break-before: always - Force new page before element
  • page-break-after: always - Force new page after element
  • page-break-inside: avoid - Keep element together

Anti-Pattern 4: Not Handling Signature Fields

Problem: Signature fields aren't clickable in generated PDFs.

Wrong approach:

// ❌ Add signature as image (not a real signature field)
const pdfDoc = await PDFDocument.load(existingPdfBytes);

const signatureImage = await pdfDoc.embedPng(signaturePngBytes);
const page = pdfDoc.getPage(0);

page.drawImage(signatureImage, {
  x: 100,
  y: 100,
  width: 200,
  height: 50
});

await pdfDoc.save();
// Not a real signature field - can't be signed digitally

Why wrong:

  • Not legally recognized (just an image)
  • Can't use DocuSign/Adobe Sign
  • No signature metadata (who, when)

Correct approach 1: Create signature field (for DocuSign)

// ✅ Create signature field for electronic signing
const pdfDoc = await PDFDocument.load(existingPdfBytes);
const form = pdfDoc.getForm();

// Create signature field
const signatureField = form.createTextField('applicant_signature');
signatureField.addToPage(pdfDoc.getPage(0), {
  x: 100,
  y: 100,
  width: 200,
  height: 50
});

// Mark as signature field (metadata)
signatureField.updateWidgets({
  borderWidth: 1,
  borderColor: { type: 'RGB', red: 0, green: 0, blue: 0 }
});

await pdfDoc.save();
// DocuSign can now detect and fill this field ✅

Correct approach 2: DocuSign API integration

// ✅ Send to DocuSign for e-signature
import { ApiClient, EnvelopesApi } from 'docusign-esign';

async function sendForSignature(pdfBytes: Uint8Array, signerEmail: string) {
  const apiClient = new ApiClient();
  apiClient.setBasePath('https://demo.docusign.net/restapi');

  const envelopesApi = new EnvelopesApi(apiClient);

  const envelope = {
    emailSubject: 'Please sign: Expungement Petition',
    documents: [{
      documentBase64: Buffer.from(pdfBytes).toString('base64'),
      name: 'Petition.pdf',
      fileExtension: 'pdf',
      documentId: '1'
    }],
    recipients: {
      signers: [{
        email: signerEmail,
        name: 'John Doe',
        recipientId: '1',
        tabs: {
          signHereTabs: [{
            documentId: '1',
            pageNumber: '1',
            xPosition: '100',
            yPosition: '100'
          }]
        }
      }]
    },
    status: 'sent'
  };

  return await envelopesApi.createEnvelope(accountId, { envelopeDefinition: envelope });
}

Anti-Pattern 5: Storing Filled PDFs Without Encryption

Problem: Sensitive legal documents stored in plain text.

Wrong approach:

// ❌ Save PDF to disk unencrypted
const pdfBytes = await pdfDoc.save();
await fs.writeFile(`./documents/${caseId}.pdf`, pdfBytes);
// Sensitive data accessible to anyone with file system access

Why wrong:

  • Legal/medical data exposed
  • HIPAA/GDPR violations
  • Data breach liability

Correct approach 1: Encrypt at rest

// ✅ Encrypt PDF with user password
const pdfBytes = await pdfDoc.save({
  userPassword: generateSecurePassword(),
  ownerPassword: process.env.PDF_OWNER_PASSWORD,
  permissions: {
    printing: 'highResolution',
    modifying: false,
    copying: false,
    annotating: false,
    fillingForms: false,
    contentAccessibility: true,
    documentAssembly: false
  }
});

await fs.writeFile(`./documents/${caseId}.pdf`, pdfBytes);

Correct approach 2: Store in encrypted storage (S3 with SSE)

// ✅ Upload to S3 with server-side encryption
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';

const s3Client = new S3Client({ region: 'us-east-1' });

await s3Client.send(new PutObjectCommand({
  Bucket: 'expungement-documents',
  Key: `cases/${caseId}/petition.pdf`,
  Body: pdfBytes,
  ServerSideEncryption: 'AES256',
  Metadata: {
    caseId: caseId,
    documentType: 'petition',
    generatedAt: new Date().toISOString()
  },
  ACL: 'private'  // Not publicly accessible
}));

// Store S3 URL in database (encrypted)
await db.documents.insert({
  case_id: caseId,
  s3_url: encrypt(`s3://expungement-documents/cases/${caseId}/petition.pdf`),
  created_at: new Date()
});

Compliance requirements:

  • HIPAA: Encryption at rest + in transit, access logging
  • GDPR: Right to deletion, data minimization
  • State bar rules: Attorney-client privilege protection

Production Checklist

□ Form fields filled correctly (test with validation)
□ Forms flattened after filling (non-editable)
□ Page breaks controlled (no mid-sentence splits)
□ Signature fields created (for DocuSign/Adobe Sign)
□ PDFs encrypted at rest (S3 SSE or user password)
□ Access logged (who viewed/downloaded)
□ Auto-deletion scheduled (retention policy)
□ Fonts embedded (cross-platform compatibility)
□ File size optimized (<5MB per document)
□ Batch generation tested (1000+ PDFs)

When to Use vs Avoid

ScenarioAppropriate?
Fill 50+ government forms✅ Yes - automate with pdf-lib
Generate invoices from template✅ Yes - Puppeteer from HTML
Create certificates at scale✅ Yes - pdf-lib or LaTeX
Assemble multi-doc packets✅ Yes - pdf-lib merge
View PDFs in browser❌ No - use pdf.js or browser
Edit PDF by hand❌ No - use Adobe Acrobat
Extract text with OCR❌ No - use Tesseract/Textract

Flat PDF Overlay at Scale (Government Forms)

Many government court forms are flat PDFs (no fillable fields). You MUST overlay text at precise X,Y coordinates. Never generate forms from scratch - courts will reject them.

The Three-Tier Strategy

1. FILLABLE PDF → Use form.getTextField().setText() (best)
2. FLAT PDF + COORDINATES → Draw text overlays at X,Y positions (this section)
3. NO TEMPLATE EXISTS → Emergency fallback with warning banner (worst)

Anti-Pattern 6: Generating Forms from Scratch

Novice thinking: "The PDF doesn't have form fields, I'll just create a new PDF"

Problem: Courts reject non-official forms. Your custom layout won't match official documents.

Wrong approach:

// ❌ NEVER DO THIS - courts reject custom forms
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage([612, 792]);

page.drawText('IN THE CIRCUIT COURT OF...', { x: 200, y: 720 });
page.drawText(`Defendant: ${data.name}`, { x: 100, y: 600 });
// Result: Court clerk says "This isn't our form" and rejects filing

Correct approach: Draw on top of official template

// ✅ Load official form, draw text in blank spaces
const templateBytes = await fs.readFile('public/forms/OR-set-aside-motion.pdf');
const pdfDoc = await PDFDocument.load(templateBytes);
const page = pdfDoc.getPage(3); // Page 4 is the form
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);

// Draw in blank spaces at measured coordinates
page.drawText(data.county.toUpperCase(), { x: 310, y: 700, size: 11, font });
page.drawText(data.caseNumber, { x: 432, y: 655, size: 10, font });
page.drawText(data.fullName, { x: 72, y: 568, size: 11, font });

Measuring Coordinates at Scale

Problem: Manually measuring X,Y for 50 states × 10+ forms = impossible.

Solution 1: Visual Coordinate Picker Tool

Use pdf-coordinates - click on PDF to capture X,Y:

  • Upload PDF, click on blank fields
  • Select coordinate system: Bottom-Left (PDF standard)
  • Export annotated PDF with coordinate labels
  • Works offline, no data upload

Solution 2: JSON Configuration (Zerodha Pattern)

Define coordinates in JSON config, not code:

// field-mappings/oregon-set-aside.json
{
  "templatePath": "/forms/or/OR-criminal-set-aside.pdf",
  "pageIndex": 3,
  "fields": [
    {
      "name": "county",
      "x": 310,
      "y": 700,
      "fontSize": 11,
      "maxWidth": 120,
      "transform": "uppercase"
    },
    {
      "name": "caseNumber",
      "x": 432,
      "y": 655,
      "fontSize": 10,
      "maxWidth": 100,
      "maxChars": 12
    },
    {
      "name": "fullName",
      "x": 72,
      "y": 568,
      "fontSize": 11,
      "maxWidth": 250,
      "shrinkToFit": true
    }
  ]
}

Solution 3: Debug Grid Overlay

Add temporary grid during development:

async function drawDebugGrid(page: PDFPage, font: PDFFont) {
  const { width, height } = page.getSize();

  // Draw grid every 50 points
  for (let x = 0; x <= width; x += 50) {
    page.drawLine({
      start: { x, y: 0 },
      end: { x, y: height },
      thickness: 0.2,
      color: rgb(0.9, 0.9, 0.9),
    });
    if (x % 100 === 0) {
      page.drawText(String(x), { x: x + 2, y: 5, size: 6, font });
    }
  }
  // Same for horizontal lines...
}

Text Overflow Handling

Problem: Long names overflow into adjacent fields or get cut off.

Three overflow strategies:

// 1. Truncate with ellipsis
function truncate(text: string, maxChars: number): string {
  if (text.length <= maxChars) return text;
  return text.slice(0, maxChars - 2) + '..';
}

// 2. Shrink font to fit (min 7pt for readability)
function shrinkToFit(text: string, maxWidthPts: number, startSize: number): number {
  let fontSize = startSize;
  const charWidth = (size: number) => size * 0.52; // Helvetica avg

  while (fontSize > 7 && text.length * charWidth(fontSize) > maxWidthPts) {
    fontSize -= 0.5;
  }
  return fontSize;
}

// 3. Multi-line wrap (for addresses)
page.drawText(longAddress, {
  x: 100,
  y: 500,
  size: 9,
  font,
  maxWidth: 200, // pdf-lib auto-wraps at this width
  lineHeight: 12,
});

Field input constraints - Prevent overflow at data collection:

export const FIELD_CONSTRAINTS = {
  fullName: { maxLength: 35 },
  county: { maxLength: 12 },
  caseNumber: { maxLength: 12 },
  agency: { maxLength: 28 },
  charges: { maxLength: 45 },
} as const;

Production Workflow for Multi-State Forms

1. DOWNLOAD official forms
   └─ Store in /public/forms/{state}/ with metadata.json

2. INSPECT each form
   └─ Run pdf-lib inspection to check: fillable? how many fields?

3. CATEGORIZE forms
   ├─ Fillable → Map field names in field-mappings/{state}.ts
   └─ Flat → Measure coordinates with pdf-coordinates tool

4. CREATE JSON config for flat PDFs
   └─ One JSON file per form with all X,Y coordinates

5. TEST with debug grid
   └─ Generate test PDF with colored text + coordinate labels

6. QA visual verification
   └─ Compare filled PDF against original blank form

7. DOCUMENT constraints
   └─ Export maxLength/maxWidth limits for form inputs

Legal Filing Requirements

Court e-filing systems require:

  • ✅ Flattened forms (no interactive fields)
  • ✅ No digital signature metadata (DocuSign breaks e-filing)
  • ✅ Standard fonts embedded (Helvetica, Times)
  • ✅ File under 10MB
  • ✅ Exact match to official form layout

Flattening for courts:

// If form had fields, flatten them
const form = pdfDoc.getForm();
if (form.getFields().length > 0) {
  form.flatten(); // Converts to static text
}

// For overlay text, it's already static - no flattening needed
const pdfBytes = await pdfDoc.save();

Coordinate System Reference

PDF coordinate system (pdf-lib default):
- Origin: Bottom-left corner (0, 0)
- X increases: Left → Right
- Y increases: Bottom → Top
- Units: Points (72 points = 1 inch)
- Letter size: 612 x 792 points (8.5" x 11")

To convert from top-left origin (e.g., Adobe Acrobat display):
  y_pdf = 792 - y_topLeft

Common positions (Letter size):
- Top margin: y = 720-750
- Header area: y = 700-750
- Body start: y = 650-700
- Left margin: x = 50-72
- Right edge: x = 540-560
- Bottom margin: y = 50-72

References

  • /references/pdf-lib-guide.md - Form filling, field types, flattening, encryption
  • /references/puppeteer-templates.md - HTML templates, page breaks, styling for print
  • /references/document-assembly.md - Merging PDFs, packet creation, watermarks
  • pdf-coordinates - Visual X,Y coordinate picker
  • Zerodha pdf_text_overlay - JSON config pattern

Scripts

  • scripts/form_filler.ts - Fill PDF forms from JSON data, batch processing
  • scripts/document_assembler.ts - Merge multiple PDFs, add cover pages, watermarks
  • scripts/generate-test-overlay-pdf.ts - Test overlay coordinates with debug grid

This skill guides: PDF generation | Form filling | Document automation | Digital signatures | pdf-lib | Puppeteer | LaTeX | DocuSign | Flat PDF overlay | Coordinate mapping

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

32.45%
按下载量换算43

Claude

30.85%
按下载量换算40

Cursor

19.25%
按下载量换算25

Gemini CLI

8.92%
按下载量换算12

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills