Building a React Markdown Previewer: A Tutorial

Markdown has become a staple for writing formatted text on the web. For developers, being able to preview Markdown in real-time can significantly enhance productivity. In this blog post, I’ll guide you through building a simple React Markdown Previewer and suggest some ideas for extending its functionality.

What is a Markdown Previewer?

A Markdown Previewer is a tool that allows you to input Markdown text and instantly see the formatted output. This is particularly useful for writers and developers who use Markdown for documentation, blogging, or note-taking.

Setting Up Your React Environment

Before you start building your Markdown Previewer, you need to set up a React environment. If you haven’t already, you can create a new React application using Create React App:

npx create-react-app markdown-previewer
cd markdown-previewer
npm start

This sets up a new React project and starts the development server.

Building the Markdown Previewer

Here’s a step-by-step guide to building a basic React Markdown Previewer.

1. Install Showdown

Showdown is a JavaScript library that converts Markdown into HTML. We’ll use this to render our Markdown. Install Showdown via npm:

npm install showdown
2. Create the Markdown Component

Let’s create a simple React component that uses Showdown to convert Markdown text entered in a textarea to HTML.

import React, { useState } from 'react';
import Showdown from 'showdown';

function MarkdownPreviewer() {
  const [text, setText] = useState("Type some *Markdown* here!");

  const converter = new Showdown.Converter();

  function handleChange(event) {
    setText(event.target.value);
  }

  return (
    <div style={{ padding: 20 }}>
      <textarea
        style={{ width: '49%', height: '200px' }}
        value={text}
        onChange={handleChange}
      />
      <div
        style={{ width: '49%', height: '200px', overflowY: 'auto', border: '1px solid black', float: 'right' }}
        dangerouslySetInnerHTML={{ __html: converter.makeHtml(text) }}
      />
    </div>
  );
}

export default MarkdownPreviewer;
3. Add Styling

For simplicity, we’ve added inline styles to our components. The textarea for input and the div for output are styled to be side by side.

Extending the Markdown Previewer

Once you have the basic Markdown Previewer up and running, consider adding more features:

  1. Syntax Highlighting: Integrate a library like Prism or Highlight.js to add syntax highlighting to the code blocks in your Markdown output.
  2. Markdown Extensions: Use Showdown extensions to support additional Markdown syntax or create your own.
  3. Live URL Preview: Parse URLs in the text and show a live preview as a tooltip or a small popup next to the link.
  4. Export to PDF: Add a feature to export the formatted Markdown to a PDF file.
  5. User Authentication: Implement user authentication so users can save their Markdown documents and access them later.

Building a Markdown Previewer with React is a rewarding project that can be tailored to fit many use cases, from personal note-taking to providing live documentation previews in development environments. By integrating additional features like syntax highlighting and document export, you can greatly enhance its functionality. Start simple, and gradually add features as you become more comfortable with React and external libraries like Showdown.

Alternative Solutions for Building a Markdown Previewer

While using React and Showdown is a popular choice for building a Markdown Previewer, there are several other approaches you can take, depending on your preferences, the technologies you’re comfortable with, or the specific requirements of your project. Below, we explore a few alternative solutions and provide sample code for each.

1. Vue.js with Marked.js

Vue.js offers a reactive way to handle UIs, much like React. Combined with Marked.js, a low-level markdown compiler for parsing markdown without caching or blocking for long periods, it can be a great alternative:

Setup:

npm install -g @vue/cli
vue create vue-markdown-previewer
cd vue-markdown-previewer
npm install marked

Component:

<template>
  <div id="app">
    <textarea v-model="input" @input="updatePreview" />
    <div v-html="output"></div>
  </div>
</template>

<script>
import marked from 'marked';

export default {
  data() {
    return {
      input: '# hello world',
      output: ''
    };
  },
  methods: {
    updatePreview() {
      this.output = marked(this.input);
    }
  }
}
</script>

<style>
textarea, div {
  width: 50%;
  height: 200px;
  vertical-align: top;
  display: inline-block;
}
</style>

2. Angular with ngx-markdown

Angular is another powerful framework for building web applications. Paired with ngx-markdown, an Angular library that leverages the marked library to parse Markdown to HTML, it provides a robust solution.

Setup:

ng new angular-markdown-previewer
cd angular-markdown-previewer
npm install ngx-markdown

Component:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <textarea [(ngModel)]="markdown" rows="10" cols="80"></textarea>
    <markdown [data]="markdown"></markdown>
  `,
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  markdown = '# Hello Markdown!';
}

Module Import:

import { MarkdownModule } from 'ngx-markdown';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    MarkdownModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

3. Plain JavaScript with Remarkable

If you prefer not to use a framework, you can use plain JavaScript with the Remarkable library, which is highly configurable and supports plugins.

HTML Setup:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Simple Markdown Previewer</title>
</head>
<body>
  <textarea id="editor" rows="10" cols="30"></textarea>
  <div id="preview"></div>
  <script src="https://cdn.jsdelivr.net/npm/remarkable/dist/remarkable.min.js"></script>
  <script src="app.js"></script>
</body>
</html>

JavaScript:

document.getElementById('editor').addEventListener('input', function() {
  var md = new Remarkable();
  var output = md.render(this.value);
  document.getElementById('preview').innerHTML = output;
});

Choosing the right technology stack for your Markdown Previewer depends on your specific requirements and familiarity with the technology. Each solution offers unique advantages: React for component-based architecture, Vue for simplicity and integration, Angular for enterprise-level applications, and plain JavaScript for small projects or learning purposes. Experiment with different libraries and frameworks to find what works best for your use case.

This project not only helps solidify your React skills but also gives you a useful tool for your development arsenal. Happy coding!