Skip to content

Commit 31d761a

Browse files
Fix template children being ignored (#5)
1 parent 4dcf8f3 commit 31d761a

File tree

4 files changed

+57
-12
lines changed

4 files changed

+57
-12
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ permissions:
77
contents: write
88
jobs:
99
linux:
10-
runs-on: ubuntu-20.04
10+
runs-on: ubuntu-22.04
1111
env:
1212
MIX_ENV: prod
1313
ELIXIR_VERSION: "1.15.3"

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
- "v*.*"
88
jobs:
99
linux:
10-
runs-on: ubuntu-20.04
10+
runs-on: ubuntu-22.04
1111
strategy:
1212
fail-fast: false
1313
matrix:

c_src/lazy_html.cpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
227237
void 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);

test/lazy_html_test.exs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@ defmodule LazyHTMLTest do
154154
assert LazyHTML.to_html(lazy_html, skip_whitespace_nodes: true) ==
155155
"<p><span> Hello </span><span> world </span></p>"
156156
end
157+
158+
test "includes template children" do
159+
lazy_html =
160+
LazyHTML.from_fragment("<template><div>First</div><div>Second</div></template>")
161+
162+
assert LazyHTML.to_html(lazy_html) ==
163+
"<template><div>First</div><div>Second</div></template>"
164+
end
157165
end
158166

159167
describe "to_tree/2" do
@@ -174,6 +182,32 @@ defmodule LazyHTMLTest do
174182
{"div", [{"data-a", "a"}, {"data-b", "b"}, {"id", "root"}], ["Hello world"]}
175183
]
176184
end
185+
186+
test "includes template children" do
187+
lazy_html =
188+
LazyHTML.from_fragment("<template><div>First</div><div>Second</div></template>")
189+
190+
assert LazyHTML.to_tree(lazy_html) == [
191+
{"template", [], [{"div", [], ["First"]}, {"div", [], ["Second"]}]}
192+
]
193+
end
194+
end
195+
196+
describe "from_tree/2" do
197+
test "includes template children" do
198+
lazy_html =
199+
LazyHTML.from_tree([
200+
{"template", [], [{"div", [], ["First"]}, {"div", [], ["Second"]}]}
201+
])
202+
203+
assert inspect(lazy_html) == """
204+
#LazyHTML<
205+
1 node
206+
#1
207+
<template><div>First</div><div>Second</div></template>
208+
>\
209+
"""
210+
end
177211
end
178212

179213
describe "query/2" do

0 commit comments

Comments
 (0)