Вопрос №7617 от пользователя Константин Бочинин в уроке «Проект HTML Builder», курс «JS: Прототипы»
Мне не хватило глубины погружения. Должен быть где-то рекурсивный процесс погружения и дальше подъем.
const typeOfTopTag = ([tag, inner, content]) => {
if (Array.isArray(inner) || Array.isArray(content)) {
return "wrapper";
}
if (typeof tag === "string" && typeof inner === "string") {
return "simple";
}
if (typeof tag === "string" && typeof inner === "object" && typeof content === "string") {
return "styled";
}
};
const buildHtml = arr => {
return arr.reduce((acc, node, i, [tag, inner, content]) => {
if (typeOfTopTag(arr) === "simple") {
return `<${tag}>${inner}</${tag}>`;
}
if (typeOfTopTag(arr) === "styled") {
return `<${tag} class = "${inner.class}">${content}</${tag}>`;
}
if (typeOfTopTag(arr) === "wrapper" && Array.isArray(tag)) {
return acc + buildHtml(node);
}
//**ТУТ ПРОВАЛИВАЮСЬ***
if (typeof tag === "string") {
return `<${tag}>` + '\n' + buildHtml(...inner) + '\n' + `</${tag}>`;
}
}, "");
};
На последнем if
проваливаюсь html>meta>title
и вылезти не могу. Как-то не так сделано :\
Вывод такой:
<html>
<meta>
<title>hello, hexlet!</title>
</meta>
</html>
В циклах был break
(ну или что-то вроде) и дальше всплываешь на уровень выше, а тут как всплыть?
С вводом ниже все работает:
const Tag = ['meta', [ ['title', 'hello, hexlet!'], ] ];
const Tag0 = ['h1', { class: 'header' }, 'html builder example'];
const Tag1 = ['title', 'hello, hexlet!'];
const Tag2 = [['title', 'hello, hexlet!'], ['title', 'hello, hexlet!']];
const Tag3 = [['title', 'hello, hexlet!'], ['title', 'hello, hexlet!'], ['title', 'hello, hexlet!']];
const Tag4 = ['div',[['span', 'span text2'], ['span', 'span text3'],]];
const Tag5 = ['h1', { class: 'header' }, 'html builder example'];
Давайте по порядку:
[tag, inner, content]
- правильно понимаю, что в разные моменты времени под одним и тем же именем могут находиться совершенно разные сущности? Ведь состав конкретного тега и позиции составляющих его частей не зафиксированы. Что такоеinner
? Почему вы ушли от терминологии предметной области: children, attributes, body? В целом именование в вашем коде резко ухудшает его читабельность.typeof tag === "string"
- что такоеtag
и зачем нужна проверка его типа? Имя тега есть абсолютно в каждом теге, и оно всегда является строкой.class = "${inner.class}"
- строку атрибутов надо формировать отдельно (выделить функцию для этого). Такое ручное формирование не пройдёт. Атрибуты - это объект, в котором может быть множество (более одного) атрибутов (причём разных видов: не толькоclass
, но иid
и многих других).typeOfTopTag(arr) === "simple"
- с помощью reduce вы делаете перебор элементов входного массива (они не являются нодами (node)), при этом внутри идёт проверка самогоarr
: если это условие является истинным, то оно будет истинным на каждом новом перебираемом элементе, ведь значение arr не меняется. Вообще, неясно, зачем это делать, похоже, вы некорректно используете функциюreduce
.return
<${tag}>${inner}</${tag}>;
- в нескольких операторах return отсутствует аккумулятор acc, таким образом по логике работы функции reduce весь предыдущий накопленный результат теряется.<${tag}>
+ '\n' + buildHtml(...inner) + '\n' +</${tag}>
- переносы строки не нужны, просто строчка html-кода- Попробуйте определять не "тип тега", а "тип элемента тега" (тело, атрибуты, вложенный тег) и отталкиваться от этого.
Почитайте весь раздел (Вопросы и ответы) с комментариями, процитирую то, что уже неоднократно здесь писал: "Попробуйте для начала реализовать функцию для простого (и базового!) случая, когда на вход подаётся тег без вложенных в него других тегов. Т.е. этот тег может содержать attributes, body, но_без_children. Сделайте так, чтобы функция, приняв его, просто вернула строковое представление (как в html).
Сделав это, далее уже легче масштабироваться до обработки сложных тегов, имеющих children (другие теги). Делается это с помощью рекурсии."
Используйте Хекслет по максимуму!
- Задавайте вопросы по уроку
- Проверяйте знания в квизах
- Проходите практику прямо в браузере
- Отслеживайте свой прогресс
Зарегистрируйтесь или войдите в свой аккаунт
С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.







