Extension:GeSHiCodeTag

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual
Crystal Clear action run.png
GeSHiCodeTag

Release status: stable

Implementation Tag
Description A tag to create a syntax-highlighted code using GeSHi
Author(s) Paul Nolasco
paul516@gmail.com
Latest version 1.65 (05/23/2008)
License GPLv3
Download download below
see below for README
Example http://wikics.org/GeshiCodeTag_Demo

Translate the GeSHiCodeTag extension if it is available at translatewiki.net

Check usage and version matrix; code metrics

See also: Extension:SyntaxHighlight GeSHi.

Introduction[edit | edit source]

I've been searching for a good syntax-highlighting code extension for MediaWiki but unfortunately I can't find one that fit my needs. So I decided to just create one myself since I'll also be using it heavily on my site. I also wrote the code as readable and customizale as possible so you can easily extend its features. Feel free to email me for questions/comments/suggestions/errors. Hope you all like my first (and hopefully not the last) MediaWiki extension!

README[edit | edit source]

Features:

  • Two types of code tags: simple and advanced.
  • Ability to list all languages supported by GeSHi.
  • Ability to disable/enable the code tags
  • Extendability and readability of the code.

Requirements:

Tested on: (If you've tested it and it's working on a different version please add it here! Thanks!)

  • MediaWiki 1.19.2, 1.17.0, 1.16.0, 1.15.3, 1.15.0, 1.14.0 1.12.0 1.11.0, 1.10.1, 1.10.0, 1.9.3, 1.9.2, 1.8.2, 1.7.1, 1.6.8, 1.5.8, 1.5.7, 1.5.3 (but see Issues below)
  • GeSHi 1.0.8.4, 1.0.8.3, 1.0.7.22, 1.0.7.21, 1.0.7.20, 1.0.7.19, 1.0.7.17, 1.0.7.12
  • PHP 5.3.9, 5.3.3, 5.3.2, 5.2.5, 5.2.4, 5.2.1, 5.1.4, 5.1.2, 5.04 (for php5.3 see Issues below or Discussion)

Compatibility note: This extension was tested on Media Wiki version 1.13.2 (and 1.14.0) and there were incompatibility problems with the edit screen interface which can easily be fixed with a few minor changes. In the GeshiCodeTag.php file, change the top couple of lines to the following:

<?php
########################
# GeshiCodeTag.php
# Licensed under GPLv3
# by Paul Nolasco
########################
 
// change directory accordingly
include_once('geshi/geshi.php');                       
$languagesPath = "extensions/geshi/geshi";
 
// 1 - ENABLED, 0 - DISABLED
// below line must be set to 0 for MediaWiki version 1.13.2 (and 1.14.0)
$codeTag["simple"] = 0;                       // ex. <php> echo </php> 
$codeTag["advanced"]["mode"] = 1;             // ex. <code php n> echo </php>

So in the above code, the $codeTag["simple"] was set to 0 making <code> in MediaWiki's interface not being interfered with. Then the only change that you will need to keep in mind is that to use GeSHi, you need to use <code php></code> as the other option (above it in the code) will just mess up the MediaWiki interface in a minor way.


Instructions:

  1. Download Geshi, extract it and place the entire folder content under yourWikiSite/extensions/
  2. Copy the GeshiCodeTag Source below and save it as GeshiCodeTag.php (Note: Be sure to change the $languagesPath depending on the path of your Geshi extension)
  3. Place GeshiCodeTag.php to yourWikiSite/extensions/
  4. Add the include tag below prior to the variable $wgSiteName in yourWikiSite/LocalSettings.php
## GeshiCodeTag extension
include "extensions/GeshiCodeTag.php";

That's it! Copy the "Tag Examples" below to see if it's working correctly

Usage[edit | edit source]

There are two code tags that you can use:

  1. Simple Tag Format: <'languages'>source code here</'language'>
  2. Advanced Tag Format: <code ['language'|list] [n] >source code here</code>


Tag Examples

- simple code tag
<php> echo "Hello World"; </php>


- advanced code tag
<code php> echo "Hello World"; </code>


- advanced code tag with line numbers
<code php n> echo "Hello World"; </code>


- default code tag
<code> echo "Hello World"; </code>


- display a list of supported languages
<code list></code>


- if invalid language argument, return the language list
<code invalid> echo "Hello World"; </code>


DEMO:
https://www.cs.colostate.edu/wiki/Test_GeSHiCodeTag

GeSHiCodeTag Source[edit | edit source]

