#html #node.js #cheerio
#HTML #node.js #приветствие
Вопрос:
У меня есть HTML, который выглядит следующим образом:
<h1>Title</h1>
<p>Some additional content, can be multiple, various tags</p>
<h2><a id="123"></a>Foo</h2>
<p>Some additional content, can be multiple, various tags</p>
<h3><a id="456"></a>Bar</h3>
Теперь, для каждого якоря с идентификатором, я хочу выяснить иерархию заголовков, например, для якоря с id="123"
я хотел бы получить что-то вроде [{level: 1, title: "Title"}, {level: 2, title: "Foo"}]
, аналогично для якоря с id="456"
, я хотел бы получить [{level: 1, title: "Title"}, {level: 2, title: "Foo"}, {level: 3, title: "Bar"}]
.
Мой код пока выглядит так:
const linkModel: IDictionary<ILinkModelEntry> = {};
const $ = cheerio.load(html);
$("a").each((_i, elt) => {
const anchor = $(elt);
const id = anchor.attr().id;
if (id) {
const parent = anchor.parent();
const parentTag = parent.prop("tagName");
let headerHierarchy: any[] = [];
if (["H1", "H2", "H3", "H4", "H5", "H6"].includes(parentTag)) {
let level = parseInt(parentTag[1]);
headerHierarchy = [{level, text: parent.text()}];
level--;
while (level > 0) {
const prevHeader = parent.prev("h" level);
const text = prevHeader.text();
headerHierarchy.unshift({level, text});
level--;
}
}
linkModel["#" id] = {originalId: id, count: count , headerHierarchy};
}
});
Что я делаю не так, поскольку
const prevHeader = parent.prev("h" level);
const text = prevHeader.text();
всегда возвращает пустую строку (т.е. ""
)?
Комментарии:
1. Вы можете сделать это с
closest()
помощью, но на самом деле вы хотите выполнить итерацию с самогоh1
начала. Возврат вверх по дереву — признак того, что вы не очень эффективны.2. Вы имеете в виду использовать
const prevHeader = parent.closest("h" level);
вместо.prev
? Похоже, тоже не работает… Ваше предложение состояло бы в том, чтобы перебирать каждый уровень заголовка и находить привязки ниже соответствующего уровня заголовка? Еще не думал о реализации, но я предполагаю, что реализация может стать очень запутанной … (не то, чтобы моя текущая реализация была очень чистой …)3. В примере ближайший заголовок будет:
$(elt).closest('h1,h2,h3,h4,h5,h6').first()
4. Спасибо. Но как я могу получить всю иерархию? Например, для
<h2>Foo</h2><h3><a id="1"></a><a id="2"></a><a id="3"></a>Bar</h3>
этого всегда будет возвращатьсяBar
, но нетFoo
(использование.closest("h2")
on$(elt)
не работает)