Skip to content

Commit d9778a5

Browse files
committed
feat: output tail
1 parent d949184 commit d9778a5

File tree

4 files changed

+71
-5
lines changed

4 files changed

+71
-5
lines changed

src/output.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// An output of an interactive code snippet.
22

33
import json from "./json.js";
4+
import text from "./text.js";
45

56
// Output modes.
67
const OutputMode = {
@@ -26,9 +27,12 @@ template.innerHTML = `
2627
// All prefer stdout to stderr.
2728
const builders = {
2829
// returns the result as a text node.
29-
[OutputMode.text]: (result) => {
30-
const text = result.stdout || result.stderr || PLACEHOLDER;
31-
return document.createTextNode(text);
30+
[OutputMode.text]: (result, shouldTail) => {
31+
const value = result.stdout || result.stderr || PLACEHOLDER;
32+
if (shouldTail) {
33+
return document.createTextNode(text.tail(value));
34+
}
35+
return document.createTextNode(value);
3236
},
3337

3438
// returns the result as an HTML table.
@@ -146,7 +150,7 @@ class CodapiOutput extends HTMLElement {
146150

147151
// showResult shows the results of the code execution.
148152
showResult(result) {
149-
const node = builders[this.mode](result);
153+
const node = builders[this.mode](result, this.tail);
150154
this.output.innerHTML = "";
151155
if (!node) {
152156
this.hide();
@@ -190,6 +194,18 @@ class CodapiOutput extends HTMLElement {
190194
}
191195
this.setAttribute("mode", value);
192196
}
197+
198+
// display only the last part of the output.
199+
get tail() {
200+
return this.hasAttribute("tail");
201+
}
202+
set tail(value) {
203+
if (value) {
204+
this.setAttribute("tail", "");
205+
} else {
206+
this.removeAttribute("tail");
207+
}
208+
}
193209
}
194210

195211
if (!window.customElements.get("codapi-output")) {

src/snippet.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class CodapiSnippet extends HTMLElement {
100100

101101
this._output = this.querySelector("codapi-output");
102102
this._output.mode = this.getAttribute("output-mode");
103+
this._output.tail = this.hasAttribute("output-tail");
103104
if (this.hasAttribute("output")) {
104105
this._fallback = this.extractFallback(this.getAttribute("output"));
105106
}

src/text.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// tail separator
2+
const TAIL_SEPARATOR = "---";
3+
14
// cut slices s around the first instance of sep,
25
// returning the text before and after sep.
36
// If sep does not appear in s, cut returns [s, ""].
@@ -9,4 +12,11 @@ function cut(s, sep) {
912
return [s, ""];
1013
}
1114

12-
export default { cut };
15+
// tail returns the last part of s after the separator line.
16+
// If s does not contain a separator, returns s unchanged.
17+
function tail(s) {
18+
const index = s.lastIndexOf(`\n${TAIL_SEPARATOR}`);
19+
return index === -1 ? s : s.slice(index + 5);
20+
}
21+
22+
export default { cut, tail };

tests/snippet.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ async function runTests() {
5555
await testOutputModeIframe();
5656
await testOutputModeDOM();
5757
await testOutputModeHidden();
58+
5859
await testOutputPlaceholder();
60+
await testOutputNoTail();
61+
await testOutputTail();
5962

6063
await testTemplate();
6164
await testTemplateChange();
@@ -760,6 +763,42 @@ async function testOutputPlaceholder() {
760763
});
761764
}
762765

766+
async function testOutputNoTail() {
767+
return new Promise((resolve, reject) => {
768+
t.log("testOutputNoTail...");
769+
const ui = createSnippet(`
770+
<pre><code>console.log("hello");
771+
console.log("---");
772+
console.log("world");</code></pre>
773+
<codapi-snippet engine="browser" sandbox="javascript" output-mode="text">
774+
</codapi-snippet>
775+
`);
776+
ui.snip.addEventListener("result", (event) => {
777+
t.assert("output", ui.output.out.innerHTML == "hello\n---\nworld");
778+
resolve();
779+
});
780+
ui.toolbar.run.click();
781+
});
782+
}
783+
784+
async function testOutputTail() {
785+
return new Promise((resolve, reject) => {
786+
t.log("testOutputTail...");
787+
const ui = createSnippet(`
788+
<pre><code>console.log("hello");
789+
console.log("---");
790+
console.log("world");</code></pre>
791+
<codapi-snippet engine="browser" sandbox="javascript" output-mode="text" output-tail>
792+
</codapi-snippet>
793+
`);
794+
ui.snip.addEventListener("result", (event) => {
795+
t.assert("output", ui.output.out.innerHTML == "world");
796+
resolve();
797+
});
798+
ui.toolbar.run.click();
799+
});
800+
}
801+
763802
async function testTemplate() {
764803
return new Promise((resolve, reject) => {
765804
t.log("testTemplate...");

0 commit comments

Comments
 (0)