<?php
########################
# GeshiCodeTag.php
# Licensed under GPLv3
# by Paul Nolasco
########################

// change directory accordingly
include_once('geshi/geshi.php');                       
$languagesPath = "extensions/geshi/geshi";
 
// 1 - ENABLED, 0 - DISABLED
$codeTag["simple"] = 1;                       // ex. <php> echo </php> 
$codeTag["advanced"]["mode"] = 1;             // ex. <code php n> echo </php>
 
// extra options
/*	
	strict mode - http://qbnz.com/highlighter/geshi-doc.html#using-strict-mode
	ex. <img src="<?php echo rand(1, 100) ?>" /> 
*/
$codeTag["advanced"]["strict"] = 0;			  
 
#############################################

$wgExtensionFunctions[] = "ExtensionCodeTag";
$wgExtensionCredits['parserhook'][] = array( 
        'name' => 'GeSHiCodeTag', 
        'author' => 'Paul Nolasco', 
        'version' => '1.65',
        'description' => 'A tag to create a syntax-highlighted code using GeSHi',
        'url' => 'http://www.mediawiki.org/wiki/Extension:GeSHiCodeTag'
);
$languages = array();
 
function ExtensionCodeTag()
{
        global $wgParser, $codeTag, $languages, $languagesPath;
 
        ReadLanguages();
 
        if($codeTag["advanced"]["mode"])
                $wgParser->setHook('code', 'AdvancedCodeTag');
 
        if($codeTag["simple"])
                foreach($languages as $lang)
                {
                     $wgParser->setHook($lang,
                                   create_function( '$source',
                                        '$geshi = new GeSHi($source,\'' . $lang . '\', \'' . $languagesPath . '\');
                                         return $geshi->parse_code();'
                     ));
                }       
}
 
function ReadLanguages()
{       
        global $languages, $languagesPath;
 
        $dirHandle = opendir($languagesPath) 
                        or die("ERROR: Invalid directory path - [$languagesPath], Modify the value of \$languagesPath'");
 
        $pattern = "^(.*)\.php$";
 
        while ($file = readdir($dirHandle))     
        {       
                if( eregi($pattern, $file) )                            
                        $languages[] = eregi_replace($pattern, "\\1", $file); 
        }
        closedir($dirHandle);
}
 
function AdvancedCodeTag ($source, $settings){          
 
        global $languages, $languagesPath, $codeTag;
        $language = array_shift($settings);      // [arg1]      
 
        // [arg1]
        if($language == '')
          $language='text';                         
 
        if($language == "list")                                                 // list all languages supported
            return "<br>List of supported languages for <b>Geshi " . GESHI_VERSION  . "</b>:<br>"
                   . implode("<br>", $languages);
 
        if($language != "" && !in_array($language, $languages))          // list languages if invalid argument
            return "<br>Invalid language argument, \"<b>" . $language . "</b>\", select one from the list:<br>" 
                   . implode("<br>", $languages);
 
        // set geshi
        $geshi = new GeSHi(trim($source), $language, $languagesPath); 
        $geshi->enable_strict_mode($codeTag["advanced"]["strict"]);        
 
 
        // [arg2 or more]
        if(in_array('n',$settings))                                                  // display line numbers
            $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS);
 
	/*
           Add more GeSHi features from [ http://qbnz.com/highlighter/geshi-doc.html  ]
           template:
		  if( in_array( '<PARAMETER NAME>', $settings ) )
		  {
			$geshi-><GESHI FUNCTION CALL>
		  }
        */
                                                                     // removes newlines replaces with <br />
        return str_replace("\n",'<br />', $geshi->parse_code());     
}

ChangeLog[edit | edit source]

  • Added 'version' and 'description' in the extension details. (as suggested by Servel333 in the discussion) --Paul516 04:06, 24 May 2008 (UTC)
  • Added changes suggested by Jonyo in the Discussion. It allows GeshiCodeTag to be interleaved with a list. --Paul516 08:17, 9 May 2007 (UTC)
  • Add default language "text" to satisfy legacy wiki code with <code>-tag. --Mstolt 08:18, 11 April 2007 (UTC)
  • Removed strict mode in the default settings. --Paul516 18:31, 10 November 2006 (UTC)
  • Added strict mode by default to Advanced Mode of GeshiCodeTag --Paul516 04:31, 16 September 2006 (UTC)
  • Trims whitespace at beginning and end of the source code. --Paul516 09:00, 10 September 2006 (UTC)
  • Added feature: If a user enters an invalid language argument it'll return a list of the supported languages. --Paul516 05:59, 1 September 2006 (UTC)



