html2md_bulletty/
iframes.rs

1use lazy_static::lazy_static;
2
3use super::TagHandler;
4use super::StructuredPrinter;
5
6use crate::common::get_tag_attr;
7use crate::dummy::IdentityHandler;
8
9use regex::Regex;
10use markup5ever_rcdom::Handle;
11
12lazy_static! {
13    /// Pattern that detects iframes with Youtube embedded videos<br/>
14    /// Examples:
15    /// * `https://www.youtube.com/embed/zE-dmXZp3nU?wmode=opaque`
16    /// * `https://www.youtube-nocookie.com/embed/5yo6exIypkY`
17    /// * `https://www.youtube.com/embed/TXm6IXrbQuM`
18    static ref YOUTUBE_PATTERN : Regex = Regex::new(r"www\.youtube(?:-nocookie)?\.com/embed/([-\w]+)").unwrap();
19
20    /// Pattern that detects iframes with Instagram embedded photos<br/>
21    /// Examples:
22    /// * `https://www.instagram.com/p/B1BKr9Wo8YX/embed/`
23    /// * `https://www.instagram.com/p/BpKjlo-B4uI/embed/`
24    static ref INSTAGRAM_PATTERN: Regex = Regex::new(r"www\.instagram\.com/p/([-\w]+)/embed").unwrap();
25
26    /// Patter that detects iframes with VKontakte embedded videos<br/>
27    /// Examples:
28    /// * `https://vk.com/video_ext.php?oid=-49423435&id=456245092&hash=e1611aefe899c4f8`
29    /// * `https://vk.com/video_ext.php?oid=-76477496&id=456239454&hash=ebfdc2d386617b97`
30    static ref VK_PATTERN: Regex = Regex::new(r"vk\.com/video_ext\.php\?oid=(-?\d+)&id=(\d+)&hash=(.*)").unwrap();
31
32    static ref YANDEX_MUSIC_TRACK_PATTERN: Regex = Regex::new(r"https://music.yandex.ru/iframe/#track/(\d+)/(\d+)").unwrap();
33    static ref YANDEX_MUSIC_ALBUM_PATTERN: Regex = Regex::new(r"https://music.yandex.ru/iframe/#album/(\d+)").unwrap();
34}
35
36#[derive(Default)]
37pub struct IframeHandler;
38
39impl TagHandler for IframeHandler {
40
41    fn handle(&mut self, tag: &Handle, printer: &mut StructuredPrinter) {
42        printer.insert_newline();
43        printer.insert_newline();
44
45        let src = get_tag_attr(tag, "src");
46        //let width = get_tag_attr(tag, "width");
47        //let height = get_tag_attr(tag, "height");
48
49        if src == None {
50            return;
51        }
52
53        let src = src.unwrap();
54
55        if let Some(capture) = YOUTUBE_PATTERN.captures(&src) {
56            let media_id = capture.get(1).map_or("", |m| m.as_str());
57            printer.append_str(&format!("[![Embedded YouTube video](https://img.youtube.com/vi/{mid}/0.jpg)](https://www.youtube.com/watch?v={mid})", mid = media_id));
58            return
59        }
60
61        if let Some(capture) = INSTAGRAM_PATTERN.captures(&src) {
62            let media_id = capture.get(1).map_or("", |m| m.as_str());
63            printer.append_str(&format!("[![Embedded Instagram post](https://www.instagram.com/p/{mid}/media/?size=m)](https://www.instagram.com/p/{mid}/embed/)", mid = media_id));
64            return
65        }
66
67        if let Some(capture) = VK_PATTERN.captures(&src) {
68            let owner_id = capture.get(1).map_or("", |m| m.as_str());
69            let video_id = capture.get(2).map_or("", |m| m.as_str());
70            let _hash = capture.get(3).map_or("", |m| m.as_str());
71            printer.append_str(&format!("[![Embedded VK video](https://st.vk.com/images/icons/video_empty_2x.png)](https://vk.com/video{oid}_{vid})", oid = owner_id, vid = video_id));
72            return
73        }
74
75        // not found, use generic implementation
76        let mut identity = IdentityHandler::default();
77        identity.handle(tag, printer);
78    }
79
80    fn after_handle(&mut self, printer: &mut StructuredPrinter) {
81        printer.insert_newline();
82        printer.insert_newline();
83    }
84
85    fn skip_descendants(&self) -> bool {
86        return true;
87    }
88}