elmethis_json_component_types/
lib.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
4pub enum Component {
5    InlineComponent(InlineComponent),
6    BlockComponent(BlockComponent),
7}
8
9#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
10pub enum InlineComponent {
11    Text(Text),
12    Icon(Icon),
13}
14
15#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
16pub enum BlockComponent {
17    Heading(Heading),
18    Paragraph(Paragraph),
19    ListItem(ListItem),
20    List(List),
21    BlockQuote(BlockQuote),
22    Callout(Callout),
23    Divider(Divider),
24    Toggle(Toggle),
25    Bookmark(Bookmark),
26    File(File),
27    Image(Image),
28    CodeBlock(CodeBlock),
29    Katex(Katex),
30    Table(Table),
31    TableRow(TableRow),
32    TableCell(TableCell),
33}
34
35// Text # -------------------------------------------------- #
36#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
37pub struct Text {
38    /// Always "Text".
39    pub r#type: String,
40    /// Always `true`
41    pub inline: bool,
42
43    pub props: TextProps,
44    // Always `None`
45    #[serde(skip_serializing_if = "Option::is_none")]
46    pub slots: Option<TextSlots>,
47}
48
49#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
50pub struct TextProps {
51    pub text: String,
52
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub color: Option<String>,
55
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub background_color: Option<String>,
58
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub bold: Option<bool>,
61
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub italic: Option<bool>,
64
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub underline: Option<bool>,
67
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub strikethrough: Option<bool>,
70
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub katex: Option<bool>,
73
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub code: Option<bool>,
76
77    #[serde(skip_serializing_if = "Option::is_none")]
78    pub ruby: Option<String>,
79
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub href: Option<String>,
82
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub favicon: Option<String>,
85}
86
87#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
88pub struct TextSlots;
89
90// Icon # -------------------------------------------------- #
91#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
92pub struct Icon {
93    /// Always "Icon".
94    pub r#type: String,
95
96    /// Always `true`
97    pub inline: bool,
98
99    pub props: IconProps,
100
101    // Always `None`
102    #[serde(skip_serializing_if = "Option::is_none")]
103    pub slots: Option<IconSlots>,
104}
105
106#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
107pub struct IconProps {
108    pub src: String,
109
110    #[serde(skip_serializing_if = "Option::is_none")]
111    pub alt: Option<String>,
112}
113
114#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
115pub struct IconSlots;
116
117// Heading # -------------------------------------------------- #
118#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
119pub struct Heading {
120    /// Always "Heading".
121    pub r#type: String,
122
123    /// Always `false`
124    pub inline: bool,
125
126    pub props: HeadingProps,
127
128    pub slots: HeadingSlots,
129}
130
131#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
132#[serde(rename_all = "lowercase")]
133#[serde(try_from = "u8", into = "u8")]
134pub enum HeadingLevel {
135    #[default]
136    H1,
137    H2,
138    H3,
139    H4,
140    H5,
141    H6,
142}
143
144impl From<HeadingLevel> for u8 {
145    fn from(level: HeadingLevel) -> Self {
146        match level {
147            HeadingLevel::H1 => 1,
148            HeadingLevel::H2 => 2,
149            HeadingLevel::H3 => 3,
150            HeadingLevel::H4 => 4,
151            HeadingLevel::H5 => 5,
152            HeadingLevel::H6 => 6,
153        }
154    }
155}
156
157impl TryFrom<u8> for HeadingLevel {
158    type Error = String;
159
160    fn try_from(value: u8) -> Result<Self, Self::Error> {
161        match value {
162            1 => Ok(HeadingLevel::H1),
163            2 => Ok(HeadingLevel::H2),
164            3 => Ok(HeadingLevel::H3),
165            4 => Ok(HeadingLevel::H4),
166            5 => Ok(HeadingLevel::H5),
167            6 => Ok(HeadingLevel::H6),
168            _ => Err(format!("Invalid heading level: {}", value)),
169        }
170    }
171}
172
173#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
174pub struct HeadingProps {
175    pub level: HeadingLevel,
176}
177
178#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
179pub struct HeadingSlots {
180    pub default: Vec<InlineComponent>,
181}
182
183// Paragraph # -------------------------------------------------- #
184#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
185pub struct Paragraph {
186    /// Always "Paragraph".
187    pub r#type: String,
188
189    /// Always `false`
190    pub inline: bool,
191
192    // Always `None`
193    #[serde(skip_serializing_if = "Option::is_none")]
194    pub props: Option<ParagraphProps>,
195
196    pub slots: ParagraphSlots,
197}
198
199#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
200pub struct ParagraphProps;
201
202#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
203pub struct ParagraphSlots {
204    pub default: Vec<InlineComponent>,
205}
206
207// ListItem # -------------------------------------------------- #
208#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
209pub struct ListItem {
210    pub r#type: String,
211    pub inline: bool,
212    #[serde(skip_serializing_if = "Option::is_none")]
213    pub props: Option<ListItemProps>,
214    pub slots: ListItemSlots,
215}
216
217#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
218pub struct ListItemProps;
219
220#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
221pub struct ListItemSlots {
222    pub default: Vec<InlineComponent>,
223}
224
225// List # -------------------------------------------------- #
226#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
227pub struct List {
228    pub r#type: String,
229    pub inline: bool,
230    #[serde(skip_serializing_if = "Option::is_none")]
231    pub props: Option<ListProps>,
232    pub slots: ListSlots,
233}
234
235#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
236pub struct ListProps {
237    #[serde(skip_serializing_if = "Option::is_none")]
238    pub list_style: Option<ListStyle>,
239}
240
241#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
242#[serde(rename_all = "lowercase")]
243pub enum ListStyle {
244    #[default]
245    Unordered,
246    Ordered,
247}
248
249#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
250pub struct ListSlots {
251    pub default: Vec<ListItem>,
252}
253
254// BlockQuote # -------------------------------------------------- #
255#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
256pub struct BlockQuote {
257    pub r#type: String,
258    pub inline: bool,
259    #[serde(skip_serializing_if = "Option::is_none")]
260    pub props: Option<BlockQuoteProps>,
261    pub slots: BlockQuoteSlots,
262}
263
264#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
265pub struct BlockQuoteProps {
266    #[serde(skip_serializing_if = "Option::is_none")]
267    pub cite: Option<String>,
268}
269
270#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
271pub struct BlockQuoteSlots {
272    pub default: Vec<Component>,
273}
274
275// Callout # -------------------------------------------------- #
276#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
277pub struct Callout {
278    pub r#type: String,
279    pub inline: bool,
280    #[serde(skip_serializing_if = "Option::is_none")]
281    pub props: Option<CalloutProps>,
282    pub slots: CalloutSlots,
283}
284
285#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
286#[serde(rename_all = "lowercase")]
287pub enum CalloutType {
288    #[default]
289    Note,
290    Tip,
291    Important,
292    Warning,
293    Caution,
294}
295
296#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
297pub struct CalloutProps {
298    #[serde(skip_serializing_if = "Option::is_none")]
299    pub r#type: Option<CalloutType>,
300}
301
302#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
303pub struct CalloutSlots {
304    pub default: Vec<Component>,
305}
306
307// Divider # -------------------------------------------------- #
308#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
309pub struct Divider {
310    pub r#type: String,
311    pub inline: bool,
312    #[serde(skip_serializing_if = "Option::is_none")]
313    pub props: Option<DividerProps>,
314    #[serde(skip_serializing_if = "Option::is_none")]
315    pub slots: Option<DividerSlots>,
316}
317
318#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
319pub struct DividerProps;
320
321#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
322pub struct DividerSlots;
323
324// Toggle # -------------------------------------------------- #
325#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
326pub struct Toggle {
327    pub r#type: String,
328    pub inline: bool,
329    #[serde(skip_serializing_if = "Option::is_none")]
330    pub props: Option<ToggleProps>,
331    pub slots: ToggleSlots,
332}
333
334#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
335pub struct ToggleProps;
336
337#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
338pub struct ToggleSlots {
339    pub default: Vec<Component>,
340    pub summary: Vec<InlineComponent>,
341}
342
343// Bookmark # -------------------------------------------------- #
344#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
345pub struct Bookmark {
346    pub r#type: String,
347    pub inline: bool,
348    pub props: BookmarkProps,
349    #[serde(skip_serializing_if = "Option::is_none")]
350    pub slots: Option<BookmarkSlots>,
351}
352
353#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
354pub struct BookmarkProps {
355    pub url: String,
356    #[serde(skip_serializing_if = "Option::is_none")]
357    pub title: Option<String>,
358    #[serde(skip_serializing_if = "Option::is_none")]
359    pub description: Option<String>,
360    #[serde(skip_serializing_if = "Option::is_none")]
361    pub image: Option<String>,
362}
363
364#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
365pub struct BookmarkSlots;
366
367// File # -------------------------------------------------- #
368#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
369pub struct File {
370    pub r#type: String,
371    pub inline: bool,
372    pub props: FileProps,
373    #[serde(skip_serializing_if = "Option::is_none")]
374    pub slots: Option<FileSlots>,
375}
376
377#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
378pub struct FileProps {
379    pub src: String,
380    #[serde(skip_serializing_if = "Option::is_none")]
381    pub name: Option<String>,
382}
383
384#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
385pub struct FileSlots;
386
387// Image # -------------------------------------------------- #
388#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
389pub struct Image {
390    pub r#type: String,
391    pub inline: bool,
392    pub props: ImageProps,
393    #[serde(skip_serializing_if = "Option::is_none")]
394    pub slots: Option<ImageSlots>,
395}
396
397#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
398pub struct ImageProps {
399    pub src: String,
400    #[serde(skip_serializing_if = "Option::is_none")]
401    pub alt: Option<String>,
402}
403
404#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
405pub struct ImageSlots;
406
407// CodeBlock # -------------------------------------------------- #
408#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
409pub struct CodeBlock {
410    pub r#type: String,
411    pub inline: bool,
412    pub props: CodeBlockProps,
413    pub slots: CodeBlockSlots,
414}
415
416#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
417pub struct CodeBlockProps {
418    pub code: String,
419    pub language: String,
420}
421
422#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
423pub struct CodeBlockSlots {
424    pub default: Vec<InlineComponent>,
425}
426
427// Katex # -------------------------------------------------- #
428#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
429pub struct Katex {
430    pub r#type: String,
431    pub inline: bool,
432    pub props: KatexProps,
433    #[serde(skip_serializing_if = "Option::is_none")]
434    pub slots: Option<KatexSlots>,
435}
436
437#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
438pub struct KatexProps {
439    pub expression: String,
440}
441
442#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
443pub struct KatexSlots;
444
445// Table # -------------------------------------------------- #
446#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
447pub struct Table {
448    pub r#type: String,
449    pub inline: bool,
450    #[serde(skip_serializing_if = "Option::is_none")]
451    pub props: Option<TableProps>,
452    pub slots: TableSlots,
453}
454
455#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
456pub struct TableProps {
457    #[serde(skip_serializing_if = "Option::is_none")]
458    pub has_column_header: Option<bool>,
459    #[serde(skip_serializing_if = "Option::is_none")]
460    pub has_row_header: Option<bool>,
461    #[serde(skip_serializing_if = "Option::is_none")]
462    pub caption: Option<String>,
463}
464
465#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
466pub struct TableSlots {
467    #[serde(skip_serializing_if = "Option::is_none")]
468    pub header: Option<Vec<TableRow>>,
469    pub body: Vec<TableRow>,
470}
471
472// TableRow # -------------------------------------------------- #
473#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
474pub struct TableRow {
475    pub r#type: String,
476    pub inline: bool,
477    #[serde(skip_serializing_if = "Option::is_none")]
478    pub props: Option<TableRowProps>,
479    pub slots: TableRowSlots,
480}
481
482#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
483pub struct TableRowProps;
484
485#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
486pub struct TableRowSlots {
487    pub default: Vec<TableCell>,
488}
489
490// TableCell # -------------------------------------------------- #
491#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
492pub struct TableCell {
493    pub r#type: String,
494    pub inline: bool,
495    #[serde(skip_serializing_if = "Option::is_none")]
496    pub props: Option<TableCellProps>,
497    pub slots: TableCellSlots,
498}
499
500#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
501pub struct TableCellProps {
502    #[serde(skip_serializing_if = "Option::is_none")]
503    pub is_header: Option<bool>,
504}
505
506#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
507pub struct TableCellSlots {
508    pub default: Vec<InlineComponent>,
509}