diff --git a/frontend/components/ErrorMessage.js b/frontend/components/ErrorMessage.js index c980ef119..828428127 100644 --- a/frontend/components/ErrorMessage.js +++ b/frontend/components/ErrorMessage.js @@ -5,6 +5,7 @@ import { highlight } from "./CellOutput.js" import { PkgTerminalView } from "./PkgTerminalView.js" import _ from "../imports/lodash.js" import { open_bottom_right_panel } from "./BottomRightPanel.js" +import AnsiUp from "../imports/AnsiUp.js" const extract_cell_id = (/** @type {string} */ file) => { const sep_index = file.indexOf("#==#") @@ -243,11 +244,22 @@ const frame_is_important_heuristic = (frame, frame_index, limited_stacktrace, fr return true } +const AnsiUpLine = (/** @type {{value: string}} */ { value }) => { + const node_ref = useRef(/** @type {HTMLElement?} */ (null)) + + useEffect(() => { + if (!node_ref.current) return + node_ref.current.innerHTML = new AnsiUp().ansi_to_html(value) + }, [node_ref.current, value]) + + return value === "" ? html`


` : html`

` +} + export const ErrorMessage = ({ msg, stacktrace, cell_id }) => { let pluto_actions = useContext(PlutoActionsContext) const default_rewriter = { pattern: /.?/, - display: (/** @type{string} */ x) => _.dropRightWhile(x.split("\n"), (s) => s === "").map((line) => html`

${line === "" ? html`
` : line}

`), + display: (/** @type{string} */ x) => _.dropRightWhile(x.split("\n"), (s) => s === "").map((line) => html`<${AnsiUpLine} value=${line} />`), } const rewriters = [ { diff --git a/src/runner/PlutoRunner/src/display/Exception.jl b/src/runner/PlutoRunner/src/display/Exception.jl index 835c500ce..365c8ef4d 100644 --- a/src/runner/PlutoRunner/src/display/Exception.jl +++ b/src/runner/PlutoRunner/src/display/Exception.jl @@ -127,7 +127,7 @@ end "Because even showerror can error... 👀" function try_showerror(io::IO, e, args...) try - showerror(io, e, args...) + showerror(IOContext(io, :color => true), e, args...) catch show_ex print(io, "\nFailed to show error:\n\n") try_showerror(io, show_ex, stacktrace(catch_backtrace()))