subdocument-splitting-plan

This commit is contained in:
rehlert committed 2026-10-06 22:52:35 +02:00
1 parent f09384d2e6
commit ca06ca2050
47 files changed
+4097 -136

No files matched your search

+139
View File
@@ -0,0 +1,139 @@
# Plan: Stempeln — Textstempel auf PDFs
## Goal
Add a new tool **"Stempeln"** (`/tools/stamp`) that places opaque, framed text stamps on PDF
pages — "BEGLAUBIGT", "EILT", "ENTWURF", "KOPIE", "AUSFERTIGUNG", plus free text with an optional
date, or an image. This is a staple of German legal/case-file work and is deliberately separate from the
watermark tool:
- Watermark = semi-transparent, decorative/repetitive, many positions.
- Stamp = fully opaque, framed, authoritative marking, usually one per page.
Pure pdf-lib drawing (text + rectangle border): lossless, instant. No new dependencies.
---
## Open decisions (defaults marked ✅)
### D1 — Stamp look
- ✅ **A. Uppercase bold text inside a plain rectangle border** (2 pt border, padding 8 pt,
default color red `#cc1a1a`, matching the existing brand red used by the watermark default).
pdf-lib has no rounded-rectangle primitive; plain rectangle is the honest option.
- B. Borderless colored text. Possible but reads as a watermark, not a stamp.
### D2 — Presets
- ✅ **Editable preset chips + free text.** Chips: BEGLAUBIGT, AUSFERTIGUNG, KOPIE, EILT,
ENTWURF, ERLEDIGT. Selecting a chip fills the text input; the input stays editable. Optional
checkbox "Datum anhängen" appends `dd.mm.yyyy` (German format).
- B. Fixed presets only. Rejected: courts/firms love their own wording.
### D3 — Relation to the watermark tool
- ✅ **Separate tool**, sharing extracted helpers from `src/lib/pdf-overlay.ts`
(position coordinate computation + hex color parsing — see page-numbers-plan; whichever plan is
implemented first creates the module). Keeps discovery simple (one tile per job) and avoids
overloading the watermark UI with a mode switch.
---
## UX
- Route `/tools/stamp`, new `src/lib/tools.ts` entry:
`{ slug: 'stamp', title: 'Stempeln', description: 'Versehen Sie Seiten mit Textstempeln wie „Beglaubigt“ oder „Eilt“.', icon: 'stamp' }`
(`stamp` is a real Lucide icon name) + icon map entry.
- After load (`loadPdfDocument` for thumbnails):
- **Options card**:
- Preset chip row (buttons; selected chip highlighted).
- Text input (bound, default "BEGLAUBIGT"), "Datum anhängen" checkbox.
- Schriftgröße slider (12–48 pt, default 24).
- Farbe color input (default `#cc1a1a`).
- Position select — same six positions + center as watermark
(reuses shared position helper; no "diagonal" for stamps).
- Rotation slider (−45°…45°, default 0) — stamps are often applied slightly tilted.
- Apply-to: "Auf alle Seiten anwenden" checkbox + `PdfPageGrid` selection when off
(watermark pattern).
- **Live preview**: rendered current page (pdfjs) with an absolutely-positioned overlay div
styled like the stamp (border, uppercase, color, rotation) at the chosen position; page
navigation. Approximation is fine, same approach as page-numbers-plan.
- Primary button **"Stempel anwenden & herunterladen"** → `{baseName}_stempel.pdf`.
## Technical approach
### Export (pdf-lib)
```ts
const font = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
const stampText = `${textInput.trim().toUpperCase()}${withDate ? ` ${formatGermanDate(new Date())}` : ''}`;
const textWidth = font.widthOfTextAtSize(stampText, size);
const boxWidth = textWidth + 2 * padding;
const boxHeight = font.heightAtSize(size) + 2 * padding;
for (const pageIndex of targetPages) {
const { width, height } = pages[pageIndex].getSize();
const { x, y } = getPositionCoords(width, height, boxWidth, boxHeight, position); // shared helper
pages[pageIndex].drawRectangle({
x, y, width: boxWidth, height: boxHeight,
borderColor: parseHexColor(colorValue), borderWidth: 2
});
pages[pageIndex].drawText(stampText, {
x: x + padding, y: y + padding + /* baseline adjust */, size, font,
color: parseHexColor(colorValue), rotate: degrees(rotationValue)
});
}
```
Details:
- Rotation is applied to the text; the border rectangle stays axis-aligned for v1 (rotated
rectangles need manual path drawing — follow-up if users care).
- Baseline adjustment: use `font.heightAtSize(size) * 0.2` descent approximation; verify visually.
- Uppercasing happens in JS (`toUpperCase()` — German umlauts are fine in WinAnsi: ä/ö/ü/ß are
supported except ẞ; uppercase ß → SS via `toLocaleUpperCase('de')` acceptable).
- Encrypted input → German error + decrypt hint (shared pattern).
### Shared helpers
Depends on `src/lib/pdf-overlay.ts` (position presets + `parseHexColor`). If page-numbers or
stamp ships first, it creates the module and rewires watermark; the second consumer just imports.
## Files changed
- `src/routes/tools/stamp/+page.svelte` — new route.
- `src/lib/pdf-overlay.ts` — shared helpers (created here if not already present).
- `src/lib/tools.ts`, `src/routes/+page.svelte` — registry + icon map.
- `tests/e2e/toolbox.spec.ts` — spec block.
- `agents.md` — structure update.
## Implementation phases
1. Shared overlay helpers (or import if they exist) — watermark regression must stay green.
2. Route UI: presets, inputs, preview overlay, page selection.
3. Export + download.
4. Registry + icon.
5. Playwright: preset "EILT" on all pages of a 3-page PDF → output valid, 3 pages; custom text
- date checkbox adds text; selection-only mode leaves other pages unmodified (compare page
content-stream sizes via pdf-lib if practical, else file-level validity + count).
6. Polish + command gauntlet.
## Verification
- Every preset chip fills the input; the stamp renders uppercase in preview and output.
- Date uses German `dd.mm.yyyy` and updates on the export day (not cached).
- Rotation visually matches preview within tolerance.
- Watermark tool unchanged (regression).
## Risks
- **Text width overflow** on small pages with long custom text + huge font: clamp computed box to
page size minus margins and shrink font if needed (simple guard loop), with a German hint.
- Preview overlay approximation may differ a few points from export — acceptable, labeled.
## Out of scope
- Image stamps (logo stamps) — users can route through the watermark image mode for that.
- Rotated border rectangles, multi-stamps per page in one run (run the tool twice; output can be
re-loaded).
- Stamp "libraries" persisted across sessions.