Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/render/format_code_cells.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,16 @@ Then for the image we can apply all the variables of the standard [image directi

Units of length are: 'em', 'ex', 'px', 'in', 'cm', 'mm', 'pt', 'pc'

The **width** and **height** can also be set by the code itself, in the metadata of the image output, which overrides those of the cell.
**classes** in the output metadata are added to those of the cell, which allows to style each image output of a cell separately, for example to show a different image in dark mode with the `only-light` and `only-dark` classes of your theme:

```python
from IPython.display import Image, display

display(Image("light.png"), metadata={"image/png": {"classes": "only-light"}})
display(Image("dark.png"), metadata={"image/png": {"classes": "only-dark"}})
```

You can also wrap the output in a [`figure`](https://docutils.sourceforge.io/docs/ref/rst/directives.html#figure), that can include:

- **align**: "left", "center", or "right"
Expand Down
10 changes: 9 additions & 1 deletion myst_nb/core/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,13 +672,21 @@ def render_image(self, data: MimeData) -> list[nodes.Element]:
"render_image_options", data.cell_metadata, line=data.line
).copy()
# Overwrite with metadata stored in output
output_options = data.output_metadata.get(data.mime_type, {})
image_options.update(
{
key: str(value)
for key, value in data.output_metadata.get(data.mime_type, {}).items()
for key, value in output_options.items()
if key in {"width", "height"}
}
)
# classes stored in output are added to those of the cell
if "classes" in output_options:
image_options["classes"] = " ".join(
str(classes)
for classes in (image_options.get("classes"), output_options["classes"])
if classes
)
for key, spec in [
("classes", options_spec.class_option),
("alt", options_spec.unchanged),
Expand Down
53 changes: 53 additions & 0 deletions tests/notebooks/metadata_image_output.ipynb

Large diffs are not rendered by default.

15 changes: 14 additions & 1 deletion tests/test_render_outputs/test_metadata_image_output.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,20 @@
Image(filename="./example.jpg", width=500, height=100)
<container classes="cell_output" nb_element="cell_code_output">
<image candidates="{'*': '_build/jupyter_execute/a4c9580c74dacf6f3316a3bd2e2a347933aa4463834dcf1bb8f20b4fcb476ae1.jpg'}" height="100" uri="_build/jupyter_execute/a4c9580c74dacf6f3316a3bd2e2a347933aa4463834dcf1bb8f20b4fcb476ae1.jpg" width="500">
<container cell_index="2" cell_metadata="{}" classes="cell" exec_count="1" nb_element="cell_code">
<container cell_index="2" cell_metadata="{'mystnb': {'image': {'classes': 'shadow'}}, 'tags': ['skip-execution']}" classes="cell tag_skip-execution" exec_count="2" nb_element="cell_code">
<container classes="cell_input" nb_element="cell_code_source">
<literal_block language="ipython3" linenos="0" xml:space="preserve">
# Outputs included with classes in output metadata, added to the classes
# in the cell metadata, cell is not executed
from IPython.display import Image, display

image = Image(filename="./example.jpg")
display(image, metadata={"image/jpeg": {"classes": "only-light"}})
display(image, metadata={"image/jpeg": {"classes": "only-dark"}})
<container classes="cell_output" nb_element="cell_code_output">
<image candidates="{'*': '_build/jupyter_execute/a4c9580c74dacf6f3316a3bd2e2a347933aa4463834dcf1bb8f20b4fcb476ae1.jpg'}" classes="shadow only-light" uri="_build/jupyter_execute/a4c9580c74dacf6f3316a3bd2e2a347933aa4463834dcf1bb8f20b4fcb476ae1.jpg">
<image candidates="{'*': '_build/jupyter_execute/a4c9580c74dacf6f3316a3bd2e2a347933aa4463834dcf1bb8f20b4fcb476ae1.jpg'}" classes="shadow only-dark" uri="_build/jupyter_execute/a4c9580c74dacf6f3316a3bd2e2a347933aa4463834dcf1bb8f20b4fcb476ae1.jpg">
<container cell_index="3" cell_metadata="{}" classes="cell" exec_count="1" nb_element="cell_code">
<container classes="cell_input" nb_element="cell_code_source">
<literal_block language="ipython3" linenos="0" xml:space="preserve">
# No outputs, cell is executed, image should have original size (370, 254)
Expand Down
Loading