Baylor Rae'

$ cat "baylor rae's thoughts" > index.php

How I use Markdown with WordPress

December 30, 2011 | Baylor Rae' No Comments

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

  1. When I save a post, WP sends a POST request to my Heroku app.
  2. Heroku parses the data and returns it to WP
  3. WP saves the parsed MD into post_content and the raw MD into post_content_filtered
  4. When I edit a post, WP grabs the content from post_content_filtered instead of post_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.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>