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:
@@ -18,7 +18,6 @@
|
||||
"dependencies": {
|
||||
"@0xproject/react-shared": "^1.0.15",
|
||||
"highlight.js": "^9.13.1",
|
||||
"highlighter": "^0.1.0",
|
||||
"less": "^2.7.2",
|
||||
"polished": "^1.9.2",
|
||||
"react": "^16.5.2",
|
||||
|
||||
@@ -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) ? (
|
||||
|
||||
@@ -43,6 +43,7 @@ const IntroLead = styled(Lead)`
|
||||
`;
|
||||
const IntroAside = styled.div`
|
||||
max-width: 32.5rem;
|
||||
position: relative;
|
||||
|
||||
${media.small`
|
||||
margin-left: -30px;
|
||||
|
||||
@@ -1,8 +1,47 @@
|
||||
const highlight = require('highlight.js/lib/highlight');
|
||||
const hljs = require('highlight.js/lib/highlight');
|
||||
const javascript = require('highlight.js/lib/languages/javascript');
|
||||
const json = require('highlight.js/lib/languages/json');
|
||||
|
||||
highlight.registerLanguage('javascript', javascript);
|
||||
highlight.registerLanguage('json', json);
|
||||
hljs.registerLanguage('javascript', javascript);
|
||||
|
||||
interface PatchInterface {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
var PATCH_TYPES: PatchInterface = {
|
||||
'+': 'addition',
|
||||
'-': 'deletion',
|
||||
'!': 'change',
|
||||
};
|
||||
|
||||
function diffHighlight(language: string, code: any, gutter: any) {
|
||||
return code
|
||||
.split(/\r?\n/g)
|
||||
.map((line: string, index: number) => {
|
||||
var type;
|
||||
if (/^-{3} [^-]+ -{4}$|^\*{3} [^*]+ \*{4}$|^@@ [^@]+ @@$/.test(line)) {
|
||||
type = 'chunk';
|
||||
} else if (/^Index: |^[+\-*]{3}|^[*=]{5,}$/.test(line)) {
|
||||
type = 'header';
|
||||
} else {
|
||||
type = PATCH_TYPES[line[0] as string] || 'null';
|
||||
line = line.replace(/^[+\-! ]/, '');
|
||||
}
|
||||
|
||||
const g = gutter[index];
|
||||
|
||||
return `<span data-test="${g !== undefined ? g + 'x' : ''}" class="line-${type}">${
|
||||
hljs.highlight(language, line).value
|
||||
}</span>`;
|
||||
})
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
function highlight(language: string, code: string, diff: boolean, gutter: any) {
|
||||
if (diff) {
|
||||
return diffHighlight(language, code, gutter);
|
||||
}
|
||||
|
||||
return hljs.highlight(language, code).value;
|
||||
}
|
||||
|
||||
export default highlight;
|
||||
|
||||
@@ -22,19 +22,25 @@ function Cov() {
|
||||
coverage.
|
||||
</IntroLead>
|
||||
<IntroAside>
|
||||
<Code language="js.diff">
|
||||
<Code
|
||||
language="javascript"
|
||||
diff
|
||||
gutterLength={2}
|
||||
gutter={[4, undefined, 4, 4, 4, undefined, 4, 2, 2, 2]}
|
||||
>
|
||||
{`+function executeTransaction(uint transactionId)
|
||||
public
|
||||
+notExecuted(transactionId)
|
||||
+pastTimeLock(transactionId)
|
||||
public
|
||||
+ notExecuted(transactionId)
|
||||
+ fullyConfirmed(transactionId)
|
||||
+ pastTimeLock(transactionId)
|
||||
{
|
||||
+Transaction storage tx = transactions[transactionId]
|
||||
+tx.executed = true
|
||||
+if (tx.destination.call.value(tx.value)(tx.data))
|
||||
+Execution(transactionId)
|
||||
else {
|
||||
-ExecutionFailure(transactionId)
|
||||
|
||||
+ Transaction storage tx = transactions[transactionId]
|
||||
+ tx.executed = true
|
||||
+ if (tx.destination.call.value(tx.value)(tx.data))
|
||||
+ Execution(transactionId)
|
||||
else {
|
||||
- ExecutionFailure(transactionId)
|
||||
- tx.executed = false
|
||||
}
|
||||
}`}
|
||||
</Code>
|
||||
@@ -69,7 +75,7 @@ else {
|
||||
|
||||
<Tabs>
|
||||
<TabBlock title="Sol-compiler">
|
||||
<Code language="js">
|
||||
<Code language="javascript">
|
||||
{`import { SolCompilerArtifactAdapter } from '@0x/sol-trace';
|
||||
|
||||
// Both artifactsDir and contractsDir are optional and will be fetched from compiler.json if not passed in
|
||||
|
||||
@@ -9,18 +9,35 @@ import { Tabs, TabBlock } from 'ts/components/Tabs';
|
||||
import Code from 'ts/components/Code';
|
||||
import InlineCode from 'ts/components/InlineCode';
|
||||
import { List, ListItem } from 'ts/components/List';
|
||||
import Intro from 'ts/components/Intro';
|
||||
import Breakout from 'ts/components/Breakout';
|
||||
import { Intro, IntroLead, IntroAside } from 'ts/components/Intro';
|
||||
|
||||
function Profiler() {
|
||||
return (
|
||||
<Base context={context}>
|
||||
<Intro title="ra">
|
||||
<p>
|
||||
<Intro title="Headline">
|
||||
<IntroLead>
|
||||
Sol-profiler gathers line-by-line gas usage for any transaction submitted through your provider.
|
||||
This will help you find unexpected inefficiencies in parts of your smart contract, and take a
|
||||
data-driven approach to optimizing it.
|
||||
</p>
|
||||
</IntroLead>
|
||||
<IntroAside>
|
||||
<Code language="javascript" diff gutterLength={6} gutter={[15, 15, undefined, 21747, 20303, 1435]}>
|
||||
{`+function() public payable {
|
||||
+ deposit();
|
||||
}
|
||||
+function deposit() public payabble {
|
||||
+ balanceOf[msg.sender] += msg.value;
|
||||
+ Deposit(msg.sender, msg.value);
|
||||
}
|
||||
-function withdraw(uint wad) public {
|
||||
- require(balanceOf[msg.sender] >= wad);
|
||||
- balanceOf[msg.sender] -= wad;
|
||||
- msg.sender.transfer(wad);
|
||||
- Withdrawal(msg.sender, wad);
|
||||
}`}
|
||||
</Code>
|
||||
</IntroAside>
|
||||
</Intro>
|
||||
<Content>
|
||||
<ContentBlock main title="Get started" />
|
||||
|
||||
@@ -6,6 +6,7 @@ const colors = {
|
||||
lightGray: '#F1F4F5',
|
||||
gray: '#F1F2F7',
|
||||
darkGray: '#E9ECED',
|
||||
darkestGray: '#E2E5E6',
|
||||
blueGray: '#ECEFF9',
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user