mirror of
https://github.com/Redocly/redoc.git
synced 2025-02-16 18:00:33 +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;
|
padding: 0 5px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: ${props => props.theme.colors[props.type].main};
|
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};
|
font-size: ${props => props.theme.typography.code.fontSize};
|
||||||
vertical-align: text-top;
|
vertical-align: text-top;
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -3,6 +3,7 @@ import styled from '../../styled-components';
|
||||||
|
|
||||||
import { SampleControls } from '../../common-elements';
|
import { SampleControls } from '../../common-elements';
|
||||||
import { CopyButtonWrapper } from '../../common-elements/CopyButtonWrapper';
|
import { CopyButtonWrapper } from '../../common-elements/CopyButtonWrapper';
|
||||||
|
import { PrismDiv } from '../../common-elements/PrismDiv';
|
||||||
import { jsonToHTML } from '../../utils/jsonToHtml';
|
import { jsonToHTML } from '../../utils/jsonToHtml';
|
||||||
import { jsonStyles } from './style';
|
import { jsonStyles } from './style';
|
||||||
|
|
||||||
|
@ -31,9 +32,10 @@ class Json extends React.PureComponent<JsonProps> {
|
||||||
<span onClick={this.expandAll}> Expand all </span>
|
<span onClick={this.expandAll}> Expand all </span>
|
||||||
<span onClick={this.collapseAll}> Collapse all </span>
|
<span onClick={this.collapseAll}> Collapse all </span>
|
||||||
</SampleControls>
|
</SampleControls>
|
||||||
<div
|
<PrismDiv
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
ref={node => (this.node = node!)}
|
// tslint:disable-next-line
|
||||||
|
innerRef={node => (this.node = node!)}
|
||||||
dangerouslySetInnerHTML={{ __html: jsonToHTML(this.props.data) }}
|
dangerouslySetInnerHTML={{ __html: jsonToHTML(this.props.data) }}
|
||||||
/>
|
/>
|
||||||
</JsonViewerWrap>
|
</JsonViewerWrap>
|
||||||
|
|
|
@ -12,27 +12,6 @@ export const jsonStyles = css`
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
white-space: pre-wrap;
|
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 {
|
.callback-function {
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { headerCommonMixin, linkifyMixin } from '../../common-elements';
|
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`
|
export const linksCss = css`
|
||||||
a {
|
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-family: ${props => props.theme.typography.fontFamily};
|
||||||
font-weight: ${props => props.theme.typography.fontWeightRegular};
|
font-weight: ${props => props.theme.typography.fontWeightRegular};
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import styled from '../../styled-components';
|
|
||||||
import { highlight } from '../../utils';
|
import { highlight } from '../../utils';
|
||||||
|
|
||||||
import { SampleControls, SampleControlsWrap } from '../../common-elements';
|
import { SampleControls, SampleControlsWrap } from '../../common-elements';
|
||||||
import { CopyButtonWrapper } from '../../common-elements/CopyButtonWrapper';
|
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-family: ${props => props.theme.typography.code.fontFamily};
|
||||||
font-size: ${props => props.theme.typography.code.fontSize};
|
font-size: ${props => props.theme.typography.code.fontSize};
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
|
|
@ -27,7 +27,7 @@ const defaultTheme: ThemeInterface = {
|
||||||
main: '#d4ad03',
|
main: '#d4ad03',
|
||||||
light: ({ colors }) => lighten(colors.tonalOffset, colors.warning.main),
|
light: ({ colors }) => lighten(colors.tonalOffset, colors.warning.main),
|
||||||
dark: ({ colors }) => darken(colors.tonalOffset, colors.warning.main),
|
dark: ({ colors }) => darken(colors.tonalOffset, colors.warning.main),
|
||||||
contrastText: ({ colors }) => readableColor(colors.warning.main),
|
contrastText: '#ffffff',
|
||||||
},
|
},
|
||||||
error: {
|
error: {
|
||||||
main: '#e53935',
|
main: '#e53935',
|
||||||
|
|
|
@ -18,11 +18,6 @@ import 'prismjs/components/prism-ruby.js';
|
||||||
import 'prismjs/components/prism-scala.js';
|
import 'prismjs/components/prism-scala.js';
|
||||||
import 'prismjs/components/prism-swift.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';
|
const DEFAULT_LANG = 'clike';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,38 +25,42 @@ function decorateWithSpan(value, className) {
|
||||||
return '<span class="' + className + '">' + htmlEncode(value) + '</span>';
|
return '<span class="' + className + '">' + htmlEncode(value) + '</span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function punctuation(val) {
|
||||||
|
return '<span class="token punctuation">' + val + '</span>';
|
||||||
|
}
|
||||||
|
|
||||||
function valueToHTML(value) {
|
function valueToHTML(value) {
|
||||||
const valueType = typeof value;
|
const valueType = typeof value;
|
||||||
let output = '';
|
let output = '';
|
||||||
if (value === undefined || value === null) {
|
if (value === undefined || value === null) {
|
||||||
output += decorateWithSpan('null', 'type-null');
|
output += decorateWithSpan('null', 'token keyword');
|
||||||
} else if (value && value.constructor === Array) {
|
} else if (value && value.constructor === Array) {
|
||||||
level++;
|
level++;
|
||||||
output += arrayToHTML(value);
|
output += arrayToHTML(value);
|
||||||
level--;
|
level--;
|
||||||
} else if (value && value.constructor === Date) {
|
} else if (value && value.constructor === Date) {
|
||||||
output += decorateWithSpan('"' + value.toISOString() + '"', 'type-string');
|
output += decorateWithSpan('"' + value.toISOString() + '"', 'token string');
|
||||||
} else if (valueType === 'object') {
|
} else if (valueType === 'object') {
|
||||||
level++;
|
level++;
|
||||||
output += objectToHTML(value);
|
output += objectToHTML(value);
|
||||||
level--;
|
level--;
|
||||||
} else if (valueType === 'number') {
|
} else if (valueType === 'number') {
|
||||||
output += decorateWithSpan(value, 'type-number');
|
output += decorateWithSpan(value, 'token number');
|
||||||
} else if (valueType === 'string') {
|
} else if (valueType === 'string') {
|
||||||
if (/^(http|https):\/\/[^\s]+$/.test(value)) {
|
if (/^(http|https):\/\/[^\s]+$/.test(value)) {
|
||||||
output +=
|
output +=
|
||||||
decorateWithSpan('"', 'type-string') +
|
decorateWithSpan('"', 'token string') +
|
||||||
'<a href="' +
|
'<a href="' +
|
||||||
value +
|
value +
|
||||||
'">' +
|
'">' +
|
||||||
htmlEncode(value) +
|
htmlEncode(value) +
|
||||||
'</a>' +
|
'</a>' +
|
||||||
decorateWithSpan('"', 'type-string');
|
decorateWithSpan('"', 'token string');
|
||||||
} else {
|
} else {
|
||||||
output += decorateWithSpan('"' + value + '"', 'type-string');
|
output += decorateWithSpan('"' + value + '"', 'token string');
|
||||||
}
|
}
|
||||||
} else if (valueType === 'boolean') {
|
} else if (valueType === 'boolean') {
|
||||||
output += decorateWithSpan(value, 'type-boolean');
|
output += decorateWithSpan(value, 'token boolean');
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
@ -64,8 +68,9 @@ function valueToHTML(value) {
|
||||||
|
|
||||||
function arrayToHTML(json) {
|
function arrayToHTML(json) {
|
||||||
const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
|
const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
|
||||||
let output =
|
let output = `<div class="collapser"></div>${punctuation(
|
||||||
'<div class="collapser"></div>[<span class="ellipsis"></span><ul class="array collapsible">';
|
'[',
|
||||||
|
)}<span class="ellipsis"></span><ul class="array collapsible">`;
|
||||||
let hasContents = false;
|
let hasContents = false;
|
||||||
const length = json.length;
|
const length = json.length;
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
|
@ -77,9 +82,9 @@ function arrayToHTML(json) {
|
||||||
}
|
}
|
||||||
output += '</div></li>';
|
output += '</div></li>';
|
||||||
}
|
}
|
||||||
output += '</ul>]';
|
output += `</ul>${punctuation(']')}`;
|
||||||
if (!hasContents) {
|
if (!hasContents) {
|
||||||
output = '[ ]';
|
output = punctuation('[ ]');
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
@ -88,23 +93,24 @@ function objectToHTML(json) {
|
||||||
const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
|
const collapsed = level > COLLAPSE_LEVEL ? 'collapsed' : '';
|
||||||
const keys = Object.keys(json);
|
const keys = Object.keys(json);
|
||||||
const length = keys.length;
|
const length = keys.length;
|
||||||
let output =
|
let output = `<div class="collapser"></div>${punctuation(
|
||||||
'<div class="collapser"></div>{<span class="ellipsis"></span><ul class="obj collapsible">';
|
'{',
|
||||||
|
)}<span class="ellipsis"></span><ul class="obj collapsible">`;
|
||||||
let hasContents = false;
|
let hasContents = false;
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
const key = keys[i];
|
const key = keys[i];
|
||||||
hasContents = true;
|
hasContents = true;
|
||||||
output += '<li><div class="hoverable ' + collapsed + '">';
|
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]);
|
output += valueToHTML(json[key]);
|
||||||
if (i < length - 1) {
|
if (i < length - 1) {
|
||||||
output += ',';
|
output += punctuation(',');
|
||||||
}
|
}
|
||||||
output += '</div></li>';
|
output += '</div></li>';
|
||||||
}
|
}
|
||||||
output += '</ul>}';
|
output += `</ul>${punctuation('}')}`;
|
||||||
if (!hasContents) {
|
if (!hasContents) {
|
||||||
output = '{ }';
|
output = punctuation('{ }');
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user