|
|
@@ -1,37 +1,40 @@ |
|
|
|
import React from "react" |
|
|
|
import PropTypes from "prop-types" |
|
|
|
import Remarkable from "react-remarkable" |
|
|
|
import Remarkable from "remarkable" |
|
|
|
import sanitize from "sanitize-html" |
|
|
|
|
|
|
|
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 = { |
|
|
|
source: PropTypes.string.isRequired |
|
|
|
source: PropTypes.string.isRequired |
|
|
|
} |
|
|
|
|
|
|
|
export default Markdown |
|
|
|
|
|
|
|
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) { |
|
|
|
return sanitize(str, sanitizeOptions) |
|
|
|
return sanitize(str, sanitizeOptions) |
|
|
|
} |