Skip to main content

notion2prompt/model/
blocks.rs

1use super::common::BlockCommon;
2use crate::types::{BlockId, Color, PageId, RichTextItem};
3use serde::{Deserialize, Serialize};
4
5/// Text content block
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
7pub struct TextBlockContent {
8    pub rich_text: Vec<RichTextItem>,
9    pub color: Color,
10}
11
12impl Default for TextBlockContent {
13    fn default() -> Self {
14        Self {
15            rich_text: Vec::new(),
16            color: Color::Default,
17        }
18    }
19}
20
21/// Paragraph block
22#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
23pub struct ParagraphBlock {
24    pub common: BlockCommon,
25    pub content: TextBlockContent,
26}
27
28/// Heading 1 block
29#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
30pub struct Heading1Block {
31    pub common: BlockCommon,
32    pub content: TextBlockContent,
33}
34
35/// Heading 2 block
36#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
37pub struct Heading2Block {
38    pub common: BlockCommon,
39    pub content: TextBlockContent,
40}
41
42/// Heading 3 block
43#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
44pub struct Heading3Block {
45    pub common: BlockCommon,
46    pub content: TextBlockContent,
47}
48
49/// Bulleted list item block
50#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
51pub struct BulletedListItemBlock {
52    pub common: BlockCommon,
53    pub content: TextBlockContent,
54}
55
56/// Numbered list item block
57#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
58pub struct NumberedListItemBlock {
59    pub common: BlockCommon,
60    pub content: TextBlockContent,
61}
62
63/// Toggle block
64#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
65pub struct ToggleBlock {
66    pub common: BlockCommon,
67    pub content: TextBlockContent,
68}
69
70/// To-do block
71#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
72pub struct ToDoBlock {
73    pub common: BlockCommon,
74    pub content: TextBlockContent,
75    pub checked: bool,
76}
77
78/// Quote block
79#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
80pub struct QuoteBlock {
81    pub common: BlockCommon,
82    pub content: TextBlockContent,
83}
84
85/// Callout block
86#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
87pub struct CalloutBlock {
88    pub common: BlockCommon,
89    pub icon: Option<Icon>,
90    pub content: TextBlockContent,
91}
92
93/// Icon types
94#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
95#[serde(tag = "type")]
96pub enum Icon {
97    #[serde(rename = "emoji")]
98    Emoji { emoji: String },
99    #[serde(rename = "external")]
100    External { external: ExternalFile },
101    #[serde(rename = "file")]
102    File { file: NotionFile },
103}
104
105/// Code block
106#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
107pub struct CodeBlock {
108    pub common: BlockCommon,
109    pub language: String,
110    pub caption: Vec<RichTextItem>,
111    pub content: TextBlockContent,
112}
113
114/// Equation block
115#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
116pub struct EquationBlock {
117    pub common: BlockCommon,
118    pub expression: String,
119}
120
121/// Divider block
122#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
123pub struct DividerBlock {
124    pub common: BlockCommon,
125}
126
127/// Breadcrumb block
128#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
129pub struct BreadcrumbBlock {
130    pub common: BlockCommon,
131}
132
133/// Table of contents block
134#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
135pub struct TableOfContentsBlock {
136    pub common: BlockCommon,
137}
138
139/// Image block
140#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
141pub struct ImageBlock {
142    pub common: BlockCommon,
143    pub image: FileObject,
144    pub caption: Vec<RichTextItem>,
145}
146
147/// Video block
148#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
149pub struct VideoBlock {
150    pub common: BlockCommon,
151    pub video: FileObject,
152    pub caption: Vec<RichTextItem>,
153}
154
155/// File block
156#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
157pub struct FileBlock {
158    pub common: BlockCommon,
159    pub file: FileObject,
160    pub caption: Vec<RichTextItem>,
161}
162
163/// PDF block
164#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
165pub struct PdfBlock {
166    pub common: BlockCommon,
167    pub pdf: FileObject,
168    pub caption: Vec<RichTextItem>,
169}
170
171/// Bookmark block
172#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
173pub struct BookmarkBlock {
174    pub common: BlockCommon,
175    pub url: String,
176    pub caption: Vec<RichTextItem>,
177}
178
179/// Embed block
180#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
181pub struct EmbedBlock {
182    pub common: BlockCommon,
183    pub url: String,
184}
185
186/// Child page block
187#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
188pub struct ChildPageBlock {
189    pub common: BlockCommon,
190    pub title: String,
191}
192
193/// The resolution state of a child database's content.
194///
195/// A child database block in Notion can reference either an inline database
196/// (whose data is directly fetchable) or a linked database (a read-only view
197/// that the Notion API cannot retrieve). This type makes that distinction
198/// explicit so every consumer handles each case meaningfully.
199#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
200#[serde(tag = "status", content = "data")]
201pub enum ChildDatabaseContent {
202    /// Database was fetched successfully with schema and rows.
203    Fetched(Box<super::Database>),
204    /// This is a linked database — a view of another database.
205    /// The Notion API does not support retrieving linked databases directly.
206    LinkedDatabase,
207    /// The database could not be accessed (permissions, not found, etc.)
208    Inaccessible { reason: String },
209    /// Fetch has not been attempted (initial state from block parsing).
210    #[default]
211    NotFetched,
212}
213
214impl ChildDatabaseContent {
215    /// Returns a reference to the database if it was successfully fetched.
216    #[allow(dead_code)]
217    pub fn as_database(&self) -> Option<&super::Database> {
218        match self {
219            Self::Fetched(db) => Some(db),
220            _ => None,
221        }
222    }
223}
224
225/// Child database block
226#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
227pub struct ChildDatabaseBlock {
228    pub common: BlockCommon,
229    pub title: String,
230    /// The resolution state of this child database reference.
231    pub content: ChildDatabaseContent,
232}
233
234/// Link to page block
235#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
236pub struct LinkToPageBlock {
237    pub common: BlockCommon,
238    pub page_id: PageId,
239}
240
241/// Table block
242#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
243pub struct TableBlock {
244    pub common: BlockCommon,
245    pub table_width: usize,
246    pub has_column_header: bool,
247    pub has_row_header: bool,
248}
249
250/// Table row block
251#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
252pub struct TableRowBlock {
253    pub common: BlockCommon,
254    pub cells: Vec<Vec<RichTextItem>>,
255}
256
257/// Column list block
258#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
259pub struct ColumnListBlock {
260    pub common: BlockCommon,
261}
262
263/// Column block
264#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
265pub struct ColumnBlock {
266    pub common: BlockCommon,
267}
268
269/// Synced block
270#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
271pub struct SyncedBlock {
272    pub common: BlockCommon,
273    pub synced_from: Option<SyncedFrom>,
274}
275
276#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
277pub struct SyncedFrom {
278    pub block_id: BlockId,
279}
280
281/// Template block
282#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
283pub struct TemplateBlock {
284    pub common: BlockCommon,
285    pub content: TextBlockContent,
286}
287
288/// Link preview block
289#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
290pub struct LinkPreviewBlock {
291    pub common: BlockCommon,
292    pub url: String,
293}
294
295/// Unsupported block
296#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
297pub struct UnsupportedBlock {
298    pub common: BlockCommon,
299    pub block_type: String,
300}
301
302/// File object types
303#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
304#[serde(tag = "type")]
305pub enum FileObject {
306    #[serde(rename = "external")]
307    External { external: ExternalFile },
308    #[serde(rename = "file")]
309    File { file: NotionFile },
310}
311
312#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
313pub struct ExternalFile {
314    pub url: String,
315}
316
317#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
318pub struct NotionFile {
319    pub url: String,
320    pub expiry_time: Option<chrono::DateTime<chrono::Utc>>,
321}