typlite/
attributes.rs

1//! Attributes for HTML elements and parsing
2
3use ecow::EcoString;
4use tinymist_derive::TypliteAttr;
5use typst_html::HtmlAttrs;
6
7use crate::Result;
8
9/// Tag attributes defined for HTML elements.
10pub mod md_attr {
11    use typst_html::HtmlAttr;
12
13    macro_rules! attrs {
14        ($($attr:ident -> $name:ident)*) => {
15            $(#[allow(non_upper_case_globals)]
16            pub const $attr: HtmlAttr = HtmlAttr::constant(
17                stringify!($name)
18            );)*
19        }
20    }
21
22    attrs! {
23        media -> media
24        src -> src
25        alt -> alt
26        level -> level
27        dest -> dest
28        lang -> lang
29        block -> block
30        text -> text
31        mode -> mode
32        value -> value
33        caption -> caption
34        class -> class
35        id -> id
36    }
37}
38
39#[derive(TypliteAttr, Default)]
40pub struct IdocAttr {
41    pub src: EcoString,
42    pub mode: EcoString,
43}
44
45#[derive(TypliteAttr, Default)]
46pub struct HeadingAttr {
47    pub id: EcoString,
48    pub level: usize,
49}
50
51#[derive(TypliteAttr, Default)]
52pub struct ImageAttr {
53    pub id: EcoString,
54    pub src: EcoString,
55    pub alt: EcoString,
56}
57
58#[derive(TypliteAttr, Default)]
59pub struct FigureAttr {
60    pub id: EcoString,
61    pub caption: EcoString,
62}
63
64#[derive(TypliteAttr, Default)]
65pub struct LinkAttr {
66    pub dest: EcoString,
67}
68
69#[derive(TypliteAttr, Default)]
70pub struct RawAttr {
71    pub id: EcoString,
72    pub lang: EcoString,
73    pub block: bool,
74    pub text: EcoString,
75}
76
77#[derive(TypliteAttr, Default)]
78pub struct ListItemAttr {
79    pub value: Option<u32>,
80}
81
82#[derive(TypliteAttr, Default)]
83pub struct AlertsAttr {
84    pub class: EcoString,
85}
86
87#[derive(TypliteAttr, Default)]
88pub struct VerbatimAttr {
89    pub block: bool,
90    pub src: EcoString,
91}
92
93pub trait TypliteAttrsParser {
94    fn parse(attrs: &HtmlAttrs) -> Result<Self>
95    where
96        Self: Sized;
97}
98
99pub trait TypliteAttrParser {
100    fn parse_attr(content: &EcoString) -> Result<Self>
101    where
102        Self: Sized;
103}
104
105impl TypliteAttrParser for usize {
106    fn parse_attr(content: &EcoString) -> Result<Self> {
107        Ok(content
108            .parse::<usize>()
109            .map_err(|_| format!("cannot parse {content} as usize"))?)
110    }
111}
112
113impl TypliteAttrParser for u32 {
114    fn parse_attr(content: &EcoString) -> Result<Self> {
115        Ok(content
116            .parse::<u32>()
117            .map_err(|_| format!("cannot parse {content} as u32"))?)
118    }
119}
120
121impl TypliteAttrParser for bool {
122    fn parse_attr(content: &EcoString) -> Result<Self> {
123        Ok(content
124            .parse::<bool>()
125            .map_err(|_| format!("cannot parse {content} as bool"))?)
126    }
127}
128
129impl TypliteAttrParser for EcoString {
130    fn parse_attr(content: &EcoString) -> Result<Self> {
131        Ok(content.clone())
132    }
133}
134
135impl<T> TypliteAttrParser for Option<T>
136where
137    T: TypliteAttrParser,
138{
139    fn parse_attr(content: &EcoString) -> Result<Self> {
140        if content.is_empty() {
141            Ok(None)
142        } else {
143            T::parse_attr(content).map(Some)
144        }
145    }
146}