export default {
name: "Terminal",
data() {
return {
term: '·',
lines: [],
buffer: [],
flushTimer: null
}
},
props: {
output: {
type: String,
default: ""
}
},
methods: {
clearTerminal(){
this.lines = []
}
},
computed:{
line(){
return this.lines.join('\n');
}
},
watch: {
output(chunk){
const newLines = chunk.split('<n>');
newLines.forEach(line => {
if (line.includes('<r>')) {
const replaced = line.replace('<r>', '');
if (this.lines.length > 0) {
this.lines[this.lines.length - 1] = replaced;
} else {
this.lines.push(replaced);
}
} else {
this.lines.push(line);
}
});
this.$nextTick(() => {
const el = this.$refs.logOutput;
if (el) {
el.scrollTop = el.scrollHeight;
}
});
}
},
template: `
<div class="block w-full bg-zinc-900 rounded-sm shadow-xs">
<div class="flex items-center w-full py-1 px-2 bg-black opacity-70">
<div class="flex-1 text-xs">TERMINAL</div>
<div class="flex-none">
<button @click="clearTerminal" title="Clear" type="button" class="p-2 cursor-pointer border border-zinc-800 rounded-sm">
<svg class="w-[10px] h-[10px] fill-[#ffffff]" viewBox="0 0 576 512" xmlns="http://www.w3.org/2000/svg">
<path d="M566.6 54.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192-34.7-34.7c-4.2-4.2-10-6.6-16-6.6c-12.5 0-22.6 10.1-22.6 22.6v29.1L364.3 320h29.1c12.5 0 22.6-10.1 22.6-22.6c0-6-2.4-11.8-6.6-16l-34.7-34.7 192-192zM341.1 353.4L222.6 234.9c-42.7-3.7-85.2 11.7-115.8 42.3l-8 8C76.5 307.5 64 337.7 64 369.2c0 6.8 7.1 11.2 13.2 8.2l51.1-25.5c5-2.5 9.5 4.1 5.4 7.9L7.3 473.4C2.7 477.6 0 483.6 0 489.9C0 502.1 9.9 512 22.1 512l173.3 0c38.8 0 75.9-15.4 103.4-42.8c30.6-30.6 45.9-73.1 42.3-115.8z"></path>
</svg>
</button>
</div>
</div>
<div
ref="logOutput"
style="scrollbar-width: thin; scrollbar-color: #18181b #000000; max-height: calc(100vh - 120px)"
class="bg-black text-gray-100 rounded-b-sm font-mono text-xs p-2 leading-relaxed h-full overflow-auto overflow-x-scroll whitespace-pre-wrap break-words"
>{{ line }}</div>
</div>
`
}
|