Skip to content

Commit 6b3601a

Browse files
Add support for declarative shadow DOM (#578)
* Update declarative shadow dom Signed-off-by: batu_hoang <[email protected]> * Fix shadowhost to adjusted current node Signed-off-by: batu_hoang <[email protected]> * Update comments according to the spec Signed-off-by: batu_hoang <[email protected]> --------- Signed-off-by: batu_hoang <[email protected]>
1 parent f952757 commit 6b3601a

File tree

3 files changed

+53
-7
lines changed

3 files changed

+53
-7
lines changed

html5ever/src/tree_builder/mod.rs

+34-3
Original file line numberDiff line numberDiff line change
@@ -1376,8 +1376,31 @@ where
13761376
fn insert_phantom(&self, name: LocalName) -> Handle {
13771377
self.insert_element(Push, ns!(html), name, vec![])
13781378
}
1379+
1380+
/// <https://html.spec.whatwg.org/multipage/parsing.html#insert-an-element-at-the-adjusted-insertion-location>
1381+
fn insert_foreign_element(
1382+
&self,
1383+
tag: Tag,
1384+
ns: Namespace,
1385+
only_add_to_element_stack: bool,
1386+
) -> Handle {
1387+
let adjusted_insertion_location = self.appropriate_place_for_insertion(None);
1388+
let qname = QualName::new(None, ns, tag.name);
1389+
let elem = create_element(&self.sink, qname.clone(), tag.attrs.clone());
1390+
1391+
if !only_add_to_element_stack {
1392+
self.insert_at(adjusted_insertion_location, AppendNode(elem.clone()));
1393+
}
1394+
1395+
self.push(&elem);
1396+
1397+
elem
1398+
}
13791399
//§ END
13801400

1401+
/// <https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inhead>
1402+
///
1403+
/// A start tag whose tag name is "template"
13811404
fn should_attach_declarative_shadow(&self, tag: &Tag) -> bool {
13821405
let adjusted_insertion_location = self.appropriate_place_for_insertion(None);
13831406

@@ -1392,7 +1415,7 @@ where
13921415
// template start tag's shadowrootmode is not in the none state
13931416
let is_shadow_root_mode = tag.attrs.iter().any(|attr| {
13941417
attr.name.local == local_name!("shadowrootmode")
1395-
&& (attr.value.to_string() == *"open" || attr.value.to_string() == *"close")
1418+
&& (attr.value.as_ref() == "open" || attr.value.as_ref() == "closed")
13961419
});
13971420

13981421
// Check if intended_parent's document allows declarative shadow roots
@@ -1416,9 +1439,17 @@ where
14161439
is_shadow_root_mode && allow_declarative_shadow_roots && adjusted_current_node_not_topmost
14171440
}
14181441

1419-
fn attach_declarative_shadow(&self, tag: &Tag) -> Result<(), String> {
1442+
/// <https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inhead>
1443+
///
1444+
/// A start tag whose tag name is "template"
1445+
fn attach_declarative_shadow(
1446+
&self,
1447+
tag: &Tag,
1448+
shadow_host: &Handle,
1449+
template: &Handle,
1450+
) -> Result<(), String> {
14201451
self.sink
1421-
.attach_declarative_shadow(self.open_elems.borrow().last().unwrap(), tag.attrs.clone())
1452+
.attach_declarative_shadow(shadow_host, template, tag.attrs.clone())
14221453
}
14231454

14241455
fn create_formatting_element_for(&self, tag: Tag) -> Handle {

html5ever/src/tree_builder/rules.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,24 @@ where
160160
self.template_modes.borrow_mut().push(InTemplate);
161161

162162
if (self.should_attach_declarative_shadow(&tag)) {
163-
if self.attach_declarative_shadow(&tag).is_err() {
164-
// TODO:
165-
// insert at the adjusted insertion location
166-
// with the result of insert a foreign element for template tag
163+
// Attach shadow path
164+
165+
// Step 1. Let declarative shadow host element be adjusted current node.
166+
let mut shadow_host = self.open_elems.borrow().last().unwrap().clone();
167+
if self.is_fragment() && self.open_elems.borrow().len() == 1 {
168+
shadow_host = self.context_elem.borrow().clone().unwrap();
169+
}
170+
171+
// Step 2. Let template be the result of insert a foreign element for template start tag, with HTML namespace and true.
172+
let template = self.insert_foreign_element(tag.clone(), ns!(html), true);
173+
174+
// Step 3 - 8.
175+
// Attach a shadow root with declarative shadow host element, mode, clonable, serializable, delegatesFocus, and "named".
176+
if self.attach_declarative_shadow(&tag, &shadow_host, &template).is_err() {
177+
// Step 8.1.1. Insert an element at the adjusted insertion location with template.
178+
// Pop the current template element created in step 2 first.
179+
self.pop();
180+
self.insert_element_for(tag);
167181
}
168182
} else {
169183
self.insert_element_for(tag);

markup5ever/interface/tree_builder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ pub trait TreeSink {
269269
fn attach_declarative_shadow(
270270
&self,
271271
_location: &Self::Handle,
272+
_template: &Self::Handle,
272273
_attrs: Vec<Attribute>,
273274
) -> Result<(), String> {
274275
Err(String::from(

0 commit comments

Comments
 (0)