diff --git a/packages/html2/src/html.ts b/packages/html2/src/html.ts
index 934e630..e32a51a 100644
--- a/packages/html2/src/html.ts
+++ b/packages/html2/src/html.ts
@@ -57,11 +57,10 @@ function followPath(topNodes: ChildNode[], path: number[]): Node {
return n;
}
-type PlaceholderAction = (variableParts: HtmlFragment[], topNodes: ChildNode[]) => void;
+type PlaceholderAction = (variableParts: HtmlFragment[], node: Node) => void;
-function nodeInserter(n: number, path: number[]): PlaceholderAction {
- return (vs, topNodes) => {
- const node = followPath(topNodes, path);
+function nodeInserter(n: number): PlaceholderAction {
+ return (vs, node) => {
function walk(f: HtmlFragment) {
if (Array.isArray(f)) {
f.forEach(walk);
@@ -80,9 +79,8 @@ function nodeInserter(n: number, path: number[]): PlaceholderAction {
};
}
-function attributesInserter(n: number, path: number[]): PlaceholderAction {
- return (vs, topNodes) => {
- const node = followPath(topNodes, path);
+function attributesInserter(n: number): PlaceholderAction {
+ return (vs, node) => {
const e = document.createElement('template');
e.innerHTML = ``;
Array.from(e.attributes).forEach(a =>
@@ -94,10 +92,8 @@ function attributeValueInserter(
attrName: string,
constantParts: string[],
placeholders: number[],
- path: number[],
): PlaceholderAction {
- return (vs, topNodes) => {
- const node = followPath(topNodes, path);
+ return (vs, node) => {
const pieces = [constantParts[0]];
placeholders.forEach((n, i) => {
pieces.push(...renderFragment(vs[n], false));
@@ -109,7 +105,7 @@ function attributeValueInserter(
export class HtmlFragmentBuilder {
template: HTMLTemplateElement = document.createElement('template');
- placeholderActions: PlaceholderAction[] = [];
+ placeholderActions: { path: number[], action: PlaceholderAction }[] = [];
constructor(constantParts: TemplateStringsArray) {
const pieces: string[] = [];
@@ -145,15 +141,17 @@ export class HtmlFragmentBuilder {
placeholders.forEach((n, i) => {
const currentPath = path.slice();
currentPath[currentPath.length - 1] = i * 2 + 1;
- this.placeholderActions.push(nodeInserter(n, currentPath));
+ this.placeholderActions.push({
+ path: currentPath,
+ action: nodeInserter(n),
+ });
});
bump(constantParts.length + placeholders.length);
break;
}
case Node.ELEMENT_NODE: {
- const currentPath = path.slice();
const e = n as Element;
- // TODO: hoist all actions for this node into a single action
+ const actions: PlaceholderAction[] = [];
for (let i = 0; i < e.attributes.length; i++) {
const attr = e.attributes[i];
const attrName = attr.name;
@@ -162,19 +160,24 @@ export class HtmlFragmentBuilder {
e.removeAttributeNode(attr);
i--;
const n = parseInt(nameIsPlaceholder[1], 10);
- this.placeholderActions.push(attributesInserter(n, currentPath));
+ actions.push(attributesInserter(n));
} else {
const { constantParts, placeholders } =
splitByPlaceholders(attr.value);
if (constantParts.length !== 1) {
- this.placeholderActions.push(attributeValueInserter(
+ actions.push(attributeValueInserter(
attrName,
constantParts,
- placeholders,
- currentPath));
+ placeholders));
}
}
}
+ if (actions.length) {
+ this.placeholderActions.push({
+ path: path.slice(),
+ action: (vs, n) => actions.forEach(a => a(vs, n)),
+ });
+ }
walk(e);
nextN = e.nextSibling;
bump(1);
@@ -197,7 +200,9 @@ export class HtmlFragmentBuilder {
}
update(template: ChildNode[], variableParts: Array) {
- this.placeholderActions.forEach(a => a(variableParts, template));
+ this.placeholderActions.forEach(({ path, action }) => {
+ action(variableParts, followPath(template, path));
+ });
}
}