Skip to main content

notionrs_types/object/block/
heading.rs

1use serde::{Deserialize, Serialize};
2
3use crate::color_setters;
4
5/// <https://developers.notion.com/reference/block#headings>
6///
7/// All heading block objects, heading_1, heading_2, and heading_3,
8/// contain the following information within their corresponding objects:
9#[derive(Deserialize, Serialize, Debug, Default, Clone)]
10pub struct HeadingBlock {
11    /// The rich text of the heading.
12    pub rich_text: Vec<crate::object::rich_text::RichText>,
13
14    /// The color of the block.
15    pub color: crate::object::color::Color,
16
17    /// When children are included in the request, it will automatically be set to true.
18    /// Whether or not the heading block is a toggle heading or not.
19    /// If true, then the heading block toggles and can support children.
20    /// If false, then the heading block is a static heading block.
21    pub is_toggleable: bool,
22
23    /// It can only be specified when making a block creation request.
24    /// If you need to retrieve the child blocks, you will have to send a request to this block again.
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub children: Option<Vec<super::Block>>,
27}
28
29impl HeadingBlock {
30    pub fn rich_text(mut self, rich_text: Vec<crate::object::rich_text::RichText>) -> Self {
31        self.rich_text = rich_text;
32        self
33    }
34
35    pub fn children(mut self, children: Vec<super::Block>) -> Self {
36        self.children = Some(children);
37        self
38    }
39
40    color_setters!(self, self.color);
41
42    pub fn is_toggleable(mut self, is_toggleable: bool) -> Self {
43        self.is_toggleable = is_toggleable;
44        self
45    }
46}
47
48impl<T> From<T> for HeadingBlock
49where
50    T: AsRef<str>,
51{
52    fn from(plain_text: T) -> Self {
53        let rich_text = crate::object::rich_text::RichText::from(plain_text.as_ref().to_string());
54        Self::default().rich_text(vec![rich_text])
55    }
56}
57
58impl std::fmt::Display for HeadingBlock {
59    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
60        write!(
61            f,
62            "{}",
63            self.rich_text
64                .iter()
65                .map(|t| { t.to_string() })
66                .collect::<String>()
67        )
68    }
69}
70
71// # --------------------------------------------------------------------------------
72//
73// unit test
74//
75// # --------------------------------------------------------------------------------
76
77#[cfg(test)]
78mod unit_tests {
79
80    use super::HeadingBlock;
81
82    #[test]
83    fn deserialize_block_heading() {
84        let json_data = r#"
85        {
86            "rich_text": [
87                {
88                    "type": "text",
89                    "text": {
90                        "content": "Heading 1",
91                        "link": null
92                    },
93                    "annotations": {
94                        "bold": false,
95                        "italic": false,
96                        "strikethrough": false,
97                        "underline": false,
98                        "code": false,
99                        "color": "default"
100                    },
101                    "plain_text": "Heading",
102                    "href": null
103                }
104            ],
105            "is_toggleable": false,
106            "color": "default"
107        }
108        "#;
109
110        let heading: HeadingBlock = serde_json::from_str::<HeadingBlock>(json_data).unwrap();
111
112        assert_eq!(heading.color, crate::object::color::Color::Default);
113
114        assert!(!heading.is_toggleable);
115
116        let rich_text = heading.rich_text.first().unwrap();
117
118        match rich_text {
119            crate::object::rich_text::RichText::Text {
120                annotations,
121                plain_text,
122                href,
123                ..
124            } => {
125                assert_eq!(plain_text, "Heading");
126                assert_eq!(*href, None);
127
128                assert!(!annotations.bold);
129                assert!(!annotations.code);
130                assert!(!annotations.strikethrough);
131                assert!(!annotations.underline);
132                assert!(!annotations.italic);
133                assert_eq!(annotations.color, crate::object::color::Color::Default)
134            }
135            _ => panic!(),
136        }
137    }
138}