| 1 |
<?php |
| 2 |
|
| 3 |
class YakkaTextProcessor { |
| 4 |
var $engine; |
| 5 |
|
| 6 |
var $pattern; |
| 7 |
|
| 8 |
var $tagState; |
| 9 |
var $tagCount; |
| 10 |
|
| 11 |
function YakkaTextProcessor(&$engine) { |
| 12 |
$this->engine = &$engine; |
| 13 |
|
| 14 |
$this->pattern = "/(\%\%.*?\%\%|\"\".*?\"\"|\[\[.*?\]\]|<|>|&|\*\*.*?\*\*|\/\/.*?\/\/|__.*?__|\#\#.*?\#\#|======.*?======|=====.*?=====|====.*?====|===.*?===|==.*?==|----|---|\n[\t\|]+(-|[0-9,a-z,A-Z]+\))?|\{\{.*?\}\}|\b[A-Z][A-Z,a-z]+[:]([A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*)\b|\b([A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*)\b|\n)/ms"; |
| 15 |
} |
| 16 |
|
| 17 |
function Process($source) { |
| 18 |
$source = str_replace("\r", "", $source); |
| 19 |
$source = trim($source)."\n"; |
| 20 |
$source = $this->ExecuteBuilder($source); |
| 21 |
$source = preg_replace("/<br \/>$/", "", trim($source)); |
| 22 |
return $source; |
| 23 |
} |
| 24 |
|
| 25 |
|
| 26 |
function ExecuteBuilder($source) { |
| 27 |
return preg_replace_callback($this->pattern, array(&$this, "Build"), $source); |
| 28 |
} |
| 29 |
|
| 30 |
function Build($things) { |
| 31 |
$thing = $things[1]; |
| 32 |
|
| 33 |
static $oldIndentLevel = 0; |
| 34 |
static $indentClosers = array(); |
| 35 |
static $br = 1; |
| 36 |
|
| 37 |
global $wakka; |
| 38 |
|
| 39 |
// convert HTML thingies |
| 40 |
if ($thing == "<") |
| 41 |
return "<"; |
| 42 |
else if ($thing == ">") |
| 43 |
return ">"; |
| 44 |
else if ($thing == "&") |
| 45 |
return "&"; |
| 46 |
// bold |
| 47 |
else if (preg_match("/^\*\*(.*)\*\*$/s", $thing, $matches)) |
| 48 |
{ |
| 49 |
return "<b>".$this->ExecuteBuilder($matches[1])."</b>"; |
| 50 |
} |
| 51 |
// italic |
| 52 |
else if (preg_match("/^\/\/(.*)\/\/$/s", $thing, $matches)) |
| 53 |
{ |
| 54 |
return "<i>".$this->ExecuteBuilder($matches[1])."</i>"; |
| 55 |
} |
| 56 |
// underlinue |
| 57 |
else if (preg_match("/^__(.*)__$/s", $thing, $matches)) |
| 58 |
{ |
| 59 |
return "<u>".$this->ExecuteBuilder($matches[1])."</u>"; |
| 60 |
} |
| 61 |
// monospace |
| 62 |
else if (preg_match("/^\#\#(.*)\#\#$/s", $thing, $matches)) |
| 63 |
{ |
| 64 |
return "<tt>".$this->ExecuteBuilder($matches[1])."</tt>"; |
| 65 |
} |
| 66 |
// headers |
| 67 |
else if (preg_match("/^======(.*)======$/s", $thing, $matches)) |
| 68 |
{ |
| 69 |
$br = 0; |
| 70 |
return "<h1>".$this->ExecuteBuilder($matches[1])."</h1>"; |
| 71 |
} |
| 72 |
else if (preg_match("/^=====(.*)=====$/s", $thing, $matches)) |
| 73 |
{ |
| 74 |
$br = 0; |
| 75 |
return "<h2>".$this->ExecuteBuilder($matches[1])."</h2>"; |
| 76 |
} |
| 77 |
else if (preg_match("/^====(.*)====$/s", $thing, $matches)) |
| 78 |
{ |
| 79 |
$br = 0; |
| 80 |
return "<h3>".$this->ExecuteBuilder($matches[1])."</h3>"; |
| 81 |
} |
| 82 |
else if (preg_match("/^===(.*)===$/s", $thing, $matches)) |
| 83 |
{ |
| 84 |
$br = 0; |
| 85 |
return "<h4>".$this->ExecuteBuilder($matches[1])."</h4>"; |
| 86 |
} |
| 87 |
else if (preg_match("/^==(.*)==$/s", $thing, $matches)) |
| 88 |
{ |
| 89 |
$br = 0; |
| 90 |
return "<h5>".$this->ExecuteBuilder($matches[1])."</h5>"; |
| 91 |
} |
| 92 |
// separators |
| 93 |
else if ($thing == "----") |
| 94 |
{ |
| 95 |
// TODO: This could probably be improved for situations where someone puts text on the same line as a separator. |
| 96 |
// Which is a stupid thing to do anyway! HAW HAW! Ahem. |
| 97 |
$br = 0; |
| 98 |
return "<hr/>"; |
| 99 |
} |
| 100 |
// forced line breaks |
| 101 |
else if ($thing == "---") |
| 102 |
{ |
| 103 |
return "<br />"; |
| 104 |
} |
| 105 |
// escaped text |
| 106 |
else if (preg_match("/^\"\"(.*)\"\"$/s", $thing, $matches)) |
| 107 |
{ |
| 108 |
return $matches[1]; |
| 109 |
} |
| 110 |
// code text |
| 111 |
else if (preg_match("/^\%\%(.*)\%\%$/s", $thing, $matches)) |
| 112 |
{ |
| 113 |
// check if a language has been specified |
| 114 |
$code = $matches[1]; |
| 115 |
if (preg_match("/^\((.+?)\)(.*)$/s", $code, $matches)) |
| 116 |
{ |
| 117 |
list(, $language, $code) = $matches; |
| 118 |
} |
| 119 |
switch ($language) |
| 120 |
{ |
| 121 |
case "php": |
| 122 |
$formatter = "php"; |
| 123 |
break; |
| 124 |
default: |
| 125 |
$formatter = "code"; |
| 126 |
} |
| 127 |
|
| 128 |
$output = "<div class=\"code\">"; |
| 129 |
$output .= "CODE";//$wakka->Format(trim($code), $formatter); |
| 130 |
$output .= "</div>"; |
| 131 |
|
| 132 |
return $output; |
| 133 |
} |
| 134 |
// forced links |
| 135 |
else if (preg_match("/^\[\[(\S*)(\s+(.+))?\]\]$/", $thing, $matches)) |
| 136 |
{ |
| 137 |
list (, $url, , $text) = $matches; |
| 138 |
if ($url) |
| 139 |
{ |
| 140 |
if (!$text) $text = $url; |
| 141 |
return $this->CreateLink($url, "", $text); |
| 142 |
} |
| 143 |
else |
| 144 |
{ |
| 145 |
return ""; |
| 146 |
} |
| 147 |
} |
| 148 |
// indented text |
| 149 |
else if (preg_match("/\n([\t\|]+)(-|([0-9,a-z,A-Z]+)\))?/s", $thing, $matches)) |
| 150 |
{ |
| 151 |
// new line |
| 152 |
$result .= ($br ? "<br />\n" : "\n"); |
| 153 |
|
| 154 |
// we definitely want no line break in this one. |
| 155 |
$br = 0; |
| 156 |
|
| 157 |
// find out which indent type we want |
| 158 |
$newIndentType = $matches[2]; |
| 159 |
if (!$newIndentType) { $opener = "<blockquote>"; $closer = "</blockquote>"; $br = 1; } |
| 160 |
else if ($newIndentType == "-") { $opener = "<ul>"; $closer = "</ul>"; $li = 1; } |
| 161 |
else { $opener = "<ol type=\"".$newIndentType."\">"; $closer = "</ol>"; $li = 1; } |
| 162 |
|
| 163 |
// get new indent level |
| 164 |
$newIndentLevel = strlen($matches[1]); |
| 165 |
if ($newIndentLevel > $oldIndentLevel) |
| 166 |
{ |
| 167 |
for ($i = 0; $i < $newIndentLevel - $oldIndentLevel; $i++) |
| 168 |
{ |
| 169 |
$result .= $opener; |
| 170 |
array_push($indentClosers, $closer); |
| 171 |
} |
| 172 |
} |
| 173 |
else if ($newIndentLevel < $oldIndentLevel) |
| 174 |
{ |
| 175 |
for ($i = 0; $i < $oldIndentLevel - $newIndentLevel; $i++) |
| 176 |
{ |
| 177 |
$result .= array_pop($indentClosers); |
| 178 |
} |
| 179 |
} |
| 180 |
|
| 181 |
$oldIndentLevel = $newIndentLevel; |
| 182 |
|
| 183 |
if ($li) $result .= "<li/>"; |
| 184 |
|
| 185 |
return $result; |
| 186 |
} |
| 187 |
// new lines |
| 188 |
else if ($thing == "\n") |
| 189 |
{ |
| 190 |
// if we got here, there was no tab in the next line; this means that we can close all open indents. |
| 191 |
$c = count($indentClosers); |
| 192 |
for ($i = 0; $i < $c; $i++) |
| 193 |
{ |
| 194 |
$result .= array_pop($indentClosers); |
| 195 |
$br = 0; |
| 196 |
} |
| 197 |
$oldIndentLevel = 0; |
| 198 |
|
| 199 |
$result .= ($br ? "<br />\n" : "\n"); |
| 200 |
$br = 1; |
| 201 |
return $result; |
| 202 |
} |
| 203 |
// events |
| 204 |
else if (preg_match("/^\{\{(.*?)\}\}$/s", $thing, $matches)) |
| 205 |
{ |
| 206 |
if ($matches[1]) |
| 207 |
return $this->engine->runAction($matches[1]); |
| 208 |
else |
| 209 |
return "{{}}"; |
| 210 |
} |
| 211 |
// interwiki links! |
| 212 |
else if (preg_match("/^[A-Z][A-Z,a-z]+[:]([A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*)$/s", $thing)) |
| 213 |
{ |
| 214 |
return $this->CreateLink($thing); |
| 215 |
} |
| 216 |
// wakka links! |
| 217 |
else if (preg_match("/^[A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*$/s", $thing)) |
| 218 |
{ |
| 219 |
return $this->CreateLink($thing); |
| 220 |
} |
| 221 |
// if we reach this point, it must have been an accident. |
| 222 |
return $thing; |
| 223 |
} |
| 224 |
|
| 225 |
function CreateLink($tag, $method = null, $text = null) { |
| 226 |
$track = 1; |
| 227 |
if (!$text) $text = $tag; |
| 228 |
|
| 229 |
// is this an interwiki link? |
| 230 |
if (preg_match("/^([A-Z][A-Z,a-z]+)[:]([A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*)$/", $tag, $matches)) |
| 231 |
{ |
| 232 |
//$tag = $this->GetInterWikiUrl($matches[1], $matches[2]); |
| 233 |
//return "<a href=\"$tag\">$text</a>"; |
| 234 |
return "--interwikiurl--"; |
| 235 |
} |
| 236 |
// is this a full link? ie, does it contain alpha-numeric characters? |
| 237 |
else if (preg_match("/[^[:alnum:]]/", $tag)) |
| 238 |
{ |
| 239 |
// check for email addresses |
| 240 |
if (preg_match("/^.+\@.+$/", $tag)) |
| 241 |
{ |
| 242 |
$tag = "mailto:".$tag; |
| 243 |
} |
| 244 |
// check for protocol-less URLs |
| 245 |
else if (!preg_match("/:/", $tag)) |
| 246 |
{ |
| 247 |
$tag = "http://".$tag; |
| 248 |
} |
| 249 |
return "<a href=\"$tag\">$text</a>"; |
| 250 |
} |
| 251 |
else |
| 252 |
{ |
| 253 |
// it's a Wakka link! |
| 254 |
return ($this->engine->pageStorage->hasPage($tag) ? "<a href=\"".$this->engine->buildCommand($tag, $method)."\">".$text."</a>" : "<span class=\"missingpage\">".$text."<a href=\"".$this->engine->buildCommand($tag, "Create")."\">?</a></span>"); |
| 255 |
} |
| 256 |
} |
| 257 |
|
| 258 |
} |
| 259 |
|
| 260 |
?> |