Fix: unify code samples and json styling, stop using injectGlobal for prism

fixes #491
This commit is contained in:
Roman Hotsiy 2018-07-19 14:34:53 +03:00
parent 58bddc8811
commit 8c9304a719
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
9 changed files with 160 additions and 51 deletions

View File

@ -0,0 +1,124 @@
import styled, { extensionsHook } from '../styled-components';
export const PrismDiv = styled.div`
/**
* Based on prism-dark.css
*/
code[class*='language-'],
pre[class*='language-'] {
color: white;
background: none;
text-shadow: 0 -0.1em 0.2em black;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
@media print {
code[class*='language-'],
pre[class*='language-'] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*='language-'] {
padding: 1em;
margin: 0.5em 0;
overflow: auto;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: hsl(30, 20%, 50%);
}
.token.punctuation {
opacity: 0.7;
}
.namespace {
opacity: 0.7;
}
.token.property,
.token.tag,
.token.number,
.token.constant,
.token.symbol {
color: #4a8bb3;
}
.token.boolean {
color: firebrick;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #a0fbaa;
& + a,
& + a:visited {
color: #4ed2ba;
text-decoration: underline;
}
}
/* .property.token.string {
color: white;
} */
.token.operator,
.token.entity,
.token.url,
.token.variable {
color: hsl(40, 90%, 60%);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: hsl(350, 40%, 70%);
}
.token.regex,
.token.important {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
.token.deleted {
color: red;
}
${extensionsHook('Prism')};
`;

View File

@ -53,7 +53,7 @@ export const Badge = withProps<{ type: string }>(styled.span)`
padding: 0 5px;
margin: 0;
background-color: ${props => props.theme.colors[props.type].main};
color: ${props => props.theme.colors[props.type].dark};
color: ${props => props.theme.colors[props.type].contrastText};
font-size: ${props => props.theme.typography.code.fontSize};
vertical-align: text-top;
`;

View File

