Build a Markdown Previewer - Not rendering code blocks

Hi All,

I’m on challenge number 2 of the Front End Development Libraries. I have everything working except I can’t figure out why using literals for code blocks in the Editor section does not render as a code block in the Preview section. Any ideas what I’m missing? Please see below for my code so far.

Thanks!

HTML

<!DOCTYPE html>
<html lang="en">
  <body>
    <head>
      <title>Markdown Previewer</title>
    </head>
<div id="root"></div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/4.2.4/marked.min.js" integrity="sha512-nwWBb9WFoP7Q0hkeTjUPmHkkYLnmYgYnZ8PvQVVL2XJ9RLCGuLqKe86bhmZ3CJXGU8F777uuPkDQTkZ2qAuyvA==" crossorigin="anonymous" referrerpolicy="no-referrer"> </script>
  </body>
</html>

CSS

body {
  background-color: #fc3903;
  text-align: center;
  margin: auto;
  justify-content: center; 
}
#editor-top {
  background-color: #16a9f2;
  width: 806px;
  height: 2em;
  margin: auto;
  margin-bottom: 0;
  margin-top: 2em;
  border-radius: 5px 5px 0 0;
  box-shadow: 0px 0px 20px black; 
  text-align: left;
}
#editor {
  margin: auto;
  margin-top: 0;
  height: 20em;
  width: 800px;
  overflow-y: scroll;
  resize: vertical;
  background-color: #b3e9f5;
}
#preview { 
  text-align: center;
  padding-top: 2em;
  margin: auto;
  width: 1000px;
  height: auto;
  min-height: 60em;
  background-color: #b3e9f5; 
  box-shadow: 0px 0px 20px black; 
  
}
#hidden {
  display: none;
}
#preview-top {
  background-color: #16a9f2;
  width: 1000px;
  height: 2em;
  margin: auto;
  margin-bottom: 0;
  margin-top: 2em;
  border-radius: 5px 5px 0 0;
  box-shadow: 0px 0px 20px black; 
  text-align: left;
}
.top-image {
  display: inline;
  height: 50%;
  padding-top: 8px;
  padding-left: 10px;
}
.top-text {
  display: inline;
  font-weight: bold;
  padding-left: 10px;
}
img {
  max-width: 90%;
}

Javyscript

import React, { useState } from "https://cdn.skypack.dev/react";
import ReactDOM from "https://cdn.skypack.dev/react-dom";
import useStateInCustomProperties from "https://cdn.skypack.dev/use-state-in-custom-properties";


class ControlledInput extends React.Component {

  constructor(props) {

    super(props);

    this.state = {
      input: "",
      messages: []

    };

    // Change code below this line

    this.handleChange = this.handleChange.bind(this);
    
    

    // Change code above this line

  }

  // Change code below this line

  handleChange (event) {

    this.setState({

      input: event.target.value

    });

  }
  
  

  

  render() {

    return (

      <div>

        { /* Change code below this line */}
        <div id="editor-top"><img className="top-image" src="https://d33wubrfki0l68.cloudfront.net/bbfa33a202e8612d49b6c1ed05c1fdd8e4001566/bbdd1/img/fcc_secondary_small.svg"></img><p className="top-text">Editor</p></div>
        <textarea id="editor" onChange={this.handleChange}></textarea>

        { /* Change code above this line */}
        
        <h4>Controlled Input:</h4>
        <div id="preview-top"><img className="top-image" src="https://d33wubrfki0l68.cloudfront.net/bbfa33a202e8612d49b6c1ed05c1fdd8e4001566/bbdd1/img/fcc_secondary_small.svg"></img><p className="top-text">Previewer</p></div>
        <div id="preview" dangerouslySetInnerHTML= {{__html: marked.parse(this.state.input)}} />

      </div>

    );
  }
};

ReactDOM.render(<ControlledInput/>, document.getElementById('root'))

Can you give us an example of exactly what you are typing into the editor?

So for example, if I type in the text below and surround it with three backticks at the beginning and at the end it just treats it as regular text. It doesn’t look the way it’s supposed to look here for instance.

function anotherExample(firstLine, lastLine) {
if (firstLine == ‘' && lastLine == '’) {
return multiLineCode;
}
}

First, is it putting this in a code element? If so then it is working properly. As far as the styling goes, you’ll need to add that yourself in your CSS. Browsers don’t add any default styling for code elements (at least that I know of).

I think that FCC example might be using the PrismJS library to do the code styling. So you might look into that.

Good question, at first I didn’t think it was but upon closer inspection it actually was putting the text within code tags. Is there anything wrong with just using CSS to style code blocks? That’s what I ended up doing.

