Extract code snippet into stand alone component (#1181)

This commit is contained in:
Charis Kyriakou 2022-03-04 08:06:19 +00:00 коммит произвёл GitHub
Родитель 5ad754a3a2
Коммит b510b85ca0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
2 изменённых файлов: 233 добавлений и 164 удалений

Просмотреть файл

@ -1,171 +1,16 @@
import * as React from 'react';
import styled from 'styled-components';
import { Box, Link } from '@primer/react';
import { AnalysisAlert, HighlightedRegion, ResultSeverity } from '../shared/analysis-result';
const borderColor = 'var(--vscode-editor-snippetFinalTabstopHighlightBorder)';
const warningColor = '#966C23';
const highlightColor = '#534425';
const getSeverityColor = (severity: ResultSeverity) => {
switch (severity) {
case 'Recommendation':
return 'blue';
case 'Warning':
return warningColor;
case 'Error':
return 'red';
}
};
const Container = styled.div`
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
`;
const TitleContainer = styled.div`
border: 0.1em solid ${borderColor};
border-top-left-radius: 0.2em;
border-top-right-radius: 0.2em;
padding: 0.5em;
`;
const CodeContainer = styled.div`
font-size: x-small;
border-left: 0.1em solid ${borderColor};
border-right: 0.1em solid ${borderColor};
border-bottom: 0.1em solid ${borderColor};
border-bottom-left-radius: 0.2em;
border-bottom-right-radius: 0.2em;
padding-top: 1em;
padding-bottom: 1em;
`;
const MessageText = styled.span<{ severity: ResultSeverity }>`
font-size: x-small;
color: ${props => getSeverityColor(props.severity)};
padding-left: 0.5em;
`;
const MessageContainer = styled.div`
padding-top: 0.5em;
padding-bottom: 0.5em;
`;
const Message = ({ alert, currentLineNumber }: {
alert: AnalysisAlert,
currentLineNumber: number
}) => {
if (alert.highlightedRegion.startLine !== currentLineNumber) {
return <></>;
}
return <MessageContainer>
<Box
borderColor="border.default"
borderWidth={1}
borderStyle="solid"
borderLeftColor={getSeverityColor(alert.severity)}
borderLeftWidth={3}
paddingTop="1em"
paddingBottom="1em">
<MessageText severity={alert.severity}>{alert.message}</MessageText>
</Box>
</MessageContainer>;
};
const replaceSpaceChar = (text: string) => text.replaceAll(' ', '\u00a0');
const PlainLine = ({ text }: { text: string }) => {
return <span>{replaceSpaceChar(text)}</span>;
};
const HighlightedLine = ({ text }: { text: string }) => {
return <span style={{ backgroundColor: highlightColor }}>{replaceSpaceChar(text)}</span>;
};
const shouldHighlightLine = (lineNumber: number, highlightedRegion: HighlightedRegion) => {
if (lineNumber < highlightedRegion.startLine) {
return false;
}
if (highlightedRegion.endLine) {
return lineNumber <= highlightedRegion.endLine;
}
return true;
};
const CodeLine = ({
line,
lineNumber,
highlightedRegion
}: {
line: string,
lineNumber: number,
highlightedRegion: HighlightedRegion
}) => {
if (!shouldHighlightLine(lineNumber, highlightedRegion)) {
return <PlainLine text={line} />;
}
const section1 = line.substring(0, highlightedRegion.startColumn - 1);
const section2 = line.substring(highlightedRegion.startColumn - 1, highlightedRegion.endColumn - 1);
const section3 = line.substring(highlightedRegion.endColumn - 1, line.length);
return (
<>
<PlainLine text={section1} />
<HighlightedLine text={section2} />
<PlainLine text={section3} />
</>
);
};
import { AnalysisAlert } from '../shared/analysis-result';
import FileCodeSnippet from './FileCodeSnippet';
const AnalysisAlertResult = ({ alert }: { alert: AnalysisAlert }) => {
const code = alert.codeSnippet.text
.split('\n')
.filter(line => line.replace('\n', '').length > 0);
const startingLine = alert.codeSnippet.startLine;
return (
<Container>
<TitleContainer>
<Link>{alert.filePath}</Link>
</TitleContainer>
<CodeContainer>
{code.map((line, index) => (
<div key={index}>
<Message alert={alert} currentLineNumber={startingLine + index} />
<Box display="flex">
<Box
p={2}
borderStyle="none"
paddingTop="0.01em"
paddingLeft="0.5em"
paddingRight="0.5em"
paddingBottom="0.2em">
{startingLine + index}
</Box>
<Box
flexGrow={1}
p={2}
borderStyle="none"
paddingTop="0.01em"
paddingLeft="1.5em"
paddingRight="0.5em"
paddingBottom="0.2em">
<CodeLine
line={line}
lineNumber={startingLine + index}
highlightedRegion={alert.highlightedRegion} />
</Box>
</Box>
</div>
))}
</CodeContainer>
</Container>
);
return <FileCodeSnippet
filePath={alert.filePath}
codeSnippet={alert.codeSnippet}
highlightedRegion={alert.highlightedRegion}
severity={alert.severity}
message={alert.message}
/>;
};
export default AnalysisAlertResult;

Просмотреть файл

@ -0,0 +1,224 @@
import * as React from 'react';
import styled from 'styled-components';
import { CodeSnippet, HighlightedRegion, ResultSeverity } from '../shared/analysis-result';
import { Box, Link } from '@primer/react';
import VerticalSpace from './VerticalSpace';
const borderColor = 'var(--vscode-editor-snippetFinalTabstopHighlightBorder)';
const warningColor = '#966C23';
const highlightColor = '#534425';
const getSeverityColor = (severity: ResultSeverity) => {
switch (severity) {
case 'Recommendation':
return 'blue';
case 'Warning':
return warningColor;
case 'Error':
return 'red';
}
};
const replaceSpaceChar = (text: string) => text.replaceAll(' ', '\u00a0');
const shouldHighlightLine = (lineNumber: number, highlightedRegion: HighlightedRegion) => {
if (lineNumber < highlightedRegion.startLine) {
return false;
}
if (highlightedRegion.endLine == undefined) {
return lineNumber == highlightedRegion.startLine;
}
return lineNumber <= highlightedRegion.endLine;
};
const Container = styled.div`
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
font-size: x-small;
width: 55em;
`;
const TitleContainer = styled.div`
border: 0.1em solid ${borderColor};
border-top-left-radius: 0.2em;
border-top-right-radius: 0.2em;
padding: 0.5em;
`;
const CodeContainer = styled.div`
border-left: 0.1em solid ${borderColor};
border-right: 0.1em solid ${borderColor};
border-bottom: 0.1em solid ${borderColor};
border-bottom-left-radius: 0.2em;
border-bottom-right-radius: 0.2em;
padding-top: 1em;
padding-bottom: 1em;
`;
const MessageText = styled.div`
font-size: x-small;
padding-left: 0.5em;
`;
const MessageContainer = styled.div`
padding-top: 0.5em;
padding-bottom: 0.5em;
`;
const PlainLine = ({ text }: { text: string }) => {
return <span>{replaceSpaceChar(text)}</span>;
};
const HighlightedLine = ({ text }: { text: string }) => {
return <span style={{ backgroundColor: highlightColor }}>{replaceSpaceChar(text)}</span>;
};
const Message = ({
messageText,
currentLineNumber,
highlightedRegion,
borderColor,
children
}: {
messageText: string,
currentLineNumber: number,
highlightedRegion: HighlightedRegion,
borderColor: string,
children: React.ReactNode
}) => {
if (highlightedRegion.startLine !== currentLineNumber) {
return <></>;
}
return <MessageContainer>
<Box
borderColor="border.default"
borderWidth={1}
borderStyle="solid"
borderLeftColor={borderColor}
borderLeftWidth={3}
paddingTop="1em"
paddingBottom="1em">
<MessageText>
{messageText}
{children && <>
<VerticalSpace size={2} />
{children}
</>
}
</MessageText>
</Box>
</MessageContainer>;
};
const CodeLine = ({
line,
lineNumber,
highlightedRegion
}: {
line: string,
lineNumber: number,
highlightedRegion: HighlightedRegion
}) => {
if (!shouldHighlightLine(lineNumber, highlightedRegion)) {
return <PlainLine text={line} />;
}
const isSingleLineHighlight = highlightedRegion.endLine === undefined;
const isFirstHighlightedLine = lineNumber === highlightedRegion.startLine;
const isLastHighlightedLine = lineNumber === highlightedRegion.endLine;
const highlightStartColumn = isSingleLineHighlight
? highlightedRegion.startColumn
: isFirstHighlightedLine
? highlightedRegion.startColumn
: 0;
const highlightEndColumn = isSingleLineHighlight
? highlightedRegion.endColumn
: isLastHighlightedLine
? highlightedRegion.endColumn
: line.length;
const section1 = line.substring(0, highlightStartColumn - 1);
const section2 = line.substring(highlightStartColumn - 1, highlightEndColumn - 1);
const section3 = line.substring(highlightEndColumn - 1, line.length);
return (
<>
<PlainLine text={section1} />
<HighlightedLine text={section2} />
<PlainLine text={section3} />
</>
);
};
const FileCodeSnippet = ({
filePath,
codeSnippet,
highlightedRegion,
severity,
message,
messageChildren,
}: {
filePath: string,
codeSnippet: CodeSnippet,
highlightedRegion: HighlightedRegion,
severity?: ResultSeverity,
message?: string,
messageChildren?: React.ReactNode,
}) => {
const code = codeSnippet.text.split('\n');
const startingLine = codeSnippet.startLine;
return (
<Container>
<TitleContainer>
<Link>{filePath}</Link>
</TitleContainer>
<CodeContainer>
{code.map((line, index) => (
<div key={index}>
{message && severity && <Message
messageText={message}
currentLineNumber={startingLine + index}
highlightedRegion={highlightedRegion}
borderColor={getSeverityColor(severity)}>
{messageChildren}
</Message>}
<Box display="flex">
<Box
p={2}
borderStyle="none"
paddingTop="0.01em"
paddingLeft="0.5em"
paddingRight="0.5em"
paddingBottom="0.2em">
{startingLine + index}
</Box>
<Box
flexGrow={1}
p={2}
borderStyle="none"
paddingTop="0.01em"
paddingLeft="1.5em"
paddingRight="0.5em"
paddingBottom="0.2em">
<CodeLine
line={line}
lineNumber={startingLine + index}
highlightedRegion={highlightedRegion} />
</Box>
</Box>
</div>
))}
</CodeContainer>
</Container>
);
};
export default FileCodeSnippet;