0

I am using reactjs to render post. In my post, I have some tag <code></code>. So I want to display code for everyone easy to see.

I render my post like this with reactjs.

<div className="post-body" dangerouslySetInnerHTML={{
                    __html: this.state.post.content.rendered
                  }} />

I installed code-prettify from this.

https://www.npmjs.com/package/code-prettify

So how can I use pretty-code ?

Here is my content render json:

"content": {
        "rendered": "<p>In blogger\/blogspot you can you the conditional tags to make custom for posts, pages, archive page, label and search page, even a specific post.<\/p>\n<h2>I.List of conditional tags you can use in your Blogger theme.<\/h2>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>\n<li>For Index page (Homepage, label pages and archive pages)\n<div class=\"toolbar\"><code class=\"prettyprint\">&lt;b:if cond='data:blog.pageType == \"index\"'&gt;<br \/>\n&lt;\/b:if&gt;<\/code><\/div>\n<\/li>\n<li>\n<div class=\"toolbar\">For posts<\/div>\n<div class=\"toolbar\"><code class=\"prettyprint\">&lt;b:if cond='data:blog.pageType == \"index\"'&gt;<br \/>\n&lt;\/b:if&gt;<\/code><\/div>\n<\/li>\n<li>\n<div class=\"toolbar\">For pages<\/div>\n<div class=\"toolbar\"><code class=\"prettyprint\">&lt;b:if cond='data:blog.pageType == \"static_page\"'&gt;<br \/>\n&lt;\/b:if&gt;<\/code><\/div>\n<\/li>\n<li>\n<div class=\"toolbar\">For archive pages<\/div>\n<div class=\"toolbar\"><code class=\"prettyprint\">&lt;b:if cond='data:blog.pageType == \"archive\"'&gt;<br \/>\n&lt;\/b:if&gt;<\/code><\/div>\n<\/li>\n<li>\n<div class=\"toolbar\">For homepage<\/div>\n<div class=\"toolbar\"><code class=\"prettyprint\">&lt;b:if cond='data:blog.url == data:blog.homepageUrl'&gt;<br \/>\n&lt;\/b:if&gt;<\/code><\/div>\n<\/li>\n<li>\n<div class=\"toolbar\">For specific url<\/div>\n<div class=\"toolbar\"><code class=\"prettyprint\">&lt;b:if cond='data:blog.url == \"PUT_URL_HERE\"'&gt;<br \/>\n&lt;\/b:if&gt;<\/code><\/div>\n<\/li>\n<li>\n<div class=\"toolbar\">For search page<\/div>\n<div class=\"toolbar\"><code class=\"prettyprint\">&lt;b:if cond='data:blog.searchLabel'&gt;<br \/>\n&lt;\/b:if&gt;<\/code><\/div>\n<\/li>\n<li>\n<div class=\"toolbar\">For error page<\/div>\n<div class=\"toolbar\"><code class=\"prettyprint\">&lt;b:if cond='data:blog.pageType == \"error_page\"'&gt;<br \/>\n&lt;\/b:if&gt;<\/code><\/div>\n<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<h2>II. How to use?<\/h2>\n<p>You can use like this:<br \/>\nExample: In home page, I want to make a different style with other pages\/posts. I will use css inside conditional tags.<br \/>\n<code class=\"prettyprint\"><br \/>\n&lt;b:if cond='data:blog.url == data:blog.homepageUrl'&gt;<br \/>\n&lt;style&gt;<br \/>\nbody {font-size:20px; background:#f1f1f1}<br \/>\n&lt;\/style&gt;<br \/>\n&lt;script&gt;<br \/>\n\/\/&lt;![CDATA[<br \/>\n$('body').addClass('homepage')<br \/>\n\/\/]]&gt;<br \/>\n&lt;\/script&gt;<br \/>\n&lt;\/b:if&gt;<br \/>\n<\/code><\/p>\n<p>You also can use else if not homepage.<\/p>\n<p><code class=\"prettyprint\"><br \/>\n&lt;b:if cond='data:blog.url == data:blog.homepageUrl'&gt;<br \/>\n&lt;style&gt;<br \/>\nbody {font-size:20px; background:#f1f1f1}<br \/>\n&lt;\/style&gt;<br \/>\n&lt;script&gt;<br \/>\n\/\/&lt;![CDATA[<br \/>\n$('body').addClass('homepage')<br \/>\n\/\/]]&gt;<br \/>\n&lt;\/script&gt;<\/code><\/p>\n<p>&lt;b:else\/&gt;<br \/>\n&lt;!&#8211; Code for other pages here &#8211;&gt;<br \/>\n&lt;\/b:if&gt;<\/p>\n",
        "protected": false
    },
