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×$y"; 343*0cecf9d5Sandi } 344*0cecf9d5Sandi 345*0cecf9d5Sandi function singlequoteopening() { 346*0cecf9d5Sandi echo "‘"; 347*0cecf9d5Sandi } 348*0cecf9d5Sandi 349*0cecf9d5Sandi function singlequoteclosing() { 350*0cecf9d5Sandi echo "’"; 351*0cecf9d5Sandi } 352*0cecf9d5Sandi 353*0cecf9d5Sandi function doublequoteopening() { 354*0cecf9d5Sandi echo "“"; 355*0cecf9d5Sandi } 356*0cecf9d5Sandi 357*0cecf9d5Sandi function doublequoteclosing() { 358*0cecf9d5Sandi echo "”"; 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).'&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