layout/
lists.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use style::properties::longhands::list_style_type::computed_value::T as ListStyleType;
6use style::properties::style_structs;
7use style::values::computed::Image;
8
9use crate::context::LayoutContext;
10use crate::dom_traversal::{NodeAndStyleInfo, PseudoElementContentItem};
11use crate::replaced::ReplacedContents;
12
13/// <https://drafts.csswg.org/css-lists/#content-property>
14pub(crate) fn make_marker<'dom>(
15    context: &LayoutContext,
16    info: &NodeAndStyleInfo<'dom>,
17) -> Option<(NodeAndStyleInfo<'dom>, Vec<PseudoElementContentItem>)> {
18    let marker_info =
19        info.with_pseudo_element(context, style::selector_parser::PseudoElement::Marker)?;
20    let style = &marker_info.style;
21    let list_style = style.get_list();
22
23    // https://drafts.csswg.org/css-lists/#marker-image
24    let marker_image = || match &list_style.list_style_image {
25        Image::Url(url) => Some(vec![
26            PseudoElementContentItem::Replaced(ReplacedContents::from_image_url(
27                marker_info.node,
28                context,
29                url,
30            )?),
31            PseudoElementContentItem::Text(" ".into()),
32        ]),
33        // XXX: Non-None image types unimplemented.
34        Image::ImageSet(..) |
35        Image::Gradient(..) |
36        Image::CrossFade(..) |
37        Image::PaintWorklet(..) |
38        Image::None => None,
39        Image::LightDark(..) => unreachable!("light-dark() should be disabled"),
40    };
41    let content = marker_image().or_else(|| {
42        Some(vec![PseudoElementContentItem::Text(
43            marker_string(list_style)?.into(),
44        )])
45    })?;
46
47    Some((marker_info, content))
48}
49
50/// <https://drafts.csswg.org/css-lists/#marker-string>
51fn marker_string(style: &style_structs::List) -> Option<&'static str> {
52    match style.list_style_type {
53        ListStyleType::None => None,
54        // TODO: Using non-breaking space here is a bit of a hack to give a bit of margin to outside
55        // markers, but really we should be setting `white-space: pre` on them instead.
56        // See https://github.com/w3c/csswg-drafts/issues/4891.
57        ListStyleType::Disc => Some("•\u{00a0}"),
58        ListStyleType::Circle => Some("◦\u{00a0}"),
59        ListStyleType::Square => Some("▪\u{00a0}"),
60        ListStyleType::DisclosureOpen => Some("▾\u{00a0}"),
61        ListStyleType::DisclosureClosed => Some("‣\u{00a0}"),
62        ListStyleType::Decimal |
63        ListStyleType::LowerAlpha |
64        ListStyleType::UpperAlpha |
65        ListStyleType::ArabicIndic |
66        ListStyleType::Bengali |
67        ListStyleType::Cambodian |
68        ListStyleType::CjkDecimal |
69        ListStyleType::Devanagari |
70        ListStyleType::Gujarati |
71        ListStyleType::Gurmukhi |
72        ListStyleType::Kannada |
73        ListStyleType::Khmer |
74        ListStyleType::Lao |
75        ListStyleType::Malayalam |
76        ListStyleType::Mongolian |
77        ListStyleType::Myanmar |
78        ListStyleType::Oriya |
79        ListStyleType::Persian |
80        ListStyleType::Telugu |
81        ListStyleType::Thai |
82        ListStyleType::Tibetan |
83        ListStyleType::CjkEarthlyBranch |
84        ListStyleType::CjkHeavenlyStem |
85        ListStyleType::LowerGreek |
86        ListStyleType::Hiragana |
87        ListStyleType::HiraganaIroha |
88        ListStyleType::Katakana |
89        ListStyleType::KatakanaIroha => {
90            // TODO: Implement support for counters.
91            None
92        },
93    }
94}