NOT included in any Wikka versionLast edited by
DomBonj:
1.1.6.5 compatibility Fri, 27 Jun 2008 15:53 EDT [
diff]
This is the development page for the Footnote action.
Installation
- Save the first code block below as actions/footnote.php
- Give it the same file permissions as the other php files in that directory
- Add four lines to handlers/page/show.php as shown on the second code block below
- Add the line from the third code block below to css/wikka.css
Code
1. New
actions/footnote.php file
actions/footnote.php
<?php
#
# Manages and displays footnotes on the page
#
# @package Actions
# @name footnote
#
# @authors DomBonj
#
# @version 0.98
#
# @input Parameters = note='text of the note'
#
# @uses Wakka::Action()
# @uses Wakka::FormClose()
# @uses Wakka::FormOpen()
# @uses Wakka::GeSHi_Highlight()
# @uses Wakka::GetConfigValue()
# @uses Wakka::Href()
# @uses Wakka::Link()
# @uses Wakka::ReturnSafeHTML()
# @uses Wakka::htmlspecialchars_ent()
#
// i18n strings
if (!
defined('FN_NOTES')) define('FN_NOTES',
'Notes');
if (!
defined('FN_GO_BACK_MSG')) define('FN_GO_BACK_MSG',
'Jump back to page');
if (!
defined('FN_ERROR_REQUEST_FORMAT')) define ('FN_ERROR_REQUEST_FORMAT',
'Incorrect parameter; usage: %s');
if (!
defined('FN_ERROR_USAGE')) define ('FN_ERROR_USAGE',
"footnote note='note_text'");
if (!
function_exists('FNprint'))
{
function FNerror
($msg) {
return ("<em class='error'>$msg</em><br />");
}
function FNwakka2callback
($things)
// the only change made to this function (from formatters/wakka.php in version 1.1.6.3) is in the processing of $things='closetags':
// instead of directly echoing the HTML closing tags, they are returned as a string
{
$thing =
$things[1];
$result=
'';
static $oldIndentLevel =
0;
static $oldIndentLength=
0;
static $indentClosers =
array();
static $newIndentSpace=
array();
static $br =
1;
static $trigger_bold =
0;
static $trigger_italic =
0;
static $trigger_underline =
0;
static $trigger_monospace =
0;
static $trigger_notes =
0;
static $trigger_strike =
0;
static $trigger_inserted =
0;
static $trigger_deleted =
0;
static $trigger_floatl =
0;
static $trigger_keys =
0;
static $trigger_strike =
0;
static $trigger_inserted =
0;
static $trigger_center =
0;
static $trigger_l =
array(-
1,
0,
0,
0,
0,
0);
static $output =
'';
static $valid_filename =
'';
static $invalid =
'';
global $wakka;
if ((!
is_array($things)) &&
($things ==
'closetags'))
{
// start of changes to standard wakka2callback
$ret =
"";
if ($trigger_strike %
2) $ret .=
('</span>');
if ($trigger_notes %
2) $ret .=
('</span>');
if ($trigger_inserted %
2) $ret .=
('</span>');
if ($trigger_underline %
2) $ret .=
('</span>');
if ($trigger_floatl %
2) $ret .=
('</div>');
if ($trigger_center %
2) $ret .=
('</div>');
if ($trigger_italic %
2) $ret .=
('</em>');
if ($trigger_monospace %
2) $ret .=
('</tt>');
if ($trigger_bold %
2) $ret .=
('</strong>');
for ($i =
1;
$i<=
5;
$i ++
)
if ($trigger_l[$i] %
2) $ret .=
("</h$i>");
$trigger_bold =
$trigger_center =
$trigger_floatl =
$trigger_inserted =
$trigger_deleted =
$trigger_italic =
$trigger_keys =
0;
$trigger_l =
array(-
1,
0,
0,
0,
0,
0);
$trigger_monospace =
$trigger_notes =
$trigger_strike =
$trigger_underline =
0;
return $ret;
// end of changes to standard wakka2callback
}
// convert HTML thingies
if ($thing ==
"<")
return "<";
else if ($thing ==
">")
return ">";
// float box left
else if ($thing ==
"<<")
{
return (++
$trigger_floatl %
2 ?
"<div class=\"floatl\">\n" :
"\n</div>\n");
}
// float box right
else if ($thing ==
">>")
{
return (++
$trigger_floatl %
2 ?
"<div class=\"floatr\">\n" :
"\n</div>\n");
}
// clear floated box
else if ($thing ==
"::c::")
{
return ("<div class=\"clear\"> </div>\n");
}
// keyboard
else if ($thing ==
"#%")
{
return (++
$trigger_keys %
2 ?
"<kbd class=\"keys\">" :
"</kbd>");
}
// bold
else if ($thing ==
"**")
{
return (++
$trigger_bold %
2 ?
"<strong>" :
"</strong>");
}
// italic
else if ($thing ==
"//")
{
return (++
$trigger_italic %
2 ?
"<em>" :
"</em>");
}
// underlinue
else if ($thing ==
"__")
{
return (++
$trigger_underline %
2 ?
"<span class=\"underline\">" :
"</span>");
}
// monospace
else if ($thing ==
"##")
{
return (++
$trigger_monospace %
2 ?
"<tt>" :
"</tt>");
}
// notes
else if ($thing ==
"''")
{
return (++
$trigger_notes %
2 ?
"<span class=\"notes\">" :
"</span>");
}
// strikethrough
else if ($thing ==
"++")
{
return (++
$trigger_strike %
2 ?
"<span class=\"strikethrough\">" :
"</span>");
}
// additions
else if ($thing ==
"££")
{
return (++
$trigger_inserted %
2 ?
"<span class=\"additions\">" :
"</span>");
}
// deletions
else if ($thing ==
"¥¥")
{
return (++
$trigger_deleted %
2 ?
"<span class=\"deletions\">" :
"</span>");
}
// center
else if ($thing ==
"@@")
{
return (++
$trigger_center %
2 ?
"<div class=\"center\">\n" :
"\n</div>\n");
}
// urls
else if (preg_match("/^([a-z]+:\/\/\S+?)([^[:alnum:]^\/])?$/",
$thing,
$matches))
{
$url =
$matches[1];
/* Inline images are disabled for security reason, use {{image action}} #142
But if you still need this functionality, update this file like below
if (preg_match("/\.(gif|jpg|png|svg)$/si", $url)) {
return '<img src="'.$wakka->Link($url).'" alt="image" />'.$wakka->htmlspecialchars_ent($matches[2]);
} else */
// Mind Mapping Mod
if (preg_match("/\.(mm)$/si",
$url)) { #145
return $wakka->
Action("mindmap ".
$url);
} else
return $wakka->
Link($url).
$matches[2];
}
// header level 5
else if ($thing ==
"==")
{
$br =
0;
return (++
$trigger_l[5] %
2 ?
"<h5>" :
"</h5>\n");
}
// header level 4
else if ($thing ==
"===")
{
$br =
0;
return (++
$trigger_l[4] %
2 ?
"<h4>" :
"</h4>\n");
}
// header level 3
else if ($thing ==
"====")
{
$br =
0;
return (++
$trigger_l[3] %
2 ?
"<h3>" :
"</h3>\n");
}
// header level 2
else if ($thing ==
"=====")
{
$br =
0;
return (++
$trigger_l[2] %
2 ?
"<h2>" :
"</h2>\n");
}
// header level 1
else if ($thing ==
"======")
{
$br =
0;
return (++
$trigger_l[1] %
2 ?
"<h1>" :
"</h1>\n");
}
// forced line breaks
else if ($thing ==
"---")
{
return "<br />";
}
// escaped text
else if (preg_match("/^\"\"(.*)\"\"$/s",
$thing,
$matches))
{
$allowed_double_doublequote_html =
$wakka->
GetConfigValue("double_doublequote_html");
if ($allowed_double_doublequote_html ==
'safe')
{
$filtered_output =
$wakka->
ReturnSafeHTML($matches[1]);
return $filtered_output;
}
elseif ($allowed_double_doublequote_html ==
'raw')
{
return $matches[1];
}
else
{
return $wakka->
htmlspecialchars_ent($matches[1]);
}
}
// code text
else if (preg_match("/^\%\%(.*?)\%\%$/s",
$thing,
$matches))
{
$output =
'';
//reinitialize variable
$code =
$matches[1];
// if configuration path isn't set, make sure we'll get an invalid path so we
// don't match anything in the home directory
$geshi_hi_path =
isset($wakka->
config['geshi_languages_path']) ?
$wakka->
config['geshi_languages_path'] :
'/:/';
$wikka_hi_path =
isset($wakka->
config['wikka_highlighters_path']) ?
$wakka->
config['wikka_highlighters_path'] :
'/:/';
// check if a language (and an optional starting line or filename) has been specified
if (preg_match('/^'.PATTERN_OPEN_BRACKET.PATTERN_FORMATTER.PATTERN_LINE_NUMBER.PATTERN_FILENAME.PATTERN_CLOSE_BRACKET.PATTERN_CODE.
'$/s',
$code,
$matches))
{
list
(,
$language, ,
$start, ,
$filename,
$invalid,
$code) =
$matches;
}
// get rid of newlines at start and end (and preceding/following whitespace)
// Note: unlike trim(), this preserves any tabs at the start of the first "real" line
$code =
preg_replace('/^\s*\n+|\n+\s*$/',
'',
$code);
// check if GeSHi path is set and we have a GeSHi highlighter for this language
if (isset($language) &&
isset($wakka->
config['geshi_path']) &&
file_exists($geshi_hi_path.
'/'.
$language.
'.php'))
{
// check if specified filename is valid and generate code block header
if (isset($filename) &&
strlen($filename) >
0 &&
strlen($invalid) ==
0) # TODO: use central regex library for filename validation
{
$valid_filename =
$filename;
// create code block header
$output .=
'<div class="code_header">';
// display filename and start line, if specified
$output .=
$filename;
if (strlen($start)>
0)
{
$output .=
' (line '.
$start.
')';
}
$output .=
'</div>'.
"\n";
}
// use GeSHi for highlighting
$output .=
$wakka->
GeSHi_Highlight($code,
$language,
$start);
}
// check Wikka highlighter path is set and if we have an internal Wikka highlighter
elseif (isset($language) &&
isset($wakka->
config['wikka_formatter_path']) &&
file_exists($wikka_hi_path.
'/'.
$language.
'.php') &&
'wakka' !=
$language)
{
// use internal Wikka highlighter
$output =
'<div class="code">'.
"\n";
$output .=
$wakka->
Format($code,
$language);
$output .=
"</div>\n";
}
// no language defined or no formatter found: make default code block;
// IncludeBuffered() will complain if 'code' formatter doesn't exist
else
{
$output =
'<div class="code">'.
"\n";
$output .=
$wakka->
Format($code,
'code');
$output .=
"</div>\n";
}
// display grab button if option is set in the config file
if ($wakka->
config['grabcode_button'] ==
'1')
{
$output .=
$wakka->
FormOpen("grabcode");
// build form
$output .=
'<input type="submit" class="grabcode" name="save" value="'.GRABCODE_BUTTON_VALUE.
'" title="'.rtrim
(sprintf(GRABCODE_BUTTON_TITLE,
$valid_filename)).
'" />';
$output .=
'<input type="hidden" name="filename" value="'.urlencode
($valid_filename).
'" />';
$output .=
'<input type="hidden" name="code" value="'.urlencode
($code).
'" />';
$output .=
$wakka->
FormClose();
}
// output
return $output;
}
// forced links
// \S : any character that is not a whitespace character
// \s : any whitespace character
else if (preg_match("/^\[\[(\S*)(\s+(.+))?\]\]$/s",
$thing,
$matches)) # recognize forced links across lines
{
list
(,
$url, ,
$text) =
$matches;
if ($url)
{
//if ($url!=($url=(preg_replace("/@@|££||\[\[/","",$url))))$result="</span>";
if (!
$text) $text =
$url;
//$text=preg_replace("/@@|££|\[\[/","",$text);
return $result.
$wakka->
Link($url,
"",
$text);
}
else
{
return "";
}
}
// indented text
elseif (preg_match("/\n([\t~]+)(-|&|([0-9a-zA-ZÄÖÜßäöü]+)\))?(\n|$)/s",
$thing,
$matches))
{
// new line
$result .=
($br ?
"<br />\n" :
"\n");
// we definitely want no line break in this one.
$br =
0;
// find out which indent type we want
$newIndentType =
$matches[2];
if (!
$newIndentType) { $opener =
"<div class=\"indent\">";
$closer =
"</div>";
$br =
1;
}
elseif ($newIndentType ==
"-") { $opener =
"<ul><li>";
$closer =
"</li></ul>";
$li =
1;
}
elseif ($newIndentType ==
"&") { $opener =
"<ul class=\"thread\"><li>";
$closer =
"</li></ul>";
$li =
1;
} #inline comments
else { $opener =
"<ol type=\"".
substr($newIndentType,
0,
1).
"\"><li>";
$closer =
"</li></ol>";
$li =
1;
}
// get new indent level
$newIndentLevel =
strlen($matches[1]);
if ($newIndentLevel >
$oldIndentLevel)
{
for ($i =
0;
$i <
$newIndentLevel -
$oldIndentLevel;
$i++
)
{
$result .=
$opener;
array_push($indentClosers,
$closer);
}
}
else if ($newIndentLevel <
$oldIndentLevel)
{
for ($i =
0;
$i <
$oldIndentLevel -
$newIndentLevel;
$i++
)
{
$result .=
array_pop($indentClosers);
}
}
$oldIndentLevel =
$newIndentLevel;
if (isset($li) && !
preg_match("/".str_replace
(")",
"\)",
$opener).
"$/",
$result))
{
$result .=
"</li><li>";
}
return $result;
}
// new lines
else if ($thing ==
"\n")
{
// if we got here, there was no tab in the next line; this means that we can close all open indents.
$c =
count($indentClosers);
for ($i =
0;
$i <
$c;
$i++
)
{
$result .=
array_pop($indentClosers);
$br =
0;
}
$oldIndentLevel =
0;
$oldIndentLength=
0;
$newIndentSpace=
array();
$result .=
($br ?
"<br />\n" :
"\n");
$br =
1;
return $result;
}
// Actions
else if (preg_match("/^\{\{(.*?)\}\}$/s",
$thing,
$matches))
{
if ($matches[1])
return $wakka->
Action($matches[1]);
else
return "{{}}";
}
// interwiki links!
else if (preg_match("/^[A-ZÄÖÜ][A-Za-zÄÖÜßäöü]+[:]\S*$/s",
$thing))
{
return $wakka->
Link($thing);
}
// wiki links!
else if (preg_match("/^[A-ZÄÖÜ]+[a-zßäöü]+[A-Z0-9ÄÖÜ][A-Za-z0-9ÄÖÜßäöü]*$/s",
$thing))
{
return $wakka->
Link($thing);
}
// separators
else if (preg_match("/-{4,}/",
$thing,
$matches))
{
// TODO: This could probably be improved for situations where someone puts text on the same line as a separator.
// Which is a stupid thing to do anyway! HAW HAW! Ahem.
$br =
0;
return "<hr />\n";
}
// mind map xml
else if (preg_match("/^<map.*<\/map>$/s",
$thing))
{
return $wakka->
Action("mindmap ".
$wakka->
Href().
"/mindmap.mm");
}
// if we reach this point, it must have been an accident.
return $thing;
}
function FNprint
(&
$thisone,
$method,
$note_txt=
'',
$base_url=
'')
{
if (!
isset($footnotes))
{
static $footnotes =
array();
static $footnotesindex;
}
$out =
'';
if ('addnote' ==
$method)
{ // display a single footnote and add it to the page's list of footnotes
$footnotesindex =
($footnotesindex) ?
$footnotesindex+
1 :
1;
// no markup for the 'title' attribute
$title_text =
$thisone->
ReturnSafeHTML(preg_replace("/(\*\*|\'\'|\#\#|\#\%|\+\+|__|\/\/|\[\[|\]\])/ms",
"",
$note_txt));
$out =
"<a href='".
$thisone->
Href().
'#fn' .
$footnotesindex .
"' title='".
$title_text .
"' ><sup id='fnback".
$footnotesindex.
"'>" .
$footnotesindex .
"</sup></a>";
$note_txt =
preg_replace("('|')",
"'",
$note_txt);
$note_txt_raw =
$thisone->
htmlspecialchars_ent($note_txt);
$footnotes[$footnotesindex] =
$note_txt_raw;
}
else if ('list' ==
$method)
{ // display the list of all the page's footnotes
$i =
1;
if (isset($footnotes) && !
empty($footnotes))
{
$out =
"<fieldset class='footnotesbox'><legend> <strong>". FN_NOTES .
' </strong></legend>';
foreach ($footnotes as $note_txt_raw)
{
$out .=
"<a id='fn".
$i.
"' href='".
$base_url .
"#fnback".
$i .
"' class='underline' title='". FN_GO_BACK_MSG .
"'><span class='underline'>".
$i.
"</span></a>: ";
// format the footnote's text
$note_txt =
preg_replace_callback(
"/(".
"\b[a-z]+:\/\/\S+|".
# URL
"\[\[[^\[]*?\]\]|".
# forced link
"\*\*|\'\'|\#\#|\#\%|\+\+|__|\/\/".
# Wiki markup
")/ms",
"FNwakka2callback",
$thisone->
htmlspecialchars_ent($note_txt_raw) );
$out .=
($note_txt . FNwakka2callback
('closetags') .
'<br />');
$i++;
}
$out .=
'</fieldset><br />';
$footnotes =
array();
$footnotesindex =
0;
}
}
else if ('purge' ==
$method)
{ // empty the footnotes array, so they are not displayed at the bottom of the page
$footnotes =
array();
$footnotesindex =
0;
}
// do nothing silently if unknown $method
return $out;
}
} // if !function_exists()
$output =
'';
if (!
isset($vars['note']))
{
$output .= FNerror
(sprintf(FN_ERROR_REQUEST_FORMAT, FN_ERROR_USAGE
));
}
else
{
$output .= FNprint
($this,
'addnote',
$vars['note']);
}
echo $output;
?>
2a. [version 1.1.6.4 only] In
handlers/page/show.php, go to line 80 and replace the following code block:
// display page
echo $this->
Format($this->
page['body'],
'wakka');
echo '<div style="clear: both"></div>'.
"\n";
echo '</div>'.
"\n";
echo '<!--closing page content-->'.
"\n";
with the following code block:
// display page
echo $this->
Format($this->
page['body'],
'wakka');
echo '<div style="clear: both"></div>'.
"\n";
// Footnote action
if (function_exists('FNprint'))
{
echo (FNprint
($this,
'list',
'',
$this->
Href()));
}
echo '</div>'.
"\n";
echo '<!--closing page content-->'.
"\n";
2b. [versions 1.1.6.2 & 1.1.6.3 only] In
handlers/page/show.php, go to line 21 and replace the following code block:
// display page
echo $this->
Format($this->
page['body'],
'wakka');
// if this is an old revision, display some buttons
if ($this->
page['latest'] ==
'N' &&
$this->
HasAccess('write'))
with the following code block:
// display page
echo $this->
Format($this->
page['body'],
'wakka');
// Footnote action
if (function_exists('FNprint')) {
echo (FNprint
($this,
'list',
"",
$this->
Href()));
}
// if this is an old revision, display some buttons
if ($this->
page['latest'] ==
'N' &&
$this->
HasAccess('write'))
3. Add the following line to
css/wikka.css:
.footnotesbox { background-color: #eeeeee; padding: 10px; margin-top: 15px; border: #666666 1px solid; font-size: 0.9em; }
CategoryUsercontributions