1//=== ÐенеÑаÑÐ¸Ñ Ð¾Ð³Ð»Ð°Ð²Ð»ÐµÐ½Ð¸Ñ (TOC) без ÑпиÑка, Ñ ÑкоÑÑми, ÑмеÑением 80px и клаÑÑом articles-link === 2 3const tocContainer = document.querySelector(".toc-table"); 4const articleBlocks = document.querySelectorAll(".article-content"); 5let globalHeadingIndex = 0; 6 7function slugify(str) { 8 return String(str).toLowerCase().trim() 9 .replace(/[^\w\s-]/g, '') // ÑбÑаÑÑ Ð·Ð°Ð¿ÑеÑÑннÑе ÑÐ¸Ð¼Ð²Ð¾Ð»Ñ 10 .replace(/\s+/g, '-') // пÑÐ¾Ð±ÐµÐ»Ñ -> ÑиÑе 11 .replace(/-+/g, '-'); // повÑоÑÑÑÑиеÑÑ ÑиÑе -> одно 12} 13 14function toSlugRU(str) { 15 const map = { 16 'а':'a','б':'b','в':'v','г':'g','д':'d','е':'e','Ñ':'yo','ж':'zh','з':'z', 17 'и':'i','й':'j','к':'k','л':'l','м':'m','н':'n','о':'o','п':'p','Ñ':'r', 18 'Ñ':'s','Ñ':'t','Ñ':'u','Ñ':'f','Ñ ':'h','Ñ':'ts','Ñ':'ch','Ñ':'sh','Ñ':'sch', 19 'Ñ':'','Ñ':'y','Ñ':'','Ñ':'e','Ñ':'yu','Ñ':'ya' 20 }; 21 // 1) пÑиводим к ÑÑÑоке и к Ð½Ð¸Ð¶Ð½ÐµÐ¼Ñ ÑегиÑÑÑÑ 22 let s = String(str).trim().toLowerCase(); 23 // 2) ÑÑанÑлиÑеÑаÑиÑ: заменÑем каждÑÑ Ð±ÑÐºÐ²Ñ Ð¸Ð· map, оÑÑалÑное оÑÑавлÑем (лаÑиниÑа и ÑиÑÑÑ Ð¿ÑойдÑÑ) 24 s = s.split('').map(ch => map[ch] !== undefined ? map[ch] : ch).join(''); 25 // 3) заменÑем лÑбÑе небÑквенно-ÑиÑÑовÑе ÑÐ¸Ð¼Ð²Ð¾Ð»Ñ (кÑоме деÑиÑа) на деÑÐ¸Ñ 26 s = s.replace(/[^a-z0-9-]+/g, '-'); 27 // 4) ÑбиÑаем повÑоÑÑÑÑиеÑÑ Ð´ÐµÑиÑÑ Ð¸ обÑезаем кÑайние деÑиÑÑ 28 s = s.replace(/-+/g, '-').replace(/^-|-$/g, ''); 29 return s; 30} 31 32function createTOC() { 33 if (!tocContainer) return; 34 35 articleBlocks.forEach((block, blockIndex) => { 36 const headings = block.querySelectorAll("h2"); 37
38 headings.forEach((heading) => { 39 const title = heading.textContent.trim(); 40 const titleSlug = toSlugRU(title); 41 42 const anchorId = `toc-${blockIndex}-${globalHeadingIndex}-${titleSlug}`; 43 44 45 // ÑÑÑанавливаем id Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ° 46 heading.setAttribute("id", anchorId); 47 48 // ÑоздаÑм ÑÑÑÐ»ÐºÑ 49 const a = document.createElement("a"); 50 a.setAttribute("href", `#${anchorId}`); 51 a.textContent = title; 52 a.classList.add("articles-link"); // ✅ ÑолÑко один нÑжнÑй клаÑÑ 53 54 // Ð¿Ð»Ð°Ð²Ð½Ð°Ñ Ð¿ÑокÑÑÑка Ñо ÑмеÑением 80px 55 a.addEventListener("click", (e) => { 56 e.preventDefault(); 57 const target = document.getElementById(anchorId); 58 if (target) { 59 const yOffset = -120; // ÑмеÑение ввеÑÑ 60 const y = target.getBoundingClientRect().top + window.scrollY + yOffset; 61 window.scrollTo({ top: y, behavior: "smooth" }); 62 history.replaceState(null, "", `#${anchorId}`); 63 } 64 }); 65 66 tocContainer.appendChild(a); 67 globalHeadingIndex++; 68 }); 69 }); 70} 71 72// ÐапÑÑк 73if (tocContainer && articleBlocks.length > 0) { 74 createTOC(); 75}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.