Feature/syntaxhighlighting (#9)
* wip code highlighting of lines * Implements gutter component * WIP: Profiler with gutter * cleaned up highlight code * Removes before content for gutter styling * Styles gutter * Add correct Profiler code content * Adds color variable for gutter gray * refactor code component width gutter and diffing
This commit is contained in:
@@ -4,12 +4,13 @@ import styled from 'styled-components';
|
||||
import { colors } from 'ts/variables';
|
||||
import BaseButton from './Button';
|
||||
|
||||
var highlight = require('highlighter')();
|
||||
|
||||
interface CodeProps {
|
||||
children: React.ReactNode;
|
||||
language?: string;
|
||||
light?: boolean;
|
||||
diff?: boolean;
|
||||
gutter?: Array<number>;
|
||||
gutterLength?: number;
|
||||
}
|
||||
|
||||
interface CodeState {
|
||||
@@ -30,37 +31,73 @@ const Button = styled(BaseButton)`
|
||||
|
||||
const Base =
|
||||
styled.div <
|
||||
CodeProps >
|
||||
`
|
||||
CodeProps >
|
||||
`
|
||||
color: ${props => (props.language === undefined ? colors.white : 'inherit')};
|
||||
background-color: ${props =>
|
||||
props.light ? 'rgba(255,255,255,.15)' : props.language === undefined ? colors.black : colors.lightGray};
|
||||
props.light ? 'rgba(255,255,255,.15)' : props.language === undefined ? colors.black : '#F1F4F5'};
|
||||
white-space: ${props => (props.language === undefined ? 'nowrap' : '')};
|
||||
position: relative;
|
||||
|
||||
${props =>
|
||||
props.diff
|
||||
? `
|
||||
background-color: #E9ECED;
|
||||
display: flex;
|
||||
padding-top: 1.5rem;
|
||||
padding-bottom: 1.5rem;
|
||||
`
|
||||
: `
|
||||
padding: 1.5rem;
|
||||
`}
|
||||
|
||||
overflow-y: scroll;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
&:hover ${Button} {
|
||||
opacity: 1;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledCode = styled.code`
|
||||
padding-top: 1.5rem;
|
||||
padding-bottom: 1.5rem;
|
||||
display: block;
|
||||
overflow-y: scroll;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
|
||||
.diff-addition {
|
||||
background-color: #d2e9e0;
|
||||
padding: 0.3125rem;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
const StyledCodeDiff =
|
||||
styled.code <
|
||||
any >
|
||||
`
|
||||
::before {
|
||||
content: '';
|
||||
width: calc(.75rem + ${props => props.gutterLength}ch);
|
||||
background-color: #e2e5e6;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.diff-deletion {
|
||||
background-color: #ebdcdc;
|
||||
padding: 0.3125rem;
|
||||
|
||||
[class^='line-'] {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding-right: 1.5rem;
|
||||
padding-left: calc(2.25rem + ${props => props.gutterLength}ch);
|
||||
::before {
|
||||
content: attr(data-test);
|
||||
font-size: 0.875rem;
|
||||
width: ${props => props.gutterLength};
|
||||
padding-left: .375rem;
|
||||
padding-right: .375rem;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.line-addition {
|
||||
background-color: rgba(0, 202, 105, 0.1);
|
||||
}
|
||||
.line-deletion {
|
||||
background-color: rgba(255, 0, 0, 0.07);
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -88,13 +125,16 @@ class Code extends React.Component<CodeProps, CodeState> {
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const { language, children } = this.props;
|
||||
const { language, children, diff, gutter } = this.props;
|
||||
|
||||
const code = children as string;
|
||||
|
||||
if (language !== undefined) {
|
||||
const { default: hljs } = await System.import(/* webpackChunkName: 'highlightjs' */ 'ts/highlight');
|
||||
const { default: highlight } = await System.import(/* webpackChunkName: 'highlightjs' */ 'ts/highlight');
|
||||
|
||||
const hlCode = hljs(children as string, language);
|
||||
this.setState({ hlCode });
|
||||
this.setState({
|
||||
hlCode: highlight(language, code, diff, gutter),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,16 +155,20 @@ class Code extends React.Component<CodeProps, CodeState> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { language, light, children } = this.props;
|
||||
const { language, light, diff, children, gutterLength } = this.props;
|
||||
const { hlCode } = this.state;
|
||||
|
||||
const Code = diff ? StyledCodeDiff : 'code';
|
||||
|
||||
return (
|
||||
<Base language={language} light={light}>
|
||||
<Base language={language} diff={diff} light={light}>
|
||||
<StyledPre>
|
||||
{this.state.hlCode !== undefined ? (
|
||||
<StyledCode dangerouslySetInnerHTML={{ __html: this.state.hlCode }} />
|
||||
) : (
|
||||
<StyledCode>{this.props.children}</StyledCode>
|
||||
)}
|
||||
<Code
|
||||
gutterLength={gutterLength}
|
||||
dangerouslySetInnerHTML={hlCode ? { __html: this.state.hlCode } : null}
|
||||
>
|
||||
{hlCode === undefined ? children : null}
|
||||
</Code>
|
||||
</StyledPre>
|
||||
{navigator.userAgent !== 'ReactSnap' ? <Button onClick={this.handleCopy}>Copy</Button> : null}
|
||||
{!('clipboard' in navigator) ? (
|
||||
|
Reference in New Issue
Block a user