Skip to main content

markdown_editor/
kind.rs

1use gpui::SharedString;
2
3use gpui_kit::base::text::editor_host::ColumnAlign;
4
5/// Public, payload-light projection of a block's kind, for matching in
6/// toolbar code. Payloads (code language, table alignments, definition
7/// targets) stay in the crate-internal `BlockKindData`.
8#[non_exhaustive]
9#[derive(Clone, Copy, PartialEq, Eq, Debug)]
10pub enum BlockKind {
11    // containers
12    Root,
13    Blockquote,
14    List {
15        ordered: bool,
16    },
17    ListItem {
18        checked: Option<bool>,
19    },
20    Table,
21    TableRow,
22    TableCell,
23    // text-bearing leaves
24    Paragraph,
25    Heading {
26        level: u8,
27    },
28    CodeBlock,
29    // atomic leaves
30    /// Reserved: on main, images are inline nodes inside a paragraph, so the
31    /// spike stores them as inline atoms and never creates this kind.
32    Image,
33    HorizontalRule,
34    Break,
35    Custom,
36    Definition,
37    Unknown,
38}
39
40/// Internal kind with payload.
41#[derive(Clone, Debug, PartialEq)]
42pub(crate) enum BlockKindData {
43    Root,
44    Blockquote,
45    List {
46        ordered: bool,
47        start: Option<u32>,
48    },
49    ListItem {
50        checked: Option<bool>,
51        spread: bool,
52    },
53    Table {
54        aligns: Vec<ColumnAlign>,
55    },
56    TableRow,
57    TableCell,
58    Paragraph,
59    Heading {
60        level: u8,
61    },
62    CodeBlock {
63        lang: Option<SharedString>,
64        meta: Option<SharedString>,
65    },
66    HorizontalRule,
67    Break {
68        html: bool,
69    },
70    Custom,
71    Definition {
72        identifier: SharedString,
73        url: SharedString,
74        title: Option<SharedString>,
75    },
76    Unknown,
77}
78
79impl BlockKindData {
80    pub(crate) fn public(&self) -> BlockKind {
81        match self {
82            Self::Root => BlockKind::Root,
83            Self::Blockquote => BlockKind::Blockquote,
84            Self::List { ordered, .. } => BlockKind::List { ordered: *ordered },
85            Self::ListItem { checked, .. } => BlockKind::ListItem { checked: *checked },
86            Self::Table { .. } => BlockKind::Table,
87            Self::TableRow => BlockKind::TableRow,
88            Self::TableCell => BlockKind::TableCell,
89            Self::Paragraph => BlockKind::Paragraph,
90            Self::Heading { level } => BlockKind::Heading { level: *level },
91            Self::CodeBlock { .. } => BlockKind::CodeBlock,
92            Self::HorizontalRule => BlockKind::HorizontalRule,
93            Self::Break { .. } => BlockKind::Break,
94            Self::Custom => BlockKind::Custom,
95            Self::Definition { .. } => BlockKind::Definition,
96            Self::Unknown => BlockKind::Unknown,
97        }
98    }
99
100    /// Whether this kind holds child blocks.
101    pub(crate) fn is_container(&self) -> bool {
102        matches!(
103            self,
104            Self::Root
105                | Self::Blockquote
106                | Self::List { .. }
107                | Self::ListItem { .. }
108                | Self::Table { .. }
109                | Self::TableRow
110        )
111    }
112
113    /// Whether this kind holds editable inline text.
114    pub(crate) fn is_textblock(&self) -> bool {
115        matches!(
116            self,
117            Self::Paragraph | Self::Heading { .. } | Self::TableCell
118        )
119    }
120}