In this series, How lit-html works, I will explore (not explain) internal implementation of lit-html.
In the previous post, we saw how getHTML()
method of TemplateResult
class handles attribute expressions and it cannot always parse comment-like string as expected.
In this post, I will explore the reparentNodes
function, which is also one that I skipped in the past post.
Recap of getTemplateElement()
method of SVGTemplateResult
class
getTemplateElement(): HTMLTemplateElement {
const template = super.getTemplateElement();
const content = template.content;
const svgElement = content.firstChild!;
content.removeChild(svgElement);
reparentNodes(content, svgElement.firstChild);
return template;
}
getTemplateElement()
method removes the redundant svg
element from the content of HTML template element, which is originally added by getHTML()
method.
If I passed this string to svg
tag function, the string returned by getHTML()
method is like that below.
const templateResult = svg`
<svg id="my-svg">
<circle cx="100" cy="100" r="100"/>
</svg>
<svg id="my-another-svg">
<circle cx="100" cy="100" r="100"/>
</svg>
`
console.log(templateResult.getHTML())
// =>
// <svg>
// <svg id="my-svg">
// <circle cx="100" cy="100" r="100"/>
// </svg>
// <svg id="my-another-svg">
// <circle cx="100" cy="100" r="100"/>
// </svg>
// </svg>
Then, the root svg
element added by getHTML()
method is removed from the content of the HTML template element.
const svgElement = content.firstChild;
content.removeChild(svgElement);
console.log(template)
// => shown like below and #document-fragment is empty...
// <template>
// #document-fragment
// </template>
After this process is the place where reparentNodes
function comes into play.
reparentNodes
function
reparentNodes
is called with the content
as container
and first child of the extra svg
element, in other words, svg
element whose id is my-svg
.
export const reparentNodes =
(container: Node,
start: Node|null,
end: Node|null = null,
before: Node|null = null): void => {
while (start !== end) {
const n = start!.nextSibling;
container.insertBefore(start!, before);
start = n;
}
};
In first while loop, since start
(svg
element whose id is my-svg
) is not the same as end
(null
), the element is inserted to the container
as the last child.
In second while loop, since start
(svg
element whose id is my-another-svg
) is also not the same as end
(null
), the element is inserted to the container
as the last child.
In third while loop, since start
(nextSibling
of the svg
element whose id is my-another-svg
) is the same as end
(null
), the loop breaks.
The reasons all the elements are inserted as the last child is that, as written in MDN, Node.insertBefore(newNode, referenceNode)
method inserts newNode
as the last child to the Node, if referenceNode
node is null
.
So, it is guaranteed that the order of elements of which the original string is consist of doesn't change.
Finally, the HTML template element is again consisted of the original elements without the redundant svg
element.
console.log(template)
// => shown like below...
// <template>
// #document-fragment
// <svg id="my-svg">
// <circle cx="100" cy="100" r="100"/>
// </svg>
// <svg id="my-another-svg">
// <circle cx="100" cy="100" r="100"/>
// </svg>
// </template>
reparentNodes
function is used in other places in lit-html so I will encounter it again later.
In addition, lit-html is exporting reparentNodes
function so that you can use this function as utility if you want (e.g. extending lit-html).
Summary
So far, I learned the following points:
- (Again)
getHTML()
method ofSVGTemplateResult
class adds a extrasvg
element to the original template so that it can be parsed in the correct namespace. -
getTemplateElement()
method returns template element, with only the extrasvg
element removed. - Part of this unwrapping operation is done by
reparentNodes
function, which is exported, and is available to developers.
Now, I've explored all the methods of TemplateResult
and SVGTemplateResult
class.
From the next post, I will dive into the render
function, which is another essential part of lit-html, to know how the library renders the content of HTML template element to the real DOM tree.
Top comments (0)