Skip to content

Commit 8c600f8

Browse files
committed
👌 Add class to loaded document
1 parent 33cf46d commit 8c600f8

File tree

4 files changed

+87
-62
lines changed

4 files changed

+87
-62
lines changed

docs/_static/custom.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/** Hide the header and footer of the Sphinx documentation,
2+
when it is embedded in a sphinx-peek iframe.
3+
*/
4+
.sp-iframe-document .mobile-header,
5+
.sp-iframe-document .back-to-top,
6+
.sp-iframe-document .bottom-of-page,
7+
.sp-iframe-document .related-pages {
8+
display: none;
9+
}

docs/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@
1414
"light_logo": "logo-light-mode.png",
1515
"dark_logo": "logo-dark-mode.png",
1616
}
17+
html_css_files = ["custom.css"]

docs/index.rst

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Simply install and add ``sphinx_peek`` to your ``conf.py`` extensions list.
4141
.. important::
4242

4343
The scroll-to-target behaviour, inside the iframe,
44-
only works reliably for same-origin references, due to browser security restrictions (see `CORS reference <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>`__).
44+
only works reliably for same-origin_ or CORS_ enabled references.
4545

4646
To test the feature locally, rather than directly opening the ``.html`` file, you can serve the documentation using a simple HTTP server, e.g.:
4747

