Extension talk:GeSHiHighlight
Any user names refer to users of that site, who are not necessarily users of MediaWiki.org (even if they share the same username).
The instructions state
Don't forget to include GeSHi also: <php>include_once("geshi.php");</php>
But it doesn't say WHERE to include this. Any ideas? Geshi seems to be working even though I skipped that particular instruction, except for some problems with the display of the text below the text entry area (where it says DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!)
bad displayed page
editI changed the code a bit, with this you don't need to rename anything.
# you want to change the below three lines define("GESHI_PATH","../../include/geshi/geshi");// definition where are stored geshi language parsing files require_once(GESHI_PATH."/../geshi.php"); // i assume geshi.php is in the parent directory of the language files define("_LANG_DEFAULT", "java"); # ok, end of editing :)
function wfSyntaxExtension() { global $wgParser, $lang_default; $langArray = geshi_list_languages(GESHI_PATH); foreach ( $langArray as $lang ){ if ($lang == "") continue; $wgParser->setHook('code='.$lang, create_function( '$text', '$geshi = new GeSHi(rtrim(ltrim($text,"\n\r")), ' ."$lang". ', GESHI_PATH); return $geshi->parse_code();' ) ); } $wgParser->setHook('code', create_function( '$text', '$geshi = new GeSHi(rtrim(ltrim($text,"\n\r")), _LANG_DEFAULT, GESHI_PATH); return $geshi->parse_code();' ) ); }
With this, you can either use <code></code> for the default language or <code=language></code=language> to specify a language.
Camel Case Option
editFor languages that are not case sensitive it is nevertheless nice to grant a uniform way of casing keywords through a whole wiki. A GeSHi language file could define a number of keywords written in camel case: for example GetType, SetRecord....
Users often do not comply to the standards and write with mixed case: gETtype, setrEcord.... It doesn't look nice, even if the code might be nevertheless valid.
The patch below defines a new constant in geshi.php: GESHI_CAPS_REPLACE and implements it for replacing the keywords with the corresponding word found in the stored array.
In the geshi.php file find the declaration of the capitalization constants:
// Capatalisation constants /** Lowercase keywords found */ define('GESHI_CAPS_NO_CHANGE', 0); /** Uppercase keywords found */ define('GESHI_CAPS_UPPER', 1); /** Leave keywords found as the case that they are */ define('GESHI_CAPS_LOWER', 2);
add the following line:
define('GESHI_CAPS_REPLACE', 3);
Find the function function change_case ($instr)
and replace it with the following:
function change_case ($instr) { if ($this->language_data['CASE_KEYWORDS'] == GESHI_CAPS_UPPER) { return strtoupper($instr); } elseif ($this->language_data['CASE_KEYWORDS'] == GESHI_CAPS_LOWER) { return strtolower($instr); /************************ * Orso B. Schmid 01 Jan 2007 * added support for camelCase keywords: * the found keywords will be replaced with the items of the array */ } elseif ($this->language_data['CASE_KEYWORDS'] == GESHI_CAPS_REPLACE) { foreach ($this->language_data['KEYWORDS'] as $nr => $wordset) { $allwords = explode(' ', strtolower(implode(' ', $wordset))); if (in_array(strtolower($instr), $allwords)) { return $wordset[array_search(strtolower($instr), $allwords)]; } } } /************************ */ return $instr; }
The new option should be called in the language file(s):
$language_data = array ( ... 'CASE_KEYWORDS' => GESHI_CAPS_REPLACE, .... )
Real code tag support
editThe code tag is not truly supported under the last stable version of GeSHi, currently 1.0.7.16. Whatever you do, the code tag converts into block (turns into pre in the html), upsetting a whole wiki content, moreover the classes are not applied to it. It is probably useless, since GeSHi will be updated soon, but there is a fast fix for displaying code tags correctly as inline elements and classes be applied.
In order to achieve this you can modify geshi.php 1.0.7.16:
- add a new html container: new constant: GESHI_HEADER_CODE
- update the function
function set_header_type ($type)
- Implement the constant in the function
function header ()
- Implement the constant in the function
function footer ()
- Note
- this patch in only tested for the version 1.0.7.16!
Add a new constant GESHI_HEADER_CODE
editFind the line where the html containers are defined: // Container HTML type
and add the following line:
define('GESHI_HEADER_CODE', 3);
Update header type
editFind the function function set_header_type ($type)
and replace the line
if (GESHI_HEADER_DIV != $type && GESHI_HEADER_PRE != $type && GESHI_HEADER_NONE != $type) {
with the line:
if (GESHI_HEADER_DIV != $type && GESHI_HEADER_PRE != $type && GESHI_HEADER_NONE != $type && GESHI_HEADER_CODE != $type) {
Implement in the function 'header'
editFind the function function header ()
and replace the block:
// Work out what to return and do it if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { if ($this->header_type == GESHI_HEADER_PRE) { return "<pre$attributes>$header<ol$ol_attributes>"; } elseif ($this->header_type == GESHI_HEADER_DIV) { return "<div$attributes>$header<ol$ol_attributes>"; } } else { if ($this->header_type == GESHI_HEADER_PRE) { return "<pre$attributes>$header"; } elseif ($this->header_type == GESHI_HEADER_DIV) { return "<div$attributes>$header"; } }
With the block:
// Work out what to return and do it if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { if ($this->header_type == GESHI_HEADER_PRE) { return "<pre$attributes>$header<ol$ol_attributes>"; } elseif ($this->header_type == GESHI_HEADER_DIV) { return "<div$attributes>$header<ol$ol_attributes>"; } } else { if ($this->header_type == GESHI_HEADER_PRE) { return "<pre$attributes>$header"; } elseif ($this->header_type == GESHI_HEADER_DIV) { return "<div$attributes>$header"; } # Orso B. Schmid 01 Jan 2007: fast fix for <code> tag: elseif ($this->header_type == GESHI_HEADER_CODE) { return "<code$attributes>$header"; } }
Implement in the function 'footer'
editFind the function function footer ()
and replace the block:
if ($this->header_type == GESHI_HEADER_DIV) { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { return "</ol>$footer_content</div>"; } return "$footer_content</div>"; } else { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { return "</ol>$footer_content<//pre>"; } return "$footer_content<//pre>"; }
with the block:
if ($this->header_type == GESHI_HEADER_DIV) { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { return "</ol>$footer_content</div>"; } return "$footer_content</div>"; } elseif ($this->header_type == GESHI_HEADER_PRE) { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { return "</ol>$footer_content<//pre>"; } return "$footer_content<//pre>"; } # Orso B. Schmid 01 Jan 2007: fast fix for <code> tag: else { return "$footer_content</code>"; }
Please replace the // with / in the pre tag! It seems that it is not possible to escape an ending pre tag within a pre tag!!!!!
Use the constant GESHI_HEADER_CODE
editNow you can call your GeSHi objects in GeSHihiglight as follows, specifying GESHI_HEADER_CODE for code tags elements. In the example below two new tags are created for every installed language file: a code=... and a pre=... tag. For all created geshi objects classes are enabled. Remove what you don't need. Or add other options as explained in the official GeSHi documentation
You can use pre or div or now code according to your needs. If you specify a default for code it remains now inline.
It is advisable to remove unused language files.
function wfSyntaxExtension() { global $wgParser, $lang_default; $langArray = geshi_list_languages(GESHI_PATH); foreach ( $langArray as $lang ){ if ($lang == "") continue; # use GESHI_HEADER_CODE to preserve inline code. $wgParser->setHook('code='.$lang, create_function( '$text', '$geshi = new GeSHi(rtrim(ltrim($text,"\n\r")), ' ."$lang". ', GESHI_PATH); $geshi->set_header_type(GESHI_HEADER_CODE); $geshi->enable_classes(true); return $geshi->parse_code();' ) ); # use GESHI_HEADER_PRE or GESHI_HEADER_DIV for block elements. $wgParser->setHook('pre='.$lang, create_function( '$text', '$geshi = new GeSHi(rtrim(ltrim($text,"\n\r")), ' ."$lang". ', GESHI_PATH); $geshi->set_header_type(GESHI_HEADER_PRE); $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS, 1); $geshi->enable_classes(true); return $geshi->parse_code();' ) ); } $wgParser->setHook('code', create_function( '$text', '$geshi = new GeSHi(rtrim(ltrim($text,"\n\r")), _LANG_DEFAULT, GESHI_PATH); $geshi->set_header_type(GESHI_HEADER_CODE); $geshi->enable_classes(true); return $geshi->parse_code();' ) ); }
I'm no PHP programmer, so the patch most likely can be optimized. It works fine under MediaWiki 1.8.2.
Note that the above conversation may have been edited or added to since the transfer. If in doubt, check the edit history.
How to enable download of the embedded code
editI extended GeSHiHighlight so that each code fragment can be given a button to download it as a file. You can see an example on page http://freeplane.sourceforge.net/wiki/index.php/Scripting:_Example_scripts .
Following modifications are required:
file download.php
with following content should be uploaded into extensions/geshi
<?php
header("Pragma: no-cache");
header("Expires: 0");
if (isset($_POST["text"]) && isset($_POST["filename"])) {
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=" . $_POST["filename"]);
echo urldecode($_POST["text"]);
}
else{
echo "Data not found";
}
?>
File GeSHiHighlight.php
is modified to consider the new argument
function wfSyntaxExtension() {
global $wgParser, $wgVersion;
$langArray = array(...);
if ( version_compare( $wgVersion, "1.5" ) >= 0 ) {
//If version 1.5 or above, $attrib param is included
foreach ( $langArray as $lang ){
$wgParser->setHook( $lang, create_function( '$text,$attrib',
'return wfSyntaxCode("' . $lang . '", $text, $attrib);'));
$wgParser->setHook( $lang.'-file', create_function( '$file_name,$attrib',
'return wfSyntaxFile("' . $lang . '", $file_name);'));
}
} else {
foreach ( $langArray as $lang ){
$wgParser->setHook( $lang, create_function( '$text',
'return wfSyntaxCode("' . $lang . '", $text, array());'));
$wgParser->setHook( $lang.'-file', create_function( '$file_name',
'return wfSyntaxFile("' . $lang . '", $file_name);'));
}
}
}
function wfSyntaxCode($lang, $text, $args) {
global $wgScriptPath;
$trimmedText = trim($text);
$geshi = new GeSHi($trimmedText, $lang, "extensions/geshi");
$html = wfSyntaxDefaults($geshi);
if(isset($args["name"])){
$encodedText = urlencode($trimmedText);
$filename = $args["name"]. "." . $lang;
$form = <<<EOFORM
<p></p><code>$filename</code></p>
<form action="$wgScriptPath/extensions/geshi/download.php" method="post">
<input type="hidden" name="text" value="$encodedText" />
<input type="hidden" name="filename" value="$filename" />
<input type="submit" value="download script" />
</form>
EOFORM;
return $form.$html;
}
else{
return $html;
}
}