Markdown Editor
Write and preview Markdown in real-time with syntax highlighting.
Write and preview Markdown in real-time with syntax highlighting.
The left pane is a plain textarea. On every input event, the editor waits 150 milliseconds, then sends the raw Markdown through marked.parse(text, { breaks: true, gfm: true }). GitHub Flavored Markdown is enabled, and single newlines become line breaks because of the breaks option. The resulting HTML string is then passed through DOMPurify with a specific blocklist before it reaches the preview pane.
The sanitizer forbids five tags — form, input, button, select, and textarea — and strips four event-handler attributes: onerror, onclick, onload, and onmouseover. Anything else in the Markdown, including raw HTML you paste in, is parsed first and cleaned second. The right pane shows the sanitized result and the toolbar re-renders live as you type.
| You type | You get | Why |
|---|---|---|
# Hello | <h1>Hello</h1> | Standard ATX heading |
**bold** and *italic* | <p><strong>bold</strong> and <em>italic</em></p> | Inline emphasis |
- [x] done | A list item reading “done”, no checkbox | The input tag is forbidden |
<img src=x onerror=alert(1)> | <img src="x"> | onerror is stripped, tag kept |
<script>alert(1)</script> | Nothing rendered | Script is removed by the sanitizer |
Character and word counts use the raw source, not the rendered output. The string # Hello world reports 13 characters and 3 words, because #, Hello, and world are each counted. The word counter trims leading and trailing whitespace and splits on runs of whitespace, so blank lines do not inflate the total.
The gfm: true flag turns on tables, fenced code blocks, strikethrough, autolinks, and task lists. Headings, blockquotes, nested lists, inline code, links, and images all work. Raw HTML embedded in the Markdown is allowed only if it survives the DOMPurify pass, so <details>, <summary>, and <br> render, while forms and interactive controls do not. Fenced code blocks get syntax highlighting only when a highlighter (hljs) is available on the page; otherwise they render as plain monospace blocks.
localStorage under an unencrypted key and leaves it there until you clear site data or replace it.Only one document is stored. The key onlinehandytools-markdown-editor holds a single string, so switching projects overwrites the previous draft without warning. There is no undo history beyond the browser’s native textarea undo, no versioning, no file import, and no collaborative editing. The exported HTML has fixed, built-in styling; it is readable anywhere but will not match a specific site’s design system. Copy HTML places the sanitized fragment on the clipboard, not a full document. Because DOMPurify is applied after marked, any Markdown extension that relies on forbidden tags will silently lose functionality rather than report an error.
The HTML export writes a complete page with a UTF-8 charset, a viewport meta tag, and inline CSS for headings, code, tables, and blockquotes. The Markdown export writes the raw source byte for byte. Filenames come from the interface strings rather than a name field, so repeated exports overwrite each other unless your browser renames them.
| Action | Output | Best for |
|---|---|---|
| Export HTML | A complete page with inline CSS | Sharing a standalone, self-contained preview |
| Export MD | The raw Markdown source | Checking into a repository or static site generator |
| Copy HTML | The sanitized HTML fragment | Pasting into a CMS field that accepts rich text |
The HTML export is one-way: headings, links, tables, and code blocks carry over, but editability does not, so treat the Markdown source as the master copy. Note that the exported page does not include the preview’s syntax highlighting — it ships the code as plain text inside a styled pre block, because the highlighter is a page script rather than part of the serializer. The clipboard option is best when a CMS accepts rendered HTML and you want formatting without downloading a file. None of the three options embeds images as data URIs, so a shared HTML file still depends on the original image hosts to display them.
Keep a README-style first heading (# Project Name) at the top so the exported file has a clear title. Use tables for comparison data and fenced code blocks with a language tag for fenced highlighting. Before publishing, paste the raw Markdown into a diff checker to review changes without reading the rendered preview. If you need a guaranteed save, copy the raw Markdown manually rather than relying on the 5-second autosave window.
Marked renders task lists as input elements, but DOMPurify is configured to forbid form, input, button, select, and textarea tags. The checkboxes are stripped, leaving the list item text without a box.
Yes. The count splits the raw editor text on whitespace, so '# Report' counts as two words and a bold '**title**' counts as one. Strip the syntax first if you need prose-only counts.
No. Autosave writes to a single localStorage key, so loading a second document overwrites the first. Export the current draft before starting another.
Yes. It bundles the rendered markup and a small inline stylesheet for headings, code blocks, tables, and blockquotes, so it opens correctly without the editor or any external CSS.
Autosave runs every 5 seconds on a timer, not on each keystroke. Edits made in the final seconds before closing may be lost, so trigger a manual copy or export if the timing is tight.
There is no file-import control. Paste the Markdown into the left pane instead; export is one-way, as HTML, raw Markdown, or clipboard HTML.
Reviewed by the HandyTools Hub team · Last updated