mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Showing colors in logs (#1419)
* Converting ansi values to colored html Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com> * Rewriting AnsiUp colors for search overlay Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
parent
6fd0bebdd6
commit
960bbe6813
@ -1,4 +1,7 @@
|
|||||||
.PodLogs {
|
.PodLogs {
|
||||||
|
--overlay-bg: #8cc474b8;
|
||||||
|
--overlay-active-bg: orange;
|
||||||
|
|
||||||
.logs {
|
.logs {
|
||||||
@include custom-scrollbar;
|
@include custom-scrollbar;
|
||||||
|
|
||||||
@ -11,14 +14,6 @@
|
|||||||
background: $logsBackground;
|
background: $logsBackground;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
||||||
.find-overlay {
|
|
||||||
position: absolute;
|
|
||||||
border-radius: 2px;
|
|
||||||
background-color: #8cc474;
|
|
||||||
margin-top: 4px;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.VirtualList {
|
.VirtualList {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
@ -29,19 +24,30 @@
|
|||||||
font-family: $font-monospace;
|
font-family: $font-monospace;
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
-webkit-font-smoothing: auto; // Better readability on non-retina screens
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: $logRowHoverBackground;
|
background: $logRowHoverBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
|
-webkit-font-smoothing: auto; // Better readability on non-retina screens
|
||||||
|
}
|
||||||
|
|
||||||
|
span.overlay {
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
background-color: #8cc474b8;
|
|
||||||
-webkit-font-smoothing: auto;
|
-webkit-font-smoothing: auto;
|
||||||
|
background-color: var(--overlay-bg);
|
||||||
|
|
||||||
|
span {
|
||||||
|
background-color: var(--overlay-bg)!important; // Rewriting inline styles from AnsiUp library
|
||||||
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background-color: orange;
|
background-color: var(--overlay-active-bg);
|
||||||
|
|
||||||
|
span {
|
||||||
|
background-color: var(--overlay-active-bg)!important; // Rewriting inline styles from AnsiUp library
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,25 +55,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.new-logs-sep {
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
height: 0;
|
|
||||||
border-top: 1px solid $primary;
|
|
||||||
margin: $margin * 2 0;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
content: 'new';
|
|
||||||
background: $primary;
|
|
||||||
color: white;
|
|
||||||
padding: $padding / 3;
|
|
||||||
border-radius: $radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.jump-to-bottom {
|
.jump-to-bottom {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 30px;
|
right: 30px;
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import "./pod-logs.scss";
|
import "./pod-logs.scss";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import AnsiUp from 'ansi_up';
|
||||||
|
import DOMPurify from "dompurify"
|
||||||
import { Trans } from "@lingui/macro";
|
import { Trans } from "@lingui/macro";
|
||||||
import { action, computed, observable, reaction } from "mobx";
|
import { action, computed, observable, reaction } from "mobx";
|
||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { disposeOnUnmount, observer } from "mobx-react";
|
||||||
@ -33,6 +35,7 @@ export class PodLogs extends React.Component<Props> {
|
|||||||
private logsElement = React.createRef<HTMLDivElement>(); // A reference for outer container in VirtualList
|
private logsElement = React.createRef<HTMLDivElement>(); // A reference for outer container in VirtualList
|
||||||
private virtualListRef = React.createRef<VirtualList>(); // A reference for VirtualList component
|
private virtualListRef = React.createRef<VirtualList>(); // A reference for VirtualList component
|
||||||
private lastLineIsShown = true; // used for proper auto-scroll content after refresh
|
private lastLineIsShown = true; // used for proper auto-scroll content after refresh
|
||||||
|
private colorConverter = new AnsiUp();
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
disposeOnUnmount(this, [
|
disposeOnUnmount(this, [
|
||||||
@ -185,6 +188,7 @@ export class PodLogs extends React.Component<Props> {
|
|||||||
const { searchQuery, isActiveOverlay } = searchStore;
|
const { searchQuery, isActiveOverlay } = searchStore;
|
||||||
const item = this.logs[rowIndex];
|
const item = this.logs[rowIndex];
|
||||||
const contents: React.ReactElement[] = [];
|
const contents: React.ReactElement[] = [];
|
||||||
|
const ansiToHtml = (ansi: string) => DOMPurify.sanitize(this.colorConverter.ansi_to_html(ansi));
|
||||||
if (searchQuery) { // If search is enabled, replace keyword with backgrounded <span>
|
if (searchQuery) { // If search is enabled, replace keyword with backgrounded <span>
|
||||||
// Case-insensitive search (lowercasing query and keywords in line)
|
// Case-insensitive search (lowercasing query and keywords in line)
|
||||||
const regex = new RegExp(searchStore.escapeRegex(searchQuery), "gi");
|
const regex = new RegExp(searchStore.escapeRegex(searchQuery), "gi");
|
||||||
@ -195,19 +199,26 @@ export class PodLogs extends React.Component<Props> {
|
|||||||
pieces.forEach((piece, index) => {
|
pieces.forEach((piece, index) => {
|
||||||
const active = isActiveOverlay(rowIndex, index);
|
const active = isActiveOverlay(rowIndex, index);
|
||||||
const lastItem = index === pieces.length - 1;
|
const lastItem = index === pieces.length - 1;
|
||||||
|
const overlayValue = matches.next().value;
|
||||||
const overlay = !lastItem ?
|
const overlay = !lastItem ?
|
||||||
<span className={cssNames({ active })}>{matches.next().value}</span> :
|
<span
|
||||||
|
className={cssNames("overlay", { active })}
|
||||||
|
dangerouslySetInnerHTML={{ __html: ansiToHtml(overlayValue) }}
|
||||||
|
/> :
|
||||||
null
|
null
|
||||||
contents.push(
|
contents.push(
|
||||||
<React.Fragment key={piece + index}>
|
<React.Fragment key={piece + index}>
|
||||||
{piece}{overlay}
|
<span dangerouslySetInnerHTML={{ __html: ansiToHtml(piece) }} />
|
||||||
|
{overlay}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className={cssNames("LogRow")}>
|
<div className={cssNames("LogRow")}>
|
||||||
{contents.length > 1 ? contents : item}
|
{contents.length > 1 ? contents : (
|
||||||
|
<span dangerouslySetInnerHTML={{ __html: ansiToHtml(item) }} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user