plugins/GeSHi.php
changeset 1 c715631f809a
parent 0 441963e5b07a
child 2 9e3258dfae15
equal deleted inserted replaced
0:441963e5b07a 1:c715631f809a
       
     1 <?php
       
     2 /*
       
     3 Plugin Name: GeSHi syntax highlighting
       
     4 Plugin URI: http://enanocms.org/GeSHi_support
       
     5 Description: Adds syntax highlighting support using the GeSHi engine.
       
     6 Author: Dan Fuhry
       
     7 Version: 0.1
       
     8 Author URI: http://enanocms.org/
       
     9 */
       
    10 
       
    11 /*
       
    12  * GeSHi highlighting plugin for Enano
       
    13  * Version 0.1
       
    14  * Copyright (C) 2007 Dan Fuhry
       
    15  *
       
    16  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
       
    17  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
       
    18  *
       
    19  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
       
    20  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
       
    21  */
       
    22 
       
    23 global $db, $session, $paths, $template, $plugins; // Common objects
       
    24 $GLOBALS['geshi_supported_formats'] = array(
       
    25     'abap', 'blitzbasic', 'cpp-qt', 'd', 'idl', 'lua', 'ocaml', 'python', 'smalltalk', 'vhdl', 'actionscript', 'bnf', 'csharp',
       
    26     'eiffel', 'ini', 'm68k', 'oobas', 'qbasic', 'smarty', 'visualfoxpro', 'ada', 'caddcl', 'fortran', 'inno', 'matlab',
       
    27     'oracle8', 'rails', 'sql', 'winbatch', 'apache', 'cadlisp', 'css', 'freebasic', 'io', 'mirc', 'pascal', 'reg', 'tcl', 'xml',
       
    28     'applescript', 'cfdg', 'delphi', 'genero', 'java5', 'mpasm', 'perl', 'robots', 'text', 'xpp', 'asm', 'cfm', 'diff', 'gml', 'java',
       
    29     'mysql', 'per', 'ruby', 'thinbasic', 'z80', 'asp', 'c_mac', 'div', 'groovy', 'javascript', 'nsis', 'php-brief', 'sas', 'tsql',
       
    30     'autoit', 'c', 'dos', 'haskell', 'latex', 'objc', 'php', 'scheme', 'vbnet', 'bash', 'cpp', 'dot', 'html', 'lisp',
       
    31     'ocaml-brief', 'plsql', 'sdlbasic', 'vb'
       
    32   );
       
    33 
       
    34 // Knock out the existing <code> tag support
       
    35 $plugins->attachHook('text_wiki_construct', 'geshi_disable_tw_code($this);');
       
    36 
       
    37 function geshi_disable_tw_code($tw)
       
    38 {
       
    39   $tw->disable[] = 'Code';
       
    40   foreach ( $tw->rules as $i => $rule )
       
    41   {
       
    42     if ( $rule == 'Code' )
       
    43     {
       
    44       unset($tw->rules[$i]);
       
    45       return true;
       
    46     }
       
    47   }
       
    48 }
       
    49 
       
    50 // Prevent <code> tags from being stripped or sanitized (the plugin will handle all sanitation)
       
    51 $plugins->attachHook('render_sanitize_pre', 'geshi_strip_code($text, $geshi_code_blocks, $random_id);');
       
    52 $plugins->attachHook('render_sanitize_post', 'geshi_restore_code($text, $geshi_code_blocks, $random_id);');
       
    53 
       
    54 function geshi_strip_code(&$text, &$codeblocks, $random_id)
       
    55 {
       
    56   global $geshi_supported_formats;
       
    57   $codeblocks = array();
       
    58   $sf = '(' . implode('|', $geshi_supported_formats) . ')';
       
    59   preg_match_all('/<code type="?' . $sf . '"?>([\w\W]*?)<\/code>/ms', $text, $matches);
       
    60   
       
    61   // for debug
       
    62   /*
       
    63   if ( strstr($text, '<code type') )
       
    64     die('processing codes: <pre>' . htmlspecialchars(print_r($matches, true)) . '</pre><pre>' . htmlspecialchars($text) . '</pre>' . htmlspecialchars('/<code type="?' . $sf . '"?>([\w\W]*?)<\/code>/'));
       
    65   */
       
    66   
       
    67   foreach ( $matches[0] as $i => $match )
       
    68   {
       
    69     $codeblocks[$i] = array(
       
    70         'match' => $match,
       
    71         'lang' => $matches[1][$i],
       
    72         'code' => $matches[2][$i]
       
    73       );
       
    74     $text = str_replace_once($match, "{GESHI_BLOCK:$i:$random_id}", $text);
       
    75   }
       
    76 }
       
    77 
       
    78 function geshi_restore_code(&$text, &$codeblocks, $random_id)
       
    79 {
       
    80   foreach ( $codeblocks as $i => $match )
       
    81   {
       
    82     $text = str_replace_once("{GESHI_BLOCK:$i:$random_id}", $match['match'], $text);
       
    83   }
       
    84 }
       
    85 
       
    86 // Formatter hook - where the actual highlighting is performed
       
    87 $plugins->attachHook('render_wikiformat_veryearly', 'geshi_strip_code($text, $codeblocks, $random_id);');
       
    88 $plugins->attachHook('render_wikiformat_post', 'geshi_perform_highlight($result, $codeblocks, $random_id);');
       
    89 
       
    90 function geshi_perform_highlight(&$text, &$codeblocks, $random_id)
       
    91 {
       
    92   static $did_header_tweak = false;
       
    93   if ( !$did_header_tweak )
       
    94   {
       
    95     $did_header_tweak = true;
       
    96     global $template;
       
    97     $template->add_header('<style type="text/css">
       
    98       pre.geshi_highlighted {
       
    99         max-height: 1000000px !important;
       
   100       }
       
   101       pre.geshi_highlighted a {
       
   102         background-image: none !important;
       
   103         padding-right: 0 !important;
       
   104       }
       
   105       </style>
       
   106       ');
       
   107   }
       
   108   if ( !defined('GESHI_ROOT') )
       
   109     define('GESHI_ROOT', ENANO_ROOT . '/plugins/geshi/');
       
   110   
       
   111   require_once ( GESHI_ROOT . '/base.php' );
       
   112   
       
   113   foreach ( $codeblocks as $i => $match )
       
   114   {
       
   115     $lang =& $match['lang'];
       
   116     $code =& $match['code'];
       
   117     
       
   118     $geshi = new GeSHi($code, $lang, null);
       
   119     $geshi->set_header_type(GESHI_HEADER_PRE);
       
   120     // $geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS);
       
   121     $geshi->set_overall_class('geshi_highlighted');
       
   122     $parsed = $geshi->parse_code();
       
   123     
       
   124     $text = str_replace_once("{GESHI_BLOCK:$i:$random_id}", $parsed, $text);
       
   125   }
       
   126 }