HTML to Markdown: A Real Migration in 6 Easy Steps cover image
Prateek Zare

Written by Prateek Zare

Software Developer with ML and Data Expertise, 8+ years of experience

Last updated

HTML to Markdown: A Real Migration in 6 Easy Steps

Maya had 42 blog posts trapped in an old CMS and one weekend to move them. The new static site reads only Markdown, so the job was HTML to Markdown, and it had to keep every table, link and code sample. This is a made up but typical case, and it shows what really happens.

What workedConvert one pilot post first, read the output line by line, fix the handful of problems it reveals, set the options once, then run the batch and compare counts of headings and links. The HTML to Markdown converter turned each post into clean text in seconds, and the checks took longer than the conversion.

HTML to markdown questions from the field

Is my HTML sent to a server during HTML to Markdown conversion?

No. The conversion runs in your browser, so nothing leaves your device.

Can HTML to Markdown conversion handle tables?

Yes. Turn on the convert tables option and you get pipe table syntax with a header separator row.

What is GitHub Flavored Markdown?

It is an extension of Markdown used by GitHub and many documentation tools. It adds tables, strikethrough, task lists and fenced code blocks with a language.

What happens to tags with no Markdown equivalent?

Structural tags such as div and section are flattened. Switch on strip remaining HTML to remove any other unsupported tags and keep plain Markdown.

Can I preview the Markdown before downloading?

Yes. The preview tab renders it as a quick visual check. It is simpler than a full Markdown engine, so treat it as a sanity check.

Do I choose hyphens or asterisks for bullets?

Either works for HTML to Markdown output. Both render the same in any Markdown processor, so match the style guide of the site you publish on.

The HTML to Markdown scenario: 42 posts, one weekend

The old CMS exported each post as an HTML file. Inside sat the article, wrapped in layout divs, with a navigation bar above it and a footer below. The posts used headings, bold text, lists, two or three tables, and now and then a code sample.

42Posts for HTML to Markdown
4 minPlanned time per post
2.8 hTotal, 42 times 4 minutes
1Pilot post to test first

Maya did the sums first. Forty two posts at four minutes each is 168 minutes, a little under three hours. That left room for fixes. The risk was not time. It was a silent mistake repeated 42 times.

Step 1: pick one pilot post

She chose the most complicated post: six headings, nine links, two tables and one code block. If the converter handled that, the simple posts would be fine. Here is a cut down version of it.

Pilot post, trimmed (HTML)

<div class="post">
  <h2>Our 2025 pricing</h2>
  <p>We now offer <strong>three</strong> plans. See the <a href="/pricing" title="Plans">pricing page</a>.</p>
  <ul><li>Starter</li><li>Team</li><li>Studio</li></ul>
  <table>
    <tr><th>Plan</th><th>Seats</th></tr>
    <tr><td>Starter</td><td>1</td></tr>
    <tr><td>Team</td><td>5</td></tr>
  </table>
  <pre><code class="language-bash">npm run build</code></pre>
</div>

Step 2: run the conversion and read the output

The converter does not use find and replace on the text. It hands the markup to the browser, which builds a real tree of elements, and then it walks that tree. Because the browser has already sorted out the nesting, the layout div simply disappears and its children are converted. No stray symbols are left behind.

Result (Markdown)

## Our 2025 pricing

We now offer **three** plans. See the [pricing page](/pricing "Plans").

- Starter
- Team
- Studio

| Plan | Seats |
| --- | --- |
| Starter | 1 |
| Team | 5 |

```bash
npm run build
```

Every piece is where it should be. The heading became two hash marks. Bold became double asterisks. The link kept its title. The table gained a separator row of dashes, which Markdown needs to recognise a table. The code block kept its language, read from the class on the code element.

What each tag became in the HTML to Markdown pilot
HTMLMarkdownNote
<h2>##One to six hashes for h1 to h6
<strong>**text**Same for the b tag
<em>*text*Same for the i tag
<a href title>[text](url "title")Title is optional
<ul><li>- itemOr * item if you tick the asterisk option
<table>Pipe table with separator rowGitHub Flavored Markdown
<pre><code class>Fenced block with languageLanguage read from the class
<div>NothingChildren are kept, wrapper removed

Step 3: fix the four problems the pilot revealed

The pilot looked good. Then Maya checked the rest of the post and found four things. Every migration meets some version of them.

HTML to Markdown problems, causes and fixes
ProblemCauseFix
A link looks broken in one placeThe title attribute contained a double quote, and the converter does not escape quotes inside titlesEdit that title before converting, or fix the line by hand afterward
Table cells ran together as plain textThe convert tables option was offTurn it on for any post with data
Menu items and footer text appeared in the outputThe export included the whole page, not only the articlePaste only the article container, or delete the extra HTML first
Images pointed to the old serverImage source paths were copied as they wereMove the image files and update the paths in a search and replace
Check link titles before HTML to Markdown runs

The converter inserts a link title into the Markdown as it is, without escaping quote marks. A title that itself contains a double quote cuts the Markdown link short. Scan for it before a big batch, using a search for the title attribute.

If your source markup is messy or minified, run it through the HTML formatter first. Indented markup is far easier to trim down to the article container.

A converted post shows its table as one run of words with no pipes after HTML to Markdown conversion. What is the most likely cause?

With table conversion off, table tags fall through to the generic handler, which strips the tags and keeps only the cell text. Turn the option on and convert again.

Why is a layout div not shown in the Markdown output?

Containers such as div, section and header add no Markdown construct. Their children are converted and the wrapper is dropped.

Step 4: set the options once

HTML to Markdown options Maya chose
OptionSettingWhy
GitHub Flavored MarkdownOnThe new site renders tables and strikethrough
Convert tablesOnPosts contain real data tables
Preserve code blocksOnKeeps fenced blocks with their language
Strip remaining HTMLOnRemoves tags that have no Markdown form
Use asterisk for bulletsOffHyphens match the site style guide

GitHub Flavored Markdown matters most. Plain Markdown has no table syntax, so the table support, the strikethrough and task lists all come from that extension. The specification requires the header row and the separator row to have the same number of cells, otherwise the table is not recognised. The converter builds the separator to match the header, including padding for short rows.

Step 5: run the batch and verify

Maya converted the posts one at a time and used the counters under the output as a check: words, lines, headings and links. Her rule was simple. The number of headings and links in the Markdown must equal the number in the source.

HTML to Markdown verification log for three posts
PostHeadings in HTMLHeadings in MarkdownLinks in HTMLLinks in MarkdownResult
Pricing 20256699Pass
Team update3344Pass
Launch notes54119Check: the last section was missing

The third post failed on both counts. She had copied only part of the article, so the last section never reached the converter. She pasted the full container and converted again. The mismatch cost two minutes and prevented a cut off post from going live. The preview tab then rendered the Markdown so she could see headings and tables as a reader would.

  1. Paste the article HTML onlyCut away navigation, footer and scripts before you paste.
  2. Convert and open the previewLook at headings, tables and code blocks visually.
  3. Compare countersHeadings and links in the output must match the source.
  4. Download the fileSave it as an md file with the post slug as its name.
  5. Log the resultNote pass or fix for each post so you can resume after a break.

Step 6: handle the small details

By post ten the routine was steady, and the remaining differences were small ones. Maya kept this list next to the keyboard so she knew what to expect rather than what to fear.

Smaller HTML to Markdown conversions worth knowing
HTMLMarkdown resultWhat to check
<blockquote>Each line starts with >Multi paragraph quotes keep their prefix on every line
<ol><li>A numbered list rebuilt from list positionNumbers restart at 1 in each list
<img src alt>![alt](src)Alt text is kept, so write good alt text first
<del> or <s>~~text~~Needs the GitHub Flavored option on the site too
Inline <code>Backticks around the textFine for short snippets

By Sunday afternoon all 42 files sat in the new site folder, each with a log line marked pass or fixed. The site build ran without a single warning, which was the real test. Nothing about the HTML to Markdown process was clever. It was repeated, counted and checked.

What the story teaches

Markdown is a smaller language than HTML. Conversion keeps meaning and drops styling. That is the right trade for text, and it is why you must decide what you can afford to lose.

Survives conversion

  • Headings, paragraphs and line structure
  • Bold, italic and strikethrough
  • Links with titles and images with alt text
  • Ordered and unordered lists
  • Tables and fenced code blocks

Does not survive

  • CSS classes, ids and inline styles
  • Colors and fonts
  • Layout wrappers such as div and section
  • Tags with no Markdown form, if stripping is on
  • Anything that relies on scripts

If you need the reverse direction, for instance to preview how the Markdown will look on the web, the Markdown to HTML converter closes the loop.

Your own migration checklist

Before you run HTML to Markdown on a whole site

Try HTML to Markdown on your own article now. Conversion, preview and download all happen in your browser.

Open the HTML to Markdown Converter

Sources: GitHub Flavored Markdown Spec