markdown_it_lazyload/
lib.rs

1//! A [markdown_it] plugin to add lazy to image tags' loading property
2//!
3//! ```
4//! let parser = &mut markdown_it::MarkdownIt::new();
5//! markdown_it::plugins::cmark::add(parser);
6//! markdown_it_lazyload::add(parser);
7//! let node = parser.parse("![Rust](https://example.com/example.png)");
8//! ```
9
10use markdown_it::{
11    parser::core::CoreRule,
12    plugins::cmark::{self, inline::image::Image},
13    MarkdownIt, Node, NodeValue,
14};
15
16struct LazyLoadImageRule;
17
18impl CoreRule for LazyLoadImageRule {
19    fn run(root: &mut Node, _: &MarkdownIt) {
20        root.walk_mut(|node: &mut Node, _| {
21            if node.is::<Image>() {
22                if let Some(img) = node.cast::<cmark::inline::image::Image>() {
23                    node.replace(LazyLoadImage {
24                        cmark_image: Image {
25                            url: img.url.clone(),
26                            title: img.title.clone(),
27                        },
28                        loading: "lazy".to_string(),
29                    })
30                }
31            }
32        });
33    }
34}
35
36#[derive(Debug)]
37pub struct LazyLoadImage {
38    pub cmark_image: Image,
39    pub loading: String,
40}
41
42impl NodeValue for LazyLoadImage {
43    // https://github.com/markdown-it-rust/markdown-it/blob/2d7c085046a144d221490331b25ca565ecddbb1b/src/plugins/cmark/inline/image.rs#L16
44    fn render(&self, node: &markdown_it::Node, fmt: &mut dyn markdown_it::Renderer) {
45        let mut attrs = node.attrs.clone();
46
47        attrs.push(("src", self.cmark_image.url.clone()));
48        attrs.push(("alt", node.collect_text()));
49
50        if let Some(title) = &self.cmark_image.title {
51            attrs.push(("title", title.clone()));
52        }
53
54        if !self.cmark_image.url.trim().is_empty() {
55            attrs.push(("loading", self.loading.clone()));
56        }
57
58        fmt.self_close("img", &attrs);
59    }
60}
61
62/// add lazyload plugin to the parser
63pub fn add(md: &mut MarkdownIt) {
64    md.add_rule::<LazyLoadImageRule>().after_all();
65}