Hoist actions
This commit is contained in:
parent
b336faff25
commit
0e26a8cd9f
|
@ -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 = `<x-dummy ${renderFragment(vs[n], true).join('')}></x-dummy>`;
|
||||
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<HtmlFragment>) {
|
||||
this.placeholderActions.forEach(a => a(variableParts, template));
|
||||
this.placeholderActions.forEach(({ path, action }) => {
|
||||
action(variableParts, followPath(template, path));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue