-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve Notebook Output Rendering #243
Conversation
- Ensure source (path, lineno) are correctly propagated to `CellOutputBundleNode` - Capture cell level metadata in `CellOutputBundleNode` - New `CellOutputRenderer` class to contain render methods - Simplify test code, using sphinx `get_doctree` and `get_and_resolve_doctree` methods
This allows ofr other post-transforms, like `ReferencesResolver` to act on the output nodes.
Codecov Report
@@ Coverage Diff @@
## master #243 +/- ##
==========================================
+ Coverage 86.52% 87.16% +0.64%
==========================================
Files 10 12 +2
Lines 987 1239 +252
==========================================
+ Hits 854 1080 +226
- Misses 133 159 +26
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
The notebook renderer class is now loaded from an entrypoint, with a configurable name. Also moved node classes to a separate module.
ANSI lexer is applied to stdout/stderr and text/plain by default
If you need a few test cases for ANSI coloring, feel free to have a look at https://nbsphinx.readthedocs.io/code-cells.html#ANSI-Colors I've implemented the ANSI support in |
Thanks @mgeier! |
73098ec
to
c4f3b40
Compare
Hey @mmcky and @AakashGfude (and I see you lurking @choldgraf 👀 😆) I have maybe a few more bits to add on this, but the main restructuring and features are there if you want to have a look and give any thoughts. |
Oh and also @akhmerov; a) because I'm sure it'll be of interest, but also b) because you can now close jupyter/jupyter-sphinx#130 however you see fit, since I don't even use |
@chrisjsewell thanks for the heads up, this is indeed very informative. At a glance |
Well we can have a look and think about that at a later date, but for now (a) its too much complication, in terms of cross-repo testing, documentation, reviewing, etc, but also (b) it has dependencies on myst-parser, myst-nb configuration values, and relies on the use of cell metadata, which jupyter-sphinx's directives might have difficulty handling. So I'm open to the possibility, but I'm afraid I haven't really got time to figure out how 😬 |
Sounds reasonable. As a quick note: factoring out myst-specifc parts would amount to making an entry point for the myst-markdown renderer. Passing render state via cell tags seems alright. |
Well, its going to be more than just tags... |
Really? That seemed to be the only context where |
Thats now, in a few hours, maybe not lol |
@akhmerov now this is what I'm talking about 😄 https://myst-nb--243.org.readthedocs.build/en/243/use/formatting_outputs.html#images |
We can also set a caption (which is rendered as [CommonMark](https://commonmark.org/)) and name, by which to reference the figure: | ||
|
||
````md | ||
```{code-cell} ipython3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chrisjsewell what happens if the code in this code-block
doesn't produce an image
? Do we throw an error if the returned mime
type of the output
block isn't compatible with the image
directive?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then the render_image
method is never called, and the metadata just isn't used,
i.e. the metadata is accessed (and validated) "lazily" when it is required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is invalid, for example I give a bad width here, then it produces a warning, and since this a text-based notebook, that warning will point to the correct line of the document (the first one of the code cell)
```{code-cell} ipython3
---
myst:
image:
width: abc
---
from IPython.display import Image
Image("images/fun-fish.png")
```
/Users/chrisjsewell/Documents/GitHub/MyST-NB-actual/docs/use/formatting_outputs.md:110: WARNING: output render: Invalid image attribute: (key: 'width'; value: abc)
not a positive measure of one of the following units:
"em" "ex" "px" "in" "cm" "mm" "pt" "pc" "%"
and also, because the image is no longer created:
/Users/chrisjsewell/Documents/GitHub/MyST-NB-actual/docs/use/formatting_outputs.md:124: WARNING: 'myst' reference target not found: fun-fish
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see -- thanks @chrisjsewell
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks @chrisjsewell. It is neat to be able to apply styles and formatting on images
that are generated by code and the ansi
support is timely on the LaTeX
side.
For ansi
support -- I came across the ansifilter project this morning that may be useful in converting to various formats. However I don't think it is directly importable to python that I can tell.
For LaTeX
output -- from what I can tell reading the code you parse ansi
codes and return a new token
object for inclusion into the AST
so we just need to support those new node types when writing the tex
(or skip those elements for stripping output of ansi
codes)?
"KL\x1b[49mMN\x1b[39mOP\x1b[22mQR\x1b[24mST\x1b[27mUV") | ||
``` | ||
|
||
This uses the built-in {py:class}`~myst_nb.ansi_lexer.AnsiColorLexer` [pygments lexer](https://pygments.org/). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chrisjsewell is there a reason we don't just import this from pygments
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because its not part of pygments, there is no built-in ANSI lexer unfortunately (from what I could see), this is a bespoke one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears to work well for the 8-bit ansi though, perhaps some finessing of the CSS.
Then, as it says in the docs, we can get round to the adding 256-bit support as and when necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh OK -- sorry had misread header comment on the file. Makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something we should contribute upstream to pygments
at some point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeh quite possibly; just wanted to get everything working first, and then we can look to tidy up
Well, fingers crossed, that should already happen, because we are using pygments to lex it to tokens, then sphinx chooses the appropriate formatter to convert it: https://pygments.org/docs/formatters/ |
@mmcky has given i the thumbs up for "working" (or at least not breaking) LaTeX, so I'm going to merge this monstrosity! |
You can change the lexer used in the `conf.py`, for example to turn off lexing: | ||
|
||
```python | ||
nb_render_text_lexer = "none" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chrisjsewell one last question. Does this option in conf.py
just control ansi
parsing of text?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, it controls what pygments lexer is applied to plain text outputs (including stdout/stderr)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok - so it does more than just ansi
. Was just thinking it might be better named nb_render_text_ansi
but it is more generally a control over the lexer used which contains more than just ansi
parsing.
It doesn't seem to support "underline" and "invert", and there don't seem to be any "intense" colors when switching to "bold".
I've already implemented this in three different places (in two languages), and I don't currently have the energy to do it yet again. Do you even have to use Pygments? Why not just use For reference, the |
No description provided.