Skip to content

Commit

Permalink
Merge pull request #12132 from MichaelHatherly/mh/stdout-colour-html
Browse files Browse the repository at this point in the history
Support colour output in stdout for `jupyter` and `julia` engines
  • Loading branch information
cscheid authored Feb 28, 2025
2 parents 7f8cfd0 + 7ba0fd4 commit d314a19
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 14 deletions.
1 change: 1 addition & 0 deletions news/changelog-1.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,4 @@ All changes included in 1.7:
- ([#10532](https://github.com/quarto-dev/quarto-cli/issues/10532)): Quarto changed default of `--headless=old` to `--headless` as [Chrome 132 has removed old headless mode](https://developer.chrome.com/blog/removing-headless-old-from-chrome) and only support new mode. For using old mode, `QUARTO_CHROMIUM` could be set to a [new `chrome-headless-shell` binary](https://developer.chrome.com/blog/chrome-headless-shell) or too an older chrome version (between 128 and 132) and `QUARTO_CHROMIUM_HEADLESS_MODE` set to `old` for using old headless mode with that compatabitle version.
- ([#10961](https://github.com/quarto-dev/quarto-cli/issues/10961)): Add more information on which Chrome Headless will be used in `quarto check install`. This is helpful to help debug mermaid issues.
- ([#11951](https://github.com/quarto-dev/quarto-cli/issues/11951)): Raw LaTeX table without `tbl-` prefix label for using Quarto crossref are now correctly passed through unmodified.
- ([#12117](https://github.com/quarto-dev/quarto-cli/issues/12117)): Color output to stdout and stderr is now correctly rendered for `html` format in the Jupyter and Julia engines.
38 changes: 24 additions & 14 deletions src/core/jupyter/jupyter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1629,7 +1629,7 @@ async function mdFromCodeCell(
}
md.push(text.join(""));
} else {
md.push(mdOutputStream(stream));
md.push(await mdOutputStream(stream, options));
}
} else if (output.output_type === "error") {
md.push(await mdOutputError(output as JupyterOutputError, options));
Expand Down Expand Up @@ -1766,7 +1766,7 @@ function isMarkdown(output: JupyterOutput, options: JupyterToMarkdownOptions) {
return isDisplayDataType(output, options, displayDataIsMarkdown);
}

function mdOutputStream(output: JupyterOutputStream) {
async function mdOutputStream(output: JupyterOutputStream, options: JupyterToMarkdownOptions) {
let text: string[] = [];
if (typeof output.text === "string") {
text = [output.text];
Expand All @@ -1781,14 +1781,23 @@ function mdOutputStream(output: JupyterOutputStream) {
/<ipython-input.*?>:\d+:\s+/,
"",
);
return mdCodeOutput(
[firstLine, ...text.slice(1)].map(colors.stripColor),
);
text = [firstLine, ...text.slice(1)];
}
}

// normal default handling
return mdCodeOutput(text.map(colors.stripColor));
if (options.toHtml && text.some(hasAnsiEscapeCodes)) {
const linesHTML = await convertToHtmlSpans(text.join("\n"));
return mdMarkdownOutput(
[
"\n::: {.ansi-escaped-output}\n```{=html}\n<pre>",
linesHTML,
"</pre>\n```\n:::\n",
],
);
} else {
// normal default behavior
return mdCodeOutput(text.map(colors.stripColor));
}
}

async function mdOutputError(
Expand Down Expand Up @@ -1864,8 +1873,8 @@ async function mdOutputDisplayData(
// if output is invalid, warn and emit empty
const data = output.data[mimeType] as unknown;
if (!Array.isArray(data) || data.some((s) => typeof s !== "string")) {
return mdWarningOutput(`Unable to process text plain output data
which does not appear to be plain text: ${JSON.stringify(data)}`);
return await mdWarningOutput(`Unable to process text plain output data
which does not appear to be plain text: ${JSON.stringify(data)}`, options);
}
const lines = data as string[];
// pandas inexplicably outputs html tables as text/plain with an enclosing single-quote
Expand Down Expand Up @@ -1900,9 +1909,10 @@ which does not appear to be plain text: ${JSON.stringify(data)}`);
}

// no type match found
return mdWarningOutput(
return await mdWarningOutput(
"Unable to display output for mime type(s): " +
Object.keys(output.data).join(", "),
Object.keys(output.data).join(", "),
options,
);
}

Expand Down Expand Up @@ -2061,12 +2071,12 @@ function mdEnclosedOutput(begin: string, text: string[], end: string) {
return md.join("");
}

function mdWarningOutput(msg: string) {
return mdOutputStream({
async function mdWarningOutput(msg: string, options: JupyterToMarkdownOptions) {
return await mdOutputStream({
output_type: "stream",
name: "stderr",
text: [msg],
});
}, options);
}

function isWarningOutput(output: JupyterOutput) {
Expand Down
18 changes: 18 additions & 0 deletions tests/docs/smoke-all/2025/02/21/12132.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
engine: julia
format: html
_quarto:
tests:
html:
ensureHtmlElements:
- ["div.cell-output-stdout div.ansi-escaped-output pre span.ansi-red-fg.ansi-bold"]
- ["div.cell-output-stdout div.ansi-escaped-output pre span.ansi-red-cyan-bold"]
---

```{julia}
printstyled("red"; color = :red, bold = true)
```

```{julia}
@info "logging"
```

0 comments on commit d314a19

Please sign in to comment.