core-components: refactor LogViewer LogLine into pieces of logic

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-12-05 12:14:42 +01:00
committed by blam
parent 439833d300
commit 1faae751b6
@@ -15,12 +15,12 @@
*/
import React from 'react';
import { AnsiLine, ChunkModifiers } from './AnsiProcessor';
import { AnsiChunk, AnsiLine, ChunkModifiers } from './AnsiProcessor';
import startCase from 'lodash/startCase';
import clsx from 'clsx';
import { useStyles } from './useStyles';
import { useStyles } from './styles';
function getModifierClasses(
export function getModifierClasses(
classes: ReturnType<typeof useStyles>,
modifiers: ChunkModifiers,
) {
@@ -49,41 +49,45 @@ function getModifierClasses(
return classNames.length > 0 ? classNames.join(' ') : undefined;
}
export interface LogLineProps {
line: AnsiLine;
classes: ReturnType<typeof useStyles>;
searchText: string;
export function findSearchResults(text: string, searchText: string) {
if (!searchText || !text.includes(searchText)) {
return undefined;
}
const searchResults = new Array<{ start: number; end: number }>();
let offset = 0;
for (;;) {
const start = text.indexOf(searchText, offset);
if (start === -1) {
break;
}
const end = start + searchText.length;
searchResults.push({ start, end });
offset = end;
}
return searchResults;
}
export function LogLine({ line, classes, searchText }: LogLineProps) {
let searchResults: Array<{ start: number; end: number }> | undefined =
undefined;
if (searchText && line.text.includes(searchText)) {
searchResults = [];
let offset = 0;
for (;;) {
const start = line.text.indexOf(searchText, offset);
if (start === -1) {
break;
}
const end = start + searchText.length;
searchResults.push({ start, end });
offset = end;
}
export interface HighlightAnsiChunk extends AnsiChunk {
highlight?: boolean;
}
export function calculateHighlightedChunks(
line: AnsiLine,
searchText: string,
): HighlightAnsiChunk[] {
const results = findSearchResults(line.text, searchText);
if (!results) {
return line.chunks;
}
const output = new Array<JSX.Element>(line.chunks.length);
const chunks = new Array<HighlightAnsiChunk>();
let key = 0;
let chunkOffset = 0;
let nextResult = searchResults?.shift();
for (const { text, modifiers } of line.chunks) {
let nextResult = results.shift();
for (const chunk of line.chunks) {
const { text, modifiers } = chunk;
if (!nextResult || chunkOffset + text.length < nextResult.start) {
output.push(
<span key={key++} className={getModifierClasses(classes, modifiers)}>
{text}
</span>,
);
chunks.push(chunk);
chunkOffset += text.length;
continue;
}
@@ -99,42 +103,49 @@ export function LogLine({ line, classes, searchText }: LogLineProps) {
const match = text.slice(localStart, localEnd);
if (beforeMatch) {
output.push(
<span key={key++} className={getModifierClasses(classes, modifiers)}>
{beforeMatch}
</span>,
);
chunks.push({ text: beforeMatch, modifiers });
}
output.push(
<span
key={key++}
className={clsx(
getModifierClasses(classes, modifiers),
classes.textHighlight,
)}
>
{match}
</span>,
);
chunks.push({ text: match, modifiers, highlight: true });
localOffset = localStart + match.length;
if (match.length === searchText.length) {
nextResult = searchResults?.shift();
nextResult = results.shift();
} else {
break;
}
}
if (localOffset < text.length) {
output.push(
<span key={key++} className={getModifierClasses(classes, modifiers)}>
{text.slice(localOffset)}
</span>,
);
chunks.push({ text: text.slice(localOffset), modifiers });
}
chunkOffset += text.length;
}
return <>{output}</>;
return chunks;
}
export interface LogLineProps {
line: AnsiLine;
classes: ReturnType<typeof useStyles>;
searchText: string;
}
export function LogLine({ line, classes, searchText }: LogLineProps) {
const chunks = calculateHighlightedChunks(line, searchText);
const elements = chunks.map(({ text, modifiers, highlight }, index) => (
<span
key={index}
className={clsx(
getModifierClasses(classes, modifiers),
highlight && classes.textHighlight,
)}
>
{text}
</span>
));
return <>{elements}</>;
}