@@ -151,50 +151,54 @@ if (searchInput && searchResults) {
151151
152152 // Function to scroll to a specific line and highlight terms
153153 function scrollToLine(lineNumber, searchTerm) {
154- // Wait for the next frame to ensure content is rendered
155- requestAnimationFrame(() => {
156- const targetElement = document.querySelector('#L' + lineNumber);
157- if (targetElement) {
158- // Add a small delay to ensure content is fully rendered
159- setTimeout(() => {
160- targetElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
161- targetElement.classList.add('highlight-line');
162- setTimeout(() => targetElement.classList.remove('highlight-line'), 2000);
163-
164- // Highlight all matching terms on the page
165- const content = document.querySelector('.agda-content');
166- if (content && searchTerm) {
167- const regex = new RegExp(searchTerm, 'gi');
168- const walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT, null, false);
169- const nodesToHighlight = [];
170-
171- while (walker.nextNode()) {
172- const node = walker.currentNode;
173- if (node.textContent.match(regex)) {
174- nodesToHighlight.push(node);
175- }
154+ const targetElement = document.querySelector('.Agda .line:nth-child(' + (lineNumber - 1) + ')');
155+ if (targetElement) {
156+ // Remove any existing highlights
157+ document.querySelectorAll('.line.highlight-line').forEach(line => {
158+ line.classList.remove('highlight-line');
159+ });
160+
161+ // Add highlight to target line
162+ targetElement.classList.add('highlight-line');
163+
164+ // Scroll to the line
165+ targetElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
166+
167+ // Highlight matching terms
168+ if (searchTerm) {
169+ const content = document.querySelector('.agda-content');
170+ if (content) {
171+ const regex = new RegExp(searchTerm, 'gi');
172+ const walker = document.createTreeWalker(content, NodeFilter.SHOW_TEXT, null, false);
173+ const nodesToHighlight = [];
174+
175+ while (walker.nextNode()) {
176+ const node = walker.currentNode;
177+ if (node.textContent.match(regex)) {
178+ nodesToHighlight.push(node);
179+ }
180+ }
181+
182+ nodesToHighlight.forEach(node => {
183+ const span = document.createElement('span');
184+ span.className = 'search-term-highlight';
185+ span.innerHTML = node.textContent.replace(regex, match => '<mark>' + match + '</mark>');
186+ node.parentNode.replaceChild(span, node);
187+ });
188+
189+ // Remove highlights after 5 seconds
190+ setTimeout(() => {
191+ const highlights = document.querySelectorAll('.search-term-highlight');
192+ highlights.forEach(highlight => {
193+ const text = highlight.textContent;
194+ const textNode = document.createTextNode(text);
195+ highlight.parentNode.replaceChild(textNode, highlight);
196+ });
197+ targetElement.classList.remove('highlight-line');
198+ }, 5000);
176199 }
177-
178- nodesToHighlight.forEach(node => {
179- const span = document.createElement('span');
180- span.className = 'search-term-highlight';
181- span.innerHTML = node.textContent.replace(regex, match => '<mark>' + match + '</mark>');
182- node.parentNode.replaceChild(span, node);
183- });
184-
185- // Remove highlights after 5 seconds
186- setTimeout(() => {
187- const highlights = document.querySelectorAll('.search-term-highlight');
188- highlights.forEach(highlight => {
189- const text = highlight.textContent;
190- const textNode = document.createTextNode(text);
191- highlight.parentNode.replaceChild(textNode, highlight);
192- });
193- }, 5000);
194- }
195- }, 100); // Small delay to ensure content is rendered
196- }
197- });
200+ }
201+ }
198202 }
199203
200204 // Check for stored line number and search term on page load
@@ -212,6 +216,17 @@ if (searchInput && searchResults) {
212216 }, 100);
213217 });
214218
219+ // Check for line number in URL hash on page load
220+ window.addEventListener('load', () => {
221+ const hash = window.location.hash;
222+ if (hash.startsWith('#L')) {
223+ const lineNumber = parseInt(hash.substring(2));
224+ if (!isNaN(lineNumber)) {
225+ scrollToLine(lineNumber);
226+ }
227+ }
228+ });
229+
215230 // Close search when clicking outside or pressing Escape
216231 document.addEventListener('click', (e) => {
217232 if (e.target === searchOverlay) {
@@ -260,6 +275,21 @@ fs.readdirSync(AGDA_HTML_DIR).forEach(file => {
260275 <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500&display=swap" rel="stylesheet">`
261276 ) ;
262277
278+ // Wrap each line in the Agda content with a numbered div
279+ content = content . replace (
280+ / < p r e c l a s s = " A g d a " > ( [ \s \S ] * ?) < \/ p r e > / g,
281+ ( match , content ) => {
282+ const lines = content . split ( '\n' ) ;
283+ const numberedLines = lines . map ( line => {
284+ if ( line . trim ( ) === '' ) {
285+ return '<div class="line"></div>' ;
286+ }
287+ return `<div class="line">${ line } </div>` ;
288+ } ) . join ( '\n' ) ;
289+ return `<pre class="Agda">${ numberedLines } </pre>` ;
290+ }
291+ ) ;
292+
263293 // Add header, sidebar, and theme toggle
264294 content = content . replace (
265295 / < b o d y [ ^ > ] * > / ,
0 commit comments