]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/transform.php
added Neil Brown's nested-DefinitionLists patch -- slightly modified
[SourceForge/phpwiki.git] / lib / transform.php
1 <!-- $Id: transform.php,v 1.2 2000-10-11 14:08:56 ahollosi Exp $ -->
2 <?php
3    // expects $pagehash and $html to be set
4
5    // Set up inline links and images
6    for ($i = 1; $i < (NUM_LINKS + 1); $i++) {
7       if (! empty($pagehash['refs'][$i])) {
8          if (preg_match("/png$/i", $pagehash['refs'][$i])) {
9             // embed PNG images
10             $embedded[$i] = "<img src='" . $pagehash['refs'][$i] . "'>";
11          } else {
12             // ordinary embedded link
13             $embedded[$i] = "<a href='" . $pagehash['refs'][$i] . "'>[$i]</a>";
14          }
15       }
16    }
17
18    $numlines = count($pagehash["content"]);
19
20    // only call these once, for efficiency
21    $quick_search_box  = RenderQuickSearch();
22    $full_search_box   = RenderFullSearch();
23    $most_popular_list = RenderMostPopular();
24
25
26
27    // Loop over all lines of the page and apply transformation rules
28    for ($index = 0; $index < $numlines; $index++) {
29       unset($tokens);
30       unset($replacements);
31       $ntokens = 0;
32       
33       $tmpline = $pagehash["content"][$index];
34
35       if (!strlen($tmpline) || $tmpline == "\r") {
36          // this is a blank line, send <p>
37          $html .= SetHTMLOutputMode("p", ZERO_DEPTH, 0);
38          continue;
39       }
40
41 /* If your web server is not accessble to the general public, you may
42 allow this code below, which allows embedded HTML. If just anyone can reach
43 your web server it is highly advised that you do not allow this.
44
45       elseif (preg_match("/(^\|)(.*)/", $tmpline, $matches)) {
46          // HTML mode
47          $html .= SetHTMLOutputMode("", ZERO_DEPTH, 0);
48          $html .= $matches[2];
49          continue;
50       }
51 */
52
53
54       //////////////////////////////////////////////////////////
55       // New linking scheme: links are in brackets. This will
56       // emulate typical HTML linking as well as Wiki linking.
57
58       // match anything between brackets except only numbers
59       // trying: 
60       $numBracketLinks = preg_match_all("/\[.+?\]/", $tmpline, $brktlinks);
61       /* On 12 Jul,2000 Jeff <dairiki@dairiki.org> adds:
62        *
63        * Simple sorting doesnt work, since (in ASCII) '[' comes between
64        * the upper- and lower-case characters.
65        *
66        * Using sort "[[Link] [Link]" will come out wrong, using
67        * rsort "[[link] [link]" will come out wrong.
68        * (An appropriate usort would work.)
69        *
70        * I've added a look-behind assertion to the preg_replace which,
71        * I think, fixes the problem.  I only hope that all PHP versions
72        * support look-behind assertions....
73       // sort instead of rsort or "[[link] [link]" will be rendered wrong.
74       sort($brktlinks[0]);
75       reset($brktlinks[0]);
76        */
77
78       for ($i = 0; $i < $numBracketLinks; $i++) {
79          $brktlink = preg_quote($brktlinks[0][$i]);
80          $linktoken = $FieldSeparator . $FieldSeparator . ++$ntokens . $FieldSeparator;
81          /* PS:
82           * If you're wondering about the double $FieldSeparator,
83           * consider what happens to (the admittedly sick):
84           *   "[Link1] [Link2]1[Link3]"
85           *
86           * Answer: without the double field separator, it gets
87           *  tokenized to "%1% %2%1%3%" (using % to represent $FieldSeparator),
88           *  which will get munged as soon as '%1%' is substituted with it's
89           *  final value.
90           */
91          $tmpline = preg_replace("|(?<!\[)$brktlink|",
92                                  $linktoken,
93                                  $tmpline);
94
95          $tokens[] = $linktoken;
96          $link = ParseAndLink($brktlinks[0][$i]);
97          $replacements[] = $link['link'];
98       }
99
100       //////////////////////////////////////////////////////////
101       // replace all URL's with tokens, so we don't confuse them
102       // with Wiki words later. Wiki words in URL's break things.
103
104       $hasURLs = preg_match_all("/\b($AllowedProtocols):[^\s\<\>\[\]\"'\(\)]*[^\s\<\>\[\]\"'\(\)\,\.\?]/", $tmpline, $urls);
105
106       // have to sort, otherwise errors creep in when the domain appears
107       // in two consecutive URL's on the same line, but the second is
108       // longer e.g. http://c2.com followed by http://c2.com/wiki 
109       rsort($urls[0]);
110       reset($urls[0]);
111
112       for ($i = 0; $i < $hasURLs; $i++) {
113          $inplaceURL = preg_quote($urls[0][$i]);
114          $URLtoken = $FieldSeparator . $FieldSeparator . ++$ntokens . $FieldSeparator;
115          $tmpline = preg_replace("|$inplaceURL|",
116                                  $URLtoken,
117                                  $tmpline);
118
119          $tokens[] = $URLtoken;
120          $replacements[] = LinkURL($urls[0][$i]);
121       }
122
123       // escape HTML metachars
124       $tmpline = ereg_replace("[&]", "&amp;", $tmpline);
125       $tmpline = ereg_replace("[>]", "&gt;", $tmpline);
126       $tmpline = ereg_replace("[<]", "&lt;", $tmpline);
127
128       // four or more dashes to <hr>
129       $tmpline = ereg_replace("^-{4,}", "<hr>", $tmpline);
130
131
132       // %%% are linebreaks
133       $tmpline = str_replace("%%%", "<br>", $tmpline);
134
135       // bold italics
136       $tmpline = preg_replace("|(''''')(.*?)(''''')|",
137                               "<strong><em>\\2</em></strong>",
138                               $tmpline);
139
140       // bold
141       $tmpline = preg_replace("|(''')(.*?)(''')|",
142                               "<strong>\\2</strong>",
143                               $tmpline);
144
145       // bold
146       $tmpline = preg_replace("|(__)(.*?)(__)|",
147                               "<strong>\\2</strong>",
148                               $tmpline);
149
150       // italics
151       $tmpline = preg_replace("|('')(.*?)('')|",
152                               "<em>\\2</em>",
153                               $tmpline);
154
155       // Link Wiki words
156       // Wikiwords preceeded by a '!' are not linked
157       if (preg_match_all("#!?\b(([A-Z][a-z]+){2,})\b#",
158                          $tmpline, $link)) {
159          // uniq the list of matches
160          unset($hash);
161          for ($i = 0; $link[0][$i]; $i++) {
162             // $realfile = $link[0][$i];
163             $hash[$link[0][$i]]++;
164          }
165
166          // all '!WikiName' entries are sorted first
167          ksort($hash);
168          while (list($realfile, $val) = each($hash)) {
169             $token = $FieldSeparator . $FieldSeparator . ++$ntokens . $FieldSeparator;
170             $tmpline = str_replace($realfile, $token, $tmpline);
171             $tokens[] = $token;
172             if (strstr($realfile, '!')) {
173                $replacements[] = substr($realfile, 1);
174             }          
175             elseif (IsWikiPage($dbi, $realfile)) {
176                $replacements[] = LinkExistingWikiWord($realfile);
177             } else {
178                $replacements[] = LinkUnknownWikiWord($realfile);
179             }
180          }
181       }
182
183       ///////////////////////////////////////////////////////
184       // Replace tokens
185       for ($i = 0; $i < $ntokens; $i++)
186           $tmpline = str_replace($tokens[$i], $replacements[$i], $tmpline);
187       
188
189       // match and replace all user-defined links ([1], [2], [3]...)
190       preg_match_all("|\[(\d+)\]|", $tmpline, $match);
191       if (count($match[0])) {
192          for ($k = 0; $k < count($match[0]); $k++) {
193             if (! empty($embedded[$match[1][$k]])) {
194                $linkpattern = preg_quote($match[0][$k]);
195                $tmpline = preg_replace("|$linkpattern|",
196                                        $embedded[$match[1][$k]],
197                                        $tmpline);
198             }
199          }
200       }
201
202       // HTML modes: pre, unordered/ordered lists, term/def
203       if (preg_match("/(^\t+)(.*?)(:\t)(.*$)/", $tmpline, $matches)) {
204          // this is a dictionary list item
205          $numtabs = strlen($matches[1]);
206          $html .= SetHTMLOutputMode("dl", SINGLE_DEPTH, $numtabs);
207          $tmpline = '';
208          if(trim($matches[2]))
209             $tmpline = "<dt>" . $matches[2];
210          $tmpline .= "<dd>" . $matches[4];
211
212       // oops, the \d needed to be \d+, thanks alister@minotaur.nu
213       } elseif (preg_match("/(^\t+)(\*|\d+|#)/", $tmpline, $matches)) {
214          // this is part of a list
215          $numtabs = strlen($matches[1]);
216          if ($matches[2] == "*") {
217             $listtag = "ul";
218          } else {
219             $listtag = "ol"; // a rather tacit assumption. oh well.
220          }
221          $tmpline = preg_replace("/^(\t+)(\*|\d+|#)/", "", $tmpline);
222          $html .= SetHTMLOutputMode($listtag, SINGLE_DEPTH, $numtabs);
223          $html .= "<li>";
224
225       // tabless markup for unordered and ordered lists
226
227       // first, unordered lists: one or more astericks at the
228       // start of a line indicate a <UL> block
229
230       } elseif (preg_match("/^([*]+)/", $tmpline, $matches)) {
231          // this is part of an unordered list
232          $numtabs = strlen($matches[1]);
233          $listtag = "ul";
234
235          $tmpline = preg_replace("/^([*]+)/", "", $tmpline);
236          $html .= SetHTMLOutputMode($listtag, SINGLE_DEPTH, $numtabs);
237          $html .= "<li>";
238
239       // second, ordered lists <OL>
240       } elseif (preg_match("/^([#]+)/", $tmpline, $matches)) {
241          // this is part of an ordered list
242          $numtabs = strlen($matches[1]);
243          $listtag = "ol";
244
245          $tmpline = preg_replace("/^([#]+)/", "", $tmpline);
246          $html .= SetHTMLOutputMode($listtag, SINGLE_DEPTH, $numtabs);
247          $html .= "<li>";
248
249
250       } elseif (preg_match("/^\s+/", $tmpline)) {
251          // this is preformatted text, i.e. <pre>
252          $html .= SetHTMLOutputMode("pre", ZERO_DEPTH, 0);
253
254       } elseif (preg_match("/^(!{1,3})[^!]/", $tmpline, $whichheading)) {
255          // lines starting with !,!!,!!! are headings
256          if($whichheading[1] == '!') $heading = "h3";
257          elseif($whichheading[1] == '!!') $heading = "h2";
258          elseif($whichheading[1] == '!!!') $heading = "h1";
259          $tmpline = preg_replace("/^!+/", "", $tmpline);
260          $html .= SetHTMLOutputMode($heading, ZERO_DEPTH, 0);
261
262       } else {
263          // it's ordinary output if nothing else
264          $html .= SetHTMLOutputMode("", ZERO_DEPTH, 0);
265       }
266
267       $tmpline = str_replace("%%Search%%", $quick_search_box, $tmpline);
268       $tmpline = str_replace("%%Fullsearch%%", $full_search_box, $tmpline);
269       $tmpline = str_replace("%%Mostpopular%%", $most_popular_list, $tmpline);
270
271       $html .= "$tmpline\n";
272    }
273
274
275    $html .= SetHTMLOutputMode("", ZERO_DEPTH, 0);
276 ?>