#4362 [WiP] file.html: fix initial scroll & highlight
Closed 4 years ago by jlanda. Opened 5 years ago by jlanda.
jlanda/pagure fix-scoll-hl  into  master

@@ -1,1 +1,1 @@ 

- !function(n,e){"use strict";function t(){var n=e.createElement("style");n.type="text/css",n.innerHTML=u(".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}",[f,m,j]),e.getElementsByTagName("head")[0].appendChild(n)}function r(t){"interactive"===e.readyState||"complete"===e.readyState?l(t):n.addEventListener("DOMContentLoaded",function(){l(t)})}function l(t){try{var r=e.querySelectorAll("code.hljs");for(var l in r)r.hasOwnProperty(l)&&i(r[l],t)}catch(o){n.console.error("LineNumbers error: ",o)}}function i(n,e){if("object"==typeof n){e=e||{singleLine:!1};var t=e.singleLine?0:1;h(function(){s(n),n.innerHTML=o(n.innerHTML,t)})}}function o(n,e){var t=c(n);if(""===t[t.length-1].trim()&&t.pop(),t.length>e){for(var r="",l=0,i=t.length;l<i;l++)r+=u('<tr><td class="{0}"><a class="{1} {2}" {3}="{5}" href="#_{5}" id="_{5}"></div></td><td class="{4}"><div class="{1}">{6}</div></td></tr>',[p,v,m,j,g,l+1,t[l].length>0?t[l]:" "]);return u('<table class="{0}">{1}</table>',[f,r])}return n}function s(n){var e=n.childNodes;for(var t in e)if(e.hasOwnProperty(t)){var r=e[t];d(r.textContent)>0&&(r.childNodes.length>0?s(r):a(r.parentNode))}}function a(n){var e=n.className;if(/hljs-/.test(e)){for(var t=c(n.innerHTML),r=0,l="";r<t.length;r++){var i=t[r].length>0?t[r]:" ";l+=u('<span class="{0}">{1}</span>\n',[e,i])}n.innerHTML=l.trim()}}function c(n){return 0===n.length?[]:n.split(L)}function d(n){return(n.trim().match(L)||[]).length}function h(e){n.setTimeout(e,0)}function u(n,e){return n.replace(/\{(\d+)\}/g,function(n,t){return e[t]?e[t]:n})}var f="hljs-ln",v="hljs-ln-line notblue text-muted",g="hljs-ln-code pl-2",p="hljs-ln-numbers bg-light text-right pr-2 pl-2 border-right mr-3",m="hljs-ln-n",j="data-line-number",L=/\r\n|\r|\n/g;n.hljs?(n.hljs.initLineNumbersOnLoad=r,n.hljs.lineNumbersBlock=i,t()):n.console.error("highlight.js not detected!")}(window,document);

+ !function(e,n){"use strict";function t(t){try{var i=n.querySelectorAll("code.hljs");for(var l in i)i.hasOwnProperty(l)&&r(i[l],t)}catch(n){e.console.error("LineNumbers error: ",n)}}function r(e,n){if("object"==typeof e){var t=(n=n||{singleLine:!1}).singleLine?0:1;s(function(){(function e(n){var t=n.childNodes;for(var r in t)if(t.hasOwnProperty(r)){var l=t[r];o(l.textContent)>0&&(l.childNodes.length>0?e(l):i(l.parentNode))}})(e),e.innerHTML=function(e,n){var t=l(e);if(""===t[t.length-1].trim()&&t.pop(),t.length>n){for(var r="",i=0,o=t.length;i<o;i++)r+=a('<tr><td class="{0}"><a class="{1} {2}" {3}="{5}" href="#_{5}" id="_{5}"></div></td><td class="{4}"><div class="{1}">{6}</div></td></tr>',[h,d,f,g,u,i+1,t[i].length>0?t[i]:" "]);return a('<table class="{0}">{1}</table>',[c,r])}return e}(e.innerHTML,t)})}}function i(e){var n=e.className;if(/hljs-/.test(n)){for(var t=l(e.innerHTML),r=0,i="";r<t.length;r++){i+=a('<span class="{0}">{1}</span>\n',[n,t[r].length>0?t[r]:" "])}e.innerHTML=i.trim()}}function l(e){return 0===e.length?[]:e.split(m)}function o(e){return(e.trim().match(m)||[]).length}function s(n){e.setTimeout(function(){n(),document.dispatchEvent(new CustomEvent("lineNumbersLoaded"))},0)}function a(e,n){return e.replace(/\{(\d+)\}/g,function(e,t){return n[t]?n[t]:e})}var c="hljs-ln",d="hljs-ln-line notblue text-muted",u="hljs-ln-code pl-2",h="hljs-ln-numbers bg-light text-right pr-2 pl-2 border-right mr-3",f="hljs-ln-n",g="data-line-number",m=/\r\n|\r|\n/g;e.hljs?(e.hljs.initLineNumbersOnLoad=function(r){"interactive"===n.readyState||"complete"===n.readyState?t(r):e.addEventListener("DOMContentLoaded",function(){t(r)})},e.hljs.lineNumbersBlock=r,function(){var e=n.createElement("style");e.type="text/css",e.innerHTML=a(".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}",[c,f,g]),n.getElementsByTagName("head")[0].appendChild(e)}()):e.console.error("highlight.js not detected!")}(window,document); 

