Hello ! I have attached a patch that solves this bug.
>From the commit message: It supports two formats: #L50 and #L50-L150 (The latter will highlight from line 50 to line 150). It also changes the hash if we click on a line, and if we click on a second line holding the SHIFT key, it will highlight the whole range, and update the hash as well, allowing one to share the URL. I have tested in Chromium 38, Iceweasel 31.2, and IE8 (I assume it should work for later versions of IE) Cheers -- Jason Pleau
>From 8bde6c68437ae6634297cdff321b495ed6e9a052 Mon Sep 17 00:00:00 2001 From: Jason Pleau <ja...@jpleau.ca> Date: Sat, 1 Nov 2014 10:44:24 -0400 Subject: [PATCH] add automatic line numbers from #Lxx location.hash It supports #L50 and #L50-L150 (The latter will highlight from line 50 to line 150). It also changes the hash if we click on a line, and if we click on a second line holding the SHIFT key, it will highlight the whole range, and update the hash as well. --- debsources/app/templates/source_file_code.inc.html | 117 ++++++++++++++++++++- 1 file changed, 112 insertions(+), 5 deletions(-) diff --git a/debsources/app/templates/source_file_code.inc.html b/debsources/app/templates/source_file_code.inc.html index 9ea5a88..17bd3d0 100644 --- a/debsources/app/templates/source_file_code.inc.html +++ b/debsources/app/templates/source_file_code.inc.html @@ -19,17 +19,14 @@ <tr> <td> <pre id="sourceslinenumbers">{% for i in range(1, nlines+1) -%} - <a id="L{{ i }}" href="#L{{ i }}">{{ i }}</a><br /> + <a id="L{{ i }}" href="#L{{ i }}" class="linenumber" data-line="{{ i }}">{{ i }}</a><br /> {%- endfor %}</pre> </td> <td> <pre><code id="sourcecode" class="{% if file_language -%} {{ file_language }}{% else %}no-highlight {%- endif %}">{% for (line, highlight) in code -%} - {% if highlight -%} - <span class="highlight">{{ line }}</span>{% else -%} - {{ line }} - {%- endif %} + <span id="line{{ loop.index }}" class="codeline {% if highlight -%} highlight {%- endif %}">{{ line }}</span> {%- endfor %}</code></pre> </td> {% if msg -%} @@ -46,3 +43,113 @@ {%- endif %} </tr> </table> + +<script type="text/javascript"> +function highlight_lines(start, end) { + // First, remove the highlight class from elements that already have it + var elements = document.querySelectorAll("span.highlight"); + for (i = 0; i < elements.length; ++i) { + var element = elements[i]; + element.className = element.className.replace(/\bhighlight\b/, ''); + } + + // Then, add the highlight class to elements that contain the lines we want to highlight + for (i = start; i <= end; ++i) { + var element = document.getElementById("line" + i); + element.className = element.className + " highlight "; + } +} + +var hash_changed = function(event, scroll) { + + event = typeof event !== 'undefined' ? event: null; + scroll = typeof scroll !== 'undefined' ? scroll: false; + + // Will match strings like #L15 and #L15-20 + var regex = /#L(\d+)(-L(\d+))*$/; + + var match = regex.exec(window.location.hash); + if (match != null) { + var first_line = second_line = null; + first_line = parseInt(match[1]); + + if (typeof match[3] !== 'undefined' && match[3].length > 0) { + second_line = parseInt(match[3]); + } else { + second_line = first_line; + } + + // If we get something like #L20-L15, just swap the two line numbers so the loop will work + if (second_line < first_line) { + var tmp = first_line; + first_line = second_line; + second_line = tmp; + } + + highlight_lines(first_line, second_line); + + if (scroll) { + window.scroll(0, document.getElementById("L"+first_line).offsetTop); + } + } +} + + +function change_hash_without_scroll(element, hash) { + // This is necessary because when changing window.location.hash, the window will + // scroll to the element's id if it matches the hash + var id = element.id; + element.id = id+'-tmpNoScroll'; + window.location.hash = hash; + element.id = id; +} + +var last_clicked; +var line_click_handler = function(event) { + if (event.preventDefault) { + event.preventDefault(); + } else { + event.returnValue = false; + } + + var callerElement = event.target || event.srcElement; + + if (!event.shiftKey || !last_clicked) { + last_clicked = callerElement; + change_hash_without_scroll(callerElement, "L" + callerElement.getAttribute('data-line')); + } else { + var first_line = parseInt(last_clicked.getAttribute('data-line')); + var second_line = parseInt(callerElement.getAttribute('data-line')); + + if (second_line < first_line) { + var tmp = first_line; + first_line = second_line; + second_line = tmp; + } + + change_hash_without_scroll(callerElement, "L" + first_line + "-L" + second_line); + } +}; + +var window_load_sourcecode = function(event) { + var line_numbers = document.querySelectorAll("a.linenumber"); + for (i = 0; i < line_numbers.length; ++i) { + var line_number_element = line_numbers[i]; + if (line_number_element.addEventListener) { + line_number_element.addEventListener('click', line_click_handler, false); + } else { + line_number_element.attachEvent('onclick', line_click_handler); + } + } +}; + +if (window.addEventListener) { + window.addEventListener('load', window_load_sourcecode, false); +} else { + window.attachEvent('onload', window_load_sourcecode); +} + +window.onhashchange = hash_changed; +hash_changed(null, true); + +</script> -- 2.1.1