docbook / xslTNG

DocBook xslTNG Stylesheets
https://xsltng.docbook.org
MIT License
41 stars 20 forks source link

Scroll into view of persistent toc is not working #451

Closed mrotteveel closed 5 months ago

mrotteveel commented 5 months ago

I upgraded my documentation from xslTNG 1.5.4 to 2.1.9, and now the scroll into view of the persistent toc is no longer working.

In my browser console, the following is reported:

ToC scroll, no match: file/documentation/chunk/en/refdocs/fblangref50/fblangref50-ddl-table.html#fblangref50-ddl-tbl-alter

The match doesn't occur, because in the persistent-toc.html the href is fblangref50-ddl-table.html#fblangref50-ddl-tbl-alter, instead of the full path it's trying now.

Manually executing the following in my browser console will scroll it into view:

var target = document.querySelector("nav.toc div a[rel-path='fblangref50-ddl-table.html#fblangref50-ddl-tbl-alter']")
target.scrollIntoView()

Example of an affected document: https://firebirdsql.org/file/documentation/chunk/en/refdocs/fblangref50/firebird-50-language-reference.html

mrotteveel commented 5 months ago

I don't really program JavaScript, but I guess that changing the code in persistent-toc.js to the following will do the trick:

      let url = window.location.pathname;
      let hash = window.location.hash;
      if (window.location.search === "?toc") {
        // Remove ?toc from the URI so that if it's bookmarked,
        // the ToC reference isn't part of the bookmark.
        window.history.replaceState({}, document.title,
                                    window.location.origin
                                    + url
                                    + hash);
      }

      let path = url.substring(url.lastIndexOf('/') + 1) + hash;
      let target = document.querySelector("nav.toc div a[rel-path='"+path+"']");
      if (target) {
        target.scrollIntoView();
      } else if (hash === '') {
        target = document.querySelector("nav.toc div a[rel-path^='"+path+"']");
        if (target) {
          target.scrollIntoView();
        } else {
          console.log(`ToC scroll, no match: ${path}`);
        }
      } else {
        console.log(`ToC scroll, no match: ${path}`);
      }

NOTE: This also addresses another issue if the current location doesn't have a hash, but the entry in the toc has a hash, by retrying with ^= (starts with).

However, I don't know if this might be too naive for all cases.

ndw commented 5 months ago

Interesting. Thanks for the report. I need to sort out some unit testing for this, I guess. I'll try to investigate this evening.

mrotteveel commented 5 months ago

I locally tried my suggested workaround and it works for my documentation. I will leave the document linked above as-is for the time being for reference.

ndw commented 5 months ago

It's curious. I have reproduced the problem, but it was in some sense the opposite of what you reported. My test case was looking for ptoc-001.html#id when the persistent ToC only contained #id. I don't actually see how the persistent ToC can contain href values that don't have hashes. But I've adapted your approach to handle all three cases: path#id, #id, path. It probably needs a more thoughtful solution, but this seems better than leaving it broken.

mrotteveel commented 2 months ago

Unfortunately the change in 2.2.0 did not fix this issue for me, so I'm now using the fix I proposed initially in a custom JS file set with persistent-toc-js.