Skip to main content

pdfplumber_core/
hyperlink.rs

1//! PDF hyperlink types.
2//!
3//! Provides [`Hyperlink`] for representing resolved URI links extracted from
4//! PDF Link annotations.
5
6use crate::BBox;
7
8/// A resolved hyperlink extracted from a PDF page.
9///
10/// Represents a Link annotation with its bounding box and resolved URI target.
11/// Created by filtering annotations with `/Subtype /Link` and resolving their
12/// `/A` (action) or `/Dest` entries.
13#[derive(Debug, Clone, PartialEq)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub struct Hyperlink {
16    /// Bounding box of the link on the page.
17    pub bbox: BBox,
18    /// The resolved URI or destination string.
19    pub uri: String,
20}
21
22#[cfg(test)]
23mod tests {
24    use super::*;
25
26    #[test]
27    fn hyperlink_with_uri() {
28        let link = Hyperlink {
29            bbox: BBox::new(100.0, 200.0, 300.0, 220.0),
30            uri: "https://example.com".to_string(),
31        };
32        assert_eq!(link.uri, "https://example.com");
33        assert_eq!(link.bbox.x0, 100.0);
34    }
35
36    #[test]
37    fn hyperlink_with_goto_dest() {
38        let link = Hyperlink {
39            bbox: BBox::new(50.0, 100.0, 150.0, 120.0),
40            uri: "#page=3".to_string(),
41        };
42        assert_eq!(link.uri, "#page=3");
43    }
44
45    #[test]
46    fn hyperlink_clone_and_eq() {
47        let link1 = Hyperlink {
48            bbox: BBox::new(10.0, 20.0, 30.0, 40.0),
49            uri: "https://rust-lang.org".to_string(),
50        };
51        let link2 = link1.clone();
52        assert_eq!(link1, link2);
53    }
54}