ToolForge
Advertisement

Markdown to HTML

Convert Markdown to HTML you control the shape of

Written by toolforge.websiteLast reviewed How we build and check these tools

Markdown to HTML tool

Nothing to convert yet.

Markdown

0 characters in

Ready-made settings

What gets parsed

Tables, task lists, strikethrough, autolinks and footnotes. Off leaves strict CommonMark.

What gets emitted

GitHub's slug rule, so an anchor written here works there too.

Adds a small # link inside each heading.

Only on links leaving the page; in-page anchors are left alone.

Adds loading and decoding attributes.

Wraps the markup in a valid HTML5 page instead of emitting a fragment.

How it is written

className and htmlFor, with every void element self-closed. An inline style attribute is still a string, not an object.

HTML

The HTML appears here as you type.

The Markdown is parsed and the HTML written in this browser — nothing is uploaded. Your source is kept on this device only while “Keep my source in this browser” is ticked. The verification preview always escapes raw HTML, so it cannot run anything your document contains.

Markdown to HTML: key facts

What it does
Convert Markdown to HTML you control the shape of
Category
Developer Tools
Cost
Free, with no account, sign-up, or install.
Your data
Runs entirely in your browser — the files and text you enter are never uploaded to a server.
Last reviewed
. Report an incorrect result.
Advertisement

Understanding the Markdown to HTML

Markdown is quick to write and HTML is what the browser reads, so somewhere between the two there has to be a converter. This one parses your source properly — a full CommonMark implementation with GitHub's extensions on top — and then hands you the markup as source code you can read, adjust and paste.

Correct parsing is the part people notice only when it is missing. A list nested three deep keeps its structure. A table becomes a real table with a header row. A fenced code block keeps its line breaks and gains a language class, and any Markdown syntax inside it stays as literal text instead of being converted. Characters that mean something in HTML get escaped, so a paragraph about "5 < 6 && 7 > 6" produces valid markup rather than a broken tag. An underscore in the middle of "MAX_BUFFER_SIZE" stays where it is.

The second half of the job is the shape of what comes out, because generated markup has to fit somewhere. Pretty-printed with two spaces, four, or a tab; compact with one element per line; or minified to a single line — with code blocks left untouched in all three, since their whitespace is content. Void elements as "<br>" or "<br />". Single or double quotes. JSX attribute names if it is going into a React component.

And a set of decisions about what the markup should carry: GitHub-style ids on headings so anchors work, optional anchor links beside them, Bootstrap or Tailwind classes on the elements, a target attribute on links that leave the page, lazy loading on images, and either a bare fragment or a complete HTML document with a stylesheet. Raw HTML in the source is escaped by default, and the other two options are explicit about what they do.

Raw HTML, and why escaping is the default

Markdown permits raw HTML, which is convenient when it is your own document and a liability when it is not. Converting Markdown that came from a user and dropping the result into a page is one of the standard ways a cross-site scripting bug gets introduced — a script tag or an onclick attribute travels through the converter untouched and executes in your visitors' browsers.

So this converter asks rather than assumes. Escape, the default, turns any raw HTML into visible text: the safest option, and usually the right one for a content pipeline. Remove drops it entirely. Keep passes it through exactly as written, for source you control.

Keep does not claim to sanitise, and that is deliberate. A filter built from pattern matching can be worked around, and a converter that advertises safety it cannot deliver is more dangerous than one that is honest. Instead, Keep reports what it found — script tags, style blocks, iframes, inline event handlers, javascript: URLs — and says plainly that it left them alone. If you need untrusted HTML made safe, that is a job for a real sanitiser at the point of use.

Getting a result

  1. Paste your Markdown into the box, or drop a .md file on it.
  2. Pick a ready-made setting — plain fragment, whole page, React/JSX, Bootstrap, Tailwind or minified — or set the options yourself.
  3. Decide what should happen to any raw HTML in the source: escape it, remove it, or keep it.
  4. Turn on the preview to check the markup renders the way you expect.
  5. Copy the HTML, copy it as JSX, or download an .html file.

Why parsing beats pattern matching

The tempting way to build a Markdown converter is a list of find-and-replace rules: turn a line starting with a hash into a heading, turn double asterisks into strong, and so on. It works on a paragraph of prose and falls apart on everything else, because Markdown's meaning depends on context that a substitution cannot see.

