xref: /dokuwiki/inc/parser/xhtml.php (revision 0cecf9d507451346a32ddf45a85b425784fbb0f8)
1*0cecf9d5Sandi<?php
2*0cecf9d5Sandiif(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
3*0cecf9d5Sandi
4*0cecf9d5Sandiif ( !defined('DOKU_LF') ) {
5*0cecf9d5Sandi    // Some whitespace to help View > Source
6*0cecf9d5Sandi    define ('DOKU_LF',"\n");
7*0cecf9d5Sandi}
8*0cecf9d5Sandi
9*0cecf9d5Sandiif ( !defined('DOKU_TAB') ) {
10*0cecf9d5Sandi    // Some whitespace to help View > Source
11*0cecf9d5Sandi    define ('DOKU_TAB',"\t");
12*0cecf9d5Sandi}
13*0cecf9d5Sandi
14*0cecf9d5Sandi/**
15*0cecf9d5Sandi* @TODO Probably useful for have constant for linefeed formatting
16*0cecf9d5Sandi*/
17*0cecf9d5Sandiclass Doku_Renderer_XHTML {
18*0cecf9d5Sandi
19*0cecf9d5Sandi    var $doc = '';
20*0cecf9d5Sandi
21*0cecf9d5Sandi    var $headers = array();
22*0cecf9d5Sandi
23*0cecf9d5Sandi    var $footnotes = array();
24*0cecf9d5Sandi
25*0cecf9d5Sandi    var $footnoteIdStack = array();
26*0cecf9d5Sandi
27*0cecf9d5Sandi    var $acronyms = array();
28*0cecf9d5Sandi    var $smileys = array();
29*0cecf9d5Sandi    var $badwords = array();
30*0cecf9d5Sandi    var $entities = array();
31*0cecf9d5Sandi    var $interwiki = array();
32*0cecf9d5Sandi
33*0cecf9d5Sandi    //@todo why ob?
34*0cecf9d5Sandi    function document_start() {
35*0cecf9d5Sandi        ob_start();
36*0cecf9d5Sandi    }
37*0cecf9d5Sandi
38*0cecf9d5Sandi    function document_end() {
39*0cecf9d5Sandi
40*0cecf9d5Sandi        if ( count ($this->footnotes) > 0 ) {
41*0cecf9d5Sandi            echo '<div class="footnotes">'.DOKU_LF;
42*0cecf9d5Sandi            foreach ( $this->footnotes as $footnote ) {
43*0cecf9d5Sandi                echo $footnote;
44*0cecf9d5Sandi            }
45*0cecf9d5Sandi            echo '</div>'.DOKU_LF;
46*0cecf9d5Sandi        }
47*0cecf9d5Sandi
48*0cecf9d5Sandi        $this->doc .= ob_get_contents();
49*0cecf9d5Sandi        ob_end_clean();
50*0cecf9d5Sandi
51*0cecf9d5Sandi    }
52*0cecf9d5Sandi
53*0cecf9d5Sandi    function toc_open() {
54*0cecf9d5Sandi        echo '<div class="toc">'.DOKU_LF;
55*0cecf9d5Sandi        echo '<div class="tocheader">Table of Contents <script type="text/javascript">showTocToggle("+","-")</script></div>'.DOKU_LF;
56*0cecf9d5Sandi        echo '<div id="tocinside">'.DOKU_LF;
57*0cecf9d5Sandi    }
58*0cecf9d5Sandi
59*0cecf9d5Sandi    function tocbranch_open($level) {
60*0cecf9d5Sandi        echo '<ul class="toc">'.DOKU_LF;
61*0cecf9d5Sandi    }
62*0cecf9d5Sandi
63*0cecf9d5Sandi    function tocitem_open($level, $empty = FALSE) {
64*0cecf9d5Sandi        if ( !$empty ) {
65*0cecf9d5Sandi            echo '<li class="level'.$level.'">';
66*0cecf9d5Sandi        } else {
67*0cecf9d5Sandi            echo '<li class="clear">';
68*0cecf9d5Sandi        }
69*0cecf9d5Sandi    }
70*0cecf9d5Sandi
71*0cecf9d5Sandi    function tocelement($level, $title) {
72*0cecf9d5Sandi        echo '<span class="li"><a href="#'.$this->__headerToLink($title).'" class="toc">';
73*0cecf9d5Sandi        echo $this->__xmlEntities($title);
74*0cecf9d5Sandi        echo '</a></span>';
75*0cecf9d5Sandi    }
76*0cecf9d5Sandi
77*0cecf9d5Sandi    function tocitem_close($level) {
78*0cecf9d5Sandi        echo '</li>'.DOKU_LF;
79*0cecf9d5Sandi    }
80*0cecf9d5Sandi
81*0cecf9d5Sandi    function tocbranch_close($level) {
82*0cecf9d5Sandi        echo '</ul>'.DOKU_LF;
83*0cecf9d5Sandi    }
84*0cecf9d5Sandi
85*0cecf9d5Sandi    function toc_close() {
86*0cecf9d5Sandi        echo '</div>'.DOKU_LF.'</div>'.DOKU_LF;
87*0cecf9d5Sandi    }
88*0cecf9d5Sandi
89*0cecf9d5Sandi    function header($text, $level) {
90*0cecf9d5Sandi        echo DOKU_LF.'<a name="'.$this->__headerToLink($text).'"></a><h'.$level.'>';
91*0cecf9d5Sandi        echo $this->__xmlEntities($text);
92*0cecf9d5Sandi        echo "</h$level>".DOKU_LF;
93*0cecf9d5Sandi    }
94*0cecf9d5Sandi
95*0cecf9d5Sandi    function section_open($level) {
96*0cecf9d5Sandi        echo "<div class=\"level$level\">".DOKU_LF;
97*0cecf9d5Sandi    }
98*0cecf9d5Sandi
99*0cecf9d5Sandi    function section_close() {
100*0cecf9d5Sandi        echo DOKU_LF.'</div>'.DOKU_LF;
101*0cecf9d5Sandi    }
102*0cecf9d5Sandi
103*0cecf9d5Sandi    function cdata($text) {
104*0cecf9d5Sandi        echo $this->__xmlEntities($text);
105*0cecf9d5Sandi    }
106*0cecf9d5Sandi
107*0cecf9d5Sandi    function p_open() {
108*0cecf9d5Sandi        echo DOKU_LF.'<p>'.DOKU_LF;
109*0cecf9d5Sandi    }
110*0cecf9d5Sandi
111*0cecf9d5Sandi    function p_close() {
112*0cecf9d5Sandi        echo DOKU_LF.'</p>'.DOKU_LF;
113*0cecf9d5Sandi    }
114*0cecf9d5Sandi
115*0cecf9d5Sandi    function linebreak() {
116*0cecf9d5Sandi        echo '<br/>'.DOKU_LF;
117*0cecf9d5Sandi    }
118*0cecf9d5Sandi
119*0cecf9d5Sandi    function hr() {
120*0cecf9d5Sandi        echo '<hr noshade="noshade" size="1" />'.DOKU_LF;
121*0cecf9d5Sandi    }
122*0cecf9d5Sandi
123*0cecf9d5Sandi    function strong_open() {
124*0cecf9d5Sandi        echo '<strong>';
125*0cecf9d5Sandi    }
126*0cecf9d5Sandi
127*0cecf9d5Sandi    function strong_close() {
128*0cecf9d5Sandi        echo '</strong>';
129*0cecf9d5Sandi    }
130*0cecf9d5Sandi
131*0cecf9d5Sandi    function emphasis_open() {
132*0cecf9d5Sandi        echo '<em>';
133*0cecf9d5Sandi    }
134*0cecf9d5Sandi
135*0cecf9d5Sandi    function emphasis_close() {
136*0cecf9d5Sandi        echo '</em>';
137*0cecf9d5Sandi    }
138*0cecf9d5Sandi
139*0cecf9d5Sandi    function underline_open() {
140*0cecf9d5Sandi        echo '<u>';
141*0cecf9d5Sandi    }
142*0cecf9d5Sandi
143*0cecf9d5Sandi    function underline_close() {
144*0cecf9d5Sandi        echo '</u>';
145*0cecf9d5Sandi    }
146*0cecf9d5Sandi
147*0cecf9d5Sandi    function monospace_open() {
148*0cecf9d5Sandi        echo '<code>';
149*0cecf9d5Sandi    }
150*0cecf9d5Sandi
151*0cecf9d5Sandi    function monospace_close() {
152*0cecf9d5Sandi        echo '</code>';
153*0cecf9d5Sandi    }
154*0cecf9d5Sandi
155*0cecf9d5Sandi    function subscript_open() {
156*0cecf9d5Sandi        echo '<sub>';
157*0cecf9d5Sandi    }
158*0cecf9d5Sandi
159*0cecf9d5Sandi    function subscript_close() {
160*0cecf9d5Sandi        echo '</sub>';
161*0cecf9d5Sandi    }
162*0cecf9d5Sandi
163*0cecf9d5Sandi    function superscript_open() {
164*0cecf9d5Sandi        echo '<sup>';
165*0cecf9d5Sandi    }
166*0cecf9d5Sandi
167*0cecf9d5Sandi    function superscript_close() {
168*0cecf9d5Sandi        echo '</sup>';
169*0cecf9d5Sandi    }
170*0cecf9d5Sandi
171*0cecf9d5Sandi    function deleted_open() {
172*0cecf9d5Sandi        echo '<del>';
173*0cecf9d5Sandi    }
174*0cecf9d5Sandi
175*0cecf9d5Sandi    function deleted_close() {
176*0cecf9d5Sandi        echo '</del>';
177*0cecf9d5Sandi    }
178*0cecf9d5Sandi
179*0cecf9d5Sandi    function footnote_open() {
180*0cecf9d5Sandi        $id = $this->__newFootnoteId();
181*0cecf9d5Sandi        echo '<a href="#fn'.$id.'" name="fnt'.$id.'" class="fn_top">'.$id.')</a>';
182*0cecf9d5Sandi        $this->footnoteIdStack[] = $id;
183*0cecf9d5Sandi        ob_start();
184*0cecf9d5Sandi    }
185*0cecf9d5Sandi
186*0cecf9d5Sandi    function footnote_close() {
187*0cecf9d5Sandi        $contents = ob_get_contents();
188*0cecf9d5Sandi        ob_end_clean();
189*0cecf9d5Sandi        $id = array_pop($this->footnoteIdStack);
190*0cecf9d5Sandi
191*0cecf9d5Sandi        $contents = '<div class="fn"><a href="#fnt'.
192*0cecf9d5Sandi            $id.'" name="fn'.$id.'" class="fn_bot">'.
193*0cecf9d5Sandi                $id.')</a> ' .DOKU_LF .$contents. "\n" . '</div>' . DOKU_LF;
194*0cecf9d5Sandi        $this->footnotes[$id] = $contents;
195*0cecf9d5Sandi    }
196*0cecf9d5Sandi
197*0cecf9d5Sandi    function listu_open() {
198*0cecf9d5Sandi        echo '<ul>'.DOKU_LF;
199*0cecf9d5Sandi    }
200*0cecf9d5Sandi
201*0cecf9d5Sandi    function listu_close() {
202*0cecf9d5Sandi        echo '</ul>'.DOKU_LF;
203*0cecf9d5Sandi    }
204*0cecf9d5Sandi
205*0cecf9d5Sandi    function listo_open() {
206*0cecf9d5Sandi        echo '<ol>'.DOKU_LF;
207*0cecf9d5Sandi    }
208*0cecf9d5Sandi
209*0cecf9d5Sandi    function listo_close() {
210*0cecf9d5Sandi        echo '</ol>'.DOKU_LF;
211*0cecf9d5Sandi    }
212*0cecf9d5Sandi
213*0cecf9d5Sandi    function listitem_open($level) {
214*0cecf9d5Sandi        echo '<li class="level'.$level.'">';
215*0cecf9d5Sandi    }
216*0cecf9d5Sandi
217*0cecf9d5Sandi    function listitem_close() {
218*0cecf9d5Sandi        echo '</li>'.DOKU_LF;
219*0cecf9d5Sandi    }
220*0cecf9d5Sandi
221*0cecf9d5Sandi    function listcontent_open() {
222*0cecf9d5Sandi        echo '<span class="li">';
223*0cecf9d5Sandi    }
224*0cecf9d5Sandi
225*0cecf9d5Sandi    function listcontent_close() {
226*0cecf9d5Sandi        echo '</span>'.DOKU_LF;
227*0cecf9d5Sandi    }
228*0cecf9d5Sandi
229*0cecf9d5Sandi    function unformatted($text) {
230*0cecf9d5Sandi        echo $this->__xmlEntities($text);
231*0cecf9d5Sandi    }
232*0cecf9d5Sandi
233*0cecf9d5Sandi    /**
234*0cecf9d5Sandi    * @TODO Support optional eval of code depending on conf/dokuwiki.php
235*0cecf9d5Sandi    */
236*0cecf9d5Sandi    function php($text) {
237*0cecf9d5Sandi        $this->preformatted($text);
238*0cecf9d5Sandi    }
239*0cecf9d5Sandi
240*0cecf9d5Sandi    /**
241*0cecf9d5Sandi    * @TODO Support optional echo of HTML depending on conf/dokuwiki.php
242*0cecf9d5Sandi    */
243*0cecf9d5Sandi    function html($text) {
244*0cecf9d5Sandi        $this->file($text);
245*0cecf9d5Sandi    }
246*0cecf9d5Sandi
247*0cecf9d5Sandi    function preformatted($text) {
248*0cecf9d5Sandi        echo '<pre class="code">' . $this->__xmlEntities($text) . '</pre>'. DOKU_LF;
249*0cecf9d5Sandi    }
250*0cecf9d5Sandi
251*0cecf9d5Sandi    function file($text) {
252*0cecf9d5Sandi        echo '<pre class="file">' . $this->__xmlEntities($text). '</pre>'. DOKU_LF;
253*0cecf9d5Sandi    }
254*0cecf9d5Sandi
255*0cecf9d5Sandi    /**
256*0cecf9d5Sandi    * @TODO Shouldn't this output <blockquote??
257*0cecf9d5Sandi    */
258*0cecf9d5Sandi    function quote_open() {
259*0cecf9d5Sandi        echo '<div class="quote">'.DOKU_LF;
260*0cecf9d5Sandi    }
261*0cecf9d5Sandi
262*0cecf9d5Sandi    /**
263*0cecf9d5Sandi    * @TODO Shouldn't this output </blockquote>?
264*0cecf9d5Sandi    */
265*0cecf9d5Sandi    function quote_close() {
266*0cecf9d5Sandi        echo '</div>'.DOKU_LF;
267*0cecf9d5Sandi    }
268*0cecf9d5Sandi
269*0cecf9d5Sandi    /**
270*0cecf9d5Sandi    * @TODO Hook up correctly with Geshi
271*0cecf9d5Sandi    */
272*0cecf9d5Sandi    function code($text, $language = NULL) {
273*0cecf9d5Sandi
274*0cecf9d5Sandi        if ( is_null($language) ) {
275*0cecf9d5Sandi            $this->preformatted($text);
276*0cecf9d5Sandi        } else {
277*0cecf9d5Sandi
278*0cecf9d5Sandi            // Handle with Geshi here (needs tuning)
279*0cecf9d5Sandi            require_once(DOKU_INC . 'geshi.php');
280*0cecf9d5Sandi            $geshi = new GeSHi($text, strtolower($language), DOKU_INC . 'geshi');
281*0cecf9d5Sandi            $geshi->enable_classes();
282*0cecf9d5Sandi            $geshi->set_header_type(GESHI_HEADER_PRE);
283*0cecf9d5Sandi            $geshi->set_overall_class('code');
284*0cecf9d5Sandi
285*0cecf9d5Sandi            // Fix this
286*0cecf9d5Sandi            $geshi->set_link_target('_blank');
287*0cecf9d5Sandi
288*0cecf9d5Sandi            $text = $geshi->parse_code();
289*0cecf9d5Sandi            echo $text;
290*0cecf9d5Sandi        }
291*0cecf9d5Sandi    }
292*0cecf9d5Sandi
293*0cecf9d5Sandi    function acronym($acronym) {
294*0cecf9d5Sandi
295*0cecf9d5Sandi        if ( array_key_exists($acronym, $this->acronyms) ) {
296*0cecf9d5Sandi
297*0cecf9d5Sandi            $title = $this->__xmlEntities($this->acronyms[$acronym]);
298*0cecf9d5Sandi
299*0cecf9d5Sandi            echo '<acronym title="'.$title
300*0cecf9d5Sandi                .'">'.$this->__xmlEntities($acronym).'</acronym>';
301*0cecf9d5Sandi
302*0cecf9d5Sandi        } else {
303*0cecf9d5Sandi            echo $this->__xmlEntities($acronym);
304*0cecf9d5Sandi        }
305*0cecf9d5Sandi    }
306*0cecf9d5Sandi
307*0cecf9d5Sandi    /**
308*0cecf9d5Sandi    * @TODO Remove hard coded link to splitbrain.org
309*0cecf9d5Sandi    */
310*0cecf9d5Sandi    function smiley($smiley) {
311*0cecf9d5Sandi
312*0cecf9d5Sandi        if ( array_key_exists($smiley, $this->smileys) ) {
313*0cecf9d5Sandi            $title = $this->__xmlEntities($this->smileys[$smiley]);
314*0cecf9d5Sandi            echo '<img src="http://wiki.splitbrain.org/smileys/'.$this->smileys[$smiley].
315*0cecf9d5Sandi                '" align="middle" alt="'.
316*0cecf9d5Sandi                    $this->__xmlEntities($smiley).'" />';
317*0cecf9d5Sandi        } else {
318*0cecf9d5Sandi            echo $this->__xmlEntities($smiley);
319*0cecf9d5Sandi        }
320*0cecf9d5Sandi    }
321*0cecf9d5Sandi
322*0cecf9d5Sandi    /**
323*0cecf9d5Sandi    * @TODO localization?
324*0cecf9d5Sandi    */
325*0cecf9d5Sandi    function wordblock($word) {
326*0cecf9d5Sandi        if ( array_key_exists($word, $this->badwords) ) {
327*0cecf9d5Sandi            echo '** BLEEP **';
328*0cecf9d5Sandi        } else {
329*0cecf9d5Sandi            echo $this->__xmlEntities($word);
330*0cecf9d5Sandi        }
331*0cecf9d5Sandi    }
332*0cecf9d5Sandi
333*0cecf9d5Sandi    function entity($entity) {
334*0cecf9d5Sandi        if ( array_key_exists($entity, $this->entities) ) {
335*0cecf9d5Sandi            echo $this->entities[$entity];
336*0cecf9d5Sandi        } else {
337*0cecf9d5Sandi            echo $this->__xmlEntities($entity);
338*0cecf9d5Sandi        }
339*0cecf9d5Sandi    }
340*0cecf9d5Sandi
341*0cecf9d5Sandi    function multiplyentity($x, $y) {
342*0cecf9d5Sandi        echo "$x&#215;$y";
343*0cecf9d5Sandi    }
344*0cecf9d5Sandi
345*0cecf9d5Sandi    function singlequoteopening() {
346*0cecf9d5Sandi        echo "&#8216;";
347*0cecf9d5Sandi    }
348*0cecf9d5Sandi
349*0cecf9d5Sandi    function singlequoteclosing() {
350*0cecf9d5Sandi        echo "&#8217;";
351*0cecf9d5Sandi    }
352*0cecf9d5Sandi
353*0cecf9d5Sandi    function doublequoteopening() {
354*0cecf9d5Sandi        echo "&#8220;";
355*0cecf9d5Sandi    }
356*0cecf9d5Sandi
357*0cecf9d5Sandi    function doublequoteclosing() {
358*0cecf9d5Sandi        echo "&#8221;";
359*0cecf9d5Sandi    }
360*0cecf9d5Sandi
361*0cecf9d5Sandi    /**
362*0cecf9d5Sandi    * @TODO Handle local vs. global namespace checks
363*0cecf9d5Sandi    */
364*0cecf9d5Sandi    function camelcaselink($link) {
365*0cecf9d5Sandi
366*0cecf9d5Sandi        echo '<a href="'.$link.'"';
367*0cecf9d5Sandi
368*0cecf9d5Sandi        if ( wikiPageExists($link) ) {
369*0cecf9d5Sandi            echo ' class="wikilink1"';
370*0cecf9d5Sandi        } else {
371*0cecf9d5Sandi            echo ' class="wikilink2"';
372*0cecf9d5Sandi        }
373*0cecf9d5Sandi
374*0cecf9d5Sandi        // Probably dont need to convert entities - parser would have rejected it
375*0cecf9d5Sandi        echo ' onclick="return svchk()" onkeypress="return svchk()">';
376*0cecf9d5Sandi        echo $this->__xmlEntities($link);
377*0cecf9d5Sandi        echo '</a>';
378*0cecf9d5Sandi    }
379*0cecf9d5Sandi
380*0cecf9d5Sandi    /**
381*0cecf9d5Sandi    * @TODO Hook up with page resolver.
382*0cecf9d5Sandi    * @TODO Support media
383*0cecf9d5Sandi    * @TODO correct attributes
384*0cecf9d5Sandi    */
385*0cecf9d5Sandi    function internallink($link, $title = NULL) {
386*0cecf9d5Sandi
387*0cecf9d5Sandi        echo '<a';
388*0cecf9d5Sandi
389*0cecf9d5Sandi        $title = $this->__getLinkTitle($title,$link, $isImage);
390*0cecf9d5Sandi
391*0cecf9d5Sandi        if ( !$isImage ) {
392*0cecf9d5Sandi
393*0cecf9d5Sandi            if ( wikiPageExists($link) ) {
394*0cecf9d5Sandi                echo ' class="wikilink1"';
395*0cecf9d5Sandi            } else {
396*0cecf9d5Sandi                echo ' class="wikilink2"';
397*0cecf9d5Sandi            }
398*0cecf9d5Sandi
399*0cecf9d5Sandi        } else {
400*0cecf9d5Sandi            echo ' class="media"';
401*0cecf9d5Sandi        }
402*0cecf9d5Sandi
403*0cecf9d5Sandi        echo ' href="http://wiki.splitbrain.org/'.$this->__xmlEntities($link).'"';
404*0cecf9d5Sandi
405*0cecf9d5Sandi        echo ' onclick="return svchk()" onkeypress="return svchk()">';
406*0cecf9d5Sandi
407*0cecf9d5Sandi        echo $title;
408*0cecf9d5Sandi
409*0cecf9d5Sandi        echo '</a>';
410*0cecf9d5Sandi    }
411*0cecf9d5Sandi
412*0cecf9d5Sandi
413*0cecf9d5Sandi    /**
414*0cecf9d5Sandi    * @TODO Should list assume blacklist check already made?
415*0cecf9d5Sandi    * @TODO External link icon
416*0cecf9d5Sandi    * @TODO correct attributes
417*0cecf9d5Sandi    */
418*0cecf9d5Sandi    function externallink($link, $title = NULL) {
419*0cecf9d5Sandi
420*0cecf9d5Sandi        echo '<a';
421*0cecf9d5Sandi
422*0cecf9d5Sandi        $title = $this->__getLinkTitle($title, $link, $isImage);
423*0cecf9d5Sandi
424*0cecf9d5Sandi        if ( !$isImage ) {
425*0cecf9d5Sandi            echo ' class="urlextern"';
426*0cecf9d5Sandi        } else {
427*0cecf9d5Sandi            echo ' class="media"';
428*0cecf9d5Sandi        }
429*0cecf9d5Sandi
430*0cecf9d5Sandi        echo ' target="_blank" href="'.$this->__xmlEntities($link).'"';
431*0cecf9d5Sandi
432*0cecf9d5Sandi        echo ' onclick="return svchk()" onkeypress="return svchk()">';
433*0cecf9d5Sandi
434*0cecf9d5Sandi        echo $title;
435*0cecf9d5Sandi
436*0cecf9d5Sandi        echo '</a>';
437*0cecf9d5Sandi    }
438*0cecf9d5Sandi
439*0cecf9d5Sandi    /**
440*0cecf9d5Sandi    * @TODO Remove hard coded link to splitbrain.org on style
441*0cecf9d5Sandi    */
442*0cecf9d5Sandi    function interwikilink($link, $title = NULL, $wikiName, $wikiUri) {
443*0cecf9d5Sandi
444*0cecf9d5Sandi        // RESOLVE THE URL
445*0cecf9d5Sandi        if ( isset($this->interwiki[$wikiName]) ) {
446*0cecf9d5Sandi
447*0cecf9d5Sandi            $wikiUriEnc = urlencode($wikiUri);
448*0cecf9d5Sandi
449*0cecf9d5Sandi            if ( strstr($this->interwiki[$wikiName],'{URL}' ) !== FALSE ) {
450*0cecf9d5Sandi
451*0cecf9d5Sandi                $url = str_replace('{URL}', $wikiUriEnc, $this->interwiki[$wikiName] );
452*0cecf9d5Sandi
453*0cecf9d5Sandi            } else if ( strstr($this->interwiki[$wikiName],'{NAME}' ) !== FALSE ) {
454*0cecf9d5Sandi
455*0cecf9d5Sandi                $url = str_replace('{NAME}', $wikiUriEnc, $this->interwiki[$wikiName] );
456*0cecf9d5Sandi
457*0cecf9d5Sandi            } else {
458*0cecf9d5Sandi
459*0cecf9d5Sandi                $url = $this->interwiki[$wikiName] . urlencode($wikiUri);
460*0cecf9d5Sandi
461*0cecf9d5Sandi            }
462*0cecf9d5Sandi
463*0cecf9d5Sandi        } else {
464*0cecf9d5Sandi            // Default to Google I'm feeling lucky
465*0cecf9d5Sandi            $url = 'http://www.google.com/search?q='.urlencode($wikiUri).'&amp;btnI=lucky';
466*0cecf9d5Sandi        }
467*0cecf9d5Sandi
468*0cecf9d5Sandi        // BUILD THE LINK
469*0cecf9d5Sandi        echo '<a';
470*0cecf9d5Sandi
471*0cecf9d5Sandi        $title = $this->__getLinkTitle($title, $wikiUri, $isImage);
472*0cecf9d5Sandi
473*0cecf9d5Sandi        if ( !$isImage ) {
474*0cecf9d5Sandi            echo ' class="interwiki"';
475*0cecf9d5Sandi        } else {
476*0cecf9d5Sandi            echo ' class="media"';
477*0cecf9d5Sandi        }
478*0cecf9d5Sandi
479*0cecf9d5Sandi        echo ' href="'.$this->__xmlEntities($url).'"';
480*0cecf9d5Sandi
481*0cecf9d5Sandi        if ( FALSE !== ( $type = interwikiImgExists($wikiName) ) ) {
482*0cecf9d5Sandi            echo ' style="background: transparent url(http://wiki.splitbrain.org/interwiki/'.
483*0cecf9d5Sandi                $wikiName.'.'.$type.') 0px 1px no-repeat;"';
484*0cecf9d5Sandi        }
485*0cecf9d5Sandi
486*0cecf9d5Sandi        echo ' onclick="return svchk()" onkeypress="return svchk()">';
487*0cecf9d5Sandi
488*0cecf9d5Sandi        echo $title;
489*0cecf9d5Sandi
490*0cecf9d5Sandi        echo '</a>';
491*0cecf9d5Sandi    }
492*0cecf9d5Sandi
493*0cecf9d5Sandi    /**
494*0cecf9d5Sandi    * @TODO Correct the CSS class for files? (not windows)
495*0cecf9d5Sandi    * @TODO Remove hard coded URL to splitbrain.org
496*0cecf9d5Sandi    */
497*0cecf9d5Sandi    function filelink($link, $title = NULL) {
498*0cecf9d5Sandi        echo '<a';
499*0cecf9d5Sandi
500*0cecf9d5Sandi        $title = $this->__getLinkTitle($title, $link, $isImage);
501*0cecf9d5Sandi
502*0cecf9d5Sandi        if ( !$isImage ) {
503*0cecf9d5Sandi            echo ' class="windows"';
504*0cecf9d5Sandi        } else {
505*0cecf9d5Sandi            echo ' class="media"';
506*0cecf9d5Sandi        }
507*0cecf9d5Sandi
508*0cecf9d5Sandi        echo ' href="'.$this->__xmlEntities($link).'"';
509*0cecf9d5Sandi
510*0cecf9d5Sandi        echo ' style="background: transparent url(http://wiki.splitbrain.org/images/windows.gif) 0px 1px no-repeat;"';
511*0cecf9d5Sandi
512*0cecf9d5Sandi        echo ' onclick="return svchk()" onkeypress="return svchk()">';
513*0cecf9d5Sandi
514*0cecf9d5Sandi        echo $title;
515*0cecf9d5Sandi
516*0cecf9d5Sandi        echo '</a>';
517*0cecf9d5Sandi    }
518*0cecf9d5Sandi
519*0cecf9d5Sandi    /**
520*0cecf9d5Sandi    * @TODO Remove hard coded URL to splitbrain.org
521*0cecf9d5Sandi    * @TODO Add error message for non-IE users
522*0cecf9d5Sandi    */
523*0cecf9d5Sandi    function windowssharelink($link, $title = NULL) {
524*0cecf9d5Sandi        echo '<a';
525*0cecf9d5Sandi
526*0cecf9d5Sandi        $title = $this->__getLinkTitle($title, $link, $isImage);
527*0cecf9d5Sandi
528*0cecf9d5Sandi        if ( !$isImage ) {
529*0cecf9d5Sandi            echo ' class="windows"';
530*0cecf9d5Sandi        } else {
531*0cecf9d5Sandi            echo ' class="media"';
532*0cecf9d5Sandi        }
533*0cecf9d5Sandi
534*0cecf9d5Sandi        $link = str_replace('\\','/',$link);
535*0cecf9d5Sandi        $link = 'file:///'.$link;
536*0cecf9d5Sandi        echo ' href="'.$this->__xmlEntities($link).'"';
537*0cecf9d5Sandi
538*0cecf9d5Sandi        echo ' style="background: transparent url(http://wiki.splitbrain.org/images/windows.gif) 0px 1px no-repeat;"';
539*0cecf9d5Sandi
540*0cecf9d5Sandi        echo ' onclick="return svchk()" onkeypress="return svchk()">';
541*0cecf9d5Sandi
542*0cecf9d5Sandi        echo $title;
543*0cecf9d5Sandi
544*0cecf9d5Sandi        echo '</a>';
545*0cecf9d5Sandi    }
546*0cecf9d5Sandi
547*0cecf9d5Sandi    /**
548*0cecf9d5Sandi    * @TODO Protect email address from harvesters
549*0cecf9d5Sandi    * @TODO Remove hard coded link to splitbrain.org
550*0cecf9d5Sandi    */
551*0cecf9d5Sandi    function email($address, $title = NULL) {
552*0cecf9d5Sandi        echo '<a';
553*0cecf9d5Sandi
554*0cecf9d5Sandi        $title = $this->__getLinkTitle($title, $address, $isImage);
555*0cecf9d5Sandi
556*0cecf9d5Sandi        if ( !$isImage ) {
557*0cecf9d5Sandi            echo ' class="mail"';
558*0cecf9d5Sandi        } else {
559*0cecf9d5Sandi            echo ' class="media"';
560*0cecf9d5Sandi        }
561*0cecf9d5Sandi
562*0cecf9d5Sandi        echo ' href="mailto:'.$this->__xmlEntities($address).'"';
563*0cecf9d5Sandi
564*0cecf9d5Sandi        echo ' style="background: transparent url(http://wiki.splitbrain.org/images/mail_icon.gif) 0px 1px no-repeat;"';
565*0cecf9d5Sandi
566*0cecf9d5Sandi        echo ' onclick="return svchk()" onkeypress="return svchk()">';
567*0cecf9d5Sandi
568*0cecf9d5Sandi        echo $title;
569*0cecf9d5Sandi
570*0cecf9d5Sandi        echo '</a>';
571*0cecf9d5Sandi
572*0cecf9d5Sandi    }
573*0cecf9d5Sandi
574*0cecf9d5Sandi    /**
575*0cecf9d5Sandi    * @TODO Resolve namespaces
576*0cecf9d5Sandi    * @TODO Add image caching
577*0cecf9d5Sandi    * @TODO Remove hard coded link to splitbrain.org
578*0cecf9d5Sandi    */
579*0cecf9d5Sandi    function internalmedia (
580*0cecf9d5Sandi        $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL
581*0cecf9d5Sandi        ) {
582*0cecf9d5Sandi
583*0cecf9d5Sandi        // Sort out the namespace here...
584*0cecf9d5Sandi        if ( strpos($src,':') ) {
585*0cecf9d5Sandi            $src = explode(':',$src);
586*0cecf9d5Sandi            $src = $src[1];
587*0cecf9d5Sandi        }
588*0cecf9d5Sandi        echo '<img class="media" src="http://wiki.splitbrain.org/media/wiki/'.$this->__xmlEntities($src).'"';
589*0cecf9d5Sandi
590*0cecf9d5Sandi        if ( !is_null($title) ) {
591*0cecf9d5Sandi            echo ' title="'.$this->__xmlEntities($title).'"';
592*0cecf9d5Sandi        }
593*0cecf9d5Sandi
594*0cecf9d5Sandi        if ( !is_null($align) ) {
595*0cecf9d5Sandi            echo ' align="'.$align.'"';
596*0cecf9d5Sandi        }
597*0cecf9d5Sandi
598*0cecf9d5Sandi        if ( !is_null($width) ) {
599*0cecf9d5Sandi            echo ' width="'.$this->__xmlEntities($width).'"';
600*0cecf9d5Sandi        }
601*0cecf9d5Sandi
602*0cecf9d5Sandi        if ( !is_null($height) ) {
603*0cecf9d5Sandi            echo ' height="'.$this->__xmlEntities($height).'"';
604*0cecf9d5Sandi        }
605*0cecf9d5Sandi
606*0cecf9d5Sandi        echo '/>';
607*0cecf9d5Sandi
608*0cecf9d5Sandi    }
609*0cecf9d5Sandi
610*0cecf9d5Sandi    /**
611*0cecf9d5Sandi    * @TODO Add image caching
612*0cecf9d5Sandi    */
613*0cecf9d5Sandi    function externalmedia (
614*0cecf9d5Sandi        $src,$title=NULL,$align=NULL,$width=NULL,$height=NULL,$cache=NULL
615*0cecf9d5Sandi        ) {
616*0cecf9d5Sandi
617*0cecf9d5Sandi        echo '<img class="media" src="'.$this->__xmlEntities($src).'"';
618*0cecf9d5Sandi
619*0cecf9d5Sandi        if ( !is_null($title) ) {
620*0cecf9d5Sandi            echo ' title="'.$this->__xmlEntities($title).'"';
621*0cecf9d5Sandi        }
622*0cecf9d5Sandi
623*0cecf9d5Sandi        if ( !is_null($align) ) {
624*0cecf9d5Sandi            echo ' align="'.$align.'"';
625*0cecf9d5Sandi        }
626*0cecf9d5Sandi
627*0cecf9d5Sandi        if ( !is_null($width) ) {
628*0cecf9d5Sandi            echo ' width="'.$this->__xmlEntities($width).'"';
629*0cecf9d5Sandi        }
630*0cecf9d5Sandi
631*0cecf9d5Sandi        if ( !is_null($height) ) {
632*0cecf9d5Sandi            echo ' height="'.$this->__xmlEntities($height).'"';
633*0cecf9d5Sandi        }
634*0cecf9d5Sandi
635*0cecf9d5Sandi        echo '/>';
636*0cecf9d5Sandi    }
637*0cecf9d5Sandi
638*0cecf9d5Sandi    // $numrows not yet implemented
639*0cecf9d5Sandi    function table_open($maxcols = NULL, $numrows = NULL){
640*0cecf9d5Sandi        echo '<table class="inline">'.DOKU_LF;
641*0cecf9d5Sandi    }
642*0cecf9d5Sandi
643*0cecf9d5Sandi    function table_close(){
644*0cecf9d5Sandi        echo '</table>'.DOKU_LF.'<br />'.DOKU_LF;
645*0cecf9d5Sandi    }
646*0cecf9d5Sandi
647*0cecf9d5Sandi    function tablerow_open(){
648*0cecf9d5Sandi        echo DOKU_TAB . '<tr>' . DOKU_LF . DOKU_TAB . DOKU_TAB;
649*0cecf9d5Sandi    }
650*0cecf9d5Sandi
651*0cecf9d5Sandi    function tablerow_close(){
652*0cecf9d5Sandi        echo DOKU_LF . DOKU_TAB . '</tr>' . DOKU_LF;
653*0cecf9d5Sandi    }
654*0cecf9d5Sandi
655*0cecf9d5Sandi    function tableheader_open($colspan = 1, $align = NULL){
656*0cecf9d5Sandi        echo '<th';
657*0cecf9d5Sandi        if ( !is_null($align) ) {
658*0cecf9d5Sandi            echo ' class="'.$align.'align"';
659*0cecf9d5Sandi        }
660*0cecf9d5Sandi        if ( $colspan > 1 ) {
661*0cecf9d5Sandi            echo ' colspan="'.$colspan.'"';
662*0cecf9d5Sandi        }
663*0cecf9d5Sandi        echo '>';
664*0cecf9d5Sandi    }
665*0cecf9d5Sandi
666*0cecf9d5Sandi    function tableheader_close(){
667*0cecf9d5Sandi        echo '</th>';
668*0cecf9d5Sandi    }
669*0cecf9d5Sandi
670*0cecf9d5Sandi    function tablecell_open($colspan = 1, $align = NULL){
671*0cecf9d5Sandi        echo '<td';
672*0cecf9d5Sandi        if ( !is_null($align) ) {
673*0cecf9d5Sandi            echo ' class="'.$align.'align"';
674*0cecf9d5Sandi        }
675*0cecf9d5Sandi        if ( $colspan > 1 ) {
676*0cecf9d5Sandi            echo ' colspan="'.$colspan.'"';
677*0cecf9d5Sandi        }
678*0cecf9d5Sandi        echo '>';
679*0cecf9d5Sandi    }
680*0cecf9d5Sandi
681*0cecf9d5Sandi    function tablecell_close(){
682*0cecf9d5Sandi        echo '</td>';
683*0cecf9d5Sandi    }
684*0cecf9d5Sandi
685*0cecf9d5Sandi    //----------------------------------------------------------
686*0cecf9d5Sandi    // Utils
687*0cecf9d5Sandi
688*0cecf9d5Sandi    function __newFootnoteId() {
689*0cecf9d5Sandi        static $id = 1;
690*0cecf9d5Sandi        return $id++;
691*0cecf9d5Sandi    }
692*0cecf9d5Sandi
693*0cecf9d5Sandi    function __xmlEntities($string) {
694*0cecf9d5Sandi        return htmlspecialchars($string);
695*0cecf9d5Sandi    }
696*0cecf9d5Sandi
697*0cecf9d5Sandi    /**
698*0cecf9d5Sandi    * @TODO Tuning needed - e.g. utf8 strtolower ?
699*0cecf9d5Sandi    */
700*0cecf9d5Sandi    function __headerToLink($title) {
701*0cecf9d5Sandi        return preg_replace('/\W/','_',trim($title));
702*0cecf9d5Sandi    }
703*0cecf9d5Sandi
704*0cecf9d5Sandi    function __getLinkTitle($title, $default, & $isImage) {
705*0cecf9d5Sandi        $isImage = FALSE;
706*0cecf9d5Sandi
707*0cecf9d5Sandi        if ( is_null($title) ) {
708*0cecf9d5Sandi
709*0cecf9d5Sandi            return $this->__xmlEntities($default);
710*0cecf9d5Sandi
711*0cecf9d5Sandi        } else if ( is_string($title) ) {
712*0cecf9d5Sandi
713*0cecf9d5Sandi            return $this->__xmlEntities($title);
714*0cecf9d5Sandi
715*0cecf9d5Sandi        } else if ( is_array($title) ) {
716*0cecf9d5Sandi
717*0cecf9d5Sandi            $isImage = TRUE;
718*0cecf9d5Sandi            return $this->__imageTitle($title);
719*0cecf9d5Sandi
720*0cecf9d5Sandi        }
721*0cecf9d5Sandi    }
722*0cecf9d5Sandi
723*0cecf9d5Sandi    /**
724*0cecf9d5Sandi    * @TODO Resolve namespace on internal images
725*0cecf9d5Sandi    * @TODO Remove hard coded url to splitbrain.org
726*0cecf9d5Sandi    * @TODO Image caching
727*0cecf9d5Sandi    */
728*0cecf9d5Sandi    function __imageTitle($img) {
729*0cecf9d5Sandi
730*0cecf9d5Sandi        if ( $img['type'] == 'internalmedia' ) {
731*0cecf9d5Sandi
732*0cecf9d5Sandi            // Resolve here...
733*0cecf9d5Sandi            if ( strpos($img['src'],':') ) {
734*0cecf9d5Sandi                $src = explode(':',$img['src']);
735*0cecf9d5Sandi                $src = $src[1];
736*0cecf9d5Sandi            } else {
737*0cecf9d5Sandi                $src = $img['src'];
738*0cecf9d5Sandi            }
739*0cecf9d5Sandi
740*0cecf9d5Sandi            $imgStr = '<img class="media" src="http://wiki.splitbrain.org/media/wiki/'.$this->__xmlEntities($src).'"';
741*0cecf9d5Sandi
742*0cecf9d5Sandi        } else {
743*0cecf9d5Sandi
744*0cecf9d5Sandi            $imgStr = '<img class="media" src="'.$this->__xmlEntities($img['src']).'"';
745*0cecf9d5Sandi
746*0cecf9d5Sandi        }
747*0cecf9d5Sandi
748*0cecf9d5Sandi        if ( !is_null($img['title']) ) {
749*0cecf9d5Sandi            $imgStr .= ' alt="'.$this->__xmlEntities($img['title']).'"';
750*0cecf9d5Sandi        } else {
751*0cecf9d5Sandi            $imgStr .= ' alt=""';
752*0cecf9d5Sandi        }
753*0cecf9d5Sandi
754*0cecf9d5Sandi        if ( !is_null($img['align']) ) {
755*0cecf9d5Sandi            $imgStr .= ' align="'.$img['align'].'"';
756*0cecf9d5Sandi        }
757*0cecf9d5Sandi
758*0cecf9d5Sandi        if ( !is_null($img['width']) ) {
759*0cecf9d5Sandi            $imgStr .= ' width="'.$this->__xmlEntities($img['width']).'"';
760*0cecf9d5Sandi        }
761*0cecf9d5Sandi
762*0cecf9d5Sandi        if ( !is_null($img['height']) ) {
763*0cecf9d5Sandi            $imgStr .= ' height="'.$this->__xmlEntities($img['height']).'"';
764*0cecf9d5Sandi        }
765*0cecf9d5Sandi
766*0cecf9d5Sandi        $imgStr .= '/>';
767*0cecf9d5Sandi
768*0cecf9d5Sandi        return $imgStr;
769*0cecf9d5Sandi    }
770*0cecf9d5Sandi}
771*0cecf9d5Sandi
772*0cecf9d5Sandi/**
773*0cecf9d5Sandi* Test whether there's an image to display with this interwiki link
774*0cecf9d5Sandi*/
775*0cecf9d5Sandifunction interwikiImgExists($name) {
776*0cecf9d5Sandi
777*0cecf9d5Sandi    static $exists = array();
778*0cecf9d5Sandi
779*0cecf9d5Sandi    if ( array_key_exists($name,$exists) ) {
780*0cecf9d5Sandi        return $exists[$name];
781*0cecf9d5Sandi    }
782*0cecf9d5Sandi
783*0cecf9d5Sandi    if( @file_exists( DOKU. 'interwiki/'.$name.'.png') ) {
784*0cecf9d5Sandi        $exists[$name] = 'png';
785*0cecf9d5Sandi    } else if ( @file_exists( DOKU . 'interwiki/'.$name.'.gif') ) {
786*0cecf9d5Sandi        $exists[$name] = 'gif';
787*0cecf9d5Sandi    } else {
788*0cecf9d5Sandi        $exists[$name] = FALSE;
789*0cecf9d5Sandi    }
790*0cecf9d5Sandi
791*0cecf9d5Sandi    return $exists[$name];
792*0cecf9d5Sandi}
793*0cecf9d5Sandi
794*0cecf9d5Sandi/**
795*0cecf9d5Sandi* For determining whether to use CSS class "wikilink1" or "wikilink2"
796*0cecf9d5Sandi* @todo use configinstead of DOKU_DATA
797*0cecf9d5Sandi*/
798*0cecf9d5Sandifunction wikiPageExists($name) {
799*0cecf9d5Sandi
800*0cecf9d5Sandi    static $pages = array();
801*0cecf9d5Sandi
802*0cecf9d5Sandi    if ( array_key_exists($name,$pages) ) {
803*0cecf9d5Sandi        return $pages[$name];
804*0cecf9d5Sandi    }
805*0cecf9d5Sandi
806*0cecf9d5Sandi    $file = str_replace(':','/',$name).'.txt';
807*0cecf9d5Sandi
808*0cecf9d5Sandi    if ( @file_exists( DOKU_DATA . $file ) ) {
809*0cecf9d5Sandi        $pages[$name] = TRUE;
810*0cecf9d5Sandi    } else {
811*0cecf9d5Sandi        $pages[$name] = FALSE;
812*0cecf9d5Sandi    }
813*0cecf9d5Sandi
814*0cecf9d5Sandi    return $pages[$name];
815*0cecf9d5Sandi}
816*0cecf9d5Sandi
817