I've been thinking over this "simple" exercise for a few days and have gotten really stuck. It's driven me really crazy. I need to convert nested arrays into HTML. Here is an example of an array:
const data = ['html', [
['head', [
['title', 'Your title text goes here'],
]],
['body', { class: 'container' }, [
['h1', { class: 'header' }, 'h1 text'],
['div', [
['span', 'span text2'],
['span', 'span text3'],
]],
]],
]];
and the expected result should be like this:
<html>
<head>
<title>your title text</title>
</head>
<body class="container">
<h1 class="header">h1 text</h1>
<div>
<span>span text2</span>
<span>span text3</span>
</div>
</body>
</html>
I've started with a helper function (create each tag from an Array), here is how it looks now:
const tagBuilder = (arr) => {
console.log(arr)
// ['div']; ==> <div></div>
if(arr.length === 1) {
return `<${arr[0]}></${arr[0]}>`
}
// Maximum length of the pure array (without nested children) is - 3
return arr.length === 3
// ['h1', { class: 'header' }, 'html builder example']
? `<${arr[0]} class="${arr[1].class}">${arr[2]}</${arr[0]}>`
// ['h1', { class: 'header' }]
: arr.length === 2 && typeof arr[1] === 'object'
? `<${arr[0]} class="${arr[1].class}"></${arr[0]}>`
// ['h1', 'header - text']
: `<${arr[0]}>${arr[1]}</${arr[0]}>`
}
It works fine so far. The tricky part starts when I'm trying to create the actual HTML builder function. I want to iterate through each element of the array, check if it has a nested element (child), save the specified tag, and go deeper.
const buildHTML = (array) => {
let acc = ""
const iterator = (arr) => {
for(const el of arr) {
}
}
iterator(array)
return acc;
}
So far I can iterate and save the HTML structure without nested arrays, but it breaks when an Array has children. I was trying "reduce" and nested "map" but no luck. Could you please point me to the solution or to the right way to explore? My guess is that the final function should look like this:
const textAndArrChild = ['div',
['span', 'span text3']];
// <div><span>span text3</span></div>
const tagBuilder = (arr) => {
// ['div']; ==> <div></div>
if(arr.length === 1) {
return `<${arr[0]}></${arr[0]}>`
}
// Maximum length of the pure array (without nested children) is - 3
return arr.length === 3
// ['h1', { class: 'header' }, 'html builder example']
? `<${arr[0]} class="${arr[1].class}">${arr[2]}</${arr[0]}>`
// ['h1', { class: 'header' }]
: arr.length === 2 && typeof arr[1] === 'object'
? `<${arr[0]} class="${arr[1].class}"></${arr[0]}>`
// ['h1', 'header - text']
: `<${arr[0]}>${arr[1]}</${arr[0]}>`
}
const buildHTML = (array) => {
return array.reduce((acc, el, index, arr) => {
if(typeof el === 'string' && Array.isArray(arr[index + 1])) {
acc = tagBuilder([el]);
// return acc += el.map(buildHTML) // TODO cause error
// need to iterate through the nested array
} else {
// insert pure tags from an array into the acc
}
return acc;
}, "")
}
console.log(buildHTML(textAndArrChild))