Skip to main content

typst_html/
property.rs

1//! Typed CSS properties.
2//!
3//! Sourced from the HTML and CSS specifications, but also sometimes informed
4//! by real-world user agent style sheets:
5//! - <https://searchfox.org/firefox-main/rev/33682acc1fa0db34ac826b143048db28ee9f16a6/layout/style/res/>
6//! - <https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/html/resources/html.css;drc=25f499fd1faae687309ba0a07b23798efcc099a8>
7
8use crate::{HtmlTag, tag};
9
10/// A value for the CSS `display` property.
11///
12/// <https://www.w3.org/TR/css-display-3/#propdef-display>
13/// <https://www.w3.org/TR/mathml-core/#new-display-math-value>
14#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
15pub enum Display {
16    // <display-outside>
17    Block,
18    Inline,
19    RunIn,
20
21    // <display-inside>
22    Flow,
23    FlowRoot,
24    Table,
25    Flex,
26    Grid,
27    Ruby,
28
29    // <display-listitem>
30    ListItem,
31
32    // <display-internal>
33    TableRowGroup,
34    TableHeaderGroup,
35    TableFooterGroup,
36    TableRow,
37    TableCell,
38    TableColumnGroup,
39    TableColumn,
40    TableCaption,
41    RubyBase,
42    RubyText,
43
44    // <display-box>
45    Contents,
46    None,
47
48    // <display-legacy>
49    InlineBlock,
50    InlineTable,
51    InlineFlex,
52    InlineGrid,
53
54    // MathML Core
55    InlineMath,
56    BlockMath,
57}
58
59impl Display {
60    /// Returns the default value for the given tag as defined by the user agent
61    /// styles in § 15 of the HTML spec.
62    pub fn default_for(tag: HtmlTag) -> Option<Self> {
63        Some(match tag {
64            // § 15.3.1 Hidden elements.
65            tag::area => Self::None,
66            tag::base => Self::None,
67            tag::datalist => Self::None,
68            tag::head => Self::None,
69            tag::link => Self::None,
70            tag::meta => Self::None,
71            tag::rp => Self::None,
72            tag::script => Self::None,
73            tag::style => Self::None,
74            tag::template => Self::None,
75            tag::title => Self::None,
76
77            // § 15.3.2 The page.
78            tag::html => Self::Block,
79            tag::body => Self::Block,
80
81            // § 15.3.3 Flow content.
82            tag::address => Self::Block,
83            tag::blockquote => Self::Block,
84            tag::dialog => Self::Block,
85            tag::div => Self::Block,
86            tag::figure => Self::Block,
87            tag::figcaption => Self::Block,
88            tag::footer => Self::Block,
89            tag::form => Self::Block,
90            tag::header => Self::Block,
91            tag::hr => Self::Block,
92            tag::legend => Self::Block,
93            tag::main => Self::Block,
94            tag::p => Self::Block,
95            tag::pre => Self::Block,
96            tag::search => Self::Block,
97            tag::slot => Self::Contents,
98
99            // § 15.3.4 Phrasing content.
100            tag::ruby => Self::Ruby,
101            tag::rt => Self::RubyText,
102
103            // § 15.3.6 Sections and headings.
104            tag::article => Self::Block,
105            tag::aside => Self::Block,
106            tag::h1 => Self::Block,
107            tag::h2 => Self::Block,
108            tag::h3 => Self::Block,
109            tag::h4 => Self::Block,
110            tag::h5 => Self::Block,
111            tag::h6 => Self::Block,
112            tag::hgroup => Self::Block,
113            tag::nav => Self::Block,
114            tag::section => Self::Block,
115
116            // § 15.3.7 Lists.
117            tag::dd => Self::Block,
118            tag::dl => Self::Block,
119            tag::dt => Self::Block,
120            tag::menu => Self::Block,
121            tag::ol => Self::Block,
122            tag::ul => Self::Block,
123            tag::li => Self::ListItem,
124
125            // § 15.3.8 Tables.
126            tag::table => Self::Table,
127            tag::thead => Self::TableHeaderGroup,
128            tag::tbody => Self::TableRowGroup,
129            tag::tfoot => Self::TableFooterGroup,
130            tag::tr => Self::TableRow,
131            tag::th => Self::TableCell,
132            tag::td => Self::TableCell,
133            tag::caption => Self::TableCaption,
134            tag::col => Self::TableColumn,
135            tag::colgroup => Self::TableColumnGroup,
136
137            // § 15.3.10 Form controls.
138            tag::input => Self::InlineBlock,
139            tag::button => Self::InlineBlock,
140
141            // § 15.3.12 The fieldset and legend elements.
142            tag::fieldset => Self::Block,
143
144            // § 15.5.5 The details and summary elements.
145            tag::details => Self::Block,
146            tag::summary => Self::Block,
147
148            // § 15.5.14 The meter element.
149            //
150            // Defined in free text rather than in a CSS snippet.
151            tag::meter => Self::InlineBlock,
152
153            // § 15.5.15 The progress element.
154            //
155            // Defined in free text rather than in a CSS snippet.
156            tag::progress => Self::InlineBlock,
157
158            // § 15.5.16 The select element.
159            //
160            // The spec is silent on `option` and only specifies a value for
161            // `select optgroup`, but UA style sheets specify `display: block`.
162            tag::select => Self::InlineBlock,
163            tag::option => Self::Block,
164            tag::optgroup => Self::Block,
165
166            // § 15.5.17 The textarea element.
167            //
168            // Defined in free text rather than in a CSS snippet.
169            tag::textarea => Self::InlineBlock,
170
171            // `display: inline` is the default of the CSS property.
172            tag::a => Self::Inline,
173            tag::abbr => Self::Inline,
174            tag::audio => Self::Inline,
175            tag::b => Self::Inline,
176            tag::bdi => Self::Inline,
177            tag::bdo => Self::Inline,
178            tag::br => Self::Inline,
179            tag::canvas => Self::Inline,
180            tag::cite => Self::Inline,
181            tag::code => Self::Inline,
182            tag::data => Self::Inline,
183            tag::del => Self::Inline,
184            tag::dfn => Self::Inline,
185            tag::em => Self::Inline,
186            tag::embed => Self::Inline,
187            tag::i => Self::Inline,
188            tag::iframe => Self::Inline,
189            tag::img => Self::Inline,
190            tag::ins => Self::Inline,
191            tag::kbd => Self::Inline,
192            tag::label => Self::Inline,
193            tag::map => Self::Inline,
194            tag::mark => Self::Inline,
195            tag::noscript => Self::Inline,
196            tag::object => Self::Inline,
197            tag::output => Self::Inline,
198            tag::picture => Self::Inline,
199            tag::q => Self::Inline,
200            tag::s => Self::Inline,
201            tag::samp => Self::Inline,
202            tag::small => Self::Inline,
203            tag::source => Self::Inline,
204            tag::span => Self::Inline,
205            tag::strong => Self::Inline,
206            tag::sub => Self::Inline,
207            tag::sup => Self::Inline,
208            tag::time => Self::Inline,
209            tag::track => Self::Inline,
210            tag::u => Self::Inline,
211            tag::var => Self::Inline,
212            tag::video => Self::Inline,
213            tag::wbr => Self::Inline,
214
215            // MathML Core elements.
216            tag::mathml::math => Self::InlineMath,
217            tag::mathml::mtable => Self::InlineTable,
218            tag::mathml::mtr => Self::TableRow,
219            tag::mathml::mtd => Self::TableCell,
220
221            // We don't make any assumptions about unknown elements.
222            _ => return None,
223        })
224    }
225
226    /// Whether this is any of the `table(-.*)?` display modes.
227    pub fn is_tabular(self) -> bool {
228        matches!(
229            self,
230            Self::Table
231                | Self::TableCaption
232                | Self::TableColumn
233                | Self::TableColumnGroup
234                | Self::TableRow
235                | Self::TableRowGroup
236                | Self::TableHeaderGroup
237                | Self::TableFooterGroup
238                | Self::TableCell
239        )
240    }
241
242    /// The CSS identifier of the value.
243    pub fn as_str(self) -> &'static str {
244        match self {
245            Self::Block => "block",
246            Self::Inline => "inline",
247            Self::RunIn => "run-in",
248            Self::Flow => "flow",
249            Self::FlowRoot => "flow-root",
250            Self::Table => "table",
251            Self::Flex => "flex",
252            Self::Grid => "grid",
253            Self::Ruby => "ruby",
254            Self::ListItem => "list-item",
255            Self::TableRowGroup => "table-row-group",
256            Self::TableHeaderGroup => "table-header-group",
257            Self::TableFooterGroup => "table-footer-group",
258            Self::TableRow => "table-row",
259            Self::TableCell => "table-cell",
260            Self::TableColumnGroup => "table-column-group",
261            Self::TableColumn => "table-column",
262            Self::TableCaption => "table-caption",
263            Self::RubyBase => "ruby-base",
264            Self::RubyText => "ruby-text",
265            Self::Contents => "contents",
266            Self::None => "none",
267            Self::InlineBlock => "inline-block",
268            Self::InlineTable => "inline-table",
269            Self::InlineFlex => "inline-flex",
270            Self::InlineGrid => "inline-grid",
271            Self::InlineMath => "inline math",
272            Self::BlockMath => "block math",
273        }
274    }
275}