Created
October 19, 2009 19:28
-
-
Save cgrand/213649 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: Pygments Support | |
Plugin URI: http://lucumr.pocoo.org/ | |
Description: Adds support for pygments to wordpress | |
Version: 1.0 | |
Author: Armin Ronacher | |
Author URI: http://lucumr.pocoo.org/ | |
Modified by Christophe Grand to support wordpress 2.8 | |
*/ | |
define('PYGMENTS_STYLE', 'pastie'); | |
define('PYGMENTS_PATH', '/usr/bin/pygmentize'); | |
/** | |
* function that highlights code in a pygments | |
* subprocess and returns the highlighted HTML. | |
* | |
* return NULL if something went wrong. | |
*/ | |
function pygments_highlight_code($tag, $code, $lexer) | |
{ | |
if (!preg_match('/^[a-zA-Z_+]+$/', $lexer)) | |
return NULL; | |
$pipes = NULL; | |
$process = proc_open(PYGMENTS_PATH . ' -l' . $lexer . ' -fhtml -Onowrap,style=' . | |
PYGMENTS_STYLE, array( | |
array('pipe', 'r'), | |
array('pipe', 'w'), | |
array('pipe', 'w') | |
), $pipes); | |
fwrite($pipes[0], $code); | |
fclose($pipes[0]); | |
$highlighted = rtrim(stream_get_contents($pipes[1])); | |
fclose($pipes[1]); | |
$errors = stream_get_contents($pipes[2]); | |
fclose($pipes[2]); | |
if (trim($errors)) | |
return NULL; | |
proc_close($process); | |
return '<' . $tag . ' class="highlight">' . addcslashes($highlighted, '\\') . '</' . $tag . '>'; | |
} | |
/** | |
* this function is called to remove the cached stuff from the post | |
* if the post was edited. This ensures that the cached output is not | |
* visible in the editor and that you can edit the post after posting. | |
*/ | |
function pygments_cleanup_code($text) | |
{ | |
// Step 1: remove the cached stuff | |
$regex = '/<!-- PYGMENTS_CACHE>.*?<PYGMENTS_CACHE -->/sm'; | |
$text = preg_replace($regex, '', $text); | |
// Step 2: remove the comments around the raw stuff | |
// and recreate the <pre lang=""></pre> stuff. | |
$regex = '/<!-- PYGMENTS_RAW\\(([^,)]+),?\\s*([^)]*)\\)>(.*?)<PYGMENTS_RAW -->/sm'; | |
return preg_replace_callback($regex, '_pygments_perform_cleanup', $text); | |
} | |
function _pygments_perform_cleanup($match) | |
{ | |
$tag = $match[2] == "" ? "pre" : $match[2]; | |
return '<' . $tag . ' lang="' . $match[1] . '">' . $match[3] . '</' . $tag . '>'; | |
} | |
/** | |
* the opposite of the pygments_cleanup_code. It's executed when | |
* rendering the blog post and just removes the raw stuff because we | |
* don't want a bloated page. | |
*/ | |
function pygments_finish_code($text) | |
{ | |
// Step 1: uncomment the cache | |
$regex = '/<!-- PYGMENTS_CACHE>(.*?)<PYGMENTS_CACHE -->/sm'; | |
$text = preg_replace($regex, '\\1', $text); | |
// Step 2: remove all the raw stuff | |
$regex = '/<!-- PYGMENTS_RAW\\(.*?<PYGMENTS_RAW -->/sm'; | |
return preg_replace($regex, '', $text); | |
} | |
/** | |
* highlight the code inline. All the pre tags with a language tag | |
* are processed by pygments then. | |
*/ | |
function pygments_highlight_code_inline($text) | |
{ | |
// Find all the pre or code blocks with a lang attribute | |
$regex = '/<(pre|code)\\s+lang=\\\\(["\'])([^\\\\]+)\\\\\\2>(.*?)<\\/\\1>/ism'; | |
return preg_replace_callback($regex, '_pygments_perform_replace', $text); | |
} | |
/** | |
* helper function (callback) for pygments_highlight_code_inline | |
*/ | |
function _pygments_perform_replace($match) | |
{ | |
$lang = strtolower($match[3]); | |
$code = $match[4]; | |
$highlighted = pygments_highlight_code($match[1], stripslashes($code), $lang); | |
if (!$highlighted) | |
$highlighted = '<' . $match[1] . '>' . htmlspecialchars($code) . '</' . $match[1] . '>'; | |
return '<!-- PYGMENTS_CACHE>' . $highlighted . '<PYGMENTS_CACHE -->' . | |
'<!-- PYGMENTS_RAW(' . $lang . ', ' . $match[1] . ')>' . $code . '<PYGMENTS_RAW -->'; | |
} | |
// register filters in wordpress | |
add_filter('the_editor_content', 'pygments_cleanup_code', 100); | |
add_filter('content_save_pre', 'pygments_highlight_code_inline', 1); | |
add_filter('the_content', 'pygments_finish_code', 1); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment