diff --git a/packages/playground/src/index.ts b/packages/playground/src/index.ts index 174350aa0888..9b318b021227 100644 --- a/packages/playground/src/index.ts +++ b/packages/playground/src/index.ts @@ -12,7 +12,7 @@ import { createDragBar, setupSidebarToggle, } from "./createElements" -import { runWithCustomLogs } from "./sidebar/runtime" +import { runWithCustomLogs, clearLogs } from "./sidebar/runtime" import { createExporter } from "./exporter" import { createUI } from "./createUI" import { getExampleSourceCode } from "./getExample" diff --git a/packages/playground/src/sidebar/runtime.ts b/packages/playground/src/sidebar/runtime.ts index fd1b2a897535..c21f0b2ecdc6 100644 --- a/packages/playground/src/sidebar/runtime.ts +++ b/packages/playground/src/sidebar/runtime.ts @@ -1,13 +1,21 @@ +import { Sandbox } from "typescriptlang-org/static/js/sandbox" import { PlaygroundPlugin, PluginFactory } from ".." +import { createUI, UI } from "../createUI" import { localize } from "../localizeWithFallback" let allLogs = "" +let addedClearAction = false export const runPlugin: PluginFactory = (i, utils) => { const plugin: PlaygroundPlugin = { id: "logs", displayName: i("play_sidebar_logs"), willMount: (sandbox, container) => { + if (!addedClearAction) { + const ui = createUI() + addClearAction(sandbox, ui, i) + } + if (allLogs.length === 0) { const noErrorsMessage = document.createElement("div") noErrorsMessage.id = "empty-message-container" @@ -33,6 +41,14 @@ export const runPlugin: PluginFactory = (i, utils) => { return plugin } +export const clearLogs = () => { + allLogs = "" + const logs = document.getElementById("log") + if (logs) { + logs.textContent = "" + } +} + export const runWithCustomLogs = (closure: Promise, i: Function) => { const noLogs = document.getElementById("empty-message-container") if (noLogs) { @@ -62,6 +78,9 @@ function rewireLoggingToElement( fixLoggingFunc("warn", "WRN") fixLoggingFunc("error", "ERR") fixLoggingFunc("info", "INF") + // @ts-expect-error + console["oldclear"] = console.clear + console.clear = clearLogs closure.then(js => { try { @@ -73,11 +92,14 @@ function rewireLoggingToElement( allLogs = allLogs + "
" + // @ts-expect-error + console["clear"] = console["oldclear"] undoLoggingFunc("log") undoLoggingFunc("debug") undoLoggingFunc("warn") undoLoggingFunc("error") undoLoggingFunc("info") + undoLoggingFunc("clear") }) function undoLoggingFunc(name: string) { @@ -113,22 +135,56 @@ function rewireLoggingToElement( } } + const objectToText = (arg: any): string => { + const isObj = typeof arg === "object" + let textRep = "" + if (arg && arg.stack && arg.message) { + // special case for err + textRep = arg.message + } else if (arg === null) { + textRep = "null" + } else if (arg === undefined) { + textRep = "undefined" + } else if (Array.isArray(arg)) { + textRep = "[" + arg.map(objectToText).join(", ") + "]" + } else if (typeof arg === "string") { + textRep = '"' + arg + '"' + } else if (isObj) { + const name = arg.constructor && arg.constructor.name + // No one needs to know an obj is an obj + const nameWithoutObject = name && name === "Object" ? "" : name + const prefix = nameWithoutObject ? `${nameWithoutObject}: ` : "" + textRep = prefix + JSON.stringify(arg, null, 2) + } else { + textRep = arg as any + } + return textRep + } + function produceOutput(args: any[]) { return args.reduce((output: any, arg: any, index) => { - const isObj = typeof arg === "object" - let textRep = "" - if (arg && arg.stack && arg.message) { - // special case for err - textRep = arg.message - } else if (isObj) { - textRep = JSON.stringify(arg, null, 2) - } else { - textRep = arg as any - } - + const textRep = objectToText(arg) const showComma = index !== args.length - 1 const comma = showComma ? ", " : "" return output + textRep + comma + " " }, "") } } + +const addClearAction = (sandbox: Sandbox, ui: UI, i: any) => { + const clearLogsAction = { + id: "clear-logs-play", + label: "Clear Playground Logs", + keybindings: [sandbox.monaco.KeyMod.CtrlCmd | sandbox.monaco.KeyCode.KEY_K], + + contextMenuGroupId: "run", + contextMenuOrder: 1.5, + + run: function () { + clearLogs() + ui.flashInfo(i("play_clear_logs")) + }, + } + + sandbox.editor.addAction(clearLogsAction) +} diff --git a/packages/typescriptlang-org/src/copy/en/playground.ts b/packages/typescriptlang-org/src/copy/en/playground.ts index a950876542b0..4a70cf245da9 100644 --- a/packages/typescriptlang-org/src/copy/en/playground.ts +++ b/packages/typescriptlang-org/src/copy/en/playground.ts @@ -47,6 +47,7 @@ export const playCopy = { play_export_sandbox: "Open in CodeSandbox", play_export_stackblitz: "Open in StackBlitz", play_export_clipboard: "URL copied to clipboard", + play_clear_logs: "Logs cleared", play_run_js: "Executed JavaScript", play_run_ts: "Executed transpiled TypeScript", play_run_js_fail: "Executed JavaScript Failed:",