pdf-operations
Skill0 starsChanged 30 days agoMITView on GitHub
Use when working on PDF manipulation in this repo — merging multiple PDFs into one, splitting a PDF into pages, extracting/reordering pages, rotating pages, or drawing overlays. Points to the existing pdf-lib pipeline instead of reimplementing it.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- adrianotomasoni/skillstheir own version, first seen Jun 28, 2026
- michaelwjames/skillsettheir own version, first seen Nov 16, 2025
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- adrianotomasoni/skills★ 1same name
- michaelwjames/skillset★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository8 other files it gives its agents.
- dependency-vuln-explainerSkill
- design-coreSkill
- design-flowSkill
- doc-style-builderSkill
- poc-spec-driven-builderSkill
- podman-disk-reclaimSkill
- prompt-cache-kitSkill
- thai-mock-namingSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 8
All PDF manipulation here runs client-side with pdf-lib + pdfjs-dist.
- Distinctive: line 32
If you need a *headless* merge (no workspace/UI involved — e.g.
- Very specific: line 53
Use isolatePdfPages in src/features/workspace/import-files.ts — it already does "one PDFDocument per page" via copyPages.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
PDF operations in pdf-kit
All PDF manipulation here runs client-side with pdf-lib + pdfjs-dist. There is no
server-side merge/split — the worker (worker/index.ts) only proxies compress and ocr
to an external Stirling-PDF instance. Don't add a server endpoint for merge/split/rotate;
pdf-lib in the browser already does it, keeping the "processed locally" guarantee shown
in the UI.
Merge multiple PDFs into one — already implemented, reuse it
This is not a missing feature. The existing workspace flow already merges any number of PDFs (and images) into a single output:
src/features/workspace/import-files.ts(importPdf→isolatePdfPages) splits every dropped PDF into one single-pagePDFDocumentper page, so each page becomes an independentWorkspacePagewith its ownsourceblob andpageIndex: 0.- The pages array holds pages from every dropped file, in the order the user arranged
them (drag-and-drop reordering, rotate, delete — see
src/features/workspace/model.ts). src/features/image-to-pdf/generate.ts(generatePdf) walks that array and, for eachkind: 'pdf'page,copyPagess it into one outputPDFDocument, thenoutput.save()returns the merged bytes.
So "merge PDF A + B into one file" == drop both files on the workspace and click
Create PDF. Covered by the test merges imported PDF pages in workspace order in
tests/pdf-generation.test.ts.
If you need a headless merge (no workspace/UI involved — e.g. a script or a new non-visual entry point), skip the isolate/thumbnail machinery and go straight to pdf-lib:
import { PDFDocument } from 'pdf-lib'
async function mergePdfs(files: Uint8Array[]) {
const output = await PDFDocument.create()
for (const bytes of files) {
const source = await PDFDocument.load(bytes)
const pages = await output.copyPages(source, source.getPageIndices())
pages.forEach((page) => output.addPage(page))
}
return output.save() // Uint8Array
}That's the whole operation — don't reach for a server round-trip or a new dependency.
Split a PDF into its pages
Use isolatePdfPages in src/features/workspace/import-files.ts — it already does
"one PDFDocument per page" via copyPages. Don't rewrite it.
Rotate / reorder / delete / duplicate pages
Handled by src/features/workspace/model.ts (rotateSelected, reorderPages,
moveSelected, deleteSelected, duplicateSelected) operating on the WorkspacePage[]
array before generatePdf runs. Rotation is composed at export time in generate.ts:
page.setRotation(degrees((sourceRotation + item.rotation) % 360)) — source PDF rotation
and the user's applied rotation are added together, not overwritten.
Overlays (text/rectangle/circle annotations)
Defined per-page in PdfPage.overlays (src/types/pdf.ts), coordinates stored as
0–1 fractions of page size. overlayPdfRect in src/features/pdf-editor/model.ts
converts a fractional rect to absolute PDF points, accounting for the source page's
rotation (not the export rotation) since overlays are flattened before the rotation is
applied. generate.ts flattens overlays with page.drawText / drawRectangle /
drawEllipse using StandardFonts.Helvetica.
Gotchas seen in this codebase
- Cache a loaded
PDFDocumentper sourceBlob(see theMapingeneratePdf) — don't callPDFDocument.loadonce per page when multiple pages share one source file. output.save()returns aUint8Array; wrap asnew Blob([bytes as BlobPart], { type: 'application/pdf' })before creating a download URL (TS needs theas BlobPartcast here).- WebP images aren't embeddable by pdf-lib directly —
generate.tsre-encodes them to PNG viaOffscreenCanvasfirst (imageByteshelper). Reuse that helper for new image formats rather than adding a new embed path. - Text overlay only draws if
isPdfTextSupported(WinAnsi-encodable) — Helvetica can't render arbitrary Unicode.
Where tests live
tests/pdf-generation.test.ts covers generatePdf (merge order, overlays, rotation).
tests/workspace.test.ts covers page array operations. e2e/pdf-kit.spec.ts covers the
full UI flow with Playwright. Add cases there rather than a new test file for a new
operation on the existing pipeline.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

