How I use Markdown with WordPress
I love writing stuff in Markdown. But when I decided to write my blog posts in MD I wanted to have the same syntax as GitHub. In particular fenced code blocks.
There are a lot of plugins for WordPress to use MD, but most of them were too complicated for my liking. And they didn’t support GitHub’s syntax. So I ended up writing a small Rack app with Sinatra that uses Redcarpet to parse my blog posts.
The rundown
- When I save a post, WP sends a POST request to my Heroku app.
- Heroku parses the data and returns it to WP
- WP saves the parsed MD into
post_content
and the raw markdown intopost_content_filtered
- When I edit a post, WP grabs the content from
post_content_filtered
instead ofpost_content
The Rack app
I’ve uploaded my Rack app to GitHub so you can see the whole thing, but here’s the important stuff.
require 'rubygems'
require "sinatra"
require "redcarpet"
get "/" do
"I'm alive, I'm alive, I'm ... why are you not excited?"
end
post "/parse" do
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,
:autolink => true, :space_after_headers => true, :fenced_code_blocks => true, :no_intra_emphasis => true)
markdown.render(params[:markdown])
end
As you can see the code is dead simple. It just grabs the content passed in
$_POST['markdown']
(from a PHP perspective) and returns the rendered Markdown.
Modifying WordPress
<?php
function markdown_filter($data, $post) {
// change this to match your heroku app url
$ch = curl_init('http://radiant-stone-4578.heroku.com/parse');
curl_setopt_array($ch, array(
// don't print the result when done
CURLOPT_RETURNTRANSFER => true,
// use a post request and pass on the content
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => 'markdown=' . urlencode($data['post_content'])
));
// grab the parsed content
$parsed = curl_exec($ch);
curl_close($ch);
// back up the original markdown
$data['post_content_filtered'] = $data['post_content'];
// save the new parsed html
$data['post_content'] = $parsed;
return $data;
}
function get_markdown($content, $id) {
$post = get_post($id);
// make sure the post has content saved in post_content_filtered
if( $post && !empty($post->post_content_filtered) )
$content = $post->post_content_filtered;
return $content;
}
/**
* I'm not entirely sure why this is done
* it was used in the "Markdown on Save" plugin
* and I kept it in case it was needed
*
* @author Mark Jaquith
*/
function get_markdown_filtered($content, $id) {
return $content;
}
// on post save/update
add_filter( 'wp_insert_post_data' , 'markdown_filter' , '99', 2 );
// when editing a post
add_filter('edit_post_content', 'get_markdown', '99', 2);
// when editing post_content_filtered
add_filter('edit_post_content_filtered', 'get_markdown_filtered', '99', 2);
All we do is override the functionality of WP to parse the post content before it is saved and grab the MD when we edit a post.
The code probably needs to be put into a plugin so it works with all themes, but I put it into my functions.php file. It’s also important to note that the PHP is based on Mark Jaquith’s Markdown on Save.