Revision [20644]
This is an old revision of CKeditor4Wikka made by MaiGre on 2009-05-20 04:16:09.
CKeditor as Wikka Editor
The new 3.x WYSIWYG Html editor by Frederico Caldeira Knabbe is about to be released : http://ckeditor.com/
&i will wait for the final release to finish this project, because there is for the moment no documentation,
&and i need to configure a little bit more ckeditor, to get for example and not
&and also to configure the filemanager.
This project - CKeditor (renamed from FCKeditor since 3.0) - is a complete editor with filemanager.
It allows to edit page as a rich document, and ouput it as Html.
This is a mature project (waiting for the 3.0 release) and it works well.
FCK team has already start a mod of the editor (version 2.6) to have wikitext output for MediWiki,
so i decided to start a CKeditor4Wikka project.
The big difference with the FCK+MediaWiki project is that
i didn't want to change anything in the FCK core because this project change really often
so i would like to have a combo that we can easily update from both sides (Wikka and CK).
Example : CKeditor 3.0 will be radically different than FCKeditor 2.x :)
So CKeditor will run normally with HTML output, but i am working on a formatter
that translate common html output into Wikka-wikitext.
This is fckoutput.php and it is use when saving the page.
When starting edition, we need also Html to feed the editor with the current state of the page.
I did a modification of the usual wakka.php formatter, in order to desactivate some translations
as actions (the editor doesn't need included actions).
This is fckinput.php and it is use when entering the Edit mode.
I began to learn Regexp since yesterday so my formatter is not optimized (i ask for your help...)
But it seems to work :)
-> Demo ici : http:/easywikka.wickedfondation.fr/
As the final content is saved as wikitext, we can easily switch between WikiEdit and CKeditor.
You can of course use Wikitext syntax in Html mode !
Not all features are implemented, here is the TODO list :
- normal list is not perfect
- numbered list are not supported yet
- thread-class list neither
- stuffs using actions like Tables, Colored Text, Pictures.. but i'm working on (and i'm waiting fo Wikka 1.7 table's !)
- stuffs using the CSS like floats
- MindMap not tested (actually i don't realy know it..)
- Code
There is also features from CKeditor not supported by Wikka (that can be hack by creating new actions!)
- right align
- justify
- anchor
- flash
- font
- text-size
- background-color
The TODO list features are still available if you choose WikiEdit editor mode
but it will not have an effect in CKeditor. You will see it with wikitext syntax.
You can find here the edit.php hack to include CKeditor,
fckinput.php : the wakka light formatter (on editor start up)
fckoutput.php : the reverse html2wikitext formatter (before saving in database)
I started this yesterday (19 april 2009) so it's definitly just a start,
but i think i need advices to clean and optimize this code!
send corrections, remarks, feedbacks, tips, ideas ! :)
Install
- create a directory /handlers/page/ckeditor/ and unzip files from http://ckeditor.com/
- copy both fckinput.php and fckoutput.php into /formatters/
- hack /handlers/page/edit.php :
REPLACE in /handlers/page/edit.php - line 271
$output .=
$this->FormOpen('edit').
'<input type="hidden" name="previous" value="'.$previous.'" />'."\n".
// We need to escape ALL entity refs before display so we display them _as_ entities instead of interpreting them
// hence hsc_secure() instead of htmlspecialchars_ent() which UNescapes entities!
// JW/2007-02-20: why is this? wouldn't it be easier for the person editing to show actual characters instead of entities?
'<div id="textarea_container">'."\n".
'<textarea id="body" name="body" rows="100" cols="20">'.$this->hsc_secure($body).'</textarea>'."\n". #427
'</div>'."\n";
$output .=
$this->FormOpen('edit').
'<input type="hidden" name="previous" value="'.$previous.'" />'."\n".
// We need to escape ALL entity refs before display so we display them _as_ entities instead of interpreting them
// hence hsc_secure() instead of htmlspecialchars_ent() which UNescapes entities!
// JW/2007-02-20: why is this? wouldn't it be easier for the person editing to show actual characters instead of entities?
'<div id="textarea_container">'."\n".
'<textarea id="body" name="body" rows="100" cols="20">'.$this->hsc_secure($body).'</textarea>'."\n". #427
'</div>'."\n";
WITH :
$output .=
$this->FormOpen('edit').
'<input type="hidden" name="previous" value="'.$previous.'" />'."\n";
$linkCK = explode('&editor=',$_SERVER["REQUEST_URI"]);
if($_GET['editor'] == 'wikiedit')
{
//classic WikiEdit
$output .=
'switch to <input type="button" onCLick=\'javascript:document.location="'.$linkCK[0].'&editor=ckeditor"\'
value="CKeditor mode"> (unsaved changes will be lost)'."\n".
'<div id="textarea_container">'."\n".
'<textarea id="body" name="body" rows="100" cols="20">'.$this->hsc_secure($body).'</textarea>'."\n". #427
'</div>'."\n";
}
else
{
//CKeditor !
$output .=
'switch to <input type="button" onCLick=\'javascript:document.location="'.$linkCK[0].'&editor=wikiedit"\'
value="WikiEdit edit"> (unsaved changes will be lost)'."\n".
'<script type="text/javascript" src="handlers/page/ckeditor/ckeditor.js"></script>'."\n".
'<div id="textarea_container">'."\n".
'<textarea name="body">'.$this->Format($body,'fckinput').'</textarea>'."\n".
'</div>'."\n".
'<script type="text/javascript"> CKEDITOR.replace( \'body\' ) </script>';
//end CKeditor !
}
$output .=
$this->FormOpen('edit').
'<input type="hidden" name="previous" value="'.$previous.'" />'."\n";
$linkCK = explode('&editor=',$_SERVER["REQUEST_URI"]);
if($_GET['editor'] == 'wikiedit')
{
//classic WikiEdit
$output .=
'switch to <input type="button" onCLick=\'javascript:document.location="'.$linkCK[0].'&editor=ckeditor"\'
value="CKeditor mode"> (unsaved changes will be lost)'."\n".
'<div id="textarea_container">'."\n".
'<textarea id="body" name="body" rows="100" cols="20">'.$this->hsc_secure($body).'</textarea>'."\n". #427
'</div>'."\n";
}
else
{
//CKeditor !
$output .=
'switch to <input type="button" onCLick=\'javascript:document.location="'.$linkCK[0].'&editor=wikiedit"\'
value="WikiEdit edit"> (unsaved changes will be lost)'."\n".
'<script type="text/javascript" src="handlers/page/ckeditor/ckeditor.js"></script>'."\n".
'<div id="textarea_container">'."\n".
'<textarea name="body">'.$this->Format($body,'fckinput').'</textarea>'."\n".
'</div>'."\n".
'<script type="text/javascript"> CKEDITOR.replace( \'body\' ) </script>';
//end CKeditor !
}
the fckinput.php file :
<?php
/** fckinput.php
* /formatters/
* Wikka Formatting Engine
* Mod of the wakka.php formatter to feed FCKeditor input html
*
* -> disable mindmap
* -> disable code // TODO: enable CODE!
* -> disable literal
* -> disable action
* -> enable action only for image - waiting for a better image support :)
* -> disable InterWiki
* -> disable urls
*
* by Thomas Bohl - MaiGre
*
*/
// i18n strings
if (!defined('GRABCODE_BUTTON_VALUE')) define('GRABCODE_BUTTON_VALUE', 'Grab');
if (!defined('GRABCODE_BUTTON_TITLE')) define('GRABCODE_BUTTON_TITLE', 'Download %s');
// code block patterns
if (!defined('PATTERN_OPEN_BRACKET')) define('PATTERN_OPEN_BRACKET', '\(');
if (!defined('PATTERN_FORMATTER')) define('PATTERN_FORMATTER', '([^;\)]+)');
if (!defined('PATTERN_LINE_NUMBER')) define('PATTERN_LINE_NUMBER', '(;(\d*?))?');
if (!defined('PATTERN_FILENAME')) define('PATTERN_FILENAME', '(;([^\)\x01-\x1f\*\?\"<>\|]*)([^\)]*))?');
if (!defined('PATTERN_CLOSE_BRACKET')) define('PATTERN_CLOSE_BRACKET', '\)');
if (!defined('PATTERN_CODE')) define('PATTERN_CODE', '(.*)');
// Note: all possible formatting tags have to be in a single regular expression for this to work correctly.
if (!function_exists("wakka2callback")) # DotMG [many lines] : Unclosed tags fix!
{
function wakka2callback($things)
{
$thing = $things[1];
$result='';
$valid_filename = '';
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 $invalid = '';
static $curIndentType;
global $wakka;
if ((!is_array($things)) && ($things == 'closetags'))
{
if ($trigger_strike % 2) echo ('</span>');
if ($trigger_notes % 2) echo ('</span>');
if ($trigger_inserted % 2) echo ('</div>');
if ($trigger_deleted % 2) echo ('</div>');
if ($trigger_underline % 2) echo('</span>');
if ($trigger_floatl % 2) echo ('</div>');
if ($trigger_center % 2) echo ('</div>');
if ($trigger_italic % 2) echo('</em>');
if ($trigger_monospace % 2) echo('</tt>');
if ($trigger_bold % 2) echo('</strong>');
for ($i = 1; $i<=5; $i ++)
if ($trigger_l[$i] % 2) echo ("</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;
}
// 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 ? "<u>" : "</u>");
}
// 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 ? "<strike>" : "</strike>");
}
// additions
else if ($thing == "££")
{
return (++$trigger_inserted % 2 ? "<ins>" : "</ins>");
}
// deletions
else if ($thing == "¥¥")
{
return (++$trigger_deleted % 2 ? "<del>" : "</del>");
}
// center
else if ($thing == "@@")
{
return (++$trigger_center % 2 ? "<div style=\"text-align: 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
$link = $wakka->Link($url);
if(isset($matches[2])) $link .= $matches[2];
return $link;
}
// 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))
{//"\{\{.*?\}\}|". # action
$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
//deleted
// 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
{
if (isset($matches[1])) // url?
{
//if ($url!=($url=(preg_replace("/@@|££||\[\[/","",$url))))$result="</span>";
$text = '';
$url = $matches[1];
if (isset($matches[3])) $text = $matches[3]; // forced link title
//$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[3];
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
{
if (ereg('[0-9]', $newIndentType[0])) { $newIndentType = '1'; }
elseif (ereg('[IVX]', $newIndentType[0])) { $newIndentType = 'I'; }
elseif (ereg('[ivx]', $newIndentType[0])) { $newIndentType = 'i'; }
elseif (ereg('[A-Z]', $newIndentType[0])) { $newIndentType = 'A'; }
elseif (ereg('[a-z]', $newIndentType[0])) { $newIndentType = 'a'; }
$opener = '<ol type="'.$newIndentType.'"><li>';
$closer = '</li></ol>';
$li = 1;
}
// get new indent level
$newIndentLevel = strlen($matches[2]);
if (($newIndentType != $curIndentType) && ($oldIndentLevel > 0))
{
for (; $oldIndentLevel > $newIndentLevel; $oldIndentLevel --)
{
$result .= array_pop($indentClosers);
}
}
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>";
}
$curIndentType = $newIndentType;
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;
}
}
$text = str_replace("\r\n", "\n", $text);
// replace 4 consecutive spaces at the beginning of a line with tab character
// $text = preg_replace("/\n[ ]{4}/", "\n\t", $text); // moved to edit.php
//if ($this->method == "show") $mind_map_pattern = "<map.*?<\/map>|"; else $mind_map_pattern = "";
$text = preg_replace_callback(
"/(".
//"\"\".*z\"\"|". # literal
//$mind_map_pattern.
"\[\[[^\[]*?\]\]|". # forced link
"-{4,}|---|". # separator (hr)
//"\b[a-z]+:\/\/\S+|". # URL
"\*\*|\'\'|\#\#|\#\%|@@|::c::|\>\>|\<\<|££|¥¥|\+\+|__|<|>|\/\/|". # Wiki markup
"======|=====|====|===|==|". # headings
"(^|\n)([\t~]+)(-(?!-)|&|([0-9]+|[a-zA-Z]+)\))?|". # indents and lists
//"\{\{.*?\}\}|". # action
"\{\{image.*?\}\}|". # action image
//"\b[A-ZÄÖÜ][A-Za-zÄÖÜßäöü]+[:](?![=_])\S*\b|". # InterWiki link
"\b([A-ZÄÖÜ]+[a-zßäöü]+[A-Z0-9ÄÖÜ][A-Za-z0-9ÄÖÜßäöü]*)\b|". # CamelWords
"\n". # new line
")/ms", "wakka2callback", $text."\n"); #append \n (#444)
// we're cutting the last <br />
$text = preg_replace("/<br \/>$/","", $text);
echo ($text);
wakka2callback('closetags');
?>
/** fckinput.php
* /formatters/
* Wikka Formatting Engine
* Mod of the wakka.php formatter to feed FCKeditor input html
*
* -> disable mindmap
* -> disable code // TODO: enable CODE!
* -> disable literal
* -> disable action
* -> enable action only for image - waiting for a better image support :)
* -> disable InterWiki
* -> disable urls
*
* by Thomas Bohl - MaiGre
*
*/
// i18n strings
if (!defined('GRABCODE_BUTTON_VALUE')) define('GRABCODE_BUTTON_VALUE', 'Grab');
if (!defined('GRABCODE_BUTTON_TITLE')) define('GRABCODE_BUTTON_TITLE', 'Download %s');
// code block patterns
if (!defined('PATTERN_OPEN_BRACKET')) define('PATTERN_OPEN_BRACKET', '\(');
if (!defined('PATTERN_FORMATTER')) define('PATTERN_FORMATTER', '([^;\)]+)');
if (!defined('PATTERN_LINE_NUMBER')) define('PATTERN_LINE_NUMBER', '(;(\d*?))?');
if (!defined('PATTERN_FILENAME')) define('PATTERN_FILENAME', '(;([^\)\x01-\x1f\*\?\"<>\|]*)([^\)]*))?');
if (!defined('PATTERN_CLOSE_BRACKET')) define('PATTERN_CLOSE_BRACKET', '\)');
if (!defined('PATTERN_CODE')) define('PATTERN_CODE', '(.*)');
// Note: all possible formatting tags have to be in a single regular expression for this to work correctly.
if (!function_exists("wakka2callback")) # DotMG [many lines] : Unclosed tags fix!
{
function wakka2callback($things)
{
$thing = $things[1];
$result='';
$valid_filename = '';
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 $invalid = '';
static $curIndentType;
global $wakka;
if ((!is_array($things)) && ($things == 'closetags'))
{
if ($trigger_strike % 2) echo ('</span>');
if ($trigger_notes % 2) echo ('</span>');
if ($trigger_inserted % 2) echo ('</div>');
if ($trigger_deleted % 2) echo ('</div>');
if ($trigger_underline % 2) echo('</span>');
if ($trigger_floatl % 2) echo ('</div>');
if ($trigger_center % 2) echo ('</div>');
if ($trigger_italic % 2) echo('</em>');
if ($trigger_monospace % 2) echo('</tt>');
if ($trigger_bold % 2) echo('</strong>');
for ($i = 1; $i<=5; $i ++)
if ($trigger_l[$i] % 2) echo ("</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;
}
// 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 ? "<u>" : "</u>");
}
// 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 ? "<strike>" : "</strike>");
}
// additions
else if ($thing == "££")
{
return (++$trigger_inserted % 2 ? "<ins>" : "</ins>");
}
// deletions
else if ($thing == "¥¥")
{
return (++$trigger_deleted % 2 ? "<del>" : "</del>");
}
// center
else if ($thing == "@@")
{
return (++$trigger_center % 2 ? "<div style=\"text-align: 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
$link = $wakka->Link($url);
if(isset($matches[2])) $link .= $matches[2];
return $link;
}
// 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))
{//"\{\{.*?\}\}|". # action
$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
//deleted
// 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
{
if (isset($matches[1])) // url?
{
//if ($url!=($url=(preg_replace("/@@|££||\[\[/","",$url))))$result="</span>";
$text = '';
$url = $matches[1];
if (isset($matches[3])) $text = $matches[3]; // forced link title
//$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[3];
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
{
if (ereg('[0-9]', $newIndentType[0])) { $newIndentType = '1'; }
elseif (ereg('[IVX]', $newIndentType[0])) { $newIndentType = 'I'; }
elseif (ereg('[ivx]', $newIndentType[0])) { $newIndentType = 'i'; }
elseif (ereg('[A-Z]', $newIndentType[0])) { $newIndentType = 'A'; }
elseif (ereg('[a-z]', $newIndentType[0])) { $newIndentType = 'a'; }
$opener = '<ol type="'.$newIndentType.'"><li>';
$closer = '</li></ol>';
$li = 1;
}
// get new indent level
$newIndentLevel = strlen($matches[2]);
if (($newIndentType != $curIndentType) && ($oldIndentLevel > 0))
{
for (; $oldIndentLevel > $newIndentLevel; $oldIndentLevel --)
{
$result .= array_pop($indentClosers);
}
}
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>";
}
$curIndentType = $newIndentType;
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;
}
}
$text = str_replace("\r\n", "\n", $text);
// replace 4 consecutive spaces at the beginning of a line with tab character
// $text = preg_replace("/\n[ ]{4}/", "\n\t", $text); // moved to edit.php
//if ($this->method == "show") $mind_map_pattern = "<map.*?<\/map>|"; else $mind_map_pattern = "";
$text = preg_replace_callback(
"/(".
//"\"\".*z\"\"|". # literal
//$mind_map_pattern.
"\[\[[^\[]*?\]\]|". # forced link
"-{4,}|---|". # separator (hr)
//"\b[a-z]+:\/\/\S+|". # URL
"\*\*|\'\'|\#\#|\#\%|@@|::c::|\>\>|\<\<|££|¥¥|\+\+|__|<|>|\/\/|". # Wiki markup
"======|=====|====|===|==|". # headings
"(^|\n)([\t~]+)(-(?!-)|&|([0-9]+|[a-zA-Z]+)\))?|". # indents and lists
//"\{\{.*?\}\}|". # action
"\{\{image.*?\}\}|". # action image
//"\b[A-ZÄÖÜ][A-Za-zÄÖÜßäöü]+[:](?![=_])\S*\b|". # InterWiki link
"\b([A-ZÄÖÜ]+[a-zßäöü]+[A-Z0-9ÄÖÜ][A-Za-z0-9ÄÖÜßäöü]*)\b|". # CamelWords
"\n". # new line
")/ms", "wakka2callback", $text."\n"); #append \n (#444)
// we're cutting the last <br />
$text = preg_replace("/<br \/>$/","", $text);
echo ($text);
wakka2callback('closetags');
?>
fckoutput.php
<?php
/** fckoutput.php
* /formatters/
* Wikka un-Formatting Engine
* Mod of the wakka.php formatter to transform hmtl from FCKeditor output to wikitext !
*
* TODO: For WikiEdit support -> colored text action, numered list, thread list, tables, mindmap, code, literal
* TODO: For CKeditor support -> colored text, right align, justify, anchor, image, flash, tables, fonts, text-size, background color
*
*
*
*
* by Thomas Bohl - MaiGre
*
*/
// i18n strings
if (!defined('GRABCODE_BUTTON_VALUE')) define('GRABCODE_BUTTON_VALUE', 'Grab');
if (!defined('GRABCODE_BUTTON_TITLE')) define('GRABCODE_BUTTON_TITLE', 'Download %s');
// code block patterns
if (!defined('PATTERN_OPEN_BRACKET')) define('PATTERN_OPEN_BRACKET', '\(');
if (!defined('PATTERN_FORMATTER')) define('PATTERN_FORMATTER', '([^;\)]+)');
if (!defined('PATTERN_LINE_NUMBER')) define('PATTERN_LINE_NUMBER', '(;(\d*?))?');
if (!defined('PATTERN_FILENAME')) define('PATTERN_FILENAME', '(;([^\)\x01-\x1f\*\?\"<>\|]*)([^\)]*))?');
if (!defined('PATTERN_CLOSE_BRACKET')) define('PATTERN_CLOSE_BRACKET', '\)');
if (!defined('PATTERN_CODE')) define('PATTERN_CODE', '(.*)');
if (!function_exists("html2wikitext"))
{
function html2wikitext($things)
{
$thing = $things[1];
$result='';
$valid_filename = '';
static $openedDIV = array();
static $openedSPAN = array();
global $wakka;
// TODO : close wikiTag !
/*if ((!is_array($things)) && ($things == 'closetags'))
{
if ($trigger_strike % 2) echo ('</span>');
if ($trigger_notes % 2) echo ('</span>');
if ($trigger_inserted % 2) echo ('</div>');
if ($trigger_deleted % 2) echo ('</div>');
if ($trigger_underline % 2) echo('</span>');
if ($trigger_floatl % 2) echo ('</div>');
if ($trigger_center % 2) echo ('</div>');
if ($trigger_italic % 2) echo('</em>');
if ($trigger_monospace % 2) echo('</tt>');
if ($trigger_bold % 2) echo('</strong>');
for ($i = 1; $i<=5; $i ++)
if ($trigger_l[$i] % 2) echo ("</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;
}
*/
//close current div
if ($thing == '</div>')
{
if(count($openedDIV[0]) >= 1) return array_shift($openedDIV);
else return $thing;
}
else if ($thing == '</span>')
{
if(count($openedSPAN[0]) >= 1) return array_shift($openedSPAN);
else return $thing;
}
else if ($thing == "<div>")
{
array_unshift($openedDIV,"\n");
return "";
}
// separator
else if ($thing == "<hr />")
return "----\n";
else if (preg_match("/^<\/?strong>$/i", $thing))
return "**";
else if (preg_match("/^<\/?em>$/i", $thing))
return "//";
else if (preg_match("/^<\/?tt>$/i", $thing))
return "##";
else if (($thing == '</kbd>')||($thing == '<kbd class="keys">'))
return "#%";
else if ((preg_match("/^<div style=\"text-align: ?center;\">$/i", $thing)))
{
array_unshift($openedDIV,"@@\n");
return '@@';
}
else if ((preg_match("/^<div style=\"margin-left: ?[2-5]0px;\">$/i", $thing)))
{
array_unshift($openedDIV,"\n");
return "\t";
}
else if ($thing == "<div class=\"clear\"> <\/div>")
return "::c::";
else if (preg_match("/^<div class=\"floatl\">$/i", $thing))
{
array_unshift($openedDIV,"<<\n");
return '<<';
}
else if (preg_match("/^<div class=\"floatr\">$/i", $thing))
{
array_unshift($openedDIV,">>\n");
return '>>';
}
else if (preg_match("#<\/?ins>#", $thing))
return "££";
else if (preg_match("#<\/?del>#", $thing))
return "¥¥";
else if (preg_match("/^<span class=\"strikethrough\">$/i", $thing,$matches))
{
array_unshift($openedSPAN,"++");
return '++';
}
else if (preg_match("/^<span class=\"underline\">$/i", $thing,$matches))
{
array_unshift($openedSPAN,"__");
return '__';
}
else if (preg_match("/^<span class=\"notes\">$/i", $thing,$matches))
{
array_unshift($openedSPAN,"''");
return "''";
}
else if (preg_match("/^<\/?h([1-5])>$/i", $thing, $matches))
{
if (preg_match("#\/#", $thing)) $break = "\n";
else $break = "";
if($matches[1] == 5) return '=='.$break;
else if($matches[1] == 4) return '==='.$break;
else if($matches[1] == 3) return '===='.$break;
else if($matches[1] == 2) return '====='.$break;
else if($matches[1] == 1) return '======'.$break;
}
else if (preg_match("/^<div class=\"indent\">$/i", $thing,$matches))
{
array_unshift($openedDIV,"\n");
return "\t~- ";
}
else if (preg_match("/^<\/?ul>$/i", $thing))
return "";
else if ($thing == "<li>")
return "\t~- ";
else if ($thing == "</li>")
return "\n";
else if (preg_match("/^<a .*href=[\"'](.+)[\"'](.*)>(.*)<\/a>$/i", $thing,$matches))
{
//CamelLinks
if (stripos($matches[1],$wakka->config['base_url']) !== FALSE)
{
$camel = explode($wakka->config['base_url'],$matches[1]);
$camel = explode('/',$camel[1]);
//forced CamelLink?
if($matches[3] == $camel[0]) return $camel[0];
else return '[['.$camel[0].' '.$matches[3].']]';
}
//normal links
if ($matches[3] == $matches[1]) return '[['.$matches[1].']]';
else return '[['.$matches[1].' '.$matches[3].']]';
}
else if ($thing == "<br />")
return "\n";
else if (preg_match("/^<\/?u>$/i", $thing))
return "__";
else if (preg_match("/^<\/?strike>$/i", $thing))
return "++";
// if we reach this point, it must have been an accident.
return 'bordel';
}
}
$text = str_replace("\n", "", $text);
$text = str_replace("\t", "", $text);
$text = str_replace("<p", "<div", $text);
$text = str_replace("</p>", "</div>", $text);
$text = preg_replace_callback(
"/(".
//stuff from fckinput.php formatter
"<hr \/>|". # separator
"<\/?strong>|".
"<\/?em>|".
"<\/?tt>|".
"<kbd class=\"keys\">|<\/kbd>|".
"<div style=\"text-align: ?center;\">|".
"<div class=\"clear\"> <\/div>|".
"<div class=\"floatr\">|".
"<div class=\"floatl\">|".
"<\/?ins>|".
"<\/?del>|".
"<span class=\"strikethrough\">|".
"<span class=\"underline\">|".
"<span class=\"notes\">|". # Wiki markup
"<\/?h[1-5]>|". # headings
"<div class=\"indent\">|".
"<\/?ul>|". # indents simplified..
"<li>|".
"<\/li>|".
"<a (.*)href=[\"'].+[\"'].*>(.*)<\/a>|". # links
"<br \/>|".
"<\/div>|". # new line
"<\/span>|".
//additional stuff from CKeditor AND wikka actions
"<div style=\"margin-left: ?[2-5]0px;\">|". #tab
"<div>|".
"<\/?u>|".
"<\/?strike>".
//"<img(.*)\/>". # action image
")/msi", "html2wikitext", $text);
echo ($text);
//html2wikitext('closetags');
?>
/** fckoutput.php
* /formatters/
* Wikka un-Formatting Engine
* Mod of the wakka.php formatter to transform hmtl from FCKeditor output to wikitext !
*
* TODO: For WikiEdit support -> colored text action, numered list, thread list, tables, mindmap, code, literal
* TODO: For CKeditor support -> colored text, right align, justify, anchor, image, flash, tables, fonts, text-size, background color
*
*
*
*
* by Thomas Bohl - MaiGre
*
*/
// i18n strings
if (!defined('GRABCODE_BUTTON_VALUE')) define('GRABCODE_BUTTON_VALUE', 'Grab');
if (!defined('GRABCODE_BUTTON_TITLE')) define('GRABCODE_BUTTON_TITLE', 'Download %s');
// code block patterns
if (!defined('PATTERN_OPEN_BRACKET')) define('PATTERN_OPEN_BRACKET', '\(');
if (!defined('PATTERN_FORMATTER')) define('PATTERN_FORMATTER', '([^;\)]+)');
if (!defined('PATTERN_LINE_NUMBER')) define('PATTERN_LINE_NUMBER', '(;(\d*?))?');
if (!defined('PATTERN_FILENAME')) define('PATTERN_FILENAME', '(;([^\)\x01-\x1f\*\?\"<>\|]*)([^\)]*))?');
if (!defined('PATTERN_CLOSE_BRACKET')) define('PATTERN_CLOSE_BRACKET', '\)');
if (!defined('PATTERN_CODE')) define('PATTERN_CODE', '(.*)');
if (!function_exists("html2wikitext"))
{
function html2wikitext($things)
{
$thing = $things[1];
$result='';
$valid_filename = '';
static $openedDIV = array();
static $openedSPAN = array();
global $wakka;
// TODO : close wikiTag !
/*if ((!is_array($things)) && ($things == 'closetags'))
{
if ($trigger_strike % 2) echo ('</span>');
if ($trigger_notes % 2) echo ('</span>');
if ($trigger_inserted % 2) echo ('</div>');
if ($trigger_deleted % 2) echo ('</div>');
if ($trigger_underline % 2) echo('</span>');
if ($trigger_floatl % 2) echo ('</div>');
if ($trigger_center % 2) echo ('</div>');
if ($trigger_italic % 2) echo('</em>');
if ($trigger_monospace % 2) echo('</tt>');
if ($trigger_bold % 2) echo('</strong>');
for ($i = 1; $i<=5; $i ++)
if ($trigger_l[$i] % 2) echo ("</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;
}
*/
//close current div
if ($thing == '</div>')
{
if(count($openedDIV[0]) >= 1) return array_shift($openedDIV);
else return $thing;
}
else if ($thing == '</span>')
{
if(count($openedSPAN[0]) >= 1) return array_shift($openedSPAN);
else return $thing;
}
else if ($thing == "<div>")
{
array_unshift($openedDIV,"\n");
return "";
}
// separator
else if ($thing == "<hr />")
return "----\n";
else if (preg_match("/^<\/?strong>$/i", $thing))
return "**";
else if (preg_match("/^<\/?em>$/i", $thing))
return "//";
else if (preg_match("/^<\/?tt>$/i", $thing))
return "##";
else if (($thing == '</kbd>')||($thing == '<kbd class="keys">'))
return "#%";
else if ((preg_match("/^<div style=\"text-align: ?center;\">$/i", $thing)))
{
array_unshift($openedDIV,"@@\n");
return '@@';
}
else if ((preg_match("/^<div style=\"margin-left: ?[2-5]0px;\">$/i", $thing)))
{
array_unshift($openedDIV,"\n");
return "\t";
}
else if ($thing == "<div class=\"clear\"> <\/div>")
return "::c::";
else if (preg_match("/^<div class=\"floatl\">$/i", $thing))
{
array_unshift($openedDIV,"<<\n");
return '<<';
}
else if (preg_match("/^<div class=\"floatr\">$/i", $thing))
{
array_unshift($openedDIV,">>\n");
return '>>';
}
else if (preg_match("#<\/?ins>#", $thing))
return "££";
else if (preg_match("#<\/?del>#", $thing))
return "¥¥";
else if (preg_match("/^<span class=\"strikethrough\">$/i", $thing,$matches))
{
array_unshift($openedSPAN,"++");
return '++';
}
else if (preg_match("/^<span class=\"underline\">$/i", $thing,$matches))
{
array_unshift($openedSPAN,"__");
return '__';
}
else if (preg_match("/^<span class=\"notes\">$/i", $thing,$matches))
{
array_unshift($openedSPAN,"''");
return "''";
}
else if (preg_match("/^<\/?h([1-5])>$/i", $thing, $matches))
{
if (preg_match("#\/#", $thing)) $break = "\n";
else $break = "";
if($matches[1] == 5) return '=='.$break;
else if($matches[1] == 4) return '==='.$break;
else if($matches[1] == 3) return '===='.$break;
else if($matches[1] == 2) return '====='.$break;
else if($matches[1] == 1) return '======'.$break;
}
else if (preg_match("/^<div class=\"indent\">$/i", $thing,$matches))
{
array_unshift($openedDIV,"\n");
return "\t~- ";
}
else if (preg_match("/^<\/?ul>$/i", $thing))
return "";
else if ($thing == "<li>")
return "\t~- ";
else if ($thing == "</li>")
return "\n";
else if (preg_match("/^<a .*href=[\"'](.+)[\"'](.*)>(.*)<\/a>$/i", $thing,$matches))
{
//CamelLinks
if (stripos($matches[1],$wakka->config['base_url']) !== FALSE)
{
$camel = explode($wakka->config['base_url'],$matches[1]);
$camel = explode('/',$camel[1]);
//forced CamelLink?
if($matches[3] == $camel[0]) return $camel[0];
else return '[['.$camel[0].' '.$matches[3].']]';
}
//normal links
if ($matches[3] == $matches[1]) return '[['.$matches[1].']]';
else return '[['.$matches[1].' '.$matches[3].']]';
}
else if ($thing == "<br />")
return "\n";
else if (preg_match("/^<\/?u>$/i", $thing))
return "__";
else if (preg_match("/^<\/?strike>$/i", $thing))
return "++";
// if we reach this point, it must have been an accident.
return 'bordel';
}
}
$text = str_replace("\n", "", $text);
$text = str_replace("\t", "", $text);
$text = str_replace("<p", "<div", $text);
$text = str_replace("</p>", "</div>", $text);
$text = preg_replace_callback(
"/(".
//stuff from fckinput.php formatter
"<hr \/>|". # separator
"<\/?strong>|".
"<\/?em>|".
"<\/?tt>|".
"<kbd class=\"keys\">|<\/kbd>|".
"<div style=\"text-align: ?center;\">|".
"<div class=\"clear\"> <\/div>|".
"<div class=\"floatr\">|".
"<div class=\"floatl\">|".
"<\/?ins>|".
"<\/?del>|".
"<span class=\"strikethrough\">|".
"<span class=\"underline\">|".
"<span class=\"notes\">|". # Wiki markup
"<\/?h[1-5]>|". # headings
"<div class=\"indent\">|".
"<\/?ul>|". # indents simplified..
"<li>|".
"<\/li>|".
"<a (.*)href=[\"'].+[\"'].*>(.*)<\/a>|". # links
"<br \/>|".
"<\/div>|". # new line
"<\/span>|".
//additional stuff from CKeditor AND wikka actions
"<div style=\"margin-left: ?[2-5]0px;\">|". #tab
"<div>|".
"<\/?u>|".
"<\/?strike>".
//"<img(.*)\/>". # action image
")/msi", "html2wikitext", $text);
echo ($text);
//html2wikitext('closetags');
?>