Quasi-cosmetic

This commit is contained in:
Tony Garnock-Jones 2023-12-03 23:40:36 +01:00
parent 0e26a8cd9f
commit be6dbd2782
1 changed files with 59 additions and 52 deletions

View File

@ -117,75 +117,82 @@ export class HtmlFragmentBuilder {
this.indexPlaceholders();
}
private indexTextNode(n: Text, path: number[]): ChildNode | null {
const { constantParts, placeholders } =
splitByPlaceholders(n.textContent ?? '');
constantParts.forEach((c, i) => {
if (i > 0) {
const placeholder = document.createElement('x-placeholder');
n.parentNode?.insertBefore(placeholder, n);
}
n.parentNode?.insertBefore(document.createTextNode(c), n);
});
const nextN = n.nextSibling;
n.parentNode?.removeChild(n);
placeholders.forEach((n, i) => {
const currentPath = path.slice();
currentPath[currentPath.length - 1] = i * 2 + 1;
this.placeholderActions.push({
path: currentPath,
action: nodeInserter(n),
});
});
path[path.length - 1] += constantParts.length + placeholders.length;
return nextN;
}
private indexElement(e: Element, path: number[]) {
const actions: PlaceholderAction[] = [];
for (let i = 0; i < e.attributes.length; i++) {
const attr = e.attributes[i];
const attrName = attr.name;
const nameIsPlaceholder = attrName.match(placeholderRe);
if (nameIsPlaceholder !== null) {
e.removeAttributeNode(attr);
i--;
const n = parseInt(nameIsPlaceholder[1], 10);
actions.push(attributesInserter(n));
} else {
const { constantParts, placeholders } =
splitByPlaceholders(attr.value);
if (constantParts.length !== 1) {
actions.push(attributeValueInserter(
attrName,
constantParts,
placeholders));
}
}
}
if (actions.length) {
this.placeholderActions.push({
path: path.slice(),
action: (vs, n) => actions.forEach(a => a(vs, n)),
});
}
}
private indexPlaceholders() {
const path: number[] = [];
const bump = (n: number) => path[path.length - 1] += n;
const walk = (parentNode: ParentNode) => {
path.push(0);
let nextN = parentNode.firstChild;
while (nextN !== null) {
const n = nextN;
switch (n.nodeType) {
case Node.TEXT_NODE: {
const { constantParts, placeholders } =
splitByPlaceholders(n.textContent ?? '');
constantParts.forEach((c, i) => {
if (i > 0) {
const placeholder = document.createElement('x-placeholder');
n.parentNode?.insertBefore(placeholder, n);
}
n.parentNode?.insertBefore(document.createTextNode(c), n);
});
nextN = n.nextSibling;
n.parentNode?.removeChild(n);
placeholders.forEach((n, i) => {
const currentPath = path.slice();
currentPath[currentPath.length - 1] = i * 2 + 1;
this.placeholderActions.push({
path: currentPath,
action: nodeInserter(n),
});
});
bump(constantParts.length + placeholders.length);
case Node.TEXT_NODE:
nextN = this.indexTextNode(n as Text, path);
break;
}
case Node.ELEMENT_NODE: {
const e = n as Element;
const actions: PlaceholderAction[] = [];
for (let i = 0; i < e.attributes.length; i++) {
const attr = e.attributes[i];
const attrName = attr.name;
const nameIsPlaceholder = attrName.match(placeholderRe);
if (nameIsPlaceholder !== null) {
e.removeAttributeNode(attr);
i--;
const n = parseInt(nameIsPlaceholder[1], 10);
actions.push(attributesInserter(n));
} else {
const { constantParts, placeholders } =
splitByPlaceholders(attr.value);
if (constantParts.length !== 1) {
actions.push(attributeValueInserter(
attrName,
constantParts,
placeholders));
}
}
}
if (actions.length) {
this.placeholderActions.push({
path: path.slice(),
action: (vs, n) => actions.forEach(a => a(vs, n)),
});
}
this.indexElement(e, path)
walk(e);
nextN = e.nextSibling;
bump(1);
path[path.length - 1]++;
break;
}
default:
nextN = n.nextSibling;
bump(1);
path[path.length - 1]++;
break;
}
}