link_preview/providers/
og.rs1use scraper::{Html, Selector};
12use std::fmt;
13
14pub enum OpenGraphTag {
16 Title,
21 Url,
23 Image,
25 Type,
30 Description,
32 Locale,
34 ImageHeight,
36 ImageWidth,
38 SiteName,
40}
41
42impl fmt::Debug for OpenGraphTag {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 f.write_str(self.str())
45 }
46}
47
48impl OpenGraphTag {
49 fn str(&self) -> &str {
50 match self {
51 OpenGraphTag::Title => "title",
52 OpenGraphTag::Url => "url",
53 OpenGraphTag::Image => "image",
54 OpenGraphTag::Type => "type",
55 OpenGraphTag::Description => "description",
56 OpenGraphTag::Locale => "locale",
57 OpenGraphTag::ImageHeight => "image:height",
58 OpenGraphTag::ImageWidth => "image:width",
59 OpenGraphTag::SiteName => "site_name",
60 }
61 }
62}
63
64pub fn find_og_tag(html: &Html, tag: OpenGraphTag) -> Option<String> {
66 let selector = Selector::parse(&format!("meta[property=\"og:{}\"]", tag.str())).unwrap();
67
68 if let Some(element) = html.select(&selector).next() {
69 if let Some(value) = element.value().attr("content") {
70 return Some(value.to_string());
71 }
72 }
73
74 None
75}
76
77#[cfg(test)]
78mod tests {
79 use crate::html_from_bytes;
80 use crate::tests::OG_COMPLIANT_HTML;
81
82 use super::{find_og_tag, OpenGraphTag};
83
84 #[test]
85 fn retrieves_title_from_og_compliant_html() {
86 let html = html_from_bytes(OG_COMPLIANT_HTML).unwrap();
87 let title = find_og_tag(&html, OpenGraphTag::Title).unwrap();
88
89 assert_eq!(title, "SEO Strategies for a better web");
90 }
91
92 #[test]
93 fn retrieves_description_from_og_compliant_html() {
94 let html = html_from_bytes(OG_COMPLIANT_HTML).unwrap();
95 let description = find_og_tag(&html, OpenGraphTag::Description).unwrap();
96
97 assert_eq!(description, "John Appleseed tells you his secrets on SEO for a better web experience by taking advantage of OpenGraph\'s Tags!");
98 }
99
100 #[test]
101 fn retrieves_url_from_og_compliant_html() {
102 let html = html_from_bytes(OG_COMPLIANT_HTML).unwrap();
103 let url = find_og_tag(&html, OpenGraphTag::Url).unwrap();
104
105 assert_eq!(url, "https://abetterweb.com");
106 }
107
108 #[test]
109 fn retrieves_locale_from_og_compliant_html() {
110 let html = html_from_bytes(OG_COMPLIANT_HTML).unwrap();
111 let locale = find_og_tag(&html, OpenGraphTag::Locale).unwrap();
112
113 assert_eq!(locale, "en_US");
114 }
115
116 #[test]
117 fn retrieves_image_from_og_compliant_html() {
118 let html = html_from_bytes(OG_COMPLIANT_HTML).unwrap();
119 let image = find_og_tag(&html, OpenGraphTag::Image).unwrap();
120
121 assert_eq!(
122 image,
123 "https://www.apple.com/ac/structured-data/images/open_graph_logo.png?201809210816"
124 );
125 }
126
127 #[test]
128 fn retrieves_type_from_og_compliant_html() {
129 let html = html_from_bytes(OG_COMPLIANT_HTML).unwrap();
130 let r#type = find_og_tag(&html, OpenGraphTag::Type).unwrap();
131
132 assert_eq!(r#type, "website");
133 }
134
135 #[test]
136 fn retrieves_image_height_from_og_compliant_html() {
137 let html = html_from_bytes(OG_COMPLIANT_HTML).unwrap();
138 let height = find_og_tag(&html, OpenGraphTag::ImageHeight).unwrap();
139
140 assert_eq!(height, "600");
141 }
142
143 #[test]
144 fn retrieves_image_width_from_og_compliant_html() {
145 let html = html_from_bytes(OG_COMPLIANT_HTML).unwrap();
146 let width = find_og_tag(&html, OpenGraphTag::ImageWidth).unwrap();
147
148 assert_eq!(width, "1200");
149 }
150
151 #[test]
152 fn retrieves_site_name_from_og_compliant_html() {
153 let html = html_from_bytes(OG_COMPLIANT_HTML).unwrap();
154 let site_name = find_og_tag(&html, OpenGraphTag::SiteName).unwrap();
155
156 assert_eq!(site_name, "TechPro");
157 }
158}