Todo List[edit | edit source]

  • Create a MediaWiki toolbar icon for GeshiCodeTag and show how to add it.

Added Features[edit | edit source]

Highlighting entire articles[edit | edit source]

A GeSHiCodeTag hack by Nad, see OrganicDesign:GeSHi for more details

The only problem with the code-wrapped-in-tags solution is that articles containing code that is to be directly executed can't include GeSHi code tags without violating the language's syntax rules, but this problem can be easily fixed by a quick hack that we use on our wiki which I've included below.

Another problem is that we'd often like the ability to use MediaWiki templates even if the content is code, for example when defining LocalSettings articles by transcluding various extension code from other articles. So I've also added an extra line of code into the GeSHi extension before it parses the content to achieve this:

The syntax[edit | edit source]

The hack allows template syntax to be used to make the entire article be rendered by the GeSHi parser. The templates expand to nothing, so they can be placed anywhere in the article without affecting its execution (if the raw article is requested, templates=expand will need to be included in the query-string to make the template reduce to nothing). It's probably best to put the template in a comment so that the execution is not affected even if templates do not expand. Here's an example:

# {{perl}}
print "bar";

Implementing the hack[edit | edit source]

First add a few extra lines after the GeSHi include statement to allow the tags to be added before parsing if a language template is transcluded. Here's the updated include line:

include 'extensions/GeSHiCodeTag.php';
$wgHooks['ParserBeforeStrip'][] = 'GeSHi';
function GeSHi( &$parser, &$text, &$strip_state ) {
	if ( preg_match( '/\\{\\{(php|perl|c|actionscript|javascript|css)\\}\\}/i', $text, $m ) ) {
		$text = "<$m[1]>\n$text\n</$m[1]>";
	}
	return true;
}

Templates or variables must be added which expand to nothing so they don't render as a red link, (my ones look like this example). Also an extra line must be added to the GeSHiCodeTag.php file just before the geshi object is instantiated in the hook function to force the templates to expand.

Change the following block of code:

create_function( '$source',
                           '$geshi = new GeSHi($source,' . $lang . ', $languagesPath);
                           return $geshi->parse_code();'
                    ));

to

create_function( '$source',
                           '$source = trim($GLOBALS["wgParser"]->replaceVariables($source)); #<- This line has been added
                           $geshi = new GeSHi($source,' . $lang . ', $languagesPath);
                           return $geshi->parse_code();'
                    ));

Issues[edit | edit source]

  • In MediaWiki 1.5.3 the active links to keywords are followed by the "external link" icon which makes the code hard to read. To suppress the icons, replace the two occurrences of
with


  • MediaWiki version less than 1.5 will only work in Simple Mode since older versions don't accept arguments in tags
  • MediaWiki versions (1.5.3, 1.5.7, 1.8.3, 1.9.2, 1.12.0, 1.16.0 and probably others) - the "div.php" lang definition errantly highlights the MediaWiki copyrightwarning system message and other text in <div></div> tags.
    • The easiest fix is to delete the div.php language module from the geshi installation folder, or to rename it e.g. to div.php_
    • Alternatively, the extension code can be modified by removing "div" from the list of languages used in "simple" mode. If you need to highlight "div" code you can use the "advanced" syntax <code div> Edit the extension as follows:
      • Find the line in the ExtensionCodeTag() functions that reads: $wgParser->setHook($lang,
      • Add a new line before that line that reads if($lang != 'div') {
      • Add a } to the end of the function. (NOTE: this should really go after the call to setHook, but the way the code is formatted that is a bit tricky to see.
      • Below is the full text of the function as it was after I modified it.
function ExtensionCodeTag() {
        global $wgParser, $codeTag, $languages, $languagesPath;
 
        ReadLanguages();
 
        if($codeTag["advanced"]["mode"])
                $wgParser->setHook('code', 'AdvancedCodeTag');
 
        if($codeTag["simple"])
                foreach($languages as $lang)
                {
 
                        if($lang != 'div')
                         {
                        $wgParser->setHook($lang,
                                   create_function( '$source',
                                        '$geshi = new GeSHi($source,\'' . $lang . '\', $languagesPath);
                                         return $geshi->parse_code();'
 
                     ));}
                }
}
  • For PHP 5.3 support some small changes needed. Changed function could be seen in discussion.

Discussion[edit | edit source]

Extension talk:GeSHiCodeTag for any questions/comments/suggestions regarding GeSHiCodeTag

Language: English  • русский