Open cderv opened 11 months ago
Here is a simplified test document
---
title: "test "
format:
html: default
keep-md: true
---
```{python}
from bokeh.io import output_notebook
output_notebook(hide_banner=True)
#| label: fig-4
#| fig-cap: "Line Plot from Bokeh"
from bokeh.plotting import figure, show
# prepare some data
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]
# create a new plot with a title and axis labels
p = figure(title="Simple line example", x_axis_label="x", y_axis_label="y")
# add a line renderer with legend and line thickness
p.line(x, y, legend_label="Temp.", line_width=2)
# show the results
show(p)
![image](https://github.com/quarto-dev/quarto-cli/assets/6791940/1bae7802-1e03-4dac-a307-7d1657f4eec7)
It happens because this is two cells - if there is only one, no problems
<details>
<summary>Very long intermediate md</summary>
````markdown
---
title: "test webpage"
format:
html: default
keep-md: true
---
::: {#9a1b83c0 .cell execution_count=1}
``` {.python .cell-code}
from bokeh.io import output_notebook
output_notebook(hide_banner=True)
::: {.cell-output .cell-output-display}
<script type="application/javascript">
(function(root) {
function now() {
return new Date();
}
const force = true;
if (typeof root._bokeh_onload_callbacks === "undefined" || force === true) {
root._bokeh_onload_callbacks = [];
root._bokeh_is_loading = undefined;
}
const JS_MIME_TYPE = 'application/javascript';
const HTML_MIME_TYPE = 'text/html';
const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';
const CLASS_NAME = 'output_bokeh rendered_html';
/**
* Render data to the DOM node
*/
function render(props, node) {
const script = document.createElement("script");
node.appendChild(script);
}
/**
* Handle when an output is cleared or removed
*/
function handleClearOutput(event, handle) {
const cell = handle.cell;
const id = cell.output_area._bokeh_element_id;
const server_id = cell.output_area._bokeh_server_id;
// Clean up Bokeh references
if (id != null && id in Bokeh.index) {
Bokeh.index[id].model.document.clear();
delete Bokeh.index[id];
}
if (server_id !== undefined) {
// Clean up Bokeh references
const cmd_clean = "from bokeh.io.state import curstate; print(curstate().uuid_to_server['" + server_id + "'].get_sessions()[0].document.roots[0]._id)";
cell.notebook.kernel.execute(cmd_clean, {
iopub: {
output: function(msg) {
const id = msg.content.text.trim();
if (id in Bokeh.index) {
Bokeh.index[id].model.document.clear();
delete Bokeh.index[id];
}
}
}
});
// Destroy server and session
const cmd_destroy = "import bokeh.io.notebook as ion; ion.destroy_server('" + server_id + "')";
cell.notebook.kernel.execute(cmd_destroy);
}
}
/**
* Handle when a new output is added
*/
function handleAddOutput(event, handle) {
const output_area = handle.output_area;
const output = handle.output;
// limit handleAddOutput to display_data with EXEC_MIME_TYPE content only
if ((output.output_type != "display_data") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {
return
}
const toinsert = output_area.element.find("." + CLASS_NAME.split(' ')[0]);
if (output.metadata[EXEC_MIME_TYPE]["id"] !== undefined) {
toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];
// store reference to embed id on output_area
output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE]["id"];
}
if (output.metadata[EXEC_MIME_TYPE]["server_id"] !== undefined) {
const bk_div = document.createElement("div");
bk_div.innerHTML = output.data[HTML_MIME_TYPE];
const script_attrs = bk_div.children[0].attributes;
for (let i = 0; i < script_attrs.length; i++) {
toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);
toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent
}
// store reference to server id on output_area
output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE]["server_id"];
}
}
function register_renderer(events, OutputArea) {
function append_mime(data, metadata, element) {
// create a DOM node to render to
const toinsert = this.create_output_subarea(
metadata,
CLASS_NAME,
EXEC_MIME_TYPE
);
this.keyboard_manager.register_events(toinsert);
// Render to node
const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};
render(props, toinsert[toinsert.length - 1]);
element.append(toinsert);
return toinsert
}
/* Handle when an output is cleared or removed */
events.on('clear_output.CodeCell', handleClearOutput);
events.on('delete.Cell', handleClearOutput);
/* Handle when a new output is added */
events.on('output_added.OutputArea', handleAddOutput);
/**
* Register the mime type and append_mime function with output_area
*/
OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {
/* Is output safe? */
safe: true,
/* Index of renderer in `output_area.display_order` */
index: 0
});
}
// register the mime type if in Jupyter Notebook environment and previously unregistered
if (root.Jupyter !== undefined) {
const events = require('base/js/events');
const OutputArea = require('notebook/js/outputarea').OutputArea;
if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {
register_renderer(events, OutputArea);
}
}
if (typeof (root._bokeh_timeout) === "undefined" || force === true) {
root._bokeh_timeout = Date.now() + 5000;
root._bokeh_failed_load = false;
}
const NB_LOAD_WARNING = {'data': {'text/html':
"<div style='background-color: #fdd'>\n"+
"<p>\n"+
"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \n"+
"may be due to a slow or bad network connection. Possible fixes:\n"+
"</p>\n"+
"<ul>\n"+
"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\n"+
"<li>use INLINE resources instead, as so:</li>\n"+
"</ul>\n"+
"<code>\n"+
"from bokeh.resources import INLINE\n"+
"output_notebook(resources=INLINE)\n"+
"</code>\n"+
"</div>"}};
function display_loaded() {
const el = document.getElementById(null);
if (el != null) {
el.textContent = "BokehJS is loading...";
}
if (root.Bokeh !== undefined) {
if (el != null) {
el.textContent = "BokehJS " + root.Bokeh.version + " successfully loaded.";
}
} else if (Date.now() < root._bokeh_timeout) {
setTimeout(display_loaded, 100)
}
}
function run_callbacks() {
try {
root._bokeh_onload_callbacks.forEach(function(callback) {
if (callback != null)
callback();
});
} finally {
delete root._bokeh_onload_callbacks
}
console.debug("Bokeh: all callbacks have finished");
}
function load_libs(css_urls, js_urls, callback) {
if (css_urls == null) css_urls = [];
if (js_urls == null) js_urls = [];
root._bokeh_onload_callbacks.push(callback);
if (root._bokeh_is_loading > 0) {
console.debug("Bokeh: BokehJS is being loaded, scheduling callback at", now());
return null;
}
if (js_urls == null || js_urls.length === 0) {
run_callbacks();
return null;
}
console.debug("Bokeh: BokehJS not loaded, scheduling load and callback at", now());
root._bokeh_is_loading = css_urls.length + js_urls.length;
function on_load() {
root._bokeh_is_loading--;
if (root._bokeh_is_loading === 0) {
console.debug("Bokeh: all BokehJS libraries/stylesheets loaded");
run_callbacks()
}
}
function on_error(url) {
console.error("failed to load " + url);
}
for (let i = 0; i < css_urls.length; i++) {
const url = css_urls[i];
const element = document.createElement("link");
element.onload = on_load;
element.onerror = on_error.bind(null, url);
element.rel = "stylesheet";
element.type = "text/css";
element.href = url;
console.debug("Bokeh: injecting link tag for BokehJS stylesheet: ", url);
document.body.appendChild(element);
}
for (let i = 0; i < js_urls.length; i++) {
const url = js_urls[i];
const element = document.createElement('script');
element.onload = on_load;
element.onerror = on_error.bind(null, url);
element.async = false;
element.src = url;
console.debug("Bokeh: injecting script tag for BokehJS library: ", url);
document.head.appendChild(element);
}
};
function inject_raw_css(css) {
const element = document.createElement("style");
element.appendChild(document.createTextNode(css));
document.body.appendChild(element);
}
const js_urls = ["https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js", "https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js", "https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js", "https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js", "https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js"];
const css_urls = [];
const inline_js = [ function(Bokeh) {
Bokeh.set_log_level("info");
},
function(Bokeh) {
}
];
function run_inline_js() {
if (root.Bokeh !== undefined || force === true) {
for (let i = 0; i < inline_js.length; i++) {
inline_js[i].call(root, root.Bokeh);
}
} else if (Date.now() < root._bokeh_timeout) {
setTimeout(run_inline_js, 100);
} else if (!root._bokeh_failed_load) {
console.log("Bokeh: BokehJS failed to load within specified timeout.");
root._bokeh_failed_load = true;
} else if (force !== true) {
const cell = $(document.getElementById(null)).parents('.cell').data().cell;
cell.output_area.append_execute_result(NB_LOAD_WARNING)
}
}
if (root._bokeh_is_loading === 0) {
console.debug("Bokeh: BokehJS loaded, going straight to plotting");
run_inline_js();
} else {
load_libs(css_urls, js_urls, function() {
console.debug("Bokeh: BokehJS plotting callback run at", now());
run_inline_js();
});
}
}(window));
</script>
::: :::
::: {#fig-4 .cell execution_count=2}
from bokeh.plotting import figure, show
# prepare some data
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]
# create a new plot with a title and axis labels
p = figure(title="Simple line example", x_axis_label="x", y_axis_label="y")
# add a line renderer with legend and line thickness
p.line(x, y, legend_label="Temp.", line_width=2)
# show the results
show(p)
::: {#fig-4-1 .cell-output .cell-output-display}
<div class="bk-root" id="bd096a76-3096-475a-9054-ff1b53329601" data-root-id="3320"></div>
Line Plot from Bokeh :::
::: {#fig-4-2 .cell-output .cell-output-display}
<script type="application/javascript">
(function(root) {
function embed_document(root) {
const docs_json = {"e88c3968-8e0a-4037-a315-5e0168c10e1b":{"defs":[],"roots":{"references":[{"attributes":{"below":[{"id":"3331"}],"center":[{"id":"3334"},{"id":"3338"},{"id":"3369"}],"left":[{"id":"3335"}],"renderers":[{"id":"3357"}],"title":{"id":"3321"},"toolbar":{"id":"3346"},"x_range":{"id":"3323"},"x_scale":{"id":"3327"},"y_range":{"id":"3325"},"y_scale":{"id":"3329"}},"id":"3320","subtype":"Figure","type":"Plot"},{"attributes":{"line_color":"#1f77b4","line_width":2,"x":{"field":"x"},"y":{"field":"y"}},"id":"3354","type":"Line"},{"attributes":{"line_alpha":0.2,"line_color":"#1f77b4","line_width":2,"x":{"field":"x"},"y":{"field":"y"}},"id":"3356","type":"Line"},{"attributes":{"data":{"x":[1,2,3,4,5],"y":[6,7,2,4,5]},"selected":{"id":"3367"},"selection_policy":{"id":"3366"}},"id":"3353","type":"ColumnDataSource"},{"attributes":{"line_alpha":0.1,"line_color":"#1f77b4","line_width":2,"x":{"field":"x"},"y":{"field":"y"}},"id":"3355","type":"Line"},{"attributes":{},"id":"3362","type":"AllLabels"},{"attributes":{"coordinates":null,"data_source":{"id":"3353"},"glyph":{"id":"3354"},"group":null,"hover_glyph":null,"muted_glyph":{"id":"3356"},"nonselection_glyph":{"id":"3355"},"view":{"id":"3358"}},"id":"3357","type":"GlyphRenderer"},{"attributes":{"tools":[{"id":"3339"},{"id":"3340"},{"id":"3341"},{"id":"3342"},{"id":"3343"},{"id":"3344"}]},"id":"3346","type":"Toolbar"},{"attributes":{},"id":"3339","type":"PanTool"},{"attributes":{},"id":"3340","type":"WheelZoomTool"},{"attributes":{},"id":"3361","type":"BasicTickFormatter"},{"attributes":{"axis":{"id":"3335"},"coordinates":null,"dimension":1,"group":null,"ticker":null},"id":"3338","type":"Grid"},{"attributes":{"coordinates":null,"group":null,"items":[{"id":"3370"}]},"id":"3369","type":"Legend"},{"attributes":{},"id":"3366","type":"UnionRenderers"},{"attributes":{},"id":"3329","type":"LinearScale"},{"attributes":{"label":{"value":"Temp."},"renderers":[{"id":"3357"}]},"id":"3370","type":"LegendItem"},{"attributes":{"axis_label":"y","coordinates":null,"formatter":{"id":"3361"},"group":null,"major_label_policy":{"id":"3362"},"ticker":{"id":"3336"}},"id":"3335","type":"LinearAxis"},{"attributes":{},"id":"3342","type":"SaveTool"},{"attributes":{},"id":"3365","type":"AllLabels"},{"attributes":{"bottom_units":"screen","coordinates":null,"fill_alpha":0.5,"fill_color":"lightgrey","group":null,"left_units":"screen","level":"overlay","line_alpha":1.0,"line_color":"black","line_dash":[4,4],"line_width":2,"right_units":"screen","syncable":false,"top_units":"screen"},"id":"3345","type":"BoxAnnotation"},{"attributes":{"overlay":{"id":"3345"}},"id":"3341","type":"BoxZoomTool"},{"attributes":{},"id":"3327","type":"LinearScale"},{"attributes":{"axis":{"id":"3331"},"coordinates":null,"group":null,"ticker":null},"id":"3334","type":"Grid"},{"attributes":{},"id":"3344","type":"HelpTool"},{"attributes":{},"id":"3323","type":"DataRange1d"},{"attributes":{"coordinates":null,"group":null,"text":"Simple line example"},"id":"3321","type":"Title"},{"attributes":{},"id":"3336","type":"BasicTicker"},{"attributes":{},"id":"3367","type":"Selection"},{"attributes":{"axis_label":"x","coordinates":null,"formatter":{"id":"3364"},"group":null,"major_label_policy":{"id":"3365"},"ticker":{"id":"3332"}},"id":"3331","type":"LinearAxis"},{"attributes":{},"id":"3364","type":"BasicTickFormatter"},{"attributes":{},"id":"3343","type":"ResetTool"},{"attributes":{},"id":"3332","type":"BasicTicker"},{"attributes":{"source":{"id":"3353"}},"id":"3358","type":"CDSView"},{"attributes":{},"id":"3325","type":"DataRange1d"}],"root_ids":["3320"]},"title":"Bokeh Application","version":"2.4.3"}};
const render_items = [{"docid":"e88c3968-8e0a-4037-a315-5e0168c10e1b","root_ids":["3320"],"roots":{"3320":"bd096a76-3096-475a-9054-ff1b53329601"}}];
root.Bokeh.embed.embed_items_notebook(docs_json, render_items);
}
if (root.Bokeh !== undefined) {
embed_document(root);
} else {
let attempts = 0;
const timer = setInterval(function(root) {
if (root.Bokeh !== undefined) {
clearInterval(timer);
embed_document(root);
} else {
attempts++;
if (attempts > 100) {
clearInterval(timer);
console.log("Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing");
}
}
}, 10, root)
}
})(window);
</script>
::: :::
</details>
we got the second cell outputing two `display_data`, one is only a HTML `div` that should contains the graph, and the other is the JS script to create it. Somehow, it got separated and we end up with somthing like
````markdown
::: {#fig-4 .cell execution_count=2}
< python source code cell here>
::: {#fig-4-1 .cell-output .cell-output-display}
```{=html}
<div class="bk-root" id="bd096a76-3096-475a-9054-ff1b53329601" data-root-id="3320"></div>
Line Plot from Bokeh :::
::: {#fig-4-2 .cell-output .cell-output-display}
<script type="application/javascript">
(...)
:::
:::
Merging the two cells fix the issue
---
title: "test webpage"
format:
html: default
keep-md: true
---
```{python}
#| label: fig-4
#| fig-cap: "Line Plot from Bokeh"
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
output_notebook(hide_banner=True)
# prepare some data
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]
# create a new plot with a title and axis labels
p = figure(title="Simple line example", x_axis_label="x", y_axis_label="y")
# add a line renderer with legend and line thickness
p.line(x, y, legend_label="Temp.", line_width=2)
# show the results
show(p)
![image](https://github.com/quarto-dev/quarto-cli/assets/6791940/8dfa10d8-8567-4cb8-b252-96fe9df19480)
<details>
<summary>Intermediate md</summary>
````markdown
---
title: "test webpage"
format:
html: default
keep-md: true
---
::: {#cell-fig-4 .cell execution_count=1}
``` {.python .cell-code}
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
output_notebook(hide_banner=True)
# prepare some data
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]
# create a new plot with a title and axis labels
p = figure(title="Simple line example", x_axis_label="x", y_axis_label="y")
# add a line renderer with legend and line thickness
p.line(x, y, legend_label="Temp.", line_width=2)
# show the results
show(p)
::: {#fig-4 .cell-output .cell-output-display}
<script>(function(root) {
function now() {
return new Date();
}
const force = true;
if (typeof root._bokeh_onload_callbacks === "undefined" || force === true) {
root._bokeh_onload_callbacks = [];
root._bokeh_is_loading = undefined;
}
const JS_MIME_TYPE = 'application/javascript';
const HTML_MIME_TYPE = 'text/html';
const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';
const CLASS_NAME = 'output_bokeh rendered_html';
/**
* Render data to the DOM node
*/
function render(props, node) {
const script = document.createElement("script");
node.appendChild(script);
}
/**
* Handle when an output is cleared or removed
*/
function handleClearOutput(event, handle) {
const cell = handle.cell;
const id = cell.output_area._bokeh_element_id;
const server_id = cell.output_area._bokeh_server_id;
// Clean up Bokeh references
if (id != null && id in Bokeh.index) {
Bokeh.index[id].model.document.clear();
delete Bokeh.index[id];
}
if (server_id !== undefined) {
// Clean up Bokeh references
const cmd_clean = "from bokeh.io.state import curstate; print(curstate().uuid_to_server['" + server_id + "'].get_sessions()[0].document.roots[0]._id)";
cell.notebook.kernel.execute(cmd_clean, {
iopub: {
output: function(msg) {
const id = msg.content.text.trim();
if (id in Bokeh.index) {
Bokeh.index[id].model.document.clear();
delete Bokeh.index[id];
}
}
}
});
// Destroy server and session
const cmd_destroy = "import bokeh.io.notebook as ion; ion.destroy_server('" + server_id + "')";
cell.notebook.kernel.execute(cmd_destroy);
}
}
/**
* Handle when a new output is added
*/
function handleAddOutput(event, handle) {
const output_area = handle.output_area;
const output = handle.output;
// limit handleAddOutput to display_data with EXEC_MIME_TYPE content only
if ((output.output_type != "display_data") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {
return
}
const toinsert = output_area.element.find("." + CLASS_NAME.split(' ')[0]);
if (output.metadata[EXEC_MIME_TYPE]["id"] !== undefined) {
toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];
// store reference to embed id on output_area
output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE]["id"];
}
if (output.metadata[EXEC_MIME_TYPE]["server_id"] !== undefined) {
const bk_div = document.createElement("div");
bk_div.innerHTML = output.data[HTML_MIME_TYPE];
const script_attrs = bk_div.children[0].attributes;
for (let i = 0; i < script_attrs.length; i++) {
toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);
toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent
}
// store reference to server id on output_area
output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE]["server_id"];
}
}
function register_renderer(events, OutputArea) {
function append_mime(data, metadata, element) {
// create a DOM node to render to
const toinsert = this.create_output_subarea(
metadata,
CLASS_NAME,
EXEC_MIME_TYPE
);
this.keyboard_manager.register_events(toinsert);
// Render to node
const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};
render(props, toinsert[toinsert.length - 1]);
element.append(toinsert);
return toinsert
}
/* Handle when an output is cleared or removed */
events.on('clear_output.CodeCell', handleClearOutput);
events.on('delete.Cell', handleClearOutput);
/* Handle when a new output is added */
events.on('output_added.OutputArea', handleAddOutput);
/**
* Register the mime type and append_mime function with output_area
*/
OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {
/* Is output safe? */
safe: true,
/* Index of renderer in `output_area.display_order` */
index: 0
});
}
// register the mime type if in Jupyter Notebook environment and previously unregistered
if (root.Jupyter !== undefined) {
const events = require('base/js/events');
const OutputArea = require('notebook/js/outputarea').OutputArea;
if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {
register_renderer(events, OutputArea);
}
}
if (typeof (root._bokeh_timeout) === "undefined" || force === true) {
root._bokeh_timeout = Date.now() + 5000;
root._bokeh_failed_load = false;
}
const NB_LOAD_WARNING = {'data': {'text/html':
"<div style='background-color: #fdd'>\n"+
"<p>\n"+
"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \n"+
"may be due to a slow or bad network connection. Possible fixes:\n"+
"</p>\n"+
"<ul>\n"+
"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\n"+
"<li>use INLINE resources instead, as so:</li>\n"+
"</ul>\n"+
"<code>\n"+
"from bokeh.resources import INLINE\n"+
"output_notebook(resources=INLINE)\n"+
"</code>\n"+
"</div>"}};
function display_loaded() {
const el = document.getElementById(null);
if (el != null) {
el.textContent = "BokehJS is loading...";
}
if (root.Bokeh !== undefined) {
if (el != null) {
el.textContent = "BokehJS " + root.Bokeh.version + " successfully loaded.";
}
} else if (Date.now() < root._bokeh_timeout) {
setTimeout(display_loaded, 100)
}
}
function run_callbacks() {
try {
root._bokeh_onload_callbacks.forEach(function(callback) {
if (callback != null)
callback();
});
} finally {
delete root._bokeh_onload_callbacks
}
console.debug("Bokeh: all callbacks have finished");
}
function load_libs(css_urls, js_urls, callback) {
if (css_urls == null) css_urls = [];
if (js_urls == null) js_urls = [];
root._bokeh_onload_callbacks.push(callback);
if (root._bokeh_is_loading > 0) {
console.debug("Bokeh: BokehJS is being loaded, scheduling callback at", now());
return null;
}
if (js_urls == null || js_urls.length === 0) {
run_callbacks();
return null;
}
console.debug("Bokeh: BokehJS not loaded, scheduling load and callback at", now());
root._bokeh_is_loading = css_urls.length + js_urls.length;
function on_load() {
root._bokeh_is_loading--;
if (root._bokeh_is_loading === 0) {
console.debug("Bokeh: all BokehJS libraries/stylesheets loaded");
run_callbacks()
}
}
function on_error(url) {
console.error("failed to load " + url);
}
for (let i = 0; i < css_urls.length; i++) {
const url = css_urls[i];
const element = document.createElement("link");
element.onload = on_load;
element.onerror = on_error.bind(null, url);
element.rel = "stylesheet";
element.type = "text/css";
element.href = url;
console.debug("Bokeh: injecting link tag for BokehJS stylesheet: ", url);
document.body.appendChild(element);
}
for (let i = 0; i < js_urls.length; i++) {
const url = js_urls[i];
const element = document.createElement('script');
element.onload = on_load;
element.onerror = on_error.bind(null, url);
element.async = false;
element.src = url;
console.debug("Bokeh: injecting script tag for BokehJS library: ", url);
document.head.appendChild(element);
}
};
function inject_raw_css(css) {
const element = document.createElement("style");
element.appendChild(document.createTextNode(css));
document.body.appendChild(element);
}
const js_urls = ["https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.min.js", "https://cdn.bokeh.org/bokeh/release/bokeh-gl-2.4.3.min.js", "https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js", "https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js", "https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-2.4.3.min.js"];
const css_urls = [];
const inline_js = [ function(Bokeh) {
Bokeh.set_log_level("info");
},
function(Bokeh) {
}
];
function run_inline_js() {
if (root.Bokeh !== undefined || force === true) {
for (let i = 0; i < inline_js.length; i++) {
inline_js[i].call(root, root.Bokeh);
}
} else if (Date.now() < root._bokeh_timeout) {
setTimeout(run_inline_js, 100);
} else if (!root._bokeh_failed_load) {
console.log("Bokeh: BokehJS failed to load within specified timeout.");
root._bokeh_failed_load = true;
} else if (force !== true) {
const cell = $(document.getElementById(null)).parents('.cell').data().cell;
cell.output_area.append_execute_result(NB_LOAD_WARNING)
}
}
if (root._bokeh_is_loading === 0) {
console.debug("Bokeh: BokehJS loaded, going straight to plotting");
run_inline_js();
} else {
load_libs(css_urls, js_urls, function() {
console.debug("Bokeh: BokehJS plotting callback run at", now());
run_inline_js();
});
}
}(window));</script>
<div class="bk-root" id="567c4106-f6c4-41f7-bfb6-0aca5bdc7c42" data-root-id="3550"></div>
<script>(function(root) {
function embed_document(root) {
const docs_json = {"104cdd4c-c6c2-4012-b05c-854ec2a8c186":{"defs":[],"roots":{"references":[{"attributes":{"below":[{"id":"3561"}],"center":[{"id":"3564"},{"id":"3568"},{"id":"3599"}],"left":[{"id":"3565"}],"renderers":[{"id":"3587"}],"title":{"id":"3551"},"toolbar":{"id":"3576"},"x_range":{"id":"3553"},"x_scale":{"id":"3557"},"y_range":{"id":"3555"},"y_scale":{"id":"3559"}},"id":"3550","subtype":"Figure","type":"Plot"},{"attributes":{"coordinates":null,"data_source":{"id":"3583"},"glyph":{"id":"3584"},"group":null,"hover_glyph":null,"muted_glyph":{"id":"3586"},"nonselection_glyph":{"id":"3585"},"view":{"id":"3588"}},"id":"3587","type":"GlyphRenderer"},{"attributes":{},"id":"3569","type":"PanTool"},{"attributes":{},"id":"3557","type":"LinearScale"},{"attributes":{"overlay":{"id":"3575"}},"id":"3571","type":"BoxZoomTool"},{"attributes":{},"id":"3592","type":"AllLabels"},{"attributes":{},"id":"3562","type":"BasicTicker"},{"attributes":{"line_alpha":0.1,"line_color":"#1f77b4","line_width":2,"x":{"field":"x"},"y":{"field":"y"}},"id":"3585","type":"Line"},{"attributes":{"line_alpha":0.2,"line_color":"#1f77b4","line_width":2,"x":{"field":"x"},"y":{"field":"y"}},"id":"3586","type":"Line"},{"attributes":{},"id":"3555","type":"DataRange1d"},{"attributes":{},"id":"3595","type":"AllLabels"},{"attributes":{"source":{"id":"3583"}},"id":"3588","type":"CDSView"},{"attributes":{},"id":"3553","type":"DataRange1d"},{"attributes":{},"id":"3573","type":"ResetTool"},{"attributes":{},"id":"3597","type":"Selection"},{"attributes":{"line_color":"#1f77b4","line_width":2,"x":{"field":"x"},"y":{"field":"y"}},"id":"3584","type":"Line"},{"attributes":{"axis_label":"x","coordinates":null,"formatter":{"id":"3594"},"group":null,"major_label_policy":{"id":"3595"},"ticker":{"id":"3562"}},"id":"3561","type":"LinearAxis"},{"attributes":{"axis":{"id":"3565"},"coordinates":null,"dimension":1,"group":null,"ticker":null},"id":"3568","type":"Grid"},{"attributes":{},"id":"3596","type":"UnionRenderers"},{"attributes":{},"id":"3591","type":"BasicTickFormatter"},{"attributes":{},"id":"3559","type":"LinearScale"},{"attributes":{"coordinates":null,"group":null,"text":"Simple line example"},"id":"3551","type":"Title"},{"attributes":{"axis":{"id":"3561"},"coordinates":null,"group":null,"ticker":null},"id":"3564","type":"Grid"},{"attributes":{"axis_label":"y","coordinates":null,"formatter":{"id":"3591"},"group":null,"major_label_policy":{"id":"3592"},"ticker":{"id":"3566"}},"id":"3565","type":"LinearAxis"},{"attributes":{"label":{"value":"Temp."},"renderers":[{"id":"3587"}]},"id":"3600","type":"LegendItem"},{"attributes":{"tools":[{"id":"3569"},{"id":"3570"},{"id":"3571"},{"id":"3572"},{"id":"3573"},{"id":"3574"}]},"id":"3576","type":"Toolbar"},{"attributes":{"bottom_units":"screen","coordinates":null,"fill_alpha":0.5,"fill_color":"lightgrey","group":null,"left_units":"screen","level":"overlay","line_alpha":1.0,"line_color":"black","line_dash":[4,4],"line_width":2,"right_units":"screen","syncable":false,"top_units":"screen"},"id":"3575","type":"BoxAnnotation"},{"attributes":{"data":{"x":[1,2,3,4,5],"y":[6,7,2,4,5]},"selected":{"id":"3597"},"selection_policy":{"id":"3596"}},"id":"3583","type":"ColumnDataSource"},{"attributes":{},"id":"3594","type":"BasicTickFormatter"},{"attributes":{"coordinates":null,"group":null,"items":[{"id":"3600"}]},"id":"3599","type":"Legend"},{"attributes":{},"id":"3570","type":"WheelZoomTool"},{"attributes":{},"id":"3566","type":"BasicTicker"},{"attributes":{},"id":"3574","type":"HelpTool"},{"attributes":{},"id":"3572","type":"SaveTool"}],"root_ids":["3550"]},"title":"Bokeh Application","version":"2.4.3"}};
const render_items = [{"docid":"104cdd4c-c6c2-4012-b05c-854ec2a8c186","root_ids":["3550"],"roots":{"3550":"567c4106-f6c4-41f7-bfb6-0aca5bdc7c42"}}];
root.Bokeh.embed.embed_items_notebook(docs_json, render_items);
}
if (root.Bokeh !== undefined) {
embed_document(root);
} else {
let attempts = 0;
const timer = setInterval(function(root) {
if (root.Bokeh !== undefined) {
clearInterval(timer);
embed_document(root);
} else {
attempts++;
if (attempts > 100) {
clearInterval(timer);
console.log("Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing");
}
}
}, 10, root)
}
})(window);</script>
Line Plot from Bokeh ::: :::
</details>
So probably something in `fixupBokehCells()` does not correctly merge the two output display data produces
@cderv Thanks for following this bug. I’m new to Quarto and have been very impressed! I’m an emacs guy that lives in a Microsoft Office World, so being able to use a mark up based language to generate docx, ppt, pdf is great. Keep up the great work!
One thing I haven’t been able to figure out is how to use Quarto with Bokeh (or Plotly) to render pdf or docx documents. Is this even possible as these are dynamic JS based packages?
Thanks
One thing I haven’t been able to figure out is how to use Quarto with Bokeh (or Plotly) to render pdf or docx documents. Is this even possible as these are dynamic JS based packages?
It's not currently possible, exactly for the reason you point out. Some libraries know how to emit static output, but not all do. I believe Bokeh and Plotly don't.
We have plans to use an offscreen HTML renderer and take screenshots for the non-HTML formats, but the situation is more complicated than it might look at a glance.
Thanks. Keep us posted. What you describe would be a great feature as those packages create great looking content. Probably many more use cases.
I believe Bokeh and Plotly don't.
Plotly as a way see https://plotly.com/python/static-image-export/ and example at https://github.com/quarto-dev/quarto-cli/issues/4225#issuecomment-1816064725
For bokeh, it is a bit more complex to export to image (https://docs.bokeh.org/en/2.4.1/docs/user_guide/export.html) as it requires Selenium
Plotly as a way see https://plotly.com/python/static-image-export/ and example at https://github.com/quarto-dev/quarto-cli/issues/4225#issuecomment-1816064725
My point that they could/should be doing that by default and emitting an image in the notebook itself.
Oh I see. If they can do that this is indeed what we want !! I'll see if there are issues about this in there repo.
WRT original report: I wish bokeh
emitted better output in this case. They're emitting two separate cells, one with text/html
and another with application/javascript
:
"outputs": [
{
"data": {
"text/html": [
"\n",
" <div class=\"bk-root\" id=\"ff6b5ddd-9a7b-49ff-850a-2d676060cc5c\" data-root-id=\"1083\"></div>\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"(function(root) {\n",
" function embed_document(root) {\n",
" const docs_json = {\"d2a1b461-05 ... },\"view\":{\"id\":\"1121\"}},\"id\":\"1120\",\"type\":\"GlyphRenderer\"}],\"root_ids\":[\"1083\"]},\"title\":\"Bokeh Application\",\"version\":\"2.4.3\"}};\n",
" const render_items = [{\"docid\":\"d2a1b461-05ae-48dd-818e-bced8fb6ab08\",\"root_ids\":[\"1083\"],\"roots\":{\"1083\":\"ff6b5ddd-9a7b-49ff-850a-2d676060cc5c\"}}];\n",
" root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" embed_document(root);\n",
" } else {\n",
" let attempts = 0;\n",
" const timer = setInterval(function(root) {\n",
" if (root.Bokeh !== undefined) {\n",
" clearInterval(timer);\n",
" embed_document(root);\n",
" } else {\n",
" attempts++;\n",
" if (attempts > 100) {\n",
" clearInterval(timer);\n",
" console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
" }\n",
" }\n",
" }, 10, root)\n",
" }\n",
"})(window);"
],
"application/vnd.bokehjs_exec.v0+json": ""
},
We can add a workaround that tries to detect a cell with "application/vnd.bokehjs_exec.v0+json": ""
, application/javascript
, and a previous cell that looks like it might have come from bokeh, and merge all of them. It's a dangerous move, though, because we can't know for sure that the previous cell was indeed generated by bokeh (since they don't actually mark it as such).
It's not clearly a bug because I bet they only test the rendered .ipynb result on jupyter lab
or jupyter notebook
. But it sure feels like an unfortunate way to generate results.
They could, for example, add metadata to the cells so that they would be parseable as a "single bokeh figure". I'm somewhat surprised that this isn't already a jupyter feature. I wonder how jupyterbook handles this.
Really unfortunate indeed. It still puzzles me why it works when single python cells, but not when there is another cell before ? Isn't the bokeh plot outputing two separate cells in both cases ? 🤔
Isn't the bokeh plot outputing two separate cells in both cases ? 🤔
You are correct, and my understanding is wrong. Let me revisit and I'll get back to you.
What's happening is that fixupBokehCells
is wrong about how bokeh cells are emitted.
We need a corpus of bokeh plots to do this well. I kind of didn't want to do this for 1.4, and now I really don't want to do this for 1.4.
Not in 1.4?🥲
PR's are always welcome. We unfortunately have a lot else on our plate that's higher priority.
@cderv - Your suggestion for using static-images in plotly
worked great for me! I was able to render plotly
images directly into standalone html
, pdf
and docx
files. Exactly what I wanted to do. Here is my code.
---
title: "Testing Plotly"
format:
html:
embed-resources: true
pdf: default
docx: default
---
## Two Figures
```{python}
#| echo: false
#| output: false
import plotly.graph_objects as go
from IPython.display import Image
import numpy as np
np.random.seed(1)
N = 100
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
sz = np.random.rand(N) * 30
fig = go.Figure()
fig.add_trace(go.Scatter(
x=x,
y=y,
mode="markers",
marker=go.scatter.Marker(
size=sz,
color=colors,
opacity=0.6,
colorscale="Viridis"
)
))
#| echo: false
#| label: "Figure 1"
#| fig-cap: "Plotly Static Figure"
img_bytes = fig.to_image(format="png")
Image(img_bytes)
#| echo: false
#| output: false
import plotly.graph_objects as go
import pandas as pd
from datetime import datetime
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
fig = go.Figure(data=[go.Candlestick(x=df['Date'],
open=df['AAPL.Open'],
high=df['AAPL.High'],
low=df['AAPL.Low'],
close=df['AAPL.Close'])])
#| echo: false
#| label: "Figure 2"
#| fig-cap: "Plotly Second Figure"
img_bytes = fig.to_image(format="png")
Image(img_bytes)
Adding new cells for static output is the key
#| echo: false
#| label: "Figure 2"
#| fig-cap: "Plotly Second Figure"
img_bytes = fig.to_image(format="png")
Image(img_bytes)
Maybe I’ve missed it, but is there a macro facility within Quarto so that I could abstract out the boiler plate code to create the static-image?
PR's are always welcome. We unfortunately have a lot else on our plate that's higher priority.
Totally get it. I’m happy with plotly for now. Really appreciate all of your and @cderv time responding to me.
(If someone would tell me how to copy qmd into GitHub,
Look at https://quarto.org/bug-reports.html#formatting-make-githubs-markdown-work-for-us
Maybe I’ve missed it, but is there a macro facility within Quarto so that I could abstract out the boiler plate code to create the static-image?
You would need to do that probably using a Python function that produce some Markdown raw output directly (https://quarto.org/docs/computations/execution-options.html#raw-output). We some include feature to reuse content, but this would work only if you object from previous chunk before include is same name always (https://quarto.org/docs/authoring/includes.html)
Thank you @prairie-guy and @cderv.
I have tested both bokeh and plotly just now, but it seems that plotly causes another bug in rendering the figures in html format. Both the title and figure legend are not correct. bokeh works fine, but only when one chunk is rendered.
The output:
The code:
---
title: "Testing Plot"
format:
html:
toc: true
embed-resources: true
standalone: true
execute:
cache: false
echo: false
jupyter: python3
---
## Figure by plotly
```{python}
#| label: fig-1
#| fig-cap: "Plotly First Figure"
import plotly.graph_objects as go
from IPython.display import Image
import numpy as np
np.random.seed(1)
N = 100
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
sz = np.random.rand(N) * 30
fig = go.Figure()
fig.add_trace(go.Scatter(
x=x,
y=y,
mode="markers",
marker=go.scatter.Marker(
size=sz,
color=colors,
opacity=0.6,
colorscale="Viridis"
)
))
fig.show()
#| label: fig-2
#| fig-cap: "Line Plot from Bokeh"
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
output_notebook(hide_banner=True)
# prepare some data
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]
# create a new plot with a title and axis labels
p = figure(title="Simple line example", x_axis_label="x", y_axis_label="y")
# add a line renderer with legend and line thickness
p.line(x, y, legend_label="Temp.", line_width=2)
# show the results
show(p)
I can't seem to reproduce that:
@y9c - Using your code with quarto preview
I get the same results as @cscheid.
@prairie-guy
This bug is trigger when the preview mode is on.
quarto preview test.qmd
Quarto 1.4.526 [✓] Checking versions of quarto binary dependencies... Pandoc version 3.1.9: OK Dart Sass version 1.69.5: OK Deno version 1.37.2: OK
It is wired that when stop the preview, then run the render command, and restart the preview command, the problem won't happen again. It might be relative to the cache of the preview mode.
This bug is trigger when the preview mode is on.
preview
and render
use the same rendering path when converting the .ipynb file to markdown, so I suspect there's something else happening.
it would be awesome if we can keep issue thread clean and scoped to original issue. I understand that issues can be related, but linking / cross reference issues by there number is clear enough for us to know they are related.
This would help keep discussion scoped and clear.
@y9c I can't reproduced either by copy pasting your example and either runnning quarto preview
or quarto render
.
Please to check your configuration and open a new issues withh all the information and examples so that you can reproduce. Sharing a reprex as github repo could insure with all get the same files. Thanks !
Looking again at this issue we have now this warning showing when rendering the example from https://github.com/quarto-dev/quarto-cli/issues/7967#issuecomment-1862491326
WARN: jupyter-fixup: cells without output data. Will not fixup bokeh cell
So definitely something with the Jupyter fixup we do for bokeh
We do generated two figures in the intermediate.md when there is only one expected.
::: {#fig-4 .cell execution_count=2}
``` {.python .cell-code}
from bokeh.plotting import figure, show
# prepare some data
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]
# create a new plot with a title and axis labels
p = figure(title="Simple line example", x_axis_label="x", y_axis_label="y")
# add a line renderer with legend and line thickness
p.line(x, y, legend_label="Temp.", line_width=2)
# show the results
show(p)
::: {#fig-4-1 .cell-output .cell-output-display}
<div id="fbd0b477-c829-4bc2-9a1e-1ad472aa1e86" data-root-id="p1001" style="display: contents;"></div>
Line Plot from Bokeh :::
::: {#fig-4-2 .cell-output .cell-output-display}
<script type="application/javascript">
(function(root) {
function embed_document(root) {
const docs_json = {"4d4cf6a6-54f1-4d4a-a143-e41d5b6564c7":{"version":"3.4.1","title":"Bokeh Application","roots":[{"type":"object","name":"Figure","id":"p1001","attributes":{"x_range":{"type":"object","name":"DataRange1d","id":"p1002"},"y_range":{"type":"object","name":"DataRange1d","id":"p1003"},"x_scale":{"type":"object","name":"LinearScale","id":"p1011"},"y_scale":{"type":"object","name":"LinearScale","id":"p1012"},"title":{"type":"object","name":"Title","id":"p1004","attributes":{"text":"Simple line example"}},"renderers":[{"type":"object","name":"GlyphRenderer","id":"p1040","attributes":{"data_source":{"type":"object","name":"ColumnDataSource","id":"p1034","attributes":{"selected":{"type":"object","name":"Selection","id":"p1035","attributes":{"indices":[],"line_indices":[]}},"selection_policy":{"type":"object","name":"UnionRenderers","id":"p1036"},"data":{"type":"map","entries":[["x",[1,2,3,4,5]],["y",[6,7,2,4,5]]]}}},"view":{"type":"object","name":"CDSView","id":"p1041","attributes":{"filter":{"type":"object","name":"AllIndices","id":"p1042"}}},"glyph":{"type":"object","name":"Line","id":"p1037","attributes":{"x":{"type":"field","field":"x"},"y":{"type":"field","field":"y"},"line_color":"#1f77b4","line_width":2}},"nonselection_glyph":{"type":"object","name":"Line","id":"p1038","attributes":{"x":{"type":"field","field":"x"},"y":{"type":"field","field":"y"},"line_color":"#1f77b4","line_alpha":0.1,"line_width":2}},"muted_glyph":{"type":"object","name":"Line","id":"p1039","attributes":{"x":{"type":"field","field":"x"},"y":{"type":"field","field":"y"},"line_color":"#1f77b4","line_alpha":0.2,"line_width":2}}}}],"toolbar":{"type":"object","name":"Toolbar","id":"p1010","attributes":{"tools":[{"type":"object","name":"PanTool","id":"p1023"},{"type":"object","name":"WheelZoomTool","id":"p1024","attributes":{"renderers":"auto"}},{"type":"object","name":"BoxZoomTool","id":"p1025","attributes":{"overlay":{"type":"object","name":"BoxAnnotation","id":"p1026","attributes":{"syncable":false,"level":"overlay","visible":false,"left":{"type":"number","value":"nan"},"right":{"type":"number","value":"nan"},"top":{"type":"number","value":"nan"},"bottom":{"type":"number","value":"nan"},"left_units":"canvas","right_units":"canvas","top_units":"canvas","bottom_units":"canvas","line_color":"black","line_alpha":1.0,"line_width":2,"line_dash":[4,4],"fill_color":"lightgrey","fill_alpha":0.5}}}},{"type":"object","name":"SaveTool","id":"p1031"},{"type":"object","name":"ResetTool","id":"p1032"},{"type":"object","name":"HelpTool","id":"p1033"}]}},"left":[{"type":"object","name":"LinearAxis","id":"p1018","attributes":{"ticker":{"type":"object","name":"BasicTicker","id":"p1019","attributes":{"mantissas":[1,2,5]}},"formatter":{"type":"object","name":"BasicTickFormatter","id":"p1020"},"axis_label":"y","major_label_policy":{"type":"object","name":"AllLabels","id":"p1021"}}}],"below":[{"type":"object","name":"LinearAxis","id":"p1013","attributes":{"ticker":{"type":"object","name":"BasicTicker","id":"p1014","attributes":{"mantissas":[1,2,5]}},"formatter":{"type":"object","name":"BasicTickFormatter","id":"p1015"},"axis_label":"x","major_label_policy":{"type":"object","name":"AllLabels","id":"p1016"}}}],"center":[{"type":"object","name":"Grid","id":"p1017","attributes":{"axis":{"id":"p1013"}}},{"type":"object","name":"Grid","id":"p1022","attributes":{"dimension":1,"axis":{"id":"p1018"}}},{"type":"object","name":"Legend","id":"p1043","attributes":{"items":[{"type":"object","name":"LegendItem","id":"p1044","attributes":{"label":{"type":"value","value":"Temp."},"renderers":[{"id":"p1040"}]}}]}}]}}]}};
const render_items = [{"docid":"4d4cf6a6-54f1-4d4a-a143-e41d5b6564c7","roots":{"p1001":"fbd0b477-c829-4bc2-9a1e-1ad472aa1e86"},"root_ids":["p1001"]}];
void root.Bokeh.embed.embed_items_notebook(docs_json, render_items);
}
if (root.Bokeh !== undefined) {
embed_document(root);
} else {
let attempts = 0;
const timer = setInterval(function(root) {
if (root.Bokeh !== undefined) {
clearInterval(timer);
embed_document(root);
} else {
attempts++;
if (attempts > 100) {
clearInterval(timer);
console.log("Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing");
}
}
}, 10, root)
}
})(window);
</script>
::: :::
So we need to merge the two data `div` and `script` one output cell IMO.
I think we are in this case here. application/vnd.bokehjs_load.v0+json
is used for this notebook. But it does not have 3 outputs as initialization oddly
https://github.com/quarto-dev/quarto-cli/blob/7bb03a08c8c2af592bc83cd2de39b8ed6c468d74/src/core/jupyter/jupyter-fixups.ts#L103-L108
So we stop fixup, and do not merge the two-cells per output that was supposed to be done after https://github.com/quarto-dev/quarto-cli/blob/7bb03a08c8c2af592bc83cd2de39b8ed6c468d74/src/core/jupyter/jupyter-fixups.ts#L112-L123
It seems from the fixup code that we expect cell.outputs
to have everything but it seems we have now different cells for the initialization and then the outputs.
As something changed in Jupyter and Bokeh and how they output ? 🤔
We added the warning at 414f5f5d6286f281b13f912cae13eebdb4269b0c to handle this case where the expected outputs weren't there...
\\n\"+\n", " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", " \"
\\n\"+\n", " \"\\n\"+\n",
" \"from bokeh.resources import INLINE\\n\"+\n",
" \"output_notebook(resources=INLINE)\\n\"+\n",
" \"
\\n\"+\n",
" \"\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"
\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"
\\n\"+\n \"
It seems this previous issue is not fixed
2107
Same problem. Downloaded repo and installed most current version
1.4.529
with./configure.sh
Not sure why Jupyter is not installed. (Installed with both mamba and conda). It does shows up in correct env:
Originally posted by @prairie-guy in https://github.com/quarto-dev/quarto-cli/issues/2107#issuecomment-1862166865