chore: highlight ansi in browser messages as well (#26881)

This commit is contained in:
Pavel Feldman 2023-09-05 17:29:07 -07:00 committed by GitHub
parent e065a927bb
commit e0db46ae14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -22,15 +22,16 @@ import { ListView } from '@web/components/listView';
import type { Boundaries } from '../geometry'; import type { Boundaries } from '../geometry';
import { msToString } from '@web/uiUtils'; import { msToString } from '@web/uiUtils';
import { ansi2html } from '@web/ansi2html'; import { ansi2html } from '@web/ansi2html';
import type * as trace from '@trace/trace';
import { PlaceholderPanel } from './placeholderPanel'; import { PlaceholderPanel } from './placeholderPanel';
export type ConsoleEntry = { export type ConsoleEntry = {
browserMessage?: trace.ConsoleMessageTraceEvent['initializer'], browserMessage?: {
body: JSX.Element[];
location: string;
},
browserError?: channels.SerializedError; browserError?: channels.SerializedError;
nodeMessage?: { nodeMessage?: {
text?: string; html: string;
base64?: string;
}, },
isError: boolean; isError: boolean;
isWarning: boolean; isWarning: boolean;
@ -54,12 +55,23 @@ export function useConsoleTabModel(model: modelUtil.MultiTraceModel | undefined,
continue; continue;
if (event.method === 'console') { if (event.method === 'console') {
const { guid } = event.params.message; const { guid } = event.params.message;
entries.push({ const browserMessage = modelUtil.context(event).initializers[guid];
browserMessage: modelUtil.context(event).initializers[guid], if (browserMessage) {
isError: modelUtil.context(event).initializers[guid]?.type === 'error', const body = browserMessage.args && browserMessage.args.length ? format(browserMessage.args) : formatAnsi(browserMessage.text);
isWarning: modelUtil.context(event).initializers[guid]?.type === 'warning', const url = browserMessage.location.url;
timestamp: event.time, const filename = url ? url.substring(url.lastIndexOf('/') + 1) : '<anonymous>';
}); const location = `${filename}:${browserMessage.location.lineNumber}`;
entries.push({
browserMessage: {
body,
location,
},
isError: modelUtil.context(event).initializers[guid]?.type === 'error',
isWarning: modelUtil.context(event).initializers[guid]?.type === 'warning',
timestamp: event.time,
});
}
} }
if (event.method === 'pageError') { if (event.method === 'pageError') {
entries.push({ entries.push({
@ -71,11 +83,14 @@ export function useConsoleTabModel(model: modelUtil.MultiTraceModel | undefined,
} }
} }
for (const event of model.stdio) { for (const event of model.stdio) {
let html = '';
if (event.text)
html = ansi2html(event.text.trim()) || '';
if (event.base64)
html = ansi2html(atob(event.base64).trim()) || '';
entries.push({ entries.push({
nodeMessage: { nodeMessage: { html },
text: event.text,
base64: event.base64,
},
isError: event.type === 'stderr', isError: event.type === 'stderr',
isWarning: false, isWarning: false,
timestamp: event.timestamp, timestamp: event.timestamp,
@ -119,11 +134,8 @@ export const ConsoleTab: React.FunctionComponent<{
const { browserMessage, browserError, nodeMessage } = entry; const { browserMessage, browserError, nodeMessage } = entry;
if (browserMessage) { if (browserMessage) {
const text = browserMessage.args && browserMessage.args.length ? format(browserMessage.args) : browserMessage.text; locationText = browserMessage.location;
const url = browserMessage.location.url; messageBody = browserMessage.body;
const filename = url ? url.substring(url.lastIndexOf('/') + 1) : '<anonymous>';
locationText = `${filename}:${browserMessage.location.lineNumber}`;
messageBody = text;
} }
if (browserError) { if (browserError) {
@ -136,11 +148,8 @@ export const ConsoleTab: React.FunctionComponent<{
} }
} }
if (nodeMessage?.text) if (nodeMessage)
messageInnerHTML = ansi2html(nodeMessage.text.trim()) || ''; messageInnerHTML = nodeMessage.html;
if (nodeMessage?.base64)
messageInnerHTML = ansi2html(atob(nodeMessage.base64).trim()) || '';
return <div className='console-line'> return <div className='console-line'>
{timestampElement} {timestampElement}
@ -157,7 +166,8 @@ export const ConsoleTab: React.FunctionComponent<{
function format(args: { preview: string, value: any }[]): JSX.Element[] { function format(args: { preview: string, value: any }[]): JSX.Element[] {
if (args.length === 1) if (args.length === 1)
return [<span>{args[0].preview}</span>]; return formatAnsi(args[0].preview);
const hasMessageFormat = typeof args[0].value === 'string' && args[0].value.includes('%'); const hasMessageFormat = typeof args[0].value === 'string' && args[0].value.includes('%');
const messageFormat = hasMessageFormat ? args[0].value as string : ''; const messageFormat = hasMessageFormat ? args[0].value as string : '';
const tail = hasMessageFormat ? args.slice(1) : args; const tail = hasMessageFormat ? args.slice(1) : args;
@ -203,6 +213,10 @@ function format(args: { preview: string, value: any }[]): JSX.Element[] {
return formatted; return formatted;
} }
function formatAnsi(text: string): JSX.Element[] {
return [<span dangerouslySetInnerHTML={{ __html: ansi2html(text.trim()) }}></span>];
}
function parseCSSStyle(cssFormat: string): Record<string, string | number> { function parseCSSStyle(cssFormat: string): Record<string, string | number> {
try { try {
const styleObject: Record<string, string | number> = {}; const styleObject: Record<string, string | number> = {};