Browse Source

[docs] Use marked instead of Showdown and escape HTML

Fixes #3501.
main
Ben Alpert 10 years ago
parent
commit
fdd13d86f2
  1. 4
      _js/examples/markdown.js
  2. 1
      _layouts/default.html
  3. 20
      docs/tutorial.md
  4. 11
      index.md
  5. 6
      js/marked.min.js
  6. 1302
      js/showdown.js

4
_js/examples/markdown.js

@ -1,6 +1,4 @@
var MARKDOWN_COMPONENT = ` var MARKDOWN_COMPONENT = `
var converter = new Showdown.converter();
var MarkdownEditor = React.createClass({ var MarkdownEditor = React.createClass({
getInitialState: function() { getInitialState: function() {
return {value: 'Type some *markdown* here!'}; return {value: 'Type some *markdown* here!'};
@ -20,7 +18,7 @@ var MarkdownEditor = React.createClass({
<div <div
className="content" className="content"
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: converter.makeHtml(this.state.value) __html: marked(this.state.value, {sanitize: true})
}} }}
/> />
</div> </div>

1
_layouts/default.html

@ -33,7 +33,6 @@
<script type="text/javascript" src="/react/js/react.js"></script> <script type="text/javascript" src="/react/js/react.js"></script>
<script type="text/javascript" src="/react/js/JSXTransformer.js"></script> <script type="text/javascript" src="/react/js/JSXTransformer.js"></script>
<script type="text/javascript" src="/react/js/live_editor.js"></script> <script type="text/javascript" src="/react/js/live_editor.js"></script>
<script type="text/javascript" src="/react/js/showdown.js"></script>
</head> </head>
<body> <body>

20
docs/tutorial.md

@ -212,7 +212,7 @@ Note that we have passed some data from the parent `CommentList` component to th
Markdown is a simple way to format your text inline. For example, surrounding text with asterisks will make it emphasized. Markdown is a simple way to format your text inline. For example, surrounding text with asterisks will make it emphasized.
First, add the third-party **Showdown** library to your application. This is a JavaScript library which takes Markdown text and converts it to raw HTML. This requires a script tag in your head (which we have already included in the React playground): First, add the third-party library **marked** to your application. This is a JavaScript library which takes Markdown text and converts it to raw HTML. This requires a script tag in your head (which we have already included in the React playground):
```html{7} ```html{7}
<!-- index.html --> <!-- index.html -->
@ -221,15 +221,14 @@ First, add the third-party **Showdown** library to your application. This is a J
<script src="https://fb.me/react-{{site.react_version}}.js"></script> <script src="https://fb.me/react-{{site.react_version}}.js"></script>
<script src="https://fb.me/JSXTransformer-{{site.react_version}}.js"></script> <script src="https://fb.me/JSXTransformer-{{site.react_version}}.js"></script>
<script src="https://code.jquery.com/jquery-1.10.0.min.js"></script> <script src="https://code.jquery.com/jquery-1.10.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.2/marked.min.js"></script>
</head> </head>
``` ```
Next, let's convert the comment text to Markdown and output it: Next, let's convert the comment text to Markdown and output it:
```javascript{2,10} ```javascript{9}
// tutorial6.js // tutorial6.js
var converter = new Showdown.converter();
var Comment = React.createClass({ var Comment = React.createClass({
render: function() { render: function() {
return ( return (
@ -237,25 +236,24 @@ var Comment = React.createClass({
<h2 className="commentAuthor"> <h2 className="commentAuthor">
{this.props.author} {this.props.author}
</h2> </h2>
{converter.makeHtml(this.props.children.toString())} {marked(this.props.children.toString())}
</div> </div>
); );
} }
}); });
``` ```
All we're doing here is calling the Showdown library. We need to convert `this.props.children` from React's wrapped text to a raw string that Showdown will understand so we explicitly call `toString()`. All we're doing here is calling the marked library. We need to convert `this.props.children` from React's wrapped text to a raw string that marked will understand so we explicitly call `toString()`.
But there's a problem! Our rendered comments look like this in the browser: "`<p>`This is `<em>`another`</em>` comment`</p>`". We want those tags to actually render as HTML. But there's a problem! Our rendered comments look like this in the browser: "`<p>`This is `<em>`another`</em>` comment`</p>`". We want those tags to actually render as HTML.
That's React protecting you from an XSS attack. There's a way to get around it but the framework warns you not to use it: That's React protecting you from an XSS attack. There's a way to get around it but the framework warns you not to use it:
```javascript{5,11} ```javascript{4,10}
// tutorial7.js // tutorial7.js
var converter = new Showdown.converter();
var Comment = React.createClass({ var Comment = React.createClass({
render: function() { render: function() {
var rawMarkup = converter.makeHtml(this.props.children.toString()); var rawMarkup = marked(this.props.children.toString(), {sanitize: true});
return ( return (
<div className="comment"> <div className="comment">
<h2 className="commentAuthor"> <h2 className="commentAuthor">
@ -268,9 +266,9 @@ var Comment = React.createClass({
}); });
``` ```
This is a special API that intentionally makes it difficult to insert raw HTML, but for Showdown we'll take advantage of this backdoor. This is a special API that intentionally makes it difficult to insert raw HTML, but for marked we'll take advantage of this backdoor.
**Remember:** by using this feature you're relying on Showdown to be secure. **Remember:** by using this feature you're relying on marked to be secure. In this case, we pass `sanitize: true` which tells marked to escape any HTML markup in the source instead of passing it through unchanged.
### Hook up the data model ### Hook up the data model

11
index.md

@ -72,16 +72,17 @@ id: home
<h3>A Component Using External Plugins</h3> <h3>A Component Using External Plugins</h3>
<p> <p>
React is flexible and provides hooks that allow you to interface with React is flexible and provides hooks that allow you to interface with
other libraries and frameworks. This example uses Showdown, an external other libraries and frameworks. This example uses **marked**, an external
Markdown library, to convert the textarea's value in real-time. Markdown library, to convert the textarea's value in real-time.
</p> </p>
<div id="markdownExample"></div> <div id="markdownExample"></div>
</div> </div>
</div> </div>
<script type="text/javascript" src="js/examples/hello.js"></script> <script type="text/javascript" src="/react/js/marked.min.js"></script>
<script type="text/javascript" src="js/examples/timer.js"></script> <script type="text/javascript" src="/react/js/examples/hello.js"></script>
<script type="text/javascript" src="js/examples/todo.js"></script> <script type="text/javascript" src="/react/js/examples/timer.js"></script>
<script type="text/javascript" src="js/examples/markdown.js"></script> <script type="text/javascript" src="/react/js/examples/todo.js"></script>
<script type="text/javascript" src="/react/js/examples/markdown.js"></script>
</section> </section>
<hr class="home-divider" /> <hr class="home-divider" />
<section class="home-bottom-section"> <section class="home-bottom-section">

6
js/marked.min.js

File diff suppressed because one or more lines are too long

1302
js/showdown.js

File diff suppressed because it is too large
Loading…
Cancel
Save