Upgrading the Markdown Parser (Because Regex is a Bad Idea)
Ten minutes after publishing my first post, I realized my markdown parser was terrible.
The Problem
Built a custom markdown converter using regex. Worked for basic stuff. Broke on anything complex.
Here's what I had:
private function convertMarkdown($text)
{
$text = preg_replace('/^### (.+)$/m', '<h3>$1</h3>', $text);
$text = preg_replace('/^## (.+)$/m', '<h2>$1</h2>', $text);
$text = preg_replace('/\*\*(.+?)\*\*/s', '<strong>$1</strong>', $text);
// ... more regex hell
}
Problems:
- Didn't handle nested markdown
- Code blocks broke everything
- Lists didn't work properly
- Tables? Forget it
- Edge cases everywhere
Regex for parsing structured text is a known bad idea. Did it anyway because I wanted to ship fast. Paid for it immediately.
The Fix
Switched to Parsedown. Proper markdown parser. Handles everything.
Installation
composer require erusev/parsedown
Implementation
Replaced entire convertMarkdown() method with:
public function getContentHtmlAttribute()
{
$parsedown = new Parsedown();
$parsedown->setSafeMode(true); // Prevents XSS
return $parsedown->text($this->content);
}
Three lines. Done.
What This Gives Me
Better markdown support:
- All heading levels (not just three)
- Proper code blocks with ``` syntax
- Nested lists work correctly
- Blockquotes
- Tables
- Links and images handled properly
Strikethrough text- Horizontal rules
Security:
setSafeMode(true)prevents XSS attacks- No raw HTML execution
- Safe by default
Maintainability:
- Not maintaining custom regex
- Battle-tested library
- Edge cases already handled
The Deploy
Changed locally. Pushed. Pulled on server.
Got this error:
Class "Parsedown" not found
Right. Forgot to install on the server.
ssh liam@46.225.13.75
cd ~/sites/hizhub
composer require erusev/parsedown
Refreshed. Worked.
Testing the New Features
Let me test some markdown features that didn't work before:
Code Blocks
function toggleTheme() {
const html = document.documentElement;
html.classList.toggle('dark');
}
Works now. Didn't before.
Tables
| Feature | Regex Parser | Parsedown |
|---|---|---|
| Speed | Fast | Fast enough |
| Reliability | Breaks | Works |
| Maintenance | Pain | None |
Tables work. Nice.
Nested Lists
- First item
- Sub-item one
- Sub-item two
- Second item
- Another sub-item
- Even deeper
- Another sub-item
All renders correctly now.
Blockquotes
"Premature optimization is the root of all evil."
- Donald Knuth
Handles quotes properly.
Horizontal rules work too.
What I Learned
Don't reinvent the wheel:
- Used regex because I thought it'd be faster
- Took longer to debug than installing a library would have
- Classic mistake
Ship fast, but not that fast:
- Could have installed Parsedown from the start
- Would have saved time overall
- Sometimes the "quick" solution costs more
Test before you ship:
- Should have tried more complex markdown before publishing
- Would have caught the limitations immediately
- Live and learn
Use battle-tested libraries:
- Parsedown has been around since 2013
- Millions of downloads
- Edge cases already handled
- Just use it
The Result
Blog now handles proper markdown. Code blocks render. Tables work. Lists nest correctly.
Took 10 minutes to fix. Should have done it right the first time.
But hey - shipped, broke, fixed. That's the process.
Lesson: Don't parse structured text with regex. Use a proper parser. Your future self will thank you.