mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-01-24 08:08:38 +00:00
Remove xterm and use ansi converter for logs (#1067)
* Steaming works without flickering * Text can be correctly copied * Show only selected step output when streaming * Improved exit code colors for better readability * Adds time display on right side When compiled assets/Build.js size was 355K, now it is 26K Fixes #1012 Fixes #998 Co-authored-by: Anbraten <anton@ju60.de>
This commit is contained in:
parent
98636a5493
commit
2f5e5b8e2c
4 changed files with 318 additions and 136 deletions
|
@ -20,7 +20,7 @@
|
||||||
"@intlify/vite-plugin-vue-i18n": "^3.4.0",
|
"@intlify/vite-plugin-vue-i18n": "^3.4.0",
|
||||||
"@kyvg/vue3-notification": "2.3.4",
|
"@kyvg/vue3-notification": "2.3.4",
|
||||||
"@meforma/vue-toaster": "1.2.2",
|
"@meforma/vue-toaster": "1.2.2",
|
||||||
"ansi-to-html": "0.7.2",
|
"ansi_up": "^5.1.0",
|
||||||
"dayjs": "1.10.7",
|
"dayjs": "1.10.7",
|
||||||
"floating-vue": "2.0.0-beta.5",
|
"floating-vue": "2.0.0-beta.5",
|
||||||
"fuse.js": "6.4.6",
|
"fuse.js": "6.4.6",
|
||||||
|
@ -31,10 +31,7 @@
|
||||||
"pinia": "2.0.0",
|
"pinia": "2.0.0",
|
||||||
"vue": "v3.2.20",
|
"vue": "v3.2.20",
|
||||||
"vue-i18n": "9",
|
"vue-i18n": "9",
|
||||||
"vue-router": "4.0.10",
|
"vue-router": "4.0.10"
|
||||||
"xterm": "4.17.0",
|
|
||||||
"xterm-addon-fit": "0.5.0",
|
|
||||||
"xterm-addon-web-links": "0.5.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify/json": "1.1.421",
|
"@iconify/json": "1.1.421",
|
||||||
|
|
|
@ -23,8 +23,26 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="loadedLogs" class="w-full flex-grow p-2">
|
<div
|
||||||
<div id="terminal" class="w-full h-full" />
|
v-show="loadedLogs"
|
||||||
|
ref="consoleElement"
|
||||||
|
class="
|
||||||
|
w-full
|
||||||
|
max-w-full
|
||||||
|
grid grid-cols-[min-content,1fr,min-content]
|
||||||
|
auto-rows-min
|
||||||
|
flex-grow
|
||||||
|
p-2
|
||||||
|
gap-x-2
|
||||||
|
overflow-x-hidden overflow-y-auto
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div v-for="line in log" :key="line.index" class="contents font-mono">
|
||||||
|
<span class="text-gray-500 whitespace-nowrap select-none text-right">{{ line.index + 1 }}</span>
|
||||||
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||||
|
<span class="align-top text-color whitespace-pre-wrap break-words" v-html="line.text" />
|
||||||
|
<span class="text-gray-500 whitespace-nowrap select-none text-right">{{ formatTime(line.time) }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="m-auto text-xl text-color">
|
<div class="m-auto text-xl text-color">
|
||||||
|
@ -36,8 +54,8 @@
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="proc?.end_time !== undefined"
|
v-if="proc?.end_time !== undefined"
|
||||||
:class="proc.exit_code == 0 ? 'dark:text-lime-400 text-lime-600' : 'dark:text-red-400 text-red-600'"
|
:class="proc.exit_code == 0 ? 'dark:text-lime-400 text-lime-700' : 'dark:text-red-400 text-red-600'"
|
||||||
class="w-full bg-gray-400 dark:bg-dark-gray-800 text-md p-4"
|
class="w-full bg-gray-200 dark:bg-dark-gray-800 text-md p-4"
|
||||||
>
|
>
|
||||||
{{ $t('repo.build.exit_code', { exitCode: proc.exit_code }) }}
|
{{ $t('repo.build.exit_code', { exitCode: proc.exit_code }) }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -46,34 +64,26 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import 'xterm/css/xterm.css';
|
import '~/style/console.css';
|
||||||
|
|
||||||
import {
|
import AnsiUp from 'ansi_up';
|
||||||
computed,
|
import { debounce } from 'lodash';
|
||||||
defineComponent,
|
import { computed, defineComponent, inject, nextTick, onMounted, PropType, Ref, ref, toRef, watch } from 'vue';
|
||||||
inject,
|
|
||||||
nextTick,
|
|
||||||
onBeforeUnmount,
|
|
||||||
onMounted,
|
|
||||||
PropType,
|
|
||||||
Ref,
|
|
||||||
ref,
|
|
||||||
toRef,
|
|
||||||
watch,
|
|
||||||
} from 'vue';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { Terminal } from 'xterm';
|
|
||||||
import { FitAddon } from 'xterm-addon-fit';
|
|
||||||
import { WebLinksAddon } from 'xterm-addon-web-links';
|
|
||||||
|
|
||||||
import Button from '~/components/atomic/Button.vue';
|
import Button from '~/components/atomic/Button.vue';
|
||||||
import Icon from '~/components/atomic/Icon.vue';
|
import Icon from '~/components/atomic/Icon.vue';
|
||||||
import useApiClient from '~/compositions/useApiClient';
|
import useApiClient from '~/compositions/useApiClient';
|
||||||
import { useDarkMode } from '~/compositions/useDarkMode';
|
|
||||||
import useNotifications from '~/compositions/useNotifications';
|
import useNotifications from '~/compositions/useNotifications';
|
||||||
import { Build, Repo } from '~/lib/api/types';
|
import { Build, Repo } from '~/lib/api/types';
|
||||||
import { findProc, isProcFinished, isProcRunning } from '~/utils/helpers';
|
import { findProc, isProcFinished, isProcRunning } from '~/utils/helpers';
|
||||||
|
|
||||||
|
type LogLine = {
|
||||||
|
index: number;
|
||||||
|
text: string;
|
||||||
|
time?: number;
|
||||||
|
};
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'BuildLog',
|
name: 'BuildLog',
|
||||||
|
|
||||||
|
@ -110,24 +120,78 @@ export default defineComponent({
|
||||||
const procSlug = computed(() => `${repo?.value.owner} - ${repo?.value.name} - ${build.value.id} - ${procId.value}`);
|
const procSlug = computed(() => `${repo?.value.owner} - ${repo?.value.name} - ${build.value.id} - ${procId.value}`);
|
||||||
const proc = computed(() => build.value && findProc(build.value.procs || [], procId.value));
|
const proc = computed(() => build.value && findProc(build.value.procs || [], procId.value));
|
||||||
const stream = ref<EventSource>();
|
const stream = ref<EventSource>();
|
||||||
const term = ref(
|
const log = ref<LogLine[]>();
|
||||||
new Terminal({
|
const consoleElement = ref<Element>();
|
||||||
convertEol: true,
|
|
||||||
disableStdin: true,
|
const loadedLogs = computed(() => !!log.value);
|
||||||
theme: {
|
const autoScroll = ref(true); // TODO: allow enable / disable
|
||||||
cursor: 'transparent',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
const fitAddon = ref(new FitAddon());
|
|
||||||
const loadedLogs = ref(true);
|
|
||||||
const autoScroll = ref(true); // TODO
|
|
||||||
const showActions = ref(false);
|
const showActions = ref(false);
|
||||||
const downloadInProgress = ref(false);
|
const downloadInProgress = ref(false);
|
||||||
|
const ansiUp = ref(new AnsiUp());
|
||||||
|
ansiUp.value.use_classes = true;
|
||||||
|
const logBuffer = ref<LogLine[]>([]);
|
||||||
|
|
||||||
|
const maxLineCount = 500; // TODO: think about way to support lazy-loading more than last 300 logs (#776)
|
||||||
|
|
||||||
|
function formatTime(time?: number): string {
|
||||||
|
return time === undefined ? '' : `${time}s`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeLog(line: LogLine) {
|
||||||
|
logBuffer.value.push({
|
||||||
|
index: line.index ?? 0,
|
||||||
|
text: ansiUp.value.ansi_to_html(line.text),
|
||||||
|
time: line.time ?? 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollDown() {
|
||||||
|
nextTick(() => {
|
||||||
|
if (!consoleElement.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
consoleElement.value.scrollTop = consoleElement.value.scrollHeight;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const flushLogs = debounce((scroll: boolean) => {
|
||||||
|
let buffer = logBuffer.value.slice(-maxLineCount);
|
||||||
|
logBuffer.value = [];
|
||||||
|
|
||||||
|
if (buffer.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// append old logs lines
|
||||||
|
if (buffer.length < maxLineCount && log.value) {
|
||||||
|
buffer = [...log.value.slice(-(maxLineCount - buffer.length)), ...buffer];
|
||||||
|
}
|
||||||
|
|
||||||
|
// deduplicate repeating times
|
||||||
|
buffer = buffer.reduce(
|
||||||
|
(acc, line) => ({
|
||||||
|
lastTime: line.time ?? 0,
|
||||||
|
lines: [
|
||||||
|
...acc.lines,
|
||||||
|
{
|
||||||
|
...line,
|
||||||
|
time: acc.lastTime === line.time ? undefined : line.time,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
{ lastTime: -1, lines: [] as LogLine[] },
|
||||||
|
).lines;
|
||||||
|
|
||||||
|
log.value = buffer;
|
||||||
|
|
||||||
|
if (scroll && autoScroll.value) {
|
||||||
|
scrollDown();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
|
||||||
async function download() {
|
async function download() {
|
||||||
if (!repo?.value || !build.value || !proc.value) {
|
if (!repo?.value || !build.value || !proc.value) {
|
||||||
throw new Error('The reposiotry, build or proc was undefined');
|
throw new Error('The repository, build or proc was undefined');
|
||||||
}
|
}
|
||||||
let logs;
|
let logs;
|
||||||
try {
|
try {
|
||||||
|
@ -163,9 +227,10 @@ export default defineComponent({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loadedProcSlug.value = procSlug.value;
|
loadedProcSlug.value = procSlug.value;
|
||||||
loadedLogs.value = false;
|
log.value = [];
|
||||||
term.value.reset();
|
logBuffer.value = [];
|
||||||
term.value.write('\x1b[?25l');
|
ansiUp.value = new AnsiUp();
|
||||||
|
ansiUp.value.use_classes = true;
|
||||||
|
|
||||||
if (!repo) {
|
if (!repo) {
|
||||||
throw new Error('Unexpected: "repo" should be provided at this place');
|
throw new Error('Unexpected: "repo" should be provided at this place');
|
||||||
|
@ -188,13 +253,8 @@ export default defineComponent({
|
||||||
|
|
||||||
if (isProcFinished(proc.value)) {
|
if (isProcFinished(proc.value)) {
|
||||||
const logs = await apiClient.getLogs(repo.value.owner, repo.value.name, build.value.number, proc.value.pid);
|
const logs = await apiClient.getLogs(repo.value.owner, repo.value.name, build.value.number, proc.value.pid);
|
||||||
term.value.write(
|
logs.forEach((line) => writeLog({ index: line.pos, text: line.out, time: line.time }));
|
||||||
logs
|
flushLogs(false);
|
||||||
.slice(Math.max(logs.length, 0) - 300, logs.length) // TODO: think about way to support lazy-loading more than last 300 logs (#776)
|
|
||||||
.map((line) => `${(line.pos || 0).toString().padEnd(logs.length.toString().length)} ${line.out}`)
|
|
||||||
.join(''),
|
|
||||||
);
|
|
||||||
loadedLogs.value = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isProcRunning(proc.value)) {
|
if (isProcRunning(proc.value)) {
|
||||||
|
@ -205,42 +265,18 @@ export default defineComponent({
|
||||||
repo.value.name,
|
repo.value.name,
|
||||||
build.value.number,
|
build.value.number,
|
||||||
proc.value.ppid,
|
proc.value.ppid,
|
||||||
(l) => {
|
(line) => {
|
||||||
loadedLogs.value = true;
|
if (line?.proc !== proc.value?.name) {
|
||||||
term.value.write(l.out, () => {
|
return;
|
||||||
if (autoScroll.value) {
|
}
|
||||||
term.value.scrollToBottom();
|
writeLog({ index: line.pos, text: line.out, time: line.time });
|
||||||
}
|
flushLogs(true);
|
||||||
});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function resize() {
|
|
||||||
fitAddon.value.fit();
|
|
||||||
}
|
|
||||||
|
|
||||||
const unmounted = ref(false);
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
term.value.loadAddon(fitAddon.value);
|
|
||||||
term.value.loadAddon(new WebLinksAddon());
|
|
||||||
|
|
||||||
await nextTick(() => {
|
|
||||||
if (unmounted.value) {
|
|
||||||
// need to check if unmounted already because we are async here
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const element = document.getElementById('terminal');
|
|
||||||
if (element === null) {
|
|
||||||
throw new Error('Unexpected: "terminal" should be provided at this place');
|
|
||||||
}
|
|
||||||
term.value.open(element);
|
|
||||||
fitAddon.value.fit();
|
|
||||||
|
|
||||||
window.addEventListener('resize', resize);
|
|
||||||
});
|
|
||||||
|
|
||||||
loadLogs();
|
loadLogs();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -248,44 +284,15 @@ export default defineComponent({
|
||||||
loadLogs();
|
loadLogs();
|
||||||
});
|
});
|
||||||
|
|
||||||
const { darkMode } = useDarkMode();
|
watch(proc, (oldProc, newProc) => {
|
||||||
watch(
|
if (oldProc && oldProc.name === newProc?.name && oldProc?.end_time !== newProc?.end_time) {
|
||||||
darkMode,
|
if (autoScroll.value) {
|
||||||
() => {
|
scrollDown();
|
||||||
if (darkMode.value) {
|
|
||||||
term.value.options = {
|
|
||||||
theme: {
|
|
||||||
background: '#303440', // dark-gray-700
|
|
||||||
foreground: '#d3d3d3', // gray-...
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
term.value.options = {
|
|
||||||
theme: {
|
|
||||||
background: 'rgb(209,213,219)', // gray-300
|
|
||||||
foreground: '#000',
|
|
||||||
selection: '#000',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
unmounted.value = true;
|
|
||||||
if (stream.value) {
|
|
||||||
stream.value.close();
|
|
||||||
}
|
}
|
||||||
const element = document.getElementById('terminal');
|
|
||||||
if (element !== null) {
|
|
||||||
// Clean up any custom DOM added in onMounted above
|
|
||||||
element.innerHTML = '';
|
|
||||||
}
|
|
||||||
window.removeEventListener('resize', resize);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return { proc, loadedLogs, showActions, download, downloadInProgress };
|
return { consoleElement, proc, log, loadedLogs, formatTime, showActions, download, downloadInProgress };
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
195
web/src/style/console.css
Normal file
195
web/src/style/console.css
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
.ansi-black-fg {
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
.ansi-red-fg {
|
||||||
|
color: #cc0000;
|
||||||
|
}
|
||||||
|
.ansi-green-fg {
|
||||||
|
color: #4e9a06;
|
||||||
|
}
|
||||||
|
.ansi-yellow-fg {
|
||||||
|
color: #c4a000;
|
||||||
|
}
|
||||||
|
.ansi-blue-fg {
|
||||||
|
color: #729fcf;
|
||||||
|
}
|
||||||
|
.ansi-magenta-fg {
|
||||||
|
color: #75507b;
|
||||||
|
}
|
||||||
|
.ansi-cyan-fg {
|
||||||
|
color: #06989a;
|
||||||
|
}
|
||||||
|
.ansi-white-fg {
|
||||||
|
color: #d3d7cf;
|
||||||
|
}
|
||||||
|
.ansi-bright-black-fg {
|
||||||
|
color: #555753;
|
||||||
|
}
|
||||||
|
.ansi-bright-red-fg {
|
||||||
|
color: #ef2929;
|
||||||
|
}
|
||||||
|
.ansi-bright-green-fg {
|
||||||
|
color: #8ae234;
|
||||||
|
}
|
||||||
|
.ansi-bright-yellow-fg {
|
||||||
|
color: #fce94f;
|
||||||
|
}
|
||||||
|
.ansi-bright-blue-fg {
|
||||||
|
color: #32afff;
|
||||||
|
}
|
||||||
|
.ansi-bright-magenta-fg {
|
||||||
|
color: #ad7fa8;
|
||||||
|
}
|
||||||
|
.ansi-bright-cyan-fg {
|
||||||
|
color: #34e2e2;
|
||||||
|
}
|
||||||
|
.ansi-bright-white-fg {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ansi-black-bg {
|
||||||
|
background-color: #374151;
|
||||||
|
}
|
||||||
|
.ansi-red-bg {
|
||||||
|
background-color: #cc0000;
|
||||||
|
}
|
||||||
|
.ansi-green-bg {
|
||||||
|
background-color: #4e9a06;
|
||||||
|
}
|
||||||
|
.ansi-yellow-bg {
|
||||||
|
background-color: #c4a000;
|
||||||
|
}
|
||||||
|
.ansi-blue-bg {
|
||||||
|
background-color: #729fcf;
|
||||||
|
}
|
||||||
|
.ansi-magenta-bg {
|
||||||
|
background-color: #75507b;
|
||||||
|
}
|
||||||
|
.ansi-cyan-bg {
|
||||||
|
background-color: #06989a;
|
||||||
|
}
|
||||||
|
.ansi-white-bg {
|
||||||
|
background-color: #d3d7cf;
|
||||||
|
}
|
||||||
|
.ansi-bright-black-bg {
|
||||||
|
background-color: #555753;
|
||||||
|
}
|
||||||
|
.ansi-bright-red-bg {
|
||||||
|
background-color: #ef2929;
|
||||||
|
}
|
||||||
|
.ansi-bright-green-bg {
|
||||||
|
background-color: #8ae234;
|
||||||
|
}
|
||||||
|
.ansi-bright-yellow-bg {
|
||||||
|
background-color: #fce94f;
|
||||||
|
}
|
||||||
|
.ansi-bright-blue-bg {
|
||||||
|
background-color: #32afff;
|
||||||
|
}
|
||||||
|
.ansi-bright-magenta-bg {
|
||||||
|
background-color: #ad7fa8;
|
||||||
|
}
|
||||||
|
.ansi-bright-cyan-bg {
|
||||||
|
background-color: #34e2e2;
|
||||||
|
}
|
||||||
|
.ansi-bright-white-bg {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .ansi-black-fg {
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
.dark .ansi-red-fg {
|
||||||
|
color: #ff7070;
|
||||||
|
}
|
||||||
|
.dark .ansi-green-fg {
|
||||||
|
color: #b0f986;
|
||||||
|
}
|
||||||
|
.dark .ansi-yellow-fg {
|
||||||
|
color: #c6c502;
|
||||||
|
}
|
||||||
|
.dark .ansi-blue-fg {
|
||||||
|
color: #8db7e0;
|
||||||
|
}
|
||||||
|
.dark .ansi-magenta-fg {
|
||||||
|
color: #f271fb;
|
||||||
|
}
|
||||||
|
.dark .ansi-cyan-fg {
|
||||||
|
color: #6bf7ff;
|
||||||
|
}
|
||||||
|
.dark .ansi-white-fg {
|
||||||
|
color: #9ca3af;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-black-fg {
|
||||||
|
color: #838887;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-red-fg {
|
||||||
|
color: #ff3333;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-green-fg {
|
||||||
|
color: #00ff00;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-yellow-fg {
|
||||||
|
color: #fffc67;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-blue-fg {
|
||||||
|
color: #6871ff;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-magenta-fg {
|
||||||
|
color: #ff76ff;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-cyan-fg {
|
||||||
|
color: #60fcff;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-white-fg {
|
||||||
|
color: #e6e3e3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .ansi-black-bg {
|
||||||
|
background-color: #666666;
|
||||||
|
}
|
||||||
|
.dark .ansi-red-bg {
|
||||||
|
background-color: #ff7070;
|
||||||
|
}
|
||||||
|
.dark .ansi-green-bg {
|
||||||
|
background-color: #b0f986;
|
||||||
|
}
|
||||||
|
.dark .ansi-yellow-bg {
|
||||||
|
background-color: #c6c502;
|
||||||
|
}
|
||||||
|
.dark .ansi-blue-bg {
|
||||||
|
background-color: #8db7e0;
|
||||||
|
}
|
||||||
|
.dark .ansi-magenta-bg {
|
||||||
|
background-color: #f271fb;
|
||||||
|
}
|
||||||
|
.dark .ansi-cyan-bg {
|
||||||
|
background-color: #6bf7ff;
|
||||||
|
}
|
||||||
|
.dark .ansi-white-bg {
|
||||||
|
background-color: #9ca3af;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-black-bg {
|
||||||
|
background-color: #838887;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-red-bg {
|
||||||
|
background-color: #ff3333;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-green-bg {
|
||||||
|
background-color: #00ff00;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-yellow-bg {
|
||||||
|
background-color: #fffc67;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-blue-bg {
|
||||||
|
background-color: #6871ff;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-magenta-bg {
|
||||||
|
background-color: #ff76ff;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-cyan-bg {
|
||||||
|
background-color: #60fcff;
|
||||||
|
}
|
||||||
|
.dark .ansi-bright-white-bg {
|
||||||
|
background-color: #e6e3e3;
|
||||||
|
}
|
|
@ -677,12 +677,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
color-convert "^2.0.1"
|
color-convert "^2.0.1"
|
||||||
|
|
||||||
ansi-to-html@0.7.2:
|
ansi_up@^5.1.0:
|
||||||
version "0.7.2"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.7.2.tgz#a92c149e4184b571eb29a0135ca001a8e2d710cb"
|
resolved "https://registry.yarnpkg.com/ansi_up/-/ansi_up-5.1.0.tgz#9cf10e6d359bb434bdcfab5ae4c3abfe1617b6db"
|
||||||
integrity sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g==
|
integrity sha512-3wwu+nJCKBVBwOCurm0uv91lMoVkhFB+3qZQz3U11AmAdDJ4tkw1sNPWJQcVxMVYwe0pGEALOjSBOxdxNc+pNQ==
|
||||||
dependencies:
|
|
||||||
entities "^2.2.0"
|
|
||||||
|
|
||||||
anymatch@~3.1.2:
|
anymatch@~3.1.2:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
|
@ -1097,7 +1095,7 @@ enquirer@^2.3.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-colors "^4.1.1"
|
ansi-colors "^4.1.1"
|
||||||
|
|
||||||
entities@^2.0.0, entities@^2.2.0:
|
entities@^2.0.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||||
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
||||||
|
@ -3242,21 +3240,6 @@ wrappy@1:
|
||||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||||
|
|
||||||
xterm-addon-fit@0.5.0:
|
|
||||||
version "0.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596"
|
|
||||||
integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==
|
|
||||||
|
|
||||||
xterm-addon-web-links@0.5.1:
|
|
||||||
version "0.5.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.5.1.tgz#73bfa3ed567af98fba947f638bd12093ee2a0bc6"
|
|
||||||
integrity sha512-dBjbOIrCNmxAcUQkkSrKj9BM6yLpmqUpZ9SOCUuZe/sznPl4d8OBZQClK7VcdZ0vf0+5i5Fce2rUUrew/XTZTg==
|
|
||||||
|
|
||||||
xterm@4.17.0:
|
|
||||||
version "4.17.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.17.0.tgz#e48ba6eeb83e118ec163f5512c3cfe9dbbf3f838"
|
|
||||||
integrity sha512-WGXlIHvLvZKtwMdFaL6kUwp+c9abd2Pcakp/GmuefBuOtGCu9fP9tBDPKyL/A17N+5tt44EYk3YsBbvkPBubMw==
|
|
||||||
|
|
||||||
yallist@^4.0.0:
|
yallist@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||||
|
|
Loading…
Reference in a new issue