\ No newline at end of file

@@ -302,6 +302,14 @@ 

      window.location.hash = hash;

      return false;

    });

+   document.addEventListener("lineNumbersLoaded", function() {

+     var cls = "highlighted-line";

+     var lines = location.hash.substr(2).split('-').map(function (x) { return parseInt(x, 10) });

+     $("#_" + lines[0]).get(0).scrollIntoView();

+     for (var i = lines[lines.length - 1]; i >= lines[0]; i--) {

+       $('#_' + i).parent().parent().addClass(cls);

+     }

+   });

    </script>

  

  {% endblock %}

Fixes #4187 on files .

Approach: add a custom event fired when highlightjs-line-numbers.min.js fills the code block with line numbers & listen to the event for scroll + highlight just after this event.

If this seems reasonable I'll extend the solution to the rest of the templates where scroll on line numbers are used

Would there be a chance to get this change upstream? It would make it much easier when upgrading highlight.js in the future :)

Otherwise, the overall approach looks good :)

I'll try to merge the event part on upstream and maintaing a rebased fork with our modifications to simplify bumping on upstream updates.

I'll update this with the result

May I suggest another option? It's a bit different, and I don't know if it is working for everybody, but it leaves highlightjs-line-numbers as-is, so no need to keep a fork and the event listener can also be removed.

I just created a setTimeout of 100 ms and then run the function. This worked quite well for me at least :grinning: . Put below https://pagure.io/fork/jlanda/pagure/blob/6ae7898dcf9580704bac3a6cb9bfa0e915776c1d/f/pagure/templates/file.html#_270

let cls = "highlighted-line";
setTimeout(function() {
  if (location.hash !== '') {
    let lines = location.hash.substr(2).split('-').map((line) => { 
      $('[data-line-number=' + line + ']').closest('tr').addClass(cls);
      return line
    });
    $("#_" + lines[0]).get(0).scrollIntoView();
  }      
}, 100);

If this is working, you can even think of calling the updateHighlight() function. The only code you then have to add:

setTimeout(function() {
  lines = updateHighlight();
  if ( lines ) {
    $("#_" + lines[0]).get(0).scrollIntoView();
  }
}, 100);

Sorry for the late reply, didn't saw this

May I suggest another option? It's a bit different, and I don't know if it is working for everybody, but it leaves highlightjs-line-numbers as-is, so no need to keep a fork and the event listener can also be removed.

We already maintain a fork, the line link thing is pagure's customization :)

I just created a setTimeout of 100 ms and then run the function. This worked quite well for me at least 😀 . Put below https://pagure.io/fork/jlanda/pagure/blob/6ae7898dcf9580704bac3a6cb9bfa0e915776c1d/f/pagure/templates/file.html#_270
let cls = "highlighted-line";
setTimeout(function() {
if (location.hash !== '') {
let lines = location.hash.substr(2).split('-').map((line) => {
$('[data-line-number=' + line + ']').closest('tr').addClass(cls);
return line
});
$("#_" + lines[0]).get(0).scrollIntoView();
}
}, 100);

If this is working, you can even think of calling the updateHighlight() function. The only code you then have to add:
setTimeout(function() {
lines = updateHighlight();
if ( lines ) {
$("#_" + lines[0]).get(0).scrollIntoView();
}
}, 100);

The timeout works unless the user's navigator needs more than 100msecs to replace all the line, otherwise it will try to scroll to a non existent html id.

I would prefer a more deterministic solution than waiting a fixed time.

The big problem here to include our changes on upstream right now is that we are using an tag and an html id that are not on upstream.

Anyhow, I don't like at all how is this minimized js file handled on our side, so I'll star from fixing that with our own repo for it so we can maintain this vendor js on a simpler way, so I'll close this PR and return to fix #4187 once we solve the maintenance hell that this file actually needs.

Pull-Request has been closed by jlanda

4 years ago