Project: Markdown Live Editor
In this project, we will build a Markdown Live Editor. The application features a side-by-side split screen: a text area input pane on the left, and a rendered HTML preview pane on the right.
1. Safety Alert: dangerouslySetInnerHTML
To render raw HTML strings generated from Markdown compilation, React requires you to use the dangerouslySetInnerHTML attribute. This attribute name serves as a warning that rendering unescaped HTML can expose users to Cross-Site Scripting (XSS) vulnerabilities.
In production applications, always sanitize the HTML string using libraries like dompurify before passing it to React.
2. Implementing the Editor
Create a new file named MarkdownEditor.jsx and add the following implementation:
import { useState } from "react";
// Simple custom compiler parsing headers, bold text, and line breaks
function compileMarkdown(markdownText) {
let html = markdownText;
// 1. Parse headers (e.g., # Header -> <h1>Header</h1>)
html = html.replace(/^# (.*$)/gim, "<h1>$1</h1>");
html = html.replace(/^## (.*$)/gim, "<h2>$1</h2>");
html = html.replace(/^### (.*$)/gim, "<h3>$1</h3>");
// 2. Parse bold text (e.g., **bold** -> <strong>bold</strong>)
html = html.replace(/\*\*(.*)\*\*/gim, "<strong>$1</strong>");
// 3. Parse line breaks into paragraphs
html = html.split("\n\n").map(para => {
if (para.trim().startsWith("<h")) return para;
return `<p>${para.replace(/\n/g, "<br />")}</p>`;
}).join("");
return html;
}
export function MarkdownEditor() {
const [markdown, setMarkdown] = useState("# Live Editor\n\nType some **bold text** here...");
const compiledHtml = compileMarkdown(markdown);
return (
<div className="editor-container">
{/* Input Textarea panel */}
<div className="editor-pane">
<h3>Markdown Input</h3>
<textarea
value={markdown}
onChange={(e) => setMarkdown(e.target.value)}
placeholder="Write markdown syntax..."
/>
</div>
{/* Rendered HTML preview panel */}
<div className="preview-pane">
<h3>Live HTML Preview</h3>
<div
className="rendered-preview"
dangerouslySetInnerHTML={{ __html: compiledHtml }}
/>
</div>
</div>
);
}3. Designing a Split-Screen Layout
Add the following split-screen CSS stylesheet to display the edit and preview panes side-by-side:
.editor-container {
display: flex;
gap: 20px;
height: 500px;
}
.editor-pane, .preview-pane {
flex: 1;
display: flex;
flex-direction: column;
}
textarea {
flex: 1;
padding: 15px;
font-family: monospace;
font-size: 14px;
border: 1px solid #ccc;
border-radius: 6px;
resize: none;
}
.rendered-preview {
flex: 1;
padding: 15px;
border: 1px solid #ccc;
border-radius: 6px;
background: #fafafa;
overflow-y: auto;
}Published on Last updated: