Fixes swagger-editor/#1502.bubble
@@ -42,6 +42,7 @@ | |||||
"base64-js": "^1.2.0", | "base64-js": "^1.2.0", | ||||
"brace": "0.7.0", | "brace": "0.7.0", | ||||
"classnames": "^2.2.5", | "classnames": "^2.2.5", | ||||
"commonmark": "^0.28.1", | |||||
"css.escape": "1.5.1", | "css.escape": "1.5.1", | ||||
"deep-extend": "0.4.1", | "deep-extend": "0.4.1", | ||||
"expect": "1.20.2", | "expect": "1.20.2", | ||||
@@ -67,11 +68,11 @@ | |||||
"react-motion": "0.4.4", | "react-motion": "0.4.4", | ||||
"react-object-inspector": "0.2.1", | "react-object-inspector": "0.2.1", | ||||
"react-redux": "^4.x.x", | "react-redux": "^4.x.x", | ||||
"react-remarkable": "1.1.1", | |||||
"react-split-pane": "0.1.57", | "react-split-pane": "0.1.57", | ||||
"redux": "^3.x.x", | "redux": "^3.x.x", | ||||
"redux-immutable": "3.0.8", | "redux-immutable": "3.0.8", | ||||
"redux-logger": "*", | "redux-logger": "*", | ||||
"remarkable": "^1.7.1", | |||||
"reselect": "2.5.3", | "reselect": "2.5.3", | ||||
"sanitize-html": "^1.14.1", | "sanitize-html": "^1.14.1", | ||||
"scroll-to-element": "^2.0.0", | "scroll-to-element": "^2.0.0", | ||||
@@ -1,37 +1,40 @@ | |||||
import React from "react" | import React from "react" | ||||
import PropTypes from "prop-types" | import PropTypes from "prop-types" | ||||
import Remarkable from "react-remarkable" | |||||
import Remarkable from "remarkable" | |||||
import sanitize from "sanitize-html" | import sanitize from "sanitize-html" | ||||
function Markdown({ source }) { | function Markdown({ source }) { | ||||
const sanitized = sanitizer(source) | |||||
const html = new Remarkable({ | |||||
html: true, | |||||
typographer: true, | |||||
breaks: true, | |||||
linkify: true, | |||||
linkTarget: "_blank" | |||||
}).render(source) | |||||
const sanitized = sanitizer(html) | |||||
// sometimes the sanitizer returns "undefined" as a string | |||||
if(!source || !sanitized || sanitized === "undefined") { | |||||
return null | |||||
} | |||||
if ( !source || !html || !sanitized ) { | |||||
return null | |||||
} | |||||
return <div className="markdown"> | |||||
<Remarkable | |||||
options={{html: true, typographer: true, breaks: true, linkify: true, linkTarget: "_blank"}} | |||||
source={sanitized} | |||||
></Remarkable> | |||||
</div> | |||||
return ( | |||||
<div className="markdown" dangerouslySetInnerHTML={{ __html: sanitized }}></div> | |||||
) | |||||
} | } | ||||
Markdown.propTypes = { | Markdown.propTypes = { | ||||
source: PropTypes.string.isRequired | |||||
source: PropTypes.string.isRequired | |||||
} | } | ||||
export default Markdown | export default Markdown | ||||
const sanitizeOptions = { | const sanitizeOptions = { | ||||
textFilter: function(text) { | |||||
return text | |||||
.replace(/"/g, "\"") | |||||
} | |||||
allowedTags: sanitize.defaults.allowedTags.concat([ "img" ]), | |||||
textFilter: function(text) { | |||||
return text.replace(/"/g, "\"") | |||||
} | |||||
} | } | ||||
export function sanitizer(str) { | export function sanitizer(str) { | ||||
return sanitize(str, sanitizeOptions) | |||||
return sanitize(str, sanitizeOptions) | |||||
} | } |
@@ -111,7 +111,7 @@ export default class Response extends React.Component { | |||||
if(examples) { | if(examples) { | ||||
examples = examples.map(example => { | examples = examples.map(example => { | ||||
// Remove unwanted properties from examples | // Remove unwanted properties from examples | ||||
return example.set("$$ref", undefined) | |||||
return example.set ? example.set("$$ref", undefined) : example | |||||
}) | }) | ||||
} | } | ||||
@@ -1,11 +1,26 @@ | |||||
import React from "react" | import React from "react" | ||||
import ReactMarkdown from "react-markdown" | import ReactMarkdown from "react-markdown" | ||||
import { Parser, HtmlRenderer } from "commonmark" | |||||
import { OAS3ComponentWrapFactory } from "../helpers" | import { OAS3ComponentWrapFactory } from "../helpers" | ||||
import { sanitizer } from "core/components/providers/markdown" | import { sanitizer } from "core/components/providers/markdown" | ||||
export default OAS3ComponentWrapFactory(({ source }) => { return source ? ( | |||||
<ReactMarkdown | |||||
source={sanitizer(source)} | |||||
className={"renderedMarkdown"} | |||||
/> | |||||
) : null}) | |||||
export default OAS3ComponentWrapFactory(({ source }) => { | |||||
if ( source ) { | |||||
const parser = new Parser() | |||||
const writer = new HtmlRenderer() | |||||
const html = writer.render(parser.parse(source || "")) | |||||
const sanitized = sanitizer(html) | |||||
if ( !source || !html || !sanitized ) { | |||||
return null | |||||
} | |||||
return ( | |||||
<ReactMarkdown | |||||
source={sanitized} | |||||
className={"renderedMarkdown"} | |||||
/> | |||||
) | |||||
} | |||||
return null | |||||
}) |