hive-skills 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +28 -0
- package/README.md +235 -0
- package/assets/LICENSE +32 -0
- package/assets/THIRD_PARTY_NOTICES.md +72 -0
- package/assets/manifest.json +1290 -0
- package/assets/skills/authored/code-review/composable/BUNDLE.md +192 -0
- package/assets/skills/authored/code-review/composable/INDEX.md +13 -0
- package/assets/skills/authored/code-review/composable/VERSION +1 -0
- package/assets/skills/authored/code-review/composable/mini/01-review-method.md +34 -0
- package/assets/skills/authored/code-review/composable/mini/02-security-review.md +20 -0
- package/assets/skills/authored/code-review/composable/mini/03-correctness-bugs.md +19 -0
- package/assets/skills/authored/code-review/composable/mini/04-concurrency.md +16 -0
- package/assets/skills/authored/code-review/composable/mini/05-error-handling.md +12 -0
- package/assets/skills/authored/code-review/composable/mini/06-performance.md +11 -0
- package/assets/skills/authored/code-review/composable/mini/07-api-design.md +20 -0
- package/assets/skills/authored/code-review/composable/mini/08-missing-tests.md +25 -0
- package/assets/skills/authored/code-review/composable/mini/09-refactoring-and-communication.md +32 -0
- package/assets/skills/authored/data-analysis/composable/BUNDLE.md +186 -0
- package/assets/skills/authored/data-analysis/composable/INDEX.md +13 -0
- package/assets/skills/authored/data-analysis/composable/VERSION +1 -0
- package/assets/skills/authored/data-analysis/composable/mini/01-data-quality-profiling.md +26 -0
- package/assets/skills/authored/data-analysis/composable/mini/02-aggregation-pitfalls.md +21 -0
- package/assets/skills/authored/data-analysis/composable/mini/03-time-series.md +19 -0
- package/assets/skills/authored/data-analysis/composable/mini/04-segmentation.md +23 -0
- package/assets/skills/authored/data-analysis/composable/mini/05-discount-pricing.md +17 -0
- package/assets/skills/authored/data-analysis/composable/mini/06-insight-generation.md +25 -0
- package/assets/skills/authored/data-analysis/composable/mini/07-executive-writing.md +26 -0
- package/assets/skills/authored/data-analysis/composable/mini/08-recommendations.md +20 -0
- package/assets/skills/authored/data-analysis/composable/mini/09-reproducibility-assumptions.md +20 -0
- package/assets/skills/authored/financial-analysis/composable/BUNDLE.md +1293 -0
- package/assets/skills/authored/financial-analysis/composable/INDEX.md +17 -0
- package/assets/skills/authored/financial-analysis/composable/VERSION +1 -0
- package/assets/skills/authored/financial-analysis/composable/mini/00-core.md +69 -0
- package/assets/skills/authored/financial-analysis/composable/mini/01-profitability-efficiency-ratios.md +173 -0
- package/assets/skills/authored/financial-analysis/composable/mini/02-liquidity-leverage-ratios.md +120 -0
- package/assets/skills/authored/financial-analysis/composable/mini/03-valuation-ratios-interpretation.md +107 -0
- package/assets/skills/authored/financial-analysis/composable/mini/04-dcf-projection-wacc.md +122 -0
- package/assets/skills/authored/financial-analysis/composable/mini/05-dcf-terminal-value-sensitivity.md +75 -0
- package/assets/skills/authored/financial-analysis/composable/mini/06-comparables-precedents.md +78 -0
- package/assets/skills/authored/financial-analysis/composable/mini/07-budget-variance-analysis.md +47 -0
- package/assets/skills/authored/financial-analysis/composable/mini/08-driver-based-forecasting-scenarios.md +111 -0
- package/assets/skills/authored/financial-analysis/composable/mini/09-rolling-forecasts-accuracy.md +114 -0
- package/assets/skills/authored/financial-analysis/composable/mini/10-reporting-exec-summary.md +58 -0
- package/assets/skills/authored/financial-analysis/composable/mini/11-industry-adaptations.md +130 -0
- package/assets/skills/authored/financial-analysis/composable/mini/12-toolkit-scripts-io.md +102 -0
- package/assets/skills/authored/python-api/composable/BUNDLE.md +389 -0
- package/assets/skills/authored/python-api/composable/INDEX.md +13 -0
- package/assets/skills/authored/python-api/composable/VERSION +1 -0
- package/assets/skills/authored/python-api/composable/mini/01-project-structure.md +44 -0
- package/assets/skills/authored/python-api/composable/mini/02-routing-and-app.md +38 -0
- package/assets/skills/authored/python-api/composable/mini/03-pydantic-models.md +45 -0
- package/assets/skills/authored/python-api/composable/mini/04-validation-and-errors.md +59 -0
- package/assets/skills/authored/python-api/composable/mini/05-dependencies-and-auth.md +60 -0
- package/assets/skills/authored/python-api/composable/mini/06-pagination-filtering.md +44 -0
- package/assets/skills/authored/python-api/composable/mini/07-async-performance.md +30 -0
- package/assets/skills/authored/python-api/composable/mini/08-testing.md +45 -0
- package/assets/skills/authored/python-api/composable/mini/09-middleware-observability.md +29 -0
- package/assets/skills/authored/tech-writing/composable/BUNDLE.md +220 -0
- package/assets/skills/authored/tech-writing/composable/INDEX.md +12 -0
- package/assets/skills/authored/tech-writing/composable/VERSION +1 -0
- package/assets/skills/authored/tech-writing/composable/mini/01-audience-analysis.md +26 -0
- package/assets/skills/authored/tech-writing/composable/mini/02-document-types.md +27 -0
- package/assets/skills/authored/tech-writing/composable/mini/03-readme-quickstart-changelog.md +22 -0
- package/assets/skills/authored/tech-writing/composable/mini/04-information-architecture.md +21 -0
- package/assets/skills/authored/tech-writing/composable/mini/05-style-clarity.md +29 -0
- package/assets/skills/authored/tech-writing/composable/mini/06-breaking-changes-migrations.md +33 -0
- package/assets/skills/authored/tech-writing/composable/mini/07-troubleshooting-security.md +30 -0
- package/assets/skills/authored/tech-writing/composable/mini/08-faq-voice-tone.md +32 -0
- package/assets/skills/converted/claude-api/composable/BUNDLE.md +14996 -0
- package/assets/skills/converted/claude-api/composable/INDEX.md +98 -0
- package/assets/skills/converted/claude-api/composable/VERSION +1 -0
- package/assets/skills/converted/claude-api/composable/mini/00-core.md +235 -0
- package/assets/skills/converted/claude-api/composable/mini/01-model-api-quick-reference.md +258 -0
- package/assets/skills/converted/claude-api/composable/mini/02-common-pitfalls.md +42 -0
- package/assets/skills/converted/claude-api/composable/mini/10-models.md +135 -0
- package/assets/skills/converted/claude-api/composable/mini/11-platform-availability.md +96 -0
- package/assets/skills/converted/claude-api/composable/mini/12-claude-platform-on-aws.md +59 -0
- package/assets/skills/converted/claude-api/composable/mini/13-live-sources.md +143 -0
- package/assets/skills/converted/claude-api/composable/mini/14-error-codes.md +256 -0
- package/assets/skills/converted/claude-api/composable/mini/15-prompt-caching.md +223 -0
- package/assets/skills/converted/claude-api/composable/mini/16-token-counting.md +56 -0
- package/assets/skills/converted/claude-api/composable/mini/17-tool-use-concepts.md +444 -0
- package/assets/skills/converted/claude-api/composable/mini/18-agent-design.md +101 -0
- package/assets/skills/converted/claude-api/composable/mini/19-anthropic-cli.md +246 -0
- package/assets/skills/converted/claude-api/composable/mini/20-model-migration.md +1301 -0
- package/assets/skills/converted/claude-api/composable/mini/30-managed-agents-overview.md +71 -0
- package/assets/skills/converted/claude-api/composable/mini/31-managed-agents-core.md +278 -0
- package/assets/skills/converted/claude-api/composable/mini/32-managed-agents-environments.md +219 -0
- package/assets/skills/converted/claude-api/composable/mini/33-managed-agents-tools.md +366 -0
- package/assets/skills/converted/claude-api/composable/mini/34-managed-agents-events.md +252 -0
- package/assets/skills/converted/claude-api/composable/mini/35-managed-agents-outcomes.md +106 -0
- package/assets/skills/converted/claude-api/composable/mini/36-managed-agents-multiagent.md +101 -0
- package/assets/skills/converted/claude-api/composable/mini/37-managed-agents-webhooks.md +123 -0
- package/assets/skills/converted/claude-api/composable/mini/38-managed-agents-memory.md +197 -0
- package/assets/skills/converted/claude-api/composable/mini/39-managed-agents-scheduled-deployments.md +146 -0
- package/assets/skills/converted/claude-api/composable/mini/40-managed-agents-client-patterns.md +211 -0
- package/assets/skills/converted/claude-api/composable/mini/41-managed-agents-onboarding.md +82 -0
- package/assets/skills/converted/claude-api/composable/mini/42-managed-agents-api-reference.md +441 -0
- package/assets/skills/converted/claude-api/composable/mini/43-managed-agents-self-hosted-sandboxes.md +174 -0
- package/assets/skills/converted/claude-api/composable/mini/50-python-readme.md +564 -0
- package/assets/skills/converted/claude-api/composable/mini/51-python-tool-use.md +590 -0
- package/assets/skills/converted/claude-api/composable/mini/52-python-streaming-batches-files.md +549 -0
- package/assets/skills/converted/claude-api/composable/mini/53-python-managed-agents.md +335 -0
- package/assets/skills/converted/claude-api/composable/mini/55-typescript-readme.md +404 -0
- package/assets/skills/converted/claude-api/composable/mini/56-typescript-tool-use.md +548 -0
- package/assets/skills/converted/claude-api/composable/mini/57-typescript-streaming-batches-files.md +384 -0
- package/assets/skills/converted/claude-api/composable/mini/58-typescript-managed-agents.md +358 -0
- package/assets/skills/converted/claude-api/composable/mini/60-csharp-readme.md +361 -0
- package/assets/skills/converted/claude-api/composable/mini/61-csharp-tool-use.md +163 -0
- package/assets/skills/converted/claude-api/composable/mini/62-csharp-streaming-batches-files.md +64 -0
- package/assets/skills/converted/claude-api/composable/mini/65-go-readme.md +185 -0
- package/assets/skills/converted/claude-api/composable/mini/66-go-tool-use.md +219 -0
- package/assets/skills/converted/claude-api/composable/mini/67-go-streaming-files.md +63 -0
- package/assets/skills/converted/claude-api/composable/mini/68-go-managed-agents.md +564 -0
- package/assets/skills/converted/claude-api/composable/mini/70-java-readme.md +237 -0
- package/assets/skills/converted/claude-api/composable/mini/71-java-tool-use.md +227 -0
- package/assets/skills/converted/claude-api/composable/mini/72-java-streaming-files.md +49 -0
- package/assets/skills/converted/claude-api/composable/mini/73-java-managed-agents.md +443 -0
- package/assets/skills/converted/claude-api/composable/mini/75-php-readme.md +173 -0
- package/assets/skills/converted/claude-api/composable/mini/76-php-tool-use.md +252 -0
- package/assets/skills/converted/claude-api/composable/mini/77-php-streaming-batches-files.md +53 -0
- package/assets/skills/converted/claude-api/composable/mini/78-php-managed-agents.md +443 -0
- package/assets/skills/converted/claude-api/composable/mini/80-ruby-readme.md +133 -0
- package/assets/skills/converted/claude-api/composable/mini/81-ruby-tool-use-streaming.md +56 -0
- package/assets/skills/converted/claude-api/composable/mini/82-ruby-managed-agents.md +394 -0
- package/assets/skills/converted/claude-api/composable/mini/85-curl-examples.md +255 -0
- package/assets/skills/converted/claude-api/composable/mini/86-curl-managed-agents.md +340 -0
- package/assets/skills/converted/claude-api/composable/presets/csharp.md +1151 -0
- package/assets/skills/converted/claude-api/composable/presets/curl.md +1154 -0
- package/assets/skills/converted/claude-api/composable/presets/go.md +1598 -0
- package/assets/skills/converted/claude-api/composable/presets/java.md +1523 -0
- package/assets/skills/converted/claude-api/composable/presets/php.md +1488 -0
- package/assets/skills/converted/claude-api/composable/presets/python.md +2605 -0
- package/assets/skills/converted/claude-api/composable/presets/ruby.md +1146 -0
- package/assets/skills/converted/claude-api/composable/presets/shared.md +6478 -0
- package/assets/skills/converted/claude-api/composable/presets/typescript.md +2261 -0
- package/assets/skills/converted/docx/composable/BUNDLE.md +617 -0
- package/assets/skills/converted/docx/composable/INDEX.md +12 -0
- package/assets/skills/converted/docx/composable/VERSION +1 -0
- package/assets/skills/converted/docx/composable/mini/00-core.md +26 -0
- package/assets/skills/converted/docx/composable/mini/01-reading-converting.md +36 -0
- package/assets/skills/converted/docx/composable/mini/02-creating-setup-layout.md +85 -0
- package/assets/skills/converted/docx/composable/mini/03-creating-elements.md +257 -0
- package/assets/skills/converted/docx/composable/mini/04-editing-existing.md +57 -0
- package/assets/skills/converted/docx/composable/mini/05-xml-reference.md +128 -0
- package/assets/skills/converted/internal-comms/composable/BUNDLE.md +220 -0
- package/assets/skills/converted/internal-comms/composable/INDEX.md +11 -0
- package/assets/skills/converted/internal-comms/composable/VERSION +1 -0
- package/assets/skills/converted/internal-comms/composable/mini/00-core.md +30 -0
- package/assets/skills/converted/internal-comms/composable/mini/01-3p-updates.md +49 -0
- package/assets/skills/converted/internal-comms/composable/mini/02-company-newsletter.md +67 -0
- package/assets/skills/converted/internal-comms/composable/mini/03-faq-answers.md +32 -0
- package/assets/skills/converted/internal-comms/composable/mini/04-general-comms.md +18 -0
- package/assets/skills/converted/mcp-builder/composable/BUNDLE.md +2460 -0
- package/assets/skills/converted/mcp-builder/composable/INDEX.md +23 -0
- package/assets/skills/converted/mcp-builder/composable/VERSION +1 -0
- package/assets/skills/converted/mcp-builder/composable/mini/00-core.md +43 -0
- package/assets/skills/converted/mcp-builder/composable/mini/01-workflow-research-planning.md +54 -0
- package/assets/skills/converted/mcp-builder/composable/mini/02-implementation-process.md +78 -0
- package/assets/skills/converted/mcp-builder/composable/mini/03-naming-conventions.md +33 -0
- package/assets/skills/converted/mcp-builder/composable/mini/04-response-formats.md +21 -0
- package/assets/skills/converted/mcp-builder/composable/mini/05-pagination.md +24 -0
- package/assets/skills/converted/mcp-builder/composable/mini/06-transport.md +47 -0
- package/assets/skills/converted/mcp-builder/composable/mini/07-annotations.md +20 -0
- package/assets/skills/converted/mcp-builder/composable/mini/08-security.md +35 -0
- package/assets/skills/converted/mcp-builder/composable/mini/09-error-handling.md +32 -0
- package/assets/skills/converted/mcp-builder/composable/mini/10-testing-and-documentation.md +21 -0
- package/assets/skills/converted/mcp-builder/composable/mini/11-python-implementation.md +432 -0
- package/assets/skills/converted/mcp-builder/composable/mini/12-python-advanced-and-checklist.md +233 -0
- package/assets/skills/converted/mcp-builder/composable/mini/13-node-implementation.md +717 -0
- package/assets/skills/converted/mcp-builder/composable/mini/14-node-advanced-and-checklist.md +200 -0
- package/assets/skills/converted/mcp-builder/composable/mini/15-evaluation-design.md +200 -0
- package/assets/skills/converted/mcp-builder/composable/mini/16-evaluation-running.md +198 -0
- package/assets/skills/converted/mcp-builder/composable/presets/node-server.md +1381 -0
- package/assets/skills/converted/mcp-builder/composable/presets/python-server.md +1129 -0
- package/assets/skills/converted/pdf/composable/BUNDLE.md +1284 -0
- package/assets/skills/converted/pdf/composable/INDEX.md +14 -0
- package/assets/skills/converted/pdf/composable/VERSION +1 -0
- package/assets/skills/converted/pdf/composable/mini/00-core.md +46 -0
- package/assets/skills/converted/pdf/composable/mini/01-creation.md +176 -0
- package/assets/skills/converted/pdf/composable/mini/02-extraction.md +178 -0
- package/assets/skills/converted/pdf/composable/mini/03-merge-split-manipulate.md +240 -0
- package/assets/skills/converted/pdf/composable/mini/04-images-ocr.md +168 -0
- package/assets/skills/converted/pdf/composable/mini/05-encryption.md +51 -0
- package/assets/skills/converted/pdf/composable/mini/06-forms.md +300 -0
- package/assets/skills/converted/pdf/composable/mini/07-libraries-reference.md +89 -0
- package/assets/skills/converted/pptx/composable/BUNDLE.md +911 -0
- package/assets/skills/converted/pptx/composable/INDEX.md +12 -0
- package/assets/skills/converted/pptx/composable/VERSION +1 -0
- package/assets/skills/converted/pptx/composable/mini/00-core.md +37 -0
- package/assets/skills/converted/pptx/composable/mini/01-reading.md +37 -0
- package/assets/skills/converted/pptx/composable/mini/02-creating-from-scratch.md +422 -0
- package/assets/skills/converted/pptx/composable/mini/03-editing-templates.md +207 -0
- package/assets/skills/converted/pptx/composable/mini/04-design.md +89 -0
- package/assets/skills/converted/pptx/composable/mini/05-qa-and-rendering.md +91 -0
- package/assets/skills/converted/pptx/composable/presets/creating.md +659 -0
- package/assets/skills/converted/pptx/composable/presets/editing.md +485 -0
- package/assets/skills/converted/skill-creator/composable/BUNDLE.md +1681 -0
- package/assets/skills/converted/skill-creator/composable/INDEX.md +21 -0
- package/assets/skills/converted/skill-creator/composable/VERSION +1 -0
- package/assets/skills/converted/skill-creator/composable/mini/00-core.md +59 -0
- package/assets/skills/converted/skill-creator/composable/mini/01-creating-a-skill.md +27 -0
- package/assets/skills/converted/skill-creator/composable/mini/02-skill-writing-guide.md +71 -0
- package/assets/skills/converted/skill-creator/composable/mini/03-test-cases.md +21 -0
- package/assets/skills/converted/skill-creator/composable/mini/04-running-and-evaluating.md +128 -0
- package/assets/skills/converted/skill-creator/composable/mini/05-improving-the-skill.md +30 -0
- package/assets/skills/converted/skill-creator/composable/mini/06-blind-comparison.md +5 -0
- package/assets/skills/converted/skill-creator/composable/mini/07-description-optimization.md +74 -0
- package/assets/skills/converted/skill-creator/composable/mini/08-packaging.md +11 -0
- package/assets/skills/converted/skill-creator/composable/mini/09-environment-specific.md +38 -0
- package/assets/skills/converted/skill-creator/composable/mini/10-scripts-and-references.md +34 -0
- package/assets/skills/converted/skill-creator/composable/mini/11-json-schemas.md +414 -0
- package/assets/skills/converted/skill-creator/composable/mini/12-agent-grader.md +225 -0
- package/assets/skills/converted/skill-creator/composable/mini/13-agent-comparator.md +204 -0
- package/assets/skills/converted/skill-creator/composable/mini/14-agent-analyzer.md +276 -0
- package/assets/skills/converted/skill-creator/composable/presets/authoring.md +198 -0
- package/assets/skills/converted/skill-creator/composable/presets/evaluating.md +1334 -0
- package/assets/skills/converted/skill-creator/composable/presets/optimizing.md +160 -0
- package/assets/skills/converted/skill-creator/composable/presets.json +5 -0
- package/assets/skills/meta/ccs-skill-creator/composable/BUNDLE.md +465 -0
- package/assets/skills/meta/ccs-skill-creator/composable/INDEX.md +8 -0
- package/assets/skills/meta/ccs-skill-creator/composable/VERSION +1 -0
- package/assets/skills/meta/ccs-skill-creator/composable/mini/00-core.md +46 -0
- package/assets/skills/meta/ccs-skill-creator/composable/mini/01-create-new-skill.md +167 -0
- package/assets/skills/meta/ccs-skill-creator/composable/mini/02-convert-existing-skill.md +120 -0
- package/assets/skills/meta/ccs-skill-creator/composable/mini/03-review-and-maintain.md +112 -0
- package/assets/skills/sources/anthropic/PROVENANCE.md +3 -0
- package/assets/skills/sources/anthropic/claude-api/LICENSE.txt +202 -0
- package/assets/skills/sources/anthropic/docx/LICENSE.txt +30 -0
- package/assets/skills/sources/anthropic/internal-comms/LICENSE.txt +202 -0
- package/assets/skills/sources/anthropic/mcp-builder/LICENSE.txt +202 -0
- package/assets/skills/sources/anthropic/pdf/LICENSE.txt +30 -0
- package/assets/skills/sources/anthropic/pptx/LICENSE.txt +30 -0
- package/assets/skills/sources/anthropic/skill-creator/LICENSE.txt +202 -0
- package/assets/skills/sources/financial-analyst/PROVENANCE.md +1 -0
- package/assets/tools/hive.py +728 -0
- package/dist/cli.js +7494 -0
- package/package.json +40 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# PDF Processing: Loading Menu
|
|
2
|
+
|
|
3
|
+
Anything with PDF files: read, extract, create, merge, split, rotate, watermark, OCR, encrypt, fill forms.
|
|
4
|
+
|
|
5
|
+
Loading policy: read this menu, then load 00-core (if present) plus the minis relevant to your task. If most of this skill is relevant, load BUNDLE.md (or a matching presets/*.md) in one read instead.
|
|
6
|
+
|
|
7
|
+
- `mini/00-core.md` - overview, quick start, tool-selection table, routing, vendored-script paths - **always load**
|
|
8
|
+
- `mini/01-creation.md` - reportlab + pdf-lib document creation, tables, sub/superscripts - Load when creating a PDF.
|
|
9
|
+
- `mini/02-extraction.md` - text/table/metadata/coordinate/annotation extraction (pdfplumber, pdftotext, pypdf, pdfjs) - Load when reading a PDF.
|
|
10
|
+
- `mini/03-merge-split-manipulate.md` - merge, split, rotate, watermark, crop, optimize, batch (pypdf, qpdf, pdftk, pdf-lib) - Load when combining or restructuring pages.
|
|
11
|
+
- `mini/04-images-ocr.md` - extract/render images, figures, OCR scanned PDFs (pdfimages, pypdfium2, pdftoppm, pytesseract) - Load for images or OCR.
|
|
12
|
+
- `mini/05-encryption.md` - add/remove passwords and permissions (pypdf, qpdf) - Load for encrypt/decrypt.
|
|
13
|
+
- `mini/06-forms.md` - fillable and non-fillable form filling, step-by-step - Load when filling a PDF form.
|
|
14
|
+
- `mini/07-libraries-reference.md` - performance tips, troubleshooting, library licenses - Load for perf, errors, or license questions.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.0.0
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Core: PDF Processing
|
|
2
|
+
|
|
3
|
+
Always-loaded foundation for doing anything with PDF files using Python libraries and command-line tools. Load the focused minis (see INDEX) for creation, extraction, merging/splitting, images/OCR, encryption, form-filling, and library/performance guidance.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This skill covers essential PDF processing operations using Python libraries and command-line tools. For advanced features, JavaScript libraries, and detailed examples, see the extraction, merge/split, images-ocr, and libraries-reference minis. If you need to fill out a PDF form, read the forms mini and follow its instructions.
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
from pypdf import PdfReader, PdfWriter
|
|
13
|
+
|
|
14
|
+
# Read a PDF
|
|
15
|
+
reader = PdfReader("document.pdf")
|
|
16
|
+
print(f"Pages: {len(reader.pages)}")
|
|
17
|
+
|
|
18
|
+
# Extract text
|
|
19
|
+
text = ""
|
|
20
|
+
for page in reader.pages:
|
|
21
|
+
text += page.extract_text()
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Reference
|
|
25
|
+
|
|
26
|
+
| Task | Best Tool | Command/Code |
|
|
27
|
+
|------|-----------|--------------|
|
|
28
|
+
| Merge PDFs | pypdf | `writer.add_page(page)` |
|
|
29
|
+
| Split PDFs | pypdf | One page per file |
|
|
30
|
+
| Extract text | pdfplumber | `page.extract_text()` |
|
|
31
|
+
| Extract tables | pdfplumber | `page.extract_tables()` |
|
|
32
|
+
| Create PDFs | reportlab | Canvas or Platypus |
|
|
33
|
+
| Command line merge | qpdf | `qpdf --empty --pages ...` |
|
|
34
|
+
| OCR scanned PDFs | pytesseract | Convert to image first |
|
|
35
|
+
| Fill PDF forms | pdf-lib or pypdf (see forms mini) | See forms mini |
|
|
36
|
+
|
|
37
|
+
## Vendored scripts
|
|
38
|
+
|
|
39
|
+
The form-filling helper scripts referenced by the forms mini (`check_fillable_fields.py`, `extract_form_field_info.py`, `convert_pdf_to_images.py`, `fill_fillable_fields.py`, `extract_form_structure.py`, `check_bounding_boxes.py`, `fill_pdf_form_with_annotations.py`) are vendored in the source skill at `skills/sources/anthropic/pdf/scripts/`. Command lines that say `scripts/...` refer to that vendored directory.
|
|
40
|
+
|
|
41
|
+
## Next Steps
|
|
42
|
+
|
|
43
|
+
- For advanced pypdfium2 usage, see the images-ocr and libraries-reference minis.
|
|
44
|
+
- For JavaScript libraries (pdf-lib, pdfjs-dist), see the creation, extraction, merge-split, and libraries-reference minis.
|
|
45
|
+
- If you need to fill out a PDF form, follow the instructions in the forms mini.
|
|
46
|
+
- For troubleshooting guides, see the libraries-reference mini.
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Creating PDFs
|
|
2
|
+
|
|
3
|
+
Creating new PDF documents with reportlab (Python) and pdf-lib (JavaScript).
|
|
4
|
+
|
|
5
|
+
## reportlab - Create PDFs
|
|
6
|
+
|
|
7
|
+
### Basic PDF Creation
|
|
8
|
+
```python
|
|
9
|
+
from reportlab.lib.pagesizes import letter
|
|
10
|
+
from reportlab.pdfgen import canvas
|
|
11
|
+
|
|
12
|
+
c = canvas.Canvas("hello.pdf", pagesize=letter)
|
|
13
|
+
width, height = letter
|
|
14
|
+
|
|
15
|
+
# Add text
|
|
16
|
+
c.drawString(100, height - 100, "Hello World!")
|
|
17
|
+
c.drawString(100, height - 120, "This is a PDF created with reportlab")
|
|
18
|
+
|
|
19
|
+
# Add a line
|
|
20
|
+
c.line(100, height - 140, 400, height - 140)
|
|
21
|
+
|
|
22
|
+
# Save
|
|
23
|
+
c.save()
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Create PDF with Multiple Pages
|
|
27
|
+
```python
|
|
28
|
+
from reportlab.lib.pagesizes import letter
|
|
29
|
+
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
|
|
30
|
+
from reportlab.lib.styles import getSampleStyleSheet
|
|
31
|
+
|
|
32
|
+
doc = SimpleDocTemplate("report.pdf", pagesize=letter)
|
|
33
|
+
styles = getSampleStyleSheet()
|
|
34
|
+
story = []
|
|
35
|
+
|
|
36
|
+
# Add content
|
|
37
|
+
title = Paragraph("Report Title", styles['Title'])
|
|
38
|
+
story.append(title)
|
|
39
|
+
story.append(Spacer(1, 12))
|
|
40
|
+
|
|
41
|
+
body = Paragraph("This is the body of the report. " * 20, styles['Normal'])
|
|
42
|
+
story.append(body)
|
|
43
|
+
story.append(PageBreak())
|
|
44
|
+
|
|
45
|
+
# Page 2
|
|
46
|
+
story.append(Paragraph("Page 2", styles['Heading1']))
|
|
47
|
+
story.append(Paragraph("Content for page 2", styles['Normal']))
|
|
48
|
+
|
|
49
|
+
# Build PDF
|
|
50
|
+
doc.build(story)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Subscripts and Superscripts
|
|
54
|
+
|
|
55
|
+
**IMPORTANT**: Never use Unicode subscript/superscript characters (₀₁₂₃₄₅₆₇₈₉, ⁰¹²³⁴⁵⁶⁷⁸⁹) in ReportLab PDFs. The built-in fonts do not include these glyphs, causing them to render as solid black boxes.
|
|
56
|
+
|
|
57
|
+
Instead, use ReportLab's XML markup tags in Paragraph objects:
|
|
58
|
+
```python
|
|
59
|
+
from reportlab.platypus import Paragraph
|
|
60
|
+
from reportlab.lib.styles import getSampleStyleSheet
|
|
61
|
+
|
|
62
|
+
styles = getSampleStyleSheet()
|
|
63
|
+
|
|
64
|
+
# Subscripts: use <sub> tag
|
|
65
|
+
chemical = Paragraph("H<sub>2</sub>O", styles['Normal'])
|
|
66
|
+
|
|
67
|
+
# Superscripts: use <super> tag
|
|
68
|
+
squared = Paragraph("x<super>2</super> + y<super>2</super>", styles['Normal'])
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
For canvas-drawn text (not Paragraph objects), manually adjust font the size and position rather than using Unicode subscripts/superscripts.
|
|
72
|
+
|
|
73
|
+
### reportlab Advanced Features
|
|
74
|
+
|
|
75
|
+
#### Create Professional Reports with Tables
|
|
76
|
+
```python
|
|
77
|
+
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph
|
|
78
|
+
from reportlab.lib.styles import getSampleStyleSheet
|
|
79
|
+
from reportlab.lib import colors
|
|
80
|
+
|
|
81
|
+
# Sample data
|
|
82
|
+
data = [
|
|
83
|
+
['Product', 'Q1', 'Q2', 'Q3', 'Q4'],
|
|
84
|
+
['Widgets', '120', '135', '142', '158'],
|
|
85
|
+
['Gadgets', '85', '92', '98', '105']
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
# Create PDF with table
|
|
89
|
+
doc = SimpleDocTemplate("report.pdf")
|
|
90
|
+
elements = []
|
|
91
|
+
|
|
92
|
+
# Add title
|
|
93
|
+
styles = getSampleStyleSheet()
|
|
94
|
+
title = Paragraph("Quarterly Sales Report", styles['Title'])
|
|
95
|
+
elements.append(title)
|
|
96
|
+
|
|
97
|
+
# Add table with advanced styling
|
|
98
|
+
table = Table(data)
|
|
99
|
+
table.setStyle(TableStyle([
|
|
100
|
+
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
|
|
101
|
+
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
|
|
102
|
+
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
|
|
103
|
+
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
|
104
|
+
('FONTSIZE', (0, 0), (-1, 0), 14),
|
|
105
|
+
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
|
|
106
|
+
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
|
|
107
|
+
('GRID', (0, 0), (-1, -1), 1, colors.black)
|
|
108
|
+
]))
|
|
109
|
+
elements.append(table)
|
|
110
|
+
|
|
111
|
+
doc.build(elements)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## pdf-lib (MIT License) - Create Complex PDFs from Scratch
|
|
115
|
+
|
|
116
|
+
pdf-lib is a powerful JavaScript library for creating and modifying PDF documents in any JavaScript environment.
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
import { PDFDocument, rgb, StandardFonts } from 'pdf-lib';
|
|
120
|
+
import fs from 'fs';
|
|
121
|
+
|
|
122
|
+
async function createPDF() {
|
|
123
|
+
const pdfDoc = await PDFDocument.create();
|
|
124
|
+
|
|
125
|
+
// Add fonts
|
|
126
|
+
const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
|
127
|
+
const helveticaBold = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
|
|
128
|
+
|
|
129
|
+
// Add page
|
|
130
|
+
const page = pdfDoc.addPage([595, 842]); // A4 size
|
|
131
|
+
const { width, height } = page.getSize();
|
|
132
|
+
|
|
133
|
+
// Add text with styling
|
|
134
|
+
page.drawText('Invoice #12345', {
|
|
135
|
+
x: 50,
|
|
136
|
+
y: height - 50,
|
|
137
|
+
size: 18,
|
|
138
|
+
font: helveticaBold,
|
|
139
|
+
color: rgb(0.2, 0.2, 0.8)
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Add rectangle (header background)
|
|
143
|
+
page.drawRectangle({
|
|
144
|
+
x: 40,
|
|
145
|
+
y: height - 100,
|
|
146
|
+
width: width - 80,
|
|
147
|
+
height: 30,
|
|
148
|
+
color: rgb(0.9, 0.9, 0.9)
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Add table-like content
|
|
152
|
+
const items = [
|
|
153
|
+
['Item', 'Qty', 'Price', 'Total'],
|
|
154
|
+
['Widget', '2', '$50', '$100'],
|
|
155
|
+
['Gadget', '1', '$75', '$75']
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
let yPos = height - 150;
|
|
159
|
+
items.forEach(row => {
|
|
160
|
+
let xPos = 50;
|
|
161
|
+
row.forEach(cell => {
|
|
162
|
+
page.drawText(cell, {
|
|
163
|
+
x: xPos,
|
|
164
|
+
y: yPos,
|
|
165
|
+
size: 12,
|
|
166
|
+
font: helveticaFont
|
|
167
|
+
});
|
|
168
|
+
xPos += 120;
|
|
169
|
+
});
|
|
170
|
+
yPos -= 25;
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
const pdfBytes = await pdfDoc.save();
|
|
174
|
+
fs.writeFileSync('created.pdf', pdfBytes);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Extracting Text, Tables, and Metadata
|
|
2
|
+
|
|
3
|
+
Extracting text, tables, coordinates, metadata, and annotations from PDFs (pdfplumber, pdftotext, pypdf, pdfjs-dist).
|
|
4
|
+
|
|
5
|
+
## pdfplumber - Text and Table Extraction
|
|
6
|
+
|
|
7
|
+
### Extract Text with Layout
|
|
8
|
+
```python
|
|
9
|
+
import pdfplumber
|
|
10
|
+
|
|
11
|
+
with pdfplumber.open("document.pdf") as pdf:
|
|
12
|
+
for page in pdf.pages:
|
|
13
|
+
text = page.extract_text()
|
|
14
|
+
print(text)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Extract Tables
|
|
18
|
+
```python
|
|
19
|
+
with pdfplumber.open("document.pdf") as pdf:
|
|
20
|
+
for i, page in enumerate(pdf.pages):
|
|
21
|
+
tables = page.extract_tables()
|
|
22
|
+
for j, table in enumerate(tables):
|
|
23
|
+
print(f"Table {j+1} on page {i+1}:")
|
|
24
|
+
for row in table:
|
|
25
|
+
print(row)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Advanced Table Extraction
|
|
29
|
+
```python
|
|
30
|
+
import pandas as pd
|
|
31
|
+
|
|
32
|
+
with pdfplumber.open("document.pdf") as pdf:
|
|
33
|
+
all_tables = []
|
|
34
|
+
for page in pdf.pages:
|
|
35
|
+
tables = page.extract_tables()
|
|
36
|
+
for table in tables:
|
|
37
|
+
if table: # Check if table is not empty
|
|
38
|
+
df = pd.DataFrame(table[1:], columns=table[0])
|
|
39
|
+
all_tables.append(df)
|
|
40
|
+
|
|
41
|
+
# Combine all tables
|
|
42
|
+
if all_tables:
|
|
43
|
+
combined_df = pd.concat(all_tables, ignore_index=True)
|
|
44
|
+
combined_df.to_excel("extracted_tables.xlsx", index=False)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## pypdf - Extract Metadata
|
|
48
|
+
```python
|
|
49
|
+
reader = PdfReader("document.pdf")
|
|
50
|
+
meta = reader.metadata
|
|
51
|
+
print(f"Title: {meta.title}")
|
|
52
|
+
print(f"Author: {meta.author}")
|
|
53
|
+
print(f"Subject: {meta.subject}")
|
|
54
|
+
print(f"Creator: {meta.creator}")
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## pdftotext (poppler-utils)
|
|
58
|
+
```bash
|
|
59
|
+
# Extract text
|
|
60
|
+
pdftotext input.pdf output.txt
|
|
61
|
+
|
|
62
|
+
# Extract text preserving layout
|
|
63
|
+
pdftotext -layout input.pdf output.txt
|
|
64
|
+
|
|
65
|
+
# Extract specific pages
|
|
66
|
+
pdftotext -f 1 -l 5 input.pdf output.txt # Pages 1-5
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Advanced: pdfplumber
|
|
70
|
+
|
|
71
|
+
### Extract Text with Precise Coordinates
|
|
72
|
+
```python
|
|
73
|
+
import pdfplumber
|
|
74
|
+
|
|
75
|
+
with pdfplumber.open("document.pdf") as pdf:
|
|
76
|
+
page = pdf.pages[0]
|
|
77
|
+
|
|
78
|
+
# Extract all text with coordinates
|
|
79
|
+
chars = page.chars
|
|
80
|
+
for char in chars[:10]: # First 10 characters
|
|
81
|
+
print(f"Char: '{char['text']}' at x:{char['x0']:.1f} y:{char['y0']:.1f}")
|
|
82
|
+
|
|
83
|
+
# Extract text by bounding box (left, top, right, bottom)
|
|
84
|
+
bbox_text = page.within_bbox((100, 100, 400, 200)).extract_text()
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Advanced Table Extraction with Custom Settings
|
|
88
|
+
```python
|
|
89
|
+
import pdfplumber
|
|
90
|
+
import pandas as pd
|
|
91
|
+
|
|
92
|
+
with pdfplumber.open("complex_table.pdf") as pdf:
|
|
93
|
+
page = pdf.pages[0]
|
|
94
|
+
|
|
95
|
+
# Extract tables with custom settings for complex layouts
|
|
96
|
+
table_settings = {
|
|
97
|
+
"vertical_strategy": "lines",
|
|
98
|
+
"horizontal_strategy": "lines",
|
|
99
|
+
"snap_tolerance": 3,
|
|
100
|
+
"intersection_tolerance": 15
|
|
101
|
+
}
|
|
102
|
+
tables = page.extract_tables(table_settings)
|
|
103
|
+
|
|
104
|
+
# Visual debugging for table extraction
|
|
105
|
+
img = page.to_image(resolution=150)
|
|
106
|
+
img.save("debug_layout.png")
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Advanced: poppler-utils
|
|
110
|
+
|
|
111
|
+
### Extract Text with Bounding Box Coordinates
|
|
112
|
+
```bash
|
|
113
|
+
# Extract text with bounding box coordinates (essential for structured data)
|
|
114
|
+
pdftotext -bbox-layout document.pdf output.xml
|
|
115
|
+
|
|
116
|
+
# The XML output contains precise coordinates for each text element
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## pdfjs-dist (Apache License)
|
|
120
|
+
|
|
121
|
+
PDF.js is Mozilla's JavaScript library for rendering PDFs in the browser.
|
|
122
|
+
|
|
123
|
+
### Extract Text with Coordinates
|
|
124
|
+
```javascript
|
|
125
|
+
import * as pdfjsLib from 'pdfjs-dist';
|
|
126
|
+
|
|
127
|
+
async function extractText() {
|
|
128
|
+
const loadingTask = pdfjsLib.getDocument('document.pdf');
|
|
129
|
+
const pdf = await loadingTask.promise;
|
|
130
|
+
|
|
131
|
+
let fullText = '';
|
|
132
|
+
|
|
133
|
+
// Extract text from all pages
|
|
134
|
+
for (let i = 1; i <= pdf.numPages; i++) {
|
|
135
|
+
const page = await pdf.getPage(i);
|
|
136
|
+
const textContent = await page.getTextContent();
|
|
137
|
+
|
|
138
|
+
const pageText = textContent.items
|
|
139
|
+
.map(item => item.str)
|
|
140
|
+
.join(' ');
|
|
141
|
+
|
|
142
|
+
fullText += `\n--- Page ${i} ---\n${pageText}`;
|
|
143
|
+
|
|
144
|
+
// Get text with coordinates for advanced processing
|
|
145
|
+
const textWithCoords = textContent.items.map(item => ({
|
|
146
|
+
text: item.str,
|
|
147
|
+
x: item.transform[4],
|
|
148
|
+
y: item.transform[5],
|
|
149
|
+
width: item.width,
|
|
150
|
+
height: item.height
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
console.log(fullText);
|
|
155
|
+
return fullText;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Extract Annotations and Forms
|
|
160
|
+
```javascript
|
|
161
|
+
import * as pdfjsLib from 'pdfjs-dist';
|
|
162
|
+
|
|
163
|
+
async function extractAnnotations() {
|
|
164
|
+
const loadingTask = pdfjsLib.getDocument('annotated.pdf');
|
|
165
|
+
const pdf = await loadingTask.promise;
|
|
166
|
+
|
|
167
|
+
for (let i = 1; i <= pdf.numPages; i++) {
|
|
168
|
+
const page = await pdf.getPage(i);
|
|
169
|
+
const annotations = await page.getAnnotations();
|
|
170
|
+
|
|
171
|
+
annotations.forEach(annotation => {
|
|
172
|
+
console.log(`Annotation type: ${annotation.subtype}`);
|
|
173
|
+
console.log(`Content: ${annotation.contents}`);
|
|
174
|
+
console.log(`Coordinates: ${JSON.stringify(annotation.rect)}`);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# Merging, Splitting, Rotating, and Manipulating Pages
|
|
2
|
+
|
|
3
|
+
Combining, splitting, rotating, watermarking, cropping, optimizing, and batch-processing PDFs (pypdf, qpdf, pdftk, pdf-lib).
|
|
4
|
+
|
|
5
|
+
## pypdf - Basic Operations
|
|
6
|
+
|
|
7
|
+
### Merge PDFs
|
|
8
|
+
```python
|
|
9
|
+
from pypdf import PdfWriter, PdfReader
|
|
10
|
+
|
|
11
|
+
writer = PdfWriter()
|
|
12
|
+
for pdf_file in ["doc1.pdf", "doc2.pdf", "doc3.pdf"]:
|
|
13
|
+
reader = PdfReader(pdf_file)
|
|
14
|
+
for page in reader.pages:
|
|
15
|
+
writer.add_page(page)
|
|
16
|
+
|
|
17
|
+
with open("merged.pdf", "wb") as output:
|
|
18
|
+
writer.write(output)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Split PDF
|
|
22
|
+
```python
|
|
23
|
+
reader = PdfReader("input.pdf")
|
|
24
|
+
for i, page in enumerate(reader.pages):
|
|
25
|
+
writer = PdfWriter()
|
|
26
|
+
writer.add_page(page)
|
|
27
|
+
with open(f"page_{i+1}.pdf", "wb") as output:
|
|
28
|
+
writer.write(output)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Rotate Pages
|
|
32
|
+
```python
|
|
33
|
+
reader = PdfReader("input.pdf")
|
|
34
|
+
writer = PdfWriter()
|
|
35
|
+
|
|
36
|
+
page = reader.pages[0]
|
|
37
|
+
page.rotate(90) # Rotate 90 degrees clockwise
|
|
38
|
+
writer.add_page(page)
|
|
39
|
+
|
|
40
|
+
with open("rotated.pdf", "wb") as output:
|
|
41
|
+
writer.write(output)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## qpdf
|
|
45
|
+
```bash
|
|
46
|
+
# Merge PDFs
|
|
47
|
+
qpdf --empty --pages file1.pdf file2.pdf -- merged.pdf
|
|
48
|
+
|
|
49
|
+
# Split pages
|
|
50
|
+
qpdf input.pdf --pages . 1-5 -- pages1-5.pdf
|
|
51
|
+
qpdf input.pdf --pages . 6-10 -- pages6-10.pdf
|
|
52
|
+
|
|
53
|
+
# Rotate pages
|
|
54
|
+
qpdf input.pdf output.pdf --rotate=+90:1 # Rotate page 1 by 90 degrees
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## pdftk (if available)
|
|
58
|
+
```bash
|
|
59
|
+
# Merge
|
|
60
|
+
pdftk file1.pdf file2.pdf cat output merged.pdf
|
|
61
|
+
|
|
62
|
+
# Split
|
|
63
|
+
pdftk input.pdf burst
|
|
64
|
+
|
|
65
|
+
# Rotate
|
|
66
|
+
pdftk input.pdf rotate 1east output rotated.pdf
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Add Watermark
|
|
70
|
+
```python
|
|
71
|
+
from pypdf import PdfReader, PdfWriter
|
|
72
|
+
|
|
73
|
+
# Create watermark (or load existing)
|
|
74
|
+
watermark = PdfReader("watermark.pdf").pages[0]
|
|
75
|
+
|
|
76
|
+
# Apply to all pages
|
|
77
|
+
reader = PdfReader("document.pdf")
|
|
78
|
+
writer = PdfWriter()
|
|
79
|
+
|
|
80
|
+
for page in reader.pages:
|
|
81
|
+
page.merge_page(watermark)
|
|
82
|
+
writer.add_page(page)
|
|
83
|
+
|
|
84
|
+
with open("watermarked.pdf", "wb") as output:
|
|
85
|
+
writer.write(output)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## pdf-lib (MIT License)
|
|
89
|
+
|
|
90
|
+
### Load and Manipulate Existing PDF
|
|
91
|
+
```javascript
|
|
92
|
+
import { PDFDocument } from 'pdf-lib';
|
|
93
|
+
import fs from 'fs';
|
|
94
|
+
|
|
95
|
+
async function manipulatePDF() {
|
|
96
|
+
// Load existing PDF
|
|
97
|
+
const existingPdfBytes = fs.readFileSync('input.pdf');
|
|
98
|
+
const pdfDoc = await PDFDocument.load(existingPdfBytes);
|
|
99
|
+
|
|
100
|
+
// Get page count
|
|
101
|
+
const pageCount = pdfDoc.getPageCount();
|
|
102
|
+
console.log(`Document has ${pageCount} pages`);
|
|
103
|
+
|
|
104
|
+
// Add new page
|
|
105
|
+
const newPage = pdfDoc.addPage([600, 400]);
|
|
106
|
+
newPage.drawText('Added by pdf-lib', {
|
|
107
|
+
x: 100,
|
|
108
|
+
y: 300,
|
|
109
|
+
size: 16
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Save modified PDF
|
|
113
|
+
const pdfBytes = await pdfDoc.save();
|
|
114
|
+
fs.writeFileSync('modified.pdf', pdfBytes);
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Advanced Merge and Split Operations
|
|
119
|
+
```javascript
|
|
120
|
+
import { PDFDocument } from 'pdf-lib';
|
|
121
|
+
import fs from 'fs';
|
|
122
|
+
|
|
123
|
+
async function mergePDFs() {
|
|
124
|
+
// Create new document
|
|
125
|
+
const mergedPdf = await PDFDocument.create();
|
|
126
|
+
|
|
127
|
+
// Load source PDFs
|
|
128
|
+
const pdf1Bytes = fs.readFileSync('doc1.pdf');
|
|
129
|
+
const pdf2Bytes = fs.readFileSync('doc2.pdf');
|
|
130
|
+
|
|
131
|
+
const pdf1 = await PDFDocument.load(pdf1Bytes);
|
|
132
|
+
const pdf2 = await PDFDocument.load(pdf2Bytes);
|
|
133
|
+
|
|
134
|
+
// Copy pages from first PDF
|
|
135
|
+
const pdf1Pages = await mergedPdf.copyPages(pdf1, pdf1.getPageIndices());
|
|
136
|
+
pdf1Pages.forEach(page => mergedPdf.addPage(page));
|
|
137
|
+
|
|
138
|
+
// Copy specific pages from second PDF (pages 0, 2, 4)
|
|
139
|
+
const pdf2Pages = await mergedPdf.copyPages(pdf2, [0, 2, 4]);
|
|
140
|
+
pdf2Pages.forEach(page => mergedPdf.addPage(page));
|
|
141
|
+
|
|
142
|
+
const mergedPdfBytes = await mergedPdf.save();
|
|
143
|
+
fs.writeFileSync('merged.pdf', mergedPdfBytes);
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## qpdf Advanced Features
|
|
148
|
+
|
|
149
|
+
### Complex Page Manipulation
|
|
150
|
+
```bash
|
|
151
|
+
# Split PDF into groups of pages
|
|
152
|
+
qpdf --split-pages=3 input.pdf output_group_%02d.pdf
|
|
153
|
+
|
|
154
|
+
# Extract specific pages with complex ranges
|
|
155
|
+
qpdf input.pdf --pages input.pdf 1,3-5,8,10-end -- extracted.pdf
|
|
156
|
+
|
|
157
|
+
# Merge specific pages from multiple PDFs
|
|
158
|
+
qpdf --empty --pages doc1.pdf 1-3 doc2.pdf 5-7 doc3.pdf 2,4 -- combined.pdf
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### PDF Optimization and Repair
|
|
162
|
+
```bash
|
|
163
|
+
# Optimize PDF for web (linearize for streaming)
|
|
164
|
+
qpdf --linearize input.pdf optimized.pdf
|
|
165
|
+
|
|
166
|
+
# Remove unused objects and compress
|
|
167
|
+
qpdf --optimize-level=all input.pdf compressed.pdf
|
|
168
|
+
|
|
169
|
+
# Attempt to repair corrupted PDF structure
|
|
170
|
+
qpdf --check input.pdf
|
|
171
|
+
qpdf --fix-qdf damaged.pdf repaired.pdf
|
|
172
|
+
|
|
173
|
+
# Show detailed PDF structure for debugging
|
|
174
|
+
qpdf --show-all-pages input.pdf > structure.txt
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Advanced PDF Cropping
|
|
178
|
+
```python
|
|
179
|
+
from pypdf import PdfWriter, PdfReader
|
|
180
|
+
|
|
181
|
+
reader = PdfReader("input.pdf")
|
|
182
|
+
writer = PdfWriter()
|
|
183
|
+
|
|
184
|
+
# Crop page (left, bottom, right, top in points)
|
|
185
|
+
page = reader.pages[0]
|
|
186
|
+
page.mediabox.left = 50
|
|
187
|
+
page.mediabox.bottom = 50
|
|
188
|
+
page.mediabox.right = 550
|
|
189
|
+
page.mediabox.top = 750
|
|
190
|
+
|
|
191
|
+
writer.add_page(page)
|
|
192
|
+
with open("cropped.pdf", "wb") as output:
|
|
193
|
+
writer.write(output)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Batch PDF Processing with Error Handling
|
|
197
|
+
```python
|
|
198
|
+
import os
|
|
199
|
+
import glob
|
|
200
|
+
from pypdf import PdfReader, PdfWriter
|
|
201
|
+
import logging
|
|
202
|
+
|
|
203
|
+
logging.basicConfig(level=logging.INFO)
|
|
204
|
+
logger = logging.getLogger(__name__)
|
|
205
|
+
|
|
206
|
+
def batch_process_pdfs(input_dir, operation='merge'):
|
|
207
|
+
pdf_files = glob.glob(os.path.join(input_dir, "*.pdf"))
|
|
208
|
+
|
|
209
|
+
if operation == 'merge':
|
|
210
|
+
writer = PdfWriter()
|
|
211
|
+
for pdf_file in pdf_files:
|
|
212
|
+
try:
|
|
213
|
+
reader = PdfReader(pdf_file)
|
|
214
|
+
for page in reader.pages:
|
|
215
|
+
writer.add_page(page)
|
|
216
|
+
logger.info(f"Processed: {pdf_file}")
|
|
217
|
+
except Exception as e:
|
|
218
|
+
logger.error(f"Failed to process {pdf_file}: {e}")
|
|
219
|
+
continue
|
|
220
|
+
|
|
221
|
+
with open("batch_merged.pdf", "wb") as output:
|
|
222
|
+
writer.write(output)
|
|
223
|
+
|
|
224
|
+
elif operation == 'extract_text':
|
|
225
|
+
for pdf_file in pdf_files:
|
|
226
|
+
try:
|
|
227
|
+
reader = PdfReader(pdf_file)
|
|
228
|
+
text = ""
|
|
229
|
+
for page in reader.pages:
|
|
230
|
+
text += page.extract_text()
|
|
231
|
+
|
|
232
|
+
output_file = pdf_file.replace('.pdf', '.txt')
|
|
233
|
+
with open(output_file, 'w', encoding='utf-8') as f:
|
|
234
|
+
f.write(text)
|
|
235
|
+
logger.info(f"Extracted text from: {pdf_file}")
|
|
236
|
+
|
|
237
|
+
except Exception as e:
|
|
238
|
+
logger.error(f"Failed to extract text from {pdf_file}: {e}")
|
|
239
|
+
continue
|
|
240
|
+
```
|