Implemented Phase 7.6.3: extract non-link annotations with subtype-specific
fields including:
- TextMarkup (Highlight/Squiggly/StrikeOut/Underline) with /QuadPoints
- Stamp with /Name icon
- FreeText with /DA default appearance
- Text (sticky notes) with /Open, /State, /StateModel
- Ink with /InkList stroke paths
- Line with /L endpoints
- Polygon/PolyLine with /Vertices
- FileAttachment with /FS filespec reference
- Other (Circle, Square, Caret, Redact, etc.) with no extra fields
Added AnnotationSpecific enum to capture subtype-specific extras while
preserving the stable AnnotationCommon struct. Unknown subtypes emit
as Other without diagnostics (future: emit unhandled_annotation_subtype).
Comprehensive unit tests for all subtypes including edge cases.
Fixed pre-existing borrow issue in content_stream.rs.
Closes: pdftract-3r77
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Phase 7.6.2: Enhanced link annotation extraction for URI hyperlinks and
internal destination links. Added support for explicit destination arrays,
named destination resolution via /Catalog /Dests and /Catalog /Names /Dests
name trees, JavaScript action diagnostics, and link-without-target handling.
Key changes:
- Added FitType enum with all 8 PDF fit types (XYZ, Fit, FitH, FitV, FitR, FitB, FitBH, FitBV)
- Added DestArray struct for explicit destinations with page_index and fit fields
- Enhanced LinkAnnotation with dest_array field for explicit destinations
- Implemented name tree walking for /Catalog /Names /Dests resolution
- Added JavaScript action handling with diagnostic truncation (>100 chars)
- Added link-without-target diagnostic when /A and /Dest are both absent
- Updated dispatch_annotations signature to pass dests_dict and names_dests_ref
Acceptance criteria:
- Critical test: 5 URI hyperlinks appear in document links (link annotation emitted)
- Critical test: Named destination /Dest /SectionTwo -> dest: "SectionTwo"
- Unit tests: Explicit /Dest array (XYZ fit), /Dest as string-name, /JavaScript action
- Unit tests: Missing target diagnostic, all FitType variants
- Public Link { uri, dest, dest_array, page_index, rect } emitted per link
- /Dest resolution falls back gracefully when unresolved
Closes: pdftract-4zcj
Implement Phase 7.6.1: Per-page /Annots walker + subtype dispatch.
Creates the annotation module with:
- AnnotationCommon struct with shared fields (subtype, rect, contents,
author, modified date, color, opacity, flags, name_id, subject)
- dispatch_annotations() function that walks /Annots arrays and
dispatches by /Subtype:
- /Link → link extractor (7.6.2 placeholder)
- /Widget → skipped (handled by forms 7.4)
- /Popup → skipped (companion subtype)
- Others → annotation extractor (7.6.3 placeholder)
- PDF date parser (D:YYYYMMDDHHmmSSOHH'mm' → ISO 8601)
- Dereference loop detection via visited set
Acceptance criteria PASS:
- Unit tests for mixed annotation subtypes
- AnnotationCommon decoding for all non-skipped annotations
- Date parsing with ISO 8601 output
- Empty /Annots handling without diagnostics
- Public API returns (Vec<LinkAnnotation>, Vec<Annotation>)
Closes: pdftract-46qa
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>