<div id="app"></div>
:root {
  --bar-bg-color: #2196f3;
  --bar-text-color: #fff;
}

html {
  font-family: "Roboto", sans-serif;
  font-size: 16px;
}

body {
  margin: 0;
  height: 100vh;
}

#app {
  height: 100%;
}

#app > div {
  height: 100%;
  display: flex;
}

/* Editor and Preview Layout and Style */

#editor-box.hidden,
#preview.hidden {
  display: none;
}

#editor-box,
#preview {
  flex: 1;
  display: flex;
  flex-direction: column;
  height: 100%;
}

#editor-box {
  margin-left: 0.5rem;
}

#preview {
  margin-right: 0.5rem;
}

#editor-box textarea {
  resize: none;
  width: 100%;
  flex: 1;
  box-sizing: border-box;
  border: 1px solid #ddd;
  background: #fff;
}

#preview #output {
  flex: 1;
  overflow: auto;
  border: 1px solid #ddd;
}

#editor-box.maximized,
#preview.maximized {
  margin: 0 0.5rem;
}

/*
-----------------
  Headers Style 
-----------------
*/

header {
  padding: 0 0.5rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--bar-bg-color);
  color: var(--bar-text-color);
  border: 1px solid #ddd;
}

header h1 {
  margin: 0;
  font-weight: 500;
  font-size: 1.25rem;
}

button.material-icons {
  /* font-size: 1.8rem;
  padding: 4px;
  border: 1px solid black;
  border-radius: 50%;
  cursor: pointer; */
  padding: 8px;
  color: inherit;
}

/*
----------------------
  Editor Style
----------------------
*/
#editor-box textarea {
  font-family: "Roboto Mono", monospace;
  font-size: 14px;
}

/*
----------------------
  Preview Style
----------------------
*/

#preview #output {
  padding: 0.9rem;
  font-family: inherit;
  font-weight: 300;
}

#preview h1 {
  font-weight: 400;
}

#preview h2,
#preview h3,
#preview h4,
#preview h5,
#preview h6 {
  font-weight: inherit;
}

#preview img {
  max-width: 100%;
  max-height: 100%;
}

#preview blockquote {
  margin: 0;
  padding: 0 8px;
  border-left: 8px solid #555;
}

#preview code {
  font-family: "Roboto Mono", monospace;
  font-size: 14px;
}

/* 
-------------------------
M E D I A   Q U E R I E S
-------------------------
*/

@media (max-width: 720px) {
  #app > div {
    flex-direction: column;
  }

  #editor-box,
  #preview {
    margin: 0;
    height: initial;
  }

  #editor-box textarea {
    padding: 0 0.5rem;
  }

  #editor-box.maximized,
  #preview.maximized {
    margin: 0;
  }

  #preview #output {
    flex: initial;
    box-sizing: border-box;
    height: calc((100vh / 2) - 42px);
  }

  #preview.maximized #output {
    height: calc(100vh - 42px);
  }
}
const { IconButton } = window["material-ui"];

function Editor(props) {
  return (
    <section
      id="editor-box"
      className={
        props.minimized ? "hidden" : props.fullscreen ? "maximized" : ""
      }
    >
      <header>
        <h1>Editor</h1>
        <IconButton
          className="material-icons"
          onClick={e => props.onExpandClick(e, "editor")}
        >
          {props.fullscreen ? "fullscreen_exit" : "fullscreen"}
        </IconButton>
      </header>
      <textarea
        id="editor"
        cols="30"
        value={props.editorText}
        onChange={props.onInputChange}
      />
    </section>
  );
}

function Preview(props) {
  return (
    <section
      id="preview"
      className={
        props.minimized ? "hidden" : props.fullscreen ? "maximized" : ""
      }
    >
      <header>
        <h1>Preview</h1>
        <IconButton
          className="material-icons"
          onClick={e => props.onExpandClick(e, "preview")}
        >
          {props.fullscreen ? "fullscreen_exit" : "fullscreen"}
        </IconButton>
      </header>
      <div id="output" dangerouslySetInnerHTML={{ __html: props.parsedText }} />
    </section>
  );
}

class MarkdownApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = { rawText: INITIAL_MARKDOWN, elementExpanded: "" };
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleExpandClick = this.handleExpandClick.bind(this);
  }

  handleInputChange(e) {
    this.setState({ rawText: e.target.value });
  }

  handleExpandClick(e, section) {
    const elementExpanded = this.state.elementExpanded;
    this.setState({
      elementExpanded: elementExpanded === section ? "" : section
    });
  }

  render() {
    const rawText = this.state.rawText;
    const elementExpanded = this.state.elementExpanded;
    return (
      <div>
        <Editor
          onInputChange={this.handleInputChange}
          editorText={rawText}
          minimized={elementExpanded === "preview"}
          fullscreen={elementExpanded === "editor"}
          onExpandClick={this.handleExpandClick}
        />
        <Preview
          parsedText={marked(rawText)}
          minimized={elementExpanded === "editor"}
          fullscreen={elementExpanded === "preview"}
          onExpandClick={this.handleExpandClick}
        />
      </div>
    );
  }
}

const INITIAL_MARKDOWN = `
# Quesadillas with Guacamole

![Quesadillas with guacamole](https://2alin.github.io/apps/markdown-previewer/assets/quesadilla_guacamole.jpg)

photo by [Robert](https://www.flickr.com/photos/rdpeyton/)

## Ingredients
* 1/4 *Oaxaca* cheese
* 4 Tortillas
* 1 Avocado
* 1 Tomato
* 1 Lemon
* 1/4 Onion
* Salt

## Instructions
1. Fill your tortillas with shredded cheese and fold them forming a half-moon shape.
2. Cook them over a large pan with moderate heat. Try to get a crusty, brown surface on your quesadillas.
3. While the quesadillas are being cooked, you can start preparing the guacamole. Slice your onion and tomato in small squares.
4. Take out the flesh of the avocado and smash with a spoon or fork in a bowl.
5. Mix the smashed avocado, onion and tomato in the bowl. Add lemon juice and salt.
6. Put some guacamole in each quesadilla and enjoy!

> The name 'guacamole' comes from the nahuatl 'Ahuacamolli' [\`aːwakaˈmolːi\`] which literally translates to 'avocado sauce'

**Nutritional value per 100g of Avocado:**
\`\`\`
Energy          160kcal
Carbohydrates   8.53g
Fat             14.66g
Protein         2.00g
\`\`\`
`;

const APP_CONTAINER = document.querySelector("#app");
ReactDOM.render(<MarkdownApp />, APP_CONTAINER);
View Compiled

External CSS

  1. https://fonts.googleapis.com/icon?family=Material+Icons
  2. https://fonts.googleapis.com/css?family=Roboto+Mono:300,400|Roboto:300,400,500

External JavaScript

  1. https://unpkg.com/react@16/umd/react.production.min.js
  2. https://unpkg.com/react-dom@16/umd/react-dom.production.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/marked/0.5.1/marked.min.js
  4. https://unpkg.com/@material-ui/core/umd/material-ui.production.min.js