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 |
?> |