<div id="tilda-toc-container">
<h3>Оглавление</h3>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {
// Ждём, пока Tilda полностью загрузит контент (в т.ч. AJAX-блоки)
setTimeout(generateTOC, 500); // небольшая задержка на случай динамической загрузки
});
function generateTOC() {
const container = document.getElementById("tilda-toc-container");
if (!container) return;
// Находим ВСЕ h2, h3, h4 на странице (кроме тех, что в самом TOC)
const headers = Array.from(
document.querySelectorAll("h2, h3, h4")
).filter(el => !el.closest("#tilda-toc-container"));
if (headers.length === 0) {
container.style.display = "none";
return;
}
// Генерация slug (поддержка кириллицы и латиницы)
function slugify(text) {
return text
.toLowerCase()
.replace(/[^\w\u0400-\u04FF\s-]/g, "") // оставляем буквы, цифры, кириллицу, пробелы, дефисы
.replace(/[\s_-]+/g, "-")
.replace(/^-+|-+$/g, "");
}
// Добавляем id ко всем заголовкам без id
headers.forEach(h => {
if (!h.id) {
let baseId = slugify(h.textContent);
let id = baseId;
let counter = 1;
while (document.getElementById(id)) {
id = baseId + "-" + counter++;
}
h.id = id;
}
});
// Создаём вложенное оглавление
const toc = document.createElement("ul");
toc.style.listStyle = "none";
toc.style.paddingLeft = "0";
toc.style.margin = "0";
let stack = [{ level: 1, element: toc }];
headers.forEach(header => {
const level = parseInt(header.tagName[1], 10); // 2, 3 или 4
const link = document.createElement("a");
link.href = "#" + header.id;
link.textContent = header.textContent;
link.style.textDecoration = "none";
link.style.color = "inherit";
link.style.display = "block";
link.style.padding = "4px 0";
// Добавляем обработчик плавной прокрутки
link.addEventListener("click", function (e) {
e.preventDefault();
const target = document.getElementById(header.id);
if (target) {
const yOffset = -80; // смещение вверх (чтобы не залезал под фиксированный хедер, если есть)
const y = target.getBoundingClientRect().top + window.scrollY + yOffset;
window.scrollTo({ top: y, behavior: "smooth" });
}
});
const li = document.createElement("li");
li.style.marginLeft = level === 2 ? "0" : level === 3 ? "16px" : "32px";
li.appendChild(link);
// Управление вложенностью
while (level < stack[stack.length - 1].level) {
stack.pop();
}
if (level > stack[stack.length - 1].level) {
const newUl = document.createElement("ul");
newUl.style.listStyle = "none";
newUl.style.paddingLeft = "0";
newUl.style.margin = "0";
stack[stack.length - 1].element.appendChild(newUl);
stack.push({ level: level, element: newUl });
}
stack[stack.length - 1].element.appendChild(li);
});
container.innerHTML = "<h3>Оглавление</h3>";
container.appendChild(toc);
}
</script>
<style>
#tilda-toc-container {
background: #f9f9f9;
padding: 16px;
border-radius: 8px;
margin-bottom: 24px;
font-family: inherit;
font-size: 16px;
}
#tilda-toc-container h3 {
margin-top: 0;
margin-bottom: 12px;
font-size: 18px;
}
</style>