mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Fix details children slotting and apply summary
Signed-off-by: stevennovaryo <steven.novaryo@gmail.com>
This commit is contained in:
parent
a824b2781f
commit
9d469fc917
2 changed files with 74 additions and 49 deletions
|
@ -8,11 +8,11 @@ slot[id="internal-contents-slot"] {
|
|||
display: block;
|
||||
}
|
||||
|
||||
summary[id="internal-fallback-summary"] {
|
||||
:host summary:first-of-type {
|
||||
display: list-item;
|
||||
counter-increment: list-item 0;
|
||||
list-style: disclosure-closed inside;
|
||||
}
|
||||
:host([open]) summary[id="internal-fallback-summary"] {
|
||||
:host([open]) summary:first-of-type {
|
||||
list-style-type: disclosure-open;
|
||||
}
|
||||
|
|
|
@ -45,8 +45,9 @@ const DEFAULT_SUMMARY: &str = "Details";
|
|||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
struct ShadowTree {
|
||||
summary: Dom<HTMLSlotElement>,
|
||||
descendants: Dom<HTMLSlotElement>,
|
||||
summary_slot: Dom<HTMLSlotElement>,
|
||||
descendants_slot: Dom<HTMLSlotElement>,
|
||||
fallback_summary: Dom<HTMLElement>,
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -103,6 +104,7 @@ impl HTMLDetailsElement {
|
|||
.expect("UA shadow tree was not created")
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/rendering.html#the-details-and-summary-elements>
|
||||
fn create_shadow_tree(&self, can_gc: CanGc) {
|
||||
let document = self.owner_document();
|
||||
let root = self
|
||||
|
@ -118,6 +120,50 @@ impl HTMLDetailsElement {
|
|||
)
|
||||
.expect("Attaching UA shadow root failed");
|
||||
|
||||
// > The details element is expected to have an internal shadow tree with three child elements:
|
||||
// > 1. The first child element is a slot that is expected to take the details element's first summary
|
||||
// > element child, if any.
|
||||
let summary_slot = HTMLSlotElement::new(local_name!("slot"), None, &document, None, can_gc);
|
||||
summary_slot.upcast::<Element>().set_attribute(
|
||||
&local_name!("id"),
|
||||
AttrValue::from_atomic("internal-summary-slot".to_owned()),
|
||||
can_gc,
|
||||
);
|
||||
root.upcast::<Node>()
|
||||
.AppendChild(summary_slot.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
// > This element has a single child summary element called the default summary which has
|
||||
// > text content that is implementation-defined (and probably locale-specific).
|
||||
let fallback_summary =
|
||||
HTMLElement::new(local_name!("summary"), None, &document, None, can_gc);
|
||||
fallback_summary.upcast::<Element>().set_attribute(
|
||||
&local_name!("id"),
|
||||
AttrValue::from_atomic("internal-fallback-summary".to_owned()),
|
||||
can_gc,
|
||||
);
|
||||
fallback_summary
|
||||
.upcast::<Node>()
|
||||
.SetTextContent(Some(DEFAULT_SUMMARY.into()), can_gc);
|
||||
summary_slot
|
||||
.upcast::<Node>()
|
||||
.AppendChild(fallback_summary.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
// > 2. The second child element is a slot that is expected to take the details element's
|
||||
// > remaining descendants, if any. This element has no contents.
|
||||
let descendants_slot =
|
||||
HTMLSlotElement::new(local_name!("slot"), None, &document, None, can_gc);
|
||||
descendants_slot.upcast::<Element>().set_attribute(
|
||||
&local_name!("id"),
|
||||
AttrValue::from_atomic("internal-contents-slot".to_owned()),
|
||||
can_gc,
|
||||
);
|
||||
root.upcast::<Node>()
|
||||
.AppendChild(descendants_slot.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
// > 3. The third child element is either a link or style element with the following styles for the default summary:
|
||||
let link_element = HTMLLinkElement::new(
|
||||
local_name!("link"),
|
||||
None,
|
||||
|
@ -135,6 +181,8 @@ impl HTMLDetailsElement {
|
|||
.AppendChild(link_element.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
// TODO(stevennovaryo): We need a mechanism for parsing and storing a stylesheet as
|
||||
// we shouldn't reparse this each time we access the element.
|
||||
let details_stylesheet = parse_details_stylesheet(
|
||||
link_element
|
||||
.upcast::<Node>()
|
||||
|
@ -143,45 +191,11 @@ impl HTMLDetailsElement {
|
|||
);
|
||||
link_element.set_stylesheet(details_stylesheet.unwrap());
|
||||
|
||||
let summary_slot = HTMLSlotElement::new(local_name!("slot"), None, &document, None, can_gc);
|
||||
summary_slot.upcast::<Element>().set_attribute(
|
||||
&local_name!("id"),
|
||||
AttrValue::from_atomic("internal-summary-slot".to_owned()),
|
||||
can_gc,
|
||||
);
|
||||
root.upcast::<Node>()
|
||||
.AppendChild(summary_slot.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
let fallback_summary =
|
||||
HTMLElement::new(local_name!("summary"), None, &document, None, can_gc);
|
||||
fallback_summary.upcast::<Element>().set_attribute(
|
||||
&local_name!("id"),
|
||||
AttrValue::from_atomic("internal-fallback-summary".to_owned()),
|
||||
can_gc,
|
||||
);
|
||||
fallback_summary
|
||||
.upcast::<Node>()
|
||||
.SetTextContent(Some(DEFAULT_SUMMARY.into()), can_gc);
|
||||
summary_slot
|
||||
.upcast::<Node>()
|
||||
.AppendChild(fallback_summary.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
let descendants_slot =
|
||||
HTMLSlotElement::new(local_name!("slot"), None, &document, None, can_gc);
|
||||
descendants_slot.upcast::<Element>().set_attribute(
|
||||
&local_name!("id"),
|
||||
AttrValue::from_atomic("internal-contents-slot".to_owned()),
|
||||
can_gc,
|
||||
);
|
||||
root.upcast::<Node>()
|
||||
.AppendChild(descendants_slot.upcast::<Node>(), can_gc)
|
||||
.unwrap();
|
||||
|
||||
let _ = self.shadow_tree.borrow_mut().insert(ShadowTree {
|
||||
summary: summary_slot.as_traced(),
|
||||
descendants: descendants_slot.as_traced(),
|
||||
summary_slot: summary_slot.as_traced(),
|
||||
descendants_slot: descendants_slot.as_traced(),
|
||||
fallback_summary: fallback_summary.as_traced(),
|
||||
});
|
||||
self.upcast::<Node>()
|
||||
.dirty(crate::dom::node::NodeDamage::OtherNodeDamage);
|
||||
|
@ -199,16 +213,18 @@ impl HTMLDetailsElement {
|
|||
fn update_shadow_tree_contents(&self, can_gc: CanGc) {
|
||||
let shadow_tree = self.shadow_tree(can_gc);
|
||||
|
||||
if let Some(summary) = self.find_corresponding_summary_element() {
|
||||
shadow_tree
|
||||
.summary
|
||||
.Assign(vec![ElementOrText::Element(DomRoot::upcast(summary))]);
|
||||
}
|
||||
|
||||
let mut discovered_first_summary_element = false;
|
||||
let mut slottable_children = vec![];
|
||||
|
||||
// Assign all children to its corresponding slots.
|
||||
for child in self.upcast::<Node>().children() {
|
||||
if let Some(element) = child.downcast::<Element>() {
|
||||
if element.local_name() == &local_name!("summary") {
|
||||
// Assign the first summary element to the summary slot.
|
||||
if element.local_name() == &local_name!("summary") && !discovered_first_summary_element {
|
||||
shadow_tree
|
||||
.summary_slot
|
||||
.Assign(vec![ElementOrText::Element(DomRoot::from_ref(element))]);
|
||||
discovered_first_summary_element = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -219,7 +235,16 @@ impl HTMLDetailsElement {
|
|||
slottable_children.push(ElementOrText::Text(DomRoot::from_ref(text)));
|
||||
}
|
||||
}
|
||||
shadow_tree.descendants.Assign(slottable_children);
|
||||
shadow_tree.descendants_slot.Assign(slottable_children);
|
||||
|
||||
// If there are no summary element, assign fallback summary instead.
|
||||
if !discovered_first_summary_element {
|
||||
shadow_tree
|
||||
.summary_slot
|
||||
.Assign(vec![ElementOrText::Element(DomRoot::upcast(
|
||||
shadow_tree.fallback_summary.as_rooted()
|
||||
))]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue