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    }
36}
37
38#[derive(TypliteAttr, Default)]
39pub struct IdocAttr {
40    pub src: EcoString,
41    pub mode: EcoString,
42}
43
44#[derive(TypliteAttr, Default)]
45pub struct HeadingAttr {
46    pub level: usize,
47}
48
49#[derive(TypliteAttr, Default)]
50pub struct ImageAttr {
51    pub src: EcoString,
52    pub alt: EcoString,
53}
54
55#[derive(TypliteAttr, Default)]
56pub struct FigureAttr {
57    pub caption: EcoString,
58}
59
60#[derive(TypliteAttr, Default)]
61pub struct LinkAttr {
62    pub dest: EcoString,
63}
64
65#[derive(TypliteAttr, Default)]
66pub struct RawAttr {
67    pub lang: EcoString,
68    pub block: bool,
69    pub text: EcoString,
70}
71
72#[derive(TypliteAttr, Default)]
73pub struct ListItemAttr {
74    pub value: Option<u32>,
75}
76
77#[derive(TypliteAttr, Default)]
78pub struct AlertsAttr {
79    pub class: EcoString,
80}
81
82pub trait TypliteAttrsParser {
83    fn parse(attrs: &HtmlAttrs) -> Result<Self>
84    where
85        Self: Sized;
86}
87
88pub trait TypliteAttrParser {
89    fn parse_attr(content: &EcoString) -> Result<Self>
90    where
91        Self: Sized;
92}
93
94impl TypliteAttrParser for usize {
95    fn parse_attr(content: &EcoString) -> Result<Self> {
96        Ok(content
97            .parse::<usize>()
98            .map_err(|_| format!("cannot parse {content} as usize"))?)
99    }
100}
101
102impl TypliteAttrParser for u32 {
103    fn parse_attr(content: &EcoString) -> Result<Self> {
104        Ok(content
105            .parse::<u32>()
106            .map_err(|_| format!("cannot parse {content} as u32"))?)
107    }
108}
109
110impl TypliteAttrParser for bool {
111    fn parse_attr(content: &EcoString) -> Result<Self> {
112        Ok(content
113            .parse::<bool>()
114            .map_err(|_| format!("cannot parse {content} as bool"))?)
115    }
116}
117
118impl TypliteAttrParser for EcoString {
119    fn parse_attr(content: &EcoString) -> Result<Self> {
120        Ok(content.clone())
121    }
122}
123
124impl<T> TypliteAttrParser for Option<T>
125where
126    T: TypliteAttrParser,
127{
128    fn parse_attr(content: &EcoString) -> Result<Self> {
129        if content.is_empty() {
130            Ok(None)
131        } else {
132            T::parse_attr(content).map(Some)
133        }
134    }
135}