mirror of
https://github.com/grafana/grafana.git
synced 2024-11-23 09:26:43 -06:00
Explore: Fix ANSI dim style being unreadable in dark mode (#41226)
* Explore: Fix ANSI dim style being unreadable in dark mode * use GrafanaTheme2 instead of opacity * tweak code and comment * fix existing tests and add new test for ANSI dim code * fix failing test
This commit is contained in:
parent
f30debf7ad
commit
32f2a75c44
@ -1,19 +1,18 @@
|
||||
import React from 'react';
|
||||
import { createTheme } from '@grafana/data';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { LogMessageAnsi } from './LogMessageAnsi';
|
||||
import React from 'react';
|
||||
import { UnThemedLogMessageAnsi as LogMessageAnsi } from './LogMessageAnsi';
|
||||
|
||||
describe('<LogMessageAnsi />', () => {
|
||||
it('renders string without ANSI codes', () => {
|
||||
const wrapper = shallow(<LogMessageAnsi value="Lorem ipsum" />);
|
||||
const wrapper = shallow(<LogMessageAnsi value="Lorem ipsum" theme={createTheme()} />);
|
||||
|
||||
expect(wrapper.find('span').exists()).toBe(false);
|
||||
expect(wrapper.text()).toBe('Lorem ipsum');
|
||||
});
|
||||
|
||||
it('renders string with ANSI codes', () => {
|
||||
const value = 'Lorem \u001B[31mipsum\u001B[0m et dolor';
|
||||
const wrapper = shallow(<LogMessageAnsi value={value} />);
|
||||
const wrapper = shallow(<LogMessageAnsi value={value} theme={createTheme()} />);
|
||||
|
||||
expect(wrapper.find('span')).toHaveLength(1);
|
||||
expect(wrapper.find('span').first().prop('style')).toMatchObject(
|
||||
@ -24,8 +23,8 @@ describe('<LogMessageAnsi />', () => {
|
||||
expect(wrapper.find('span').first().text()).toBe('ipsum');
|
||||
});
|
||||
it('renders string with ANSI codes with correctly converted css classnames', () => {
|
||||
const value = 'Lorem [1;32mIpsum';
|
||||
const wrapper = shallow(<LogMessageAnsi value={value} />);
|
||||
const value = 'Lorem \u001B[1;32mIpsum';
|
||||
const wrapper = shallow(<LogMessageAnsi value={value} theme={createTheme()} />);
|
||||
|
||||
expect(wrapper.find('span')).toHaveLength(1);
|
||||
expect(wrapper.find('span').first().prop('style')).toMatchObject(
|
||||
@ -34,4 +33,16 @@ describe('<LogMessageAnsi />', () => {
|
||||
})
|
||||
);
|
||||
});
|
||||
it('renders string with ANSI dim code with appropriate themed color', () => {
|
||||
const value = 'Lorem \u001B[1;2mIpsum';
|
||||
const theme = createTheme();
|
||||
const wrapper = shallow(<LogMessageAnsi value={value} theme={theme} />);
|
||||
|
||||
expect(wrapper.find('span')).toHaveLength(1);
|
||||
expect(wrapper.find('span').first().prop('style')).toMatchObject(
|
||||
expect.objectContaining({
|
||||
color: theme.colors.text.secondary,
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { findHighlightChunksInText } from '@grafana/data';
|
||||
import { findHighlightChunksInText, GrafanaTheme2 } from '@grafana/data';
|
||||
import ansicolor from 'ansicolor';
|
||||
import React, { PureComponent } from 'react';
|
||||
// @ts-ignore
|
||||
import Highlighter from 'react-highlight-words';
|
||||
import { withTheme2 } from '../../themes';
|
||||
import { Themeable2 } from '../../types';
|
||||
|
||||
interface Style {
|
||||
[key: string]: string;
|
||||
@ -13,13 +15,19 @@ interface ParsedChunk {
|
||||
text: string;
|
||||
}
|
||||
|
||||
function convertCSSToStyle(css: string): Style {
|
||||
return css.split(/;\s*/).reduce((accumulated, line) => {
|
||||
function convertCSSToStyle(theme: GrafanaTheme2, css: string): Style {
|
||||
return css.split(/;\s*/).reduce<Style>((accumulated, line) => {
|
||||
// The ansicolor package returns this color if the chunk has the ANSI dim
|
||||
// style (`\e[2m`), but it is nearly unreadable in the dark theme, so we use
|
||||
// GrafanaTheme2 instead to style it in a way that works across all themes.
|
||||
if (line === 'color:rgba(0,0,0,0.5)') {
|
||||
return { color: theme.colors.text.secondary };
|
||||
}
|
||||
|
||||
const match = line.match(/([^:\s]+)\s*:\s*(.+)/);
|
||||
|
||||
if (match && match[1] && match[2]) {
|
||||
const key = match[1].replace(/-([a-z])/g, (_, character) => character.toUpperCase());
|
||||
// @ts-ignore
|
||||
accumulated[key] = match[2];
|
||||
}
|
||||
|
||||
@ -27,7 +35,7 @@ function convertCSSToStyle(css: string): Style {
|
||||
}, {});
|
||||
}
|
||||
|
||||
interface Props {
|
||||
interface Props extends Themeable2 {
|
||||
value: string;
|
||||
highlight?: {
|
||||
searchWords: string[];
|
||||
@ -40,7 +48,7 @@ interface State {
|
||||
prevValue: string;
|
||||
}
|
||||
|
||||
export class LogMessageAnsi extends PureComponent<Props, State> {
|
||||
export class UnThemedLogMessageAnsi extends PureComponent<Props, State> {
|
||||
state: State = {
|
||||
chunks: [],
|
||||
prevValue: '',
|
||||
@ -57,7 +65,7 @@ export class LogMessageAnsi extends PureComponent<Props, State> {
|
||||
chunks: parsed.spans.map((span) => {
|
||||
return span.css
|
||||
? {
|
||||
style: convertCSSToStyle(span.css),
|
||||
style: convertCSSToStyle(props.theme, span.css),
|
||||
text: span.text,
|
||||
}
|
||||
: { text: span.text };
|
||||
@ -90,3 +98,6 @@ export class LogMessageAnsi extends PureComponent<Props, State> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const LogMessageAnsi = withTheme2(UnThemedLogMessageAnsi);
|
||||
LogMessageAnsi.displayName = 'LogMessageAnsi';
|
||||
|
Loading…
Reference in New Issue
Block a user