Hai Tien
  • 2,929
  • 7
  • 36
  • 55
  • Is there something specific in the [npm page](https://www.npmjs.com/package/code-prettify) or [docs page](https://github.com/google/code-prettify/blob/HEAD/docs/getting_started.md) that you don't understand? try to provide a [mcve] – Sagiv b.g Dec 22 '18 at 16:32
  • @Sagivb.g friend, I do not know how to import it in reactjs and how to call it after render? – Hai Tien Dec 22 '18 at 16:35
  • The [docs](https://github.com/google/code-prettify/blob/HEAD/docs/getting_started.md#marking-code-sections) are quite clear on that, just include the script and add a class to the `pre` tag -> `
    `
    – Sagiv b.g Dec 22 '18 at 16:39

2 Answers2

1

The docs are quite clear on how to use it, just include the script and add a prettyprint class to the pre tag

<pre class="prettyprint">

Here is a running example:

const codeFromServer = `<code>
function add(n1,n2){
  console.log(x + y);
}

const x = 8;
const y = 10;

add(x,y);
</code>
`;

class App extends React.Component{
  render(){
    return(
      <pre className="prettyprint" 
      dangerouslySetInnerHTML={{
                    __html: codeFromServer
                  }}></pre>
    );
  }
}

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />
Sagiv b.g
  • 30,379
  • 9
  • 68
  • 99
  • Like the way you do, it won't work. I also want to import pretty-code into bundle file. Codefromserver is block code and it can contain ``. post.content.rendered will render a block code (html) not only simple like your explain. – Hai Tien Dec 22 '18 at 16:53
  • So maybe provide the full picture here and attach an example of the data you receive from the server? by the way, my example uses a `code` tag as part of the string – Sagiv b.g Dec 22 '18 at 16:55
  • You can see content.rendered from json in updated question. – Hai Tien Dec 22 '18 at 17:00
  • You will need to extract the `code` blocks or return them with the `prettyprint` class. with that said, this is a really bad practice to get `html` markup from the server and render it. – Sagiv b.g Dec 22 '18 at 17:09
  • It already added class from serverside. I want only to call `pretty-code` after post is rendered – Hai Tien Dec 22 '18 at 17:13
  • As you said, it is bad practice, then WordPress API is bad ? – Hai Tien Dec 22 '18 at 17:23
  • 2
    I used the "auto run" script version, there is [another way to use this](https://github.com/google/code-prettify/blob/HEAD/docs/getting_started.md#serving-your-own-js--css) which let you invoke it on demand with `PR.prettyPrint()`. As for bad practice, yeah it is [risky](https://en.wikipedia.org/wiki/Cross-site_scripting) to render `HTML` that's why the react API is named `dangerouslySetInnerHTML` – Sagiv b.g Dec 22 '18 at 17:30
  • Thank you so much. I will try this way – Hai Tien Dec 22 '18 at 17:32
0

As Sagiv b.g mentioned there is a way to run it on demand, e.g. on page render like in the code snippet below. Also it is demonstrated how you can inject lib dynamically.

class CodePrettyComponent extends Component {
  static getHeadOrBody() {
    return document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0];
  }

  static codePrettify() {
    // Check if PR object already exists
    if (typeof PR !== 'undefined') {
        return;
    }

    // Inject if not
    CodePrettyComponent.getHeadOrBody().appendChild(
      Object.assign(
        document.createElement('script'),
        {
          type: 'text/javascript',
          async: true,
          src: 'https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js'
        }
      )
    );
  }

  componentDidMount() {
    // Injecting lib into document
    CodePrettyComponent.codePrettify();
    
    // Waiting for lib to be loaded and invoke
    setTimeout(() => { PR.prettyPrint(); }, 1500);
  }

  render() {
    return (
      <pre class = "prettyprint" >
        <code class = "language-groovy" >
          <!-- your code here -->
        </code>
      </pre>
    );
  };
};
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>

For rendering HTML in React use html-to-react. With parseWithInstructions() you can filter out potentially risky candidates.

Paul T. Rawkeen
  • 3,994
  • 3
  • 35
  • 51