@dodona/papyros
Version:
Scratchpad for multiple programming languages in the browser.
253 lines (242 loc) • 10.2 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { customElement } from "lit/decorators.js";
import { css, html } from "lit";
import { OutputType, OUTPUT_TAB, TURTLE_TAB } from "../state/InputOutput";
import { PapyrosElement } from "./PapyrosElement";
import { tabButtonStyles } from "./shared-styles";
import "@material/web/icon/icon";
let Output = class Output extends PapyrosElement {
static get styles() {
return css `
:host {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.tabs {
display: flex;
flex-direction: row;
gap: 0.25rem;
padding-top: 0.25rem;
flex-shrink: 0;
position: relative;
z-index: 1;
}
.content {
flex: 1;
overflow: auto;
container-type: size;
padding: 0.75rem;
background-color: var(--md-sys-color-surface-container-highest);
}
.content.turtle {
margin-top: -1px;
padding: 0;
background-color: transparent;
}
img {
max-width: 100%;
max-height: 300px;
display: block;
margin: 0.5rem 0;
}
img.turtle {
max-width: 100cqw;
max-height: 100cqh;
margin: 0;
box-sizing: border-box;
background-color: var(--md-sys-color-surface-container-highest);
border: 1px solid var(--md-sys-color-outline-variant);
}
.turtle-placeholder {
width: 400px;
height: 400px;
max-width: 100cqw;
max-height: 100cqh;
margin: 0;
background-color: var(--md-sys-color-surface-container-highest);
border: 1px solid var(--md-sys-color-outline-variant);
}
pre {
font-family: monospace;
margin: 0;
}
.error {
color: var(--md-sys-color-error);
}
.place-holder {
color: var(--md-sys-color-on-surface);
opacity: 0.5;
}
md-icon {
vertical-align: bottom;
}
${tabButtonStyles}
`;
}
get maxOutputLength() {
if (this.papyros.debugger.active && this.papyros.debugger.debugOutputs !== undefined) {
return this.papyros.debugger.debugOutputs;
}
return this.papyros.constants.maxOutputLength;
}
get outputs() {
return this.papyros.io.output.slice(0, this.maxOutputLength);
}
get overflow() {
return this.papyros.io.output.slice(this.maxOutputLength);
}
get showOverflowWarning() {
return !this.papyros.debugger.active && this.papyros.io.output.length > this.maxOutputLength;
}
get downloadOverflowUrl() {
const blob = new Blob(this.overflow.map((o) => {
if (o.type === OutputType.img || o.type === OutputType.turtle) {
return `[Image output of type ${o.contentType} omitted]\n`;
}
else if (o.type === OutputType.stdout) {
return o.content;
}
else if (o.type === OutputType.stderr) {
if (typeof o.content === "string") {
return `Error: ${o.content}\n`;
}
else {
const errorObject = o.content;
let errorString = `Error: ${errorObject.name}\nInfo: ${errorObject.info}\nTraceback: ${errorObject.traceback}\n`;
if (errorObject.where) {
errorString += `Where: ${errorObject.where.trim()}\n`;
}
if (errorObject.what) {
errorString += `What: ${errorObject.what.trim()}\n`;
}
if (errorObject.why) {
errorString += `Why: ${errorObject.why.trim()}\n`;
}
return errorString;
}
}
else {
return "[Unsupported output type omitted]\n";
}
}), { type: "text/plain" });
return URL.createObjectURL(blob);
}
get renderedOutputs() {
let outputsToRender;
if (this.papyros.io.activeOutputTab === TURTLE_TAB) {
// Latest snapshot within this.outputs (which is sliced by the debugger's current
// step via maxOutputLength) — so stepping the debugger shows the drawing build up.
const lastIdx = this.outputs.findLastIndex((o) => o.type === OutputType.turtle);
outputsToRender = lastIdx >= 0 ? [this.outputs[lastIdx]] : [];
}
else {
outputsToRender = this.outputs.filter((o) => o.type !== OutputType.turtle);
}
return outputsToRender.map((o) => {
var _a, _b, _c;
if (o.type === OutputType.stdout) {
return html `${o.content}`;
}
else if (o.type === OutputType.img) {
const mimeType = (_a = o.contentType) !== null && _a !== void 0 ? _a : "image/png";
return html `<img src="data:${mimeType},${o.content}"></img>`;
}
else if (o.type === OutputType.turtle) {
const mimeType = (_b = o.contentType) !== null && _b !== void 0 ? _b : "image/svg+xml;base64";
return html `<img class="turtle" src="data:${mimeType},${o.content}"></img>`;
}
else if (o.type === OutputType.stderr) {
if (typeof o.content === "string") {
return html `<span class="error">${o.content}</span>`;
}
else {
const errorObject = o.content;
const errorHTML = [
// an array to avoid unintentional spaces/newlines
html `<md-icon title="${errorObject.info}"> ${this.papyros.constants.icons.help} </md-icon>
${errorObject.name} traceback:
<md-icon title="${errorObject.traceback}">
${this.papyros.constants.icons.info}
</md-icon> `,
html `<span class="where">${(_c = errorObject.where) === null || _c === void 0 ? void 0 : _c.trim()}</span> `,
];
if (errorObject.what) {
errorHTML.push(html `<span class="what">${errorObject.what.trim()}</span> `);
}
if (errorObject.why) {
errorHTML.push(html `<span class="why">${errorObject.why.trim()}</span> `);
}
return html `<span class="error">${errorHTML}</span>`;
}
}
else {
return html ``; // unsupported output type
}
});
}
get showTurtleTab() {
return this.papyros.io.hasTurtleOutput || this.papyros.io.activeOutputTab === TURTLE_TAB;
}
renderTabs() {
const activeTab = this.papyros.io.activeOutputTab;
return html `
<div class="tabs">
<button
class=${activeTab === OUTPUT_TAB ? "active" : ""}
=${() => this.papyros.io.selectOutputTab(OUTPUT_TAB)}
>
${this.t("Papyros.output_tab_output")}
</button>
${this.showTurtleTab
? html `
<button
class=${activeTab === TURTLE_TAB ? "active" : ""}
=${() => this.papyros.io.selectOutputTab(TURTLE_TAB)}
>
${this.t("Papyros.output_tab_turtle")}
</button>
`
: html ``}
</div>
`;
}
render() {
const activeTab = this.papyros.io.activeOutputTab;
const rendered = this.renderedOutputs;
const showPlaceholder = activeTab === OUTPUT_TAB && rendered.length === 0;
const showTurtlePlaceholder = activeTab === TURTLE_TAB && rendered.length === 0;
const showOverflow = activeTab === OUTPUT_TAB && this.showOverflowWarning;
return html `
${this.renderTabs()}
<div class="content ${activeTab === TURTLE_TAB ? "turtle" : ""}">
${showPlaceholder
? html `<pre class="place-holder">${this.t("Papyros.output_placeholder")}</pre>`
: showTurtlePlaceholder
? html `<div class="turtle-placeholder"></div>`
: html `<pre>${rendered}</pre>`}
${showOverflow
? html `
<p>
${this.t("Papyros.output_overflow")}
<a href="${this.downloadOverflowUrl}" download="papyros_output.txt">
${this.t("Papyros.output_overflow_download")}
</a>
</p>
`
: html ``}
</div>
`;
}
};
Output = __decorate([
customElement("p-output")
], Output);
export { Output };
//# sourceMappingURL=Output.js.map