@@ -224,6 +224,16 @@ size_t leading_whitespace_size(const unsigned char *data, size_t length) {
224224 return size;
225225}
226226
227+ lxb_dom_node_t *template_aware_first_child (lxb_dom_node_t *node) {
228+ if (lxb_html_tree_node_is (node, LXB_TAG_TEMPLATE)) {
229+ // <template> elements don't have direct children, instead they hold
230+ // a document fragment node, so we reach for its first child instead.
231+ return lxb_html_interface_template (node)->content ->node .first_child ;
232+ } else {
233+ return lxb_dom_node_first_child (node);
234+ }
235+ }
236+
227237void append_node_html (lxb_dom_node_t *node, bool skip_whitespace_nodes,
228238 std::string &html) {
229239 if (node->type == LXB_DOM_NODE_TYPE_TEXT) {
@@ -282,7 +292,7 @@ void append_node_html(lxb_dom_node_t *node, bool skip_whitespace_nodes,
282292 html.append (" />" );
283293 } else {
284294 html.append (" >" );
285- for (auto child = lxb_dom_node_first_child (node); child != NULL ;
295+ for (auto child = template_aware_first_child (node); child != NULL ;
286296 child = lxb_dom_node_next (child)) {
287297 append_node_html (child, skip_whitespace_nodes, html);
288298 }
@@ -353,7 +363,7 @@ void node_to_tree(ErlNifEnv *env, fine::ResourcePtr<LazyHTML> &resource,
353363 auto attrs_term = attributes_to_term (env, element, sort_attributes);
354364
355365 auto children = std::vector<ERL_NIF_TERM>();
356- for (auto child = lxb_dom_node_first_child (node); child != NULL ;
366+ for (auto child = template_aware_first_child (node); child != NULL ;
357367 child = lxb_dom_node_next (child)) {
358368 node_to_tree (env, resource, child, children, sort_attributes);
359369 }
@@ -368,12 +378,6 @@ void node_to_tree(ErlNifEnv *env, fine::ResourcePtr<LazyHTML> &resource,
368378 env, resource, reinterpret_cast <char *>(character_data->data .data ),
369379 character_data->data .length );
370380 tree.push_back (term);
371- } else if (node->type == LXB_DOM_NODE_TYPE_DOCUMENT ||
372- node->type == LXB_DOM_NODE_TYPE_DOCUMENT_FRAGMENT) {
373- for (auto child = lxb_dom_node_first_child (node); child != NULL ;
374- child = lxb_dom_node_next (child)) {
375- node_to_tree (env, resource, child, tree, sort_attributes);
376- }
377381 } else if (node->type == LXB_DOM_NODE_TYPE_COMMENT) {
378382 auto character_data = lxb_dom_interface_character_data (node);
379383 auto term = fine::make_resource_binary (
@@ -432,11 +436,18 @@ lxb_dom_node_t *node_from_tree_item(ErlNifEnv *env,
432436 }
433437 }
434438
435- auto node = lxb_dom_interface_node (element);
439+ auto insert_into_node = lxb_dom_interface_node (element);
440+
441+ if (lxb_html_tree_node_is (insert_into_node, LXB_TAG_TEMPLATE)) {
442+ // <template> elements don't have direct children, instead they hold
443+ // a document fragment node, so we insert into the fragment instead.
444+ insert_into_node =
445+ &lxb_html_interface_template (insert_into_node)->content ->node ;
446+ }
436447
437448 for (auto child_item : children_tree) {
438449 auto child_node = node_from_tree_item (env, document, child_item);
439- lxb_dom_node_insert_child (node , child_node);
450+ lxb_dom_node_insert_child (insert_into_node , child_node);
440451 }
441452
442453 return lxb_dom_interface_node (element);
0 commit comments