@ -3,6 +3,7 @@ import styled from '../../styled-components';
import { SampleControls } from '../../common-elements';
import { CopyButtonWrapper } from '../../common-elements/CopyButtonWrapper';
import { PrismDiv } from '../../common-elements/PrismDiv';
import { jsonToHTML } from '../../utils/jsonToHtml';
import { jsonStyles } from './style';
@ -31,9 +32,10 @@ class Json extends React.PureComponent<JsonProps> {
<span onClick={this.expandAll}> Expand all </span>
<span onClick={this.collapseAll}> Collapse all </span>
</SampleControls>
<div
<PrismDiv
className={this.props.className}
ref={node => (this.node = node!)}
// tslint:disable-next-line
innerRef={node => (this.node = node!)}
dangerouslySetInnerHTML={{ __html: jsonToHTML(this.props.data) }}
/>
</JsonViewerWrap>

View File

@ -12,27 +12,6 @@ export const jsonStyles = css`
word-wrap: break-word;
white-space: pre-wrap;
.type-null {
color: gray;
}
.type-boolean {
color: firebrick;
}
.type-number {
color: #4a8bb3;
}
.type-string {
color: #66b16e;
& + a,
& + a:visited {
color: #66b16e;
text-decoration: underline;
}
}
.callback-function {
color: gray;
}

View File

@ -1,5 +1,6 @@
import { headerCommonMixin, linkifyMixin } from '../../common-elements';
import styled, { css, extensionsHook, withProps } from '../../styled-components';
import { PrismDiv } from '../../common-elements/PrismDiv';
import { css, extensionsHook, withProps } from '../../styled-components';
export const linksCss = css`
a {
@ -16,7 +17,9 @@ export const linksCss = css`
}
`;
export const StyledMarkdownBlock = withProps<{ dense?: boolean; inline?: boolean }>(styled.div)`
export const StyledMarkdownBlock = withProps<{ dense?: boolean; inline?: boolean }>(
PrismDiv.extend,
)`
font-family: ${props => props.theme.typography.fontFamily};
font-weight: ${props => props.theme.typography.fontWeightRegular};

View File

@ -1,11 +1,11 @@
import * as React from 'react';
import styled from '../../styled-components';
import { highlight } from '../../utils';
import { SampleControls, SampleControlsWrap } from '../../common-elements';
import { CopyButtonWrapper } from '../../common-elements/CopyButtonWrapper';
import { PrismDiv } from '../../common-elements/PrismDiv';
const StyledPre = styled.pre`
const StyledPre = PrismDiv.withComponent('pre').extend`
font-family: ${props => props.theme.typography.code.fontFamily};
font-size: ${props => props.theme.typography.code.fontSize};
overflow-x: auto;

View File

@ -27,7 +27,7 @@ const defaultTheme: ThemeInterface = {
main: '#d4ad03',
light: ({ colors }) => lighten(colors.tonalOffset, colors.warning.main),
dark: ({ colors }) => darken(colors.tonalOffset, colors.warning.main),
contrastText: ({ colors }) => readableColor(colors.warning.main),
contrastText: '#ffffff',
},
error: {
main: '#e53935',

View File

@ -18,11 +18,6 @@ import 'prismjs/components/prism-ruby.js';
import 'prismjs/components/prism-scala.js';
import 'prismjs/components/prism-swift.js';
import { injectGlobal } from '../styled-components';
import prismStyles from 'prismjs/themes/prism-dark.css'; // dark theme
injectGlobal`${prismStyles}`;
const DEFAULT_LANG = 'clike';
/**

View File

@ -25,38 +25,42 @@ function decorateWithSpan(value, className) {
return '<span class="' + className + '">' + htmlEncode(value) + '</span>';
}
function punctuation(val) {
return '<span class="token punctuation">' + val + '</span>';
}
function valueToHTML(value) {
const valueType = typeof value;
let output = '';
if (value === undefined || value === null) {
output += decorateWithSpan('null', 'type-null');
output += decorateWithSpan('null', 'token keyword');
} else if (value && value.constructor === Array) {
level++;
output += arrayToHTML(value);
level--;
} else if (value && value.constructor === Date) {
output += decorateWithSpan('"' + value.toISOString() + '"', 'type-string');
output += decorateWithSpan('"' + value.toISOString() + '"', 'token string');
} else if (valueType === 'object') {
level++;
output += objectToHTML(value);
level--;
} else if (valueType === 'number') {
output += decorateWithSpan(value, 'type-number');
output += decorateWithSpan(value, 'token number');
} else if (valueType === 'string') {
if (/^(http|https):\/\/[^\s]+$/.test(value)) {
output +=
decorateWithSpan('"', 'type-string') +
decorateWithSpan('"', 'token string') +
'<a href="' +
value +
'">' +
htmlEncode(value) +
'</a>' +
decorateWithSpan('"', 'type-string');
decorateWithSpan('"', 'token string');
} else {
output += decorateWithSpan('"' + value + '"', 'type-string');
output += decorateWithSpan('"' + value + '"', 'token string');
}
} else if (valueType === 'boolean') {
output += decorateWithSpan(value, 'type-boolean');
output += decorateWithSpan(value, 'token boolean');
}
return output;
@ -64,8 +68,9 @@ function valueToHTML(value) {
function arrayToHTML(json) {
const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
let output =
'<div class="collapser"></div>[<span class="ellipsis"></span><ul class="array collapsible">';
let output = `<div class="collapser"></div>${punctuation(
'[',
)}<span class="ellipsis"></span><ul class="array collapsible">`;
let hasContents = false;
const length = json.length;
for (let i = 0; i < length; i++) {
@ -77,9 +82,9 @@ function arrayToHTML(json) {
}
output += '</div></li>';
}
output += '</ul>]';
output += `</ul>${punctuation(']')}`;
if (!hasContents) {
output = '[ ]';
output = punctuation('[ ]');
}
return output;
}
@ -88,23 +93,24 @@ function objectToHTML(json) {
const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
const keys = Object.keys(json);
const length = keys.length;
let output =
'<div class="collapser"></div>{<span class="ellipsis"></span><ul class="obj collapsible">';
let output = `<div class="collapser"></div>${punctuation(
'{',
)}<span class="ellipsis"></span><ul class="obj collapsible">`;
let hasContents = false;
for (let i = 0; i < length; i++) {
const key = keys[i];
hasContents = true;
output += '<li><div class="hoverable ' + collapsed + '">';
output += '<span class="property">"' + htmlEncode(key) + '"</span>: ';
output += '<span class="property token string">"' + htmlEncode(key) + '"</span>: ';
output += valueToHTML(json[key]);
if (i < length - 1) {
output += ',';
output += punctuation(',');
}
output += '</div></li>';
}
output += '</ul>}';
output += `</ul>${punctuation('}')}`;
if (!hasContents) {
output = '{ }';
output = punctuation('{ }');
}
return output;
}