-
-
Notifications
You must be signed in to change notification settings - Fork 476
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
gh-36144: Revive sage live doc using jupyter-sphinx
<!-- ^^^^^ Please provide a concise, informative and self-explanatory title. Don't put issue numbers in there, do this in the PR body below. For example, instead of "Fixes #1234" use "Introduce new method to calculate 1+1" --> <!-- Describe your changes here in detail --> We fix #33320 and #24367. We also upgrade jupyter-sphinx standard package to the latest version 0.4.0: https://github.com/jupyter/jupyter-sphinx/releases/tag/v0.4.0, and patch it to facilitate live doc. By default, live doc depends on https://github.com/sagemath/sage-binder- env for binder (remote jupyter server). To showcase the live doc, we edited "A Tour of Sage" doc and some parts of sage doc. Visit - https://deploy-preview-36144--sagemath- tobias.netlify.app/a_tour_of_sage or - https://deploy-preview-36144--sagemath- tobias.netlify.app/tutorial/latex (edited to resolve #24367) **Click the activate button to activate live doc** The button is hidden to the right middle side of the browser. After clicked, the activate button shows the status of the launching kernel. **Be patient if the kernel loads slow. It may take several minutes.** Sometimes it may be stuck in the "launching" state. In that case, reload the page and try again. Note that `%display latex` is the default. You should use `%display plain` to get plain textual output. ## Preparation ``` ./sage -i jupyterlab ``` If things do not work as expected, first remove the existing documentation by ``` make doc-clean doc-uninstall ``` ## Build static doc ``` export SAGE_LIVE_DOC=no # default make -j4 ``` ## Build live doc with the default Binder repo ``` export SAGE_LIVE_DOC=yes export SAGE_JUPYTER_SERVER=binder # default make -j4 ``` ## Build live doc with a custom Binder repo ``` export SAGE_LIVE_DOC=yes export SAGE_JUPYTER_SERVER=binder:sagemath/sage-binder-env # default make -j4 ``` The kernel is "sagemath". ## Build live doc with a local server ``` export SAGE_LIVE_DOC=yes export SAGE_JUPYTER_SERVER=http://localhost:8889 export SAGE_JUPYTER_SERVER_TOKEN=secret # default make -j4 ``` and run a local jupyter server before browsing the documentation. ``` ./sage --notebook=jupyterlab \ --ServerApp.token='secret' \ --ServerApp.allow_origin='null' \ --ServerApp.disable_check_xsrf=true \ --ServerApp.port=8889 \ --ServerApp.open_browser=false ``` ## Build live doc selectively First build static doc ``` make -j4 ``` and then build live doc selectively either by ``` ./sage --docbuild --live-doc a_tour_of_sage html ``` or ``` export SAGE_JUPYTER_SERVER=http://localhost:8889 export SAGE_JUPYTER_SERVER_TOKEN=secret # default ./sage --docbuild --live-doc a_tour_of_sage html ``` with a local server. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> <!-- If your change requires a documentation PR, please link it appropriately --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> <!-- Feel free to remove irrelevant items. --> - [x] The title is concise, informative, and self-explanatory. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [x] I have updated the documentation accordingly. Related upstream issues: - jupyter/jupyter-sphinx#201 - jupyter/jupyter-sphinx#231 URL: #36144 Reported by: Kwankyu Lee Reviewer(s): github-actions[bot], Kwankyu Lee, Matthias Köppe
- Loading branch information
Showing
22 changed files
with
915 additions
and
964 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
tarball=jupyter_sphinx-VERSION.tar.gz | ||
sha1=241f6dfcd3aae4f44f330e2ba76480011b382d3d | ||
md5=e7ab370d9793be5b20bce5447ccbd45b | ||
cksum=2021246952 | ||
sha1=fb2abdd5e35da0886b12d45a6373c4dbcc24b244 | ||
md5=130daa6be810976c9f8e30aa04011e50 | ||
cksum=2882523000 | ||
upstream_url=https://pypi.io/packages/source/j/jupyter_sphinx/jupyter_sphinx-VERSION.tar.gz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
0.3.2 | ||
0.4.0.p0 |
57 changes: 57 additions & 0 deletions
57
build/pkgs/jupyter_sphinx/patches/0001-Patch-for-sage-live-doc.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
From 5bffbe38302c695123779f87300d84090b4bd118 Mon Sep 17 00:00:00 2001 | ||
From: Kwankyu Lee <[email protected]> | ||
Date: Mon, 28 Aug 2023 00:18:59 +0900 | ||
Subject: [PATCH] Patch for sage live doc | ||
|
||
--- | ||
jupyter_sphinx/__init__.py | 4 ++-- | ||
jupyter_sphinx/execute.py | 11 +++++++++++ | ||
2 files changed, 13 insertions(+), 2 deletions(-) | ||
|
||
diff --git a/jupyter_sphinx/__init__.py b/jupyter_sphinx/__init__.py | ||
index 34af884..b7ca8ee 100644 | ||
--- a/jupyter_sphinx/__init__.py | ||
+++ b/jupyter_sphinx/__init__.py | ||
@@ -31,7 +31,7 @@ from .thebelab import ThebeButton, ThebeButtonNode, ThebeOutputNode, ThebeSource | ||
REQUIRE_URL_DEFAULT = ( | ||
"https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js" | ||
) | ||
-THEBELAB_URL_DEFAULT = "https://unpkg.com/thebelab@^0.4.0" | ||
+THEBELAB_URL_DEFAULT = "https://unpkg.com/thebe@latest/lib/index.js" | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
@@ -186,7 +186,7 @@ def setup(app): | ||
app.add_config_value("jupyter_sphinx_embed_url", None, "html") | ||
|
||
# thebelab config, can be either a filename or a dict | ||
- app.add_config_value("jupyter_sphinx_thebelab_config", None, "html") | ||
+ app.add_config_value("jupyter_sphinx_thebelab_config", None, "env") | ||
app.add_config_value("jupyter_sphinx_thebelab_url", THEBELAB_URL_DEFAULT, "html") | ||
|
||
# linenos config | ||
diff --git a/jupyter_sphinx/execute.py b/jupyter_sphinx/execute.py | ||
index 558a26b..de44455 100644 | ||
--- a/jupyter_sphinx/execute.py | ||
+++ b/jupyter_sphinx/execute.py | ||
@@ -152,6 +152,17 @@ class ExecuteJupyterCells(SphinxTransform): | ||
kernel_name = default_kernel | ||
file_name = next(default_names) | ||
|
||
+ # Save time when jupyter notebook execution is not necessary | ||
+ if not any(not "execute" in node or node["execute"] for node in nodes): | ||
+ # mimics empty cell output for each node | ||
+ for node in nodes: | ||
+ source = node.children[0] | ||
+ source.attributes["classes"].append("code_cell") | ||
+ node.attributes["cm_language"] = kernel_name | ||
+ node += CellOutputNode(classes=["cell_output"]) | ||
+ apply_styling(node, thebe_config) | ||
+ continue | ||
+ | ||
# Add empty placeholder cells for non-executed nodes so nodes | ||
# and cells can be zipped and the provided input/output | ||
# can be inserted later | ||
-- | ||
2.42.0 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* from https://codemirror.net/5/theme/monokai.css */ | ||
/* Based on Sublime Text's Monokai theme */ | ||
|
||
.cm-s-monokai.CodeMirror { background: #272822; color: #f8f8f2; } | ||
.cm-s-monokai div.CodeMirror-selected { background: #49483E; } | ||
.cm-s-monokai .CodeMirror-line::selection, .cm-s-monokai .CodeMirror-line > span::selection, .cm-s-monokai .CodeMirror-line > span > span::selection { background: rgba(73, 72, 62, .99); } | ||
.cm-s-monokai .CodeMirror-line::-moz-selection, .cm-s-monokai .CodeMirror-line > span::-moz-selection, .cm-s-monokai .CodeMirror-line > span > span::-moz-selection { background: rgba(73, 72, 62, .99); } | ||
.cm-s-monokai .CodeMirror-gutters { background: #272822; border-right: 0px; } | ||
.cm-s-monokai .CodeMirror-guttermarker { color: white; } | ||
.cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; } | ||
.cm-s-monokai .CodeMirror-linenumber { color: #d0d0d0; } | ||
.cm-s-monokai .CodeMirror-cursor { border-left: 1px solid #f8f8f0; } | ||
|
||
.cm-s-monokai span.cm-comment { color: #75715e; } | ||
.cm-s-monokai span.cm-atom { color: #ae81ff; } | ||
.cm-s-monokai span.cm-number { color: #ae81ff; } | ||
|
||
.cm-s-monokai span.cm-comment.cm-attribute { color: #97b757; } | ||
.cm-s-monokai span.cm-comment.cm-def { color: #bc9262; } | ||
.cm-s-monokai span.cm-comment.cm-tag { color: #bc6283; } | ||
.cm-s-monokai span.cm-comment.cm-type { color: #5998a6; } | ||
|
||
.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute { color: #a6e22e; } | ||
.cm-s-monokai span.cm-keyword { color: #f92672; } | ||
.cm-s-monokai span.cm-builtin { color: #66d9ef; } | ||
.cm-s-monokai span.cm-string { color: #e6db74; } | ||
|
||
.cm-s-monokai span.cm-variable { color: #f8f8f2; } | ||
.cm-s-monokai span.cm-variable-2 { color: #9effff; } | ||
.cm-s-monokai span.cm-variable-3, .cm-s-monokai span.cm-type { color: #66d9ef; } | ||
.cm-s-monokai span.cm-def { color: #fd971f; } | ||
.cm-s-monokai span.cm-bracket { color: #f8f8f2; } | ||
.cm-s-monokai span.cm-tag { color: #f92672; } | ||
.cm-s-monokai span.cm-header { color: #ae81ff; } | ||
.cm-s-monokai span.cm-link { color: #ae81ff; } | ||
.cm-s-monokai span.cm-error { background: #f92672; color: #f8f8f0; } | ||
|
||
.cm-s-monokai .CodeMirror-activeline-background { background: #373831; } | ||
.cm-s-monokai .CodeMirror-matchingbracket { | ||
text-decoration: underline; | ||
color: white !important; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
div.jupyter_container { | ||
margin: .5rem 0; | ||
} | ||
|
||
div.jupyter_container + div.jupyter_container { | ||
margin: 0 0 .5rem 0; | ||
} | ||
|
||
div.jupyter_container div.cell_input pre { | ||
margin: .5rem; | ||
} | ||
|
||
div.jupyter_container div.cell_output div.output { | ||
margin: .5rem; | ||
} | ||
|
||
.thebelab-cell .jp-OutputArea { | ||
margin: 0 .5rem; | ||
} | ||
|
||
.thebelab-cell .jp-OutputArea-output { | ||
margin: 0 0 .5rem 0; | ||
overflow-x: auto; | ||
} | ||
|
||
.thebelab-button { | ||
margin: .5rem 0 .5rem .5rem; | ||
padding: 0 .5rem; | ||
min-width: 2rem; | ||
} | ||
|
||
.thebelab-button:active { | ||
color: #0f0fff; | ||
} | ||
|
||
.thebelab-busy { | ||
margin-left: .5rem; | ||
} | ||
|
||
#thebelab-activate-button { | ||
position: fixed; | ||
right: -5.1rem; | ||
top: calc(50% - 1.5rem); | ||
width: 6rem; | ||
border-radius: 1rem; | ||
transition-property: right; | ||
transition-duration: 300ms; | ||
transition-timing-function: ease-out; | ||
z-index: 100; | ||
} | ||
|
||
#thebelab-activate-button:hover { | ||
right: .4rem; | ||
} | ||
|
||
#thebelab-activate-button:active { | ||
color: #0f0fff; | ||
} | ||
|
||
body[data-theme="dark"] { | ||
.jupyter_container { | ||
color: white; | ||
background-color: black; | ||
} | ||
|
||
.jupyter_container .highlight { | ||
background-color: black; | ||
} | ||
|
||
.thebelab-button { | ||
color: #d0d0d0; | ||
background-color: #383838; | ||
} | ||
|
||
.thebelab-button:active { | ||
color: #368ce2; | ||
} | ||
|
||
#thebelab-activate-button { | ||
background-color: #383838; | ||
} | ||
|
||
#thebelab-activate-button:active { | ||
color: #368ce2; | ||
} | ||
|
||
.thebelab-cell .jp-OutputArea-output { | ||
color: white; | ||
background-color: black; | ||
} | ||
|
||
.thebelab-cell .jp-OutputArea-output pre { | ||
color: white; | ||
background-color: black; | ||
} | ||
} | ||
|
||
@media (prefers-color-scheme: dark) { | ||
body[data-theme="auto"] { /* the same styles with body[data-theme="dark"] */ | ||
.jupyter_container { | ||
color: white; | ||
background-color: black; | ||
} | ||
|
||
.jupyter_container .highlight { | ||
background-color: black; | ||
} | ||
|
||
.thebelab-button { | ||
color: #d0d0d0; | ||
background-color: #383838; | ||
} | ||
|
||
.thebelab-button:active { | ||
color: #368ce2; | ||
} | ||
|
||
#thebelab-activate-button { | ||
background-color: #383838; | ||
} | ||
|
||
#thebelab-activate-button:active { | ||
color: #368ce2; | ||
} | ||
|
||
.thebelab-cell .jp-OutputArea-output { | ||
color: white; | ||
background-color: black; | ||
} | ||
|
||
.thebelab-cell .jp-OutputArea-output pre { | ||
color: white; | ||
background-color: black; | ||
} | ||
} | ||
} | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// Change the editor theme according to the furo light/dark/auto mode | ||
function changeTheme(editor, theme) { | ||
if (theme === 'dark') { | ||
editor.setOption('theme', 'monokai'); // the same with pygments dark style in conf.py | ||
} else if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) { | ||
editor.setOption('theme', 'monokai'); | ||
} else { | ||
editor.setOption('theme', 'default'); | ||
} | ||
} | ||
|
||
// Change the editor theme of all CodeMirror cells | ||
function changeThemeAll(theme) { | ||
const querySet = document.querySelectorAll('.CodeMirror'); | ||
for (var i = 0; i < querySet.length; i++) { | ||
changeTheme(querySet[i].CodeMirror, theme); | ||
} | ||
} | ||
|
||
// Use the theme data of the body element set by setTheme function | ||
// defined in https://github.com/pradyunsg/furo/blob/main/src/furo/assets/scripts/furo.js | ||
const body = document.body; | ||
const observer1 = new MutationObserver((mutationsList) => { | ||
for (let mutation of mutationsList) { | ||
if (mutation.type === 'attributes' && mutation.attributeName === 'data-theme') { | ||
const theme = body.dataset.theme; | ||
changeThemeAll(theme); | ||
} | ||
} | ||
}); | ||
observer1.observe(body, { attributes: true }); | ||
|
||
|
||
// In the furo auto mode, we watch prefers-color-scheme and use the theme data | ||
// of the body element to change the CodeMirror editor theme | ||
const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)'); | ||
|
||
function handlePrefersColorSchemeChange(e) { | ||
const theme = body.dataset.theme; | ||
if (theme === 'auto') { | ||
changeThemeAll(theme); | ||
} | ||
} | ||
|
||
prefersDarkMode.addEventListener('change', handlePrefersColorSchemeChange); | ||
|
||
|
||
// Change the editor theme of a new CodeMirror cell. | ||
const callback = function(mutationsList, observer) { | ||
for(const mutation of mutationsList) { | ||
if (mutation.type === 'childList') { | ||
const theme = body.dataset.theme; | ||
for (const addedNode of mutation.addedNodes) { | ||
if (addedNode.classList && addedNode.classList.contains('CodeMirror')) { | ||
changeTheme(addedNode.CodeMirror, theme); | ||
}}}}}; | ||
const observer2 = new MutationObserver(callback); | ||
observer2.observe(document.getElementsByClassName("content")[0], { childList: true, subtree: true }); | ||
|
||
|
||
// Listen to the kernel status changes | ||
// https://thebe.readthedocs.io/en/stable/events.html | ||
thebelab.on("status", function (evt, data) { | ||
if (data.status === 'building') { | ||
const elements = document.querySelectorAll('.thebelab-cell'); | ||
elements.forEach(element => { | ||
element.style.filter = 'opacity(50%)'; | ||
}); | ||
const element = document.getElementById("thebelab-activate-button"); | ||
element.innerHTML = "Building"; | ||
element.style.right = '.4rem'; | ||
} | ||
else if (data.status === 'built') { | ||
const elements = document.querySelectorAll('.thebelab-cell'); | ||
elements.forEach(element => { | ||
element.style.filter = 'opacity(60%)'; | ||
}); | ||
const element = document.getElementById("thebelab-activate-button"); | ||
element.innerHTML = "Built"; | ||
element.style.right = '.4rem'; | ||
} | ||
else if (data.status === 'launching') { | ||
const elements = document.querySelectorAll('.thebelab-cell'); | ||
elements.forEach(element => { | ||
element.style.filter = 'opacity(70%)'; | ||
}); | ||
const element = document.getElementById("thebelab-activate-button"); | ||
element.innerHTML = "Launching"; | ||
element.style.right = '.4rem'; | ||
} | ||
else if (data.status === 'failed') { | ||
const elements = document.querySelectorAll('.thebelab-cell'); | ||
elements.forEach(element => { | ||
element.style.filter = 'opacity(50%)'; | ||
}); | ||
const element = document.getElementById("thebelab-activate-button"); | ||
element.innerHTML = 'Failed: ' + data.message; | ||
element.style.right = '.4rem'; | ||
element.style.width = 'auto'; | ||
element.style.color = 'red'; | ||
} | ||
else if (data.status === 'ready') { | ||
const elements = document.querySelectorAll('.thebelab-cell'); | ||
elements.forEach(element => { | ||
element.style.filter = 'opacity(100%)'; | ||
}); | ||
const element = document.getElementById("thebelab-activate-button"); | ||
element.innerHTML = "Ready"; | ||
element.style.right = null; | ||
// Run custom code when the kernel is ready | ||
const kernel = data.kernel; | ||
kernel.requestExecute({code: "%display latex"}); | ||
} | ||
}); |
Oops, something went wrong.