[plain text] [download]
  1. <?php
  2. /*
  3. Plugin Name: Illudium PU-36 Explosive Codeolulator
  4. Version: 1.0.2
  5. Plugin URI: http://rephrase.net/box/word/codeolulator/
  6. Description: Converts &lt;pre&gt;&lt;code&gt; blocks into pretty ordered lists
  7. Author: Sam Angove
  8. Author URI: http://rephrase.net/
  9. */
  10.  
  11. /*
  12. Changelog:
  13. 1.0.2:
  14. * wrap in a class
  15. * use proper wp query methods
  16. * look for code.php in templates
  17. 1.0.1:
  18. * rewrite rules generated better
  19. * don't add "view/download" link for really short code blocks
  20. * code without a number means show all code snippets
  21. Credits:
  22. As far as I know, the original idea was Simon Willison's:
  23.    <http://simon.incutio.com/archive/2002/07/10/numberedCodeListing>
  24.    
  25. Part of this plugin's code -- an irritatingly small amount, actually; just
  26. the stuff for counting whitespace. I'd have had to reinvent the wheel less
  27. if I'd found it earlier -- was taken straight from Aaron Schaefer's Code Viewer.
  28. If you want code samples kept in a separate location, use that instead.
  29.    <http://elasticdog.com/2004/09/code-viewer/>
  30. */
  31.  
  32.  
  33. /******
  34.   Options
  35.      ******/
  36.  
  37. /* Show a "View/Download" link to plaintext version? */
  38. $codeolulator['show_download_link'] = true;
  39.  
  40. /* Code snippets less than this many lines long will not
  41.    get a "View/Download" link attached to them. */
  42. $codeolulator['download_link_minimum_length'] = 4;
  43.  
  44. /* How many spaces makes one tab in your code samples? */
  45. $codeolulator['tab_length'] = 4;
  46.  
  47. /* "View/Download" link.
  48.    Is passed through sprintf(), with %s replaced by the link. */
  49. $codeolulator['download_link_text'] = '<a href="%s">View/Download</a>';
  50.  
  51.  
  52. class Codeolulator {
  53.        
  54.         function register_query_var($vars) {
  55.                 $vars[] = 'code';
  56.                 return $vars;
  57.         }
  58.        
  59.         function post_filter($text) {
  60.                 $code = get_query_var('code');
  61.                 if (empty($code) && strpos($text, '<pre>') !== false) {
  62.                         $text = preg_replace_callback("#<pre>\\s*<code>(.*?)</code>\\s*</pre>#ms", array('Codeolulator', 'post_filter_callback'), $text);
  63.                 }
  64.                 return $text;
  65.         }
  66.        
  67.         function post_filter_callback($matches) {
  68.                 global $codeolulator;
  69.                
  70.                 static $code_snippet_number = 0;
  71.                 $code_snippet_number++;   
  72.                
  73.                 $list = '<ol class="codelist">';
  74.  
  75.                 $lines = preg_split("#\n(?!\\z)#", $matches[1]);
  76.                
  77.                 foreach ($lines as $number => $line) {
  78.                         $type = ($number % 2 == 1) ? 'even' : 'odd';           
  79.                        
  80.                         // convert spaces to tabs
  81.                         $line = str_replace(str_repeat(' ', $codeolulator['tab_length']), "\t", $line);
  82.                                                
  83.                         // If the line is blank, insert a space to prevent collapsing,
  84.                         // otherwise insert the line.
  85.                         if (ltrim($line) == "") {
  86.                                 $list .= "\t" . '<li class="' . $type . '">&nbsp;</li>' . "\n";
  87.                         } else {
  88.                                 $numtabs = strlen($line) - strlen(ltrim($line))// determine the number of tabs
  89.                                 $line = trim($line);                              // trim leading/trailing whitespace
  90.        
  91.                                 $list .= "\t" . '<li class="tab' . $numtabs . ' ' . $type . '"><code>' . $line . '</code></li>' . "\n";
  92.                         }
  93.                        
  94.                 }
  95.                 $list .= "</ol>\n";
  96.  
  97.                
  98.                 if ($codeolulator['show_download_link'] && count($lines) > $codeolulator['download_link_minimum_length']) {
  99.                         $link = get_permalink();
  100.                        
  101.                         if (false === strpos($link, '?'))
  102.                                 $link = trailingslashit($link) . 'code/' . $code_snippet_number;
  103.                         else
  104.                                 $link .= '&code=' . $code_snippet_number;
  105.        
  106.                         $list .= '<div class="sourcelink">' . sprintf($codeolulator['download_link_text'], $link) . "</div>\n";
  107.                 }
  108.                
  109.                 $list = apply_filters('codeolulator_list', $list);
  110.                 return $list;
  111.                
  112.         }
  113.        
  114.         function show_code_snippets() {
  115.                 $code = get_query_var('code');
  116.                
  117.                 if (!empty($code)) {
  118.                        
  119.                         if ( file_exists( TEMPLATEPATH . '/code.php') ) {
  120.                                 load_template( TEMPLATEPATH . '/code.php');
  121.                                 exit;
  122.                         }
  123.                        
  124.                         @header('Content-type: text/plain; charset=utf-8');
  125.                         $snippets = array();
  126.                        
  127.                         // This is overly elaborate for single posts, but I figured I might as well
  128.                         // make it support multiple posts from the start.
  129.                         if (have_posts()) :
  130.                                 while (have_posts()) : the_post();
  131.                                         ob_start();
  132.                                                 the_content();
  133.                                                 $content = ob_get_contents();
  134.                                         ob_end_clean();
  135.                                        
  136.                                         preg_match_all("#<pre>\\s*<code>(.*?)</code>\\s*</pre>#s", html_entity_decode($content), $matches, PREG_PATTERN_ORDER);
  137.                                        
  138.                                         if (isset($matches[1])) $snippets = array_merge($snippets, $matches[1]);
  139.                                                        
  140.                                 endwhile;
  141.                         endif;
  142.                        
  143.                         if ($code == 0)
  144.                                 // don't use implode, sometimes there's only one
  145.                                 foreach ($snippets as $snippet) {
  146.                                         echo "$snippet\n\n";
  147.                                 }
  148.                         else
  149.                                 echo $snippets[$code-1];
  150.  
  151.                         exit;
  152.                 }
  153.         }
  154.  
  155.         function generate_rewrite($wp_rewrite) {
  156.                 // (?:code/)?(code/?|\d+) doesn't work on apache 1.3?
  157.                 // Make the regex stupid.
  158.                 $wp_rewrite->add_rewrite_tag('%code%', 'code/([0-9]+)', "code=");
  159.                 $structure = trailingslashit($wp_rewrite->permalink_structure) . "%code%";
  160.                 $rules = $wp_rewrite->generate_rewrite_rule($structure);
  161.                 foreach ($rules as $match => $redirect) {
  162.                         $match = str_replace(array('(/[0-9]+)?/?$', '/trackback/?$'), '$', $match);
  163.                         $redirect = preg_replace(array("#&tb=1#", "#&page=.[0-9]+#"), '', $redirect);
  164.                         $newrules[$match] = $redirect;
  165.                 }
  166.                 $wp_rewrite->rules += $newrules;
  167.         }
  168. }
  169.  
  170.  
  171.  
  172. add_action('generate_rewrite_rules'array('Codeolulator', 'generate_rewrite'));
  173. add_action('template_redirect', array('Codeolulator', 'show_code_snippets'));
  174.  
  175. add_filter('query_vars', array('Codeolulator', 'register_query_var'));
  176. add_filter('the_content', array('Codeolulator', 'post_filter'), 9);
  177.  
  178. ?>