Guide

HTML to Markdown conversion

--flat-html turns rendered HTML into clean Markdown, with conversion rules you can extend per site and elements you can keep intact. Gutenberg content is covered by the same pass: its blocks are HTML with comment markers, and the markers are stripped on the way out.

The --flat-html option converts HTML content to clean Markdown format. This is useful for:

  • Sites using page builders (Bricks Builder, Elementor) that output complex HTML
  • Migrating content to markdown-based systems
  • Cleaning up HTML before export

Built-in Conversions

HTML Element Markdown Output
<h1> - <h6> # - ######
<p> Plain text with line breaks
<strong>, <b> <strong>bold</strong>
<em>, <i> *italic*
<a href="..."> [text](url)
<img src="..." alt="..."> ![alt](src)
<ul>, <ol> - or 1. lists
<blockquote> > quote
<code> `inline`
<pre><code> ``` code block
<hr> ---
Bricks: .brxe-heading ## heading
Bricks: .brxe-text paragraph

Custom Conversion Rules

You can define custom rules in your config.yaml for site-specific HTML classes:

 1flat_html_rules:
 2  # Bricks Builder custom headings
 3  - class: "brxe-heading"
 4    tag: "div"
 5    markdown: "## {content}\n\n"
 6
 7  # Elementor headings
 8  - class: "elementor-heading-title"
 9    markdown: "# {content}\n\n"
10
11  # Custom paragraph class
12  - class: "my-paragraph"
13    markdown: "{content}\n\n"
14
15  # Specific tag + class combination
16  - class: "custom-quote"
17    tag: "span"
18    markdown: "> {content}\n\n"

Rule fields:

  • class (required): CSS class to match
  • tag (optional): HTML tag to match (e.g., "div", "span")
  • markdown: Output template where {content} is replaced with the element's text

Preserving HTML Elements

Use --preserve-classes and --preserve-ids to keep certain elements intact during HTML processing with --flat-html or --basic-html. This is useful for:

  • Newsletter signup forms (Klaviyo, Mailchimp)
  • Embedded widgets and third-party scripts
  • Custom interactive elements you don't want converted
 1# Preserve Klaviyo forms (with wildcard)
 2wpexportjson export --url https://example.com --basic-html \
 3  --preserve-classes "klaviyo-form-*"
 4
 5# Preserve specific elements by ID
 6wpexportjson export --url https://example.com --flat-html \
 7  --preserve-ids "newsletter-form,sidebar-widget"
 8
 9# Combine classes and IDs (comma-separated)
10wpexportjson export --url https://example.com --basic-html \
11  --preserve-classes "klaviyo-form-*,mailchimp-widget" \
12  --preserve-ids "contact-form"

Wildcard support:

  • klaviyo-form-* matches klaviyo-form-XL7uTf, klaviyo-form-ABC123, etc.
  • brxe-*-section matches brxe-hero-section, brxe-footer-section, etc.

Configuration file:

1preserve_classes:
2  - "klaviyo-form-*"
3  - "mailchimp-widget"
4preserve_ids:
5  - "newsletter-form"

Usage Example

1# Convert HTML to Markdown with default rules
2wpexportjson export --url https://example.com --flat-html -f markdown
3
4# With custom rules from config file
5wpexportjson export --url https://example.com --flat-html --config config.yaml -f markdown
6
7# Combine with content crawling for page builder sites
8wpexportjson export --url https://example.com --crawl-content --flat-html -f markdown

Markdown Frontmatter Output

When using --assisted-crawl with markdown format, SEO fields are included in the frontmatter:

 1---
 2id: 123
 3title: "Original Post Title"
 4seo_title: "SEO Optimized Title | Site Name"
 5meta_description: "A compelling description for search engines..."
 6og_title: "Title for Social Sharing"
 7og_image: "https://example.com/social-image.jpg"
 8lang: "en-US"
 9hreflangs:
10  - lang: "en-US"
11    href: "https://example.com/post/"
12  - lang: "de-DE"
13    href: "https://example.com/de/post/"
14  - lang: "fr-FR"
15    href: "https://example.com/fr/post/"
16excerpt: "A brief summary of the post content..."
17# ... other fields
18---
19
20# Post Title
21
22The full post content follows directly after the frontmatter...

Gutenberg blocks support

WordPress Gutenberg editor stores content as HTML with special comment markers. Here's how wpexporter handles Gutenberg blocks:

✅ Standard Export Behavior

Gutenberg blocks export automatically in all formats:

Content Type Export Result
Standard blocks (paragraphs, headings, lists) ✅ Exported as HTML content
Core blocks (quote, code, image, gallery) ✅ Embedded HTML preserved
Custom blocks (plugins, themes) ✅ Rendered HTML output
Block patterns & reusable blocks ✅ Resolved to final HTML

No configuration needed for JSON, WordPress WXR, or HTML-preserving formats.

🔄 Markdown Conversion with --flat-html

When exporting to Markdown format, use --flat-html to convert Gutenberg HTML to clean Markdown:

1# Convert Gutenberg content to Markdown
2wpexportjson export --url https://example.com --flat-html -f markdown

Common Gutenberg CSS classes for custom rules in config.yaml:

 1flat_html_rules:
 2  # Core Gutenberg blocks
 3  - class: "wp-block-heading"
 4    markdown: "## {content}\n\n"
 5  - class: "wp-block-paragraph"
 6    markdown: "{content}\n\n"
 7  - class: "wp-block-quote"
 8    markdown: "> {content}\n\n"
 9  - class: "wp-block-code"
10    markdown: "```\n{content}\n```\n\n"
11  - class: "wp-block-preformatted"
12    markdown: "```\n{content}\n```\n\n"
13  - class: "wp-block-list"
14    markdown: "{content}\n\n"
15  - class: "wp-block-image"
16    markdown: "{content}\n\n"
17
18  # Extended blocks
19  - class: "wp-block-pullquote"
20    markdown: "> <strong>{content}</strong>\n\n"
21  - class: "wp-block-verse"
22    markdown: "*{content}*\n\n"
23  - class: "wp-block-table"
24    markdown: "{content}\n\n"

📋 Block Detection

The exporter preserves Gutenberg comment markers in HTML exports:

1<!-- wp:paragraph -->
2<p>Content here...</p>
3<!-- /wp:paragraph -->

These markers are stripped during Markdown conversion with --flat-html.