The failures are specific and repeatable. A rule that converts headings has no idea it is inside a fenced code block, so a shell comment in your example turns into an h1. A rule that converts links runs before the rule that converts images, so an image becomes a link with a stray exclamation mark in front of it. A rule that turns underscores into emphasis cannot tell a word from a variable name, so a constant like MAX_BUFFER_SIZE comes out with italics in the middle. Nested lists need a parser that tracks indentation as state; there is no regular expression for it.

A parser builds a tree first and asks what each node is afterwards, so the context is never in doubt. This converter does that, which is why the cases above simply work — and why its output is a fair test of what a Markdown file will look like once it is published.

  • Text inside a code fence stays text, however much it looks like Markdown.
  • Emphasis markers inside a word are ignored, matching the CommonMark rule.
  • A URL containing brackets keeps them, instead of the link ending at the first one.

Reasons to use it here

  • A genuine CommonMark parse with GitHub's extensions, so nested lists, tables, task lists, footnotes and code fences all convert correctly rather than approximately.
  • Text is escaped properly, so angle brackets and ampersands in your writing produce valid markup instead of broken tags.
  • The output's shape is yours: pretty, compact or minified; two spaces, four, or a tab; and both void-element and quoting styles.
  • JSX attribute names for pasting straight into a React component, with every void element self-closed.
  • GitHub-style heading ids and optional anchor links, matching the slugs the Markdown Previewer produces.
  • Bootstrap or Tailwind classes applied to the generated elements, on top of whatever the parse already produced.
  • A fragment for a template or a complete HTML document with a stylesheet, and a preview that renders the exact markup you are about to copy.
  • Raw HTML is escaped unless you say otherwise, and the alternatives state exactly what they do. Everything runs in your browser.

Making generated markup fit an existing codebase

Correct HTML and usable HTML are not the same thing. Markup that is going into a React component needs className rather than class and every void element closed. Markup going into a file that uses tabs should not arrive indented with spaces. Markup that will be styled by a framework needs that framework's classes on its tables and blockquotes, and a build step that inlines a fragment does not want a doctype wrapped around it.

None of that changes the meaning of the document, which is exactly why it is worth making adjustable rather than picking one and hoping. Every option here is a property of the step that writes the tree out as text, so switching between them re-emits the same parsed document in a different shape.

One rule is fixed: the contents of a code block are never reformatted. Indentation inside a fenced block is content, not layout, so it survives pretty-printing, compacting and minifying alike. It is the single most common way an HTML formatter quietly corrupts a page.

Frequently Asked Questions

Does it handle tables, task lists and nested lists?

Yes. Tables, task lists, strikethrough, autolinks and footnotes come from the GitHub extensions, which are on by default and can be switched off if your destination only accepts strict CommonMark — in which case a warning tells you which extended syntax went unconverted. Nested lists are handled by the parser rather than by pattern matching, so indentation is tracked properly however deep it goes.

Can I get output I can paste into a React component?

Turn on JSX attribute names, or use the React/JSX preset, and copy with the Copy as JSX button. You get className instead of class, htmlFor instead of for, and every void element self-closed. One caveat: an inline style attribute stays a string, and React wants an object, so convert any of those by hand.

What happens to HTML that is already in my Markdown?

By default it is escaped — it becomes visible text rather than markup, which is the safe choice when the source is not entirely yours. You can also remove it, or keep it exactly as written. Keep does not sanitise anything; it reports the risky constructs it can see, such as script tags and inline event handlers, and tells you they were left in place.

Will it reformat my code blocks?

No. Whitespace inside a fenced code block is content, so its contents are emitted verbatim in every output format, including minified. The block itself gets a language class — language-js by default, or the bare language name, or no class at all, depending on what your highlighter expects.

How is this different from the Markdown Previewer?

The previewer is for writing and reading: it shows the finished, styled document and gives you an editor, an outline and a check. This tool's product is the markup itself, and the shape of that markup — indentation, quoting, attribute names, classes, heading ids — is what you control here. The preview in this tool renders the emitted HTML string, which is a different question from how the Markdown looks.

Is anything uploaded?

No. The parse, the conversion and every export happen in your browser. Your source is stored in this browser's local storage on this device only while the autosave box is ticked, and long documents are never written there. If your document references a remote image, the browser fetches it when the preview draws it.

Related Tools

Advertisement
Buy Me a Coffee