DEV Community

loading...

Indent (xml like) text with flatMap!

Attila Gonda
An atheist cylon who is trying to make it in the world. he/him
・2 min read

For a hobby-project I needed to indent an XML text which my code compiled and came up with a solution which is quite simple.

The input is an array with XML tags and all children nodes is nested inside other array.

A short example for that:

const input = [
    '<!DOCTYPE html>',
    '<html lang="en">',
    [
        '<head>',
        [
            '<title>Hello, World</title>',
        ],
        '</head>',
        '<body>',
        [
            '<h1>It works!</h1>',
        ],
        '</body>',
    ],
    '</html>',
];

And the output I wanted to achieve is this:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Hello, World</title>
    </head>
    <body>
        <h1>It works!</h1>
    </body>
</html>

With the given input, the following code would achieve the goal:


function indentText (nodes) {
    return Array.isArray(nodes)
        ? nodes.flatMap(indentText).map(node => '\t' + node)
        : nodes;
}

const output = input
    .flatMap(indentText)
    .join('\n');

console.log(output);

Walk-through on the callback:

  • A callback passed to the Array.prototype.flatMap will walk through all the items and expected to return an item or an array for flattening.
  • If the passed value is not an array, it just returns it back - because we want to maintain the value.
  • If it's an array, it's a whole other story: Because flatMap only works on the first level, the method calls itself recursively through flatMap to resolve the deeper layers.
    • The recursive call makes sure there will be no arrays inside the actual one, just text (assuming the input is correct)
    • Mapping the items and adding an indent prefix to them. On the deepest level it will add a single character on each item, which will be accumulated during the recursive call going up the levels

Discussion (3)

Collapse
chrisachard profile image
Chris Achard

Neat idea! I don't think I've ever used flatmap in this way - but will definitely think about it next time I have to recurse through something like this. Thanks :)

Collapse
pcdevil profile image
Attila Gonda Author

Thanks for the kind words! :)
This was a breakthrough for me: Previously I didn't understand how flatMap works, but when I thought about the problem it just *clicked* and I knew this will work flawlessly :))

Collapse
chrisachard profile image
Chris Achard

I love that feeling! It makes learning new things addicting :)