mirror of
https://github.com/Redocly/redoc.git
synced 2024-11-29 12:03:44 +03:00
Fix: unify code samples and json styling, stop using injectGlobal for prism
fixes #491
This commit is contained in:
parent
58bddc8811
commit
8c9304a719
124
src/common-elements/PrismDiv.tsx
Normal file
124
src/common-elements/PrismDiv.tsx
Normal 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')};
|
||||
`;
|
|
@ -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;
|
||||
`;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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';
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user