mirror of
				https://github.com/Redocly/redoc.git
				synced 2025-10-29 06:47:26 +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