1if (document.querySelector("main article")) { 2 document.addEventListener("DOMContentLoaded", () => { 3 const articles = Array.from(document.querySelectorAll("main article")); 4 if (articles.length === 0) return; 5 6 function getCurrentArticleIndex() { 7 const scrollY = window.scrollY; 8 9 let currentIndex = 0; 10 let smallestDistance = Infinity; 11 12 articles.forEach((article, i) => { 13 const rect = article.getBoundingClientRect(); 14 const distance = Math.abs(rect.top); 15 16 if (distance < smallestDistance) { 17 smallestDistance = distance; 18 currentIndex = i; 19 } 20 }); 21 22 return currentIndex; 23 } 24 25 function scrollToArticle(index) { 26 if (index < 0 || index >= articles.length) return; 27 const article = articles[index]; 28 article.scrollIntoView({ behavior: "smooth", block: "start" }); 29 30 const link = article.querySelector("header h1 a"); 31 if (!link) return; 32 33 setTimeout(() => { 34 link.classList.add("flash"); 35 setTimeout(() => { 36 link.classList.remove("flash"); 37 }, 600); 38 }, 500); 39 } 40 41 document.addEventListener("keydown", (e) => { 42 if (e.target.tagName.toLowerCase() === "input" || e.target.tagName.toLowerCase() === "textarea") return; 43 const key = e.key.toLowerCase(); 44 const currentIndex = getCurrentArticleIndex(); 45 46 if (key === "j") { 47 scrollToArticle(currentIndex + 1); 48 } else if (key === "k") { 49 scrollToArticle(currentIndex - 1); 50 } 51 }); 52 }); 53} 54
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.