Bug: HTML <table> elements rendered as flat concatenated text instead of markdown table
Summary
When a WordPress post contains an HTML <table> (built with Gutenberg, Classic Editor, or any page builder), the markdown output collapses every cell value into a single unstructured text block. All semantic structure is lost — column headers, row boundaries, and cell separation disappear.
This makes the markdown output significantly less useful for the plugin's primary use cases (LLM ingestion, agent retrieval), since tabular data is one of the most information-dense content patterns publishers expose.
Steps to reproduce
- Create a WordPress post containing a standard HTML table (for instance a pricing or comparison table).
- Request the
.md version of the post (or use Accept: text/markdown content negotiation).
- Observe how the table is rendered in the markdown output.
Example
HTML input
<table>
<thead>
<tr>
<th>Plan</th>
<th>Price</th>
<th>Storage</th>
<th>Support</th>
</tr>
</thead>
<tbody>
<tr>
<td>Free</td>
<td>$0</td>
<td>5 GB</td>
<td>Community</td>
</tr>
<tr>
<td>Pro</td>
<td>$10/mo</td>
<td>100 GB</td>
<td>Email</td>
</tr>
<tr>
<td>Enterprise</td>
<td>Custom</td>
<td>Unlimited</td>
<td>Dedicated</td>
</tr>
</tbody>
</table>
Current output
PlanPriceStorageSupportFree$05 GBCommunityPro$10/mo100 GBEmailEnterpriseCustomUnlimitedDedicated
All structure is lost. A consumer cannot recover the original 4-column × 3-row table from this output.
Expected output (GitHub Flavored Markdown table syntax)
| Plan | Price | Storage | Support |
| ---------- | ------- | --------- | --------- |
| Free | $0 | 5 GB | Community |
| Pro | $10/mo | 100 GB | Email |
| Enterprise | Custom | Unlimited | Dedicated |
Root cause
The underlying converter league/html-to-markdown does not ship with a <table> converter out of the box. When no converter handles a tag, its inline text is collected without separators, producing the concatenated output observed above. This is a known limitation of the library.
Suggested fix
Two viable approaches:
Option A — Custom Converter (recommended). Implement a TableConverter class in src/Converter/ that implements League\HTMLToMarkdown\Converter\ConverterInterface, returns ['table', 'thead', 'tbody', 'tr', 'th', 'td'] from getSupportedTags(), and emits GFM pipe-table syntax. Register it on the HtmlConverter instance in MarkdownConverter::__construct() via $this->converter->getEnvironment()->addConverter(new TableConverter()).
Option B — HTML pre-processing. Pre-walk the HTML with DOMDocument in MarkdownConverter::convert() before calling $this->converter->convert($html). Replace each <table> node with its pre-computed markdown equivalent wrapped in a placeholder, then unwrap after conversion.
Option A is cleaner because it integrates with the library's extension model and handles nested cases (links, formatting, lists inside cells) via the existing converter chain.
Environment
- Markdown Alternate version: 1.1.0
- WordPress version: 6.7
- PHP version: 8.2
- Page builder used in the test post: Gutenberg
Why this matters
Markdown Alternate's value proposition is "clean structured content for LLMs and agents". Tables encode exactly the kind of dense, comparative information that benefits most from markdown ingestion (specs, comparisons, schedules, pricing). Losing them silently is a meaningful regression versus simply scraping the HTML.
Happy to test a patch once available.
Bug: HTML
<table>elements rendered as flat concatenated text instead of markdown tableSummary
When a WordPress post contains an HTML
<table>(built with Gutenberg, Classic Editor, or any page builder), the markdown output collapses every cell value into a single unstructured text block. All semantic structure is lost — column headers, row boundaries, and cell separation disappear.This makes the markdown output significantly less useful for the plugin's primary use cases (LLM ingestion, agent retrieval), since tabular data is one of the most information-dense content patterns publishers expose.
Steps to reproduce
.mdversion of the post (or useAccept: text/markdowncontent negotiation).Example
HTML input
Current output
All structure is lost. A consumer cannot recover the original 4-column × 3-row table from this output.
Expected output (GitHub Flavored Markdown table syntax)
Root cause
The underlying converter
league/html-to-markdowndoes not ship with a<table>converter out of the box. When no converter handles a tag, its inline text is collected without separators, producing the concatenated output observed above. This is a known limitation of the library.Suggested fix
Two viable approaches:
Option A — Custom Converter (recommended). Implement a
TableConverterclass insrc/Converter/that implementsLeague\HTMLToMarkdown\Converter\ConverterInterface, returns['table', 'thead', 'tbody', 'tr', 'th', 'td']fromgetSupportedTags(), and emits GFM pipe-table syntax. Register it on theHtmlConverterinstance inMarkdownConverter::__construct()via$this->converter->getEnvironment()->addConverter(new TableConverter()).Option B — HTML pre-processing. Pre-walk the HTML with
DOMDocumentinMarkdownConverter::convert()before calling$this->converter->convert($html). Replace each<table>node with its pre-computed markdown equivalent wrapped in a placeholder, then unwrap after conversion.Option A is cleaner because it integrates with the library's extension model and handles nested cases (links, formatting, lists inside cells) via the existing converter chain.
Environment
Why this matters
Markdown Alternate's value proposition is "clean structured content for LLMs and agents". Tables encode exactly the kind of dense, comparative information that benefits most from markdown ingestion (specs, comparisons, schedules, pricing). Losing them silently is a meaningful regression versus simply scraping the HTML.
Happy to test a patch once available.