@@ -64,6 +64,18 @@ Also, the CSS of the peek modal can be customized (see `html_css_files <https://
6464
- ``.sp-iframe``: the iframe containing the target document
6565
- ``.sp-overlay``: the overlay that covers the rest of the page
6666

67+
After loading the page, into the iframe, the extension will also add a class ``.sp-iframe-document`` to the root document.
68+
This allows you to customize the CSS of the target document, e.g. to hide header and footer elements in the furo theme:
69+
70+
.. code-block:: css
71+
72+
.sp-iframe-document .mobile-header,
73+
.sp-iframe-document .back-to-top,
74+
.sp-iframe-document .bottom-of-page,
75+
.sp-iframe-document .related-pages {
76+
display: none;
77+
}
78+
6779
More Examples
6880
-------------
6981

@@ -83,3 +95,7 @@ A reference to :ref:`other:subsection` within a paragraph.
8395
:hidden:
8496

8597
other
98+
99+
100+
.. _CORS: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
101+
.. _same-origin: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy

src/sphinx_peek/assets/sphinx_peek.js

Lines changed: 60 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ document.addEventListener("DOMContentLoaded", function () {
8686
let link_target = this.getAttribute("data-sp-link");
8787
this.insertAdjacentHTML(
8888
"beforeend",
89-
`<div id="sp_overlay" class="sp-overlay"><div id="sp_modal" class="sp-modal"><iframe id="sp_preframe" class="sp-iframe" src="${link_target}" onload=scrollToContent(this)></iframe></div></div>`,
89+
`<div id="sp_overlay" class="sp-overlay"><div id="sp_modal" class="sp-modal"><iframe id="sp_preframe" class="sp-iframe" src="${link_target}" onload=onIframeLoad(this)></iframe></div></div>`,
9090
);
9191
// stop click event propagation on the preview window,
9292
// to prevent closing the preview if we resize it (treated as a click)
@@ -195,67 +195,66 @@ function setPreviewPosition(preview, anchor, config) {
195195
*
196196
* @param {HTMLIFrameElement} iframe - The iframe that was loaded.
197197
*/
198-
function scrollToContent(iframe) {
199-
var target = iframe.getAttribute("src");
200-
if (target === null) {
201-
console.warn(
202-
`Sphinx Peek: Cannot get iframe src attribute for '${target}'`,
203-
);
204-
return;
205-
}
206-
let targetIndex = target.indexOf("#");
207-
var targetId = target.substring(targetIndex + 1);
208-
if (targetIndex !== -1 && targetId !== "") {
209-
setTimeout(function () {
210-
// try to get iframe contentDocument (this is the same as iframe.contentWindow.document)
211-
// if we cannot access the iframe content, we cannot scroll to the target
212-
// this can happen if the iframe is not on the same domain, or the page is not being served, due to CORS
213-
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/contentDocument
214-
try {
215-
var contentDocument = iframe.contentDocument;
216-
} catch (e) {
217-
console.warn(
218-
`Sphinx Peek: Cannot access iframe contentDocument for '${target}': ${e}`,
219-
);
220-
return;
221-
}
222-
if (contentDocument === null) {
223-
console.warn(
224-
`Sphinx Peek: Cannot access iframe contentDocument for '${target}'`,
225-
);
226-
return;
227-
}
198+
function onIframeLoad(iframe) {
199+
setTimeout(function () {
200+
// try to get iframe contentDocument (this is the same as iframe.contentWindow.document)
201+
// if we cannot access the iframe content, we cannot scroll to the target
202+
// this can happen if the iframe is not on the same domain, or the page is not being served, due to CORS
203+
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/contentDocument
204+
try {
205+
var contentDocument = iframe.contentDocument;
206+
} catch (e) {
207+
console.info(
208+
`Sphinx Peek: Cannot access iframe contentDocument: ${e}`,
209+
iframe,
210+
);
211+
return;
212+
}
213+
if (contentDocument === null) {
214+
console.info("Sphinx Peek: Cannot access iframe contentDocument", iframe);
215+
return;
216+
}
228217

229-
// try to get the target element by id
230-
var element = contentDocument.getElementById(targetId);
231-
if (element === null) {
232-
console.warn(
233-
`Sphinx Peek: Anchor does not exist in iframe contentDocument: ${target}`,
234-
);
235-
return;
236-
}
218+
// add a class to the iframe document, so we can add CSS depending on it
219+
contentDocument.documentElement.classList.add("sp-iframe-document");
237220

238-
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView#behavior
239-
// Note this seems to have some differing behavior between browsers:
240-
// - Firefox (OSX arm64, 121.0): works as expected
241-
// - Chrome (OSX arm64, 120.0.6099.216):
242-
// - does not appear to respect the behavior "instant", i.e. the scrolling is visible
243-
// - Safari (OSX arm64, 17.2.1):
244-
// - it can sometimes scroll the parent page as well to bring the element to the top of parent page
245-
let scrollTop = window.document.documentElement.scrollTop;
246-
element.scrollIntoView({ behavior: "instant" });
247-
if (window.document.documentElement.scrollTop !== scrollTop) {
248-
// "fix" the Safari behavior by restoring the original scroll position
249-
// TODO this should also be done for all window parents, i.e. when opening nested iframes
250-
window.document.documentElement.scrollTo({
251-
top: scrollTop,
252-
behavior: "instant",
253-
});
221+
let src = iframe.getAttribute("src");
222+
if (src === null) {
223+
console.warn("Sphinx Peek: Cannot get iframe 'src' attribute", iframe);
224+
} else {
225+
let anchorIndex = src.indexOf("#");
226+
let anchorId = src.substring(anchorIndex + 1);
227+
if (anchorIndex !== -1 && anchorId !== "") {
228+
// try to get the anchor element by id
229+
let anchor = contentDocument.getElementById(anchorId);
230+
if (anchor === null) {
231+
console.warn(
232+
`Sphinx Peek: Anchor ${anchorId} does not exist in iframe contentDocument`,
233+
iframe,
234+
);
235+
return;
236+
}
237+
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView#behavior
238+
// Note this seems to have some differing behavior between browsers:
239+
// - Firefox (OSX arm64, 121.0): works as expected
240+
// - Chrome (OSX arm64, 120.0.6099.216):
241+
// - does not appear to respect the behavior "instant", i.e. the scrolling is visible
242+
// - Safari (OSX arm64, 17.2.1):
243+
// - it can sometimes scroll the parent page as well to bring the element to the top of parent page
244+
let scrollTop = window.document.documentElement.scrollTop;
245+
anchor.scrollIntoView({ behavior: "instant" });
246+
if (window.document.documentElement.scrollTop !== scrollTop) {
247+
// "fix" the Safari behavior by restoring the original scroll position
248+
// TODO this should also be done for all window parents, i.e. when opening nested iframes
249+
window.document.documentElement.scrollTo({
250+
top: scrollTop,
251+
behavior: "instant",
252+
});
253+
}
254+
// Note this was another solution proposed, but it does not seem to work
255+
// https://stackoverflow.com/questions/20956663/scrollintoview-to-apply-to-iframe-only/20958953#20958953
256+
// contentDocument.documentElement.scrollTop = element.offsetTop;
254257
}
255-
256-
// Note this was another solution proposed, but it does not seem to work
257-
// https://stackoverflow.com/questions/20956663/scrollintoview-to-apply-to-iframe-only/20958953#20958953
258-
// contentDocument.documentElement.scrollTop = element.offsetTop;
259-
}, 500);
260-
}
258+
}
259+
}, 200);
261260
}

0 commit comments

Comments
 (0)