5.2.20
04/06/20
Last Modified 06/08/07 by Walter Tasin
Horde/WickedAndGeSHi Reload Page

Attachments

 wickedngeshi.tar.gz

Extend Horde's Wicked to Use GeSHi Syntax Highlighter

Introduction

Wicked uses the pear module Text_Wiki for parsing and rendering. There is a <code> directive to do the syntaxhighlighting of code blocks, but this is limited to php and html.
So I searched an easy way make syntax highlighting for other languages inside Horde's beta module "Wicked" possible.
Surfin' around I found the 'Generic Syntaxhighlighter' (aka GeSHi), which allows to integrate syntax highlighting with two simple adapter subclasses for Text_Wiki.

You can find another approach for syntax highlighting by using Text_Highlighter of PEAR at Extend Horde's Wicked to Use PEAR's Text_Highlighter

Requirements

  • a working Horde installation
  • a working Wicked installation (I use here the recent cvs version)
    • of course Text_Wiki installed (here version 1.0.3 is used)
  • a copy of GeSHi (best installed in an additional directory and add this path to your php configuration (i. e. add it to the include_path directive).
    • GeSHi is licensed under the GPL, please refer to GeShi's license for more information.

Installation

Extend Wicked

To extend Wicked you need to download the attached file wickedngeshi.tar.gz.
Untar the package inside the Wicked directory of your Horde installation.
The tarball contains the following files:

  • lib/Text_Wiki/Render/Xhtml/Geshi.php
  • lib/Text_Wiki/Parse/Default/Geshi.php
  • scripts/upgrades/extensions/add_geshi.diff

Now you have to apply the following simple patch to activate the Geshi classes.
<geshi type="diff">--- lib/Page.php 2007-06-08 14:40:06.000000000 +0200

lib/Page.php 2007-06-08 14:41:12.000000000 +0200

@@ -470,6 +470,8 @@
$this->_proc->insertRule('Image2', 'Image');
$this->_proc->deleteRule('Image');
if ($format == 'Default') {

$this->_proc->insertRule('Geshi', 'Code');

$this->_proc->insertRule('Code2', 'Code');
$this->_proc->deleteRule('Code');
@@ -493,6 +495,8 @@

$this->_proc->setRenderConf('Xhtml', 'Wikilink', $linkConf);
$this->_proc->setRenderConf('Xhtml', 'Freelink', $linkConf);

$this->_proc->setRenderConf('Xhtml', 'Geshi',

array('charset' => NLS::getCharset()));

$this->_proc->setRenderConf('Xhtml', 'Toc',
array('title' => '<h2>' . _("Table of C
ontents") . '</h2>'));
$this->_proc->setRenderConf('Xhtml', 'Table',
</geshi>

You can also find this patch inside the tarball (see scripts/upgrades/extensions/add_geshi.diff).

Download GeSHi

You can find the GeSHi package at GeSHi's Sourceforge Site.
Download the latest stable release package (this site uses GeSHi 1.0.7.16)

Untar the package

  • either in your Wicked directory of your Horde installation
    (e.g. /srv/www/horde/wicked)
  • or (the slightly better way) inside an extra directory
    and *add* this directory to the include_path of your php installation.
    (e.g. /php/extra.includes).

Delete unnecessary GeSHi directories

As mentioned at http://qbnz.com/highlighter/geshi-doc.html#installation you should delete all unnecessary directories for a live site due to some security issues.
These are docs/ and contrib/.

Example of an installation

The following step by step installation assumes

  • your Wicked is installed in /srv/www/horde/wicked
  • the tarballs mentioned above are downloaded at /root:
  • the GPL'd GeSHi will be installed in /usr/local/share/php.inc

server:/srv/www/horde/wicked # tar xvzf /root/wickedngeshi.tar.gz
lib/Text_Wiki/Render/Xhtml/Geshi.php
lib/Text_Wiki/Parse/Geshi.php
scripts/upgrades/extensions/
scripts/upgrades/extensions/add_geshi.diff
server:/srv/www/horde/wicked # patch -p0 < scripts/upgrades/extensions/add_geshi.diff
server:/srv/www/horde/wicked # cd /usr/local/share
server:/usr/local/share # md php.inc
server:/usr/local/share/php.inc # tar xvzf /root/GeSHi-1.0.7.16.tar.gz
geshi/
geshi/geshi.php
geshi/geshi/
geshi/geshi/dos.php
geshi/geshi/div.php
geshi/geshi/java.php
geshi/geshi/nsis.php
...
geshi/docs/
geshi/docs/geshi-doc.txt
geshi/docs/TODO
geshi/docs/THANKS
geshi/docs/README
geshi/docs/COPYING
geshi/docs/CHANGES
geshi/docs/BUGS
geshi/docs/geshi-doc.html
geshi/docs/api/
...
geshi/contrib/
geshi/contrib/cssgen.php
geshi/contrib/example.php
server:/usr/local/share/php.inc # rm -rf geshi/docs/
server:/usr/local/share/php.inc # rm -rf geshi/contrib/

Edit your php.ini to add /usr/local/share/php.inc to the include_path entry. Here's an example:

...

;;;;;;;;;;;;;;;;;;;;;;;;;
; Paths and Directories ;
;;;;;;;;;;;;;;;;;;;;;;;;;

; UNIX: "/path1:/path2"
;include_path = ".:/php/includes"

include_path = ".:/usr/share/php:/usr/local/share/php.inc"

; Windows: "\path1;\path2"
;include_path = ".;c:\php\includes"

...

That's all you're done

Usage

The <geshi> parser works like the <code> parser (which still works), except that the type attribute is mandatory.

The type attribute

With the type attribute you specify the language of the inserted code.

You find a list of the supported languages at GeSHi.
The type value is the same as the name of the language file without the .php extension.
You can find the language files in the geshi subdirectory of the geshi installation.

Here a small list of the known language values:
diff, php, c, cpp, java, dos, bash, apache, mysql, perl, vb, ada, java5, pascal, delphi, ...

Don't forget: All attribute values have to be quoted. <geshi type="php">

Input:

<geshi type="diff">--- wicked/lib/Text_Wiki/Render/Xhtml/Url.php    2005-11-19 04:45:46.000000000 +0100

+++  wicked/lib/Text_Wiki/Render/Xhtml/Url.php    2005-12-16 09:14:52.000000000 +0100

@@ -38,7 +38,7 @@
         }
 
         if ($target) {
-            $target = ' target="' . htmlspecialchars($target) . '"';

+             $target = htmlspecialchars($target);

         }
 
         $text = htmlspecialchars($text);
</geshi>

Output:
<geshi type="diff">--- wicked/lib/Text_Wiki/Render/Xhtml/Url.php 2005-11-19 04:45:46.000000000 +0100

wicked/lib/Text_Wiki/Render/Xhtml/Url.php 2005-12-16 09:14:52.000000000 +0100

@@ -38,7 +38,7 @@
}

if ($target) {
- $target = ' target="' . htmlspecialchars($target) . '"';

$target = htmlspecialchars($target);

}

$text = htmlspecialchars($text);
</geshi>

BTW: Parsing a diff file shows up a slightly different result on this site, that's because I have modified Geshi's diff.php to my needs.

The start attribute

For getting an output with line numbers you can use the start attribute.
The given number must be a positive integer value. It defines the start value of the line numbering.

Don't forget: All attribute values have to be quoted. <geshi type="mysql" start="1">

Input:

<geshi type="c" start="1">/* Simple example */
#include <stdio.h>

int main()
{
    printf("Hello world!\ 
 This is only a test\n");
    return 0;
}
</geshi>

Output:
<geshi type="c" start="1">/* Simple example */
#include <stdio.h>

int main()
{ printf("Hello world!\
This is only a test\n");
return 0;
}

</geshi>

Further examples

Input:

<geshi type="cpp" start="161">...
int Screen::GetScreenHeight()
{
        bool bOk;
        int nValue;
        if((bOk=GetScreenInfo()))
          nValue=m_InfoConsole.dwMaximumWindowSize.Y;

        return (bOk) ? nValue : -1;
}

WINDOW Screen::GetVisibleWindow()
{
        WINDOW wValue={-1, -1, -1, -1};
        if((GetScreenInfo()))
          wValue=m_InfoConsole.srWindow;

        return wValue ;
}
...
</geshi>

Output:
<geshi type="cpp" start="161">...
int Screen::GetScreenHeight()
{

bool bOk;
int nValue;
if((bOk=GetScreenInfo()))
nValue=m_InfoConsole.dwMaximumWindowSize.Y;

return (bOk) ? nValue : -1;
}

WINDOW Screen::GetVisibleWindow()
{

WINDOW wValue={-1, -1, -1, -1};
if((GetScreenInfo()))
wValue=m_InfoConsole.srWindow;

return wValue ;
}

...
</geshi>


Input:

<geshi type="mysql">-- $Horde: wicked/scripts/sql/wicked.sql,v 1.4 2005/03/09 18:03:47 eraserhd Exp $

...

CREATE TABLE wicked_attachment_history (
    page_id                 INT NOT NULL,
    attachment_name         VARCHAR(100) NOT NULL,
    attachment_majorversion SMALLINT NOT NULL,
    attachment_minorversion INT NOT NULL,
    attachment_created      INT NOT NULL,
    change_author           VARCHAR(255),
    change_log              TEXT,
--
    PRIMARY KEY (page_id, attachment_name, attachment_majorversion,
                 attachment_minorversion)
);

CREATE INDEX wicked_attachment_history_name_idx ON wicked_attachment_history 
  (page_id, attachment_name);
CREATE INDEX wicked_attachment_history_version_idx ON wicked_attachment_history
  (attachment_majorversion, attachment_minorversion);

GRANT SELECT, INSERT, UPDATE, DELETE ON wicked_pages TO horde;
GRANT SELECT, INSERT, UPDATE, DELETE ON wicked_history TO horde;
GRANT SELECT, INSERT, UPDATE, DELETE ON wicked_attachments TO horde;
GRANT SELECT, INSERT, UPDATE, DELETE ON wicked_attachment_history TO horde;
</geshi>

Output:
<geshi type="mysql">-- $Horde: wicked/scripts/sql/wicked.sql,v 1.4 2005/03/09 18:03:47 eraserhd Exp $

...

CREATE TABLE wicked_attachment_history (
page_id INT NOT NULL,
attachment_name VARCHAR(100) NOT NULL,
attachment_majorversion SMALLINT NOT NULL,
attachment_minorversion INT NOT NULL,
attachment_created INT NOT NULL,
change_author VARCHAR(255),
change_log TEXT,
--
PRIMARY KEY (page_id, attachment_name, attachment_majorversion,
attachment_minorversion)
);

CREATE INDEX wicked_attachment_history_name_idx ON wicked_attachment_history
(page_id, attachment_name);
CREATE INDEX wicked_attachment_history_version_idx ON wicked_attachment_history
(attachment_majorversion, attachment_minorversion);

GRANT SELECT, INSERT, UPDATE, DELETE ON wicked_pages TO horde;
GRANT SELECT, INSERT, UPDATE, DELETE ON wicked_history TO horde;
GRANT SELECT, INSERT, UPDATE, DELETE ON wicked_attachments TO horde;
GRANT SELECT, INSERT, UPDATE, DELETE ON wicked_attachment_history TO horde;
</geshi>


Input:

<geshi type="java" start="1">/*
 * RMIDateCalc.java
 *
 * Created on 20. Januar 2006, 22:28
 *
 */
import java.rmi.*;
 
/**
 * Like DateCalc (only for Remote Method Invocation)
 * @author Tasin
 */
public interface RMIDateCalc extends Remote
{
       public String RMICalculate(int a) throws RemoteException;    
       public String RMICalculate(String algo, int a) throws RemoteException;    
       public String RMICalculate(String codebase, String algo, int a) 
          throws RemoteException;    
}
</geshi>

Output:
<geshi type="java" start="1">/*
* RMIDateCalc.java
*
* Created on 20. Januar 2006, 22:28
*
*/
import java.rmi.*;

/**
* Like DateCalc (only for Remote Method Invocation)
* @author Tasin
*/
public interface RMIDateCalc extends Remote
{ public String RMICalculate(int a) throws RemoteException;
public String RMICalculate(String algo, int a) throws RemoteException;
public String RMICalculate(String codebase, String algo, int a)
throws RemoteException;
}

</geshi>