From 2d7873510947895ec27f3ca829430df3bd6a474c Mon Sep 17 00:00:00 2001 From: clee2000 <44682903+clee2000@users.noreply.github.com> Date: Mon, 14 Jul 2025 15:47:55 -0700 Subject: [PATCH 1/2] Change how ipynb download link is found (#206) sphinx gallery 0.11.1 puts it 2nd, but 0.17.1 puts it first, so the wrong link gets used Made change in js/theme.js then ran `grunt build` and a bunch of stuff got generated, no idea if that's correct, so I ended up not committing the `grunt build` changes and just made the change manually in the static folder --- js/theme.js | 18 +++++++++++++----- pytorch_sphinx_theme/static/js/theme.js | 17 +++++++++++++---- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/js/theme.js b/js/theme.js index 1c44e34c..b26200dc 100644 --- a/js/theme.js +++ b/js/theme.js @@ -250,10 +250,19 @@ if (downloadNote.length >= 1) { var tutorialUrlArray = $("#tutorial-type").text().split('/'); tutorialUrlArray[0] = tutorialUrlArray[0] + "_source" - var githubLink = "https://github.com/pytorch/tutorials/blob/master/" + tutorialUrlArray.join("/") + ".py", - notebookLink = $(".reference.download")[1].href, - notebookDownloadPath = notebookLink.split('_downloads')[1], - colabLink = "https://colab.research.google.com/github/pytorch/tutorials/blob/gh-pages/_downloads" + notebookDownloadPath; + var githubLink = "https://github.com/pytorch/tutorials/blob/master/" + tutorialUrlArray.join("/") + ".py"; + var notebookLink = ""; + // some versions of sphinx gallery have different orders of the download + // links so we need to check if the link ends with .ipynb to find the + // correct one + for (var i = 0; i < $(".reference.download").length; i++) { + notebookLink = $(".reference.download")[i].href; + if (notebookLink.endsWith(".ipynb")) { + break; + } + } + var notebookDownloadPath = notebookLink.split('_downloads')[1]; + var colabLink = "https://colab.research.google.com/github/pytorch/tutorials/blob/gh-pages/_downloads" + notebookDownloadPath; $("#google-colab-link").wrap(""); $("#download-notebook-link").wrap(""); @@ -428,4 +437,3 @@ $(window).scroll(function () { } }); }); - diff --git a/pytorch_sphinx_theme/static/js/theme.js b/pytorch_sphinx_theme/static/js/theme.js index ceee8f06..1f071b84 100644 --- a/pytorch_sphinx_theme/static/js/theme.js +++ b/pytorch_sphinx_theme/static/js/theme.js @@ -945,10 +945,19 @@ if (downloadNote.length >= 1) { var tutorialUrlArray = $("#tutorial-type").text().split('/'); tutorialUrlArray[0] = tutorialUrlArray[0] + "_source" - var githubLink = "https://github.com/pytorch/tutorials/blob/master/" + tutorialUrlArray.join("/") + ".py", - notebookLink = $(".reference.download")[1].href, - notebookDownloadPath = notebookLink.split('_downloads')[1], - colabLink = "https://colab.research.google.com/github/pytorch/tutorials/blob/gh-pages/_downloads" + notebookDownloadPath; + var githubLink = "https://github.com/pytorch/tutorials/blob/master/" + tutorialUrlArray.join("/") + ".py"; + var notebookLink = ""; + // some versions of sphinx gallery have different orders of the download + // links so we need to check if the link ends with .ipynb to find the + // correct one + for (var i = 0; i < $(".reference.download").length; i++) { + notebookLink = $(".reference.download")[i].href; + if (notebookLink.endsWith(".ipynb")) { + break; + } + } + var notebookDownloadPath = notebookLink.split('_downloads')[1]; + var colabLink = "https://colab.research.google.com/github/pytorch/tutorials/blob/gh-pages/_downloads" + notebookDownloadPath; $("#google-colab-link").wrap(""); $("#download-notebook-link").wrap(""); From 54a4f469487c66f8c63582c4bf46142fbee0df7d Mon Sep 17 00:00:00 2001 From: Edward Yang Date: Thu, 15 Jan 2026 09:38:41 -0500 Subject: [PATCH 2/2] Use CSS only solution to handle anchor margin and speed up scroll Signed-off-by: Edward Yang --- js/scroll-to-anchor.js | 99 --------------------- pytorch_sphinx_theme/layout.html | 1 - pytorch_sphinx_theme/static/css/theme.css | 11 +++ pytorch_sphinx_theme/static/js/theme.js | 101 ---------------------- 4 files changed, 11 insertions(+), 201 deletions(-) delete mode 100644 js/scroll-to-anchor.js diff --git a/js/scroll-to-anchor.js b/js/scroll-to-anchor.js deleted file mode 100644 index da092e5c..00000000 --- a/js/scroll-to-anchor.js +++ /dev/null @@ -1,99 +0,0 @@ -// Modified from https://stackoverflow.com/a/13067009 -// Going for a JS solution to scrolling to an anchor so we can benefit from -// less hacky css and smooth scrolling. - -window.scrollToAnchor = { - bind: function() { - var document = window.document; - var history = window.history; - var location = window.location - var HISTORY_SUPPORT = !!(history && history.pushState); - - var anchorScrolls = { - ANCHOR_REGEX: /^#[^ ]+$/, - offsetHeightPx: function() { - var OFFSET_HEIGHT_PADDING = 20; - // TODO: this is a little janky. We should try to not rely on JS for this - return utilities.headersHeight() + OFFSET_HEIGHT_PADDING; - }, - - /** - * Establish events, and fix initial scroll position if a hash is provided. - */ - init: function() { - this.scrollToCurrent(); - // This interferes with clicks below it, causing a double fire - // $(window).on('hashchange', $.proxy(this, 'scrollToCurrent')); - $('body').on('click', 'a', $.proxy(this, 'delegateAnchors')); - $('body').on('click', '#pytorch-right-menu li span', $.proxy(this, 'delegateSpans')); - }, - - /** - * Return the offset amount to deduct from the normal scroll position. - * Modify as appropriate to allow for dynamic calculations - */ - getFixedOffset: function() { - return this.offsetHeightPx(); - }, - - /** - * If the provided href is an anchor which resolves to an element on the - * page, scroll to it. - * @param {String} href - * @return {Boolean} - Was the href an anchor. - */ - scrollIfAnchor: function(href, pushToHistory) { - var match, anchorOffset; - - if(!this.ANCHOR_REGEX.test(href)) { - return false; - } - - match = document.getElementById(href.slice(1)); - - if(match) { - var anchorOffset = $(match).offset().top - this.getFixedOffset(); - - $('html, body').scrollTop(anchorOffset); - - // Add the state to history as-per normal anchor links - if(HISTORY_SUPPORT && pushToHistory) { - history.pushState({}, document.title, location.pathname + href); - } - } - - return !!match; - }, - - /** - * Attempt to scroll to the current location's hash. - */ - scrollToCurrent: function(e) { - if(this.scrollIfAnchor(window.location.hash) && e) { - e.preventDefault(); - } - }, - - delegateSpans: function(e) { - var elem = utilities.closest(e.target, "a"); - - if(this.scrollIfAnchor(elem.getAttribute('href'), true)) { - e.preventDefault(); - } - }, - - /** - * If the click event's target was an anchor, fix the scroll position. - */ - delegateAnchors: function(e) { - var elem = e.target; - - if(this.scrollIfAnchor(elem.getAttribute('href'), true)) { - e.preventDefault(); - } - } - }; - - $(document).ready($.proxy(anchorScrolls, 'init')); - } -}; diff --git a/pytorch_sphinx_theme/layout.html b/pytorch_sphinx_theme/layout.html index ec98e804..008284e5 100644 --- a/pytorch_sphinx_theme/layout.html +++ b/pytorch_sphinx_theme/layout.html @@ -712,7 +712,6 @@

Resources

mobileTOC.bind(); pytorchAnchors.bind(); sideMenus.bind(); - scrollToAnchor.bind(); highlightNavigation.bind(); mainMenuDropdown.bind(); filterTags.bind(); diff --git a/pytorch_sphinx_theme/static/css/theme.css b/pytorch_sphinx_theme/static/css/theme.css index c04db2d2..592039c8 100644 --- a/pytorch_sphinx_theme/static/css/theme.css +++ b/pytorch_sphinx_theme/static/css/theme.css @@ -12591,4 +12591,15 @@ article.pytorch-article .tutorials-callout-container .btn.callout-button a { color: white; } +/* Scroll padding to account for fixed header when navigating to anchors */ +html { + scroll-padding-top: 90px; +} +@media screen and (min-width: 1201px) { + html { + /* page-level-bar (45px) + padding (20px) when fixed */ + scroll-padding-top: 65px; + } +} + /*# sourceMappingURL=theme.css.map */ diff --git a/pytorch_sphinx_theme/static/js/theme.js b/pytorch_sphinx_theme/static/js/theme.js index 1f071b84..695643f3 100644 --- a/pytorch_sphinx_theme/static/js/theme.js +++ b/pytorch_sphinx_theme/static/js/theme.js @@ -383,107 +383,6 @@ window.pytorchAnchors = { }; },{}],9:[function(require,module,exports){ -// Modified from https://stackoverflow.com/a/13067009 -// Going for a JS solution to scrolling to an anchor so we can benefit from -// less hacky css and smooth scrolling. - -window.scrollToAnchor = { - bind: function() { - var document = window.document; - var history = window.history; - var location = window.location - var HISTORY_SUPPORT = !!(history && history.pushState); - - var anchorScrolls = { - ANCHOR_REGEX: /^#[^ ]+$/, - offsetHeightPx: function() { - var OFFSET_HEIGHT_PADDING = 20; - // TODO: this is a little janky. We should try to not rely on JS for this - return utilities.headersHeight() + OFFSET_HEIGHT_PADDING; - }, - - /** - * Establish events, and fix initial scroll position if a hash is provided. - */ - init: function() { - this.scrollToCurrent(); - // This interferes with clicks below it, causing a double fire - // $(window).on('hashchange', $.proxy(this, 'scrollToCurrent')); - $('body').on('click', 'a', $.proxy(this, 'delegateAnchors')); - $('body').on('click', '#pytorch-right-menu li span', $.proxy(this, 'delegateSpans')); - }, - - /** - * Return the offset amount to deduct from the normal scroll position. - * Modify as appropriate to allow for dynamic calculations - */ - getFixedOffset: function() { - return this.offsetHeightPx(); - }, - - /** - * If the provided href is an anchor which resolves to an element on the - * page, scroll to it. - * @param {String} href - * @return {Boolean} - Was the href an anchor. - */ - scrollIfAnchor: function(href, pushToHistory) { - var match, anchorOffset; - - if(!this.ANCHOR_REGEX.test(href)) { - return false; - } - - match = document.getElementById(href.slice(1)); - - if(match) { - var anchorOffset = $(match).offset().top - this.getFixedOffset(); - - $('html, body').scrollTop(anchorOffset); - - // Add the state to history as-per normal anchor links - if(HISTORY_SUPPORT && pushToHistory) { - history.pushState({}, document.title, location.pathname + href); - } - } - - return !!match; - }, - - /** - * Attempt to scroll to the current location's hash. - */ - scrollToCurrent: function(e) { - if(this.scrollIfAnchor(window.location.hash) && e) { - e.preventDefault(); - } - }, - - delegateSpans: function(e) { - var elem = utilities.closest(e.target, "a"); - - if(this.scrollIfAnchor(elem.getAttribute('href'), true)) { - e.preventDefault(); - } - }, - - /** - * If the click event's target was an anchor, fix the scroll position. - */ - delegateAnchors: function(e) { - var elem = e.target; - - if(this.scrollIfAnchor(elem.getAttribute('href'), true)) { - e.preventDefault(); - } - } - }; - - $(document).ready($.proxy(anchorScrolls, 'init')); - } -}; - -},{}],10:[function(require,module,exports){ window.sideMenus = { rightMenuIsOnScreen: function() { return document.getElementById("pytorch-content-right").offsetParent !== null;