I needed to generate the HTML strings from a tree object with proper indentation. e.g.
{
children: [
{ tag: 'div', children: [{ tag: 'span', children: ['bar1', 'bar2'] }] },
{ tag: 'div', children: ['baz'] },
],
tag: 'body',
}
would become
<body>
<div>
<span>
bar1
bar2
</span>
</div>
<div>
baz
</div>
</body>
Here is my attempt
function generateHTMLFrom(tree) {
const recur = (node, depth = 0, indent = ' ') => {
if (!node.children) return node
return [
`${indent.repeat(depth * 2)}`,
`<${node.tag}>`,
...node.children.flatMap((child) => recur(child, depth + 1)),
`${indent.repeat(depth * 2)}</${node.tag}>`,
]
}
return recur(tree).join('\n')
}
But the format is actually messed up because the indentation is all wrong
Can someone help me fix this?
You almost got it. I would recommend to take out complexity from your recursion to simplify it (no need, just for better readability).
Instead of multiplying depth * 2, you could initialize your argument with indent = ' '. And the first two lines of your returned array could combine in the way as you already did for the closing tag.
`${indent.repeat(depth)}<${node.tag}>`
And last but not least (your actual little mistake) the return value should not be node, it should be your node with an indentation:
return `${indent.repeat(depth)}${node}`;
You will end up with something like this:
const tree = {
tag: 'body',
children: [
{ tag: 'div', children: [ { tag: 'span', children: [ 'bar1', 'bar2' ] } ] },
{ tag: 'div', children: [ 'baz' ]
}
]
};
function generateHTML (tree) {
const recur = (node, depth=0, indent=' ') => {
if (!node.children) {
return `${indent.repeat(depth)}${node}`;
}
return [
`${indent.repeat(depth)}<${node.tag}>`,
...node.children.flatMap((child) => recur(child, depth + 1)),
`${indent.repeat(depth)}</${node.tag}>`
];
};
return recur(tree).join('\n');
}
console.log(generateHTML(tree));