Eric Hartwell's InfoDabble

 
Welcome to Eric Hartwell's InfoDabble
About | Site Map
Home Tech Notes Apollo 17: Blue Marble Apollo 17 Flight Journal   Calendars About me  

HowTo: Create a MediaWiki Pretty Printer Extension

By Eric Hartwell - latest revision April 8, 2006

This article describes a pretty printer extension for MediaWiki, the software that runs the various Wikimedia projects.

  • multiple languages, starting with PHP
  • auto-language detection
  • style sheets or inline font
  • braces

WikiMedia Extensions

MediaWiki, the software that runs the various Wikimedia projects, allows developers to write their own extensions to the wiki markup. An extension defines an XML-style tag which can be used in the wiki editor like this:

<tagname attribute="some attribute"> some text </tagname>

The attributes and the text between the tags get passed on to a PHP function you implement. This function can then return a HTML string that gets inserted into the output in place of the tags and text. Note that the return string should be HTML, not wiki markup.

Step 1: Basic PHP Pretty Printer Extension

A pretty printer for PHP is easy to implement in PHP, since the built-in highlight_string function does the parsing and coloring. It doesn't adjust the brackets or spacing, though.

The most basic PrettyPrinter extension simply uses highlight_string to apply HTML formatting to the source text:

<?php
# PrettyPrinter WikiMedia extension
# With WikiMedia's extension mechanism it is possible to define new tags of the form
# <PrettyPrinter> some text </PrettyPrinter>
# The function registered by the extension gets the text between the tags as input and can transform it into arbitrary HTML code.
# Note: The output is not interpreted as WikiText but directly included in the HTML output. So Wiki markup is not supported.
# To activate the extension, include it from your LocalSettings.php with: include("extensions/PrettyPrinter.php");

$wgExtensionFunctions[] = "wfPrettyPrinter";

function
wfPrettyPrinter() {
    global
$wgParser;
    
# Register the extension with the WikiText parser.
    # The first parameter is the name of the new tag. In this case it defines the tag <PrettyPrinter> ... </PrettyPrinter>
    # The second parameter is the callback function for processing the text between the tags
    
$wgParser->setHook( "PrettyPrintert", "renderPrettyPrinter" );
}

# The callback function for converting the input text to HTML output
function renderPrettyPrinterTranscript( $input, $argv ) {
    
# $argv is an array containing any arguments passed to the extension like <example argument="foo" bar>..
    
$output highlight_string( $input, TRUE  );
    return
$output;
}
?>

Install the extension by adding it to the end of your LocalSettings.php file (above the ?>):

include("extensions/PrettyPrinter.php");

Step 2: Smart PHP Pretty Printer Extension

We can considerably improve the utility of the extension by adding a few simple features.

  • The highlight_string() function requires a starting "<?php" and ending "?>" before it will transform the text, but you're more likely to use code snippets in a wiki. If they're missing, the extension automatically adds them before the transform, then strips them from the output.
  • The highlight_string() adds leading and trailing line feeds. The extension removes these.
  • The source language can be specified through the src="" attribute. Theoretically, it could be inferred from the input if not specified.
  • Common HTML tags (div, span, p, pre, code, blockquote) can be specified as attributes. If a value is given for the attribute, it is output as the class. For example,
    <PrettyPrinter span="snippet"> ... </PrettyPrinter>
    wraps the formatted output with
    <span class="snippet"> ... </span>
  • The extension passes unrecognized attribute/value pairs through to the output unchanged: attribute or attribute="value".

<?php

# PrettyPrinter WikiMedia extension
# With WikiMedia's extension mechanism it is possible to define new tags of the form <PrettyPrinter> some text </PrettyPrinter>
# The function registered by the extension gets the text between the tags as input and can transform it into arbitrary HTML code.
# Note: The output is not interpreted as WikiText but directly included in the HTML output. So Wiki markup is not supported.
# To activate the extension, include it from your LocalSettings.php with: include("extensions/PrettyPrinter.php");

$wgExtensionFunctions[] = "wfPrettyPrinter";

function
wfPrettyPrinter() {
    
# Register the extension with the WikiText parser.
    # The first parameter is the name of the new tag. In this case it defines the tag <PrettyPrinter> ... </PrettyPrinter>
    # The second parameter is the callback function for processing the text between the tags
    
    
global $wgParser;
    
$wgParser->setHook( "PrettyPrinter", "renderPrettyPrinter" );
}

# The callback function for converting the input text to HTML output
function renderPrettyPrinter( $input, $argv ) {
    
# $argv is an array containing any arguments passed to the extension like <example argument="foo" bar>..
    
    # default language is php
    
$src = "php";
    
    
    
# Parse the arguments. If there's a parameter for a html tag, translate it to a class: span="code" => span class="code"
    
    
foreach ( $argv as $name=>$value ) {
        
        
# No argument: argument is passed as noarg=noarg
        
if ( $value == $name)    $value = null;
        
        
# Special processing for certain tags
        
switch ( strtolower($name) ) {
            case
"src":
            
$src = $value;
            break;
            
            case
"div":
            case
"span":
            case
"p":
            case
"pre":
            case
"code":
            case
"blockquote":
            if (
$value )    $prefix .= "<" . $name . ' class="' .  $value . '">';
            else        
$prefix .= "<" . $name . ">";
            
$postfix = "</" . $name . ">" . $postfix;
            break;
            
            default:
            
# Unknown tag: pass through unchanged tag=value
            
            
if ( $value )    $prefix .= "<" . $name . '="' . $value . '">';
            else        
$prefix .= "<" . $name . ">";
            
$postfix = "</" . $name . ">" . $postfix;
            break;
        }
    }
    
    
# Language-specific processing
    
switch ($src)
    {
        case
'C':
        case
'c':
        break;
        
        case
'php':
        case
'PHP':
        
# Add ?php prefix and ? suffix if not already there (required for parser)
        
if ( strncmp( ltrim( $input ) , "<?php", 5) != 0) {
            
$strip = true;
            
$input = "<?php\n" . $input . "\n?>";
        }
        
$output .= highlight_string ($input, TRUE );
        if (
$strip)
        {
            
$output = preg_replace( "@<span.*?/span>@", "", $output, 1);
            
$output = preg_replace( "@<br /><br />.*?\?&gt;@", "", $output, 1);
        }
        
$output = str_replace( "\n", "", $output );
        break;
    }
    
    return
$prefix . $output . $postfix;
}

?>

Generic Pretty Printer

Wikipedia points to the open source PrettyPrinter source code formatter/beautifier at BerliOS Developer. It's written in C++, which might be translated to php ...


Revision History

  • April 8, 2006 - initial version
Creative Commons License

Unless otherwise noted, this work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License

 

Site Map | About Me