Another thing that tripped me up was figuring out how to make test 5 below pass.

" User Story #5: When my markdown previewer first loads, the default text in the #editor field should contain valid markdown that represents at least one of each of the following elements: a heading element (H1 size), a sub heading element (H2 size), a link, inline code, a code block, a list item, a blockquote, an image, and bolded text."

I tried to store the markdown in a variable, but in order to do multiple lines of text I had to use backticks. However, using template literals (to mark code) inside of template literals doesn’t work so well, so I used defined variables and referenced them inside the defaultText variable instead as shown below which worked. I had to use an array for the multi-line code blocks. I’m sure there’s a better way to do it, but that’s what I came up with.

import ReactDOM from "https://cdn.skypack.dev/react-dom";
import useStateInCustomProperties from "https://cdn.skypack.dev/use-state-in-custom-properties";

let inlineCode = "`<div></div>`";
let multiLineCode = ["```", "function() {", "console.log('Hello World!')}", "```"];

let defaultText = `# Welcome to my React Markdown Previewer!
## This is a sub-heading...
### And here's some other cool stuff:

Heres some code, ${inlineCode}, between 2 backticks.


You can also make text **bold**... whoa!
Or _italic_.
Or... wait for it... **_both!_**
And feel free to go crazy ~~crossing stuff out~~.

There's also [links](https://www.freecodecamp.org), and
> Block Quotes!

And if you want to get really crazy, even tables:

Wild Header | Crazy Header | Another Header?
------------ | ------------- | -------------
Your content can | be here, and it | can be here....
And here. | Okay. | I think we get it.

- And of course there are lists.
  - Some are bulleted.
     - With different indentation levels.
        - That look like this.


1. And there are numbered lists too.
1. Use just 1s if you want!
1. And last but not least, let's not forget embedded images:

![freeCodeCamp Logo](https://cdn.freecodecamp.org/testable-projects-fcc/images/fcc_secondary.svg)

Here's some multi-line code:

${multiLineCode[0]}
${multiLineCode[1]}
${multiLineCode[2]}
${multiLineCode[3]}

`;

class ControlledInput extends React.Component {

  constructor(props) {

    super(props);

    this.state = {
      input: defaultText,
      messages: []

    };

    // Change code below this line

    this.handleChange = this.handleChange.bind(this);
    
    

    // Change code above this line

  }

  // Change code below this line

  handleChange (event) {

    this.setState({

      input: event.target.value

    });

  }
  
  

  

  render() {

    return (

      <div>

        { /* Change code below this line */}
        <div id="editor-top"><img className="top-image" src="https://d33wubrfki0l68.cloudfront.net/bbfa33a202e8612d49b6c1ed05c1fdd8e4001566/bbdd1/img/fcc_secondary_small.svg"></img><p className="top-text">Editor</p></div>
        <textarea id="editor" onChange={this.handleChange}>{this.state.input}</textarea>

        { /* Change code above this line */}
        
        <h4>Controlled Input:</h4>
        <div id="preview-top"><img className="top-image" src="https://d33wubrfki0l68.cloudfront.net/bbfa33a202e8612d49b6c1ed05c1fdd8e4001566/bbdd1/img/fcc_secondary_small.svg"></img><p className="top-text">Previewer</p></div>
        <div id="preview" dangerouslySetInnerHTML= {{__html: marked.parse(this.state.input)}} />

      </div>

    );
  }
};

ReactDOM.render(<ControlledInput/>, document.getElementById('root'))

Thanks for your help! Finally got it to pass now. I’m still working on adding a button to the editor and previewer to get them to expand though. Here’s my work so far. Any suggestions for improvements I could make to it?

Not at all. In fact, I think that’s the only way to do it. The Prism library just does it all for you.

I think you just need to escape the back ticks with the backward slash and then you should be able to stick them directly in the template literal.

Prisma will tokenize the code and add span elements around the tokens with different classes applied. Using CSS to just style the code block is not really the same thing.

As an example:

// this is multi-line code:

function anotherExample(firstLine, lastLine) {
  if (firstLine == '```' && lastLine == '```') {
    return multiLineCode;
  }
}

The HTML output

<pre><code><span class="token comment">// this is multi-line code:</span>

<span class="token keyword">function</span> <span class="token function">anotherExample</span><span class="token punctuation">(</span><span class="token parameter">firstLine<span class="token punctuation">,</span> lastLine</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>firstLine <span class="token operator">==</span> <span class="token string">'```'</span> <span class="token operator">&amp;&amp;</span> lastLine <span class="token operator">==</span> <span class="token string">'```'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> multiLineCode<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>